summaryrefslogtreecommitdiffstats
path: root/src/peds
diff options
context:
space:
mode:
Diffstat (limited to 'src/peds')
-rw-r--r--src/peds/CivilianPed.cpp42
-rw-r--r--src/peds/Ped.cpp18534
-rw-r--r--src/peds/Ped.h48
-rw-r--r--src/peds/PedAI.cpp5413
-rw-r--r--src/peds/PedFight.cpp3250
-rw-r--r--src/peds/PedStats.cpp118
-rw-r--r--src/peds/PedStats.h80
-rw-r--r--src/peds/PedType.cpp113
-rw-r--r--src/peds/PedType.h79
9 files changed, 13739 insertions, 13938 deletions
diff --git a/src/peds/CivilianPed.cpp b/src/peds/CivilianPed.cpp
index 2d782a73..401d2e67 100644
--- a/src/peds/CivilianPed.cpp
+++ b/src/peds/CivilianPed.cpp
@@ -424,3 +424,45 @@ CCivilianPed::ProcessControl(void)
if (m_moved.Magnitude() > 0.0f)
Avoid();
}
+
+// It's "CPhoneInfo::ProcessNearestFreePhone" in PC IDB but that's not true, someone made it up.
+bool
+CPed::RunToReportCrime(eCrimeType crimeToReport)
+{
+#ifdef PEDS_REPORT_CRIMES_ON_PHONE
+ if (bRunningToPhone) {
+ if (!isPhoneAvailable(m_phoneId)) {
+ m_phoneId = -1;
+ bIsRunning = false;
+ ClearSeek(); // clears bRunningToPhone
+ return false;
+ }
+
+ return true;
+ }
+#else
+ // They changed true into false to make this function unusable. So running to phone actually starts but first frame after that cancels it.
+ if (m_nPedState == PED_SEEK_POS)
+ return false;
+#endif
+
+ CVector pos = GetPosition();
+ int phoneId = gPhoneInfo.FindNearestFreePhone(&pos);
+
+ if (phoneId == -1)
+ return false;
+
+ CPhone *phone = &gPhoneInfo.m_aPhones[phoneId];
+#ifndef PEDS_REPORT_CRIMES_ON_PHONE
+ if (phone->m_nState != PHONE_STATE_FREE)
+ return false;
+#endif
+
+ bRunningToPhone = true;
+ SetSeek(phone->m_pEntity->GetMatrix() * -phone->m_pEntity->GetForward(), 1.0f); // original: phone.m_vecPos, 0.3f
+ SetMoveState(PEDMOVE_RUN);
+ bIsRunning = true; // not there in original
+ m_phoneId = phoneId;
+ m_crimeToReportOnPhone = crimeToReport;
+ return true;
+} \ No newline at end of file
diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp
index 05e00ec2..c41c1f0c 100644
--- a/src/peds/Ped.cpp
+++ b/src/peds/Ped.cpp
@@ -3,111 +3,44 @@
#include "main.h"
#include "Pools.h"
#include "Particle.h"
-#include "Stats.h"
-#include "World.h"
#include "RpAnimBlend.h"
#include "Bones.h"
#include "Ped.h"
-#include "Wanted.h"
-#include "PlayerPed.h"
-#include "PedType.h"
-#include "AnimBlendClumpData.h"
#include "AnimBlendAssociation.h"
#include "Fire.h"
#include "DMAudio.h"
#include "General.h"
-#include "SurfaceTable.h"
#include "VisibilityPlugins.h"
-#include "AudioManager.h"
#include "HandlingMgr.h"
#include "Replay.h"
-#include "Camera.h"
#include "Radar.h"
#include "PedPlacement.h"
#include "Shadows.h"
#include "Weather.h"
#include "ZoneCull.h"
#include "Population.h"
-#include "Renderer.h"
-#include "Lights.h"
-#include "PointLights.h"
#include "Pad.h"
#include "Phones.h"
-#include "Darkel.h"
-#include "PathFind.h"
-#include "ModelIndices.h"
-#include "FileMgr.h"
-#include "TempColModels.h"
-#include "Pickups.h"
-#include "Train.h"
#include "TrafficLights.h"
-#include "PedRoutes.h"
-#include "Sprite.h"
-#include "RwHelper.h"
-#include "Font.h"
-#include "Text.h"
#include "CopPed.h"
#include "Script.h"
#include "CarCtrl.h"
#include "Garages.h"
#include "WaterLevel.h"
-#include "CarAI.h"
-#include "Zones.h"
-#include "Cranes.h"
#include "Timecycle.h"
#include "ParticleObject.h"
#include "Floater.h"
#include "Range2D.h"
-#define CAN_SEE_ENTITY_ANGLE_THRESHOLD DEGTORAD(60.0f)
-
CPed *gapTempPedList[50];
uint16 gnNumTempPedList;
static CColPoint aTempPedColPts[MAX_COLLISION_POINTS];
-uint16 nPlayerInComboMove;
-
-RpClump *flyingClumpTemp;
-
-// This is beta fistfite.dat array. Not used anymore since they're being fetched from fistfite.dat.
-FightMove tFightMoves[NUM_FIGHTMOVES] = {
- {NUM_ANIMS, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
- {ANIM_PUNCH_R, 0.2f, 8.0f / 30.0f, 0.0f, 0.3f, HITLEVEL_HIGH, 1, 0},
- {ANIM_FIGHT_IDLE, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
- {ANIM_FIGHT_SH_F, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
- {ANIM_FIGHT_KNEE, 4.0f / 30.0f, 0.2f, 0.0f, 0.6f, HITLEVEL_LOW, 2, 0},
- {ANIM_FIGHT_HEAD, 4.0f / 30.0f, 0.2f, 0.0f, 0.7f, HITLEVEL_HIGH, 3, 0},
- {ANIM_FIGHT_PUNCH, 4.0f / 30.0f, 7.0f / 30.0f, 10.0f / 30.0f, 0.4f, HITLEVEL_HIGH, 1, 0},
- {ANIM_FIGHT_LHOOK, 8.0f / 30.0f, 10.0f / 30.0f, 0.0f, 0.4f, HITLEVEL_HIGH, 3, 0},
- {ANIM_FIGHT_KICK, 8.0f / 30.0f, 10.0f / 30.0f, 0.0f, 0.5, HITLEVEL_MEDIUM, 2, 0},
- {ANIM_FIGHT_LONGKICK, 8.0f / 30.0f, 10.0f / 30.0f, 0.0f, 0.5, HITLEVEL_MEDIUM, 4, 0},
- {ANIM_FIGHT_ROUNDHOUSE, 8.0f / 30.0f, 10.0f / 30.0f, 0.0f, 0.6f, HITLEVEL_MEDIUM, 4, 0},
- {ANIM_FIGHT_BODYBLOW, 5.0f / 30.0f, 7.0f / 30.0f, 0.0f, 0.35f, HITLEVEL_LOW, 2, 0},
- {ANIM_KICK_FLOOR, 10.0f / 30.0f, 14.0f / 30.0f, 0.0f, 0.4f, HITLEVEL_GROUND, 1, 0},
- {ANIM_HIT_FRONT, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
- {ANIM_HIT_BACK, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
- {ANIM_HIT_RIGHT, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
- {ANIM_HIT_LEFT, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
- {ANIM_HIT_BODYBLOW, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
- {ANIM_HIT_CHEST, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
- {ANIM_HIT_HEAD, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
- {ANIM_HIT_WALK, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
- {ANIM_FLOOR_HIT, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
- {ANIM_HIT_BEHIND, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
- {ANIM_FIGHT2_IDLE, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
-};
uint16 CPed::nThreatReactionRangeMultiplier = 1;
uint16 CPed::nEnterCarRangeMultiplier = 1;
-CVector vecPedCarDoorAnimOffset;
-CVector vecPedCarDoorLoAnimOffset;
-CVector vecPedVanRearDoorAnimOffset;
-CVector vecPedQuickDraggedOutCarAnimOffset;
-CVector vecPedDraggedOutCarAnimOffset;
-CVector vecPedTrainDoorAnimOffset;
-
bool CPed::bNastyLimbsCheat;
bool CPed::bPedCheat2;
bool CPed::bPedCheat3;
@@ -122,53 +55,6 @@ void CPed::operator delete(void *p, int handle) { CPools::GetPedPool()->Delete((
bool CPed::bPopHeadsOnHeadshot = false;
#endif
-CPed::~CPed(void)
-{
- CWorld::Remove(this);
- CRadar::ClearBlipForEntity(BLIP_CHAR, CPools::GetPedPool()->GetIndex(this));
- if (InVehicle()){
- uint8 door_flag = GetCarDoorFlag(m_vehEnterType);
- if (m_pMyVehicle->pDriver == this)
- m_pMyVehicle->pDriver = nil;
- else {
- // FIX: Passenger counter now decreasing after removing ourself from vehicle.
- m_pMyVehicle->RemovePassenger(this);
- }
- if (m_nPedState == PED_EXIT_CAR || m_nPedState == PED_DRAG_FROM_CAR)
- m_pMyVehicle->m_nGettingOutFlags &= ~door_flag;
- bInVehicle = false;
- m_pMyVehicle = nil;
- } else if (EnteringCar()) {
- QuitEnteringCar();
- }
- if (m_pFire)
- m_pFire->Extinguish();
- CPopulation::UpdatePedCount((ePedType)m_nPedType, true);
- DMAudio.DestroyEntity(m_audioEntityId);
-}
-
-void
-CPed::FlagToDestroyWhenNextProcessed(void)
-{
- bRemoveFromWorld = true;
- if (!InVehicle())
- return;
- if (m_pMyVehicle->pDriver == this){
- m_pMyVehicle->pDriver = nil;
- if (IsPlayer() && m_pMyVehicle->GetStatus() != STATUS_WRECKED)
- m_pMyVehicle->SetStatus(STATUS_ABANDONED);
- }else{
- m_pMyVehicle->RemovePassenger(this);
- }
- bInVehicle = false;
- m_pMyVehicle = nil;
- if (CharCreatedBy == MISSION_CHAR)
- m_nPedState = PED_DEAD;
- else
- m_nPedState = PED_NONE;
- m_pVehicleAnim = nil;
-}
-
CPed::CPed(uint32 pedType) : m_pedIK(this)
{
m_type = ENTITY_TYPE_PED;
@@ -397,1617 +283,66 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
CPopulation::UpdatePedCount((ePedType)m_nPedType, false);
}
-uint32
-CPed::GiveWeapon(eWeaponType weaponType, uint32 ammo)
-{
- CWeapon &weapon = GetWeapon(weaponType);
-
- if (HasWeapon(weaponType)) {
- if (weapon.m_nAmmoTotal + ammo > 99999)
- weapon.m_nAmmoTotal = 99999;
- else
- weapon.m_nAmmoTotal += ammo;
-
- weapon.Reload();
- } else {
- weapon.Initialise(weaponType, ammo);
- // TODO: It seems game uses this as both weapon count and max WeaponType we have, which is ofcourse erroneous.
- m_maxWeaponTypeAllowed++;
- }
- if (weapon.m_eWeaponState == WEAPONSTATE_OUT_OF_AMMO)
- weapon.m_eWeaponState = WEAPONSTATE_READY;
-
- return weaponType;
-}
-
-static RwObject*
-RemoveAllModelCB(RwObject *object, void *data)
-{
- RpAtomic *atomic = (RpAtomic*)object;
- if (CVisibilityPlugins::GetAtomicModelInfo(atomic)) {
- RpClumpRemoveAtomic(RpAtomicGetClump(atomic), atomic);
- RpAtomicDestroy(atomic);
- }
- return object;
-}
-
-static PedOnGroundState
-CheckForPedsOnGroundToAttack(CPed *attacker, CPed **pedOnGround)
-{
- PedOnGroundState stateToReturn;
- float angleToFace;
- CPed *currentPed = nil;
- PedState currentPedState;
- CPed *pedOnTheFloor = nil;
- CPed *deadPed = nil;
- CPed *pedBelow = nil;
- bool foundDead = false;
- bool foundOnTheFloor = false;
- bool foundBelow = false;
- float angleDiff;
- float distance;
-
- if (!CGame::nastyGame)
- return NO_PED;
-
- for (int currentPedId = 0; currentPedId < attacker->m_numNearPeds; currentPedId++) {
-
- currentPed = attacker->m_nearPeds[currentPedId];
-
- CVector posDifference = currentPed->GetPosition() - attacker->GetPosition();
- distance = posDifference.Magnitude();
-
- if (distance < 2.0f) {
- angleToFace = CGeneral::GetRadianAngleBetweenPoints(
- currentPed->GetPosition().x, currentPed->GetPosition().y,
- attacker->GetPosition().x, attacker->GetPosition().y);
-
- angleToFace = CGeneral::LimitRadianAngle(angleToFace);
- attacker->m_fRotationCur = CGeneral::LimitRadianAngle(attacker->m_fRotationCur);
-
- angleDiff = Abs(angleToFace - attacker->m_fRotationCur);
-
- if (angleDiff > PI)
- angleDiff = 2 * PI - angleDiff;
-
- currentPedState = currentPed->m_nPedState;
-
- if (currentPed->OnGroundOrGettingUp()) {
- if (distance < 2.0f && angleDiff < DEGTORAD(65.0f)) {
- if (currentPedState == PED_DEAD) {
- foundDead = 1;
- if (!deadPed)
- deadPed = currentPed;
- } else if (!currentPed->IsPedHeadAbovePos(-0.6f)) {
- foundOnTheFloor = 1;
- if (!pedOnTheFloor)
- pedOnTheFloor = currentPed;
- }
- }
- } else if ((distance < 0.8f && angleDiff < DEGTORAD(75.0f))
- || (distance < 1.3f && angleDiff < DEGTORAD(55.0f))
- || (distance < 1.7f && angleDiff < DEGTORAD(35.0f))
- || (distance < 2.0f && angleDiff < DEGTORAD(30.0f))) {
-
- // Either this condition or below one was probably returning 4 early in development. See Fight().
- foundBelow = 1;
- pedBelow = currentPed;
- break;
- } else {
- if (angleDiff < DEGTORAD(75.0f)) {
- foundBelow = 1;
- if (!pedBelow)
- pedBelow = currentPed;
- }
- }
- }
- }
-
- if (foundOnTheFloor) {
- currentPed = pedOnTheFloor;
- stateToReturn = PED_ON_THE_FLOOR;
- } else if (foundDead) {
- currentPed = deadPed;
- stateToReturn = PED_DEAD_ON_THE_FLOOR;
- } else if (foundBelow) {
- currentPed = pedBelow;
- stateToReturn = PED_IN_FRONT_OF_ATTACKER;
- } else {
- currentPed = nil;
- stateToReturn = NO_PED;
- }
-
- if (pedOnGround)
- *pedOnGround = currentPed;
-
- return stateToReturn;
-}
-
-bool
-CPed::IsPlayer(void)
-{
- return m_nPedType == PEDTYPE_PLAYER1 || m_nPedType == PEDTYPE_PLAYER2 ||
- m_nPedType == PEDTYPE_PLAYER3 || m_nPedType == PEDTYPE_PLAYER4;
-}
-
-bool
-CPed::UseGroundColModel(void)
-{
- return m_nPedState == PED_FALL ||
- m_nPedState == PED_DIVE_AWAY ||
- m_nPedState == PED_DIE ||
- m_nPedState == PED_DEAD;
-}
-
-bool
-CPed::CanSetPedState(void)
-{
- return !DyingOrDead() && m_nPedState != PED_ARRESTED && !EnteringCar() && m_nPedState != PED_STEAL_CAR;
-}
-
-bool
-CPed::IsPedInControl(void)
-{
- return m_nPedState <= PED_STATES_NO_AI
- && !bIsInTheAir && !bIsLanding
- && m_fHealth > 0.0f;
-}
-
-bool
-CPed::CanStrafeOrMouseControl(void)
-{
-#ifdef FREE_CAM
- if (CCamera::bFreeCam)
- return false;
-#endif
- return m_nPedState == PED_NONE || m_nPedState == PED_IDLE || m_nPedState == PED_FLEE_POS || m_nPedState == PED_FLEE_ENTITY ||
- m_nPedState == PED_ATTACK || m_nPedState == PED_FIGHT || m_nPedState == PED_AIM_GUN || m_nPedState == PED_JUMP;
-}
-
-void
-CPed::AddWeaponModel(int id)
-{
- RpAtomic *atm;
-
- if (id != -1) {
-#ifdef PED_SKIN
- if (IsClumpSkinned(GetClump())) {
- if (m_pWeaponModel)
- RemoveWeaponModel(-1);
-
- m_pWeaponModel = (RpAtomic*)CModelInfo::GetModelInfo(id)->CreateInstance();
- } else
-#endif
- {
- atm = (RpAtomic*)CModelInfo::GetModelInfo(id)->CreateInstance();
- RwFrameDestroy(RpAtomicGetFrame(atm));
- RpAtomicSetFrame(atm, m_pFrames[PED_HANDR]->frame);
- RpClumpAddAtomic(GetClump(), atm);
- }
- m_wepModelID = id;
- }
-}
-
-void
-CPed::AimGun(void)
-{
- CVector vector;
-
- if (m_pSeekTarget) {
- if (m_pSeekTarget->IsPed()) {
- ((CPed*)m_pSeekTarget)->m_pedIK.GetComponentPosition(vector, PED_MID);
- } else {
- vector = m_pSeekTarget->GetPosition();
- }
- Say(SOUND_PED_ATTACK);
-
- bCanPointGunAtTarget = m_pedIK.PointGunAtPosition(vector);
- if (m_pLookTarget != m_pSeekTarget) {
- SetLookFlag(m_pSeekTarget, true);
- }
-
- } else {
- if (IsPlayer()) {
- bCanPointGunAtTarget = m_pedIK.PointGunInDirection(m_fLookDirection, ((CPlayerPed*)this)->m_fFPSMoveHeading);
- } else {
- bCanPointGunAtTarget = m_pedIK.PointGunInDirection(m_fLookDirection, 0.0f);
- }
- }
-}
-
-void
-CPed::ApplyHeadShot(eWeaponType weaponType, CVector pos, bool evenOnPlayer)
-{
- CVector pos2 = CVector(
- pos.x,
- pos.y,
- pos.z + 0.1f
- );
-
- if (!IsPlayer() || evenOnPlayer) {
- ++CStats::HeadsPopped;
-
- // BUG: This condition will always return true. Even fixing it won't work, because these states are unused.
- // if (m_nPedState != PED_PASSENGER || m_nPedState != PED_TAXI_PASSENGER) {
- SetDie(ANIM_KO_SHOT_FRONT1, 4.0f, 0.0f);
- // }
-
- bBodyPartJustCameOff = true;
- m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 150;
-
- CParticle::AddParticle(PARTICLE_TEST, pos2,
- CVector(0.0f, 0.0f, 0.0f), nil, 0.2f, 0, 0, 0, 0);
-
- if (CEntity::GetIsOnScreen()) {
- for(int i=0; i < 32; i++) {
- CParticle::AddParticle(PARTICLE_BLOOD_SMALL,
- pos2, CVector(0.0f, 0.0f, 0.03f),
- nil, 0.0f, 0, 0, 0, 0);
- }
-
- for (int i = 0; i < 16; i++) {
- CParticle::AddParticle(PARTICLE_DEBRIS2,
- pos2,
- CVector(0.0f, 0.0f, 0.01f),
- nil, 0.0f, 0, 0, 0, 0);
- }
- }
- }
-}
-
-static RwObject*
-SetPedAtomicVisibilityCB(RwObject* object, void* data)
-{
- if (data == nil)
- RpAtomicSetFlags((RpAtomic*)object, 0);
- return object;
-}
-
-static RwFrame*
-RecurseFrameChildrenVisibilityCB(RwFrame* frame, void* data)
-{
- RwFrameForAllObjects(frame, SetPedAtomicVisibilityCB, data);
- RwFrameForAllChildren(frame, RecurseFrameChildrenVisibilityCB, nil);
- return frame;
-}
-
-void
-CPed::RemoveBodyPart(PedNode nodeId, int8 direction)
-{
- RwFrame *frame;
- CVector pos;
-
- frame = m_pFrames[nodeId]->frame;
- if (frame) {
- if (CGame::nastyGame) {
-#ifdef PED_SKIN
- if(!IsClumpSkinned(GetClump()))
-#endif
- {
-#ifdef DEBUGMENU
- if (bPopHeadsOnHeadshot || nodeId != PED_HEAD)
-#else
- if (nodeId != PED_HEAD)
-#endif
- SpawnFlyingComponent(nodeId, direction);
-
- RecurseFrameChildrenVisibilityCB(frame, nil);
- }
- pos.x = 0.0f;
- pos.y = 0.0f;
- pos.z = 0.0f;
- TransformToNode(pos, PED_HEAD);
-
- if (CEntity::GetIsOnScreen()) {
- CParticle::AddParticle(PARTICLE_TEST, pos,
- CVector(0.0f, 0.0f, 0.0f),
- nil, 0.1f, 0, 0, 0, 0);
-
- for (int i = 0; i < 16; i++) {
- CParticle::AddParticle(PARTICLE_BLOOD_SMALL,
- pos,
- CVector(0.0f, 0.0f, 0.03f),
- nil, 0.0f, 0, 0, 0, 0);
- }
- }
- bBodyPartJustCameOff = true;
- m_bodyPartBleeding = nodeId;
- }
- } else {
- printf("Trying to remove ped component");
- }
-}
-
-void
-CPed::SetLookFlag(CEntity *target, bool keepTryingToLook)
-{
- if (m_lookTimer < CTimer::GetTimeInMilliseconds()) {
- bIsLooking = true;
- bIsRestoringLook = false;
- m_pLookTarget = target;
- m_pLookTarget->RegisterReference((CEntity**)&m_pLookTarget);
- m_fLookDirection = 999999.0f;
- m_lookTimer = 0;
- bKeepTryingToLook = keepTryingToLook;
- if (m_nPedState != PED_DRIVING) {
- m_pedIK.m_flags &= ~CPedIK::LOOKAROUND_HEAD_ONLY;
- }
- }
-}
-
-void
-CPed::SetLookFlag(float direction, bool keepTryingToLook)
-{
- if (m_lookTimer < CTimer::GetTimeInMilliseconds()) {
- bIsLooking = true;
- bIsRestoringLook = false;
- m_pLookTarget = nil;
- m_fLookDirection = direction;
- m_lookTimer = 0;
- bKeepTryingToLook = keepTryingToLook;
- if (m_nPedState != PED_DRIVING) {
- m_pedIK.m_flags &= ~CPedIK::LOOKAROUND_HEAD_ONLY;
- }
- }
-}
-
-void
-CPed::SetLookTimer(int time)
-{
- if (CTimer::GetTimeInMilliseconds() > m_lookTimer) {
- m_lookTimer = CTimer::GetTimeInMilliseconds() + time;
- }
-}
-
-bool
-CPed::OurPedCanSeeThisOne(CEntity *target)
-{
- CColPoint colpoint;
- CEntity *ent;
-
- CVector2D dist = CVector2D(target->GetPosition()) - CVector2D(GetPosition());
-
- // Check if target is behind ped
- if (DotProduct2D(dist, CVector2D(GetForward())) < 0.0f)
- return false;
-
- // Check if target is too far away
- if (dist.Magnitude() >= 40.0f)
- return false;
-
- // Check line of sight from head
- CVector headPos = this->GetPosition();
- headPos.z += 1.0f;
- return !CWorld::ProcessLineOfSight(headPos, target->GetPosition(), colpoint, ent, true, false, false, false, false, false);
-}
-
-void
-CPed::Avoid(void)
-{
- CPed *nearestPed;
-
- if(m_pedStats->m_temper > m_pedStats->m_fear && m_pedStats->m_temper > 50)
- return;
-
- if (CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) {
-
- if (m_nMoveState != PEDMOVE_NONE && m_nMoveState != PEDMOVE_STILL) {
- nearestPed = m_nearPeds[0];
-
- if (nearestPed && nearestPed->m_nPedState != PED_DEAD && nearestPed != m_pSeekTarget && nearestPed != m_pedInObjective) {
-
- // Check if this ped wants to avoid the nearest one
- if (CPedType::GetAvoid(m_nPedType) & CPedType::GetFlag(nearestPed->m_nPedType)) {
-
- // Further codes checks whether the distance between us and ped will be equal or below 1.0, if we walk up to him by 1.25 meters.
- // If so, we want to avoid it, so we turn our body 45 degree and look to somewhere else.
-
- // Game converts from radians to degress and back again here, doesn't make much sense
- CVector2D forward(-Sin(m_fRotationCur), Cos(m_fRotationCur));
- forward.Normalise(); // this is kinda pointless
-
- // Move forward 1.25 meters
- CVector2D testPosition = CVector2D(GetPosition()) + forward*1.25f;
-
- // Get distance to ped we want to avoid
- CVector2D distToPed = CVector2D(nearestPed->GetPosition()) - testPosition;
-
- if (distToPed.Magnitude() <= 1.0f && OurPedCanSeeThisOne((CEntity*)nearestPed)) {
- m_nPedStateTimer = CTimer::GetTimeInMilliseconds()
- + 500 + (m_randomSeed + 3 * CTimer::GetFrameCounter())
- % 1000 / 5;
-
- m_fRotationDest += DEGTORAD(45.0f);
- if (!bIsLooking) {
- SetLookFlag(nearestPed, false);
- SetLookTimer(CGeneral::GetRandomNumberInRange(500, 800));
- }
- }
- }
- }
- }
- }
-}
-
-void
-CPed::ClearAimFlag(void)
+CPed::~CPed(void)
{
- if (bIsAimingGun) {
- bIsAimingGun = false;
- bIsRestoringGun = true;
- m_pedIK.m_flags &= ~CPedIK::AIMS_WITH_ARM;
-#if defined VC_PED_PORTS || defined FIX_BUGS
- m_lookTimer = 0;
-#endif
- }
-
- if (IsPlayer())
- ((CPlayerPed*)this)->m_fFPSMoveHeading = 0.0f;
-}
-
-void
-CPed::ClearLookFlag(void) {
- if (bIsLooking) {
- bIsLooking = false;
- bIsRestoringLook = true;
- bShakeFist = false;
-
- m_pedIK.m_flags &= ~CPedIK::LOOKAROUND_HEAD_ONLY;
- if (IsPlayer())
- m_lookTimer = CTimer::GetTimeInMilliseconds() + 2000;
- else
- m_lookTimer = CTimer::GetTimeInMilliseconds() + 4000;
-
- if (m_nPedState == PED_LOOK_HEADING || m_nPedState == PED_LOOK_ENTITY) {
- ClearLook();
+ CWorld::Remove(this);
+ CRadar::ClearBlipForEntity(BLIP_CHAR, CPools::GetPedPool()->GetIndex(this));
+ if (InVehicle()){
+ uint8 door_flag = GetCarDoorFlag(m_vehEnterType);
+ if (m_pMyVehicle->pDriver == this)
+ m_pMyVehicle->pDriver = nil;
+ else {
+ // FIX: Passenger counter now decreasing after removing ourself from vehicle.
+ m_pMyVehicle->RemovePassenger(this);
}
+ if (m_nPedState == PED_EXIT_CAR || m_nPedState == PED_DRAG_FROM_CAR)
+ m_pMyVehicle->m_nGettingOutFlags &= ~door_flag;
+ bInVehicle = false;
+ m_pMyVehicle = nil;
+ } else if (EnteringCar()) {
+ QuitEnteringCar();
}
-}
-
-bool
-CPed::IsPedHeadAbovePos(float zOffset)
-{
- return zOffset + GetPosition().z < GetNodePosition(PED_HEAD).z;
+ if (m_pFire)
+ m_pFire->Extinguish();
+ CPopulation::UpdatePedCount((ePedType)m_nPedType, true);
+ DMAudio.DestroyEntity(m_audioEntityId);
}
void
-CPed::FinishedAttackCB(CAnimBlendAssociation *attackAssoc, void *arg)
+CPed::Initialise(void)
{
- CWeaponInfo *currentWeapon;
- CAnimBlendAssociation *newAnim;
- CPed *ped = (CPed*)arg;
-
- if (attackAssoc) {
- switch (attackAssoc->animId) {
- case ANIM_WEAPON_START_THROW:
- // what?!
- if ((!ped->IsPlayer() || ((CPlayerPed*)ped)->m_bHaveTargetSelected) && ped->IsPlayer()) {
- attackAssoc->blendDelta = -1000.0f;
- newAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_WEAPON_THROWU);
- } else {
- attackAssoc->blendDelta = -1000.0f;
- newAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_WEAPON_THROW);
- }
-
- newAnim->SetFinishCallback(FinishedAttackCB, ped);
- return;
-
- case ANIM_FIGHT_PPUNCH:
- attackAssoc->blendDelta = -8.0f;
- attackAssoc->flags |= ASSOC_DELETEFADEDOUT;
- ped->ClearAttack();
- return;
-
- case ANIM_WEAPON_THROW:
- case ANIM_WEAPON_THROWU:
- if (ped->GetWeapon()->m_nAmmoTotal > 0) {
- currentWeapon = CWeaponInfo::GetWeaponInfo(ped->GetWeapon()->m_eWeaponType);
- ped->AddWeaponModel(currentWeapon->m_nModelId);
- }
- break;
- default:
- break;
- }
- }
-
- if (!ped->bIsAttacking)
- ped->ClearAttack();
+ debug("Initialising CPed...\n");
+ CPedType::Initialise();
+ LoadFightData();
+ SetAnimOffsetForEnterOrExitVehicle();
+ debug("CPed ready\n");
}
void
-CPed::Attack(void)
+CPed::SetModelIndex(uint32 mi)
{
- CAnimBlendAssociation *weaponAnimAssoc;
- int32 weaponAnim;
- float animStart;
- eWeaponType ourWeaponType;
- float weaponAnimTime;
- eWeaponFire ourWeaponFire;
- float animLoopEnd;
- CWeaponInfo *ourWeapon;
- bool attackShouldContinue;
- AnimationId reloadAnim;
- CAnimBlendAssociation *reloadAnimAssoc;
- float delayBetweenAnimAndFire;
- CVector firePos;
-
- ourWeaponType = GetWeapon()->m_eWeaponType;
- ourWeapon = CWeaponInfo::GetWeaponInfo(ourWeaponType);
- ourWeaponFire = ourWeapon->m_eWeaponFire;
- weaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ourWeapon->m_AnimToPlay);
- attackShouldContinue = bIsAttacking;
- reloadAnimAssoc = nil;
- reloadAnim = NUM_ANIMS;
- delayBetweenAnimAndFire = ourWeapon->m_fAnimFrameFire;
- weaponAnim = ourWeapon->m_AnimToPlay;
-
- if (weaponAnim == ANIM_WEAPON_HGUN_BODY)
- reloadAnim = ANIM_HGUN_RELOAD;
- else if (weaponAnim == ANIM_WEAPON_AK_BODY)
- reloadAnim = ANIM_AK_RELOAD;
-
- if (reloadAnim != NUM_ANIMS)
- reloadAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), reloadAnim);
-
- if (bIsDucking)
- return;
-
- if (reloadAnimAssoc) {
- if (!IsPlayer() || ((CPlayerPed*)this)->m_bHaveTargetSelected)
- ClearAttack();
-
- return;
- }
-
- if (CTimer::GetTimeInMilliseconds() < m_shootTimer)
- attackShouldContinue = true;
-
- if (!weaponAnimAssoc) {
- weaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ourWeapon->m_Anim2ToPlay);
- delayBetweenAnimAndFire = ourWeapon->m_fAnim2FrameFire;
-
- // Long throw granade, molotov
- if (!weaponAnimAssoc && ourWeapon->m_bThrow) {
- weaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_THROWU);
- delayBetweenAnimAndFire = 0.2f;
- }
-
- if (!weaponAnimAssoc) {
- if (attackShouldContinue) {
- if (ourWeaponFire != WEAPON_FIRE_PROJECTILE || !IsPlayer() || ((CPlayerPed*)this)->m_bHaveTargetSelected) {
- if (!CGame::nastyGame || ourWeaponFire != WEAPON_FIRE_MELEE || CheckForPedsOnGroundToAttack(this, nil) < PED_ON_THE_FLOOR) {
- weaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ourWeapon->m_AnimToPlay, 8.0f);
- }
- else {
- weaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ourWeapon->m_Anim2ToPlay, 8.0f);
- }
-
- weaponAnimAssoc->SetFinishCallback(FinishedAttackCB, this);
- weaponAnimAssoc->SetRun();
-
- if (weaponAnimAssoc->currentTime == weaponAnimAssoc->hierarchy->totalLength)
- weaponAnimAssoc->SetCurrentTime(0.0f);
-
- if (IsPlayer()) {
- ((CPlayerPed*)this)->m_fAttackButtonCounter = 0.0f;
- ((CPlayerPed*)this)->m_bHaveTargetSelected = false;
- }
- }
- } else
- FinishedAttackCB(nil, this);
-
- return;
- }
- }
-
- animStart = ourWeapon->m_fAnimLoopStart;
- weaponAnimTime = weaponAnimAssoc->currentTime;
- if (weaponAnimTime > animStart && weaponAnimTime - weaponAnimAssoc->timeStep <= animStart) {
- if (ourWeapon->m_bCanAimWithArm)
- m_pedIK.m_flags |= CPedIK::AIMS_WITH_ARM;
- else
- m_pedIK.m_flags &= ~CPedIK::AIMS_WITH_ARM;
- }
-
- if (weaponAnimTime <= delayBetweenAnimAndFire || weaponAnimTime - weaponAnimAssoc->timeStep > delayBetweenAnimAndFire || !weaponAnimAssoc->IsRunning()) {
- if (weaponAnimAssoc->speed < 1.0f)
- weaponAnimAssoc->speed = 1.0f;
-
- } else {
- firePos = ourWeapon->m_vecFireOffset;
- if (ourWeaponType == WEAPONTYPE_BASEBALLBAT) {
- if (weaponAnimAssoc->animId == ourWeapon->m_Anim2ToPlay)
- firePos.z = 0.7f * ourWeapon->m_fRadius - 1.0f;
-
- firePos = GetMatrix() * firePos;
- } else if (ourWeaponType != WEAPONTYPE_UNARMED) {
- TransformToNode(firePos, weaponAnimAssoc->animId == ANIM_KICK_FLOOR ? PED_FOOTR : PED_HANDR);
- } else {
- firePos = GetMatrix() * firePos;
- }
-
- GetWeapon()->Fire(this, &firePos);
-
- if (ourWeaponType == WEAPONTYPE_MOLOTOV || ourWeaponType == WEAPONTYPE_GRENADE) {
- RemoveWeaponModel(ourWeapon->m_nModelId);
- }
- if (!GetWeapon()->m_nAmmoTotal && ourWeaponFire != WEAPON_FIRE_MELEE && FindPlayerPed() != this) {
- SelectGunIfArmed();
- }
-
- if (GetWeapon()->m_eWeaponState != WEAPONSTATE_MELEE_MADECONTACT) {
- // If reloading just began, start the animation
- // Last condition will always return true, even IDA hides it
- if (GetWeapon()->m_eWeaponState == WEAPONSTATE_RELOADING && reloadAnim != NUM_ANIMS /* && !reloadAnimAssoc*/) {
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, reloadAnim, 8.0f);
- ClearLookFlag();
- ClearAimFlag();
- bIsAttacking = false;
- bIsPointingGunAt = false;
- m_shootTimer = CTimer::GetTimeInMilliseconds();
- return;
- }
- } else {
- if (weaponAnimAssoc->animId == ANIM_WEAPON_BAT_V || weaponAnimAssoc->animId == ANIM_WEAPON_BAT_H) {
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_BAT_ATTACK, 1.0f);
- } else if (weaponAnimAssoc->animId == ANIM_FIGHT_PPUNCH) {
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_FIGHT_PUNCH_39, 0.0f);
- }
-
- weaponAnimAssoc->speed = 0.5f;
-
- if (bIsAttacking || CTimer::GetTimeInMilliseconds() < m_shootTimer) {
- weaponAnimAssoc->callbackType = 0;
- }
- }
-
- attackShouldContinue = false;
- }
-
- if (ourWeaponType == WEAPONTYPE_SHOTGUN) {
- weaponAnimTime = weaponAnimAssoc->currentTime;
- firePos = ourWeapon->m_vecFireOffset;
-
- if (weaponAnimTime > 1.0f && weaponAnimTime - weaponAnimAssoc->timeStep <= 1.0f && weaponAnimAssoc->IsRunning()) {
- TransformToNode(firePos, PED_HANDR);
-
- CVector gunshellPos(
- firePos.x - 0.6f * GetForward().x,
- firePos.y - 0.6f * GetForward().y,
- firePos.z - 0.15f * GetUp().z
- );
-
- CVector2D gunshellRot(
- GetRight().x,
- GetRight().y
- );
-
- gunshellRot.Normalise();
- GetWeapon()->AddGunshell(this, gunshellPos, gunshellRot, 0.025f);
- }
- }
-#ifdef VC_PED_PORTS
- if (IsPlayer()) {
- if (CPad::GetPad(0)->GetSprint()) {
- // animBreakout is a member of WeaponInfo in VC, so it's me that added the below line.
- float animBreakOut = ((ourWeaponType == WEAPONTYPE_FLAMETHROWER || ourWeaponType == WEAPONTYPE_UZI || ourWeaponType == WEAPONTYPE_SHOTGUN) ? 25 / 30.0f : 99 / 30.0f);
- if (!attackShouldContinue && weaponAnimAssoc->currentTime > animBreakOut) {
- weaponAnimAssoc->blendDelta = -4.0f;
- FinishedAttackCB(nil, this);
- return;
- }
- }
- }
-#endif
- animLoopEnd = ourWeapon->m_fAnimLoopEnd;
- if (ourWeaponFire == WEAPON_FIRE_MELEE && weaponAnimAssoc->animId == ourWeapon->m_Anim2ToPlay)
- animLoopEnd = 3.4f/6.0f;
-
- weaponAnimTime = weaponAnimAssoc->currentTime;
-
- // Anim loop end, either start the loop again or finish the attack
- if (weaponAnimTime > animLoopEnd || !weaponAnimAssoc->IsRunning() && ourWeaponFire != WEAPON_FIRE_PROJECTILE) {
-
- if (weaponAnimTime - 2.0f * weaponAnimAssoc->timeStep <= animLoopEnd
- && (bIsAttacking || CTimer::GetTimeInMilliseconds() < m_shootTimer)
- && GetWeapon()->m_eWeaponState != WEAPONSTATE_RELOADING) {
-
- weaponAnim = weaponAnimAssoc->animId;
- if (ourWeaponFire != WEAPON_FIRE_MELEE || CheckForPedsOnGroundToAttack(this, nil) < PED_ON_THE_FLOOR) {
- if (weaponAnim != ourWeapon->m_Anim2ToPlay || weaponAnim == ANIM_RBLOCK_CSHOOT) {
- weaponAnimAssoc->Start(ourWeapon->m_fAnimLoopStart);
- } else {
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ourWeapon->m_AnimToPlay, 8.0f);
- }
- } else {
- if (weaponAnim == ourWeapon->m_Anim2ToPlay)
- weaponAnimAssoc->SetCurrentTime(0.1f);
- else
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ourWeapon->m_Anim2ToPlay, 8.0f);
- }
-#ifdef VC_PED_PORTS
- } else if (IsPlayer() && m_pPointGunAt && bIsAimingGun && GetWeapon()->m_eWeaponState != WEAPONSTATE_RELOADING) {
- weaponAnimAssoc->SetCurrentTime(ourWeapon->m_fAnimLoopEnd);
- weaponAnimAssoc->flags &= ~ASSOC_RUNNING;
- SetPointGunAt(m_pPointGunAt);
-#endif
- } else {
- ClearAimFlag();
-
- // Echoes of bullets, at the end of the attack. (Bug: doesn't play while reloading)
- if (weaponAnimAssoc->currentTime - weaponAnimAssoc->timeStep <= ourWeapon->m_fAnimLoopEnd) {
- switch (ourWeaponType) {
- case WEAPONTYPE_UZI:
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_UZI_BULLET_ECHO, 0.0f);
- break;
- case WEAPONTYPE_AK47:
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_AK47_BULLET_ECHO, 0.0f);
- break;
- case WEAPONTYPE_M16:
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_M16_BULLET_ECHO, 0.0f);
- break;
- default:
- break;
- }
- }
-
- // Fun fact: removing this part leds to reloading flamethrower
- if (ourWeaponType == WEAPONTYPE_FLAMETHROWER && weaponAnimAssoc->IsRunning()) {
- weaponAnimAssoc->flags |= ASSOC_DELETEFADEDOUT;
- weaponAnimAssoc->flags &= ~ASSOC_RUNNING;
- weaponAnimAssoc->blendDelta = -4.0f;
- }
- }
- }
- if (weaponAnimAssoc->currentTime > delayBetweenAnimAndFire)
- attackShouldContinue = false;
+ CEntity::SetModelIndex(mi);
+ RpAnimBlendClumpInit(GetClump());
+ RpAnimBlendClumpFillFrameArray(GetClump(), m_pFrames);
+ CPedModelInfo *modelInfo = (CPedModelInfo *)CModelInfo::GetModelInfo(GetModelIndex());
+ SetPedStats(modelInfo->m_pedStatType);
+ m_headingRate = m_pedStats->m_headingChangeRate;
+ m_animGroup = (AssocGroupId) modelInfo->m_animGroup;
+ CAnimManager::AddAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE);
- bIsAttacking = attackShouldContinue;
-}
+ // This is a mistake by R*, velocity is CVector, whereas m_vecAnimMoveDelta is CVector2D.
+ (*RPANIMBLENDCLUMPDATA(m_rwObject))->velocity = (CVector*) &m_vecAnimMoveDelta;
-void
-CPed::RemoveWeaponModel(int modelId)
-{
- // modelId is not used!! This function just removes the current weapon.
#ifdef PED_SKIN
- if(IsClumpSkinned(GetClump())){
- if(m_pWeaponModel){
- RwFrame *frm = RpAtomicGetFrame(m_pWeaponModel);
- RpAtomicDestroy(m_pWeaponModel);
- RwFrameDestroy(frm);
- m_pWeaponModel = nil;
- }
- }else
-#endif
- RwFrameForAllObjects(m_pFrames[PED_HANDR]->frame,RemoveAllModelCB,nil);
- m_wepModelID = -1;
-}
-
-void
-CPed::SetCurrentWeapon(uint32 weaponType)
-{
- CWeaponInfo *weaponInfo;
- if (HasWeapon(weaponType)) {
- weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
- RemoveWeaponModel(weaponInfo->m_nModelId);
-
- m_currentWeapon = weaponType;
-
- weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
- AddWeaponModel(weaponInfo->m_nModelId);
- }
-}
-
-// Only used while deciding which gun ped should switch to, if no ammo left.
-bool
-CPed::SelectGunIfArmed(void)
-{
- for (int i = 0; i < m_maxWeaponTypeAllowed; i++) {
- if (GetWeapon(i).m_nAmmoTotal > 0) {
- eWeaponType weaponType = GetWeapon(i).m_eWeaponType;
- if (weaponType >= WEAPONTYPE_COLT45 && weaponType != WEAPONTYPE_M16 && weaponType <= WEAPONTYPE_FLAMETHROWER) {
- SetCurrentWeapon(i);
- return true;
- }
- }
- }
- SetCurrentWeapon(WEAPONTYPE_UNARMED);
- return false;
-}
-
-void
-CPed::Duck(void)
-{
- if (CTimer::GetTimeInMilliseconds() > m_duckTimer)
- ClearDuck();
-}
-
-void
-CPed::ClearDuck(void)
-{
- CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_DOWN);
- if (!animAssoc) {
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_LOW);
-
- if (!animAssoc) {
- bIsDucking = false;
- return;
- }
- }
-
- if (!bCrouchWhenShooting)
- return;
-
- if (m_nPedState != PED_ATTACK && m_nPedState != PED_AIM_GUN)
- return;
-
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RBLOCK_CSHOOT);
- if (!animAssoc || animAssoc->blendDelta < 0.0f) {
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_RBLOCK_CSHOOT, 4.0f);
- }
-}
-
-void
-CPed::ClearPointGunAt(void)
-{
- CAnimBlendAssociation *animAssoc;
- CWeaponInfo *weaponInfo;
-
- ClearLookFlag();
- ClearAimFlag();
- bIsPointingGunAt = false;
-#ifndef VC_PED_PORTS
- if (m_nPedState == PED_AIM_GUN) {
- RestorePreviousState();
-#else
- if (m_nPedState == PED_AIM_GUN || m_nPedState == PED_ATTACK) {
- m_nPedState = PED_IDLE;
- RestorePreviousState();
- }
-#endif
- weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), weaponInfo->m_AnimToPlay);
- if (!animAssoc || animAssoc->blendDelta < 0.0f) {
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), weaponInfo->m_Anim2ToPlay);
- }
- if (animAssoc) {
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- animAssoc->blendDelta = -4.0f;
- }
-#ifndef VC_PED_PORTS
- }
-#endif
-}
-
-void
-CPed::BeingDraggedFromCar(void)
-{
- CAnimBlendAssociation *animAssoc;
- AnimationId enterAnim;
- bool dontRunAnim = false;
- PedLineUpPhase lineUpType;
-
- if (!m_pVehicleAnim) {
- CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 100.0f);
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SIT);
- if (!animAssoc) {
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_LSIT);
- if (!animAssoc) {
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SITP);
- if (!animAssoc)
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SITPLO);
- }
- }
- if (animAssoc)
- animAssoc->blendDelta = -1000.0f;
-
- if (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR) {
- if (bWillBeQuickJacked) {
- enterAnim = ANIM_CAR_QJACKED;
- } else if (m_pMyVehicle->bLowVehicle) {
- enterAnim = ANIM_CAR_LJACKED_LHS;
- } else {
- enterAnim = ANIM_CAR_JACKED_LHS;
- }
- } else if (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR) {
- if (m_pMyVehicle->bLowVehicle)
- enterAnim = ANIM_CAR_LJACKED_RHS;
- else
- enterAnim = ANIM_CAR_JACKED_RHS;
- } else
- dontRunAnim = true;
-
-
- if (!dontRunAnim)
- m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, enterAnim);
-
- m_pVehicleAnim->SetFinishCallback(PedSetDraggedOutCarCB, this);
- lineUpType = LINE_UP_TO_CAR_START;
- } else if (m_pVehicleAnim->currentTime <= 1.4f) {
- m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
- lineUpType = LINE_UP_TO_CAR_START;
- } else {
- lineUpType = LINE_UP_TO_CAR_2;
- }
-
- LineUpPedWithCar(lineUpType);
-#ifdef VC_PED_PORTS
- if (m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE) {
- if (m_pMyVehicle) {
- m_pMyVehicle->ProcessOpenDoor(m_vehEnterType, NUM_ANIMS, m_pVehicleAnim->currentTime * 5.0f);
- }
- }
-#endif
-}
-
-void
-CPed::RestartNonPartialAnims(void)
-{
- CAnimBlendAssociation *assoc;
-
- for (assoc = RpAnimBlendClumpGetFirstAssociation(GetClump()); assoc; assoc = RpAnimBlendGetNextAssociation(assoc)) {
- if (!assoc->IsPartial())
- assoc->SetRun();
- }
-}
-
-void
-CPed::PedSetDraggedOutCarCB(CAnimBlendAssociation *dragAssoc, void *arg)
-{
- CAnimBlendAssociation *quickJackedAssoc;
- CVehicle *vehicle;
- CPed *ped = (CPed*)arg;
-
- quickJackedAssoc = RpAnimBlendClumpGetAssociation(ped->GetClump(), ANIM_CAR_QJACKED);
- if (ped->m_nPedState != PED_ARRESTED) {
- ped->m_nLastPedState = PED_NONE;
- if (dragAssoc)
- dragAssoc->blendDelta = -1000.0f;
- }
- ped->RestartNonPartialAnims();
- ped->m_pVehicleAnim = nil;
- ped->m_pSeekTarget = nil;
- vehicle = ped->m_pMyVehicle;
-
- if (vehicle) {
- vehicle->m_nGettingOutFlags &= ~GetCarDoorFlag(ped->m_vehEnterType);
-
- if (vehicle->pDriver == ped) {
- vehicle->RemoveDriver();
- if (vehicle->m_nDoorLock == CARLOCK_LOCKED_INITIALLY)
- vehicle->m_nDoorLock = CARLOCK_UNLOCKED;
-
- if (ped->m_nPedType == PEDTYPE_COP && vehicle->IsLawEnforcementVehicle())
- vehicle->ChangeLawEnforcerState(false);
- } else {
- vehicle->RemovePassenger(ped);
- }
- }
- ped->bInVehicle = false;
- if (ped->IsPlayer())
- AudioManager.PlayerJustLeftCar();
-
-#ifdef VC_PED_PORTS
- if (ped->m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE) {
- dragAssoc->SetDeleteCallback(PedSetDraggedOutCarPositionCB, ped);
- ped->m_fHealth = 0.0f;
- ped->SetDie(ANIM_FLOOR_HIT, 1000.0f, 0.5f);
- return;
- }
-#endif
-
- if (quickJackedAssoc) {
- dragAssoc->SetDeleteCallback(PedSetQuickDraggedOutCarPositionCB, ped);
- } else {
- dragAssoc->SetDeleteCallback(PedSetDraggedOutCarPositionCB, ped);
- if (ped->CanSetPedState())
- CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_GETUP1, 1000.0f);
- }
-
- ped->ReplaceWeaponWhenExitingVehicle();
-
- ped->m_nStoredMoveState = PEDMOVE_NONE;
- ped->bVehExitWillBeInstant = false;
-}
-
-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->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;
-}
-
-// This function was mostly duplicate of GetLocalPositionToOpenCarDoor, so I've used it.
-CVector
-CPed::GetPositionToOpenCarDoor(CVehicle *veh, uint32 component)
-{
- CVector localPos;
- CVector vehDoorPos;
-
- localPos = GetLocalPositionToOpenCarDoor(veh, component, 1.0f);
- vehDoorPos = Multiply3x3(veh->GetMatrix(), localPos) + veh->GetPosition();
-
-/*
- // Not used.
- CVector localVehDoorOffset;
-
- if (veh->bIsVan && (component == VEHICLE_ENTER_REAR_LEFT || component == VEHICLE_ENTER_REAR_RIGHT)) {
- localVehDoorOffset = vecPedVanRearDoorAnimOffset;
- } else {
- if (veh->bIsLow) {
- localVehDoorOffset = vecPedCarDoorLoAnimOffset;
- } else {
- localVehDoorOffset = vecPedCarDoorAnimOffset;
- }
- }
-
- vehDoorPosWithoutOffset = Multiply3x3(veh->GetMatrix(), localPos + localVehDoorOffset) + veh->GetPosition();
-*/
- return vehDoorPos;
-}
-
-CVector
-CPed::GetPositionToOpenCarDoor(CVehicle *veh, uint32 component, float offset)
-{
- CVector doorPos;
- CMatrix vehMat(veh->GetMatrix());
-
- doorPos = Multiply3x3(vehMat, GetLocalPositionToOpenCarDoor(veh, component, offset));
-
- return veh->GetPosition() + doorPos;
-}
-
-void
-CPed::LineUpPedWithCar(PedLineUpPhase phase)
-{
- bool vehIsUpsideDown = false;
- int vehAnim;
- float seatPosMult = 0.0f;
- float currentZ;
- float adjustedTimeStep;
-
- if (CReplay::IsPlayingBack())
- return;
-
- if (!bChangedSeat && phase != LINE_UP_TO_CAR_2) {
- if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SIT)) {
- SetPedPositionInCar();
- return;
- }
- if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_LSIT)) {
- SetPedPositionInCar();
- return;
- }
- if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SITP)) {
- SetPedPositionInCar();
- return;
- }
- if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SITPLO)) {
- SetPedPositionInCar();
- return;
- }
- bChangedSeat = true;
- }
- if (phase == LINE_UP_TO_CAR_START) {
- m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
- }
- CVehicle *veh = m_pMyVehicle;
-
- // Not quite right, IsUpsideDown func. checks for <= -0.9f.
- if (veh->GetUp().z <= -0.8f)
- vehIsUpsideDown = true;
-
- if (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR) {
- if (vehIsUpsideDown) {
- m_fRotationDest = -PI + veh->GetForward().Heading();
- } else if (veh->bIsBus) {
- m_fRotationDest = 0.5f * PI + veh->GetForward().Heading();
- } else {
- m_fRotationDest = veh->GetForward().Heading();
- }
- } else if (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR) {
- if (vehIsUpsideDown) {
- m_fRotationDest = veh->GetForward().Heading();
- } else if (veh->bIsBus) {
- m_fRotationDest = -0.5f * PI + veh->GetForward().Heading();
- } else {
- m_fRotationDest = veh->GetForward().Heading();
- }
- } else {
- // I don't know will this part ever run(maybe boats?), but the game also handles that. I don't know is it intentional.
-
- if (vehIsUpsideDown) {
- m_fRotationDest = veh->GetForward().Heading();
- } else if (veh->bIsBus) {
- m_fRotationDest = 0.5f * PI + veh->GetForward().Heading();
- } else {
- m_fRotationDest = veh->GetForward().Heading();
- }
- }
-
- if (!bInVehicle)
- seatPosMult = 1.0f;
-
-#ifdef VC_PED_PORTS
- bool multExtractedFromAnim = false;
- bool multExtractedFromAnimBus = false;
- float zBlend;
-#endif
- if (m_pVehicleAnim) {
- vehAnim = m_pVehicleAnim->animId;
-
- switch (vehAnim) {
- case ANIM_CAR_JACKED_RHS:
- case ANIM_CAR_LJACKED_RHS:
- case ANIM_CAR_JACKED_LHS:
- case ANIM_CAR_LJACKED_LHS:
- case ANIM_VAN_GETIN_L:
- case ANIM_VAN_GETIN:
-#ifdef VC_PED_PORTS
- multExtractedFromAnim = true;
- zBlend = Max(m_pVehicleAnim->currentTime / m_pVehicleAnim->hierarchy->totalLength - 0.3f, 0.0f) / (1.0f - 0.3f);
- // fall through
-#endif
- case ANIM_CAR_QJACKED:
- case ANIM_CAR_GETOUT_LHS:
- case ANIM_CAR_GETOUT_LOW_LHS:
- case ANIM_CAR_GETOUT_RHS:
- case ANIM_CAR_GETOUT_LOW_RHS:
-#ifdef VC_PED_PORTS
- if (!multExtractedFromAnim) {
- multExtractedFromAnim = true;
- zBlend = Max(m_pVehicleAnim->currentTime / m_pVehicleAnim->hierarchy->totalLength - 0.5f, 0.0f) / (1.0f - 0.5f);
- }
- // fall through
-#endif
- case ANIM_CAR_CRAWLOUT_RHS:
- case ANIM_CAR_CRAWLOUT_RHS2:
- case ANIM_VAN_GETOUT_L:
- case ANIM_VAN_GETOUT:
- seatPosMult = m_pVehicleAnim->currentTime / m_pVehicleAnim->hierarchy->totalLength;
- break;
- case ANIM_CAR_GETIN_RHS:
- case ANIM_CAR_GETIN_LHS:
-#ifdef VC_PED_PORTS
- if (veh && veh->IsCar() && veh->bIsBus) {
- multExtractedFromAnimBus = true;
- zBlend = Min(m_pVehicleAnim->currentTime / m_pVehicleAnim->hierarchy->totalLength, 0.5f) / 0.5f;
- }
- // fall through
-#endif
- case ANIM_CAR_QJACK:
- case ANIM_CAR_GETIN_LOW_LHS:
- case ANIM_CAR_GETIN_LOW_RHS:
- case ANIM_DRIVE_BOAT:
- seatPosMult = m_pVehicleAnim->GetTimeLeft() / m_pVehicleAnim->hierarchy->totalLength;
- break;
- case ANIM_CAR_CLOSEDOOR_LHS:
- case ANIM_CAR_CLOSEDOOR_LOW_LHS:
- case ANIM_CAR_CLOSEDOOR_RHS:
- case ANIM_CAR_CLOSEDOOR_LOW_RHS:
- case ANIM_CAR_SHUFFLE_RHS:
- case ANIM_CAR_LSHUFFLE_RHS:
- seatPosMult = 0.0f;
- break;
- case ANIM_CAR_CLOSE_LHS:
- case ANIM_CAR_CLOSE_RHS:
- case ANIM_COACH_OPEN_L:
- case ANIM_COACH_OPEN_R:
- case ANIM_COACH_IN_L:
- case ANIM_COACH_IN_R:
- case ANIM_COACH_OUT_L:
- seatPosMult = 1.0f;
- break;
- default:
- break;
- }
- }
-
- CVector neededPos;
-
- if (phase == LINE_UP_TO_CAR_2) {
- neededPos = GetPosition();
- } else {
- neededPos = GetPositionToOpenCarDoor(veh, m_vehEnterType, seatPosMult);
- }
-
- CVector 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) {
-#ifdef VC_PED_PORTS
- if (multExtractedFromAnim) {
- neededPos.z += (autoZPos.z - neededPos.z) * zBlend;
- } else {
-#endif
- currentZ = GetPosition().z;
- if (m_pVehicleAnim && vehAnim != ANIM_VAN_GETIN_L && vehAnim != ANIM_VAN_CLOSE_L && vehAnim != ANIM_VAN_CLOSE && vehAnim != ANIM_VAN_GETIN) {
- neededPos.z = autoZPos.z;
- m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
- } else if (neededPos.z <= currentZ && m_pVehicleAnim && vehAnim != ANIM_VAN_CLOSE_L && vehAnim != ANIM_VAN_CLOSE) {
- adjustedTimeStep = Min(m_pVehicleAnim->timeStep, 0.1f);
-
- // Smoothly change ped position
- neededPos.z = currentZ - (currentZ - neededPos.z) / (m_pVehicleAnim->GetTimeLeft() / adjustedTimeStep);
- }
-#ifdef VC_PED_PORTS
- }
-#endif
- } else {
- // We may need to raise up the ped
- if (phase == LINE_UP_TO_CAR_START) {
- currentZ = GetPosition().z;
-
- if (neededPos.z > currentZ) {
-#ifdef VC_PED_PORTS
- if (multExtractedFromAnimBus) {
- neededPos.z = (neededPos.z - currentZ) * zBlend + currentZ;
- } else {
-#endif
- if (m_pVehicleAnim &&
- (vehAnim == ANIM_CAR_GETIN_RHS || vehAnim == ANIM_CAR_GETIN_LOW_RHS || vehAnim == ANIM_CAR_GETIN_LHS || vehAnim == ANIM_CAR_GETIN_LOW_LHS
- || vehAnim == ANIM_CAR_QJACK || vehAnim == ANIM_VAN_GETIN_L || vehAnim == ANIM_VAN_GETIN)) {
- adjustedTimeStep = Min(m_pVehicleAnim->timeStep, 0.1f);
-
- // Smoothly change ped position
- neededPos.z = (neededPos.z - currentZ) / (m_pVehicleAnim->GetTimeLeft() / adjustedTimeStep) + currentZ;
- } else if (EnteringCar()) {
- neededPos.z = Max(currentZ, autoZPos.z);
- }
-#ifdef VC_PED_PORTS
- }
-#endif
- }
- }
- }
-
- bool stillGettingInOut = false;
- if (CTimer::GetTimeInMilliseconds() < m_nPedStateTimer)
- stillGettingInOut = veh->m_vehType != VEHICLE_TYPE_BOAT || bOnBoat;
-
- if (!stillGettingInOut) {
- m_fRotationCur = m_fRotationDest;
- } else {
- float limitedDest = CGeneral::LimitRadianAngle(m_fRotationDest);
- float timeUntilStateChange = (m_nPedStateTimer - CTimer::GetTimeInMilliseconds())/600.0f;
-
- if (timeUntilStateChange <= 0.0f) {
- m_vecOffsetSeek.x = 0.0f;
- m_vecOffsetSeek.y = 0.0f;
- }
- m_vecOffsetSeek.z = 0.0f;
-
- neededPos -= timeUntilStateChange * m_vecOffsetSeek;
-
- if (PI + m_fRotationCur < limitedDest) {
- limitedDest -= 2 * PI;
- } else if (m_fRotationCur - PI > limitedDest) {
- limitedDest += 2 * PI;
- }
- m_fRotationCur -= (m_fRotationCur - limitedDest) * (1.0f - timeUntilStateChange);
- }
-
- if (seatPosMult > 0.2f || vehIsUpsideDown) {
- SetPosition(neededPos);
- SetHeading(m_fRotationCur);
- } else {
- CMatrix vehDoorMat(veh->GetMatrix());
- vehDoorMat.GetPosition() += Multiply3x3(vehDoorMat, GetLocalPositionToOpenCarDoor(veh, m_vehEnterType, 0.0f));
- // VC couch anims are inverted, so they're fixing it here.
- GetMatrix() = vehDoorMat;
- }
-
-}
-
-static void
-particleProduceFootDust(CPed *ped, CVector const &pos, float size, int times)
-{
- switch (ped->m_nSurfaceTouched)
- {
- case SURFACE_TARMAC:
- case SURFACE_GRAVEL:
- case SURFACE_PAVEMENT:
- case SURFACE_SAND:
- for (int i = 0; i < times; ++i) {
- CVector adjustedPos = pos;
- adjustedPos.x += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f);
- adjustedPos.y += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f);
- CParticle::AddParticle(PARTICLE_PEDFOOT_DUST, adjustedPos, CVector(0.0f, 0.0f, 0.0f), nil, size, CRGBA(0, 0, 0, 0), 0, 0, 0, 0);
- }
- break;
- default:
- break;
- }
-}
-
-static void
-particleProduceFootSplash(CPed *ped, CVector const &pos, float size, int times)
-{
-#ifdef PC_PARTICLE
- for (int i = 0; i < times; i++) {
- CVector adjustedPos = pos;
- adjustedPos.x += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f);
- adjustedPos.y += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f);
-
- CVector direction = ped->GetForward() * -0.05f;
- CParticle::AddParticle(PARTICLE_RAIN_SPLASHUP, adjustedPos, direction, nil, size, CRGBA(32, 32, 32, 32), 0, 0, CGeneral::GetRandomNumber() & 1, 200);
- }
-#else
- for ( int32 i = 0; i < times; i++ )
- {
- CVector adjustedPos = pos;
- adjustedPos.x += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f);
- adjustedPos.y += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f);
-
- CParticle::AddParticle(PARTICLE_RAIN_SPLASHUP, adjustedPos, CVector(0.0f, 0.0f, 0.0f), nil, size, CRGBA(0, 0, 0, 0), 0, 0, CGeneral::GetRandomNumber() & 1, 200);
- }
+ if(modelInfo->GetHitColModel() == nil)
+ modelInfo->CreateHitColModelSkinned(GetClump());
#endif
}
void
-CPed::PlayFootSteps(void)
-{
- if (bDoBloodyFootprints) {
- if (m_bloodyFootprintCountOrDeathTime > 0 && m_bloodyFootprintCountOrDeathTime < 300) {
- m_bloodyFootprintCountOrDeathTime--;
-
- if (m_bloodyFootprintCountOrDeathTime == 0)
- bDoBloodyFootprints = false;
- }
- }
-
- if (!bIsStanding)
- return;
-
- CAnimBlendAssociation *assoc = RpAnimBlendClumpGetFirstAssociation(GetClump());
- CAnimBlendAssociation *walkRunAssoc = nil;
- float walkRunAssocBlend = 0.0f, idleAssocBlend = 0.0f;
-
- for (; assoc; assoc = RpAnimBlendGetNextAssociation(assoc)) {
- if (assoc->flags & ASSOC_WALK) {
- walkRunAssoc = assoc;
- walkRunAssocBlend += assoc->blendAmount;
- } else if ((assoc->flags & ASSOC_NOWALK) == 0) {
- idleAssocBlend += assoc->blendAmount;
- }
- }
-
-#ifdef GTA_PS2_STUFF
- CAnimBlendAssociation *runStopAsoc = NULL;
-
- if ( IsPlayer() )
- {
- runStopAsoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP);
-
- if ( runStopAsoc == NULL )
- runStopAsoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP_R);
- }
-
- if ( runStopAsoc != NULL && runStopAsoc->blendAmount > 0.1f )
- {
- {
- CVector pos(0.0f, 0.0f, 0.0f);
- TransformToNode(pos, PED_FOOTL);
-
- pos.z -= 0.1f;
- pos += GetForward()*0.2f;
- particleProduceFootDust(this, pos, 0.02f, 1);
- }
-
- {
- CVector pos(0.0f, 0.0f, 0.0f);
- TransformToNode(pos, PED_FOOTR);
-
- pos.z -= 0.1f;
- pos += GetForward()*0.2f;
- particleProduceFootDust(this, pos, 0.02f, 1);
- }
- }
-#endif
-
-
- if (walkRunAssoc && walkRunAssocBlend > 0.5f && idleAssocBlend < 1.0f) {
- float stepStart = 1 / 15.0f;
- float stepEnd = walkRunAssoc->hierarchy->totalLength / 2.0f + stepStart;
- float currentTime = walkRunAssoc->currentTime;
- int stepPart = 0;
-
- if (currentTime >= stepStart && currentTime - walkRunAssoc->timeStep < stepStart)
- stepPart = 1;
- else if (currentTime >= stepEnd && currentTime - walkRunAssoc->timeStep < stepEnd)
- stepPart = 2;
-
- if (stepPart != 0) {
- DMAudio.PlayOneShot(m_audioEntityId, stepPart == 1 ? SOUND_STEP_START : SOUND_STEP_END, 1.0f);
- CVector footPos(0.0f, 0.0f, 0.0f);
- TransformToNode(footPos, stepPart == 1 ? PED_FOOTL : PED_FOOTR);
-
- CVector forward = GetForward();
-
- footPos.z -= 0.1f;
- footPos += 0.2f * forward;
-
- if (bDoBloodyFootprints) {
- CVector2D top(forward * 0.26f);
- CVector2D right(GetRight() * 0.14f);
-
- CShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpBloodPoolTex, &footPos,
- top.x, top.y,
- right.x, right.y,
- 255, 255, 0, 0, 4.0f, 3000.0f, 1.0f);
-
- if (m_bloodyFootprintCountOrDeathTime <= 20) {
- m_bloodyFootprintCountOrDeathTime = 0;
- bDoBloodyFootprints = false;
- } else {
- m_bloodyFootprintCountOrDeathTime -= 20;
- }
- }
- if (CWeather::Rain <= 0.1f || CCullZones::CamNoRain() || CCullZones::PlayerNoRain()) {
- if(IsPlayer())
- particleProduceFootDust(this, footPos, 0.0f, 4);
- }
-#ifdef PC_PARTICLE
- else if(stepPart == 2)
-#else
- else
-#endif
- {
- particleProduceFootSplash(this, footPos, 0.15f, 4);
- }
- }
- }
-
- if (m_nSurfaceTouched == SURFACE_WATER) {
- float pedSpeed = CVector2D(m_vecMoveSpeed).Magnitude();
- if (pedSpeed > 0.03f && CTimer::GetFrameCounter() % 2 == 0 && pedSpeed > 0.13f) {
-#ifdef PC_PARTICLE
- float particleSize = pedSpeed * 2.0f;
-
- if (particleSize < 0.25f)
- particleSize = 0.25f;
-
- if (particleSize > 0.75f)
- particleSize = 0.75f;
-
- CVector particlePos = GetPosition() + GetForward() * 0.3f;
- particlePos.z -= 1.2f;
-
- CVector particleDir = m_vecMoveSpeed * -0.75f;
-
- particleDir.z = CGeneral::GetRandomNumberInRange(0.01f, 0.03f);
- CParticle::AddParticle(PARTICLE_PED_SPLASH, particlePos, particleDir, nil, 0.8f * particleSize, CRGBA(155,155,185,128), 0, 0, 0, 0);
-
- particleDir.z = CGeneral::GetRandomNumberInRange(0.03f, 0.05f);
- CParticle::AddParticle(PARTICLE_RUBBER_SMOKE, particlePos, particleDir, nil, particleSize, CRGBA(255,255,255,255), 0, 0, 0, 0);
-#else
- CVector particlePos = (GetPosition() - 0.3f * GetUp()) + GetForward()*0.3f;
- CVector particleDir = m_vecMoveSpeed * 0.45f;
- particleDir.z = CGeneral::GetRandomNumberInRange(0.03f, 0.05f);
- CParticle::AddParticle(PARTICLE_PED_SPLASH, particlePos-CVector(0.0f, 0.0f, 1.2f), particleDir, nil, 0.0f, CRGBA(155, 185, 155, 255));
-#endif
- }
- }
-}
-
-bool
-CPed::IsPointerValid(void)
-{
- int pedIndex = CPools::GetPedPool()->GetIndex(this) >> 8;
- if (pedIndex < 0 || pedIndex >= NUMPEDS)
- return false;
-
- if (m_entryInfoList.first || FindPlayerPed() == this)
- return true;
-
- return false;
-}
-
-// Some kind of binary sort
-void
-CPed::SortPeds(CPed **list, int min, int max)
+CPed::SetPedStats(ePedStats pedStat)
{
- if (min >= max)
- return;
-
- CVector leftDiff, rightDiff;
- CVector middleDiff = GetPosition() - list[(max + min) / 2]->GetPosition();
- float middleDist = middleDiff.Magnitude();
-
- int left = max;
- int right = min;
- while(right <= left){
- float rightDist, leftDist;
- do {
- rightDiff = GetPosition() - list[right]->GetPosition();
- rightDist = rightDiff.Magnitude();
- } while (middleDist > rightDist && ++right);
-
- do {
- leftDiff = GetPosition() - list[left]->GetPosition();
- leftDist = leftDiff.Magnitude();
- } while (middleDist < leftDist && left--);
-
- if (right <= left) {
- CPed *ped = list[right];
- list[right] = list[left];
- list[left] = ped;
- right++;
- left--;
- }
- }
- SortPeds(list, min, left);
- SortPeds(list, right, max);
+ m_pedStats = CPedStats::ms_apPedStats[pedStat];
}
void
@@ -2077,1402 +412,201 @@ CPed::BuildPedLists(void)
}
}
-void
-CPed::SetPedStats(ePedStats pedStat)
-{
- m_pedStats = CPedStats::ms_apPedStats[pedStat];
-}
-
-void
-CPed::SetModelIndex(uint32 mi)
-{
- CEntity::SetModelIndex(mi);
- RpAnimBlendClumpInit(GetClump());
- RpAnimBlendClumpFillFrameArray(GetClump(), m_pFrames);
- CPedModelInfo *modelInfo = (CPedModelInfo *)CModelInfo::GetModelInfo(GetModelIndex());
- SetPedStats(modelInfo->m_pedStatType);
- m_headingRate = m_pedStats->m_headingChangeRate;
- m_animGroup = (AssocGroupId) modelInfo->m_animGroup;
- CAnimManager::AddAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE);
-
- // This is a mistake by R*, velocity is CVector, whereas m_vecAnimMoveDelta is CVector2D.
- (*RPANIMBLENDCLUMPDATA(m_rwObject))->velocity = (CVector*) &m_vecAnimMoveDelta;
-
-#ifdef PED_SKIN
- if(modelInfo->GetHitColModel() == nil)
- modelInfo->CreateHitColModelSkinned(GetClump());
-#endif
-}
-
-void
-CPed::RemoveLighting(bool reset)
-{
- CRenderer::RemoveVehiclePedLights(this, reset);
-}
-
bool
-CPed::SetupLighting(void)
-{
- ActivateDirectional();
- SetAmbientColoursForPedsCarsAndObjects();
-
-#ifndef MASTER
- // Originally this was being called through iteration of Sectors, but putting it here is better.
- if (GetDebugDisplay() != 0 && !IsPlayer())
- DebugRenderOnePedText();
-#endif
-
- if (bRenderScorched) {
- WorldReplaceNormalLightsWithScorched(Scene.world, 0.1f);
- } else {
- // Note that this lightMult is only affected by LIGHT_DARKEN. If there's no LIGHT_DARKEN, it will be 1.0.
- float lightMult = CPointLights::GenerateLightsAffectingObject(&GetPosition());
- if (!bHasBlip && lightMult != 1.0f) {
- SetAmbientAndDirectionalColours(lightMult);
- return true;
- }
- }
- return false;
-}
-
-void
-CPed::Teleport(CVector pos)
-{
- CWorld::Remove(this);
- SetPosition(pos);
- bIsStanding = false;
- m_nPedStateTimer = 0;
- m_actionX = 0.0f;
- m_actionY = 0.0f;
- m_pDamageEntity = nil;
- CWorld::Add(this);
-}
-
-void
-CPed::CalculateNewOrientation(void)
-{
- if (CReplay::IsPlayingBack() || !IsPedInControl())
- return;
-
- SetHeading(m_fRotationCur);
-}
-
-float
-CPed::WorkOutHeadingForMovingFirstPerson(float offset)
-{
- if (!IsPlayer())
- return 0.0f;
-
- CPad *pad0 = CPad::GetPad(0);
- float leftRight = pad0->GetPedWalkLeftRight();
- float upDown = pad0->GetPedWalkUpDown();
- float &angle = ((CPlayerPed*)this)->m_fWalkAngle;
-
- if (upDown != 0.0f) {
- angle = CGeneral::GetRadianAngleBetweenPoints(0.0f, 0.0f, -leftRight, upDown);
- } else {
- if (leftRight < 0.0f)
- angle = 0.5f * PI;
- else if (leftRight > 0.0f)
- angle = -0.5f * PI;
- }
-
- return CGeneral::LimitRadianAngle(offset + angle);
-}
-
-void
-CPed::CalculateNewVelocity(void)
+CPed::OurPedCanSeeThisOne(CEntity *target)
{
- if (IsPedInControl()) {
- float headAmount = DEGTORAD(m_headingRate) * CTimer::GetTimeStep();
- m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur);
- float limitedRotDest = CGeneral::LimitRadianAngle(m_fRotationDest);
-
- if (m_fRotationCur - PI > limitedRotDest) {
- limitedRotDest += 2 * PI;
- } else if(PI + m_fRotationCur < limitedRotDest) {
- limitedRotDest -= 2 * PI;
- }
-
- if (IsPlayer() && m_nPedState == PED_ATTACK)
- headAmount /= 4.0f;
-
- float neededTurn = limitedRotDest - m_fRotationCur;
- if (neededTurn <= headAmount) {
- if (neededTurn > (-headAmount))
- m_fRotationCur += neededTurn;
- else
- m_fRotationCur -= headAmount;
- } else {
- m_fRotationCur += headAmount;
- }
- }
-
- CVector2D forward(Sin(m_fRotationCur), Cos(m_fRotationCur));
-
- m_moved.x = CrossProduct2D(m_vecAnimMoveDelta, forward); // (m_vecAnimMoveDelta.x * Cos(m_fRotationCur)) + -Sin(m_fRotationCur) * m_vecAnimMoveDelta.y;
- m_moved.y = DotProduct2D(m_vecAnimMoveDelta, forward); // m_vecAnimMoveDelta.y* Cos(m_fRotationCur) + (m_vecAnimMoveDelta.x * Sin(m_fRotationCur));
-
- if (CTimer::GetTimeStep() >= 0.01f) {
- m_moved = m_moved * (1 / CTimer::GetTimeStep());
- } else {
- m_moved = m_moved * (1 / 100.0f);
- }
-
- if ((!TheCamera.Cams[TheCamera.ActiveCam].GetWeaponFirstPersonOn() && !TheCamera.Cams[0].Using3rdPersonMouseCam())
- || FindPlayerPed() != this || !CanStrafeOrMouseControl())
- return;
-
- float walkAngle = WorkOutHeadingForMovingFirstPerson(m_fRotationCur);
- float pedSpeed = m_moved.Magnitude();
- float localWalkAngle = CGeneral::LimitRadianAngle(walkAngle - m_fRotationCur);
-
- if (localWalkAngle < -0.5f * PI) {
- localWalkAngle += PI;
- } else if (localWalkAngle > 0.5f * PI) {
- localWalkAngle -= PI;
- }
-
- // Interestingly this part is responsible for diagonal walking.
- if (localWalkAngle > -DEGTORAD(50.0f) && localWalkAngle < DEGTORAD(50.0f)) {
- TheCamera.Cams[TheCamera.ActiveCam].m_fPlayerVelocity = pedSpeed;
- m_moved = CVector2D(-Sin(walkAngle), Cos(walkAngle)) * pedSpeed;
- }
-
- CAnimBlendAssociation *idleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE);
- CAnimBlendAssociation *fightAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FIGHT_IDLE);
-#ifdef VC_PED_PORTS
- if ((!idleAssoc || idleAssoc->blendAmount < 0.5f) && !fightAssoc && !bIsDucking) {
-#else
- if ((!idleAssoc || idleAssoc->blendAmount < 0.5f) && !fightAssoc) {
-#endif
- LimbOrientation newUpperLegs;
- newUpperLegs.yaw = localWalkAngle;
-
- if (newUpperLegs.yaw < -DEGTORAD(100.0f)) {
- newUpperLegs.yaw += PI;
- } else if (newUpperLegs.yaw > DEGTORAD(100.0f)) {
- newUpperLegs.yaw -= PI;
- }
-
- if (newUpperLegs.yaw > -DEGTORAD(50.0f) && newUpperLegs.yaw < DEGTORAD(50.0f)) {
-#ifdef PED_SKIN
- if(IsClumpSkinned(GetClump())){
-/*
- // this looks shit
- newUpperLegs.pitch = 0.0f;
- RwV3d axis = { -1.0f, 0.0f, 0.0f };
- RtQuatRotate(&m_pFrames[PED_UPPERLEGL]->hanimFrame->q, &axis, RADTODEG(newUpperLegs.yaw), rwCOMBINEPRECONCAT);
- RtQuatRotate(&m_pFrames[PED_UPPERLEGR]->hanimFrame->q, &axis, RADTODEG(newUpperLegs.yaw), rwCOMBINEPRECONCAT);
-*/
- newUpperLegs.pitch = 0.1f;
- RwV3d Xaxis = { 1.0f, 0.0f, 0.0f };
- RwV3d Zaxis = { 0.0f, 0.0f, 1.0f };
- RtQuatRotate(&m_pFrames[PED_UPPERLEGL]->hanimFrame->q, &Zaxis, RADTODEG(newUpperLegs.pitch), rwCOMBINEPOSTCONCAT);
- RtQuatRotate(&m_pFrames[PED_UPPERLEGL]->hanimFrame->q, &Xaxis, RADTODEG(newUpperLegs.yaw), rwCOMBINEPOSTCONCAT);
- RtQuatRotate(&m_pFrames[PED_UPPERLEGR]->hanimFrame->q, &Zaxis, RADTODEG(newUpperLegs.pitch), rwCOMBINEPOSTCONCAT);
- RtQuatRotate(&m_pFrames[PED_UPPERLEGR]->hanimFrame->q, &Xaxis, RADTODEG(newUpperLegs.yaw), rwCOMBINEPOSTCONCAT);
+ CColPoint colpoint;
+ CEntity *ent;
- bDontAcceptIKLookAts = true;
- }else
-#endif
- {
- newUpperLegs.pitch = 0.0f;
- m_pedIK.RotateTorso(m_pFrames[PED_UPPERLEGL], &newUpperLegs, false);
- m_pedIK.RotateTorso(m_pFrames[PED_UPPERLEGR], &newUpperLegs, false);
- }
- }
- }
-}
+ CVector2D dist = CVector2D(target->GetPosition()) - CVector2D(GetPosition());
-bool
-CPed::CanBeDeleted(void)
-{
- if (bInVehicle)
+ // Check if target is behind ped
+ if (DotProduct2D(dist, CVector2D(GetForward())) < 0.0f)
return false;
- switch (CharCreatedBy) {
- case RANDOM_CHAR:
- return true;
- case MISSION_CHAR:
- return false;
- default:
- return true;
- }
-}
-
-bool
-CPed::CanPedDriveOff(void)
-{
- if (m_nPedState != PED_DRIVING || m_lookTimer > CTimer::GetTimeInMilliseconds())
+ // Check if target is too far away
+ if (dist.Magnitude() >= 40.0f)
return false;
- for (int i = 0; i < m_numNearPeds; i++) {
- CPed *nearPed = m_nearPeds[i];
- if (nearPed->m_nPedType == m_nPedType && nearPed->m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER && nearPed->m_carInObjective == m_carInObjective) {
- m_lookTimer = CTimer::GetTimeInMilliseconds() + 1000;
- return false;
- }
- }
- return true;
-}
-
-#ifdef VC_PED_PORTS
-bool
-CPed::CanPedJumpThis(CEntity *unused, CVector *damageNormal = nil)
-{
- if (m_nSurfaceTouched == SURFACE_WATER)
- return true;
-
- CVector pos = GetPosition();
- CVector forwardOffset = GetForward();
- if (damageNormal && damageNormal->z > 0.17f) {
- if (damageNormal->z > 0.9f)
- return false;
-
- CColModel *ourCol = CModelInfo::GetModelInfo(m_modelIndex)->GetColModel();
- pos.z = ourCol->spheres->center.z - ourCol->spheres->radius * damageNormal->z + pos.z;
- pos.z = pos.z + 0.05f;
- float collPower = damageNormal->Magnitude2D();
- if (damageNormal->z > 0.5f) {
- CVector invDamageNormal(-damageNormal->x, -damageNormal->y, 0.0f);
- invDamageNormal *= 1.0f / collPower;
- CVector estimatedJumpDist = invDamageNormal + collPower * invDamageNormal * ourCol->spheres->radius;
- forwardOffset = estimatedJumpDist * Min(2.0f / collPower, 4.0f);
- } else {
- forwardOffset += collPower * ourCol->spheres->radius * forwardOffset;
- }
- } else {
- pos.z -= 0.15f;
- }
-
- CVector forwardPos = pos + forwardOffset;
- return CWorld::GetIsLineOfSightClear(pos, forwardPos, true, false, false, true, false, false, false);
-}
-#else
-bool
-CPed::CanPedJumpThis(CEntity *unused)
-{
- CVector2D forward(-Sin(m_fRotationCur), Cos(m_fRotationCur));
- CVector pos = GetPosition();
- CVector forwardPos(
- forward.x + pos.x,
- forward.y + pos.y,
- pos.z);
-
- return CWorld::GetIsLineOfSightClear(pos, forwardPos, true, false, false, true, false, false, false);
-}
-#endif
-
-bool
-CPed::CanPedReturnToState(void)
-{
- return m_nPedState <= PED_STATES_NO_AI && m_nPedState != PED_AIM_GUN && m_nPedState != PED_ATTACK &&
- m_nPedState != PED_FIGHT && m_nPedState != PED_STEP_AWAY && m_nPedState != PED_SNIPER_MODE && m_nPedState != PED_LOOK_ENTITY;
-}
-
-bool
-CPed::CanSeeEntity(CEntity *entity, float threshold = CAN_SEE_ENTITY_ANGLE_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;
-}
-
-bool
-CPed::IsTemporaryObjective(eObjective objective)
-{
- return objective == OBJECTIVE_LEAVE_CAR || objective == OBJECTIVE_SET_LEADER ||
-#ifdef VC_PED_PORTS
- objective == OBJECTIVE_LEAVE_CAR_AND_DIE ||
-#endif
- objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER;
-}
-
-void
-CPed::SetMoveState(eMoveState state)
-{
- m_nMoveState = state;
-}
-
-void
-CPed::SetObjectiveTimer(int time)
-{
- if (time == 0) {
- m_objectiveTimer = 0;
- } else if (CTimer::GetTimeInMilliseconds() > m_objectiveTimer) {
- m_objectiveTimer = CTimer::GetTimeInMilliseconds() + time;
- }
-}
-
-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_ENTER_CAR_AS_PASSENGER:
- case OBJECTIVE_ENTER_CAR_AS_DRIVER:
- case OBJECTIVE_GOTO_AREA_ON_FOOT:
- case OBJECTIVE_RUN_TO_AREA:
- return;
- default:
- m_prevObjective = m_objective;
- }
-}
-
-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_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:
- return;
- default:
- m_prevObjective = m_objective;
- }
-}
-
-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
-#if defined VC_PED_PORTS || defined FIX_BUGS
- && m_nPedState != PED_CARJACK
-#endif
- )
- 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::SetLeader(CEntity *leader)
-{
- m_leader = (CPed*)leader;
-
- if(m_leader)
- m_leader->RegisterReference((CEntity **)&m_leader);
+ // Check line of sight from head
+ CVector headPos = this->GetPosition();
+ headPos.z += 1.0f;
+ return !CWorld::ProcessLineOfSight(headPos, target->GetPosition(), colpoint, ent, true, false, false, false, false, false);
}
+// Some kind of binary sort
void
-CPed::SetObjective(eObjective newObj, void *entity)
+CPed::SortPeds(CPed **list, int min, int max)
{
- if (DyingOrDead())
- return;
-
- if (m_prevObjective == newObj) {
- // Why?
- if (m_prevObjective != OBJECTIVE_NONE)
- return;
- }
-
- if (entity == this)
+ if (min >= max)
return;
- SetObjectiveTimer(0);
- 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_FOLLOW_CHAR_IN_FORMATION:
- case OBJECTIVE_GOTO_AREA_ANY_MEANS:
- case OBJECTIVE_GUARD_ATTACK:
- if (m_pedInObjective == entity)
- return;
-
- break;
- case OBJECTIVE_LEAVE_CAR:
- case OBJECTIVE_FLEE_CAR:
-#ifdef VC_PED_PORTS
- case OBJECTIVE_LEAVE_CAR_AND_DIE:
-#endif
- 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;
+ CVector leftDiff, rightDiff;
+ CVector middleDiff = GetPosition() - list[(max + min) / 2]->GetPosition();
+ float middleDist = middleDiff.Magnitude();
- break;
- case OBJECTIVE_SET_LEADER:
- if (m_leader == entity)
- return;
+ int left = max;
+ int right = min;
+ while(right <= left){
+ float rightDist, leftDist;
+ do {
+ rightDiff = GetPosition() - list[right]->GetPosition();
+ rightDist = rightDiff.Magnitude();
+ } while (middleDist > rightDist && ++right);
- break;
- default:
- break;
- }
- } else {
- if ((newObj == OBJECTIVE_LEAVE_CAR
-#ifdef VC_PED_PORTS
- || newObj == OBJECTIVE_LEAVE_CAR_AND_DIE
-#endif
- ) && !bInVehicle)
- return;
- }
+ do {
+ leftDiff = GetPosition() - list[left]->GetPosition();
+ leftDist = leftDiff.Magnitude();
+ } while (middleDist < leftDist && left--);
-#ifdef VC_PED_PORTS
- ClearPointGunAt();
-#endif
- bObjectiveCompleted = false;
- if (IsTemporaryObjective(m_objective) && !IsTemporaryObjective(newObj)) {
- m_prevObjective = newObj;
- } else {
- if (m_objective != newObj) {
- if (IsTemporaryObjective(newObj))
- ForceStoredObjective(newObj);
- else
- SetStoredObjective();
+ if (right <= left) {
+ CPed *ped = list[right];
+ list[right] = list[left];
+ list[left] = ped;
+ right++;
+ left--;
}
- m_objective = newObj;
- }
-
- switch (newObj) {
- 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:
- m_pNextPathNode = nil;
- bUsePedNodeSeek = false;
- m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f);
- m_pedInObjective = (CPed*)entity;
- m_pedInObjective->RegisterReference((CEntity**)&m_pedInObjective);
- m_pLookTarget = (CEntity*)entity;
- 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_GUARD_ATTACK:
- m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f);
- m_pedInObjective = (CPed*)entity;
- 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:
-#ifdef VC_PED_PORTS
- case OBJECTIVE_LEAVE_CAR_AND_DIE:
-#endif
- 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_ENTER_CAR_AS_PASSENGER:
- case OBJECTIVE_ENTER_CAR_AS_DRIVER:
- if (m_nMoveState == PEDMOVE_STILL)
- SetMoveState(PEDMOVE_RUN);
-
- if (((CVehicle*)entity)->m_vehType == VEHICLE_TYPE_BOAT && !IsPlayer()) {
- 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;
- default:
- break;
- }
-}
-
-void
-CPed::SetIdle(void)
-{
- if (m_nPedState != PED_IDLE && m_nPedState != PED_MUG && m_nPedState != PED_FLEE_ENTITY) {
-#ifdef VC_PED_PORTS
- if (m_nPedState == PED_AIM_GUN)
- ClearPointGunAt();
-
- m_nLastPedState = PED_NONE;
-#endif
- m_nPedState = PED_IDLE;
- SetMoveState(PEDMOVE_STILL);
- }
- if (m_nWaitState == WAITSTATE_FALSE) {
- m_nWaitTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(2000, 4000);
}
+ SortPeds(list, min, left);
+ SortPeds(list, right, max);
}
void
-CPed::SetObjective(eObjective newObj)
+CPed::SetMoveState(eMoveState state)
{
- if (DyingOrDead())
- 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
-#ifdef VC_PED_PORTS
- || m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE)
- && !IsPlayer()
-#else
- )
-#endif
- && !IsPedInControl()) {
-
- bStartWanderPathOnFoot = true;
- return;
- }
- // Unused code from assembly...
- /*
- else if(m_objective == OBJECTIVE_FLEE_CAR) {
-
- } 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;
- }
- }
+ m_nMoveState = state;
}
-// 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)
+CPed::SetMoveAnim(void)
{
- if (DyingOrDead())
- return;
-
- if (m_prevObjective == newObj && m_prevObjective != OBJECTIVE_NONE)
+ if (m_nStoredMoveState == m_nMoveState || !IsPedInControl())
return;
- SetObjectiveTimer(0);
-
- if (m_objective == newObj && newObj == OBJECTIVE_FOLLOW_ROUTE && m_routeLastPoint == routePoint && m_routeType == routeType)
+ if (m_nMoveState == PEDMOVE_NONE) {
+ m_nStoredMoveState = PEDMOVE_NONE;
return;
-
- 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::ClearChat(void)
-{
- CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_CHAT);
- if (animAssoc) {
- animAssoc->blendDelta = -8.0f;
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- }
- bIsTalking = false;
- ClearLookFlag();
- RestorePreviousState();
-}
-
-bool
-CPed::IsGangMember(void)
-{
- return m_nPedType >= PEDTYPE_GANG1 && m_nPedType <= PEDTYPE_GANG9;
-}
-
-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;
+ AssocGroupId animGroupToUse;
+ if (m_leader && m_leader->IsPlayer())
+ animGroupToUse = ASSOCGRP_PLAYER;
+ else
+ animGroupToUse = m_animGroup;
- attackerPed = ((CVehicle*)attacker)->pDriver;
- if (!attackerPed)
+ CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_BLOCK);
+ if (!animAssoc) {
+ CAnimBlendAssociation *fightIdleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FIGHT_IDLE);
+ animAssoc = fightIdleAssoc;
+ if (fightIdleAssoc && m_nPedState == PED_FIGHT)
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);
+ if (fightIdleAssoc) {
+ CAnimBlendAssociation *idleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE);
+ if (!idleAssoc || idleAssoc->blendDelta <= 0.0f) {
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), animGroupToUse, ANIM_IDLE_STANCE, 8.0f);
}
}
}
-}
-
-void
-CPed::QuitEnteringCar(void)
-{
- CVehicle *veh = m_pMyVehicle;
- if (m_pVehicleAnim)
- m_pVehicleAnim->blendDelta = -1000.0f;
-
- RestartNonPartialAnims();
-
- if (!RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE))
- CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 100.0f);
-
- if (veh) {
- if (m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || m_nPedState == PED_CARJACK)
- veh->bIsBeingCarJacked = false;
-
- if (veh->m_nNumGettingIn != 0)
- veh->m_nNumGettingIn--;
-
-#ifdef VC_PED_PORTS
- if (m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER)
- RestorePreviousObjective();
-#endif
-
- veh->m_nGettingInFlags &= ~GetCarDoorFlag(m_vehEnterType);
- }
-
- bUsesCollision = true;
-
- ReplaceWeaponWhenExitingVehicle();
-
- 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) {
-#ifdef VC_PED_PORTS
- if (veh->AutoPilot.m_nCruiseSpeed == 0 && veh->VehicleCreatedBy == RANDOM_VEHICLE)
-#else
- if (veh->AutoPilot.m_nCruiseSpeed == 0)
-#endif
- veh->AutoPilot.m_nCruiseSpeed = 17;
- }
-}
-
-void
-CPed::ReactToAttack(CEntity *attacker)
-{
- if (IsPlayer() && attacker->IsPed()) {
- InformMyGangOfAttack(attacker);
- SetLookFlag(attacker, true);
- SetLookTimer(700);
- return;
- }
-
-#ifdef VC_PED_PORTS
- if (m_nPedState == PED_DRIVING && InVehicle()
- && (m_pMyVehicle->pDriver == this || m_pMyVehicle->pDriver && m_pMyVehicle->pDriver->m_nPedState == PED_DRIVING && m_pMyVehicle->pDriver->m_objective != OBJECTIVE_LEAVE_CAR_AND_DIE)) {
-
- if (m_pMyVehicle->VehicleCreatedBy == RANDOM_VEHICLE
- && (m_pMyVehicle->GetStatus() == STATUS_SIMPLE || m_pMyVehicle->GetStatus() == STATUS_PHYSICS)
- && m_pMyVehicle->AutoPilot.m_nCarMission == MISSION_CRUISE) {
-
- CCarCtrl::SwitchVehicleToRealPhysics(m_pMyVehicle);
- m_pMyVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;
- m_pMyVehicle->AutoPilot.m_nCruiseSpeed = GAME_SPEED_TO_CARAI_SPEED * m_pMyVehicle->pHandling->Transmission.fUnkMaxVelocity;
- m_pMyVehicle->SetStatus(STATUS_PHYSICS);
- }
- } else
-#endif
- if (IsPedInControl() && (CharCreatedBy != MISSION_CHAR || bRespondsToThreats)) {
- CPed *ourLeader = m_leader;
- if (ourLeader != attacker && (!ourLeader || FindPlayerPed() != ourLeader)
- && 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));
+ if (!animAssoc) {
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_TIRED);
+ if (animAssoc)
+ if (m_nWaitState == WAITSTATE_STUCK || m_nWaitState == WAITSTATE_FINISH_FLEE)
return;
- }
- 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);
+ if (animAssoc) {
+ CAnimBlendAssociation *idleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE);
+ if (!idleAssoc || idleAssoc->blendDelta <= 0.0f) {
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), animGroupToUse, ANIM_IDLE_STANCE, 4.0f);
}
}
}
-}
-
-bool
-CPed::TurnBody(void)
-{
- bool turnDone = true;
-
- if (m_pLookTarget)
- m_fLookDirection = CGeneral::GetRadianAngleBetweenPoints(
- m_pLookTarget->GetPosition().x,
- m_pLookTarget->GetPosition().y,
- GetPosition().x,
- GetPosition().y);
-
- float limitedLookDir = CGeneral::LimitRadianAngle(m_fLookDirection);
- float currentRot = m_fRotationCur;
-
- if (currentRot - PI > limitedLookDir)
- limitedLookDir += 2 * PI;
- else if (PI + currentRot < limitedLookDir)
- limitedLookDir -= 2 * PI;
-
- float neededTurn = currentRot - limitedLookDir;
- m_fRotationDest = limitedLookDir;
-
- if (Abs(neededTurn) > 0.05f) {
- turnDone = false;
- currentRot -= neededTurn * 0.2f;
- }
-
- m_fRotationCur = currentRot;
- m_fLookDirection = limitedLookDir;
- return turnDone;
-}
-
-void
-CPed::Chat(void)
-{
- // We're already looking to our partner
- if (bIsLooking && TurnBody())
- ClearLookFlag();
-
- if (!m_pLookTarget || !m_pLookTarget->IsPed()) {
- ClearChat();
- return;
- }
-
- CPed *partner = (CPed*) m_pLookTarget;
+ if (!animAssoc) {
+ m_nStoredMoveState = m_nMoveState;
+ if (m_nMoveState == PEDMOVE_WALK || m_nMoveState == PEDMOVE_RUN || m_nMoveState == PEDMOVE_SPRINT) {
+ for (CAnimBlendAssociation *assoc = RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_PARTIAL);
+ assoc; assoc = RpAnimBlendGetNextAssociation(assoc, ASSOC_PARTIAL)) {
- if (partner->m_nPedState != PED_CHAT) {
- ClearChat();
- if (partner->m_pedInObjective) {
- if (partner->m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT ||
- partner->m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE)
- ReactToAttack(partner->m_pedInObjective);
- }
- return;
- }
- if (bIsTalking) {
- if (CGeneral::GetRandomNumber() < 512) {
- CAnimBlendAssociation *chatAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_CHAT);
- if (chatAssoc) {
- chatAssoc->blendDelta = -4.0f;
- chatAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ if (!(assoc->flags & ASSOC_FADEOUTWHENDONE)) {
+ assoc->blendDelta = -2.0f;
+ assoc->flags |= ASSOC_DELETEFADEDOUT;
+ }
}
- bIsTalking = false;
- } else
- Say(SOUND_PED_CHAT);
-
- } else {
-
- if (CGeneral::GetRandomNumber() < 20 && !RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_IDLE)) {
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_XPRESS_SCRATCH, 4.0f);
- }
- if (!bIsTalking && !RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_IDLE)) {
- CAnimBlendAssociation *chatAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_CHAT, 4.0f);
- float chatTime = CGeneral::GetRandomNumberInRange(0.0f, 3.0f);
- chatAssoc->SetCurrentTime(chatTime);
-
- bIsTalking = true;
- Say(SOUND_PED_CHAT);
- }
- }
- if (m_standardTimer && CTimer::GetTimeInMilliseconds() > m_standardTimer) {
- ClearChat();
- m_standardTimer = CTimer::GetTimeInMilliseconds() + 30000;
- }
-}
-
-void
-CPed::CheckAroundForPossibleCollisions(void)
-{
- CVector ourCentre, objCentre;
- CEntity *objects[8];
- int16 maxObject;
-
- if (CTimer::GetTimeInMilliseconds() <= m_nPedStateTimer)
- return;
-
- GetBoundCentre(ourCentre);
-
- CWorld::FindObjectsInRange(ourCentre, 10.0f, true, &maxObject, 6, objects, false, true, false, true, false);
- for (int i = 0; i < maxObject; i++) {
- CEntity *object = objects[i];
- if (bRunningToPhone) {
- if (gPhoneInfo.PhoneAtThisPosition(object->GetPosition()))
- break;
- }
- object->GetBoundCentre(objCentre);
- float radius = object->GetBoundRadius();
- if (radius > 4.5f || radius < 1.0f)
- radius = 1.0f;
-
- // Developers gave up calculating Z diff. later according to asm.
- float diff = CVector(ourCentre - objCentre).MagnitudeSqr2D();
-
- if (sq(radius + 1.0f) > diff)
- m_fRotationDest += DEGTORAD(22.5f);
- }
-}
-
-#ifdef PEDS_REPORT_CRIMES_ON_PHONE
-void
-ReportPhonePickUpCB(CAnimBlendAssociation* assoc, void* arg)
-{
- CPed* ped = (CPed*)arg;
- ped->m_nMoveState = PEDMOVE_STILL;
- CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_IDLE_STANCE, 8.0f);
-
- if (assoc->blendAmount > 0.5f && ped) {
- CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_PHONE_TALK, 8.0f);
- }
-}
-
-void
-ReportPhonePutDownCB(CAnimBlendAssociation* assoc, void* arg)
-{
- assoc->flags |= ASSOC_DELETEFADEDOUT;
- assoc->blendDelta = -1000.0f;
- CPed* ped = (CPed*)arg;
-
- if (ped->m_phoneId != -1 && crimeReporters[ped->m_phoneId] == ped) {
- crimeReporters[ped->m_phoneId] = nil;
- gPhoneInfo.m_aPhones[ped->m_phoneId].m_nState = PHONE_STATE_FREE;
- ped->m_phoneId = -1;
- }
-
- if (assoc->blendAmount > 0.5f)
- ped->bUpdateAnimHeading = true;
-
- ped->SetWanderPath(CGeneral::GetRandomNumber() & 7);
-}
-#endif
-
-bool
-CPed::MakePhonecall(void)
-{
-#ifdef PEDS_REPORT_CRIMES_ON_PHONE
- if (!IsPlayer() && CTimer::GetTimeInMilliseconds() > m_phoneTalkTimer - 7000 && bRunningToPhone) {
-
- FindPlayerPed()->m_pWanted->RegisterCrime_Immediately(m_crimeToReportOnPhone, GetPosition(),
- (m_crimeToReportOnPhone == CRIME_POSSESSION_GUN ? (uintptr)m_threatEntity : (uintptr)m_victimOfPlayerCrime), false);
-
- if (m_crimeToReportOnPhone != CRIME_POSSESSION_GUN)
- FindPlayerPed()->m_pWanted->SetWantedLevelNoDrop(1);
-
- bRunningToPhone = false;
- }
-#endif
- if (CTimer::GetTimeInMilliseconds() <= m_phoneTalkTimer)
- return false;
-
-#ifdef PEDS_REPORT_CRIMES_ON_PHONE
- CAnimBlendAssociation* talkAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_PHONE_TALK);
- if (talkAssoc && talkAssoc->blendAmount > 0.5f) {
- CAnimBlendAssociation* endAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_PHONE_OUT, 8.0f);
- endAssoc->flags &= ~ASSOC_DELETEFADEDOUT;
- endAssoc->SetFinishCallback(ReportPhonePutDownCB, this);
- }
-#endif
- SetIdle();
-
- gPhoneInfo.m_aPhones[m_phoneId].m_nState = PHONE_STATE_FREE;
-#ifndef PEDS_REPORT_CRIMES_ON_PHONE
- m_phoneId = -1;
-#endif
-
- // Because SetWanderPath is now done async in ReportPhonePutDownCB
-#ifdef PEDS_REPORT_CRIMES_ON_PHONE
- return false;
-#else
- return true;
-#endif
-}
-
-bool
-CPed::FacePhone(void)
-{
- // This function was broken since it's left unused early in development.
-#ifdef PEDS_REPORT_CRIMES_ON_PHONE
- float phoneDir = CGeneral::GetRadianAngleBetweenPoints(
- gPhoneInfo.m_aPhones[m_phoneId].m_vecPos.x, gPhoneInfo.m_aPhones[m_phoneId].m_vecPos.y,
- GetPosition().x, GetPosition().y);
-
- if (m_facePhoneStart) {
- m_lookTimer = 0;
- SetLookFlag(phoneDir, true);
- m_lookTimer = CTimer::GetTimeInMilliseconds() + 3000;
- m_facePhoneStart = false;
- }
-
- if (bIsLooking && TurnBody()) {
- ClearLookFlag();
- SetIdle();
- m_phoneTalkTimer = CTimer::GetTimeInMilliseconds() + 10000;
- CAnimBlendAssociation* assoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_PHONE_IN, 4.0f);
- assoc->SetFinishCallback(ReportPhonePickUpCB, this);
- return true;
- }
-
- return false;
-#else
- float currentRot = RADTODEG(m_fRotationCur);
- float phoneDir = CGeneral::GetRadianAngleBetweenPoints(
- gPhoneInfo.m_aPhones[m_phoneId].m_vecPos.x,
- gPhoneInfo.m_aPhones[m_phoneId].m_vecPos.y,
- GetPosition().x,
- GetPosition().y);
-
- SetLookFlag(phoneDir, false);
- phoneDir = CGeneral::LimitAngle(phoneDir);
- m_moved = CVector2D(0.0f, 0.0f);
- if (currentRot - 180.0f > phoneDir)
- phoneDir += 2 * 180.0f;
- else if (180.0f + currentRot < phoneDir)
- phoneDir -= 2 * 180.0f;
-
- float neededTurn = currentRot - phoneDir;
-
- if (Abs(neededTurn) <= 0.75f) {
- SetIdle();
- ClearLookFlag();
- m_phoneTalkTimer = CTimer::GetTimeInMilliseconds() + 10000;
- return true;
- } else {
- m_fRotationCur = DEGTORAD(currentRot - neededTurn * 0.2f);
- return false;
- }
-#endif
-}
-
-CPed *
-CPed::CheckForDeadPeds(void)
-{
- int event;
- if (CEventList::FindClosestEvent(EVENT_DEAD_PED, GetPosition(), &event)) {
- int pedHandle = gaEvent[event].entityRef;
- if (pedHandle && gaEvent[event].entityType == EVENT_ENTITY_PED) {
- bGonnaInvestigateEvent = true;
- return CPools::GetPed(pedHandle);
- }
- }
- bGonnaInvestigateEvent = false;
- return nil;
-}
-
-#ifdef PEDS_REPORT_CRIMES_ON_PHONE
-// returns event id, parameter is optional
-int32
-CPed::CheckForPlayerCrimes(CPed *victim)
-{
- int i;
- float dist;
- float mindist = 60.0f;
- CPlayerPed *player = FindPlayerPed();
- int32 victimRef = (victim ? CPools::GetPedRef(victim) : 0);
- int event = -1;
-
- for (i = 0; i < NUMEVENTS; i++) {
- if (gaEvent[i].type == EVENT_NULL || gaEvent[i].type > EVENT_CAR_SET_ON_FIRE)
- continue;
-
- // those are already handled in game, also DEAD_PED isn't registered alone, most of the time there is SHOOT_PED etc.
- if (gaEvent[i].type == EVENT_DEAD_PED || gaEvent[i].type == EVENT_GUNSHOT || gaEvent[i].type == EVENT_EXPLOSION)
- continue;
-
- if (victim && gaEvent[i].entityRef != victimRef)
- continue;
-
- if (gaEvent[i].criminal != player)
- continue;
-
- dist = (GetPosition() - gaEvent[i].posn).Magnitude();
- if (dist < mindist) {
- mindist = dist;
- event = i;
+ ClearAimFlag();
+ ClearLookFlag();
}
- }
- if (event != -1) {
- if (victim) {
- m_victimOfPlayerCrime = victim;
- } else {
- switch (gaEvent[event].entityType) {
- case EVENT_ENTITY_PED:
- m_victimOfPlayerCrime = CPools::GetPed(gaEvent[event].entityRef);
- break;
- case EVENT_ENTITY_VEHICLE:
- m_victimOfPlayerCrime = CPools::GetVehicle(gaEvent[event].entityRef);
- break;
- case EVENT_ENTITY_OBJECT:
- m_victimOfPlayerCrime = CPools::GetObject(gaEvent[event].entityRef);
- break;
- default:
+ switch (m_nMoveState) {
+ case PEDMOVE_STILL:
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), animGroupToUse, ANIM_IDLE_STANCE, 4.0f);
break;
- }
- }
- }
-
- return event;
-}
-#endif
-
-bool
-CPed::CheckForExplosions(CVector2D &area)
-{
- int event = 0;
- if (CEventList::FindClosestEvent(EVENT_EXPLOSION, GetPosition(), &event)) {
- area.x = gaEvent[event].posn.x;
- area.y = gaEvent[event].posn.y;
- CEntity *actualEntity = nil;
-
- switch (gaEvent[event].entityType) {
- case EVENT_ENTITY_PED:
- actualEntity = CPools::GetPed(gaEvent[event].entityRef);
+ case PEDMOVE_WALK:
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), animGroupToUse, ANIM_WALK, 1.0f);
break;
- case EVENT_ENTITY_VEHICLE:
- actualEntity = CPools::GetVehicle(gaEvent[event].entityRef);
+ case PEDMOVE_RUN:
+ if (m_nPedState == PED_FLEE_ENTITY) {
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), animGroupToUse, ANIM_RUN, 3.0f);
+ } else {
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), animGroupToUse, ANIM_RUN, 1.0f);
+ }
break;
- case EVENT_ENTITY_OBJECT:
- actualEntity = CPools::GetObject(gaEvent[event].entityRef);
+ case PEDMOVE_SPRINT:
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), animGroupToUse, ANIM_SPRINT, 1.0f);
break;
default:
break;
}
- if (actualEntity) {
- m_pEventEntity = actualEntity;
- m_pEventEntity->RegisterReference((CEntity **) &m_pEventEntity);
- bGonnaInvestigateEvent = true;
- } else
- bGonnaInvestigateEvent = false;
-
- CEventList::ClearEvent(event);
- return true;
- } else if (CEventList::FindClosestEvent(EVENT_FIRE, GetPosition(), &event)) {
- area.x = gaEvent[event].posn.x;
- area.y = gaEvent[event].posn.y;
- CEventList::ClearEvent(event);
- bGonnaInvestigateEvent = false;
- return true;
- }
-
- bGonnaInvestigateEvent = false;
- return false;
-}
-
-CPed *
-CPed::CheckForGunShots(void)
-{
- int event;
- if (CEventList::FindClosestEvent(EVENT_GUNSHOT, GetPosition(), &event)) {
- if (gaEvent[event].entityType == EVENT_ENTITY_PED) {
- // Probably due to we don't want peds to go gunshot area? (same on VC)
- bGonnaInvestigateEvent = false;
- return CPools::GetPed(gaEvent[event].entityRef);
- }
- }
- bGonnaInvestigateEvent = false;
- return nil;
-}
-
-PointBlankNecessity
-CPed::CheckForPointBlankPeds(CPed *pedToVerify)
-{
- float pbDistance = 1.1f;
- if (GetWeapon()->IsType2Handed())
- pbDistance = 1.6f;
-
- for (int i = 0; i < m_numNearPeds; i++) {
- CPed *nearPed = m_nearPeds[i];
-
- if (!pedToVerify || pedToVerify == nearPed) {
-
- CVector diff = nearPed->GetPosition() - GetPosition();
- if (diff.Magnitude() < pbDistance) {
-
- float neededAngle = CGeneral::GetRadianAngleBetweenPoints(
- nearPed->GetPosition().x, nearPed->GetPosition().y,
- GetPosition().x, GetPosition().y);
- neededAngle = CGeneral::LimitRadianAngle(neededAngle);
- m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur);
-
- float neededTurn = Abs(neededAngle - m_fRotationCur);
-
- if (neededTurn > PI)
- neededTurn = 2*PI - neededTurn;
+ if (animAssoc) {
+ if (m_leader) {
+ CAnimBlendAssociation *walkAssoc = RpAnimBlendClumpGetAssociation(m_leader->GetClump(), ANIM_WALK);
+ if (!walkAssoc)
+ walkAssoc = RpAnimBlendClumpGetAssociation(m_leader->GetClump(), ANIM_RUN);
- if (nearPed->OnGroundOrGettingUp() || nearPed->m_nPedState == PED_DIVE_AWAY)
- return NO_POINT_BLANK_PED;
+ if (!walkAssoc)
+ walkAssoc = RpAnimBlendClumpGetAssociation(m_leader->GetClump(), ANIM_SPRINT);
- if (neededTurn < CAN_SEE_ENTITY_ANGLE_THRESHOLD) {
- if (pedToVerify == nearPed)
- return POINT_BLANK_FOR_WANTED_PED;
+ if (walkAssoc) {
+ animAssoc->speed = walkAssoc->speed;
+ } else {
+ if (CharCreatedBy == MISSION_CHAR)
+ animAssoc->speed = 1.0f;
else
- return POINT_BLANK_FOR_SOMEONE_ELSE;
+ animAssoc->speed = 1.2f - m_randomSeed * 0.4f / MYRAND_MAX;
+
}
+ } else {
+ if (CharCreatedBy == MISSION_CHAR)
+ animAssoc->speed = 1.0f;
+ else
+ animAssoc->speed = 1.2f - m_randomSeed * 0.4f / MYRAND_MAX;
}
}
}
- return NO_POINT_BLANK_PED;
-}
-
-bool
-CPed::CheckIfInTheAir(void)
-{
- if (bInVehicle)
- return false;
-
- CVector pos = GetPosition();
- CColPoint foundColPoint;
- CEntity *foundEntity;
-
- float startZ = pos.z - 1.54f;
- bool foundGround = CWorld::ProcessVerticalLine(pos, startZ, foundColPoint, foundEntity, true, true, false, true, false, false, nil);
- if (!foundGround && m_nPedState != PED_JUMP)
- {
- pos.z -= FEET_OFFSET;
- if (CWorld::TestSphereAgainstWorld(pos, 0.15f, this, true, false, false, false, false, false))
- foundGround = true;
- }
- return !foundGround;
-}
-
-void
-CPed::ClearAll(void)
-{
- if (!IsPedInControl() && m_nPedState != PED_DEAD)
- return;
-
- m_nPedState = PED_NONE;
- m_nMoveState = PEDMOVE_NONE;
- m_pSeekTarget = nil;
- m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f);
- m_fleeFromPosX = 0.0f;
- m_fleeFromPosY = 0.0f;
- m_fleeFrom = nil;
- m_fleeTimer = 0;
- bUsesCollision = true;
-#ifdef VC_PED_PORTS
- ClearPointGunAt();
-#else
- ClearAimFlag();
- ClearLookFlag();
-#endif
- bIsPointingGunAt = false;
- bRenderPedInCar = true;
- bKnockedUpIntoAir = false;
- m_pCollidingEntity = nil;
}
void
-CPed::ClearAttack(void)
-{
- if (m_nPedState != PED_ATTACK || bIsDucking || m_nWaitState == WAITSTATE_PLAYANIM_DUCK)
- return;
-
-#ifdef VC_PED_PORTS
- // VC uses CCamera::Using1stPersonWeaponMode
- if (FindPlayerPed() == this && (TheCamera.PlayerWeaponMode.Mode == CCam::MODE_SNIPER ||
- TheCamera.PlayerWeaponMode.Mode == CCam::MODE_M16_1STPERSON || TheCamera.PlayerWeaponMode.Mode == CCam::MODE_ROCKETLAUNCHER)) {
- SetPointGunAt(nil);
- } else
-#endif
- if (bIsPointingGunAt) {
- if (m_pLookTarget)
- SetPointGunAt(m_pLookTarget);
- else
- ClearPointGunAt();
- } else if (m_objective != OBJECTIVE_NONE) {
- SetIdle();
- } else {
- RestorePreviousState();
- }
-}
-
-void
-CPed::ClearAttackByRemovingAnim(void)
+CPed::StopNonPartialAnims(void)
{
- if (m_nPedState != PED_ATTACK || bIsDucking)
- return;
-
- CWeaponInfo *weapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
- CAnimBlendAssociation *weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), weapon->m_AnimToPlay);
- if (!weaponAssoc) {
- weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), weapon->m_Anim2ToPlay);
-
- if (!weaponAssoc && weapon->m_bThrow)
- weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_THROWU);
+ CAnimBlendAssociation *assoc;
- if (!weaponAssoc) {
- ClearAttack();
- return;
- }
+ for (assoc = RpAnimBlendClumpGetFirstAssociation(GetClump()); assoc; assoc = RpAnimBlendGetNextAssociation(assoc)) {
+ if (!assoc->IsPartial())
+ assoc->flags &= ~ASSOC_RUNNING;
}
- weaponAssoc->blendDelta = -8.0f;
- weaponAssoc->flags &= ~ASSOC_RUNNING;
- weaponAssoc->flags |= ASSOC_DELETEFADEDOUT;
- weaponAssoc->SetDeleteCallback(FinishedAttackCB, this);
}
void
-CPed::StopNonPartialAnims(void)
+CPed::RestartNonPartialAnims(void)
{
CAnimBlendAssociation *assoc;
for (assoc = RpAnimBlendClumpGetFirstAssociation(GetClump()); assoc; assoc = RpAnimBlendGetNextAssociation(assoc)) {
if (!assoc->IsPartial())
- assoc->flags &= ~ASSOC_RUNNING;
+ assoc->SetRun();
}
}
@@ -3498,775 +632,6 @@ CPed::SetStoredState(void)
}
void
-CPed::SetDie(AnimationId animId, float delta, float speed)
-{
- CPlayerPed *player = FindPlayerPed();
- if (player == this) {
- if (!player->m_bCanBeDamaged)
- return;
- }
-
- m_threatEntity = nil;
- if (DyingOrDead())
- return;
-
- if (m_nPedState == PED_FALL || m_nPedState == PED_GETUP)
- delta *= 0.5f;
-
- SetStoredState();
- ClearAll();
- m_fHealth = 0.0f;
- if (m_nPedState == PED_DRIVING) {
- if (!IsPlayer())
- FlagToDestroyWhenNextProcessed();
- } else if (bInVehicle) {
- if (m_pVehicleAnim)
- m_pVehicleAnim->blendDelta = -1000.0f;
- } else if (EnteringCar()) {
- QuitEnteringCar();
- }
-
- m_nPedState = PED_DIE;
- if (animId == NUM_ANIMS) {
- bIsPedDieAnimPlaying = false;
- } else {
- CAnimBlendAssociation *dieAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animId, delta);
- if (speed > 0.0f)
- dieAssoc->speed = speed;
-
- dieAssoc->flags &= ~ASSOC_FADEOUTWHENDONE;
- if (dieAssoc->IsRunning()) {
- dieAssoc->SetFinishCallback(FinishDieAnimCB, this);
- bIsPedDieAnimPlaying = true;
- }
- }
-
- Say(SOUND_PED_DEATH);
- if (m_nLastPedState == PED_ENTER_CAR || m_nLastPedState == PED_CARJACK)
- QuitEnteringCar();
- if (!bInVehicle)
- StopNonPartialAnims();
-
- m_bloodyFootprintCountOrDeathTime = CTimer::GetTimeInMilliseconds();
-}
-
-bool
-CPed::InflictDamage(CEntity *damagedBy, eWeaponType method, float damage, ePedPieceTypes pedPiece, uint8 direction)
-{
- CPlayerPed *player = FindPlayerPed();
- float dieDelta = 4.0f;
- float dieSpeed = 0.0f;
- AnimationId dieAnim = ANIM_KO_SHOT_FRONT1;
- bool headShot = false;
- bool willLinger = false;
- int random;
-
- if (player == this) {
- if (!player->m_bCanBeDamaged)
- return false;
-
- player->AnnoyPlayerPed(false);
- }
-
- if (DyingOrDead())
- return false;
-
- if (!bUsesCollision && method != WEAPONTYPE_DROWNING)
- return false;
-
- if (bOnlyDamagedByPlayer && damagedBy != player && damagedBy != FindPlayerVehicle() &&
- method != WEAPONTYPE_DROWNING && method != WEAPONTYPE_EXPLOSION)
- return false;
-
- float healthImpact;
- if (IsPlayer())
- healthImpact = damage * 0.33f;
- else
- healthImpact = damage * m_pedStats->m_defendWeakness;
-
- bool detectDieAnim = true;
- if (m_nPedState == PED_FALL || m_nPedState == PED_GETUP) {
- if (!IsPedHeadAbovePos(-0.3f)) {
- if (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL))
- dieAnim = ANIM_FLOOR_HIT_F;
- else
- dieAnim = ANIM_FLOOR_HIT;
- dieDelta *= 2.0f;
- dieSpeed = 0.5f;
- detectDieAnim = false;
- } else if (m_nPedState == PED_FALL) {
- dieAnim = NUM_ANIMS;
- detectDieAnim = false;
- }
- }
- if (detectDieAnim) {
- switch (method) {
- case WEAPONTYPE_UNARMED:
- if (bMeleeProof)
- return false;
-
- if (m_nPedState == PED_FALL) {
- if (IsPedHeadAbovePos(-0.3f)) {
- dieAnim = NUM_ANIMS;
- } else {
- if (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL))
- dieAnim = ANIM_FLOOR_HIT_F;
- else
- dieAnim = ANIM_FLOOR_HIT;
- dieDelta = dieDelta * 2.0f;
- dieSpeed = 0.5f;
- }
- } else {
- switch (direction) {
- case 0:
- dieAnim = ANIM_KO_SKID_FRONT;
- break;
- case 1:
- dieAnim = ANIM_KO_SPIN_R;
- break;
- case 2:
- dieAnim = ANIM_KO_SKID_BACK;
- break;
- case 3:
- dieAnim = ANIM_KO_SPIN_L;
- break;
- default:
- break;
- }
- }
- break;
- case WEAPONTYPE_BASEBALLBAT:
- if (bMeleeProof)
- return false;
-
- if (m_nPedState == PED_FALL) {
- if (IsPedHeadAbovePos(-0.3f)) {
- dieAnim = NUM_ANIMS;
- } else {
- if (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL))
- dieAnim = ANIM_FLOOR_HIT_F;
- else
- dieAnim = ANIM_FLOOR_HIT;
- dieDelta = dieDelta * 2.0f;
- dieSpeed = 0.5f;
- }
- } else {
- switch (direction) {
- case 0:
- dieAnim = ANIM_KO_SKID_FRONT;
- break;
- case 1:
- dieAnim = ANIM_KO_SPIN_R;
- break;
- case 2:
- dieAnim = ANIM_KO_SKID_BACK;
- break;
- case 3:
- dieAnim = ANIM_KO_SPIN_L;
- break;
- default:
- break;
- }
- }
- break;
- case WEAPONTYPE_COLT45:
- case WEAPONTYPE_UZI:
- case WEAPONTYPE_SHOTGUN:
- case WEAPONTYPE_AK47:
- case WEAPONTYPE_M16:
- case WEAPONTYPE_SNIPERRIFLE:
- if (bBulletProof)
- return false;
-
- bool dontRemoveLimb;
- if (IsPlayer() || bNoCriticalHits)
- dontRemoveLimb = true;
- else {
- switch (method) {
- case WEAPONTYPE_SNIPERRIFLE:
- dontRemoveLimb = false;
- break;
- case WEAPONTYPE_M16:
- dontRemoveLimb = false;
- break;
- case WEAPONTYPE_SHOTGUN:
- dontRemoveLimb = CGeneral::GetRandomNumber() & 7;
- break;
- default:
- dontRemoveLimb = CGeneral::GetRandomNumber() & 15;
- break;
- }
- }
-
- if (dontRemoveLimb) {
- if (method == WEAPONTYPE_SHOTGUN) {
- switch (direction) {
- case 0:
- dieAnim = ANIM_KO_SKID_FRONT;
- break;
- case 1:
- dieAnim = ANIM_KO_SPIN_R;
- break;
- case 2:
- dieAnim = ANIM_KO_SKID_BACK;
- break;
- case 3:
- dieAnim = ANIM_KO_SPIN_L;
- break;
- default:
- break;
- }
- } else
- dieAnim = ANIM_KO_SHOT_FRONT1;
-
- willLinger = false;
- } else {
- switch (pedPiece) {
- case PEDPIECE_TORSO:
- willLinger = false;
- dieAnim = ANIM_KO_SHOT_FRONT1;
- break;
- case PEDPIECE_MID:
- willLinger = false;
- dieAnim = ANIM_KO_SHOT_STOM;
- break;
- case PEDPIECE_LEFTARM:
- dieAnim = ANIM_KO_SHOT_ARML;
- RemoveBodyPart(PED_UPPERARML, direction);
- willLinger = true;
- break;
- case PEDPIECE_RIGHTARM:
- dieAnim = ANIM_KO_SHOT_ARMR;
- RemoveBodyPart(PED_UPPERARMR, direction);
- willLinger = true;
- break;
- case PEDPIECE_LEFTLEG:
- dieAnim = ANIM_KO_SHOT_LEGL;
- RemoveBodyPart(PED_UPPERLEGL, direction);
- willLinger = true;
- break;
- case PEDPIECE_RIGHTLEG:
- dieAnim = ANIM_KO_SHOT_LEGR;
- RemoveBodyPart(PED_UPPERLEGR, direction);
- willLinger = true;
- break;
- case PEDPIECE_HEAD:
- dieAnim = ANIM_KO_SHOT_FACE;
- RemoveBodyPart(PED_HEAD, direction);
- headShot = true;
- willLinger = true;
- break;
- default:
- break;
- }
- }
- break;
- case WEAPONTYPE_ROCKETLAUNCHER:
- case WEAPONTYPE_GRENADE:
- case WEAPONTYPE_EXPLOSION:
- if (bExplosionProof)
- return false;
-
- if (CGame::nastyGame && !IsPlayer() && !bInVehicle &&
- 1.0f + healthImpact > m_fArmour + m_fHealth) {
-
- random = CGeneral::GetRandomNumber();
- if (random & 1)
- RemoveBodyPart(PED_UPPERARML, direction);
- if (random & 2)
- RemoveBodyPart(PED_UPPERLEGR, direction);
- if (random & 4)
- RemoveBodyPart(PED_HEAD, direction);
- if (random & 8)
- RemoveBodyPart(PED_UPPERARMR, direction);
- if (random & 0x10)
- RemoveBodyPart(PED_UPPERLEGL, direction);
- if (bBodyPartJustCameOff)
- willLinger = true;
- }
- // fall through
- case WEAPONTYPE_MOLOTOV:
- if (bExplosionProof)
- return false;
-
- switch (direction) {
- case 0:
- dieAnim = ANIM_KO_SKID_FRONT;
- break;
- case 1:
- dieAnim = ANIM_KO_SPIN_R;
- break;
- case 2:
- dieAnim = ANIM_KO_SKID_BACK;
- break;
- case 3:
- dieAnim = ANIM_KO_SPIN_L;
- break;
- default:
- break;
- }
- break;
- case WEAPONTYPE_FLAMETHROWER:
- if (bFireProof)
- return false;
-
- dieAnim = ANIM_KO_SHOT_FRONT1;
- break;
- case WEAPONTYPE_RAMMEDBYCAR:
- case WEAPONTYPE_RUNOVERBYCAR:
- if (bCollisionProof)
- return false;
-
- random = CGeneral::GetRandomNumber() & 3;
- switch (random) {
- case 0:
- if ((pedPiece != PEDPIECE_LEFTARM || random <= 1)
- && (pedPiece != PEDPIECE_MID || random != 1)) {
- if (pedPiece == PEDPIECE_RIGHTARM && random > 1
- || pedPiece == PEDPIECE_MID && random == 2)
-
- dieAnim = ANIM_KO_SPIN_L;
- else
- dieAnim = ANIM_KO_SKID_FRONT;
- } else
- dieAnim = ANIM_KO_SPIN_R;
-
- break;
- case 1:
- if (m_nPedState == PED_DIVE_AWAY)
- dieAnim = ANIM_KD_LEFT;
- else
- dieAnim = ANIM_KO_SPIN_R;
- break;
- case 2:
- if ((pedPiece != PEDPIECE_LEFTARM || random <= 1)
- && (pedPiece != PEDPIECE_MID || random != 1)) {
- if ((pedPiece != PEDPIECE_RIGHTARM || random <= 1)
- && (pedPiece != PEDPIECE_MID || random != 2)) {
- dieAnim = ANIM_KO_SKID_BACK;
- } else {
- dieAnim = ANIM_KD_RIGHT;
- }
- } else
- dieAnim = ANIM_KD_LEFT;
- break;
- case 3:
- if (m_nPedState == PED_DIVE_AWAY)
- dieAnim = ANIM_KD_RIGHT;
- else
- dieAnim = ANIM_KO_SPIN_L;
- break;
- default:
- break;
- }
- if (damagedBy) {
- CVehicle *vehicle = (CVehicle*)damagedBy;
- if (method == WEAPONTYPE_RAMMEDBYCAR) {
- float vehSpeed = vehicle->m_vecMoveSpeed.Magnitude();
- dieDelta = 8.0f * vehSpeed + 4.0f;
- } else {
- float vehSpeed = vehicle->m_vecMoveSpeed.Magnitude();
- dieDelta = 12.0f * vehSpeed + 4.0f;
- dieSpeed = 16.0f * vehSpeed + 1.0f;
- }
- }
- break;
- case WEAPONTYPE_DROWNING:
- dieAnim = ANIM_DROWN;
- break;
- case WEAPONTYPE_FALL:
- if (bCollisionProof)
- return false;
-
- switch (direction) {
- case 0:
- dieAnim = ANIM_KO_SKID_FRONT;
- break;
- case 1:
- dieAnim = ANIM_KO_SPIN_R;
- break;
- case 2:
- dieAnim = ANIM_KO_SKID_BACK;
- break;
- case 3:
- dieAnim = ANIM_KO_SPIN_L;
- break;
- default:
- break;
- }
- break;
- default:
- break;
- }
- }
-
- if (m_fArmour != 0.0f && method != WEAPONTYPE_DROWNING) {
- if (player == this)
- CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastArmourLoss = CTimer::GetTimeInMilliseconds();
-
- if (healthImpact < m_fArmour) {
- m_fArmour = m_fArmour - healthImpact;
- healthImpact = 0.0f;
- } else {
- healthImpact = healthImpact - m_fArmour;
- m_fArmour = 0.0f;
- }
- }
-
- if (healthImpact != 0.0f) {
- if (player == this)
- CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastHealthLoss = CTimer::GetTimeInMilliseconds();
-
- m_lastWepDam = method;
- }
-
- if (m_fHealth - healthImpact >= 1.0f && !willLinger) {
- m_fHealth -= healthImpact;
- return false;
- }
-
- if (bInVehicle) {
- if (method != WEAPONTYPE_DROWNING) {
-#ifdef VC_PED_PORTS
- if (m_pMyVehicle) {
- if (m_pMyVehicle->IsCar() && m_pMyVehicle->pDriver == this) {
- if (m_pMyVehicle->GetStatus() == STATUS_SIMPLE) {
- m_pMyVehicle->SetStatus(STATUS_PHYSICS);
- CCarCtrl::SwitchVehicleToRealPhysics(m_pMyVehicle);
- }
- m_pMyVehicle->AutoPilot.m_nCarMission = MISSION_NONE;
- m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0;
- m_pMyVehicle->AutoPilot.m_nTempAction = TEMPACT_HANDBRAKESTRAIGHT;
- m_pMyVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 2000;
- }
- if (m_pMyVehicle->CanPedExitCar()) {
- SetObjective(OBJECTIVE_LEAVE_CAR_AND_DIE, m_pMyVehicle);
- } else {
- m_fHealth = 0.0f;
- if (m_pMyVehicle && m_pMyVehicle->pDriver == this) {
- SetRadioStation();
- m_pMyVehicle->SetStatus(STATUS_ABANDONED);
- }
- SetDie(dieAnim, dieDelta, dieSpeed);
- /*
- if (damagedBy == FindPlayerPed() && damagedBy != this) {
- // PlayerInfo stuff
- }
- */
- }
- for (int i = 0; i < ARRAY_SIZE(m_pMyVehicle->pPassengers); i++) {
- CPed* passenger = m_pMyVehicle->pPassengers[i];
- if (passenger && passenger != this && damagedBy)
- passenger->ReactToAttack(damagedBy);
- }
-
- CPed *driverOfVeh = m_pMyVehicle->pDriver;
- if (driverOfVeh && driverOfVeh != this && damagedBy)
- driverOfVeh->ReactToAttack(damagedBy);
-
- if (damagedBy == FindPlayerPed() || damagedBy && damagedBy == FindPlayerVehicle()) {
- CDarkel::RegisterKillByPlayer(this, method, headShot);
- m_threatEntity = FindPlayerPed();
- } else {
- CDarkel::RegisterKillNotByPlayer(this, method);
- }
- }
-#endif
- m_fHealth = 1.0f;
- return false;
- }
- m_fHealth = 0.0f;
- if (player == this)
- m_pMyVehicle->SetStatus(STATUS_PLAYER_DISABLED);
-
- SetDie(NUM_ANIMS, 4.0f, 0.0f);
- return true;
- } else {
- m_fHealth = 0.0f;
- SetDie(dieAnim, dieDelta, dieSpeed);
-
- if (damagedBy == player || damagedBy && damagedBy == FindPlayerVehicle()) {
-
- // There are PlayerInfo stuff here in VC
- CDarkel::RegisterKillByPlayer(this, method, headShot);
- m_threatEntity = player;
- } else {
- CDarkel::RegisterKillNotByPlayer(this, method);
- }
- if (method == WEAPONTYPE_DROWNING)
- bIsInTheAir = false;
-
- return true;
- }
-}
-
-void
-CPed::ClearFlee(void)
-{
- RestorePreviousState();
- bUsePedNodeSeek = false;
- m_standardTimer = 0;
- m_fleeTimer = 0;
-}
-
-void
-CPed::ClearFall(void)
-{
- SetGetUp();
-}
-
-void
-CPed::SetGetUp(void)
-{
- if (m_nPedState == PED_GETUP && bGetUpAnimStarted)
- return;
-
- if (!CanSetPedState())
- return;
-
- if (m_fHealth >= 1.0f || IsPedHeadAbovePos(-0.3f)) {
- if (bUpdateAnimHeading) {
- m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur);
- m_fRotationCur -= HALFPI;
- bUpdateAnimHeading = false;
- }
- if (m_nPedState != PED_GETUP) {
- SetStoredState();
- m_nPedState = PED_GETUP;
- }
-
- CVehicle *collidingVeh = (CVehicle*)m_pCollidingEntity;
- CVehicle *veh = (CVehicle*)CPedPlacement::IsPositionClearOfCars(&GetPosition());
- if (veh && veh->m_vehType != VEHICLE_TYPE_BIKE ||
- collidingVeh && collidingVeh->IsVehicle() && collidingVeh->m_vehType != VEHICLE_TYPE_BIKE
- && ((uint8)(CTimer::GetFrameCounter() + m_randomSeed + 5) % 8 ||
- CCollision::ProcessColModels(GetMatrix(), *GetColModel(), collidingVeh->GetMatrix(), *collidingVeh->GetColModel(),
- aTempPedColPts, nil, nil) > 0)) {
-
- bGetUpAnimStarted = false;
- if (IsPlayer())
- InflictDamage(nil, WEAPONTYPE_RUNOVERBYCAR, CTimer::GetTimeStep(), PEDPIECE_TORSO, 0);
- else {
- if (!CPad::GetPad(0)->ArePlayerControlsDisabled())
- return;
-
- InflictDamage(nil, WEAPONTYPE_RUNOVERBYCAR, 1000.0f, PEDPIECE_TORSO, 0);
- }
- return;
- }
- bGetUpAnimStarted = true;
- m_pCollidingEntity = nil;
- bKnockedUpIntoAir = false;
- CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_SPRINT);
- if (animAssoc) {
- if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN)) {
- CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_RUN, 8.0f);
- } else {
- CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 8.0f);
- }
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- }
-
- if (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL))
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_GETUP_FRONT, 1000.0f);
- else
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_GETUP1, 1000.0f);
-
- animAssoc->SetFinishCallback(PedGetupCB,this);
- } else {
- m_fHealth = 0.0f;
- SetDie(NUM_ANIMS, 4.0f, 0.0f);
- }
-}
-
-void
-CPed::ClearInvestigateEvent(void)
-{
- CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_ROAD_CROSS);
- if (!animAssoc)
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_XPRESS_SCRATCH);
- if (!animAssoc)
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_HBHB);
- if (!animAssoc)
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_CHAT);
- if (animAssoc) {
- animAssoc->blendDelta = -8.0f;
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- }
- if (m_eventType > EVENT_EXPLOSION)
- m_standardTimer = CTimer::GetTimeInMilliseconds() + 15000;
-
- bGonnaInvestigateEvent = false;
- m_pEventEntity = nil;
- ClearLookFlag();
- RestorePreviousState();
- if(m_nMoveState == PEDMOVE_NONE || m_nMoveState == PEDMOVE_STILL)
- SetMoveState(PEDMOVE_WALK);
-}
-
-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::ClearLook(void)
-{
- RestorePreviousState();
- ClearLookFlag();
-}
-
-void
-CPed::ClearObjective(void)
-{
- if (IsPedInControl() || m_nPedState == PED_DRIVING) {
- m_objective = OBJECTIVE_NONE;
-#ifdef VC_PED_PORTS
- m_pedInObjective = nil;
- m_carInObjective = nil;
-#endif
- if (m_nPedState == PED_DRIVING && m_pMyVehicle) {
-
- if (m_pMyVehicle->pDriver != this) {
-#if defined VC_PED_PORTS || defined FIX_BUGS
- if(!IsPlayer())
-#endif
- bWanderPathAfterExitingCar = true;
-
- SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);
- }
-#ifdef VC_PED_PORTS
- m_nLastPedState = PED_NONE;
-#endif
- } else {
- SetIdle();
- SetMoveState(PEDMOVE_STILL);
- }
- } else {
- bClearObjective = true;
- }
-}
-
-void
-CPed::ClearPause(void)
-{
- RestorePreviousState();
-}
-
-void
-CPed::ClearSeek(void)
-{
- SetIdle();
- bRunningToPhone = false;
-}
-
-bool
-CPed::SetWanderPath(int8 pathStateDest)
-{
- uint8 nextPathState;
-
- if (IsPedInControl()) {
- if (bKindaStayInSamePlace) {
- SetIdle();
- return false;
- } else {
- m_nPathDir = pathStateDest;
- if (pathStateDest == 0)
- pathStateDest = CGeneral::GetRandomNumberInRange(1, 7);
-
- ThePaths.FindNextNodeWandering(PATH_PED, GetPosition(), &m_pLastPathNode, &m_pNextPathNode,
- m_nPathDir, &nextPathState);
-
- // Circular loop until we find a node for current m_nPathDir
- while (!m_pNextPathNode) {
- m_nPathDir = (m_nPathDir+1) % 8;
-
- // We're at where we started and couldn't find any node
- if (m_nPathDir == pathStateDest) {
- ClearAll();
- SetIdle();
- return false;
- }
- ThePaths.FindNextNodeWandering(PATH_PED, GetPosition(), &m_pLastPathNode, &m_pNextPathNode,
- m_nPathDir, &nextPathState);
- }
-
- // We did it, save next path state and return true
- m_nPathDir = nextPathState;
- m_nPedState = PED_WANDER_PATH;
- SetMoveState(PEDMOVE_WALK);
- bIsRunning = false;
- return true;
- }
- } else {
- m_nPathDir = pathStateDest;
- bStartWanderPathOnFoot = true;
- return false;
- }
-}
-
-void
-CPed::ClearWeapons(void)
-{
- CWeaponInfo *currentWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
- RemoveWeaponModel(currentWeapon->m_nModelId);
-
- m_maxWeaponTypeAllowed = WEAPONTYPE_BASEBALLBAT;
- m_currentWeapon = WEAPONTYPE_UNARMED;
-
- currentWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
- AddWeaponModel(currentWeapon->m_nModelId);
- for(int i = 0; i < WEAPONTYPE_TOTAL_INVENTORY_WEAPONS; i++) {
- CWeapon &weapon = GetWeapon(i);
- weapon.m_eWeaponType = WEAPONTYPE_UNARMED;
- weapon.m_eWeaponState = WEAPONSTATE_READY;
- weapon.m_nAmmoInClip = 0;
- weapon.m_nAmmoTotal = 0;
- weapon.m_nTimer = 0;
- }
-}
-
-void
-CPed::RestoreGunPosition(void)
-{
- if (bIsLooking) {
- m_pedIK.m_flags &= ~CPedIK::LOOKAROUND_HEAD_ONLY;
- bIsRestoringGun = false;
- } else if (m_pedIK.RestoreGunPosn()) {
- bIsRestoringGun = false;
- } else {
- if (IsPlayer())
- ((CPlayerPed*)this)->m_fFPSMoveHeading = 0.0f;
- }
-}
-
-void
-CPed::RestoreHeadingRate(void)
-{
- m_headingRate = m_pedStats->m_headingChangeRate;
-}
-
-void
-CPed::RestoreHeadingRateCB(CAnimBlendAssociation *assoc, void *arg)
-{
- ((CPed*)arg)->m_headingRate = ((CPed*)arg)->m_pedStats->m_headingChangeRate;
-}
-
-void
CPed::RestorePreviousState(void)
{
if(!CanSetPedState() || m_nPedState == PED_FALL)
@@ -4315,4776 +680,1007 @@ CPed::RestorePreviousState(void)
}
}
-void
-CPed::SetAimFlag(CEntity *to)
-{
- bIsAimingGun = true;
- bIsRestoringGun = false;
- m_pLookTarget = to;
- m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);
- m_pSeekTarget = to;
- m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget);
- m_lookTimer = 0;
-}
-
-void
-CPed::SetAimFlag(float angle)
-{
- bIsAimingGun = true;
- bIsRestoringGun = false;
- m_fLookDirection = angle;
- m_lookTimer = 0;
- m_pLookTarget = nil;
- m_pSeekTarget = nil;
- if (CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_bCanAimWithArm)
- m_pedIK.m_flags |= CPedIK::AIMS_WITH_ARM;
- else
- m_pedIK.m_flags &= ~CPedIK::AIMS_WITH_ARM;
-}
-
-void
-CPed::SetPointGunAt(CEntity *to)
-{
- if (to) {
- SetLookFlag(to, true);
- SetAimFlag(to);
-#ifdef VC_PED_PORTS
- SetLookTimer(INT32_MAX);
-#endif
- }
-
- if (m_nPedState == PED_AIM_GUN || bIsDucking || m_nWaitState == WAITSTATE_PLAYANIM_DUCK)
- return;
-
- if (m_nPedState != PED_ATTACK)
- SetStoredState();
-
- m_nPedState = PED_AIM_GUN;
- bIsPointingGunAt = true;
- CWeaponInfo *curWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
- SetMoveState(PEDMOVE_NONE);
-
- CAnimBlendAssociation *aimAssoc;
-
- if (bCrouchWhenShooting)
- aimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), curWeapon->m_Anim2ToPlay);
- else
- aimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), curWeapon->m_AnimToPlay);
-
- if (!aimAssoc || aimAssoc->blendDelta < 0.0f) {
- if (bCrouchWhenShooting)
- aimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, curWeapon->m_Anim2ToPlay, 4.0f);
- else
- aimAssoc = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, curWeapon->m_AnimToPlay);
-
- aimAssoc->blendAmount = 0.0f;
- aimAssoc->blendDelta = 8.0f;
- }
- if (to)
- Say(SOUND_PED_ATTACK);
-}
-
-void
-CPed::SetAmmo(eWeaponType weaponType, uint32 ammo)
-{
- if (HasWeapon(weaponType)) {
- GetWeapon(weaponType).m_nAmmoTotal = ammo;
- } else {
- GetWeapon(weaponType).Initialise(weaponType, ammo);
- m_maxWeaponTypeAllowed++;
- }
-}
-
-void
-CPed::GrantAmmo(eWeaponType weaponType, uint32 ammo)
-{
- if (HasWeapon(weaponType)) {
- GetWeapon(weaponType).m_nAmmoTotal += ammo;
- } else {
- GetWeapon(weaponType).Initialise(weaponType, ammo);
- m_maxWeaponTypeAllowed++;
- }
-}
-
-void
-CPed::SetEvasiveStep(CEntity *reason, uint8 animType)
-{
- AnimationId stepAnim;
-
- if (m_nPedState == PED_STEP_AWAY || !IsPedInControl() || ((IsPlayer() || !bRespondsToThreats) && animType == 0))
- return;
-
- float angleToFace = CGeneral::GetRadianAngleBetweenPoints(
- reason->GetPosition().x, reason->GetPosition().y,
- GetPosition().x, GetPosition().y);
- angleToFace = CGeneral::LimitRadianAngle(angleToFace);
- m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur);
- float neededTurn = Abs(angleToFace - m_fRotationCur);
- bool vehPressedHorn = false;
-
- if (neededTurn > PI)
- neededTurn = TWOPI - neededTurn;
-
- CVehicle *veh = (CVehicle*)reason;
- if (reason->IsVehicle() && veh->m_vehType == VEHICLE_TYPE_CAR) {
- if (veh->m_nCarHornTimer != 0) {
- vehPressedHorn = true;
- if (!IsPlayer())
- animType = 1;
- }
- }
- if (neededTurn <= DEGTORAD(90.0f) || veh->GetModelIndex() == MI_RCBANDIT || vehPressedHorn || animType != 0) {
- SetLookFlag(veh, true);
- if ((CGeneral::GetRandomNumber() & 1) && veh->GetModelIndex() != MI_RCBANDIT && animType == 0) {
- stepAnim = ANIM_IDLE_TAXI;
- } else {
-
- float vehDirection = CGeneral::GetRadianAngleBetweenPoints(
- veh->m_vecMoveSpeed.x, veh->m_vecMoveSpeed.y,
- 0.0f, 0.0f);
-
- // Let's turn our back to the "reason"
- angleToFace += PI;
-
- if (angleToFace > PI)
- angleToFace -= TWOPI;
-
- // We don't want to run towards car's direction
- float dangerZone = angleToFace - vehDirection;
- dangerZone = CGeneral::LimitRadianAngle(dangerZone);
-
- // So, add or subtract 90deg (jump to left/right) according to that
- if (dangerZone > 0.0f)
- angleToFace = vehDirection - HALFPI;
- else
- angleToFace = vehDirection + HALFPI;
-
- stepAnim = NUM_ANIMS;
- if (animType == 0 || animType == 1)
- stepAnim = ANIM_EV_STEP;
- else if (animType == 2)
- stepAnim = ANIM_HANDSCOWER;
- }
- if (!RpAnimBlendClumpGetAssociation(GetClump(), stepAnim)) {
- CAnimBlendAssociation *stepAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, stepAnim, 8.0f);
- stepAssoc->flags &= ~ASSOC_DELETEFADEDOUT;
- stepAssoc->SetFinishCallback(PedEvadeCB, this);
-
- if (animType == 0)
- Say(SOUND_PED_EVADE);
-
- m_fRotationCur = CGeneral::LimitRadianAngle(angleToFace);
- ClearAimFlag();
- SetStoredState();
- m_nPedState = PED_STEP_AWAY;
- }
- }
-}
-
-void
-CPed::SetEvasiveDive(CPhysical *reason, uint8 onlyRandomJump)
-{
- if (!IsPedInControl() || !bRespondsToThreats)
- return;
-
- CAnimBlendAssociation *animAssoc;
- float angleToFace, neededTurn;
- bool handsUp = false;
-
- angleToFace = m_fRotationCur;
- CVehicle *veh = (CVehicle*) reason;
- if (reason->IsVehicle() && veh->m_vehType == VEHICLE_TYPE_CAR && veh->m_nCarHornTimer != 0 && !IsPlayer()) {
- onlyRandomJump = true;
- }
-
- if (onlyRandomJump) {
- if (reason) {
- // Simple version of my bug fix below. Doesn't calculate "danger zone", selects jump direction randomly.
- // Also doesn't include random hands up, sound etc. Only used on player ped and peds running from gun shots.
-
- float vehDirection = CGeneral::GetRadianAngleBetweenPoints(
- veh->m_vecMoveSpeed.x, veh->m_vecMoveSpeed.y,
- 0.0f, 0.0f);
- angleToFace = (CGeneral::GetRandomNumber() & 1) * PI + (-0.5f*PI) + vehDirection;
- angleToFace = CGeneral::LimitRadianAngle(angleToFace);
- }
- } else {
- if (IsPlayer()) {
- ((CPlayerPed*)this)->m_nEvadeAmount = 5;
- ((CPlayerPed*)this)->m_pEvadingFrom = reason;
- reason->RegisterReference((CEntity**) &((CPlayerPed*)this)->m_pEvadingFrom);
- return;
- }
-
- angleToFace = CGeneral::GetRadianAngleBetweenPoints(
- reason->GetPosition().x, reason->GetPosition().y,
- GetPosition().x, GetPosition().y);
- angleToFace = CGeneral::LimitRadianAngle(angleToFace);
- m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur);
-
- // FIX: Peds no more dive into cars. Taken from SetEvasiveStep, last if statement inverted
-#ifdef FIX_BUGS
- float vehDirection = CGeneral::GetRadianAngleBetweenPoints(
- veh->m_vecMoveSpeed.x, veh->m_vecMoveSpeed.y,
- 0.0f, 0.0f);
-
- // Let's turn our back to the "reason"
- angleToFace += PI;
-
- if (angleToFace > PI)
- angleToFace -= 2 * PI;
-
- // We don't want to dive towards car's direction
- float dangerZone = angleToFace - vehDirection;
- dangerZone = CGeneral::LimitRadianAngle(dangerZone);
-
- // So, add or subtract 90deg (jump to left/right) according to that
- if (dangerZone > 0.0f)
- angleToFace = 0.5f * PI + vehDirection;
- else
- angleToFace = vehDirection - 0.5f * PI;
-#endif
-
- neededTurn = Abs(angleToFace - m_fRotationCur);
-
- if (neededTurn > PI)
- neededTurn = 2 * PI - neededTurn;
-
- if (neededTurn <= 0.5f*PI) {
- if (CGeneral::GetRandomNumber() & 1)
- handsUp = true;
- } else {
- if (CGeneral::GetRandomNumber() & 7)
- return;
- }
- Say(SOUND_PED_EVADE);
- }
-
- if (handsUp || !IsPlayer() && m_pedStats->m_flags & STAT_NO_DIVE) {
- m_fRotationCur = angleToFace;
- ClearLookFlag();
- ClearAimFlag();
- SetLookFlag(reason, true);
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_HANDSUP);
- if (animAssoc)
- return;
-
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_HANDSUP, 8.0f);
- animAssoc->flags &= ~ASSOC_DELETEFADEDOUT;
- animAssoc->SetFinishCallback(PedEvadeCB, this);
- SetStoredState();
- m_nPedState = PED_STEP_AWAY;
- } else {
- m_fRotationCur = angleToFace;
- ClearLookFlag();
- ClearAimFlag();
- SetStoredState();
- m_nPedState = PED_DIVE_AWAY;
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_EV_DIVE, 8.0f);
- animAssoc->SetFinishCallback(PedEvadeCB, this);
- }
-
- if (reason->IsVehicle() && m_nPedType == PEDTYPE_COP) {
- if (veh->pDriver && veh->pDriver->IsPlayer()) {
- CWanted *wanted = FindPlayerPed()->m_pWanted;
- wanted->RegisterCrime_Immediately(CRIME_RECKLESS_DRIVING, GetPosition(), (uintptr)this, false);
- wanted->RegisterCrime_Immediately(CRIME_SPEEDING, GetPosition(), (uintptr)this, false);
- }
- }
-#ifdef PEDS_REPORT_CRIMES_ON_PHONE
- else if (reason->IsVehicle()) {
- if (veh->pDriver && veh->pDriver->IsPlayer()) {
- CWanted* wanted = FindPlayerPed()->m_pWanted;
- wanted->RegisterCrime(CRIME_RECKLESS_DRIVING, GetPosition(), (uintptr)this, false);
- }
- }
-#endif
-}
-
-void
-CPed::SetAttack(CEntity *victim)
+uint32
+CPed::ScanForThreats(void)
{
- CPed *victimPed = nil;
- if (victim && victim->IsPed())
- victimPed = (CPed*)victim;
-
- CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_ARMED);
- if (animAssoc) {
- animAssoc->blendDelta = -1000.0f;
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- }
-
- if (m_attackTimer > CTimer::GetTimeInMilliseconds() || m_nWaitState == WAITSTATE_SURPRISE)
- return;
-
- if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_HGUN_RELOAD)) {
- bIsAttacking = false;
- return;
- }
-
- if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_AK_RELOAD)) {
- if (!IsPlayer() || m_nPedState != PED_ATTACK || ((CPlayerPed*)this)->m_bHaveTargetSelected)
- bIsAttacking = false;
- else
- bIsAttacking = true;
-
- return;
- }
-
- CWeaponInfo *curWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
- if (curWeapon->m_eWeaponFire == WEAPON_FIRE_INSTANT_HIT && !IsPlayer()) {
- if (GetWeapon()->HitsGround(this, nil, victim))
- return;
- }
-
- if (GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED) {
- if (IsPlayer() ||
- (m_nPedState != PED_FIGHT && m_nMoveState != PEDMOVE_NONE && m_nMoveState != PEDMOVE_STILL && !(m_pedStats->m_flags & STAT_SHOPPING_BAGS))) {
-
- if (m_nPedState != PED_ATTACK) {
- m_nPedState = PED_ATTACK;
- bIsAttacking = false;
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, curWeapon->m_AnimToPlay, 8.0f);
- animAssoc->SetRun();
- if (animAssoc->currentTime == animAssoc->hierarchy->totalLength)
- animAssoc->SetCurrentTime(0.0f);
-
- animAssoc->SetFinishCallback(FinishedAttackCB, this);
- }
- } else {
- StartFightAttack(CGeneral::GetRandomNumber() % 256);
- }
- return;
+ int fearFlags = m_fearFlags;
+ CVector ourPos = GetPosition();
+ float closestPedDist = 60.0f;
+ CVector2D explosionPos = GetPosition();
+ if (fearFlags & PED_FLAG_EXPLOSION && CheckForExplosions(explosionPos)) {
+ m_eventOrThreat = explosionPos;
+ return PED_FLAG_EXPLOSION;
}
-
- m_pSeekTarget = victim;
- if (m_pSeekTarget)
- m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget);
-
- if (curWeapon->m_bCanAim) {
- CVector aimPos = GetRight() * 0.1f + GetForward() * 0.2f + GetPosition();
- CEntity *obstacle = CWorld::TestSphereAgainstWorld(aimPos, 0.2f, nil, true, false, false, true, false, false);
- if (obstacle)
- return;
-
- m_pLookTarget = victim;
- if (victim) {
- m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);
- m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget);
- }
- if (m_pLookTarget) {
- SetAimFlag(m_pLookTarget);
- } else {
- SetAimFlag(m_fRotationCur);
-
- if (FindPlayerPed() == this && TheCamera.Cams[0].Using3rdPersonMouseCam())
- ((CPlayerPed*)this)->m_fFPSMoveHeading = TheCamera.Find3rdPersonQuickAimPitch();
+
+ CPed *shooter = nil;
+ if ((fearFlags & PED_FLAG_GUN) && (shooter = CheckForGunShots()) && (m_nPedType != shooter->m_nPedType || m_nPedType == PEDTYPE_CIVMALE || m_nPedType == PEDTYPE_CIVFEMALE)) {
+ if (!IsGangMember()) {
+ m_threatEntity = shooter;
+ m_threatEntity->RegisterReference((CEntity **) &m_threatEntity);
+ return PED_FLAG_GUN;
}
- }
- if (m_nPedState == PED_ATTACK) {
- bIsAttacking = true;
- return;
- }
-
- if (IsPlayer() || !victimPed || victimPed->IsPedInControl()) {
- if (IsPlayer())
- CPad::GetPad(0)->ResetAverageWeapon();
-
- PointBlankNecessity pointBlankStatus;
- if ((curWeapon->m_eWeaponFire == WEAPON_FIRE_INSTANT_HIT || GetWeapon()->m_eWeaponType == WEAPONTYPE_FLAMETHROWER)
- && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_M16_1STPERSON
- && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_M16_1STPERSON_RUNABOUT
- && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_SNIPER
- && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_SNIPER_RUNABOUT
- && (pointBlankStatus = CheckForPointBlankPeds(victimPed)) != NO_POINT_BLANK_PED) {
- ClearAimFlag();
-
- // This condition is pointless
- if (pointBlankStatus == POINT_BLANK_FOR_WANTED_PED || !victimPed)
- StartFightAttack(200);
- } else {
- if (!curWeapon->m_bCanAim)
- m_pSeekTarget = nil;
-
- if (m_nPedState != PED_AIM_GUN)
- SetStoredState();
- m_nPedState = PED_ATTACK;
- SetMoveState(PEDMOVE_NONE);
- if (bCrouchWhenShooting) {
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_RBLOCK_CSHOOT, 4.0f);
- } else {
- float animDelta = 8.0f;
- if (curWeapon->m_eWeaponFire == WEAPON_FIRE_MELEE)
- animDelta = 1000.0f;
-
- if (GetWeapon()->m_eWeaponType != WEAPONTYPE_BASEBALLBAT
- || CheckForPedsOnGroundToAttack(this, nil) < PED_ON_THE_FLOOR) {
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, curWeapon->m_AnimToPlay, animDelta);
- } else {
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, curWeapon->m_Anim2ToPlay, animDelta);
- }
- }
-
- animAssoc->SetRun();
- if (animAssoc->currentTime == animAssoc->hierarchy->totalLength)
- animAssoc->SetCurrentTime(0.0f);
-
- animAssoc->SetFinishCallback(FinishedAttackCB, this);
+ if (CPedType::GetFlag(shooter->m_nPedType) & fearFlags) {
+ m_threatEntity = shooter;
+ m_threatEntity->RegisterReference((CEntity **) &m_threatEntity);
+ return CPedType::GetFlag(shooter->m_nPedType);
}
- return;
- }
-
- if (GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT && victimPed->m_nPedState == PED_GETUP)
- SetWaitState(WAITSTATE_SURPRISE, nil);
-
- SetLookFlag(victim, false);
- SetLookTimer(100);
-}
-
-void
-CPed::StartFightAttack(uint8 buttonPressure)
-{
- if (!IsPedInControl() || m_attackTimer > CTimer::GetTimeInMilliseconds())
- return;
-
- if (m_nPedState == PED_FIGHT) {
- m_fightButtonPressure = buttonPressure;
- return;
- }
-
- if (m_nPedState != PED_AIM_GUN)
- SetStoredState();
-
- if (m_nWaitState != WAITSTATE_FALSE) {
- m_nWaitState = WAITSTATE_FALSE;
- RestoreHeadingRate();
- }
-
- m_nPedState = PED_FIGHT;
- m_fightButtonPressure = 0;
- RpAnimBlendClumpRemoveAssociations(GetClump(), ASSOC_REPEAT);
- CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WALK_START);
-
- if (animAssoc) {
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- animAssoc->blendDelta = -1000.0f;
- }
-
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP);
- if (!animAssoc)
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP_R);
-
- if (animAssoc) {
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- animAssoc->blendDelta = -1000.0f;
- RestoreHeadingRate();
}
- SetMoveState(PEDMOVE_NONE);
- m_nStoredMoveState = PEDMOVE_NONE;
-
- CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT_IDLE)->blendAmount = 1.0f;
-
- CPed *pedOnGround = nil;
- if (IsPlayer() && CheckForPedsOnGroundToAttack(this, &pedOnGround) > PED_IN_FRONT_OF_ATTACKER) {
- m_curFightMove = FIGHTMOVE_GROUNDKICK;
- } else if (m_pedStats->m_flags & STAT_SHOPPING_BAGS) {
- m_curFightMove = FIGHTMOVE_ROUNDHOUSE;
+ CPed *deadPed = nil;
+ if (fearFlags & PED_FLAG_DEADPEDS && CharCreatedBy != MISSION_CHAR
+ && (deadPed = CheckForDeadPeds()) != nil && (deadPed->GetPosition() - ourPos).MagnitudeSqr() < sq(20.0f)) {
+ m_pEventEntity = deadPed;
+ m_pEventEntity->RegisterReference((CEntity **) &m_pEventEntity);
+ return PED_FLAG_DEADPEDS;
} else {
- m_curFightMove = FIGHTMOVE_STDPUNCH;
- }
-
- if (pedOnGround && IsPlayer()) {
- m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(
- pedOnGround->GetPosition().x, pedOnGround->GetPosition().y,
- GetPosition().x, GetPosition().y);
-
- m_fRotationDest = CGeneral::LimitRadianAngle(m_fRotationDest);
- m_fRotationCur = m_fRotationDest;
- m_lookTimer = 0;
- SetLookFlag(pedOnGround, true);
- SetLookTimer(1500);
- }
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 4.0f);
- animAssoc->SetFinishCallback(FinishFightMoveCB, this);
- m_fightState = FIGHTSTATE_NO_MOVE;
- m_takeAStepAfterAttack = false;
- bIsAttacking = true;
-
- if (IsPlayer())
- nPlayerInComboMove = 0;
-}
-
-void
-CPed::LoadFightData(void)
-{
- float startFireTime, endFireTime, comboFollowOnTime, strikeRadius;
- int damage, flags;
- char line[256], moveName[32], animName[32], hitLevel;
- int moveId = 0;
-
- CAnimBlendAssociation *animAssoc;
-
- size_t bp, buflen;
- int lp, linelen;
-
- buflen = CFileMgr::LoadFile("DATA\\fistfite.dat", work_buff, sizeof(work_buff), "r");
-
- for (bp = 0; bp < buflen; ) {
- // read file line by line
- for (linelen = 0; work_buff[bp] != '\n' && bp < buflen; bp++) {
- line[linelen++] = work_buff[bp];
- }
- bp++;
- line[linelen] = '\0';
-
- // skip white space
- for (lp = 0; line[lp] <= ' ' && line[lp] != '\0'; lp++);
-
- if (line[lp] == '\0' ||
- line[lp] == '#')
- continue;
-
- sscanf(
- &line[lp],
- "%s %f %f %f %f %c %s %d %d",
- moveName,
- &startFireTime,
- &endFireTime,
- &comboFollowOnTime,
- &strikeRadius,
- &hitLevel,
- animName,
- &damage,
- &flags);
-
- if (strncmp(moveName, "ENDWEAPONDATA", 13) == 0)
- return;
-
- tFightMoves[moveId].startFireTime = startFireTime / 30.0f;
- tFightMoves[moveId].endFireTime = endFireTime / 30.0f;
- tFightMoves[moveId].comboFollowOnTime = comboFollowOnTime / 30.0f;
- tFightMoves[moveId].strikeRadius = strikeRadius;
- tFightMoves[moveId].damage = damage;
- tFightMoves[moveId].flags = flags;
-
- switch (hitLevel) {
- case 'G':
- tFightMoves[moveId].hitLevel = HITLEVEL_GROUND;
- break;
- case 'H':
- tFightMoves[moveId].hitLevel = HITLEVEL_HIGH;
- break;
- case 'L':
- tFightMoves[moveId].hitLevel = HITLEVEL_LOW;
- break;
- case 'M':
- tFightMoves[moveId].hitLevel = HITLEVEL_MEDIUM;
- break;
- case 'N':
- tFightMoves[moveId].hitLevel = HITLEVEL_NULL;
- break;
- default:
- break;
- }
-
- if (strncmp(animName, "null", 4) != 0) {
- animAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, animName);
- tFightMoves[moveId].animId = (AnimationId)animAssoc->animId;
- } else {
- tFightMoves[moveId].animId = ANIM_WALK;
- }
- moveId++;
- }
-}
-
-// Actually GetLocalDirectionTo(Turn/Look)
-int
-CPed::GetLocalDirection(const CVector2D &posOffset)
-{
- int direction;
- float angle;
-
- for (angle = posOffset.Heading() - m_fRotationCur + DEGTORAD(45.0f); angle < 0.0f; angle += TWOPI);
-
- for (direction = RADTODEG(angle)/90.0f; direction > 3; direction -= 4);
-
- // 0-forward, 1-left, 2-backward, 3-right.
- return direction;
-}
-
-bool
-CPed::FightStrike(CVector &touchedNodePos)
-{
- CColModel *ourCol;
- CVector attackDistance;
- ePedPieceTypes closestPedPiece = PEDPIECE_TORSO;
- float maxDistanceToBeBeaten;
- CPed *nearPed;
- int state = m_fightState;
- bool pedFound = false;
-
- if (state == FIGHTSTATE_JUST_ATTACKED)
- return false;
-
- // Pointless code
- if (state > FIGHTSTATE_NO_MOVE)
- attackDistance = touchedNodePos - m_vecHitLastPos;
-
- for (int i = 0; i < m_numNearPeds; i++) {
- nearPed = m_nearPeds[i];
- if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED)
- maxDistanceToBeBeaten = nearPed->GetBoundRadius() + tFightMoves[m_curFightMove].strikeRadius + 0.1f;
- else
- maxDistanceToBeBeaten = nearPed->GetBoundRadius() + tFightMoves[m_curFightMove].strikeRadius;
+ uint32 flagsOfSomePed = 0;
- if (nearPed->bUsesCollision || nearPed->m_nPedState == PED_DEAD) {
- CVector nearPedCentre;
- nearPed->GetBoundCentre(nearPedCentre);
- CVector potentialAttackDistance = nearPedCentre - touchedNodePos;
+ CPed *pedToFearFrom = nil;
+#ifndef VC_PED_PORTS
+ for (int i = 0; i < m_numNearPeds; i++) {
+ if (CharCreatedBy != RANDOM_CHAR || m_nearPeds[i]->CharCreatedBy != MISSION_CHAR || m_nearPeds[i]->IsPlayer()) {
+ CPed *nearPed = m_nearPeds[i];
- // He can beat us
- if (sq(maxDistanceToBeBeaten) > potentialAttackDistance.MagnitudeSqr()) {
+ // BUG: WTF Rockstar?! Putting this here will result in returning the flags of farthest ped to us, since m_nearPeds is sorted by distance.
+ // Fixed at the bottom of the function.
+ flagsOfSomePed = CPedType::GetFlag(nearPed->m_nPedType);
-#ifdef PED_SKIN
- // Have to animate a skinned clump because the initial col model is useless
- if(IsClumpSkinned(GetClump()))
- ourCol = ((CPedModelInfo *)CModelInfo::GetModelInfo(GetModelIndex()))->AnimatePedColModelSkinned(GetClump());
- else
-#endif
- if (nearPed->OnGround() || !nearPed->IsPedHeadAbovePos(-0.3f)) {
- ourCol = &CTempColModels::ms_colModelPedGroundHit;
- } else {
-#ifdef ANIMATE_PED_COL_MODEL
- ourCol = CPedModelInfo::AnimatePedColModel(((CPedModelInfo *)CModelInfo::GetModelInfo(GetModelIndex()))->GetHitColModel(),
- RpClumpGetFrame(GetClump()));
+ if (CPedType::GetFlag(nearPed->m_nPedType) & fearFlags) {
+ if (nearPed->m_fHealth > 0.0f && OurPedCanSeeThisOne(m_nearPeds[i])) {
+ // FIX: Taken from VC
+#ifdef FIX_BUGS
+ float nearPedDistSqr = (nearPed->GetPosition() - ourPos).MagnitudeSqr2D();
#else
- ourCol = ((CPedModelInfo*)CModelInfo::GetModelInfo(m_modelIndex))->GetHitColModel();
+ float nearPedDistSqr = (CVector2D(ourPos) - explosionPos).MagnitudeSqr();
#endif
- }
-
- for (int j = 0; j < ourCol->numSpheres; j++) {
- attackDistance = nearPed->GetPosition() + ourCol->spheres[j].center;
- attackDistance -= touchedNodePos;
- CColSphere *ourPieces = ourCol->spheres;
- float maxDistanceToBeat = ourPieces[j].radius + tFightMoves[m_curFightMove].strikeRadius;
-
- // We can beat him too
- if (sq(maxDistanceToBeat) > attackDistance.MagnitudeSqr()) {
- pedFound = true;
- closestPedPiece = (ePedPieceTypes) ourPieces[j].piece;
- break;
+ if (sq(closestPedDist) > nearPedDistSqr) {
+ closestPedDist = Sqrt(nearPedDistSqr);
+ pedToFearFrom = m_nearPeds[i];
+ }
}
}
}
}
- if (pedFound)
- break;
- }
-
- if (pedFound) {
- if (nearPed->IsPlayer() && nearPed->m_nPedState == PED_GETUP)
- return false;
-
- float oldVictimHealth = nearPed->m_fHealth;
- CVector bloodPos = 0.5f * attackDistance + touchedNodePos;
- int damageMult = tFightMoves[m_curFightMove].damage * ((CGeneral::GetRandomNumber() & 1) + 2) + 1;
-
- CVector2D diff (GetPosition() - nearPed->GetPosition());
- int direction = nearPed->GetLocalDirection(diff);
- if (IsPlayer()) {
- if (((CPlayerPed*)this)->m_bAdrenalineActive)
- damageMult = 20;
- } else {
- damageMult *= m_pedStats->m_attackStrength;
- }
-
- // Change direction if we used kick.
- if (m_curFightMove == FIGHTMOVE_KICK) {
- if (CGeneral::GetRandomNumber() & 1) {
- direction++;
- if (direction > 3)
- direction -= 4;
- }
- }
- nearPed->ReactToAttack(this);
-
- // Mostly unused. if > 5, ANIM_HIT_WALK will be run, that's it.
- int unk2;
- if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED && !nearPed->IsPlayer())
- unk2 = 101;
- else
- unk2 = damageMult;
-
- nearPed->StartFightDefend(direction, tFightMoves[m_curFightMove].hitLevel, unk2);
- PlayHitSound(nearPed);
- m_fightState = FIGHTSTATE_JUST_ATTACKED;
- RpAnimBlendClumpGetAssociation(GetClump(), tFightMoves[m_curFightMove].animId)->speed = 0.6f;
- if (!nearPed->DyingOrDead()) {
- nearPed->InflictDamage(this, WEAPONTYPE_UNARMED, damageMult * 3.0f, closestPedPiece, direction);
- }
-
- if (CGame::nastyGame
- && tFightMoves[m_curFightMove].hitLevel > HITLEVEL_MEDIUM
- && nearPed->m_nPedState == PED_DIE
- && nearPed->GetIsOnScreen()) {
+#else
+ bool weSawOurEnemy = false;
+ bool weMaySeeOurEnemy = false;
+ float closestEnemyDist = 60.0f;
+ if ((CTimer::GetFrameCounter() + (uint8)m_randomSeed + 16) & 4) {
- // Just for blood particle. We will restore it below.
- attackDistance /= (10.0f * attackDistance.Magnitude());
- for(int i=0; i<4; i++) {
- CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, attackDistance, nil, 0.0f, 0, 0, 0, 0);
- }
- }
- if (!nearPed->OnGround()) {
- float curVictimHealth = nearPed->m_fHealth;
- if (curVictimHealth > 0.0f
- && (curVictimHealth < 40.0f && oldVictimHealth > 40.0f && !nearPed->IsPlayer()
- || nearPed->m_fHealth < 20.0f && oldVictimHealth > 20.0f
- || GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED && IsPlayer()
- || nearPed->m_pedStats->m_flags & STAT_ONE_HIT_KNOCKDOWN)) {
-
- nearPed->SetFall(0, (AnimationId)(direction + ANIM_KO_SKID_FRONT), 0);
- if (nearPed->m_nPedState == PED_FALL)
- nearPed->bIsStanding = false;
- }
- }
- if (nearPed->m_nPedState == PED_DIE || !nearPed->bIsStanding) {
- attackDistance = nearPed->GetPosition() - GetPosition();
- attackDistance.Normalise();
- attackDistance.z = 1.0f;
- nearPed->bIsStanding = false;
-
- float moveMult;
- if (m_curFightMove == FIGHTMOVE_GROUNDKICK) {
- moveMult = Min(damageMult * 0.6f, 4.0f);
- } else {
- if (nearPed->m_nPedState != PED_DIE || damageMult >= 20) {
- moveMult = damageMult;
- } else {
- moveMult = Min(damageMult * 2.0f, 14.0f);
+ for (int i = 0; i < m_numNearPeds; ++i) {
+ if (CharCreatedBy == RANDOM_CHAR && m_nearPeds[i]->CharCreatedBy == MISSION_CHAR && !m_nearPeds[i]->IsPlayer()) {
+ continue;
}
- }
-
- nearPed->ApplyMoveForce(moveMult * 0.6f * attackDistance);
- }
- CEventList::RegisterEvent(nearPed->m_nPedType == PEDTYPE_COP ? EVENT_ASSAULT_POLICE : EVENT_ASSAULT, EVENT_ENTITY_PED, nearPed, this, 2000);
- }
-
- if (m_fightState == FIGHTSTATE_NO_MOVE)
- m_fightState = FIGHTSTATE_1;
-
- m_vecHitLastPos = *touchedNodePos;
- return false;
-}
-
-void
-CPed::SetFall(int extraTime, AnimationId animId, uint8 evenIfNotInControl)
-{
- if (!IsPedInControl() && (!evenIfNotInControl || DyingOrDead()))
- return;
-
- ClearLookFlag();
- ClearAimFlag();
- SetStoredState();
- m_nPedState = PED_FALL;
- CAnimBlendAssociation *fallAssoc = RpAnimBlendClumpGetAssociation(GetClump(), animId);
-
- if (fallAssoc) {
- fallAssoc->SetCurrentTime(0.0f);
- fallAssoc->blendAmount = 0.0f;
- fallAssoc->blendDelta = 8.0f;
- fallAssoc->SetRun();
- } else {
- fallAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animId, 8.0f);
- }
-
- if (extraTime == -1) {
- m_getUpTimer = UINT32_MAX;
- } else if (fallAssoc) {
- if (IsPlayer()) {
- m_getUpTimer = 1000.0f * fallAssoc->hierarchy->totalLength
- + CTimer::GetTimeInMilliseconds()
- + 500.0f;
- } else {
- m_getUpTimer = 1000.0f * fallAssoc->hierarchy->totalLength
- + CTimer::GetTimeInMilliseconds()
- + extraTime
- + ((m_randomSeed + CTimer::GetFrameCounter()) % 1000);
- }
- } else {
- m_getUpTimer = extraTime
- + CTimer::GetTimeInMilliseconds()
- + 1000
- + ((m_randomSeed + CTimer::GetFrameCounter()) % 1000);
- }
- bFallenDown = true;
-}
-
-void
-CPed::SetFlee(CEntity *fleeFrom, int time)
-{
- if (!IsPedInControl() || bKindaStayInSamePlace || !fleeFrom)
- return;
-
- SetStoredState();
- m_nPedState = PED_FLEE_ENTITY;
- bUsePedNodeSeek = true;
- SetMoveState(PEDMOVE_RUN);
- m_fleeFrom = fleeFrom;
- m_fleeFrom->RegisterReference((CEntity **) &m_fleeFrom);
-
- if (time <= 0)
- m_fleeTimer = 0;
- else
- m_fleeTimer = CTimer::GetTimeInMilliseconds() + time;
-
- float angleToFace = CGeneral::GetRadianAngleBetweenPoints(
- GetPosition().x, GetPosition().y,
- fleeFrom->GetPosition().x, fleeFrom->GetPosition().y);
-
- m_fRotationDest = CGeneral::LimitRadianAngle(angleToFace);
- if (m_fRotationCur - PI > m_fRotationDest) {
- m_fRotationDest += 2 * PI;
- } else if (PI + m_fRotationCur < m_fRotationDest) {
- m_fRotationDest -= 2 * PI;
- }
-}
-
-void
-CPed::SetFlee(CVector2D const &from, int time)
-{
- if (CTimer::GetTimeInMilliseconds() < m_nPedStateTimer || !IsPedInControl() || bKindaStayInSamePlace)
- return;
-
- if (m_nPedState != PED_FLEE_ENTITY) {
- SetStoredState();
- m_nPedState = PED_FLEE_POS;
- SetMoveState(PEDMOVE_RUN);
- m_fleeFromPosX = from.x;
- m_fleeFromPosY = from.y;
- }
-
- bUsePedNodeSeek = true;
- m_pNextPathNode = nil;
- m_fleeTimer = CTimer::GetTimeInMilliseconds() + time;
-
- float angleToFace = CGeneral::GetRadianAngleBetweenPoints(
- GetPosition().x, GetPosition().y,
- from.x, from.y);
-
- m_fRotationDest = CGeneral::LimitRadianAngle(angleToFace);
- if (m_fRotationCur - PI > m_fRotationDest) {
- m_fRotationDest += 2 * PI;
- } else if (PI + m_fRotationCur < m_fRotationDest) {
- m_fRotationDest -= 2 * PI;
- }
-}
-
-void
-CPed::SetWaitState(eWaitState state, void *time)
-{
- AnimationId waitAnim = NUM_ANIMS;
- CAnimBlendAssociation *animAssoc;
-
- if (!IsPedInControl())
- return;
-
- if (state != m_nWaitState)
- FinishedWaitCB(nil, this);
-
- switch (state) {
- case WAITSTATE_TRAFFIC_LIGHTS:
- m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 500;
- SetMoveState(PEDMOVE_STILL);
- break;
- case WAITSTATE_CROSS_ROAD:
- m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 1000;
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_HBHB, 4.0f);
- break;
- case WAITSTATE_CROSS_ROAD_LOOK:
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_ROAD_CROSS, 8.0f);
-
- if (time)
- m_nWaitTimer = CTimer::GetTimeInMilliseconds() + *(int*)time;
- else
- m_nWaitTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(2000,5000);
-
- break;
- case WAITSTATE_LOOK_PED:
- case WAITSTATE_LOOK_SHOP:
- case WAITSTATE_LOOK_ACCIDENT:
- case WAITSTATE_FACEOFF_GANG:
- break;
- case WAITSTATE_DOUBLEBACK:
- m_headingRate = 0.0f;
- m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 3500;
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_HBHB, 4.0f);
-#ifdef FIX_BUGS
- animAssoc->SetFinishCallback(RestoreHeadingRateCB, this);
-#endif
- break;
- case WAITSTATE_HITWALL:
- m_headingRate = 2.0f;
- m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 5000;
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_HIT_WALL, 16.0f);
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- animAssoc->flags |= ASSOC_FADEOUTWHENDONE;
- animAssoc->SetDeleteCallback(FinishedWaitCB, this);
-
- if (m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER && CharCreatedBy == RANDOM_CHAR && m_nPedState == PED_SEEK_CAR) {
- ClearObjective();
- RestorePreviousState();
- m_hitRecoverTimer = CTimer::GetTimeInMilliseconds() + 30000;
- }
- break;
- case WAITSTATE_TURN180:
- m_headingRate = 0.0f;
- m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 5000;
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_TURN_180, 4.0f);
- animAssoc->SetFinishCallback(FinishedWaitCB, this);
- animAssoc->SetDeleteCallback(RestoreHeadingRateCB, this);
- break;
- case WAITSTATE_SURPRISE:
- m_headingRate = 0.0f;
- m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 2000;
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_HIT_WALL, 4.0f);
- animAssoc->SetFinishCallback(FinishedWaitCB, this);
- break;
- case WAITSTATE_STUCK:
- SetMoveState(PEDMOVE_STILL);
- SetMoveAnim();
- m_headingRate = 0.0f;
- m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 5000;
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_TIRED, 4.0f);
-#ifdef FIX_BUGS
- animAssoc->SetFinishCallback(RestoreHeadingRateCB, this);
-#endif
-
- if (m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER && CharCreatedBy == RANDOM_CHAR && m_nPedState == PED_SEEK_CAR) {
- ClearObjective();
- RestorePreviousState();
- m_hitRecoverTimer = CTimer::GetTimeInMilliseconds() + 30000;
- }
- break;
- case WAITSTATE_LOOK_ABOUT:
- SetMoveState(PEDMOVE_STILL);
- SetMoveAnim();
- m_headingRate = 0.0f;
- m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 5000;
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_HBHB, 4.0f);
-#ifdef FIX_BUGS
- animAssoc->SetFinishCallback(RestoreHeadingRateCB, this);
-#endif
-
- break;
- case WAITSTATE_PLAYANIM_COWER:
- waitAnim = ANIM_HANDSCOWER;
- case WAITSTATE_PLAYANIM_HANDSUP:
- if (waitAnim == NUM_ANIMS)
- waitAnim = ANIM_HANDSUP;
- case WAITSTATE_PLAYANIM_HANDSCOWER:
- if (waitAnim == NUM_ANIMS)
- waitAnim = ANIM_HANDSCOWER;
- m_headingRate = 0.0f;
- if (time)
- m_nWaitTimer = CTimer::GetTimeInMilliseconds() + *(int*)time;
- else
- m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 3000;
-
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, waitAnim, 4.0f);
- animAssoc->SetDeleteCallback(FinishedWaitCB, this);
- break;
- case WAITSTATE_PLAYANIM_DUCK:
- waitAnim = ANIM_DUCK_DOWN;
- case WAITSTATE_PLAYANIM_TAXI:
- if (waitAnim == NUM_ANIMS)
- waitAnim = ANIM_IDLE_TAXI;
- case WAITSTATE_PLAYANIM_CHAT:
- if (waitAnim == NUM_ANIMS)
- waitAnim = ANIM_IDLE_CHAT;
- if (time)
- m_nWaitTimer = CTimer::GetTimeInMilliseconds() + *(int*)time;
- else
- m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 3000;
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, waitAnim, 4.0f);
- animAssoc->flags &= ~ASSOC_FADEOUTWHENDONE;
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- animAssoc->SetDeleteCallback(FinishedWaitCB, this);
- break;
- case WAITSTATE_FINISH_FLEE:
- SetMoveState(PEDMOVE_STILL);
- SetMoveAnim();
- m_headingRate = 0.0f;
- m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 2500;
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_TIRED, 4.0f);
-#ifdef FIX_BUGS
- animAssoc->SetFinishCallback(RestoreHeadingRateCB, this);
-#endif
- break;
- default:
- m_nWaitState = WAITSTATE_FALSE;
- RestoreHeadingRate();
- return;
- }
- m_nWaitState = state;
-}
-
-
-void
-CPed::PlayHitSound(CPed *hitTo)
-{
- // That was very complicated to reverse for me...
- // First index is our fight move ID (from 1 to 12, total 12), second is the one of we fight with (from 13 to 22, total 10).
- enum {
- S33 = SOUND_FIGHT_PUNCH_33,
- S34 = SOUND_FIGHT_KICK_34,
- S35 = SOUND_FIGHT_HEADBUTT_35,
- S36 = SOUND_FIGHT_PUNCH_36,
- S37 = SOUND_FIGHT_PUNCH_37,
- S38 = SOUND_FIGHT_CLOSE_PUNCH_38,
- S39 = SOUND_FIGHT_PUNCH_39,
- S40 = SOUND_FIGHT_PUNCH_OR_KICK_BELOW_40 ,
- S41 = SOUND_FIGHT_PUNCH_41,
- S42 = SOUND_FIGHT_PUNCH_FROM_BEHIND_42,
- S43 = SOUND_FIGHT_KNEE_OR_KICK_43,
- S44 = SOUND_FIGHT_KICK_44,
- NO_SND = SOUND_NO_SOUND
- };
- uint16 hitSoundsByFightMoves[12][10] = {
- {S39,S42,S43,S43,S39,S39,S39,S39,S39,S42},
- {NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND},
- {NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND},
- {S39,S39,S39,S39,S33,S43,S39,S39,S39,S39},
- {S39,S39,S39,S39,S35,S39,S38,S38,S39,S39},
- {S39,S39,S39,S39,S33,S39,S41,S36,S39,S39},
- {S39,S39,S39,S39,S37,S40,S38,S38,S39,S39},
- {S39,S39,S39,S39,S34,S43,S44,S37,S39,S39},
- {S39,S39,S39,S39,S34,S43,S44,S37,S39,S39},
- {S39,S39,S39,S39,S34,S43,S44,S37,S39,S40},
- {S39,S39,S39,S39,S33,S39,S41,S37,S39,S40},
- {S39,S39,S39,S39,S39,S39,S39,S39,S33,S33}
- };
-
- // This is why first dimension is between FightMove 1 and 12.
- if (m_curFightMove == FIGHTMOVE_NULL || m_curFightMove >= FIGHTMOVE_HITFRONT)
- return;
-
- uint16 soundId;
-
- // And this is why second dimension is between 13 and 22.
- if (hitTo->m_curFightMove > FIGHTMOVE_GROUNDKICK && hitTo->m_curFightMove < FIGHTMOVE_IDLE2NORM) {
- soundId = hitSoundsByFightMoves[m_curFightMove - FIGHTMOVE_STDPUNCH][hitTo->m_curFightMove - FIGHTMOVE_HITFRONT];
-
- } else {
- if (hitTo->m_nPedState == PED_DEAD || hitTo->UseGroundColModel()) {
- soundId = hitSoundsByFightMoves[m_curFightMove - FIGHTMOVE_STDPUNCH][FIGHTMOVE_HITONFLOOR - FIGHTMOVE_HITFRONT];
- } else {
- soundId = hitSoundsByFightMoves[m_curFightMove - FIGHTMOVE_STDPUNCH][FIGHTMOVE_HITFRONT - FIGHTMOVE_HITFRONT];
- }
- }
-
- if (soundId != NO_SND)
- DMAudio.PlayOneShot(m_audioEntityId, soundId, 0.0f);
-}
-
-void
-CPed::CollideWithPed(CPed *collideWith)
-{
- CAnimBlendAssociation *animAssoc;
- AnimationId animToPlay;
-
- bool weAreMissionChar = CharCreatedBy == MISSION_CHAR;
- bool heIsMissionChar = collideWith->CharCreatedBy == MISSION_CHAR;
- CVector posDiff = collideWith->GetPosition() - GetPosition();
- int waitTime = 0;
-
- if (weAreMissionChar || !collideWith->IsPlayer() || collideWith->m_nPedState != PED_MAKE_CALL) {
- bool weDontLookToHim = DotProduct(posDiff, GetForward()) > 0.0f;
- bool heLooksToUs = DotProduct(posDiff, collideWith->GetForward()) < 0.0f;
-
- if (m_nMoveState != PEDMOVE_NONE && m_nMoveState != PEDMOVE_STILL) {
-
- if ((!IsPlayer() || ((CPlayerPed*)this)->m_fMoveSpeed <= 1.8f)
- && (IsPlayer() || heIsMissionChar && weAreMissionChar || m_nMoveState != PEDMOVE_RUN && m_nMoveState != PEDMOVE_SPRINT
-#ifdef VC_PED_PORTS
- || m_objective == OBJECTIVE_FOLLOW_CHAR_IN_FORMATION && m_pedInObjective == collideWith
- || collideWith->m_objective == OBJECTIVE_FOLLOW_CHAR_IN_FORMATION && collideWith->m_pedInObjective == this
-#endif
- )) {
-
- if (m_objective != OBJECTIVE_FOLLOW_CHAR_IN_FORMATION && m_objective != OBJECTIVE_GOTO_CHAR_ON_FOOT) {
-
- if (CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) {
-
- if (heIsMissionChar || !weAreMissionChar && collideWith->m_nMoveState != PEDMOVE_STILL) {
+ // BUG: Explained at the same occurence of this bug above. Fixed at the bottom of the function.
+ flagsOfSomePed = CPedType::GetFlag(m_nearPeds[i]->m_nPedType);
- if (weAreMissionChar && (m_nPedState == PED_SEEK_POS || m_nPedState == PED_SEEK_ENTITY)) {
+ if (flagsOfSomePed & fearFlags) {
+ if (m_nearPeds[i]->m_fHealth > 0.0f) {
- if (collideWith->m_nMoveState != PEDMOVE_STILL
- && (!collideWith->IsPlayer() || collideWith->IsPlayer() && CPad::GetPad(0)->ArePlayerControlsDisabled())) {
- float seekPosDist = (GetPosition() - m_vecSeekPos).MagnitudeSqr2D();
- float heAndSeekPosDist = (collideWith->GetPosition() - m_vecSeekPos).MagnitudeSqr2D();
+ // VC also has ability to include objects to line of sight check here (via last bit of flagsL)
+ if (OurPedCanSeeThisOne(m_nearPeds[i])) {
+ if (m_nearPeds[i]->m_nPedState == PED_ATTACK) {
+ if (m_nearPeds[i]->m_pedInObjective == this) {
- if (seekPosDist <= heAndSeekPosDist) {
- waitTime = 1000;
- collideWith->SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, &waitTime);
- collideWith->m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + waitTime;
- } else {
- waitTime = 500;
- SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, &waitTime);
- m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + waitTime;
+ float enemyDistSqr = (m_nearPeds[i]->GetPosition() - ourPos).MagnitudeSqr2D();
+ if (sq(closestEnemyDist) > enemyDistSqr) {
+ float enemyDist = Sqrt(enemyDistSqr);
+ weSawOurEnemy = true;
+ closestPedDist = enemyDist;
+ closestEnemyDist = enemyDist;
+ pedToFearFrom = m_nearPeds[i];
}
- } else if (collideWith->m_nMoveState == PEDMOVE_STILL) {
- SetDirectionToWalkAroundObject(collideWith);
}
} else {
- if (weAreMissionChar || m_pedStats->m_fear <= 100 - collideWith->m_pedStats->m_temper
- || (collideWith->IsPlayer() || collideWith->m_nMoveState == PEDMOVE_NONE || collideWith->m_nMoveState == PEDMOVE_STILL) &&
- (!collideWith->IsPlayer() || ((CPlayerPed*)collideWith)->m_fMoveSpeed <= 1.0f)) {
- SetDirectionToWalkAroundObject(collideWith);
- if (!weAreMissionChar)
- Say(SOUND_PED_CHAT);
- } else {
- SetEvasiveStep(collideWith, 2);
+ float nearPedDistSqr = (m_nearPeds[i]->GetPosition() - ourPos).MagnitudeSqr2D();
+ if (sq(closestPedDist) > nearPedDistSqr && !weSawOurEnemy) {
+ closestPedDist = Sqrt(nearPedDistSqr);
+ pedToFearFrom = m_nearPeds[i];
}
}
- } else {
- if (m_pedStats->m_temper <= m_pedStats->m_fear
- || GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED
- || weAreMissionChar
- || collideWith->m_nPedType == PEDTYPE_CIVFEMALE
- || collideWith->m_nPedType == m_nPedType
- || collideWith->GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED) {
- SetDirectionToWalkAroundObject(collideWith);
- Say(SOUND_PED_CHAT);
- } else {
- TurnBody();
- SetAttack(collideWith);
-#ifdef VC_PED_PORTS
- m_fRotationCur = 0.3f + m_fRotationCur;
- m_fRotationDest = m_fRotationCur;
-#endif
- }
- m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(250, 450);
- }
- }
- } else {
-#ifdef VC_PED_PORTS
- if (m_pedInObjective && (collideWith == m_pedInObjective || collideWith->m_pedInObjective == m_pedInObjective) && CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) {
-#else
- if (m_pedInObjective && collideWith == m_pedInObjective && CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) {
-#endif
- if (heLooksToUs) {
- SetEvasiveStep(collideWith, 1);
- m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 3000;
- }
- } else if (weDontLookToHim && IsPedInControl()) {
+ } else if (!weSawOurEnemy) {
+ CPed *nearPed = m_nearPeds[i];
+ if (nearPed->m_nPedState == PED_ATTACK) {
+ CColPoint foundCol;
+ CEntity *foundEnt;
- if (m_pedStats != collideWith->m_pedStats) {
+ // We don't see him yet but he's behind a ped, vehicle or object
+ // VC also has ability to include objects to line of sight check here (via last bit of flagsL)
+ if (!CWorld::ProcessLineOfSight(ourPos, nearPed->GetPosition(), foundCol, foundEnt,
+ true, false, false, false, false, false, false)) {
- if (collideWith->m_pedStats->m_fear <= 100 - m_pedStats->m_temper
-#ifdef VC_PED_PORTS
- || collideWith->IsPlayer() || CTimer::GetTimeInMilliseconds() < m_nPedStateTimer
-#endif
- ) {
-
- if (collideWith->IsPlayer()) {
- // He's on our right side
- if (DotProduct(posDiff,GetRight()) <= 0.0f)
- m_fRotationCur -= m_headingRate;
- else
- m_fRotationCur += m_headingRate;
- } else {
- // He's on our right side
- if (DotProduct(posDiff, collideWith->GetRight()) <= 0.0f)
- collideWith->m_fRotationCur -= collideWith->m_headingRate;
- else
- collideWith->m_fRotationCur += collideWith->m_headingRate;
- }
- } else {
- SetLookFlag(collideWith, false);
- TurnBody();
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT_PPUNCH, 8.0f);
- animAssoc->flags |= ASSOC_FADEOUTWHENDONE;
-#ifdef VC_PED_PORTS
- m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 2000;
-#endif
- if (!heIsMissionChar) {
- CVector2D posDiff2D(posDiff);
- int direction = collideWith->GetLocalDirection(posDiff2D);
- collideWith->StartFightDefend(direction, HITLEVEL_HIGH, 5);
+ if (nearPed->m_pedInObjective == this) {
+ float enemyDistSqr = (m_nearPeds[i]->GetPosition() - ourPos).MagnitudeSqr2D();
+ if (sq(closestEnemyDist) > enemyDistSqr) {
+ float enemyDist = Sqrt(enemyDistSqr);
+ weMaySeeOurEnemy = true;
+ closestPedDist = enemyDist;
+ closestEnemyDist = enemyDist;
+ pedToFearFrom = m_nearPeds[i];
+ }
+ } else if (!nearPed->GetWeapon()->IsTypeMelee() && !weMaySeeOurEnemy) {
+ float nearPedDistSqr = (m_nearPeds[i]->GetPosition() - ourPos).MagnitudeSqr2D();
+ if (sq(closestPedDist) > nearPedDistSqr) {
+ weMaySeeOurEnemy = true;
+ closestPedDist = Sqrt(nearPedDistSqr);
+ pedToFearFrom = m_nearPeds[i];
+ }
+ }
}
}
}
}
}
- } else if (collideWith->m_pedStats->m_defendWeakness <= 1.5f || heIsMissionChar
-#ifdef VC_PED_PORTS
- || m_pedStats->m_defendWeakness <= collideWith->m_pedStats->m_defendWeakness
-#endif
- ) {
- // He looks us and we're not at his right side
- if (heLooksToUs && DotProduct(posDiff,collideWith->GetRight()) > 0.0f) {
- CVector moveForce = GetRight();
- moveForce.z += 0.1f;
- ApplyMoveForce(moveForce);
- if (collideWith->m_nMoveState != PEDMOVE_RUN && collideWith->m_nMoveState != PEDMOVE_SPRINT)
- animToPlay = ANIM_HIT_LEFT;
- else
- animToPlay = ANIM_SHOT_LEFT_PARTIAL;
- } else if (heLooksToUs) {
- CVector moveForce = GetRight() * -1.0f;
- moveForce.z += 0.1f;
- ApplyMoveForce(moveForce);
- if (collideWith->m_nMoveState != PEDMOVE_RUN && collideWith->m_nMoveState != PEDMOVE_SPRINT)
- animToPlay = ANIM_HIT_RIGHT;
- else
- animToPlay = ANIM_SHOT_RIGHT_PARTIAL;
- } else {
- if (collideWith->m_nMoveState != PEDMOVE_RUN && collideWith->m_nMoveState != PEDMOVE_SPRINT)
- animToPlay = ANIM_HIT_BACK;
- else
- animToPlay = ANIM_SHOT_BACK_PARTIAL;
- }
-
- if (collideWith->IsPedInControl() && CTimer::GetTimeInMilliseconds() > collideWith->m_nPedStateTimer) {
- animAssoc = CAnimManager::BlendAnimation(collideWith->GetClump(), ASSOCGRP_STD, animToPlay, 8.0f);
- animAssoc->flags |= ASSOC_FADEOUTWHENDONE;
- collideWith->m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 1000;
- if (m_nPedState == PED_ATTACK)
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_FIGHT_PUNCH_39, 0.0f);
- }
- } else {
- // We're at his right side
- if (DotProduct(posDiff, collideWith->GetRight()) <= 0.0f) {
- CVector moveForce = GetRight() * -1.0f;
- moveForce.z += 0.1f;
- ApplyMoveForce(moveForce);
- if (heLooksToUs)
- animToPlay = ANIM_KO_SPIN_L;
- else
- animToPlay = ANIM_KD_RIGHT;
- } else {
- CVector moveForce = GetRight();
- moveForce.z += 0.1f;
- ApplyMoveForce(moveForce);
- if (heLooksToUs)
- animToPlay = ANIM_KO_SPIN_R;
- else
- animToPlay = ANIM_KD_LEFT;
- }
-
- if (m_nPedState == PED_ATTACK && collideWith->IsPedInControl())
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_FIGHT_PUNCH_39, 0.0f);
-
- collideWith->SetFall(3000, animToPlay, 0);
- }
- } else {
- if (!IsPedInControl())
- return;
-
- if (collideWith->m_nMoveState == PEDMOVE_NONE || collideWith->m_nMoveState == PEDMOVE_STILL)
- return;
-
- if (m_nPedType != collideWith->m_nPedType || m_nPedType == PEDTYPE_CIVMALE || m_nPedType == PEDTYPE_CIVFEMALE) {
-
- if (!weAreMissionChar && heLooksToUs && m_pedStats->m_fear > 100 - collideWith->m_pedStats->m_temper) {
-
- if (CGeneral::GetRandomNumber() & 1 && CTimer::GetTimeInMilliseconds() < m_nPedStateTimer){
- SetEvasiveStep(collideWith, 2);
- m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 3000;
- } else if (collideWith->m_nMoveState > PEDMOVE_WALK) {
- waitTime = 2000;
- SetWaitState(WAITSTATE_PLAYANIM_DUCK, &waitTime);
- }
- }
- } else if (heLooksToUs
- && collideWith->m_nPedState != PED_STEP_AWAY
- && m_nPedState != PED_STEP_AWAY
- && CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) {
-
- SetEvasiveStep(collideWith, 1);
- m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 3000;
}
}
-
- if (IsPlayer()) {
- SetLookFlag(collideWith, true);
- SetLookTimer(800);
- }
- } else {
- bool isRunning = m_nMoveState == PEDMOVE_RUN || m_nMoveState == PEDMOVE_SPRINT;
- SetFindPathAndFlee(collideWith, 5000, !isRunning);
- }
-}
-
-void
-CPed::CreateDeadPedMoney(void)
-{
- if (!CGame::nastyGame)
- return;
-
- int mi = GetModelIndex();
-
- if ((mi >= MI_COP && mi <= MI_FIREMAN) || CharCreatedBy == MISSION_CHAR || bInVehicle)
- return;
-
- int money = CGeneral::GetRandomNumber() % 60;
- if (money < 10)
- return;
-
- if (money == 43)
- money = 700;
-
- int pickupCount = money / 40 + 1;
- int moneyPerPickup = money / pickupCount;
-
- for(int i = 0; i < pickupCount; i++) {
- // (CGeneral::GetRandomNumber() % 256) * PI / 128 gives a float up to something TWOPI-ish.
- float pickupX = 1.5f * Sin((CGeneral::GetRandomNumber() % 256) * PI / 128) + GetPosition().x;
- float pickupY = 1.5f * Cos((CGeneral::GetRandomNumber() % 256) * PI / 128) + 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));
- }
- }
-}
-
-void
-CPed::CreateDeadPedWeaponPickups(void)
-{
- bool found = false;
- float angleToPed;
- CVector pickupPos;
-
- if (bInVehicle)
- return;
-
- for(int i = 0; i < WEAPONTYPE_TOTAL_INVENTORY_WEAPONS; i++) {
-
- eWeaponType weapon = GetWeapon(i).m_eWeaponType;
- int weaponAmmo = GetWeapon(i).m_nAmmoTotal;
- if (weapon == WEAPONTYPE_UNARMED || weapon == WEAPONTYPE_DETONATOR || weaponAmmo == 0)
- continue;
-
- angleToPed = i * 1.75f;
- pickupPos = GetPosition();
- pickupPos.x += 1.5f * Sin(angleToPed);
- pickupPos.y += 1.5f * Cos(angleToPed);
- pickupPos.z = CWorld::FindGroundZFor3DCoord(pickupPos.x, pickupPos.y, pickupPos.z, &found) + 0.5f;
-
- CVector pedPos = GetPosition();
- pedPos.z += 0.3f;
-
- CVector pedToPickup = pickupPos - pedPos;
- float distance = pedToPickup.Magnitude();
-
- // outer edge of pickup
- distance = (distance + 0.3f) / distance;
- CVector pickupPos2 = pedPos;
- pickupPos2 += distance * pedToPickup;
-
- // pickup must be on ground and line to its edge must be clear
- if (!found || CWorld::GetIsLineOfSightClear(pickupPos2, pedPos, true, false, false, false, false, false, false)) {
- // otherwise try another position (but disregard second check apparently)
- angleToPed += 3.14f;
- pickupPos = GetPosition();
- pickupPos.x += 1.5f * Sin(angleToPed);
- pickupPos.y += 1.5f * Cos(angleToPed);
- pickupPos.z = CWorld::FindGroundZFor3DCoord(pickupPos.x, pickupPos.y, pickupPos.z, &found) + 0.5f;
- }
- if (found)
- CPickups::GenerateNewOne_WeaponType(pickupPos, weapon, PICKUP_ONCE_TIMEOUT, Min(weaponAmmo, AmmoForWeapon_OnStreet[weapon]));
- }
- ClearWeapons();
-}
-
-void
-CPed::SetAttackTimer(uint32 time)
-{
- if (CTimer::GetTimeInMilliseconds() > m_attackTimer)
- m_attackTimer = Max(m_shootTimer, CTimer::GetTimeInMilliseconds()) + time;
-}
-
-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);
- m_vehEnterType = vehEnterType;
- if (m_vehEnterType == CAR_DOOR_LF) {
- if (veh->pDriver && veh->pDriver->IsPlayer())
- veh->SetStatus(STATUS_PLAYER_DISABLED);
- else
- veh->SetStatus(STATUS_ABANDONED);
- }
- RemoveInCarAnims();
- SetMoveState(PEDMOVE_NONE);
- LineUpPedWithCar(LINE_UP_TO_CAR_START);
- m_pVehicleAnim = nil;
- m_nPedState = PED_DRAG_FROM_CAR;
- bChangedSeat = false;
- bWillBeQuickJacked = quickJack;
-
- SetHeading(m_fRotationCur);
-
- Say(SOUND_PED_CAR_JACKED);
- SetRadioStation();
- veh->m_nGettingOutFlags |= GetCarDoorFlag(m_vehEnterType);
-}
-
-void
-CPed::SetBuyIceCream(void)
-{
- if (m_nPedState == PED_BUY_ICECREAM || !IsPedInControl())
- return;
-
- if (!m_carInObjective)
- return;
-
-#ifdef FIX_ICECREAM
-
- // Simulating BuyIceCream
- CPed* driver = m_carInObjective->pDriver;
- if (driver) {
- m_nPedState = PED_BUY_ICECREAM;
- bFindNewNodeAfterStateRestore = true;
- SetObjectiveTimer(8000);
- SetChat(driver, 8000);
- driver->SetChat(this, 8000);
- return;
- }
-#endif
-
- // Side of the Ice Cream van
- m_fRotationDest = m_carInObjective->GetForward().Heading() - HALFPI;
-
- if (Abs(m_fRotationDest - m_fRotationCur) < HALFPI) {
- m_standardTimer = CTimer::GetTimeInMilliseconds() + 3000;
- m_nPedState = PED_BUY_ICECREAM;
- }
-}
-
-void
-CPed::SetChat(CEntity *chatWith, uint32 time)
-{
- if(m_nPedState != PED_CHAT)
- SetStoredState();
-
- m_nPedState = PED_CHAT;
- SetMoveState(PEDMOVE_STILL);
-#if defined VC_PED_PORTS || defined FIX_BUGS
- m_lookTimer = 0;
#endif
- SetLookFlag(chatWith, true);
- m_standardTimer = CTimer::GetTimeInMilliseconds() + time;
- m_lookTimer = CTimer::GetTimeInMilliseconds() + 3000;
-}
-
-void
-CPed::SetDead(void)
-{
- bUsesCollision = false;
-
- m_fHealth = 0.0f;
- if (m_nPedState == PED_DRIVING)
- bIsVisible = false;
-
- m_nPedState = PED_DEAD;
- m_pVehicleAnim = nil;
- m_pCollidingEntity = nil;
-
- CWeaponInfo *weapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
- RemoveWeaponModel(weapon->m_nModelId);
-
- m_currentWeapon = WEAPONTYPE_UNARMED;
- CEventList::RegisterEvent(EVENT_INJURED_PED, EVENT_ENTITY_PED, this, nil, 250);
- if (this != FindPlayerPed()) {
- CreateDeadPedWeaponPickups();
- CreateDeadPedMoney();
- }
-
- m_bloodyFootprintCountOrDeathTime = CTimer::GetTimeInMilliseconds();
- m_deadBleeding = false;
- bDoBloodyFootprints = false;
- bVehExitWillBeInstant = false;
- CEventList::RegisterEvent(EVENT_DEAD_PED, EVENT_ENTITY_PED, this, nil, 1000);
-}
-
-void
-CPed::SetSeek(CEntity *seeking, float distanceToCountDone)
-{
- if (!IsPedInControl())
- return;
-
- if (m_nPedState == PED_SEEK_ENTITY && m_pSeekTarget == seeking)
- return;
-
- if (!seeking)
- return;
-
- if (m_nPedState != PED_SEEK_ENTITY)
- SetStoredState();
-
- m_nPedState = PED_SEEK_ENTITY;
- m_distanceToCountSeekDone = distanceToCountDone;
- m_pSeekTarget = seeking;
- m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget);
- SetMoveState(PEDMOVE_STILL);
-}
-
-void
-CPed::SetSeek(CVector pos, float distanceToCountDone)
-{
- if (!IsPedInControl()
- || (m_nPedState == PED_SEEK_POS && m_vecSeekPos.x == pos.x && m_vecSeekPos.y == pos.y))
- return;
-
- if (GetWeapon()->m_eWeaponType == WEAPONTYPE_M16
- || GetWeapon()->m_eWeaponType == WEAPONTYPE_AK47
- || GetWeapon()->m_eWeaponType == WEAPONTYPE_SNIPERRIFLE
- || GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER
- || GetWeapon()->m_eWeaponType == WEAPONTYPE_SHOTGUN) {
- ClearPointGunAt();
- }
-
- if (m_nPedState != PED_SEEK_POS)
- SetStoredState();
-
- m_nPedState = PED_SEEK_POS;
- m_distanceToCountSeekDone = distanceToCountDone;
- m_vecSeekPos = pos;
-}
-
-void
-CPed::DeadPedMakesTyresBloody(void)
-{
- int minX = CWorld::GetSectorIndexX(GetPosition().x - 2.0f);
- if (minX < 0) minX = 0;
- int minY = CWorld::GetSectorIndexY(GetPosition().y - 2.0f);
- if (minY < 0) minY = 0;
- int maxX = CWorld::GetSectorIndexX(GetPosition().x + 2.0f);
- if (maxX > NUMSECTORS_X-1) maxX = NUMSECTORS_X-1;
- int maxY = CWorld::GetSectorIndexY(GetPosition().y + 2.0f);
- if (maxY > NUMSECTORS_Y-1) maxY = NUMSECTORS_Y-1;
-
- CWorld::AdvanceCurrentScanCode();
-
- for (int curY = minY; curY <= maxY; curY++) {
- for (int curX = minX; curX <= maxX; curX++) {
- CSector *sector = CWorld::GetSector(curX, curY);
- MakeTyresMuddySectorList(sector->m_lists[ENTITYLIST_VEHICLES]);
- MakeTyresMuddySectorList(sector->m_lists[ENTITYLIST_VEHICLES_OVERLAP]);
- }
- }
-}
+ int16 lastVehicle;
+ CEntity* vehicles[8];
+ CWorld::FindObjectsInRange(ourPos, 20.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];
-void
-CPed::Die(void)
-{
- // UNUSED: This is a perfectly empty function.
-}
+ CPed *driver = nearVeh->pDriver;
+ if (driver) {
-uint8
-CPed::DoesLOSBulletHitPed(CColPoint &colPoint)
-{
+ // BUG: Same bug as above. Fixed at the bottom of function.
+ flagsOfSomePed = CPedType::GetFlag(driver->m_nPedType);
+ if (CPedType::GetFlag(driver->m_nPedType) & fearFlags) {
+ if (driver->m_fHealth > 0.0f && OurPedCanSeeThisOne(nearVeh->pDriver)) {
+ // FIX: Taken from VC
#ifdef FIX_BUGS
- return 1;
+ float driverDistSqr = (driver->GetPosition() - ourPos).MagnitudeSqr2D();
#else
- uint8 retVal = 2;
-
- float headZ = GetNodePosition(PED_HEAD).z;
-
- if (m_nPedState == PED_FALL)
- retVal = 1;
-
- float colZ = colPoint.point.z;
- if (colZ < headZ)
- retVal = 1;
-
- if (headZ + 0.2f <= colZ)
- retVal = 0;
-
- return retVal;
+ float driverDistSqr = (CVector2D(ourPos) - explosionPos).MagnitudeSqr();
#endif
-}
-
-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 {
- bCrouchWhenShooting = false;
- bKindaStayInSamePlace = false;
- bIsDucking = 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;
- }
-
- bool justDucked = false;
- CVehicle *foundVeh = nil;
- float maxDist = 225.0f;
- bIsDucking = false;
- bCrouchWhenShooting = false;
- if (CTimer::GetTimeInMilliseconds() > m_leaveCarTimer) {
- CVector pos = GetPosition();
- int16 lastVehicle;
- CEntity *vehicles[8];
- 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->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 (sq(closestPedDist) > driverDistSqr) {
+ closestPedDist = Sqrt(driverDistSqr);
+ pedToFearFrom = nearVeh->pDriver;
+ }
+ }
}
}
}
- 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)
- && CWorld::GetIsLineOfSightClear(GetPosition(), duckPos, 1, 0, 0, 1, 0, 0, 0)) {
- 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;
-
- // BUG? Shouldn't we register the reference?
- m_pSeekTarget = foundVeh;
- ClearPointGunAt();
- } else {
- m_duckAndCoverTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(10000, 15000);
- bDuckAndCover = false;
- }
- } else {
- bDuckAndCover = false;
- }
- }
-
- if (!justDucked && !bDuckAndCover)
- return false;
-
- if (!Seek())
- 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);
- return false;
-}
-
-void
-CPed::EndFight(uint8 endType)
-{
- if (m_nPedState != PED_FIGHT)
- return;
+ m_threatEntity = pedToFearFrom;
+ if (m_threatEntity)
+ m_threatEntity->RegisterReference((CEntity **) &m_threatEntity);
- m_curFightMove = FIGHTMOVE_NULL;
- RestorePreviousState();
- CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FIGHT_IDLE);
- if (animAssoc)
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+#ifdef FIX_BUGS
+ if (pedToFearFrom)
+ flagsOfSomePed = CPedType::GetFlag(((CPed*)m_threatEntity)->m_nPedType);
+ else
+ flagsOfSomePed = 0;
+#endif
- switch (endType) {
- case ENDFIGHT_NORMAL:
- CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 8.0f);
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT2_IDLE, 8.0f);
- break;
- case ENDFIGHT_WITH_A_STEP:
- CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 1.0f);
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_WALK_START, 8.0f);
- break;
- case ENDFIGHT_FAST:
- CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 8.0f);
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT2_IDLE, 8.0f)->speed = 2.0f;
- break;
- default:
- break;
+ return flagsOfSomePed;
}
- m_nWaitTimer = 0;
}
void
-CPed::EnterCar(void)
-{
- if (IsNotInWreckedVehicle() && m_fHealth > 0.0f) {
- CVehicle *veh = (CVehicle*)m_pSeekTarget;
-
- // Not used.
- // CVector posForDoor = GetPositionToOpenCarDoor(veh, m_vehEnterType);
-
- if (veh->CanPedOpenLocks(this)) {
- if (m_vehEnterType && m_pVehicleAnim) {
- veh->ProcessOpenDoor(m_vehEnterType, m_pVehicleAnim->animId, m_pVehicleAnim->currentTime);
- }
- }
- bIsInTheAir = false;
- LineUpPedWithCar(LINE_UP_TO_CAR_START);
- } else {
- QuitEnteringCar();
- SetDie(ANIM_KO_SHOT_FRONT1, 4.0f, 0.0f);
- }
-}
-
-uint8
-CPed::GetNearestTrainPedPosition(CVehicle *train, CVector &enterPos)
+CPed::SetLookFlag(float direction, bool keepTryingToLook)
{
- CVector enterStepOffset;
- CVehicleModelInfo *trainModel = (CVehicleModelInfo *)CModelInfo::GetModelInfo(train->GetModelIndex());
- CMatrix trainMat = CMatrix(train->GetMatrix());
- CVector leftEntryPos, rightEntryPos, midEntryPos;
- float distLeftEntry, distRightEntry, distMidEntry;
-
- // enterStepOffset = vecPedCarDoorAnimOffset;
- enterStepOffset = CVector(1.5f, 0.0f, 0.0f);
-
- if (train->pPassengers[TRAIN_POS_LEFT_ENTRY]) {
- distLeftEntry = 999.0f;
- } else {
- leftEntryPos = trainModel->m_positions[TRAIN_POS_LEFT_ENTRY] - enterStepOffset;
- leftEntryPos = Multiply3x3(trainMat, leftEntryPos);
- leftEntryPos += train->GetPosition();
- distLeftEntry = (leftEntryPos - GetPosition()).Magnitude();
- }
-
- if (train->pPassengers[TRAIN_POS_MID_ENTRY]) {
- distMidEntry = 999.0f;
- } else {
- midEntryPos = trainModel->m_positions[TRAIN_POS_MID_ENTRY] - enterStepOffset;
- midEntryPos = Multiply3x3(trainMat, midEntryPos);
- midEntryPos += train->GetPosition();
- distMidEntry = (midEntryPos - GetPosition()).Magnitude();
- }
-
- if (train->pPassengers[TRAIN_POS_RIGHT_ENTRY]) {
- distRightEntry = 999.0f;
- } else {
- rightEntryPos = trainModel->m_positions[TRAIN_POS_RIGHT_ENTRY] - enterStepOffset;
- rightEntryPos = Multiply3x3(trainMat, rightEntryPos);
- rightEntryPos += train->GetPosition();
- distRightEntry = (rightEntryPos - GetPosition()).Magnitude();
- }
-
- if (distMidEntry < distLeftEntry) {
- if (distMidEntry < distRightEntry) {
- enterPos = midEntryPos;
- m_vehEnterType = TRAIN_POS_MID_ENTRY;
- } else {
- enterPos = rightEntryPos;
- m_vehEnterType = TRAIN_POS_RIGHT_ENTRY;
+ if (m_lookTimer < CTimer::GetTimeInMilliseconds()) {
+ bIsLooking = true;
+ bIsRestoringLook = false;
+ m_pLookTarget = nil;
+ m_fLookDirection = direction;
+ m_lookTimer = 0;
+ bKeepTryingToLook = keepTryingToLook;
+ if (m_nPedState != PED_DRIVING) {
+ m_pedIK.m_flags &= ~CPedIK::LOOKAROUND_HEAD_ONLY;
}
- } else if (distRightEntry < distLeftEntry) {
- enterPos = rightEntryPos;
- m_vehEnterType = TRAIN_POS_RIGHT_ENTRY;
- } else {
- enterPos = leftEntryPos;
- m_vehEnterType = TRAIN_POS_LEFT_ENTRY;
}
-
- return 1;
-}
-
-uint8
-CPed::GetNearestTrainDoor(CVehicle *train, CVector &doorPos)
-{
- GetNearestTrainPedPosition(train, doorPos);
-/*
- // Not used.
- CVehicleModelInfo* trainModel = (CVehicleModelInfo*)CModelInfo::GetModelInfo(train->m_modelIndex);
- CMatrix trainMat = CMatrix(train->GetMatrix());
-
- doorPos = trainModel->m_positions[m_vehEnterType];
- doorPos.x -= 1.5f;
- doorPos = Multiply3x3(trainMat, doorPos);
- doorPos += train->GetPosition();
-*/
- return 1;
}
void
-CPed::LineUpPedWithTrain(void)
+CPed::SetLookFlag(CEntity *target, bool keepTryingToLook)
{
- 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;
+ if (m_lookTimer < CTimer::GetTimeInMilliseconds()) {
+ bIsLooking = true;
+ bIsRestoringLook = false;
+ m_pLookTarget = target;
+ m_pLookTarget->RegisterReference((CEntity**)&m_pLookTarget);
+ m_fLookDirection = 999999.0f;
+ m_lookTimer = 0;
+ bKeepTryingToLook = keepTryingToLook;
+ if (m_nPedState != PED_DRIVING) {
+ m_pedIK.m_flags &= ~CPedIK::LOOKAROUND_HEAD_ONLY;
}
- 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::EnterTrain(void)
-{
- LineUpPedWithTrain();
-}
-
-void
-CPed::ExitTrain(void)
-{
- LineUpPedWithTrain();
-}
-
-void
-CPed::ExitCar(void)
-{
- if (!m_pVehicleAnim)
- return;
-
- AnimationId exitAnim = (AnimationId) m_pVehicleAnim->animId;
- float animTime = m_pVehicleAnim->currentTime;
-
- m_pMyVehicle->ProcessOpenDoor(m_vehEnterType, exitAnim, animTime);
+CPed::ClearLookFlag(void) {
+ if (bIsLooking) {
+ bIsLooking = false;
+ bIsRestoringLook = true;
+ bShakeFist = false;
- if (m_pSeekTarget) {
- // Car is upside down
- if (m_pMyVehicle->GetUp().z > -0.8f) {
- if (exitAnim == ANIM_CAR_CLOSE_RHS || exitAnim == ANIM_CAR_CLOSE_LHS || animTime > 0.3f)
- LineUpPedWithCar(LINE_UP_TO_CAR_END);
- else
- LineUpPedWithCar((m_pMyVehicle->GetModelIndex() == MI_DODO ? LINE_UP_TO_CAR_END : LINE_UP_TO_CAR_START));
- } else {
- LineUpPedWithCar(LINE_UP_TO_CAR_END);
- }
- }
+ m_pedIK.m_flags &= ~CPedIK::LOOKAROUND_HEAD_ONLY;
+ if (IsPlayer())
+ m_lookTimer = CTimer::GetTimeInMilliseconds() + 2000;
+ else
+ m_lookTimer = CTimer::GetTimeInMilliseconds() + 4000;
- // 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() < 0.04f) {
- foundPed = m_nearPeds[i];
- break;
- }
+ if (m_nPedState == PED_LOOK_HEADING || m_nPedState == PED_LOOK_ENTITY) {
+ ClearLook();
}
- if (foundPed && animTime > 0.4f && foundPed->IsPedInControl())
- foundPed->SetFall(1000, ANIM_KO_SKID_FRONT, 1);
}
}
void
-CPed::Fall(void)
+FinishFuckUCB(CAnimBlendAssociation *animAssoc, void *arg)
{
- if (m_getUpTimer != UINT32_MAX && CTimer::GetTimeInMilliseconds() > m_getUpTimer
-#ifdef VC_PED_PORTS
- && bIsStanding
-#endif
- )
- ClearFall();
+ CPed *ped = (CPed*)arg;
- // VC plays animations ANIM_STD_FALL_ONBACK and ANIM_STD_FALL_ONFRONT in here, which doesn't exist in III.
+ if (animAssoc->animId == ANIM_FUCKU && ped->GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED)
+ ped->RemoveWeaponModel(0);
}
void
-CPed::Fight(void)
+CPed::MoveHeadToLook(void)
{
- CAnimBlendAssociation *currentAssoc, *animAssoc;
- bool hasShoppingBags, punchOnly, canKick, canKneeHead, canRoundhouse;
- float angleToFace, nextAngle;
- bool goForward = false;
- int nextFightMove;
-
- switch (m_curFightMove) {
- case FIGHTMOVE_NULL:
- return;
- case FIGHTMOVE_IDLE2NORM:
- m_curFightMove = FIGHTMOVE_NULL;
- RestorePreviousState();
+ CVector lookPos;
- // FIX: Uninitialized
- currentAssoc = nil;
- break;
- case FIGHTMOVE_IDLE:
- currentAssoc = nil;
- break;
- default:
- currentAssoc = RpAnimBlendClumpGetAssociation(GetClump(), tFightMoves[m_curFightMove].animId);
- break;
+ if (m_lookTimer && CTimer::GetTimeInMilliseconds() > m_lookTimer) {
+ ClearLookFlag();
+ } else if (m_nPedState == PED_DRIVING) {
+ m_pedIK.m_flags |= CPedIK::LOOKAROUND_HEAD_ONLY;
}
- if (!bIsAttacking && IsPlayer()) {
- if (currentAssoc) {
- currentAssoc->blendDelta = -1000.0f;
- currentAssoc->flags |= ASSOC_DELETEFADEDOUT;
- currentAssoc->flags &= ~ASSOC_RUNNING;
- }
- if (m_takeAStepAfterAttack)
- EndFight(ENDFIGHT_WITH_A_STEP);
- else
- EndFight(ENDFIGHT_FAST);
-
- } else if (currentAssoc && m_fightState > FIGHTSTATE_MOVE_FINISHED) {
- float animTime = currentAssoc->currentTime;
- FightMove &curMove = tFightMoves[m_curFightMove];
- if (curMove.hitLevel != HITLEVEL_NULL && animTime > curMove.startFireTime && animTime <= curMove.endFireTime && m_fightState >= FIGHTSTATE_NO_MOVE) {
-
- CVector touchingNodePos(0.0f, 0.0f, 0.0f);
-
- switch (m_curFightMove) {
- case FIGHTMOVE_STDPUNCH:
- case FIGHTMOVE_PUNCHHOOK:
- case FIGHTMOVE_BODYBLOW:
- TransformToNode(touchingNodePos, PED_HANDR);
- break;
- case FIGHTMOVE_IDLE:
- case FIGHTMOVE_SHUFFLE_F:
- break;
- case FIGHTMOVE_KNEE:
- TransformToNode(touchingNodePos, PED_LOWERLEGR);
- break;
- case FIGHTMOVE_HEADBUTT:
- TransformToNode(touchingNodePos, PED_HEAD);
- break;
- case FIGHTMOVE_PUNCHJAB:
- TransformToNode(touchingNodePos, PED_HANDL);
- break;
- case FIGHTMOVE_KICK:
- case FIGHTMOVE_LONGKICK:
- case FIGHTMOVE_ROUNDHOUSE:
- case FIGHTMOVE_GROUNDKICK:
- TransformToNode(touchingNodePos, PED_FOOTR);
- break;
- }
-
- if (m_curFightMove == FIGHTMOVE_PUNCHJAB) {
- touchingNodePos += 0.1f * GetForward();
- } else if (m_curFightMove == FIGHTMOVE_PUNCHHOOK) {
- touchingNodePos += 0.22f * GetForward();
- }
- FightStrike(touchingNodePos);
- m_fightButtonPressure = 0;
- return;
- }
-
- if (curMove.hitLevel != HITLEVEL_NULL) {
- if (animTime > curMove.endFireTime) {
- if (IsPlayer())
- currentAssoc->speed = 1.0f;
- else
- currentAssoc->speed = 0.8f;
- }
-
- if (IsPlayer() && !nPlayerInComboMove) {
- if (curMove.comboFollowOnTime > 0.0f && m_fightButtonPressure != 0 && animTime > curMove.comboFollowOnTime) {
-
- // Notice that it increases fight move index, because we're in combo!
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[++m_curFightMove].animId, 8.0f);
- animAssoc->SetFinishCallback(FinishFightMoveCB, this);
- animAssoc->SetCurrentTime(0.1f * animAssoc->hierarchy->totalLength);
- m_fightButtonPressure = 0;
- nPlayerInComboMove = 1;
- }
- }
- } else {
- if (curMove.startFireTime > 0.0f && m_curFightMove != FIGHTMOVE_SHUFFLE_F && animTime > curMove.startFireTime) {
- if (IsPlayer())
- currentAssoc->speed = 1.3f;
- else
- currentAssoc->speed = 0.8f;
- }
- }
- } else if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED) {
- EndFight(ENDFIGHT_FAST);
-
- } else if (m_fightButtonPressure != 0) {
- bool canAffectMultiplePeople = true;
- nextAngle = m_fRotationCur;
- bool kickGround = false;
- float angleForGroundKick = 0.0f;
- CPed *pedOnGround = nil;
-
- Say(SOUND_PED_ATTACK);
-
- if (IsPlayer()) {
- canRoundhouse = false;
- punchOnly = false;
- canKick = true;
- nextFightMove = (m_fightButtonPressure > 190 ? FIGHTMOVE_HEADBUTT : FIGHTMOVE_KNEE);
- hasShoppingBags = false;
- canKneeHead = true;
- nPlayerInComboMove = 0;
- } else {
- nextFightMove = (m_fightButtonPressure > 120 ? FIGHTMOVE_HEADBUTT : FIGHTMOVE_KNEE);
- uint16 pedFeatures = m_pedStats->m_flags;
- punchOnly = pedFeatures & STAT_PUNCH_ONLY;
- canRoundhouse = pedFeatures & STAT_CAN_ROUNDHOUSE;
- canKneeHead = pedFeatures & STAT_CAN_KNEE_HEAD;
- canKick = pedFeatures & STAT_CAN_KICK;
- hasShoppingBags = pedFeatures & STAT_SHOPPING_BAGS;
- }
-
- // Attack isn't scripted, find the victim
- if (IsPlayer() || !m_pedInObjective) {
-
- for (int i = 0; i < m_numNearPeds; i++) {
-
- CPed *nearPed = m_nearPeds[i];
- float nearPedDist = (nearPed->GetPosition() - GetPosition()).Magnitude();
- if (nearPedDist < 3.0f) {
- float angleToFace = CGeneral::GetRadianAngleBetweenPoints(
- nearPed->GetPosition().x, nearPed->GetPosition().y,
- GetPosition().x, GetPosition().y);
-
- nextAngle = CGeneral::LimitRadianAngle(angleToFace);
- m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur);
-
- float neededTurn = Abs(nextAngle - m_fRotationCur);
- if (neededTurn > PI)
- neededTurn = TWOPI - neededTurn;
-
- if (!nearPed->OnGroundOrGettingUp()) {
-
- if (nearPedDist < 0.8f && neededTurn < DEGTORAD(75.0f) && canKneeHead) {
- canAffectMultiplePeople = false;
- } else if (nearPedDist >= 1.3f || neededTurn >= DEGTORAD(55.0f) || hasShoppingBags) {
-
- if (nearPedDist < 1.7f
- && neededTurn < DEGTORAD(35.0f)
- && (canKick || hasShoppingBags)) {
+ if (m_pLookTarget) {
- nextFightMove = FIGHTMOVE_KICK;
- if (hasShoppingBags) {
- nextFightMove = FIGHTMOVE_ROUNDHOUSE;
- } else if (canRoundhouse && CGeneral::GetRandomNumber() & 1) {
- nextFightMove = FIGHTMOVE_ROUNDHOUSE;
- }
- canAffectMultiplePeople = false;
- } else if (nearPedDist < 2.0f && neededTurn < DEGTORAD(30.0f) && canKick) {
- canAffectMultiplePeople = false;
- nextFightMove = FIGHTMOVE_LONGKICK;
- } else if (neededTurn < DEGTORAD(30.0f)) {
- goForward = true;
- }
- } else {
- nextFightMove += 2; // Makes it 6 or 7
- if (punchOnly)
- nextFightMove = FIGHTMOVE_PUNCHJAB;
+ if (!bShakeFist && GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED) {
- canAffectMultiplePeople = false;
- }
- } else if (!CGame::nastyGame
- || nearPedDist >= 1.3f
- || neededTurn >= DEGTORAD(55.0f)
- || punchOnly) {
-
- if (nearPedDist > 0.8f
- && nearPedDist < 3.0f
- && neededTurn < DEGTORAD(30.0f)) {
- goForward = true;
- }
+ CAnimBlendAssociation *fuckUAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FUCKU);
+ if (fuckUAssoc) {
- } else if (nearPed->m_nPedState != PED_DEAD || pedOnGround) {
- if (!nearPed->IsPedHeadAbovePos(-0.3f)) {
- canAffectMultiplePeople = false;
- nextFightMove = FIGHTMOVE_GROUNDKICK;
- }
+ float animTime = fuckUAssoc->currentTime;
+ if (animTime > 4.0f / 30.0f && animTime - fuckUAssoc->timeStep > 4.0f / 30.0f) {
- } else {
- pedOnGround = nearPed;
- kickGround = true;
- angleForGroundKick = nextAngle;
- }
- }
+ bool lookingToCop = false;
+ if (m_pLookTarget->GetModelIndex() == MI_POLICE
+ || m_pLookTarget->IsPed() && ((CPed*)m_pLookTarget)->m_nPedType == PEDTYPE_COP) {
- if (!canAffectMultiplePeople) {
- m_fRotationDest = nextAngle;
- if (IsPlayer()) {
- m_fRotationCur = m_fRotationDest;
- m_lookTimer = 0;
- SetLookFlag(nearPed, true);
- SetLookTimer(1500);
+ lookingToCop = true;
}
- break;
- }
- }
- } else {
- // Because we're in a scripted fight with some particular ped.
- canAffectMultiplePeople = false;
-
- float fightingPedDist = (m_pedInObjective->GetPosition() - GetPosition()).Magnitude();
- if (hasShoppingBags) {
- if (fightingPedDist >= 1.7f)
- nextFightMove = FIGHTMOVE_SHUFFLE_F;
- else
- nextFightMove = FIGHTMOVE_ROUNDHOUSE;
-
- } else if (punchOnly) {
- if (fightingPedDist >= 1.3f)
- nextFightMove = FIGHTMOVE_SHUFFLE_F;
- else
- nextFightMove = FIGHTMOVE_PUNCHJAB;
-
- } else if (fightingPedDist >= 3.0f) {
- nextFightMove = FIGHTMOVE_STDPUNCH;
-
- } else {
- angleToFace = CGeneral::GetRadianAngleBetweenPoints(
- m_pedInObjective->GetPosition().x,
- m_pedInObjective->GetPosition().y,
- GetPosition().x,
- GetPosition().y);
-
- nextAngle = CGeneral::LimitRadianAngle(angleToFace);
- m_fRotationDest = nextAngle;
- m_fRotationCur = m_fRotationDest;
- if (!m_pedInObjective->OnGroundOrGettingUp()) {
-
- if (fightingPedDist >= 0.8f || !canKneeHead) {
-
- if (fightingPedDist >= 1.3f) {
-
- if (fightingPedDist < 1.7f && canKick) {
- nextFightMove = FIGHTMOVE_KICK;
- if (canRoundhouse && CGeneral::GetRandomNumber() & 1)
- nextFightMove = FIGHTMOVE_ROUNDHOUSE;
-
- } else if (fightingPedDist < 2.0f && canKick) {
- nextFightMove += 5; // Makes it 9 or 10
- } else {
- nextFightMove = FIGHTMOVE_SHUFFLE_F;
+ if (IsPlayer() && (m_pedStats->m_temper >= 52 || lookingToCop)) {
+ AddWeaponModel(MI_FINGERS);
+ ((CPlayerPed*)this)->AnnoyPlayerPed(true);
- }
- } else {
- nextFightMove += 2; // Makes it 6 or 7
- }
+ } else if ((CGeneral::GetRandomNumber() & 3) == 0) {
+ AddWeaponModel(MI_FINGERS);
}
- } else if (!CGame::nastyGame
- || fightingPedDist >= 1.3f
- || m_pedInObjective->IsPlayer()
- || m_pedInObjective->m_nPedState != PED_DEAD && m_pedInObjective->IsPedHeadAbovePos(-0.3f)) {
- nextFightMove = FIGHTMOVE_IDLE;
- } else {
- nextFightMove = FIGHTMOVE_GROUNDKICK;
}
}
}
- if (canAffectMultiplePeople) {
- if (kickGround && IsPlayer()) {
- m_fRotationDest = angleForGroundKick;
- nextFightMove = FIGHTMOVE_GROUNDKICK;
- m_fRotationCur = m_fRotationDest;
- m_lookTimer = 0;
- SetLookFlag(pedOnGround, true);
- SetLookTimer(1500);
- } else if (goForward) {
- nextFightMove = FIGHTMOVE_SHUFFLE_F;
- } else {
- nextFightMove = FIGHTMOVE_STDPUNCH;
- }
+ if (m_pLookTarget->IsPed()) {
+ ((CPed*)m_pLookTarget)->m_pedIK.GetComponentPosition((RwV3d*) &lookPos, PED_MID);
+ } else {
+ lookPos = m_pLookTarget->GetPosition();
}
- if (nextFightMove != FIGHTMOVE_IDLE) {
- m_curFightMove = nextFightMove;
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 4.0f);
-
- animAssoc->SetFinishCallback(FinishFightMoveCB, this);
- if (m_fightState == FIGHTSTATE_MOVE_FINISHED && animAssoc->currentTime != 0.0f) {
- animAssoc->SetCurrentTime(0.0f);
- animAssoc->SetRun();
+ if (!m_pedIK.LookAtPosition(lookPos)) {
+ if (!bKeepTryingToLook) {
+ ClearLookFlag();
}
- m_fightButtonPressure = 0;
+ return;
}
- m_fightState = FIGHTSTATE_NO_MOVE;
- } else if (m_takeAStepAfterAttack && m_curFightMove != FIGHTMOVE_SHUFFLE_F
-#ifndef FIX_BUGS
- && CheckForPedsOnGroundToAttack(this, nil) == 4) {
-#else
- && CheckForPedsOnGroundToAttack(this, nil) == PED_IN_FRONT_OF_ATTACKER) {
-#endif
- m_curFightMove = FIGHTMOVE_SHUFFLE_F;
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), tFightMoves[m_curFightMove].animId);
- if (animAssoc) {
- animAssoc->SetCurrentTime(0.0f);
- animAssoc->blendDelta = 4.0f;
- animAssoc->SetRun();
- } else {
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 32.0f);
- }
- animAssoc->SetFinishCallback(FinishFightMoveCB, this);
- m_fightState = FIGHTSTATE_NO_MOVE;
- m_fightButtonPressure = 0;
- m_takeAStepAfterAttack = false;
+ if (!bShakeFist || bIsAimingGun || bIsRestoringGun)
+ return;
- } else if (m_takeAStepAfterAttack) {
- EndFight(ENDFIGHT_FAST);
+ if (m_lookTimer - CTimer::GetTimeInMilliseconds() >= 1000)
+ return;
- } else if (m_curFightMove == FIGHTMOVE_IDLE) {
- if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
- EndFight(ENDFIGHT_NORMAL);
- }
+ bool notRocketLauncher = false;
+ bool notTwoHanded = false;
+ AnimationId animToPlay = NUM_ANIMS;
- } else {
- m_curFightMove = FIGHTMOVE_IDLE;
- if (IsPlayer())
- m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 500;
- else
- m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 2000;
- }
-}
+ if (!GetWeapon()->IsType2Handed())
+ notTwoHanded = true;
-// 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++) {
+ if (notTwoHanded && GetWeapon()->m_eWeaponType != WEAPONTYPE_ROCKETLAUNCHER)
+ notRocketLauncher = true;
- CPathNode *testNode = &ThePaths.m_pathNodes[ThePaths.ConnectedNode(i + node->firstLink)];
+ if (IsPlayer() && notRocketLauncher) {
- if (testNode && testNode != closeNode && testNode != closeNode2) {
- CVector2D posDiff(ped->m_vecSeekPos - testNode->GetPosition());
- float dist = posDiff.MagnitudeSqr();
+ if (m_pLookTarget->IsPed()) {
- if (farDist.MagnitudeSqr() > dist) {
+ if (m_pedStats->m_temper >= 49 && ((CPed*)m_pLookTarget)->m_nPedType != PEDTYPE_COP) {
- if (closeDist.MagnitudeSqr() <= dist) {
- ped->m_pNextPathNode = closeNode;
- closeDist = posDiff;
+ // FIX: Unreachable and meaningless condition
+#ifndef FIX_BUGS
+ if (m_pedStats->m_temper < 47)
+#endif
+ animToPlay = ANIM_FIGHT_PPUNCH;
} else {
- ped->m_pNextPathNode = (closeNode2 ? closeNode2 : testNode);
- farDist = posDiff;
+ animToPlay = ANIM_FUCKU;
}
+ } else if (m_pedStats->m_temper > 49 || m_pLookTarget->GetModelIndex() == MI_POLICE) {
+ animToPlay = ANIM_FUCKU;
}
-
- if (--runCount > 0)
- SelectClosestNodeForSeek(ped, testNode, closeDist, farDist, closeNode, (closeNode2 ? closeNode2 : testNode), runCount);
+ } else if (notRocketLauncher && (CGeneral::GetRandomNumber() & 1)) {
+ animToPlay = ANIM_FUCKU;
}
- }
-}
-bool
-CPed::FindBestCoordsFromNodes(CVector unused, CVector *bestCoords)
-{
- if (m_pNextPathNode || !bUsePedNodeSeek)
- return false;
-
- 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);
-
- // Above function decided that going to the next node is more logical than seeking the object.
- if (m_pNextPathNode) {
+ if (animToPlay != NUM_ANIMS) {
+ CAnimBlendAssociation *newAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animToPlay, 4.0f);
- CVector pathToNextNode = m_pNextPathNode->GetPosition() - ourPos;
- if (pathToNextNode.MagnitudeSqr2D() < seekPosDist.MagnitudeSqr()) {
- *bestCoords = m_pNextPathNode->GetPosition();
- return true;
+ if (newAssoc) {
+ newAssoc->flags |= ASSOC_FADEOUTWHENDONE;
+ newAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ if (newAssoc->animId == ANIM_FUCKU)
+ newAssoc->SetDeleteCallback(FinishFuckUCB, this);
+ }
}
- m_pNextPathNode = nil;
+ bShakeFist = false;
+ return;
+ } else if (999999.0f == m_fLookDirection) {
+ ClearLookFlag();
+ } else if (!m_pedIK.LookInDirection(m_fLookDirection, 0.0f)) {
+ if (!bKeepTryingToLook)
+ ClearLookFlag();
}
-
- return false;
}
void
-CPed::FinishDieAnimCB(CAnimBlendAssociation *animAssoc, void *arg)
+CPed::RestoreHeadPosition(void)
{
- CPed *ped = (CPed*)arg;
-
- if (ped->bIsPedDieAnimPlaying)
- ped->bIsPedDieAnimPlaying = false;
+ if (m_pedIK.RestoreLookAt()) {
+ bIsRestoringLook = false;
+ }
}
void
-CPed::FinishFightMoveCB(CAnimBlendAssociation *animAssoc, void *arg)
+CPed::SetAimFlag(float angle)
{
- CPed *ped = (CPed*)arg;
-
- if (tFightMoves[ped->m_curFightMove].animId == animAssoc->animId) {
- ped->m_fightState = FIGHTSTATE_MOVE_FINISHED;
- animAssoc->blendDelta = -1000.0f;
- }
+ bIsAimingGun = true;
+ bIsRestoringGun = false;
+ m_fLookDirection = angle;
+ m_lookTimer = 0;
+ m_pLookTarget = nil;
+ m_pSeekTarget = nil;
+ if (CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_bCanAimWithArm)
+ m_pedIK.m_flags |= CPedIK::AIMS_WITH_ARM;
+ else
+ m_pedIK.m_flags &= ~CPedIK::AIMS_WITH_ARM;
}
void
-CPed::FinishHitHeadCB(CAnimBlendAssociation *animAssoc, void *arg)
+CPed::SetAimFlag(CEntity *to)
{
- CPed *ped = (CPed*)arg;
-
- if (animAssoc) {
- animAssoc->blendDelta = -4.0f;
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- }
-
- if (ped->m_nPedState == PED_JUMP)
- ped->RestorePreviousState();
-
- ped->bIsLanding = false;
+ bIsAimingGun = true;
+ bIsRestoringGun = false;
+ m_pLookTarget = to;
+ m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);
+ m_pSeekTarget = to;
+ m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget);
+ m_lookTimer = 0;
}
void
-CPed::FinishJumpCB(CAnimBlendAssociation *animAssoc, void *arg)
+CPed::ClearAimFlag(void)
{
- CPed *ped = (CPed*)arg;
-
- ped->bResetWalkAnims = true;
- ped->bIsLanding = false;
+ if (bIsAimingGun) {
+ bIsAimingGun = false;
+ bIsRestoringGun = true;
+ m_pedIK.m_flags &= ~CPedIK::AIMS_WITH_ARM;
+#if defined VC_PED_PORTS || defined FIX_BUGS
+ m_lookTimer = 0;
+#endif
+ }
- animAssoc->blendDelta = -1000.0f;
+ if (IsPlayer())
+ ((CPlayerPed*)this)->m_fFPSMoveHeading = 0.0f;
}
void
-CPed::FinishLaunchCB(CAnimBlendAssociation *animAssoc, void *arg)
+CPed::AimGun(void)
{
- CPed *ped = (CPed*)arg;
-
- if (ped->m_nPedState != PED_JUMP)
- return;
-
- CVector forward(0.15f * ped->GetForward() + ped->GetPosition());
- forward.z += CModelInfo::GetModelInfo(ped->GetModelIndex())->GetColModel()->spheres->center.z + 0.25f;
-
- CEntity *obstacle = CWorld::TestSphereAgainstWorld(forward, 0.25f, nil, true, true, false, true, false, false);
- if (!obstacle) {
- // Forward of forward
- forward += 0.15f * ped->GetForward();
- forward.z += 0.15f;
- obstacle = CWorld::TestSphereAgainstWorld(forward, 0.25f, nil, true, true, false, true, false, false);
- }
-
- if (obstacle) {
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
-
- // ANIM_HIT_WALL in VC (which makes more sense)
- CAnimBlendAssociation *handsCoverAssoc = CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_HANDSCOWER, 8.0f);
- handsCoverAssoc->flags &= ~ASSOC_FADEOUTWHENDONE;
- handsCoverAssoc->SetFinishCallback(FinishHitHeadCB, ped);
- ped->bIsLanding = true;
- return;
- }
-
- float velocityFromAnim = 0.1f;
- CAnimBlendAssociation *sprintAssoc = RpAnimBlendClumpGetAssociation(ped->GetClump(), ANIM_SPRINT);
-
- if (sprintAssoc) {
- velocityFromAnim = 0.05f * sprintAssoc->blendAmount + 0.17f;
- } else {
- CAnimBlendAssociation *runAssoc = RpAnimBlendClumpGetAssociation(ped->GetClump(), ANIM_RUN);
- if (runAssoc) {
- velocityFromAnim = 0.07f * runAssoc->blendAmount + 0.1f;
- }
- }
-
- if (ped->IsPlayer()
-#ifdef VC_PED_PORTS
- || ped->m_pedInObjective && ped->m_pedInObjective->IsPlayer()
-#endif
- )
- ped->ApplyMoveForce(0.0f, 0.0f, 8.5f);
- else
- ped->ApplyMoveForce(0.0f, 0.0f, 4.5f);
-
- if (sq(velocityFromAnim) > ped->m_vecMoveSpeed.MagnitudeSqr2D()
-#ifdef VC_PED_PORTS
- || ped->m_pCurrentPhysSurface
-#endif
- ) {
+ CVector vector;
-#ifdef FREE_CAM
- if (TheCamera.Cams[0].Using3rdPersonMouseCam() && !CCamera::bFreeCam) {
-#else
- if (TheCamera.Cams[0].Using3rdPersonMouseCam()) {
-#endif
- float fpsAngle = ped->WorkOutHeadingForMovingFirstPerson(ped->m_fRotationCur);
- ped->m_vecMoveSpeed.x = -velocityFromAnim * Sin(fpsAngle);
- ped->m_vecMoveSpeed.y = velocityFromAnim * Cos(fpsAngle);
+ if (m_pSeekTarget) {
+ if (m_pSeekTarget->IsPed()) {
+ ((CPed*)m_pSeekTarget)->m_pedIK.GetComponentPosition(vector, PED_MID);
} else {
- ped->m_vecMoveSpeed.x = -velocityFromAnim * Sin(ped->m_fRotationCur);
- ped->m_vecMoveSpeed.y = velocityFromAnim * Cos(ped->m_fRotationCur);
- }
-#ifdef VC_PED_PORTS
- if (ped->m_pCurrentPhysSurface) {
- ped->m_vecMoveSpeed.x += ped->m_pCurrentPhysSurface->m_vecMoveSpeed.x;
- ped->m_vecMoveSpeed.y += ped->m_pCurrentPhysSurface->m_vecMoveSpeed.y;
+ vector = m_pSeekTarget->GetPosition();
}
-#endif
- }
-
- ped->bIsStanding = false;
- ped->bIsInTheAir = true;
- animAssoc->blendDelta = -1000.0f;
- CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_JUMP_GLIDE);
-
- if (ped->bDoBloodyFootprints) {
- CVector bloodPos(0.0f, 0.0f, 0.0f);
- ped->TransformToNode(bloodPos, PED_FOOTL);
-
- bloodPos.z -= 0.1f;
- bloodPos += 0.2f * ped->GetForward();
-
- CShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpBloodPoolTex, &bloodPos,
- 0.26f * ped->GetForward().x,
- 0.26f * ped->GetForward().y,
- 0.14f * ped->GetRight().x,
- 0.14f * ped->GetRight().y,
- 255, 255, 0, 0, 4.0f, 3000, 1.0f);
-
- bloodPos = CVector(0.0f, 0.0f, 0.0f);
- ped->TransformToNode(bloodPos, PED_FOOTR);
+ Say(SOUND_PED_ATTACK);
- bloodPos.z -= 0.1f;
- bloodPos += 0.2f * ped->GetForward();
- CShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpBloodPoolTex, &bloodPos,
- 0.26f * ped->GetForward().x,
- 0.26f * ped->GetForward().y,
- 0.14f * ped->GetRight().x,
- 0.14f * ped->GetRight().y,
- 255, 255, 0, 0, 4.0f, 3000, 1.0f);
+ bCanPointGunAtTarget = m_pedIK.PointGunAtPosition(vector);
+ if (m_pLookTarget != m_pSeekTarget) {
+ SetLookFlag(m_pSeekTarget, true);
+ }
- if (ped->m_bloodyFootprintCountOrDeathTime <= 40) {
- ped->m_bloodyFootprintCountOrDeathTime = 0;
- ped->bDoBloodyFootprints = false;
+ } else {
+ if (IsPlayer()) {
+ bCanPointGunAtTarget = m_pedIK.PointGunInDirection(m_fLookDirection, ((CPlayerPed*)this)->m_fFPSMoveHeading);
} else {
- ped->m_bloodyFootprintCountOrDeathTime -= 40;
+ bCanPointGunAtTarget = m_pedIK.PointGunInDirection(m_fLookDirection, 0.0f);
}
}
}
void
-CPed::FinishedWaitCB(CAnimBlendAssociation *animAssoc, void *arg)
+CPed::RestoreGunPosition(void)
{
- CPed *ped = (CPed*)arg;
-
- ped->m_nWaitTimer = 0;
- ped->RestoreHeadingRate();
- ped->Wait();
+ if (bIsLooking) {
+ m_pedIK.m_flags &= ~CPedIK::LOOKAROUND_HEAD_ONLY;
+ bIsRestoringGun = false;
+ } else if (m_pedIK.RestoreGunPosn()) {
+ bIsRestoringGun = false;
+ } else {
+ if (IsPlayer())
+ ((CPlayerPed*)this)->m_fFPSMoveHeading = 0.0f;
+ }
}
void
-CPed::Wait(void)
+CPed::ScanForInterestingStuff(void)
{
- AnimationId mustHaveAnim = NUM_ANIMS;
- CAnimBlendAssociation *animAssoc;
- CPed *pedWeLook;
-
- if (DyingOrDead()) {
- m_nWaitState = WAITSTATE_FALSE;
- RestoreHeadingRate();
+ if (!IsPedInControl())
return;
- }
-
- switch (m_nWaitState) {
-
- case WAITSTATE_TRAFFIC_LIGHTS:
- if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
- if (CTrafficLights::LightForPeds() == PED_LIGHTS_WALK) {
- m_nWaitState = WAITSTATE_FALSE;
- SetMoveState(PEDMOVE_WALK);
- }
- }
- break;
-
- case WAITSTATE_CROSS_ROAD:
- if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
- if (CGeneral::GetRandomNumber() & 1 || !m_nWaitTimer)
- m_nWaitState = WAITSTATE_FALSE;
- else
- SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, nil);
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_HBHB);
- if (animAssoc) {
- animAssoc->blendDelta = -8.0f;
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- }
- }
- break;
+ if (m_objective != OBJECTIVE_NONE)
+ return;
- case WAITSTATE_CROSS_ROAD_LOOK:
- if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
- m_nWaitState = WAITSTATE_FALSE;
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_ROAD_CROSS);
- if (animAssoc) {
- animAssoc->blendDelta = -8.0f;
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- }
- }
- break;
+ if (CharCreatedBy == MISSION_CHAR)
+ return;
- case WAITSTATE_DOUBLEBACK:
- if (CTimer::GetTimeInMilliseconds() <= m_nWaitTimer) {
- uint32 timeLeft = m_nWaitTimer - CTimer::GetTimeInMilliseconds();
- if (timeLeft < 2500 && timeLeft > 2000) {
- m_nWaitTimer -= 500;
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_XPRESS_SCRATCH, 4.0f);
- }
- } else {
- m_nWaitState = WAITSTATE_FALSE;
- SetMoveState(PEDMOVE_WALK);
- }
- break;
+ LookForSexyPeds();
+ LookForSexyCars();
+ if (LookForInterestingNodes())
+ return;
- case WAITSTATE_HITWALL:
- if (CTimer::GetTimeInMilliseconds() <= m_nWaitTimer) {
- if (m_collidingThingTimer > CTimer::GetTimeInMilliseconds()) {
- m_collidingThingTimer = CTimer::GetTimeInMilliseconds() + 2500;
- }
- } else {
- m_nWaitState = WAITSTATE_FALSE;
- }
- break;
+ if (m_nPedType == PEDTYPE_CRIMINAL && m_hitRecoverTimer < CTimer::GetTimeInMilliseconds()) {
+ if (CGeneral::GetRandomNumber() % 100 < 10) {
+ int mostExpensiveVehAround = -1;
+ int bestMonetaryValue = 0;
- case WAITSTATE_TURN180:
- if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
- m_nWaitState = WAITSTATE_FALSE;
- SetMoveState(PEDMOVE_WALK);
- m_fRotationCur = m_fRotationCur + PI;
- if (m_nPedState == PED_INVESTIGATE)
- ClearInvestigateEvent();
- }
+ CVector pos = GetPosition();
+ int16 lastVehicle;
+ CEntity *vehicles[8];
+ CWorld::FindObjectsInRange(pos, 10.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false);
- if (m_collidingThingTimer > CTimer::GetTimeInMilliseconds()) {
- m_collidingThingTimer = CTimer::GetTimeInMilliseconds() + 2500;
- }
- break;
+ for (int i = 0; i < lastVehicle; i++) {
+ CVehicle* veh = (CVehicle*)vehicles[i];
- case WAITSTATE_SURPRISE:
- if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
- if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_HIT_WALL)) {
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_XPRESS_SCRATCH, 4.0f);
- animAssoc->SetFinishCallback(FinishedWaitCB, this);
- m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 5000;
- } else {
- m_nWaitState = WAITSTATE_FALSE;
+ if (veh->VehicleCreatedBy != MISSION_VEHICLE) {
+ if (veh->m_vecMoveSpeed.Magnitude() <= 0.1f && veh->IsVehicleNormal()
+ && veh->IsCar() && bestMonetaryValue < veh->pHandling->nMonetaryValue) {
+ mostExpensiveVehAround = i;
+ bestMonetaryValue = veh->pHandling->nMonetaryValue;
+ }
}
}
- break;
-
- case WAITSTATE_STUCK:
- if (CTimer::GetTimeInMilliseconds() <= m_nWaitTimer)
- break;
-
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_TIRED);
-
- if (!animAssoc)
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_TURN_180);
- if (!animAssoc)
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_XPRESS_SCRATCH);
- if (!animAssoc)
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_ROAD_CROSS);
-
- if (animAssoc) {
- if (animAssoc->IsPartial()) {
- animAssoc->blendDelta = -8.0f;
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- } else {
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 4.0f);
- }
-
- if (animAssoc->animId == ANIM_TURN_180) {
- m_fRotationCur = CGeneral::LimitRadianAngle(PI + m_fRotationCur);
- m_nWaitState = WAITSTATE_FALSE;
- SetMoveState(PEDMOVE_WALK);
- m_nStoredMoveState = PEDMOVE_NONE;
- m_panicCounter = 0;
- return;
- }
+ if (bestMonetaryValue > 2000 && mostExpensiveVehAround != -1 && vehicles[mostExpensiveVehAround]) {
+ SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, vehicles[mostExpensiveVehAround]);
+ m_hitRecoverTimer = CTimer::GetTimeInMilliseconds() + 5000;
+ return;
}
+ m_hitRecoverTimer = CTimer::GetTimeInMilliseconds() + 5000;
+ } else if (m_objective != OBJECTIVE_MUG_CHAR && !(CGeneral::GetRandomNumber() & 7)) {
+ CPed *charToMug = nil;
+ for (int i = 0; i < m_numNearPeds; ++i) {
+ CPed *nearPed = m_nearPeds[i];
- AnimationId animToPlay;
-
- switch (CGeneral::GetRandomNumber() & 3) {
- case 0:
- animToPlay = ANIM_ROAD_CROSS;
- break;
- case 1:
- animToPlay = ANIM_IDLE_TIRED;
- break;
- case 2:
- animToPlay = ANIM_XPRESS_SCRATCH;
- break;
- case 3:
- animToPlay = ANIM_TURN_180;
- break;
- default:
+ if ((nearPed->GetPosition() - GetPosition()).MagnitudeSqr() > sq(7.0f))
break;
- }
-
- animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animToPlay, 4.0f);
-
- if (animToPlay == ANIM_TURN_180)
- animAssoc->SetFinishCallback(FinishedWaitCB, this);
-
- m_nWaitTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(1500, 5000);
- break;
-
- case WAITSTATE_LOOK_ABOUT:
- if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
- m_nWaitState = WAITSTATE_FALSE;
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_HBHB);
- if (animAssoc) {
- animAssoc->blendDelta = -8.0f;
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- }
- }
- break;
-
- case WAITSTATE_PLAYANIM_HANDSUP:
- mustHaveAnim = ANIM_HANDSUP;
-
- case WAITSTATE_PLAYANIM_HANDSCOWER:
- if (mustHaveAnim == NUM_ANIMS)
- mustHaveAnim = ANIM_HANDSCOWER;
-
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), mustHaveAnim);
- pedWeLook = (CPed*) m_pLookTarget;
-
- if ((!m_pLookTarget || !m_pLookTarget->IsPed() || pedWeLook->m_pPointGunAt)
- && m_nPedState != PED_FLEE_ENTITY
- && m_nPedState != PED_ATTACK
- && CTimer::GetTimeInMilliseconds() <= m_nWaitTimer
- && animAssoc) {
-
- TurnBody();
- } else {
- m_nWaitState = WAITSTATE_FALSE;
- m_nWaitTimer = 0;
- if (m_pLookTarget && m_pLookTarget->IsPed()) {
-
- if (m_nPedState != PED_FLEE_ENTITY && m_nPedState != PED_ATTACK) {
-
- if (m_pedStats->m_fear <= 100 - pedWeLook->m_pedStats->m_temper) {
-
- if (GetWeapon()->IsTypeMelee()) {
-#ifdef VC_PED_PORTS
- if(m_pedStats->m_flags & STAT_GUN_PANIC) {
-#endif
- SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, m_pLookTarget);
- if (m_nPedState == PED_FLEE_ENTITY || m_nPedState == PED_FLEE_POS) {
-
- bUsePedNodeSeek = true;
- m_pNextPathNode = nil;
- }
- if (m_nMoveState != PEDMOVE_RUN)
- SetMoveState(PEDMOVE_WALK);
-
- if (m_nPedType != PEDTYPE_COP) {
- ProcessObjective();
- SetMoveState(PEDMOVE_WALK);
- }
-#ifdef VC_PED_PORTS
- } else {
- SetObjective(OBJECTIVE_NONE);
- SetWanderPath(CGeneral::GetRandomNumberInRange(0.0f, 8.0f));
- }
-#endif
- } else {
- SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, m_pLookTarget);
- SetObjectiveTimer(20000);
- }
- } else {
- SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, m_pLookTarget);
- if (m_nPedState == PED_FLEE_ENTITY || m_nPedState == PED_FLEE_POS)
- {
- bUsePedNodeSeek = true;
- m_pNextPathNode = nil;
- }
- SetMoveState(PEDMOVE_RUN);
- Say(SOUND_PED_FLEE_RUN);
- }
- }
- }
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), mustHaveAnim);
- if (animAssoc) {
- animAssoc->blendDelta = -4.0f;
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- }
- }
- break;
- case WAITSTATE_PLAYANIM_COWER:
- mustHaveAnim = ANIM_HANDSCOWER;
-
- case WAITSTATE_PLAYANIM_DUCK:
- if (mustHaveAnim == NUM_ANIMS)
- mustHaveAnim = ANIM_DUCK_DOWN;
-
- case WAITSTATE_PLAYANIM_TAXI:
- if (mustHaveAnim == NUM_ANIMS)
- mustHaveAnim = ANIM_IDLE_TAXI;
-
- case WAITSTATE_PLAYANIM_CHAT:
- if (mustHaveAnim == NUM_ANIMS)
- mustHaveAnim = ANIM_IDLE_CHAT;
- if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), mustHaveAnim);
- if (animAssoc) {
- animAssoc->blendDelta = -4.0f;
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- }
- m_nWaitState = WAITSTATE_FALSE;
- }
-#ifdef VC_PED_PORTS
- else if (m_nWaitState == WAITSTATE_PLAYANIM_TAXI) {
- if (m_pedInObjective) {
- if (m_objective == OBJECTIVE_GOTO_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT) {
-
- // VC also calls CleanUpOldReference here for old LookTarget.
- m_pLookTarget = m_pedInObjective;
- m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);
- TurnBody();
- }
+ if ((nearPed->m_nPedType == PEDTYPE_CIVFEMALE || nearPed->m_nPedType == PEDTYPE_CIVMALE
+ || nearPed->m_nPedType == PEDTYPE_CRIMINAL || nearPed->m_nPedType == PEDTYPE_UNUSED1
+ || nearPed->m_nPedType == PEDTYPE_PROSTITUTE)
+ && nearPed->CharCreatedBy != MISSION_CHAR
+ && nearPed->IsPedShootable()
+ && nearPed->m_objective != OBJECTIVE_MUG_CHAR) {
+ charToMug = nearPed;
+ break;
}
}
-#endif
- break;
+ if (charToMug)
+ SetObjective(OBJECTIVE_MUG_CHAR, charToMug);
- case WAITSTATE_FINISH_FLEE:
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_TIRED);
- if (animAssoc) {
- if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 4.0f);
- int timer = 2000;
- m_nWaitState = WAITSTATE_FALSE;
- SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, &timer);
- }
- } else {
- m_nWaitState = WAITSTATE_FALSE;
- }
- break;
- default:
- break;
+ m_hitRecoverTimer = CTimer::GetTimeInMilliseconds() + 5000;
+ }
}
- if(!m_nWaitState)
- RestoreHeadingRate();
-}
-
-bool
-CPed::Seek(void)
-{
- float distanceToCountItDone = m_distanceToCountSeekDone;
- eMoveState nextMove = PEDMOVE_NONE;
-
- if (m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER) {
-
- if (m_nPedState != PED_EXIT_TRAIN && m_nPedState != PED_ENTER_TRAIN && m_nPedState != PED_SEEK_IN_BOAT &&
- m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER && m_objective != OBJECTIVE_SOLICIT_VEHICLE && !bDuckAndCover) {
-
- if ((!m_pedInObjective || !m_pedInObjective->bInVehicle)
- && !((CTimer::GetFrameCounter() + (m_randomSeed % 256) + 17) & 7)) {
-
- CEntity *obstacle = CWorld::TestSphereAgainstWorld(m_vecSeekPos, 0.4f, nil,
- false, true, false, false, false, false);
+ if (m_nPedState == PED_WANDER_PATH) {
+#ifndef VC_PED_PORTS
+ if (CTimer::GetTimeInMilliseconds() > m_standardTimer) {
- if (obstacle) {
- if (!obstacle->IsVehicle() || ((CVehicle*)obstacle)->m_vehType == VEHICLE_TYPE_CAR) {
- distanceToCountItDone = 2.5f;
- } else {
- CVehicleModelInfo *vehModel = (CVehicleModelInfo *)CModelInfo::GetModelInfo(obstacle->GetModelIndex());
- float yLength = vehModel->GetColModel()->boundingBox.max.y
- - vehModel->GetColModel()->boundingBox.min.y;
- distanceToCountItDone = yLength * 0.55f;
+ // += 2 is weird
+ for (int i = 0; i < m_numNearPeds; i += 2) {
+ if (m_nearPeds[i]->m_nPedState == PED_WANDER_PATH && WillChat(m_nearPeds[i])) {
+ if (CGeneral::GetRandomNumberInRange(0, 100) >= 100)
+ m_standardTimer = CTimer::GetTimeInMilliseconds() + 30000;
+ else {
+ if ((GetPosition() - m_nearPeds[i]->GetPosition()).Magnitude() >= 1.8f) {
+ m_standardTimer = CTimer::GetTimeInMilliseconds() + 30000;
+ } else if (CanSeeEntity(m_nearPeds[i])) {
+ int time = CGeneral::GetRandomNumber() % 4000 + 10000;
+ SetChat(m_nearPeds[i], time);
+ m_nearPeds[i]->SetChat(this, time);
+ return;
+ }
}
}
}
}
- }
-
- if (!m_pSeekTarget && m_nPedState == PED_SEEK_ENTITY)
- ClearSeek();
-
- float seekPosDist = (m_vecSeekPos - GetPosition()).Magnitude2D();
- if (seekPosDist < 2.0f || m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT) {
-
- if (m_objective == OBJECTIVE_FOLLOW_CHAR_IN_FORMATION) {
-
- if (m_pedInObjective->m_nMoveState != PEDMOVE_STILL)
- nextMove = m_pedInObjective->m_nMoveState;
- } else
- nextMove = PEDMOVE_WALK;
-
- } else if (m_objective != OBJECTIVE_FOLLOW_CHAR_IN_FORMATION) {
-
- if (m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS || m_objective == OBJECTIVE_RUN_TO_AREA || bIsRunning)
- nextMove = PEDMOVE_RUN;
- else
- nextMove = PEDMOVE_WALK;
-
- } else if (seekPosDist <= 2.0f) {
-
- if (m_pedInObjective->m_nMoveState != PEDMOVE_STILL)
- nextMove = m_pedInObjective->m_nMoveState;
-
- } else {
- nextMove = PEDMOVE_RUN;
- }
-
- if (m_nPedState == PED_SEEK_ENTITY) {
- if (m_pSeekTarget->IsPed()) {
- if (((CPed*)m_pSeekTarget)->bInVehicle)
- distanceToCountItDone += 2.0f;
- }
- }
-
- if (seekPosDist >= distanceToCountItDone) {
- if (bIsRunning)
- nextMove = PEDMOVE_RUN;
-
- if (CTimer::GetTimeInMilliseconds() <= m_nPedStateTimer) {
-
- if (m_actionX != 0.0f && m_actionY != 0.0f) {
-
- m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(
- m_actionX, m_actionY,
- GetPosition().x, GetPosition().y);
-
- float neededTurn = Abs(m_fRotationDest - m_fRotationCur);
-
- if (neededTurn > PI)
- neededTurn = TWOPI - neededTurn;
+#else
+ if (CGeneral::GetRandomNumberInRange(0.0f, 1.0f) < 0.5f) {
+ if (CTimer::GetTimeInMilliseconds() > m_standardTimer) {
+ for (int i = 0; i < m_numNearPeds; i ++) {
+ if (m_nearPeds[i] && m_nearPeds[i]->m_nPedState == PED_WANDER_PATH) {
+ if ((GetPosition() - m_nearPeds[i]->GetPosition()).Magnitude() < 1.8f
+ && CanSeeEntity(m_nearPeds[i])
+ && m_nearPeds[i]->CanSeeEntity(this)
+ && WillChat(m_nearPeds[i])) {
- if (neededTurn > HALFPI) {
- if (seekPosDist >= 1.0f) {
- if (seekPosDist < 2.0f) {
- if (bIsRunning)
- nextMove = PEDMOVE_RUN;
- else
- nextMove = PEDMOVE_WALK;
+ int time = CGeneral::GetRandomNumber() % 4000 + 10000;
+ SetChat(m_nearPeds[i], time);
+ m_nearPeds[i]->SetChat(this, time);
+ return;
}
- } else {
- nextMove = PEDMOVE_STILL;
}
}
-
- CVector2D moveDist(GetPosition().x - m_actionX, GetPosition().y - m_actionY);
- if (moveDist.Magnitude() < 0.5f) {
- m_nPedStateTimer = 0;
- m_actionX = 0;
- m_actionY = 0;
- }
}
} else {
- m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(
- m_vecSeekPos.x, m_vecSeekPos.y,
- GetPosition().x, GetPosition().y);
-
- float neededTurn = Abs(m_fRotationDest - m_fRotationCur);
-
- if (neededTurn > PI)
- neededTurn = TWOPI - neededTurn;
-
- if (neededTurn > HALFPI) {
- if (seekPosDist >= 1.0 && neededTurn <= DEGTORAD(135.0f)) {
- if (seekPosDist < 2.0f)
- nextMove = PEDMOVE_WALK;
- } else {
- nextMove = PEDMOVE_STILL;
- }
- }
- }
-
- if (((m_nPedState == PED_FLEE_POS || m_nPedState == PED_FLEE_ENTITY) && m_nMoveState < nextMove)
- || (m_nPedState != PED_FLEE_POS && m_nPedState != PED_FLEE_ENTITY && m_objective != OBJECTIVE_GOTO_CHAR_ON_FOOT && m_nWaitState == WAITSTATE_FALSE)) {
-
- SetMoveState(nextMove);
- }
-
- SetMoveAnim();
- return false;
- }
-
- if ((m_objective != OBJECTIVE_FOLLOW_CHAR_IN_FORMATION || m_pedInObjective->m_nMoveState == PEDMOVE_STILL) && m_nMoveState != PEDMOVE_STILL) {
- m_nPedStateTimer = 0;
- m_actionX = 0;
- m_actionY = 0;
- }
-
- if (m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT || m_objective == OBJECTIVE_RUN_TO_AREA || m_objective == OBJECTIVE_GOTO_AREA_ANY_MEANS) {
- if (m_pNextPathNode)
- m_pNextPathNode = nil;
- else
- bScriptObjectiveCompleted = true;
-
- bUsePedNodeSeek = true;
- }
-
- if (SeekFollowingPath(nil))
- m_nCurPathNode++;
-
- return true;
-}
-
-bool
-CPed::SeekFollowingPath(CVector *unused)
-{
- return m_nCurPathNode <= m_nPathNodes && m_nPathNodes;
-}
-
-void
-CPed::Flee(void)
-{
- if (CTimer::GetTimeInMilliseconds() > m_fleeTimer && m_fleeTimer) {
- bool mayFinishFleeing = true;
- if (m_nPedState == PED_FLEE_ENTITY) {
- if ((CVector2D(GetPosition()) - ms_vec2DFleePosition).MagnitudeSqr() < sq(30.0f))
- mayFinishFleeing = false;
- }
-
- if (mayFinishFleeing) {
- eMoveState moveState = m_nMoveState;
- ClearFlee();
-
- if (m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE || m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS)
- RestorePreviousObjective();
-
- if ((m_nPedState == PED_IDLE || m_nPedState == PED_WANDER_PATH) && CGeneral::GetRandomNumber() & 1) {
- SetWaitState(moveState <= PEDMOVE_WALK ? WAITSTATE_CROSS_ROAD_LOOK : WAITSTATE_FINISH_FLEE, nil);
- }
- return;
+ m_standardTimer = CTimer::GetTimeInMilliseconds() + 200;
}
- m_fleeTimer = CTimer::GetTimeInMilliseconds() + 5000;
+#endif
}
- if (bUsePedNodeSeek) {
- CPathNode *realLastNode = nil;
- uint8 nextDirection = 0;
- uint8 curDirectionShouldBe = 9; // means not defined yet
-
- if (m_nPedStateTimer < CTimer::GetTimeInMilliseconds()
- && m_collidingThingTimer < CTimer::GetTimeInMilliseconds()) {
-
- if (m_pNextPathNode && CTimer::GetTimeInMilliseconds() > m_standardTimer) {
-
- curDirectionShouldBe = CGeneral::GetNodeHeadingFromVector(GetPosition().x - ms_vec2DFleePosition.x, GetPosition().y - ms_vec2DFleePosition.y);
- if (m_nPathDir < curDirectionShouldBe)
- m_nPathDir += 8;
+ // Parts below aren't there in VC, they're in somewhere else.
+ if (!CGame::noProstitutes && m_nPedType == PEDTYPE_PROSTITUTE && CharCreatedBy != MISSION_CHAR
+ && m_objectiveTimer < CTimer::GetTimeInMilliseconds() && !CTheScripts::IsPlayerOnAMission()) {
- int dirDiff = m_nPathDir - curDirectionShouldBe;
- if (dirDiff > 2 && dirDiff < 6) {
- realLastNode = nil;
- m_pLastPathNode = m_pNextPathNode;
- m_pNextPathNode = nil;
- }
- }
+ CVector pos = GetPosition();
+ int16 lastVehicle;
+ CEntity* vehicles[8];
+ CWorld::FindObjectsInRange(pos, CHECK_NEARBY_THINGS_MAX_DIST, true, &lastVehicle, 6, vehicles, false, true, false, false, false);
- if (m_pNextPathNode) {
- m_vecSeekPos = m_pNextPathNode->GetPosition();
- if (m_nMoveState == PEDMOVE_RUN)
- bIsRunning = true;
+ for (int i = 0; i < lastVehicle; i++) {
+ CVehicle* veh = (CVehicle*)vehicles[i];
- eMoveState moveState = m_nMoveState;
- if (Seek()) {
- realLastNode = m_pLastPathNode;
- m_pLastPathNode = m_pNextPathNode;
- m_pNextPathNode = nil;
+ if (veh->IsVehicleNormal()) {
+ if (veh->IsCar()) {
+ if ((GetPosition() - veh->GetPosition()).Magnitude() < 5.0f && veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, nil)) {
+ SetObjective(OBJECTIVE_SOLICIT_VEHICLE, veh);
+ Say(SOUND_PED_SOLICIT);
+ return;
+ }
}
- bIsRunning = false;
- SetMoveState(moveState);
- }
- }
-
- if (!m_pNextPathNode) {
- if (curDirectionShouldBe == 9) {
- curDirectionShouldBe = CGeneral::GetNodeHeadingFromVector(GetPosition().x - ms_vec2DFleePosition.x, GetPosition().y - ms_vec2DFleePosition.y);
}
- ThePaths.FindNextNodeWandering(PATH_PED, GetPosition(), &m_pLastPathNode, &m_pNextPathNode,
- curDirectionShouldBe,
- &nextDirection);
-
- if (curDirectionShouldBe < nextDirection)
- curDirectionShouldBe += 8;
-
- if (m_pNextPathNode && m_pNextPathNode != realLastNode && m_pNextPathNode != m_pLastPathNode && curDirectionShouldBe - nextDirection != 4) {
- m_nPathDir = nextDirection;
- m_standardTimer = CTimer::GetTimeInMilliseconds() + 2000;
- } else {
- bUsePedNodeSeek = false;
- SetMoveState(PEDMOVE_RUN);
- Flee();
- }
- }
- return;
- }
-
- if ((m_nPedState == PED_FLEE_ENTITY || m_nPedState == PED_ON_FIRE) && m_nPedStateTimer < CTimer::GetTimeInMilliseconds()) {
-
- float angleToFleeFromPos = CGeneral::GetRadianAngleBetweenPoints(
- GetPosition().x,
- GetPosition().y,
- ms_vec2DFleePosition.x,
- ms_vec2DFleePosition.y);
-
- m_fRotationDest = CGeneral::LimitRadianAngle(angleToFleeFromPos);
-
- if (m_fRotationCur - PI > m_fRotationDest)
- m_fRotationDest += TWOPI;
- else if (PI + m_fRotationCur < m_fRotationDest)
- m_fRotationDest -= TWOPI;
- }
-
- if (CTimer::GetTimeInMilliseconds() & 0x20) {
- //CVector forwardPos = GetPosition();
- CMatrix forwardMat(GetMatrix());
- forwardMat.GetPosition() += Multiply3x3(forwardMat, CVector(0.0f, 4.0f, 0.0f));
- CVector forwardPos = forwardMat.GetPosition();
-
- CEntity *foundEnt;
- CColPoint foundCol;
- bool found = CWorld::ProcessVerticalLine(forwardPos, forwardMat.GetPosition().z - 100.0f, foundCol, foundEnt, 1, 0, 0, 0, 1, 0, 0);
-
- if (!found || Abs(forwardPos.z - forwardMat.GetPosition().z) > 1.0f) {
- m_fRotationDest += DEGTORAD(112.5f);
- m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 2000;
- }
- }
-
- if (CTimer::GetTimeInMilliseconds() >= m_collidingThingTimer)
- return;
-
- if (!m_collidingEntityWhileFleeing)
- return;
-
- double collidingThingPriorityMult = (double)(m_collidingThingTimer - CTimer::GetTimeInMilliseconds()) * 2.0 / 2500;
-
- if (collidingThingPriorityMult <= 1.5) {
-
- double angleToFleeEntity = CGeneral::GetRadianAngleBetweenPoints(
- GetPosition().x,
- GetPosition().y,
- m_collidingEntityWhileFleeing->GetPosition().x,
- m_collidingEntityWhileFleeing->GetPosition().y);
- angleToFleeEntity = CGeneral::LimitRadianAngle(angleToFleeEntity);
-
- double angleToFleeCollidingThing = CGeneral::GetRadianAngleBetweenPoints(
- m_vecDamageNormal.x,
- m_vecDamageNormal.y,
- 0.0f,
- 0.0f);
- angleToFleeCollidingThing = CGeneral::LimitRadianAngle(angleToFleeCollidingThing);
-
- if (angleToFleeEntity - PI > angleToFleeCollidingThing)
- angleToFleeCollidingThing += TWOPI;
- else if (PI + angleToFleeEntity < angleToFleeCollidingThing)
- angleToFleeCollidingThing -= TWOPI;
-
- if (collidingThingPriorityMult <= 1.0f) {
- // Range [0.0, 1.0]
-
- float angleToFleeBoth = (angleToFleeCollidingThing + angleToFleeEntity) * 0.5f;
-
- if (m_fRotationDest - PI > angleToFleeBoth)
- angleToFleeBoth += TWOPI;
- else if (PI + m_fRotationDest < angleToFleeBoth)
- angleToFleeBoth -= TWOPI;
-
- m_fRotationDest = (1.0f - collidingThingPriorityMult) * m_fRotationDest + collidingThingPriorityMult * angleToFleeBoth;
- } else {
- // Range (1.0, 1.5]
-
- double adjustedMult = (collidingThingPriorityMult - 1.0f) * 2.0f;
- m_fRotationDest = angleToFleeEntity * (1.0 - adjustedMult) + adjustedMult * angleToFleeCollidingThing;
- }
- } else {
- m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(
- m_vecDamageNormal.x,
- m_vecDamageNormal.y,
- 0.0f,
- 0.0f);
- m_fRotationDest = CGeneral::LimitRadianAngle(m_fRotationDest);
- }
-
- m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur);
-
- if (m_fRotationCur - PI > m_fRotationDest)
- m_fRotationDest += TWOPI;
- else if (PI + m_fRotationCur < m_fRotationDest)
- m_fRotationDest -= TWOPI;
-
-}
-
-void
-CPed::FollowPath(void)
-{
- m_vecSeekPos.x = m_stPathNodeStates[m_nCurPathNode].x;
- m_vecSeekPos.y = m_stPathNodeStates[m_nCurPathNode].y;
- m_vecSeekPos.z = GetPosition().z;
-
- // Mysterious code
-/* int v4 = 0;
- int maxNodeIndex = m_nPathNodes - 1;
- if (maxNodeIndex > 0) {
- if (maxNodeIndex > 8) {
- while (v4 < maxNodeIndex - 8)
- v4 += 8;
}
-
- while (v4 < maxNodeIndex)
- v4++;
-
}
-*/
- if (Seek()) {
- m_nCurPathNode++;
- if (m_nCurPathNode == m_nPathNodes)
- RestorePreviousState();
- }
-}
-
-CVector
-CPed::GetFormationPosition(void)
-{
- 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;
- switch (m_pedFormation) {
- case FORMATION_REAR:
- formationOffset = CVector(0.0f, -1.5f, 0.0f);
- break;
- case FORMATION_REAR_LEFT:
- formationOffset = CVector(-1.5f, -1.5f, 0.0f);
- break;
- case FORMATION_REAR_RIGHT:
- formationOffset = CVector(1.5f, -1.5f, 0.0f);
- break;
- case FORMATION_FRONT_LEFT:
- formationOffset = CVector(-1.5f, 1.5f, 0.0f);
- break;
- case FORMATION_FRONT_RIGHT:
- formationOffset = CVector(1.5f, 1.5f, 0.0f);
- break;
- case FORMATION_LEFT:
- formationOffset = CVector(-1.5f, 0.0f, 0.0f);
- break;
- case FORMATION_RIGHT:
- formationOffset = CVector(1.5f, 0.0f, 0.0f);
- break;
- case FORMATION_FRONT:
- formationOffset = CVector(0.0f, 1.5f, 0.0f);
- break;
- default:
- formationOffset = CVector(0.0f, 0.0f, 0.0f);
- break;
- }
- return formationOffset + m_pedInObjective->GetPosition();
-}
-
-void
-CPed::GetNearestDoor(CVehicle *veh, CVector &posToOpen)
-{
- CVector *enterOffset = nil;
- if (m_vehEnterType == CAR_DOOR_LF && veh->pDriver
- || m_vehEnterType == CAR_DOOR_RF && veh->pPassengers[0]
- || m_vehEnterType == CAR_DOOR_LR && veh->pPassengers[1]
- || m_vehEnterType == CAR_DOOR_RR && veh->pPassengers[2])
- {
- enterOffset = &vecPedQuickDraggedOutCarAnimOffset;
- }
-
- CVector lfPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_LF);
- CVector rfPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_RF);
-
- // Left front door is closer
- if ((lfPos - GetPosition()).MagnitudeSqr2D() < (rfPos - GetPosition()).MagnitudeSqr2D()) {
-
- if (veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, enterOffset)) {
- m_vehEnterType = CAR_DOOR_LF;
- posToOpen = lfPos;
- } else if (veh->IsRoomForPedToLeaveCar(CAR_DOOR_RF, enterOffset)) {
- m_vehEnterType = CAR_DOOR_RF;
- posToOpen = rfPos;
- }
- } else {
-
- if (veh->IsRoomForPedToLeaveCar(CAR_DOOR_RF, enterOffset)) {
+ if (m_nPedType == PEDTYPE_CIVMALE || m_nPedType == PEDTYPE_CIVFEMALE) {
+ CVector pos = GetPosition();
+ int16 lastVehicle;
+ CEntity* vehicles[8];
+ CWorld::FindObjectsInRange(pos, CHECK_NEARBY_THINGS_MAX_DIST, true, &lastVehicle, 6, vehicles, false, true, false, false, false);
- CPed *rfPassenger = veh->pPassengers[0];
- if (rfPassenger && (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)) {
+ for (int i = 0; i < lastVehicle; i++) {
+ CVehicle* veh = (CVehicle*)vehicles[i];
- m_vehEnterType = CAR_DOOR_LF;
- posToOpen = lfPos;
- } else {
- m_vehEnterType = CAR_DOOR_RF;
- posToOpen = rfPos;
+ if (veh->GetModelIndex() == MI_MRWHOOP) {
+ if (veh->GetStatus() != STATUS_ABANDONED && veh->GetStatus() != STATUS_WRECKED) {
+ if ((GetPosition() - veh->GetPosition()).Magnitude() < 5.0f) {
+ SetObjective(OBJECTIVE_BUY_ICE_CREAM, veh);
+ return;
+ }
+ }
}
- } else if (veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, enterOffset)) {
- m_vehEnterType = 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_vehEnterType = CAR_DOOR_RF;
- posToOpen = GetPositionToOpenCarDoor(veh, CAR_DOOR_RF);
- return true;
- case MI_RHINO:
- default:
- break;
- }
-
- CVector2D rfPosDist(999.0f, 999.0f);
- CVector2D lrPosDist(999.0f, 999.0f);
- CVector2D rrPosDist(999.0f, 999.0f);
-
- if (!veh->pPassengers[0]
- && !(veh->m_nGettingInFlags & CAR_DOOR_FLAG_RF)
- && veh->IsRoomForPedToLeaveCar(CAR_DOOR_RF, nil)) {
-
- rfPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_RF);
- canEnter = true;
- rfPosDist = rfPos - GetPosition();
- }
- if (vehModel->m_numDoors == 4) {
- if (!veh->pPassengers[1]
- && !(veh->m_nGettingInFlags & CAR_DOOR_FLAG_LR)
- && veh->IsRoomForPedToLeaveCar(CAR_DOOR_LR, nil)) {
- lrPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_LR);
- canEnter = true;
- lrPosDist = lrPos - GetPosition();
- }
- if (!veh->pPassengers[2]
- && !(veh->m_nGettingInFlags & CAR_DOOR_FLAG_RR)
- && veh->IsRoomForPedToLeaveCar(CAR_DOOR_RR, nil)) {
- rrPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_RR);
- canEnter = true;
- rrPosDist = rrPos - GetPosition();
- }
-
- // When the door we should enter is blocked by some object.
- if (!canEnter)
- veh->ShufflePassengersToMakeSpace();
- }
-
- CVector2D nextToCompare = rfPosDist;
- posToOpen = rfPos;
- m_vehEnterType = CAR_DOOR_RF;
- if (lrPosDist.MagnitudeSqr() < nextToCompare.MagnitudeSqr()) {
- m_vehEnterType = CAR_DOOR_LR;
- posToOpen = lrPos;
- nextToCompare = lrPosDist;
- }
-
- if (rrPosDist.MagnitudeSqr() < nextToCompare.MagnitudeSqr()) {
- m_vehEnterType = CAR_DOOR_RR;
- posToOpen = rrPos;
- }
- return canEnter;
-}
-
-int
-CPed::GetNextPointOnRoute(void)
+CPed::WillChat(CPed *stranger)
{
- 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;
+ if (m_pNextPathNode && m_pLastPathNode) {
+ if (m_pNextPathNode != m_pLastPathNode && ThePaths.TestCrossesRoad(m_pNextPathNode, m_pLastPathNode)) {
+ return false;
}
}
- return nextPoint;
-}
-
-// These categories are purely random, most of ped models have no correlation. So I don't think making an enum.
-uint8
-CPed::GetPedRadioCategory(uint32 modelIndex)
-{
- switch (modelIndex) {
- case MI_MALE01:
- case MI_FEMALE03:
- case MI_PROSTITUTE2:
- case MI_WORKER1:
- case MI_MOD_MAN:
- case MI_MOD_WOM:
- case MI_ST_WOM:
- case MI_FAN_WOM:
- return 3;
- case MI_TAXI_D:
- case MI_PIMP:
- case MI_MALE02:
- case MI_FEMALE02:
- case MI_FATFEMALE01:
- case MI_FATFEMALE02:
- case MI_DOCKER1:
- case MI_WORKER2:
- case MI_FAN_MAN2:
- return 9;
- case MI_GANG01:
- case MI_GANG02:
- case MI_SCUM_MAN:
- case MI_SCUM_WOM:
- case MI_HOS_WOM:
- case MI_CONST1:
- return 1;
- case MI_GANG03:
- case MI_GANG04:
- case MI_GANG07:
- case MI_GANG08:
- case MI_CT_MAN2:
- case MI_CT_WOM2:
- case MI_B_MAN3:
- case MI_SHOPPER3:
- return 4;
- case MI_GANG05:
- case MI_GANG06:
- case MI_GANG11:
- case MI_GANG12:
- case MI_CRIMINAL02:
- case MI_B_WOM2:
- case MI_ST_MAN:
- case MI_HOS_MAN:
- return 5;
- case MI_FATMALE01:
- case MI_LI_MAN2:
- case MI_SHOPPER1:
- case MI_CAS_MAN:
- return 6;
- case MI_PROSTITUTE:
- case MI_P_WOM2:
- case MI_LI_WOM2:
- case MI_B_WOM3:
- case MI_CAS_WOM:
- return 2;
- case MI_P_WOM1:
- case MI_DOCKER2:
- case MI_STUD_MAN:
- return 7;
- case MI_CT_MAN1:
- case MI_CT_WOM1:
- case MI_LI_MAN1:
- case MI_LI_WOM1:
- case MI_B_MAN1:
- case MI_B_MAN2:
- case MI_B_WOM1:
- case MI_SHOPPER2:
- case MI_STUD_WOM:
- return 8;
- default:
- return 0;
- }
-}
-
-// Some kind of VC leftover I think
-int
-CPed::GetWeaponSlot(eWeaponType weaponType)
-{
- if (HasWeapon(weaponType))
- return weaponType;
- else
- return -1;
-}
-
-void
-CPed::GoToNearestDoor(CVehicle *veh)
-{
- CVector posToOpen;
- GetNearestDoor(veh, posToOpen);
- SetSeek(posToOpen, 0.5f);
- SetMoveState(PEDMOVE_RUN);
-}
-
-bool
-CPed::HaveReachedNextPointOnRoute(float distToCountReached)
-{
- if ((m_nextRoutePointPos - GetPosition()).Magnitude2D() >= distToCountReached)
+ if (m_nSurfaceTouched == SURFACE_TARMAC)
+ return false;
+ if (stranger == this)
+ return false;
+ if (m_nPedType == stranger->m_nPedType)
+ return true;
+ if (m_nPedType == PEDTYPE_CRIMINAL)
+ return false;
+ if ((IsGangMember() || stranger->IsGangMember()) && m_nPedType != stranger->m_nPedType)
return false;
-
- m_routePointsPassed += m_routePointsBeingPassed;
return true;
}
void
-CPed::Idle(void)
+CPed::CalculateNewVelocity(void)
{
- CVehicle *veh = m_pMyVehicle;
- if (veh && veh->m_nGettingOutFlags && m_vehEnterType) {
-
- if (veh->m_nGettingOutFlags & GetCarDoorFlag(m_vehEnterType)) {
-
- if (m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT) {
-
- CVector doorPos = GetPositionToOpenCarDoor(veh, m_vehEnterType);
- CVector doorDist = GetPosition() - doorPos;
+ if (IsPedInControl()) {
+ float headAmount = DEGTORAD(m_headingRate) * CTimer::GetTimeStep();
+ m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur);
+ float limitedRotDest = CGeneral::LimitRadianAngle(m_fRotationDest);
- if (doorDist.MagnitudeSqr() < sq(0.5f)) {
- SetMoveState(PEDMOVE_WALK);
- return;
- }
- }
+ if (m_fRotationCur - PI > limitedRotDest) {
+ limitedRotDest += 2 * PI;
+ } else if(PI + m_fRotationCur < limitedRotDest) {
+ limitedRotDest -= 2 * PI;
}
- }
- CAnimBlendAssociation *armedIdleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_ARMED);
- CAnimBlendAssociation *unarmedIdleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE);
- int waitTime;
-
- if (m_nMoveState == PEDMOVE_STILL) {
-
- eWeaponType curWeapon = GetWeapon()->m_eWeaponType;
- if (!armedIdleAssoc ||
- CTimer::GetTimeInMilliseconds() <= m_nWaitTimer && curWeapon != WEAPONTYPE_UNARMED && curWeapon != WEAPONTYPE_MOLOTOV && curWeapon != WEAPONTYPE_GRENADE) {
-
- if ((!GetWeapon()->IsType2Handed() || curWeapon == WEAPONTYPE_SHOTGUN) && curWeapon != WEAPONTYPE_BASEBALLBAT
- || !unarmedIdleAssoc || unarmedIdleAssoc->blendAmount <= 0.95f || m_nWaitState != WAITSTATE_FALSE || CTimer::GetTimeInMilliseconds() <= m_nWaitTimer) {
+ if (IsPlayer() && m_nPedState == PED_ATTACK)
+ headAmount /= 4.0f;
- m_moved = CVector2D(0.0f, 0.0f);
- return;
- }
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_ARMED, 3.0f);
- waitTime = CGeneral::GetRandomNumberInRange(4000, 7500);
+ float neededTurn = limitedRotDest - m_fRotationCur;
+ if (neededTurn <= headAmount) {
+ if (neededTurn > (-headAmount))
+ m_fRotationCur += neededTurn;
+ else
+ m_fRotationCur -= headAmount;
} else {
- armedIdleAssoc->blendDelta = -2.0f;
- armedIdleAssoc->flags |= ASSOC_DELETEFADEDOUT;
- waitTime = CGeneral::GetRandomNumberInRange(3000, 8500);
- }
- m_nWaitTimer = CTimer::GetTimeInMilliseconds() + waitTime;
- } else {
- if (armedIdleAssoc) {
- armedIdleAssoc->blendDelta = -8.0f;
- armedIdleAssoc->flags |= ASSOC_DELETEFADEDOUT;
- m_nWaitTimer = 0;
- }
- if (!IsPlayer())
- SetMoveState(PEDMOVE_STILL);
- }
- m_moved = CVector2D(0.0f, 0.0f);
-}
-
-void
-CPed::InTheAir(void)
-{
- CColPoint foundCol;
- CEntity *foundEnt;
-
- CVector ourPos = GetPosition();
- CVector bitBelow = GetPosition();
- bitBelow.z -= 4.04f;
-
- if (m_vecMoveSpeed.z < 0.0f && !bIsPedDieAnimPlaying) {
- if (!DyingOrDead()) {
- if (CWorld::ProcessLineOfSight(ourPos, bitBelow, foundCol, foundEnt, true, true, false, true, false, false, false)) {
- if (GetPosition().z - foundCol.point.z < 1.3f
-#ifdef VC_PED_PORTS
- || bIsStanding
-#endif
- )
- SetLanding();
- } else {
- if (!RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FALL_FALL)) {
- if (m_vecMoveSpeed.z < -0.1f)
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FALL_FALL, 4.0f);
- }
- }
+ m_fRotationCur += headAmount;
}
}
-}
-void
-CPed::SetLanding(void)
-{
- if (DyingOrDead())
- return;
-
- CAnimBlendAssociation *fallAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FALL_FALL);
- CAnimBlendAssociation *landAssoc;
-
- RpAnimBlendClumpSetBlendDeltas(GetClump(), ASSOC_PARTIAL, -1000.0f);
- if (fallAssoc) {
- landAssoc = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_FALL_COLLAPSE);
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_FALL_COLLAPSE, 1.0f);
+ CVector2D forward(Sin(m_fRotationCur), Cos(m_fRotationCur));
- if (IsPlayer())
- Say(SOUND_PED_LAND);
+ m_moved.x = CrossProduct2D(m_vecAnimMoveDelta, forward); // (m_vecAnimMoveDelta.x * Cos(m_fRotationCur)) + -Sin(m_fRotationCur) * m_vecAnimMoveDelta.y;
+ m_moved.y = DotProduct2D(m_vecAnimMoveDelta, forward); // m_vecAnimMoveDelta.y* Cos(m_fRotationCur) + (m_vecAnimMoveDelta.x * Sin(m_fRotationCur));
+ if (CTimer::GetTimeStep() >= 0.01f) {
+ m_moved = m_moved * (1 / CTimer::GetTimeStep());
} else {
- landAssoc = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_FALL_LAND);
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_FALL_LAND, 1.0f);
- }
-
- landAssoc->SetFinishCallback(PedLandCB, this);
- bIsInTheAir = false;
- bIsLanding = true;
-}
-
-void
-CPed::Initialise(void)
-{
- debug("Initialising CPed...\n");
- CPedType::Initialise();
- LoadFightData();
- SetAnimOffsetForEnterOrExitVehicle();
- debug("CPed ready\n");
-}
-
-void
-CPed::SetAnimOffsetForEnterOrExitVehicle(void)
-{
- // FIX: If there were no translations on enter anims, there were overflows all over this function.
-
- CAnimBlendHierarchy *enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, ANIM_CAR_JACKED_LHS)->hierarchy;
- CAnimBlendSequence *seq = enterAssoc->sequences;
- CAnimManager::UncompressAnimation(enterAssoc);
- if (seq->numFrames > 0) {
- if (!seq->HasTranslation())
- vecPedDraggedOutCarAnimOffset = CVector(0.0f, 0.0f, 0.0f);
- else {
- KeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);
- vecPedDraggedOutCarAnimOffset = lastFrame->translation;
- }
- }
-
- enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, ANIM_CAR_GETIN_LHS)->hierarchy;
- seq = enterAssoc->sequences;
- CAnimManager::UncompressAnimation(enterAssoc);
- if (seq->numFrames > 0) {
- if (!seq->HasTranslation())
- vecPedCarDoorAnimOffset = CVector(0.0f, 0.0f, 0.0f);
- else {
- KeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);
- vecPedCarDoorAnimOffset = lastFrame->translation;
- }
- }
-
- enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, ANIM_CAR_GETIN_LOW_LHS)->hierarchy;
- seq = enterAssoc->sequences;
- CAnimManager::UncompressAnimation(enterAssoc);
- if (seq->numFrames > 0) {
- if (!seq->HasTranslation())
- vecPedCarDoorLoAnimOffset = CVector(0.0f, 0.0f, 0.0f);
- else {
- KeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);
- vecPedCarDoorLoAnimOffset = lastFrame->translation;
- }
- }
-
- enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, ANIM_CAR_QJACKED)->hierarchy;
- seq = enterAssoc->sequences;
- CAnimManager::UncompressAnimation(enterAssoc);
- if (seq->numFrames > 0) {
- if (!seq->HasTranslation())
- vecPedQuickDraggedOutCarAnimOffset = CVector(0.0f, 0.0f, 0.0f);
- else {
- KeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);
- vecPedQuickDraggedOutCarAnimOffset = lastFrame->translation;
- }
- }
-
- enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, ANIM_VAN_GETIN_L)->hierarchy;
- seq = enterAssoc->sequences;
- CAnimManager::UncompressAnimation(enterAssoc);
- if (seq->numFrames > 0) {
- if (!seq->HasTranslation())
- vecPedVanRearDoorAnimOffset = CVector(0.0f, 0.0f, 0.0f);
- else {
- KeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);
- vecPedVanRearDoorAnimOffset = lastFrame->translation;
- }
- }
-
- enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, ANIM_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;
- }
+ m_moved = m_moved * (1 / 100.0f);
}
-}
-void
-CPed::InvestigateEvent(void)
-{
- CAnimBlendAssociation *animAssoc;
- AnimationId animToPlay;
- AssocGroupId animGroup;
-
- if (m_nWaitState == WAITSTATE_TURN180)
+ if ((!TheCamera.Cams[TheCamera.ActiveCam].GetWeaponFirstPersonOn() && !TheCamera.Cams[0].Using3rdPersonMouseCam())
+ || FindPlayerPed() != this || !CanStrafeOrMouseControl())
return;
- if (CTimer::GetTimeInMilliseconds() > m_standardTimer) {
-
- if (m_standardTimer) {
- if (m_eventType < EVENT_ASSAULT_NASTYWEAPON)
- SetWaitState(WAITSTATE_TURN180, nil);
+ float walkAngle = WorkOutHeadingForMovingFirstPerson(m_fRotationCur);
+ float pedSpeed = m_moved.Magnitude();
+ float localWalkAngle = CGeneral::LimitRadianAngle(walkAngle - m_fRotationCur);
- m_standardTimer = 0;
- } else {
- ClearInvestigateEvent();
- }
- return;
+ if (localWalkAngle < -0.5f * PI) {
+ localWalkAngle += PI;
+ } else if (localWalkAngle > 0.5f * PI) {
+ localWalkAngle -= PI;
}
- CVector2D vecDist = m_eventOrThreat - GetPosition();
- float distSqr = vecDist.MagnitudeSqr();
- if (sq(m_distanceToCountSeekDone) >= distSqr) {
-
- m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(vecDist.x, vecDist.y, 0.0f, 0.0f);
- SetMoveState(PEDMOVE_STILL);
-
- switch (m_eventType) {
- case EVENT_DEAD_PED:
- case EVENT_HIT_AND_RUN:
- case EVENT_HIT_AND_RUN_COP:
-
- if (CTimer::GetTimeInMilliseconds() > m_lookTimer) {
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_ROAD_CROSS);
-
- if (animAssoc) {
- animAssoc->blendDelta = -8.0f;
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- if (m_pEventEntity)
- SetLookFlag(m_pEventEntity, true);
-
- SetLookTimer(CGeneral::GetRandomNumberInRange(1500, 4000));
-
- } else if (CGeneral::GetRandomNumber() & 3) {
- ClearLookFlag();
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_ROAD_CROSS, 4.0f);
-
- SetLookTimer(CGeneral::GetRandomNumberInRange(1000, 2500));
- Say(SOUND_PED_CHAT_EVENT);
-
- } else {
- ClearInvestigateEvent();
- }
- }
- break;
- case EVENT_FIRE:
- case EVENT_EXPLOSION:
-
- if (bHasACamera && CTimer::GetTimeInMilliseconds() > m_lookTimer) {
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_CAM);
- if (!animAssoc)
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE);
-
- if (animAssoc && animAssoc->animId == ANIM_IDLE_CAM) {
- CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 4.0f);
- SetLookTimer(CGeneral::GetRandomNumberInRange(1000, 2500));
-
- } else if (CGeneral::GetRandomNumber() & 3) {
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_CAM, 4.0f);
- SetLookTimer(CGeneral::GetRandomNumberInRange(2500, 5000));
- Say(SOUND_PED_CHAT_EVENT);
-
- } else {
- m_standardTimer = 0;
- }
-
- } else if (CTimer::GetTimeInMilliseconds() > m_lookTimer) {
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE);
- if (!animAssoc)
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_HBHB);
-
- if (!animAssoc)
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_XPRESS_SCRATCH);
-
- if (animAssoc && animAssoc->animId == ANIM_IDLE_STANCE) {
- if (CGeneral::GetRandomNumber() & 1)
- animToPlay = ANIM_IDLE_HBHB;
- else
- animToPlay = ANIM_XPRESS_SCRATCH;
-
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animToPlay, 4.0f);
- SetLookTimer(CGeneral::GetRandomNumberInRange(1500, 4000));
-
- } else if (animAssoc && animAssoc->animId == ANIM_IDLE_HBHB) {
- animAssoc->blendDelta = -8.0f;
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- if (CGeneral::GetRandomNumber() & 1) {
- animToPlay = ANIM_IDLE_STANCE;
- animGroup = m_animGroup;
- } else {
- animToPlay = ANIM_XPRESS_SCRATCH;
- animGroup = ASSOCGRP_STD;
- }
-
- CAnimManager::BlendAnimation(GetClump(), animGroup, animToPlay, 4.0f);
- SetLookTimer(CGeneral::GetRandomNumberInRange(1000, 2500));
-
- } else {
- if (CGeneral::GetRandomNumber() & 1) {
- animToPlay = ANIM_IDLE_STANCE;
- animGroup = m_animGroup;
- } else {
- animToPlay = ANIM_IDLE_HBHB;
- animGroup = ASSOCGRP_STD;
- }
-
- CAnimManager::BlendAnimation(GetClump(), animGroup, animToPlay, 4.0f);
- SetLookTimer(CGeneral::GetRandomNumberInRange(1000, 2500));
- }
- Say(SOUND_PED_CHAT_EVENT);
- }
- break;
- case EVENT_ICECREAM:
- case EVENT_SHOPSTALL:
-
- m_fRotationDest = m_fAngleToEvent;
- if (CTimer::GetTimeInMilliseconds() > m_lookTimer) {
-
- if (m_lookTimer) {
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_ROAD_CROSS);
+ // Interestingly this part is responsible for diagonal walking.
+ if (localWalkAngle > -DEGTORAD(50.0f) && localWalkAngle < DEGTORAD(50.0f)) {
+ TheCamera.Cams[TheCamera.ActiveCam].m_fPlayerVelocity = pedSpeed;
+ m_moved = CVector2D(-Sin(walkAngle), Cos(walkAngle)) * pedSpeed;
+ }
- if (animAssoc) {
- animAssoc->blendDelta = -8.0f;
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- if (m_eventType == EVENT_ICECREAM)
- animToPlay = ANIM_IDLE_CHAT;
- else
- animToPlay = ANIM_XPRESS_SCRATCH;
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animToPlay,4.0f);
- SetLookTimer(CGeneral::GetRandomNumberInRange(2000, 5000));
+ CAnimBlendAssociation *idleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE);
+ CAnimBlendAssociation *fightAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FIGHT_IDLE);
+#ifdef VC_PED_PORTS
+ if ((!idleAssoc || idleAssoc->blendAmount < 0.5f) && !fightAssoc && !bIsDucking) {
+#else
+ if ((!idleAssoc || idleAssoc->blendAmount < 0.5f) && !fightAssoc) {
+#endif
+ LimbOrientation newUpperLegs;
+ newUpperLegs.yaw = localWalkAngle;
- } else {
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_CHAT);
- if (animAssoc) {
- animAssoc->blendDelta = -8.0f;
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- ClearInvestigateEvent();
- } else {
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_XPRESS_SCRATCH);
- if (animAssoc) {
- animAssoc->blendDelta = -8.0f;
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- }
- ClearInvestigateEvent();
- }
- }
- } else {
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_ROAD_CROSS, 4.0f);
- SetLookTimer(CGeneral::GetRandomNumberInRange(1000, 2500));
- }
- }
- break;
- default:
- return;
+ if (newUpperLegs.yaw < -DEGTORAD(100.0f)) {
+ newUpperLegs.yaw += PI;
+ } else if (newUpperLegs.yaw > DEGTORAD(100.0f)) {
+ newUpperLegs.yaw -= PI;
}
- } else {
- m_vecSeekPos.x = m_eventOrThreat.x;
- m_vecSeekPos.y = m_eventOrThreat.y;
- m_vecSeekPos.z = GetPosition().z;
- Seek();
- if (m_eventType < EVENT_ICECREAM) {
- if (sq(5.0f + m_distanceToCountSeekDone) < distSqr) {
- SetMoveState(PEDMOVE_RUN);
- return;
- }
- }
- if (m_eventType <= EVENT_EXPLOSION || m_eventType >= EVENT_SHOPSTALL) {
- SetMoveState(PEDMOVE_WALK);
- return;
- }
- if (distSqr > sq(1.2f)) {
- SetMoveState(PEDMOVE_WALK);
- return;
- }
+ if (newUpperLegs.yaw > -DEGTORAD(50.0f) && newUpperLegs.yaw < DEGTORAD(50.0f)) {
+#ifdef PED_SKIN
+ if(IsClumpSkinned(GetClump())){
+/*
+ // this looks shit
+ newUpperLegs.pitch = 0.0f;
+ RwV3d axis = { -1.0f, 0.0f, 0.0f };
+ RtQuatRotate(&m_pFrames[PED_UPPERLEGL]->hanimFrame->q, &axis, RADTODEG(newUpperLegs.yaw), rwCOMBINEPRECONCAT);
+ RtQuatRotate(&m_pFrames[PED_UPPERLEGR]->hanimFrame->q, &axis, RADTODEG(newUpperLegs.yaw), rwCOMBINEPRECONCAT);
+*/
+ newUpperLegs.pitch = 0.1f;
+ RwV3d Xaxis = { 1.0f, 0.0f, 0.0f };
+ RwV3d Zaxis = { 0.0f, 0.0f, 1.0f };
+ RtQuatRotate(&m_pFrames[PED_UPPERLEGL]->hanimFrame->q, &Zaxis, RADTODEG(newUpperLegs.pitch), rwCOMBINEPOSTCONCAT);
+ RtQuatRotate(&m_pFrames[PED_UPPERLEGL]->hanimFrame->q, &Xaxis, RADTODEG(newUpperLegs.yaw), rwCOMBINEPOSTCONCAT);
+ RtQuatRotate(&m_pFrames[PED_UPPERLEGR]->hanimFrame->q, &Zaxis, RADTODEG(newUpperLegs.pitch), rwCOMBINEPOSTCONCAT);
+ RtQuatRotate(&m_pFrames[PED_UPPERLEGR]->hanimFrame->q, &Xaxis, RADTODEG(newUpperLegs.yaw), rwCOMBINEPOSTCONCAT);
- for (int i = 0; i < m_numNearPeds; i++) {
- if ((m_eventOrThreat - m_nearPeds[i]->GetPosition()).MagnitudeSqr() < sq(0.4f)) {
- SetMoveState(PEDMOVE_STILL);
- return;
+ bDontAcceptIKLookAts = true;
+ }else
+#endif
+ {
+ newUpperLegs.pitch = 0.0f;
+ m_pedIK.RotateTorso(m_pFrames[PED_UPPERLEGL], &newUpperLegs, false);
+ m_pedIK.RotateTorso(m_pFrames[PED_UPPERLEGR], &newUpperLegs, false);
}
}
-
- SetMoveState(PEDMOVE_WALK);
}
}
-bool
-CPed::IsPedDoingDriveByShooting(void)
-{
- if (FindPlayerPed() == this && GetWeapon()->m_eWeaponType == WEAPONTYPE_UZI) {
- if (TheCamera.Cams[TheCamera.ActiveCam].LookingLeft || TheCamera.Cams[TheCamera.ActiveCam].LookingRight)
- return true;
- }
- return false;
-}
-
-bool
-CPed::IsPedShootable(void)
+float
+CPed::WorkOutHeadingForMovingFirstPerson(float offset)
{
- return m_nPedState <= PED_STATES_NO_ST;
-}
+ if (!IsPlayer())
+ return 0.0f;
-bool
-CPed::IsRoomToBeCarJacked(void)
-{
- if (!m_pMyVehicle)
- return false;
+ CPad *pad0 = CPad::GetPad(0);
+ float leftRight = pad0->GetPedWalkLeftRight();
+ float upDown = pad0->GetPedWalkUpDown();
+ float &angle = ((CPlayerPed*)this)->m_fWalkAngle;
- CVector offset;
- if (m_pMyVehicle->bLowVehicle || m_nPedType == PEDTYPE_COP) {
- offset = vecPedDraggedOutCarAnimOffset;
+ if (upDown != 0.0f) {
+ angle = CGeneral::GetRadianAngleBetweenPoints(0.0f, 0.0f, -leftRight, upDown);
} else {
- offset = vecPedQuickDraggedOutCarAnimOffset;
- }
-
- offset.z = 0.0f;
- if (m_pMyVehicle->IsRoomForPedToLeaveCar(CAR_DOOR_LF, &offset)) {
- return true;
+ if (leftRight < 0.0f)
+ angle = 0.5f * PI;
+ else if (leftRight > 0.0f)
+ angle = -0.5f * PI;
}
- return false;
+ return CGeneral::LimitRadianAngle(offset + angle);
}
void
-CPed::KillPedWithCar(CVehicle *car, float impulse)
+CPed::UpdatePosition(void)
{
- CVehicleModelInfo *vehModel;
- CColModel *vehColModel;
- uint8 damageDir;
- PedNode nodeToDamage;
- eWeaponType killMethod;
-
- if (m_nPedState == PED_FALL || m_nPedState == PED_DIE) {
- if (!this->m_pCollidingEntity || car->GetStatus() == STATUS_PLAYER)
- this->m_pCollidingEntity = car;
- return;
- }
-
- if (m_nPedState == PED_DEAD)
+ if (CReplay::IsPlayingBack() || !bIsStanding)
return;
- if (m_pCurSurface) {
- if (m_pCurSurface->IsVehicle() && (((CVehicle*)m_pCurSurface)->m_vehType == VEHICLE_TYPE_BOAT || IsPlayer()))
- return;
- }
-
- CVector distVec = GetPosition() - car->GetPosition();
-
- if ((impulse > 12.0f || car->GetModelIndex() == MI_TRAIN) && !IsPlayer()) {
- nodeToDamage = PED_TORSO;
- killMethod = WEAPONTYPE_RAMMEDBYCAR;
- uint8 randVal = CGeneral::GetRandomNumber() & 3;
-
- if (car == FindPlayerVehicle()) {
- float carSpeed = car->m_vecMoveSpeed.Magnitude();
- uint8 shakeFreq;
- if (100.0f * carSpeed * 2000.0f / car->m_fMass + 80.0f <= 250.0f) {
- shakeFreq = 100.0f * carSpeed * 2000.0f / car->m_fMass + 80.0f;
- } else {
- shakeFreq = 250.0f;
- }
- CPad::GetPad(0)->StartShake(40000 / shakeFreq, shakeFreq);
- }
- bIsStanding = false;
- damageDir = GetLocalDirection(-m_vecMoveSpeed);
- vehModel = (CVehicleModelInfo *)CModelInfo::GetModelInfo(car->GetModelIndex());
- vehColModel = vehModel->GetColModel();
- float carRightAndDistDotProd = DotProduct(distVec, car->GetRight());
-
- if (car->GetModelIndex() == MI_TRAIN) {
- killMethod = WEAPONTYPE_RUNOVERBYCAR;
- nodeToDamage = PED_HEAD;
- m_vecMoveSpeed = 0.9f * car->m_vecMoveSpeed;
- m_vecMoveSpeed.z = 0.0f;
- if (damageDir == 1 || damageDir == 3)
- damageDir = 2;
- if (CGame::nastyGame)
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_SPLATTER, 0.0f);
-
- // Car doesn't look to us
- } else if (DotProduct(car->m_vecMoveSpeed, car->GetForward()) >= 0.0f){
-
- if (0.99f * vehColModel->boundingBox.max.x < Abs(carRightAndDistDotProd)) {
-
- // We're at the right of the car
- if (carRightAndDistDotProd <= 0.0f)
- nodeToDamage = PED_UPPERARML;
- else
- nodeToDamage = PED_UPPERARMR;
-
- if (Abs(DotProduct(distVec, car->GetForward())) < 0.85f * vehColModel->boundingBox.max.y) {
- killMethod = WEAPONTYPE_RUNOVERBYCAR;
- m_vecMoveSpeed = 0.9f * car->m_vecMoveSpeed;
- m_vecMoveSpeed.z = 0.0f;
- if (damageDir == 1 || damageDir == 3)
- damageDir = 2;
- if (CGame::nastyGame)
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_SPLATTER, 0.0f);
-
- }
- } else {
- float carFrontAndDistDotProd = DotProduct(distVec, car->GetForward());
-
- // carFrontAndDistDotProd <= 0.0 car looks to us
- if ((carFrontAndDistDotProd <= 0.1 || randVal == 1) && randVal != 0) {
- killMethod = WEAPONTYPE_RUNOVERBYCAR;
- nodeToDamage = PED_HEAD;
- m_vecMoveSpeed = 0.9f * car->m_vecMoveSpeed;
- m_vecMoveSpeed.z = 0.0f;
- if (damageDir == 1 || damageDir == 3)
- damageDir = 2;
-
- if (CGame::nastyGame)
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_SPLATTER, 0.0f);
-
- } else {
- nodeToDamage = PED_MID;
- float vehColMaxY = vehColModel->boundingBox.max.y;
- float vehColMinY = vehColModel->boundingBox.min.y;
- float vehColMaxZ = vehColModel->boundingBox.max.z;
- float carFrontZ = car->GetForward().z;
- float carHighestZ, carLength;
-
- if (carFrontZ < -0.2f) {
- // Highest point of car's back
- carHighestZ = (car->GetMatrix() * CVector(0.0f, vehColMinY, vehColMaxZ)).z;
- carLength = vehColMaxY - vehColMinY;
-
- } else if (carFrontZ > 0.1f) {
- // Highest point of car's front
- carHighestZ = (car->GetMatrix() * CVector(0.0f, vehColMaxY, vehColMaxZ)).z;
- float highestZDist = carHighestZ - GetPosition().z;
- if (highestZDist > 0.0f) {
- GetMatrix().GetPosition().z += 0.5f * highestZDist;
- carHighestZ += highestZDist * 0.25f;
- }
- carLength = vehColMaxY;
-
- } else {
- // Highest point of car's front
- carHighestZ = (car->GetMatrix() * CVector(0.0f, vehColMaxY, vehColMaxZ)).z;
- carLength = vehColMaxY;
- }
-
- float pedJumpSpeedToReachHighestZ = (carHighestZ - GetPosition().z) / (carLength / car->m_vecMoveSpeed.Magnitude());
-
- // TODO: What are we doing down here?
- float unknown = ((CGeneral::GetRandomNumber() % 256) * 0.002 + 1.5) * pedJumpSpeedToReachHighestZ;
-
- // After this point, distVec isn't distVec anymore.
- distVec = car->m_vecMoveSpeed;
- distVec.Normalise();
- distVec *= 0.2 * unknown;
-
- if (damageDir != 1 && damageDir != 3)
- distVec.z += unknown;
- else
- distVec.z += 1.5f * unknown;
+ CVector2D velocityChange;
- m_vecMoveSpeed = distVec;
- damageDir += 2;
- if (damageDir > 3)
- damageDir = damageDir - 4;
+ SetHeading(m_fRotationCur);
+ if (m_pCurrentPhysSurface) {
+ CVector2D velocityOfSurface;
+ if (!IsPlayer() && m_pCurrentPhysSurface->IsVehicle() && ((CVehicle*)m_pCurrentPhysSurface)->IsBoat()) {
- if (car->m_vehType == VEHICLE_TYPE_CAR) {
- CObject *bonnet = ((CAutomobile*)car)->RemoveBonnetInPedCollision();
+ // It seems R* didn't like m_vecOffsetFromPhysSurface for boats
+ CVector offsetToSurface = GetPosition() - m_pCurrentPhysSurface->GetPosition();
+ offsetToSurface.z -= FEET_OFFSET;
- if (bonnet) {
- if (CGeneral::GetRandomNumber() & 1) {
- bonnet->m_vecMoveSpeed += Multiply3x3(car->GetMatrix(), CVector(0.1f, 0.0f, 0.5f));
- } else {
- bonnet->m_vecMoveSpeed += Multiply3x3(car->GetMatrix(), CVector(-0.1f, 0.0f, 0.5f));
- }
- CVector forceDir = car->GetUp() * 10.0f;
- bonnet->ApplyTurnForce(forceDir, car->GetForward());
- }
- }
- }
- }
- }
+ CVector surfaceMoveVelocity = m_pCurrentPhysSurface->m_vecMoveSpeed;
+ CVector surfaceTurnVelocity = CrossProduct(m_pCurrentPhysSurface->m_vecTurnSpeed, offsetToSurface);
- if (car->pDriver) {
- CEventList::RegisterEvent((m_nPedType == PEDTYPE_COP ? EVENT_HIT_AND_RUN_COP : EVENT_HIT_AND_RUN), EVENT_ENTITY_PED, this, car->pDriver, 1000);
+ // Also we use that weird formula instead of friction if it's boat
+ float slideMult = -m_pCurrentPhysSurface->m_vecTurnSpeed.MagnitudeSqr();
+ velocityOfSurface = slideMult * offsetToSurface * CTimer::GetTimeStep() + (surfaceTurnVelocity + surfaceMoveVelocity);
+ m_vecMoveSpeed.z = slideMult * offsetToSurface.z * CTimer::GetTimeStep() + (surfaceTurnVelocity.z + surfaceMoveVelocity.z);
+ } else {
+ velocityOfSurface = m_pCurrentPhysSurface->GetSpeed(m_vecOffsetFromPhysSurface);
}
+ // Reminder: m_moved is displacement from walking/running.
+ velocityChange = m_moved + velocityOfSurface - m_vecMoveSpeed;
+ m_fRotationCur += m_pCurrentPhysSurface->m_vecTurnSpeed.z * CTimer::GetTimeStep();
+ m_fRotationDest += m_pCurrentPhysSurface->m_vecTurnSpeed.z * CTimer::GetTimeStep();
+ } else if (m_nSurfaceTouched == SURFACE_STEEP_CLIFF && (m_vecDamageNormal.x != 0.0f || m_vecDamageNormal.y != 0.0f)) {
+ // Ped got damaged by steep slope
+ m_vecMoveSpeed = CVector(0.0f, 0.0f, -0.001f);
+ // some kind of
+ CVector2D reactionForce = m_vecDamageNormal;
+ reactionForce.Normalise();
- ePedPieceTypes pieceToDamage;
- switch (nodeToDamage) {
- case PED_HEAD:
- pieceToDamage = PEDPIECE_HEAD;
- break;
- case PED_UPPERARML:
- pieceToDamage = PEDPIECE_LEFTARM;
- break;
- case PED_UPPERARMR:
- pieceToDamage = PEDPIECE_RIGHTARM;
- break;
- default:
- pieceToDamage = PEDPIECE_MID;
- break;
- }
- InflictDamage(car, killMethod, 1000.0f, pieceToDamage, damageDir);
+ velocityChange = 0.02f * reactionForce + m_moved;
- if (DyingOrDead()
- && bIsPedDieAnimPlaying && !m_pCollidingEntity) {
- m_pCollidingEntity = car;
+ float reactionAndVelocityDotProd = DotProduct2D(reactionForce, velocityChange);
+ // they're in same direction
+ if (reactionAndVelocityDotProd < 0.0f) {
+ velocityChange -= reactionAndVelocityDotProd * reactionForce;
}
- if (nodeToDamage == PED_MID)
- bKnockedUpIntoAir = true;
- else
- bKnockedUpIntoAir = false;
-
- distVec.Normalise();
-
-#ifdef VC_PED_PORTS
- distVec *= Min(car->m_fMass / 1400.0f, 1.0f);
-#endif
- car->ApplyMoveForce(distVec * -100.0f);
- Say(SOUND_PED_DEFEND);
-
- } else if (m_vecDamageNormal.z < -0.8f && impulse > 3.0f
- || impulse > 6.0f && (!IsPlayer() || impulse > 10.0f)) {
-
- bIsStanding = false;
- uint8 fallDirection = GetLocalDirection(-car->m_vecMoveSpeed);
- float damage;
- if (IsPlayer() && car->GetModelIndex() == MI_TRAIN)
- damage = 150.0f;
- else
- damage = 30.0f;
+ } else {
+ velocityChange = m_moved - m_vecMoveSpeed;
+ }
- InflictDamage(car, WEAPONTYPE_RAMMEDBYCAR, damage, PEDPIECE_TORSO, fallDirection);
- SetFall(1000, (AnimationId)(fallDirection + ANIM_KO_SKID_FRONT), true);
-
- if (OnGround() && !m_pCollidingEntity &&
- (!IsPlayer() || bHasHitWall || car->GetModelIndex() == MI_TRAIN || m_vecDamageNormal.z < -0.8f)) {
-
- m_pCollidingEntity = car;
- }
-
- bKnockedUpIntoAir = false;
- if (car->GetModelIndex() != MI_TRAIN && !bHasHitWall) {
- m_vecMoveSpeed = car->m_vecMoveSpeed * 0.75f;
+ // Take time step into account
+ if (m_pCurrentPhysSurface) {
+ float speedChange = velocityChange.Magnitude();
+ float changeMult = speedChange;
+ if (m_nPedState == PED_DIE && m_pCurrentPhysSurface->IsVehicle()) {
+ changeMult = 0.002f * CTimer::GetTimeStep();
+ } else if (!(m_pCurrentPhysSurface->IsVehicle() && ((CVehicle*)m_pCurrentPhysSurface)->IsBoat())) {
+ changeMult = 0.01f * CTimer::GetTimeStep();
}
- m_vecMoveSpeed.z = 0.0f;
- distVec.Normalise();
-#ifdef VC_PED_PORTS
- distVec *= Min(car->m_fMass / 1400.0f, 1.0f);
-#endif
- car->ApplyMoveForce(distVec * -60.0f);
- Say(SOUND_PED_DEFEND);
- }
-#ifdef VC_PED_PORTS
- // Killing gang members with car wasn't triggering a fight, until now... Taken from VC.
- if (IsGangMember()) {
- CPed *driver = car->pDriver;
- if (driver && driver->IsPlayer()
-#ifdef FIX_BUGS
- && (CharCreatedBy != MISSION_CHAR || bRespondsToThreats) && (!m_leader || m_leader != driver)
-#endif
- ) {
- RegisterThreatWithGangPeds(driver);
+ if (speedChange > changeMult) {
+ velocityChange = velocityChange * (changeMult / speedChange);
}
}
-#endif
+ m_vecMoveSpeed.x += velocityChange.x;
+ m_vecMoveSpeed.y += velocityChange.y;
}
void
-CPed::Look(void)
-{
- // UNUSED: This is a perfectly empty function.
-}
-
-bool
-CPed::LookForInterestingNodes(void)
+CPed::CalculateNewOrientation(void)
{
- CBaseModelInfo *model;
- CPtrNode *ptrNode;
- CVector effectDist;
- C2dEffect *effect;
- CMatrix *objMat;
-
- if ((CTimer::GetFrameCounter() + (m_randomSeed % 256)) & 7 || CTimer::GetTimeInMilliseconds() <= m_standardTimer) {
- return false;
- }
- bool found = false;
- uint8 randVal = CGeneral::GetRandomNumber() % 256;
-
- int minX = CWorld::GetSectorIndexX(GetPosition().x - CHECK_NEARBY_THINGS_MAX_DIST);
- if (minX < 0) minX = 0;
- int minY = CWorld::GetSectorIndexY(GetPosition().y - CHECK_NEARBY_THINGS_MAX_DIST);
- if (minY < 0) minY = 0;
- int maxX = CWorld::GetSectorIndexX(GetPosition().x + CHECK_NEARBY_THINGS_MAX_DIST);
-#ifdef FIX_BUGS
- if (maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X - 1;
-#else
- if (maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X;
-#endif
-
- int maxY = CWorld::GetSectorIndexY(GetPosition().y + CHECK_NEARBY_THINGS_MAX_DIST);
-#ifdef FIX_BUGS
- if (maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y - 1;
-#else
- if (maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y;
-#endif
-
- for (int curY = minY; curY <= maxY && !found; curY++) {
- for (int curX = minX; curX <= maxX && !found; curX++) {
- CSector *sector = CWorld::GetSector(curX, curY);
-
- for (ptrNode = sector->m_lists[ENTITYLIST_VEHICLES].first; ptrNode && !found; ptrNode = ptrNode->next) {
- CVehicle *veh = (CVehicle*)ptrNode->item;
- model = veh->GetModelInfo();
- if (model->GetNum2dEffects() != 0) {
- for (int e = 0; e < model->GetNum2dEffects(); e++) {
- effect = model->Get2dEffect(e);
- if (effect->type == EFFECT_ATTRACTOR && effect->attractor.probability >= randVal) {
- objMat = &veh->GetMatrix();
- CVector effectPos = veh->GetMatrix() * effect->pos;
- effectDist = effectPos - GetPosition();
- if (effectDist.MagnitudeSqr() < sq(8.0f)) {
- found = true;
- break;
- }
- }
- }
- }
- }
- for (ptrNode = sector->m_lists[ENTITYLIST_OBJECTS].first; ptrNode && !found; ptrNode = ptrNode->next) {
- CObject *obj = (CObject*)ptrNode->item;
- model = CModelInfo::GetModelInfo(obj->GetModelIndex());
- if (model->GetNum2dEffects() != 0) {
- for (int e = 0; e < model->GetNum2dEffects(); e++) {
- effect = model->Get2dEffect(e);
- if (effect->type == EFFECT_ATTRACTOR && effect->attractor.probability >= randVal) {
- objMat = &obj->GetMatrix();
- CVector effectPos = obj->GetMatrix() * effect->pos;
- effectDist = effectPos - GetPosition();
- if (effectDist.MagnitudeSqr() < sq(8.0f)) {
- found = true;
- break;
- }
- }
- }
- }
- }
- for (ptrNode = sector->m_lists[ENTITYLIST_BUILDINGS].first; ptrNode && !found; ptrNode = ptrNode->next) {
- CBuilding *building = (CBuilding*)ptrNode->item;
- model = CModelInfo::GetModelInfo(building->GetModelIndex());
- if (model->GetNum2dEffects() != 0) {
- for (int e = 0; e < model->GetNum2dEffects(); e++) {
- effect = model->Get2dEffect(e);
- if (effect->type == EFFECT_ATTRACTOR && effect->attractor.probability >= randVal) {
- objMat = &building->GetMatrix();
- CVector effectPos = building->GetMatrix() * effect->pos;
- effectDist = effectPos - GetPosition();
- if (effectDist.MagnitudeSqr() < sq(8.0f)) {
- found = true;
- break;
- }
- }
- }
- }
- }
- for (ptrNode = sector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP].first; ptrNode && !found; ptrNode = ptrNode->next) {
- CBuilding *building = (CBuilding*)ptrNode->item;
- model = CModelInfo::GetModelInfo(building->GetModelIndex());
- if (model->GetNum2dEffects() != 0) {
- for (int e = 0; e < model->GetNum2dEffects(); e++) {
- effect = model->Get2dEffect(e);
- if (effect->type == EFFECT_ATTRACTOR && effect->attractor.probability >= randVal) {
- objMat = &building->GetMatrix();
- CVector effectPos = building->GetMatrix() * effect->pos;
- effectDist = effectPos - GetPosition();
- if (effectDist.MagnitudeSqr() < sq(8.0f)) {
- found = true;
- break;
- }
- }
- }
- }
- }
- }
- }
-
- if (!found)
- return false;
-
- CVector effectFrontLocal = Multiply3x3(*objMat, effect->attractor.dir);
- float angleToFace = CGeneral::GetRadianAngleBetweenPoints(effectFrontLocal.x, effectFrontLocal.y, 0.0f, 0.0f);
- randVal = CGeneral::GetRandomNumber() % 256;
- if (randVal <= m_randomSeed % 256) {
- m_standardTimer = CTimer::GetTimeInMilliseconds() + 2000;
- SetLookFlag(angleToFace, true);
- SetLookTimer(1000);
- return false;
- }
+ if (CReplay::IsPlayingBack() || !IsPedInControl())
+ return;
- CVector2D effectPos = *objMat * effect->pos;
- switch (effect->attractor.type) {
- case ATTRACTORTYPE_ICECREAM:
- SetInvestigateEvent(EVENT_ICECREAM, effectPos, 0.1f, 15000, angleToFace);
- break;
- case ATTRACTORTYPE_STARE:
- SetInvestigateEvent(EVENT_SHOPSTALL, effectPos, 1.0f,
- CGeneral::GetRandomNumberInRange(8000, 10 * effect->attractor.probability + 8500),
- angleToFace);
- break;
- default:
- return true;
- }
- return true;
+ SetHeading(m_fRotationCur);
}
void
-CPed::SetInvestigateEvent(eEventType event, CVector2D pos, float distanceToCountDone, uint16 time, float angle)
+CPed::ClearAll(void)
{
- if (!IsPedInControl() || CharCreatedBy == MISSION_CHAR)
+ if (!IsPedInControl() && m_nPedState != PED_DEAD)
return;
- SetStoredState();
- bFindNewNodeAfterStateRestore = false;
- m_nPedState = PED_INVESTIGATE;
- m_standardTimer = CTimer::GetTimeInMilliseconds() + time;
- m_eventType = event;
- m_eventOrThreat = pos;
- m_distanceToCountSeekDone = distanceToCountDone;
- m_fAngleToEvent = angle;
-
- if (m_eventType >= EVENT_ICECREAM)
- m_lookTimer = 0;
- else
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_HANDSCOWER, 4.0f);
-
+ m_nPedState = PED_NONE;
+ m_nMoveState = PEDMOVE_NONE;
+ m_pSeekTarget = nil;
+ m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f);
+ m_fleeFromPosX = 0.0f;
+ m_fleeFromPosY = 0.0f;
+ m_fleeFrom = nil;
+ m_fleeTimer = 0;
+ bUsesCollision = true;
+#ifdef VC_PED_PORTS
+ ClearPointGunAt();
+#else
+ ClearAimFlag();
+ ClearLookFlag();
+#endif
+ bIsPointingGunAt = false;
+ bRenderPedInCar = true;
+ bKnockedUpIntoAir = false;
+ m_pCollidingEntity = nil;
}
void
-CPed::LookForSexyCars(void)
+CPed::ProcessBuoyancy(void)
{
- CEntity *vehicles[8];
- CVehicle *veh;
- int foundVehId = 0;
- int bestPriceYet = 0;
- int16 lastVehicle;
+ static uint32 nGenerateRaindrops = 0;
+ static uint32 nGenerateWaterCircles = 0;
+ CRGBA color(((0.5f * CTimeCycle::GetDirectionalRed() + CTimeCycle::GetAmbientRed()) * 127.5f),
+ ((0.5f * CTimeCycle::GetDirectionalBlue() + CTimeCycle::GetAmbientBlue()) * 127.5f),
+ ((0.5f * CTimeCycle::GetDirectionalGreen() + CTimeCycle::GetAmbientGreen()) * 127.5f),
+ (CGeneral::GetRandomNumber() % 256 * 48.0f) + 48);
- if (!IsPedInControl() && m_nPedState != PED_DRIVING)
+ if (bInVehicle)
return;
- if (m_lookTimer < CTimer::GetTimeInMilliseconds()) {
- CWorld::FindObjectsInRange(GetPosition(), 10.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false);
-
- for (int vehId = 0; vehId < lastVehicle; vehId++) {
- veh = (CVehicle*)vehicles[vehId];
- if (veh != m_pMyVehicle && bestPriceYet < veh->pHandling->nMonetaryValue) {
- foundVehId = vehId;
- bestPriceYet = veh->pHandling->nMonetaryValue;
- }
- }
- if (lastVehicle > 0 && bestPriceYet > 40000)
- SetLookFlag(vehicles[foundVehId], false);
-
- m_lookTimer = CTimer::GetTimeInMilliseconds() + 10000;
- }
-}
-
-void
-CPed::LookForSexyPeds(void)
-{
- if ((!IsPedInControl() && m_nPedState != PED_DRIVING)
- || m_lookTimer >= CTimer::GetTimeInMilliseconds() || m_nPedType != PEDTYPE_CIVMALE)
- return;
+ CVector buoyancyPoint;
+ CVector buoyancyImpulse;
- for (int i = 0; i < m_numNearPeds; i++) {
- if (CanSeeEntity(m_nearPeds[i])) {
- if ((GetPosition() - m_nearPeds[i]->GetPosition()).Magnitude() < 10.0f) {
- CPed *nearPed = m_nearPeds[i];
- if ((nearPed->m_pedStats->m_sexiness > m_pedStats->m_sexiness)
- && nearPed->m_nPedType == PEDTYPE_CIVFEMALE) {
+#ifndef VC_PED_PORTS
+ float buoyancyLevel = (m_nPedState == PED_DEAD ? 1.5f : 1.3f);
+#else
+ float buoyancyLevel = (m_nPedState == PED_DEAD ? 1.8f : 1.1f);
+#endif
- SetLookFlag(nearPed, true);
- m_lookTimer = CTimer::GetTimeInMilliseconds() + 4000;
- Say(SOUND_PED_CHAT_SEXY);
- return;
- }
- }
+ if (mod_Buoyancy.ProcessBuoyancy(this, GRAVITY * m_fMass * buoyancyLevel, &buoyancyPoint, &buoyancyImpulse)) {
+ bTouchingWater = true;
+ CEntity *entity;
+ CColPoint point;
+ if (CWorld::ProcessVerticalLine(GetPosition(), GetPosition().z - 3.0f, point, entity, false, true, false, false, false, false, nil)
+ && entity->IsVehicle() && ((CVehicle*)entity)->IsBoat()) {
+ bIsInWater = false;
+ return;
}
- }
- m_lookTimer = CTimer::GetTimeInMilliseconds() + 10000;
-}
-
-void
-CPed::MakeTyresMuddySectorList(CPtrList &list)
-{
- for (CPtrNode *node = list.first; node; node = node->next) {
- CVehicle *veh = (CVehicle*)node->item;
- if (veh->IsCar() && veh->m_scanCode != CWorld::GetCurrentScanCode()) {
- veh->m_scanCode = CWorld::GetCurrentScanCode();
-
- if (Abs(GetPosition().x - veh->GetPosition().x) < 10.0f) {
-
- if (Abs(GetPosition().y - veh->GetPosition().y) < 10.0f
- && veh->m_vecMoveSpeed.MagnitudeSqr2D() > 0.05f) {
-
- for(int wheel = 0; wheel < 4; wheel++) {
-
- if (!((CAutomobile*)veh)->m_aWheelSkidmarkBloody[wheel]
- && ((CAutomobile*)veh)->m_aSuspensionSpringRatio[wheel] < 1.0f) {
-
- CColModel *vehCol = veh->GetModelInfo()->GetColModel();
- CVector approxWheelOffset;
- switch (wheel) {
- case 0:
- approxWheelOffset = CVector(-vehCol->boundingBox.max.x, vehCol->boundingBox.max.y, 0.0f);
- break;
- case 1:
- approxWheelOffset = CVector(-vehCol->boundingBox.max.x, vehCol->boundingBox.min.y, 0.0f);
- break;
- case 2:
- approxWheelOffset = CVector(vehCol->boundingBox.max.x, vehCol->boundingBox.max.y, 0.0f);
- break;
- case 3:
- approxWheelOffset = CVector(vehCol->boundingBox.max.x, vehCol->boundingBox.min.y, 0.0f);
- break;
- default:
- break;
- }
-
- // I hope so
- CVector wheelPos = veh->GetMatrix() * approxWheelOffset;
- if (Abs(wheelPos.z - GetPosition().z) < 2.0f) {
-
- if ((wheelPos - GetPosition()).MagnitudeSqr2D() < 1.0f) {
- if (CGame::nastyGame) {
- ((CAutomobile*)veh)->m_aWheelSkidmarkBloody[wheel] = true;
- DMAudio.PlayOneShot(veh->m_audioEntityId, SOUND_SPLATTER, 0.0f);
- }
- veh->ApplyMoveForce(CVector(0.0f, 0.0f, 50.0f));
-
- CVector vehAndWheelDist = wheelPos - veh->GetPosition();
- veh->ApplyTurnForce(CVector(0.0f, 0.0f, 50.0f), vehAndWheelDist);
+ bIsInWater = true;
+ ApplyMoveForce(buoyancyImpulse);
+ if (!DyingOrDead()) {
+ if (bTryingToReachDryLand) {
+ if (buoyancyImpulse.z / m_fMass > GRAVITY * 0.4f * CTimer::GetTimeStep()) {
+ bTryingToReachDryLand = false;
+ CVector pos = GetPosition();
+ if (PlacePedOnDryLand()) {
+ if (m_fHealth > 20.0f)
+ InflictDamage(nil, WEAPONTYPE_DROWNING, 15.0f, PEDPIECE_TORSO, false);
- if (veh == FindPlayerVehicle()) {
- CPad::GetPad(0)->StartShake(300, 70);
- }
- }
- }
+ if (bIsInTheAir) {
+ RpAnimBlendClumpSetBlendDeltas(GetClump(), ASSOC_PARTIAL, -1000.0f);
+ bIsInTheAir = false;
}
+ pos.z = pos.z - 0.8f;
+#ifdef PC_PARTICLE
+ CParticleObject::AddObject(POBJECT_PED_WATER_SPLASH, pos, CVector(0.0f, 0.0f, 0.0f), 0.0f, 50, color, true);
+#else
+ CParticleObject::AddObject(POBJECT_PED_WATER_SPLASH, pos, CVector(0.0f, 0.0f, 0.0f), 0.0f, 50, CRGBA(0, 0, 0, 0), true);
+#endif
+ m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
+ m_nPedState = PED_IDLE;
+ return;
}
}
}
- }
- }
-}
-
-void
-CPed::Mug(void)
-{
- if (m_pSeekTarget && m_pSeekTarget->IsPed()) {
-
- if (CTimer::GetTimeInMilliseconds() <= m_attackTimer - 2000) {
- if ((m_pSeekTarget->GetPosition() - GetPosition()).Magnitude() > 3.0f)
- m_wepSkills = 50;
-
- Say(SOUND_PED_MUGGING);
- ((CPed*)m_pSeekTarget)->Say(SOUND_PED_ROBBED);
- } else {
- SetWanderPath(CGeneral::GetRandomNumber() & 7);
- SetFlee(m_pSeekTarget, 20000);
- }
-
- } else {
- SetIdle();
- }
-}
-
-void
-CPed::MoveHeadToLook(void)
-{
- CVector lookPos;
-
- if (m_lookTimer && CTimer::GetTimeInMilliseconds() > m_lookTimer) {
- ClearLookFlag();
- } else if (m_nPedState == PED_DRIVING) {
- m_pedIK.m_flags |= CPedIK::LOOKAROUND_HEAD_ONLY;
- }
-
- if (m_pLookTarget) {
-
- if (!bShakeFist && GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED) {
-
- CAnimBlendAssociation *fuckUAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FUCKU);
- if (fuckUAssoc) {
-
- float animTime = fuckUAssoc->currentTime;
- if (animTime > 4.0f / 30.0f && animTime - fuckUAssoc->timeStep > 4.0f / 30.0f) {
-
- bool lookingToCop = false;
- if (m_pLookTarget->GetModelIndex() == MI_POLICE
- || m_pLookTarget->IsPed() && ((CPed*)m_pLookTarget)->m_nPedType == PEDTYPE_COP) {
-
- lookingToCop = true;
- }
-
- if (IsPlayer() && (m_pedStats->m_temper >= 52 || lookingToCop)) {
- AddWeaponModel(MI_FINGERS);
- ((CPlayerPed*)this)->AnnoyPlayerPed(true);
-
- } else if ((CGeneral::GetRandomNumber() & 3) == 0) {
- AddWeaponModel(MI_FINGERS);
- }
- }
- }
- }
-
- if (m_pLookTarget->IsPed()) {
- ((CPed*)m_pLookTarget)->m_pedIK.GetComponentPosition((RwV3d*) &lookPos, PED_MID);
- } else {
- lookPos = m_pLookTarget->GetPosition();
- }
-
- if (!m_pedIK.LookAtPosition(lookPos)) {
- if (!bKeepTryingToLook) {
- ClearLookFlag();
+ float speedMult = 0.0f;
+ if (buoyancyImpulse.z / m_fMass > GRAVITY * 0.75f * CTimer::GetTimeStep()
+ || mod_Buoyancy.m_waterlevel > GetPosition().z) {
+ speedMult = pow(0.9f, CTimer::GetTimeStep());
+ m_vecMoveSpeed.x *= speedMult;
+ m_vecMoveSpeed.y *= speedMult;
+ m_vecMoveSpeed.z *= speedMult;
+ bIsStanding = false;
+ InflictDamage(nil, WEAPONTYPE_DROWNING, 3.0f * CTimer::GetTimeStep(), PEDPIECE_TORSO, 0);
}
- return;
- }
-
- if (!bShakeFist || bIsAimingGun || bIsRestoringGun)
- return;
-
- if (m_lookTimer - CTimer::GetTimeInMilliseconds() >= 1000)
- return;
-
- bool notRocketLauncher = false;
- bool notTwoHanded = false;
- AnimationId animToPlay = NUM_ANIMS;
-
- if (!GetWeapon()->IsType2Handed())
- notTwoHanded = true;
-
- if (notTwoHanded && GetWeapon()->m_eWeaponType != WEAPONTYPE_ROCKETLAUNCHER)
- notRocketLauncher = true;
-
- if (IsPlayer() && notRocketLauncher) {
-
- if (m_pLookTarget->IsPed()) {
-
- if (m_pedStats->m_temper >= 49 && ((CPed*)m_pLookTarget)->m_nPedType != PEDTYPE_COP) {
+ if (buoyancyImpulse.z / m_fMass > GRAVITY * 0.25f * CTimer::GetTimeStep()) {
+ if (speedMult == 0.0f) {
+ speedMult = pow(0.9f, CTimer::GetTimeStep());
+ }
+ m_vecMoveSpeed.x *= speedMult;
+ m_vecMoveSpeed.y *= speedMult;
+ if (m_vecMoveSpeed.z >= -0.1f) {
+ if (m_vecMoveSpeed.z < -0.04f)
+ m_vecMoveSpeed.z = -0.02f;
+ } else {
+ m_vecMoveSpeed.z = -0.01f;
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_SPLASH, 0.0f);
+#ifdef PC_PARTICLE
+ CVector aBitForward = 2.2f * m_vecMoveSpeed + GetPosition();
+ float level = 0.0f;
+ if (CWaterLevel::GetWaterLevel(aBitForward, &level, false))
+ aBitForward.z = level;
- // FIX: Unreachable and meaningless condition
-#ifndef FIX_BUGS
- if (m_pedStats->m_temper < 47)
+ CParticleObject::AddObject(POBJECT_PED_WATER_SPLASH, aBitForward, CVector(0.0f, 0.0f, 0.1f), 0.0f, 200, color, true);
+ nGenerateRaindrops = CTimer::GetTimeInMilliseconds() + 80;
+ nGenerateWaterCircles = CTimer::GetTimeInMilliseconds() + 100;
+#else
+ CVector aBitForward = 1.6f * m_vecMoveSpeed + GetPosition();
+ float level = 0.0f;
+ if (CWaterLevel::GetWaterLevel(aBitForward, &level, false))
+ aBitForward.z = level + 0.5f;
+
+ CVector vel = m_vecMoveSpeed * 0.1f;
+ vel.z = 0.18f;
+ CParticleObject::AddObject(POBJECT_PED_WATER_SPLASH, aBitForward, vel, 0.0f, 350, CRGBA(0, 0, 0, 0), true);
+ nGenerateRaindrops = CTimer::GetTimeInMilliseconds() + 300;
+ nGenerateWaterCircles = CTimer::GetTimeInMilliseconds() + 60;
#endif
- animToPlay = ANIM_FIGHT_PPUNCH;
- } else {
- animToPlay = ANIM_FUCKU;
}
- } else if (m_pedStats->m_temper > 49 || m_pLookTarget->GetModelIndex() == MI_POLICE) {
- animToPlay = ANIM_FUCKU;
}
- } else if (notRocketLauncher && (CGeneral::GetRandomNumber() & 1)) {
- animToPlay = ANIM_FUCKU;
- }
+ } else
+ return;
+ } else
+ bTouchingWater = false;
- if (animToPlay != NUM_ANIMS) {
- CAnimBlendAssociation *newAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animToPlay, 4.0f);
+ if (nGenerateWaterCircles && CTimer::GetTimeInMilliseconds() >= nGenerateWaterCircles) {
+ CVector pos = GetPosition();
+ float level = 0.0f;
+ if (CWaterLevel::GetWaterLevel(pos, &level, false))
+ pos.z = level;
- if (newAssoc) {
- newAssoc->flags |= ASSOC_FADEOUTWHENDONE;
- newAssoc->flags |= ASSOC_DELETEFADEDOUT;
- if (newAssoc->animId == ANIM_FUCKU)
- newAssoc->SetDeleteCallback(FinishFuckUCB, this);
+ if (pos.z != 0.0f) {
+ nGenerateWaterCircles = 0;
+ for(int i = 0; i < 4; i++) {
+#ifdef PC_PARTICLE
+ pos.x += CGeneral::GetRandomNumberInRange(-0.75f, 0.75f);
+ pos.y += CGeneral::GetRandomNumberInRange(-0.75f, 0.75f);
+ CParticle::AddParticle(PARTICLE_RAIN_SPLASH_BIGGROW, pos, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f, color, 0, 0, 0, 0);
+#else
+ pos.x += CGeneral::GetRandomNumberInRange(-2.5f, 2.5f);
+ pos.y += CGeneral::GetRandomNumberInRange(-2.5f, 2.5f);
+ CParticle::AddParticle(PARTICLE_RAIN_SPLASH_BIGGROW, pos+CVector(0.0f, 0.0f, 1.0f), CVector(0.0f, 0.0f, 0.0f));
+#endif
}
}
- bShakeFist = false;
- return;
- } else if (999999.0f == m_fLookDirection) {
- ClearLookFlag();
- } else if (!m_pedIK.LookInDirection(m_fLookDirection, 0.0f)) {
- if (!bKeepTryingToLook)
- ClearLookFlag();
}
-}
-void
-FinishFuckUCB(CAnimBlendAssociation *animAssoc, void *arg)
-{
- CPed *ped = (CPed*)arg;
-
- if (animAssoc->animId == ANIM_FUCKU && ped->GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED)
- ped->RemoveWeaponModel(0);
-}
-
-void
-CPed::Pause(void)
-{
- m_moved = CVector2D(0.0f, 0.0f);
- if (CTimer::GetTimeInMilliseconds() > m_leaveCarTimer)
- ClearPause();
-}
-
-void
-CPed::PedAnimAlignCB(CAnimBlendAssociation *animAssoc, void *arg)
-{
- CPed *ped = (CPed*)arg;
-
- CVehicle *veh = ped->m_pMyVehicle;
- if (animAssoc)
- animAssoc->blendDelta = -1000.0f;
-
- if (!ped->IsNotInWreckedVehicle())
- return;
-
- if (!ped->EnteringCar()) {
-#ifdef VC_PED_PORTS
- if (ped->m_nPedState != PED_DRIVING)
-#endif
- ped->QuitEnteringCar();
-
- return;
- }
- if (ped->m_fHealth == 0.0f) {
- ped->QuitEnteringCar();
- return;
- }
- bool itsVan = !!veh->bIsVan;
- bool itsBus = !!veh->bIsBus;
-#ifdef FIX_BUGS
- bool itsLow = !!veh->bLowVehicle;
-#endif
- eDoors enterDoor;
- AnimationId enterAnim;
-
- switch (ped->m_vehEnterType) {
- case CAR_DOOR_RF:
- itsVan = false;
- enterDoor = DOOR_FRONT_RIGHT;
- break;
- case CAR_DOOR_RR:
- enterDoor = DOOR_REAR_RIGHT;
- break;
- case CAR_DOOR_LF:
- itsVan = false;
- enterDoor = DOOR_FRONT_LEFT;
- break;
- case CAR_DOOR_LR:
- enterDoor = DOOR_REAR_LEFT;
- break;
- default:
- break;
- }
-
- if (veh->IsDoorMissing(enterDoor) || veh->IsDoorFullyOpen(enterDoor)) {
+ if (nGenerateRaindrops && CTimer::GetTimeInMilliseconds() >= nGenerateRaindrops) {
+ CVector pos = GetPosition();
+ float level = 0.0f;
+ if (CWaterLevel::GetWaterLevel(pos, &level, false))
+ pos.z = level;
- veh->AutoPilot.m_nCruiseSpeed = 0;
- if (ped->m_nPedState == PED_CARJACK) {
- ped->PedAnimDoorOpenCB(nil, ped);
- return;
- }
- if (enterDoor != DOOR_FRONT_LEFT && enterDoor != DOOR_REAR_LEFT) {
- if (itsVan) {
- enterAnim = ANIM_VAN_GETIN;
- } else if (itsBus) {
- enterAnim = ANIM_COACH_IN_R;
-#ifdef FIX_BUGS
- } else if (itsLow) {
- enterAnim = ANIM_CAR_GETIN_LOW_RHS;
+ if (pos.z >= 0.0f) {
+#ifdef PC_PARTICLE
+ pos.z += 0.25f;
+#else
+ pos.z += 0.5f;
#endif
- } else {
- enterAnim = ANIM_CAR_GETIN_RHS;
- }
- } else if (itsVan) {
- enterAnim = ANIM_VAN_GETIN_L;
- } else if (itsBus) {
- enterAnim = ANIM_COACH_IN_L;
-#ifdef FIX_BUGS
- } else if (itsLow) {
- enterAnim = ANIM_CAR_GETIN_LOW_LHS;
+ nGenerateRaindrops = 0;
+#ifdef PC_PARTICLE
+ CParticleObject::AddObject(POBJECT_SPLASHES_AROUND, pos, CVector(0.0f, 0.0f, 0.0f), 4.5f, 1500, CRGBA(0,0,0,0), true);
+#else
+ CParticleObject::AddObject(POBJECT_SPLASHES_AROUND, pos, CVector(0.0f, 0.0f, 0.0f), 4.5f, 2500, CRGBA(0,0,0,0), true);
#endif
- } else {
- enterAnim = ANIM_CAR_GETIN_LHS;
- }
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, enterAnim);
- ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);
-
- } else if (veh->CanPedOpenLocks(ped)) {
-
- veh->AutoPilot.m_nCruiseSpeed = 0;
- if (enterDoor != DOOR_FRONT_LEFT && enterDoor != DOOR_REAR_LEFT) {
- if (itsVan) {
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_VAN_OPEN);
- } else if (itsBus) {
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_COACH_OPEN_R);
- } else {
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_OPEN_RHS);
- }
- } else if (itsVan) {
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_VAN_OPEN_L);
- } else if (itsBus) {
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_COACH_OPEN_L);
- } else {
-
- if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER && veh->pDriver) {
-
- if (!veh->bLowVehicle
- && veh->pDriver->CharCreatedBy != MISSION_CHAR
- && veh->pDriver->m_nPedState == PED_DRIVING) {
-
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_QJACK);
- ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);
- veh->pDriver->SetBeingDraggedFromCar(veh, ped->m_vehEnterType, true);
-
- if (veh->pDriver->IsGangMember())
- veh->pDriver->RegisterThreatWithGangPeds(ped);
- return;
- }
- }
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_OPEN_LHS);
}
- ped->m_pVehicleAnim->SetFinishCallback(PedAnimDoorOpenCB, ped);
-
- } else {
- if (enterDoor != DOOR_FRONT_LEFT && enterDoor != DOOR_REAR_LEFT)
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_DOORLOCKED_RHS);
- else
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_DOORLOCKED_LHS);
-
- ped->bCancelEnteringCar = true;
- ped->m_pVehicleAnim->SetFinishCallback(PedAnimDoorOpenCB, ped);
}
}
@@ -10429,3346 +3025,458 @@ CPed::ProcessControl(void)
}
}
-void
-CPed::SetInTheAir(void)
-{
- if (bIsInTheAir)
- return;
-
- bIsInTheAir = true;
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FALL_GLIDE, 4.0f);
-
- if (m_nPedState == PED_ATTACK) {
- ClearAttack();
- ClearPointGunAt();
- } else if (m_nPedState == PED_FIGHT) {
- EndFight(ENDFIGHT_FAST);
- }
-
-}
-
-void
-CPed::RestoreHeadPosition(void)
-{
- if (m_pedIK.RestoreLookAt()) {
- bIsRestoringLook = false;
- }
-}
-
-void
-CPed::PointGunAt(void)
-{
- CWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
- CAnimBlendAssociation *weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), weaponInfo->m_AnimToPlay);
- if (!weaponAssoc || weaponAssoc->blendDelta < 0.0f)
- weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), weaponInfo->m_Anim2ToPlay);
-
- if (weaponAssoc && weaponAssoc->currentTime > weaponInfo->m_fAnimLoopStart) {
- weaponAssoc->SetCurrentTime(weaponInfo->m_fAnimLoopStart);
- weaponAssoc->flags &= ~ASSOC_RUNNING;
-
- if (weaponInfo->m_bCanAimWithArm)
- m_pedIK.m_flags |= CPedIK::AIMS_WITH_ARM;
- else
- m_pedIK.m_flags &= ~CPedIK::AIMS_WITH_ARM;
- }
-}
-
-void
-CPed::PedAnimDoorCloseCB(CAnimBlendAssociation *animAssoc, void *arg)
+int32
+CPed::ProcessEntityCollision(CEntity *collidingEnt, CColPoint *collidingPoints)
{
- CPed *ped = (CPed*)arg;
-
- CAutomobile *veh = (CAutomobile*)(ped->m_pMyVehicle);
-
- if (!ped->IsNotInWreckedVehicle() || ped->DyingOrDead())
- return;
-
- if (ped->EnteringCar()) {
- bool isLow = !!veh->bLowVehicle;
+ bool collidedWithBoat = false;
+ bool belowTorsoCollided = false;
+ float gravityEffect = -0.15f * CTimer::GetTimeStep();
+ CColPoint intersectionPoint;
+ CColLine ourLine;
- if (!veh->bIsBus)
- veh->ProcessOpenDoor(ped->m_vehEnterType, ANIM_CAR_CLOSEDOOR_LHS, 1.0f);
+ CColModel *ourCol = CModelInfo::GetModelInfo(GetModelIndex())->GetColModel();
+ CColModel *hisCol = CModelInfo::GetModelInfo(collidingEnt->GetModelIndex())->GetColModel();
- eDoors door;
- switch (ped->m_vehEnterType) {
- case CAR_DOOR_RF: door = DOOR_FRONT_RIGHT; break;
- case CAR_DOOR_RR: door = DOOR_REAR_RIGHT; break;
- case CAR_DOOR_LF: door = DOOR_FRONT_LEFT; break;
- case CAR_DOOR_LR: door = DOOR_REAR_LEFT; break;
- default: assert(0);
- }
+ if (!bUsesCollision)
+ return false;
- if (veh->Damage.GetDoorStatus(door) == DOOR_STATUS_SWINGING)
- veh->Damage.SetDoorStatus(door, DOOR_STATUS_OK);
+ if (collidingEnt->IsVehicle() && ((CVehicle*)collidingEnt)->IsBoat())
+ collidedWithBoat = true;
- if (door == DOOR_FRONT_LEFT || ped->m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER || veh->bIsBus) {
- PedSetInCarCB(nil, ped);
- } else if (ped->m_vehEnterType == CAR_DOOR_RF
- && (veh->m_nGettingInFlags & CAR_DOOR_FLAG_LF ||
- (veh->pDriver != nil &&
- (veh->pDriver->m_objective != OBJECTIVE_LEAVE_CAR
+ // ofc we're not vehicle
+ if (!m_bIsVehicleBeingShifted && !bSkipLineCol
#ifdef VC_PED_PORTS
- && veh->pDriver->m_objective != OBJECTIVE_LEAVE_CAR_AND_DIE
-#endif
- || !veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, nil))))) {
-
- if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER
-#if defined VC_PED_PORTS || defined FIX_BUGS
- || ped->m_nPedState == PED_CARJACK
+ && !collidingEnt->IsPed()
#endif
- )
- veh->bIsBeingCarJacked = false;
-
- ped->m_objective = OBJECTIVE_ENTER_CAR_AS_PASSENGER;
- PedSetInCarCB(nil, ped);
-
- ped->SetObjective(OBJECTIVE_LEAVE_CAR, veh);
- if (!ped->IsPlayer())
- ped->bFleeAfterExitingCar = true;
-
- ped->bUsePedNodeSeek = true;
- ped->m_pNextPathNode = nil;
-
- } else {
- if (animAssoc)
- animAssoc->blendDelta = -1000.0f;
-
- if (isLow)
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_LSHUFFLE_RHS);
- else
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_SHUFFLE_RHS);
-
- ped->m_pVehicleAnim->SetFinishCallback(PedSetInCarCB, ped);
- }
- } else {
+ ) {
+ if (!bCollisionProcessed) {
#ifdef VC_PED_PORTS
- if (ped->m_nPedState != PED_DRIVING)
+ m_pCurrentPhysSurface = nil;
#endif
- ped->QuitEnteringCar();
- }
-}
-
-void
-CPed::PedAnimDoorCloseRollingCB(CAnimBlendAssociation* animAssoc, void* arg)
-{
- CPed* ped = (CPed*)arg;
-
- CAutomobile* veh = (CAutomobile*)(ped->m_pMyVehicle);
-
- if (animAssoc)
- animAssoc->blendDelta = -1000.0f;
-
- if (veh->bLowVehicle) {
- veh->ProcessOpenDoor(CAR_DOOR_LF, ANIM_CAR_ROLLDOOR_LOW, 1.0f);
- } else {
- veh->ProcessOpenDoor(CAR_DOOR_LF, ANIM_CAR_ROLLDOOR, 1.0f);
- }
-
- veh->m_nGettingOutFlags &= ~CAR_DOOR_FLAG_LF;
-
- if (veh->Damage.GetDoorStatus(DOOR_FRONT_LEFT) == DOOR_STATUS_SWINGING)
- veh->Damage.SetDoorStatus(DOOR_FRONT_LEFT, DOOR_STATUS_OK);
-}
-
-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 (bIsStanding) {
+ bIsStanding = false;
+ bWasStanding = true;
+ }
+ bCollisionProcessed = true;
+ m_fCollisionSpeed += m_vecMoveSpeed.Magnitude2D() * CTimer::GetTimeStep();
+ bStillOnValidPoly = false;
+ if (IsPlayer() || m_fCollisionSpeed >= 1.0f
+ && (m_fCollisionSpeed >= 2.0f || m_nPedState != PED_WANDER_PATH)) {
+ m_collPoly.valid = false;
+ m_fCollisionSpeed = 0.0f;
+ bHitSteepSlope = false;
+ } else {
+ CVector pos = GetPosition();
+ float potentialGroundZ = GetPosition().z - FEET_OFFSET;
+ if (bWasStanding) {
+ pos.z += -0.25f;
+ potentialGroundZ += gravityEffect;
+ }
+ if (CCollision::IsStoredPolyStillValidVerticalLine(pos, potentialGroundZ, intersectionPoint, &m_collPoly)) {
+ bStillOnValidPoly = true;
#ifdef VC_PED_PORTS
- if (ped->m_nPedState != PED_DRIVING)
+ if(!bSomeVCflag1 || FEET_OFFSET + intersectionPoint.point.z < GetPosition().z) {
+ GetMatrix().GetPosition().z = FEET_OFFSET + intersectionPoint.point.z;
+ if (bSomeVCflag1)
+ bSomeVCflag1 = false;
+ }
+#else
+ GetMatrix().GetPosition().z = FEET_OFFSET + intersectionPoint.point.z;
#endif
- ped->QuitEnteringCar();
-
- return;
- }
-
- eDoors door;
- CPed *pedInSeat = nil;
- switch (ped->m_vehEnterType) {
- case CAR_DOOR_RF: door = DOOR_FRONT_RIGHT; pedInSeat = veh->pPassengers[0]; 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; 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);
+ m_vecMoveSpeed.z = 0.0f;
+ bIsStanding = true;
+ } else {
+ m_collPoly.valid = false;
+ m_fCollisionSpeed = 0.0f;
+ bHitSteepSlope = false;
}
}
}
-#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) {
- ped->QuitEnteringCar();
- if (ped->m_vehEnterType != CAR_DOOR_LF && ped->m_vehEnterType != CAR_DOOR_LR)
- ped->SetFall(1000, ANIM_KO_SPIN_R, false);
- else
- ped->SetFall(1000, ANIM_KO_SPIN_L, false);
-
- return;
- }
- veh->ProcessOpenDoor(ped->m_vehEnterType, ANIM_CAR_OPEN_LHS, 1.0f);
-
- if (ped->m_vehEnterType == CAR_DOOR_LF || ped->m_vehEnterType == CAR_DOOR_RF)
- isVan = false;
-
- if (ped->m_nPedState != PED_CARJACK || isBus) {
- AnimationId animToPlay;
- if (ped->m_vehEnterType != CAR_DOOR_LF && ped->m_vehEnterType != CAR_DOOR_LR) {
- if (isVan) {
- animToPlay = ANIM_VAN_GETIN;
- } else if (isBus) {
- animToPlay = ANIM_COACH_IN_R;
- } else if (isLow) {
- animToPlay = ANIM_CAR_GETIN_LOW_RHS;
- } else {
- animToPlay = ANIM_CAR_GETIN_RHS;
- }
- } else if (isVan) {
- animToPlay = ANIM_VAN_GETIN_L;
- } else if (isBus) {
- animToPlay = ANIM_COACH_IN_L;
- } else if (isLow) {
- animToPlay = ANIM_CAR_GETIN_LOW_LHS;
- } else {
- animToPlay = ANIM_CAR_GETIN_LHS;
- }
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, animToPlay);
- ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);
- } else {
- CPed *pedToDragOut = nil;
- switch (ped->m_vehEnterType) {
- case CAR_DOOR_RF: pedToDragOut = veh->pPassengers[0]; break;
- case CAR_DOOR_RR: pedToDragOut = veh->pPassengers[2]; break;
- case CAR_DOOR_LF: pedToDragOut = veh->pDriver; break;
- case CAR_DOOR_LR: pedToDragOut = veh->pPassengers[1]; break;
- default: assert(0);
- }
-
- if (vehUpsideDown) {
- ped->QuitEnteringCar();
- if (ped->m_nPedType == PEDTYPE_COP)
- ((CCopPed*)ped)->SetArrestPlayer(ped->m_pedInObjective);
- }
+ if (!bStillOnValidPoly) {
+ CVector potentialCenter = GetPosition();
+ potentialCenter.z = GetPosition().z - 0.52f;
- if (ped->m_vehEnterType != CAR_DOOR_LF && ped->m_vehEnterType != CAR_DOOR_LR) {
- if (pedToDragOut && !pedToDragOut->bDontDragMeOutCar) {
- if (pedToDragOut->m_nPedState != PED_DRIVING) {
- ped->QuitEnteringCar();
- pedToDragOut = nil;
+ // 0.52f should be a ped's approx. radius
+ float totalRadiusWhenCollided = collidingEnt->GetBoundRadius() + 0.52f - gravityEffect;
+ if (bWasStanding) {
+ if (collidedWithBoat) {
+ potentialCenter.z += 2.0f * gravityEffect;
+ totalRadiusWhenCollided += Abs(gravityEffect);
} else {
- if (isLow)
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_PULLOUT_LOW_RHS);
- else
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_PULLOUT_RHS);
-
- ped->m_pVehicleAnim->SetFinishCallback(PedAnimPullPedOutCB, ped);
- }
- } else if (ped->m_nPedType == PEDTYPE_COP) {
- ped->QuitEnteringCar();
- if (ped->m_pedInObjective && ped->m_pedInObjective->m_nPedState == PED_DRIVING) {
- veh->SetStatus(STATUS_PLAYER_DISABLED);
- ((CCopPed*)ped)->SetArrestPlayer(ped->m_pedInObjective);
- } else if (!veh->IsDoorMissing(DOOR_FRONT_RIGHT)) {
- ((CAutomobile*)veh)->Damage.SetDoorStatus(DOOR_FRONT_RIGHT, DOOR_STATUS_SWINGING);
+ potentialCenter.z += gravityEffect;
}
- } else {
- // BUG: Probably we will sit on top of the passenger if his m_ped_flagF4 is true.
- if (isLow)
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_GETIN_LOW_LHS);
- else
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_GETIN_LHS);
-
- ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);
}
- } else {
- if (pedToDragOut) {
- if (pedToDragOut->m_nPedState != PED_DRIVING || pedToDragOut->bDontDragMeOutCar) {
-
- // BUG: Player freezes in that condition due to its objective isn't restored. It's an unfinished feature, used in VC.
- ped->QuitEnteringCar();
- pedToDragOut = nil;
- } else {
- if (isLow)
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_PULLOUT_LOW_LHS);
- else
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_PULLOUT_LHS);
-
- ped->m_pVehicleAnim->SetFinishCallback(PedAnimPullPedOutCB, ped);
+ if (sq(totalRadiusWhenCollided) > (potentialCenter - collidingEnt->GetBoundCentre()).MagnitudeSqr()) {
+ ourLine.p0 = GetPosition();
+ ourLine.p1 = GetPosition();
+ ourLine.p1.z = GetPosition().z - FEET_OFFSET;
+ if (bWasStanding) {
+ ourLine.p1.z = ourLine.p1.z + gravityEffect;
+ ourLine.p0.z = ourLine.p0.z + -0.25f;
}
- } else {
- if (isLow)
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_GETIN_LOW_LHS);
- else
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_GETIN_LHS);
-
- ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);
- }
- }
-
- if (pedToDragOut) {
- pedToDragOut->SetBeingDraggedFromCar(veh, ped->m_vehEnterType, false);
- if (pedToDragOut->IsGangMember())
- pedToDragOut->RegisterThreatWithGangPeds(ped);
- }
- }
-
- if (veh->pDriver && ped) {
- veh->pDriver->SetLookFlag(ped, true);
- veh->pDriver->SetLookTimer(1000);
- }
- return;
-}
+ float minDist = 1.0f;
+ belowTorsoCollided = CCollision::ProcessVerticalLine(ourLine, collidingEnt->GetMatrix(), *hisCol,
+ intersectionPoint, minDist, false, &m_collPoly);
-void
-CPed::SetJump(void)
-{
- if (!bInVehicle &&
-#if defined VC_PED_PORTS || defined FIX_BUGS
- m_nPedState != PED_JUMP && !RpAnimBlendClumpGetAssociation(GetClump(), ANIM_JUMP_LAUNCH) &&
+ if (collidedWithBoat && bWasStanding && !belowTorsoCollided) {
+ ourLine.p0.z = ourLine.p1.z;
+ ourLine.p1.z = ourLine.p1.z + gravityEffect;
+ belowTorsoCollided = CCollision::ProcessVerticalLine(ourLine, collidingEnt->GetMatrix(), *hisCol,
+ intersectionPoint, minDist, false, &m_collPoly);
+ }
+ if (belowTorsoCollided) {
+#ifndef VC_PED_PORTS
+ if (!collidingEnt->IsPed()) {
#endif
- (m_nSurfaceTouched != SURFACE_STEEP_CLIFF || DotProduct(GetForward(), m_vecDamageNormal) >= 0.0f)) {
- SetStoredState();
- m_nPedState = PED_JUMP;
- CAnimBlendAssociation *jumpAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_JUMP_LAUNCH, 8.0f);
- jumpAssoc->SetFinishCallback(FinishLaunchCB, this);
- m_fRotationDest = m_fRotationCur;
- }
-}
-
-void
-CPed::RemoveInCarAnims(void)
-{
- if (!IsPlayer())
- return;
-
- CAnimBlendAssociation *animAssoc;
-
- if (m_pMyVehicle && m_pMyVehicle->bLowVehicle) {
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVE_LOW_L);
- if (animAssoc)
- animAssoc->blendDelta = -1000.0f;
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVE_LOW_R);
- if (animAssoc)
- animAssoc->blendDelta = -1000.0f;
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVEBY_L);
- if (animAssoc)
- animAssoc->blendDelta = -1000.0f;
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVEBY_R);
- if (animAssoc)
- animAssoc->blendDelta = -1000.0f;
- } else {
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVE_L);
- if (animAssoc)
- animAssoc->blendDelta = -1000.0f;
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVE_R);
- if (animAssoc)
- animAssoc->blendDelta = -1000.0f;
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVEBY_L);
- if (animAssoc)
- animAssoc->blendDelta = -1000.0f;
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVEBY_R);
- if (animAssoc)
- animAssoc->blendDelta = -1000.0f;
- }
+ if (!bIsStanding
+ || FEET_OFFSET + intersectionPoint.point.z > GetPosition().z
+ || collidedWithBoat && 3.12f + intersectionPoint.point.z > GetPosition().z) {
+ if (!collidingEnt->IsVehicle() && !collidingEnt->IsObject()) {
+ m_pCurSurface = collidingEnt;
+ collidingEnt->RegisterReference((CEntity**)&m_pCurSurface);
+ bTryingToReachDryLand = false;
+ bOnBoat = false;
+ } else {
+ m_pCurrentPhysSurface = (CPhysical*)collidingEnt;
+ collidingEnt->RegisterReference((CEntity**)&m_pCurrentPhysSurface);
+ m_vecOffsetFromPhysSurface = intersectionPoint.point - collidingEnt->GetPosition();
+ m_pCurSurface = collidingEnt;
+ collidingEnt->RegisterReference((CEntity**)&m_pCurSurface);
+ m_collPoly.valid = false;
+ if (collidingEnt->IsVehicle() && ((CVehicle*)collidingEnt)->IsBoat()) {
+ bOnBoat = true;
+ } else {
+ bOnBoat = false;
+ }
+ }
#ifdef VC_PED_PORTS
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVE_BOAT);
- if (animAssoc)
- animAssoc->blendDelta = -1000.0f;
+ if (!bSomeVCflag1 || FEET_OFFSET + intersectionPoint.point.z < GetPosition().z) {
+ GetMatrix().GetPosition().z = FEET_OFFSET + intersectionPoint.point.z;
+ if (bSomeVCflag1)
+ bSomeVCflag1 = false;
+ }
+#else
+ GetMatrix().GetPosition().z = FEET_OFFSET + intersectionPoint.point.z;
#endif
+ m_nSurfaceTouched = intersectionPoint.surfaceB;
+ if (m_nSurfaceTouched == SURFACE_STEEP_CLIFF) {
+ bHitSteepSlope = true;
+ m_vecDamageNormal = intersectionPoint.normal;
+ }
+ }
+#ifdef VC_PED_PORTS
+ float upperSpeedLimit = 0.33f;
+ float lowerSpeedLimit = -0.25f;
+ float speed = m_vecMoveSpeed.Magnitude2D();
+ if (m_nPedState == PED_IDLE) {
+ upperSpeedLimit *= 2.0f;
+ lowerSpeedLimit *= 1.5f;
+ }
+ CAnimBlendAssociation *fallAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FALL_FALL);
+ if (!bWasStanding && speed > upperSpeedLimit && (/*!bPushedAlongByCar ||*/ m_vecMoveSpeed.z < lowerSpeedLimit)
+ && m_pCollidingEntity != collidingEnt) {
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_LB);
- if (animAssoc)
- animAssoc->blendDelta = -1000.0f;
-}
-
-void
-CPed::PedAnimGetInCB(CAnimBlendAssociation *animAssoc, void *arg)
-{
- CPed *ped = (CPed*) arg;
-
- CVehicle *veh = ped->m_pMyVehicle;
- if (animAssoc)
- animAssoc->blendDelta = -1000.0f;
+ float damage = 100.0f * Max(speed - 0.25f, 0.0f);
+ float damage2 = damage;
+ if (m_vecMoveSpeed.z < -0.25f)
+ damage += (-0.25f - m_vecMoveSpeed.z) * 150.0f;
- if (!ped->IsNotInWreckedVehicle() || ped->DyingOrDead())
- return;
+ uint8 dir = 2; // from backward
+ if (m_vecMoveSpeed.x > 0.01f || m_vecMoveSpeed.x < -0.01f || m_vecMoveSpeed.y > 0.01f || m_vecMoveSpeed.y < -0.01f) {
+ CVector2D offset = -m_vecMoveSpeed;
+ dir = GetLocalDirection(offset);
+ }
- if (!ped->EnteringCar()) {
-#ifdef VC_PED_PORTS
- if(ped->m_nPedState != PED_DRIVING)
-#endif
- ped->QuitEnteringCar();
- return;
- }
+ InflictDamage(collidingEnt, WEAPONTYPE_FALL, damage, PEDPIECE_TORSO, dir);
+ if (IsPlayer() && damage2 > 5.0f)
+ Say(SOUND_PED_LAND);
- if (ped->IsPlayer() && ped->bGonnaKillTheCarJacker && ((CPlayerPed*)ped)->m_pArrestingCop) {
- PedSetInCarCB(nil, ped);
- ped->m_nLastPedState = ped->m_nPedState;
- ped->m_nPedState = PED_ARRESTED;
- ped->bGonnaKillTheCarJacker = false;
- if (veh) {
- veh->m_nNumGettingIn = 0;
- veh->m_nGettingInFlags = 0;
- veh->bIsHandbrakeOn = true;
- veh->SetStatus(STATUS_PLAYER_DISABLED);
- }
- return;
- }
- if (ped->IsPlayer() && ped->m_vehEnterType == CAR_DOOR_LF
- && (Pads[0].GetAccelerate() >= 255.0f || Pads[0].GetBrake() >= 255.0f)
- && veh->IsCar()) {
- if (((CAutomobile*)veh)->Damage.GetDoorStatus(DOOR_FRONT_LEFT) != DOOR_STATUS_MISSING)
- ((CAutomobile*)veh)->Damage.SetDoorStatus(DOOR_FRONT_LEFT, DOOR_STATUS_SWINGING);
+ } else if (!bWasStanding && fallAnim && -0.016f * CTimer::GetTimeStep() > m_vecMoveSpeed.z) {
+ InflictDamage(collidingEnt, WEAPONTYPE_FALL, 15.0f, PEDPIECE_TORSO, 2);
+ }
+#else
+ float speedSqr = 0.0f;
+ CAnimBlendAssociation *fallAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FALL_FALL);
+ if (!bWasStanding && (m_vecMoveSpeed.z < -0.25f || (speedSqr = m_vecMoveSpeed.MagnitudeSqr()) > sq(0.5f))) {
+ if (speedSqr == 0.0f)
+ speedSqr = sq(m_vecMoveSpeed.z);
- PedSetInCarCB(nil, ped);
- return;
- }
- bool isVan = !!veh->bIsVan;
- bool isBus = !!veh->bIsBus;
- bool isLow = !!veh->bLowVehicle;
- eDoors enterDoor;
- switch (ped->m_vehEnterType) {
- case CAR_DOOR_RF:
- isVan = false;
- enterDoor = DOOR_FRONT_RIGHT;
- break;
- case CAR_DOOR_RR:
- enterDoor = DOOR_REAR_RIGHT;
- break;
- case CAR_DOOR_LF:
- isVan = false;
- enterDoor = DOOR_FRONT_LEFT;
- break;
- case CAR_DOOR_LR:
- enterDoor = DOOR_REAR_LEFT;
- break;
- default:
- break;
- }
- if (!veh->IsDoorMissing(enterDoor)) {
- if (veh->IsCar())
- ((CAutomobile*)veh)->Damage.SetDoorStatus(enterDoor, DOOR_STATUS_SWINGING);
- }
- CPed *driver = veh->pDriver;
- if (driver && (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || ped->m_nPedState == PED_CARJACK)) {
- if (veh->bIsBus) {
- driver->SetObjective(OBJECTIVE_LEAVE_CAR, veh);
- if (driver->IsPlayer()) {
- veh->bIsHandbrakeOn = true;
- veh->SetStatus(STATUS_PLAYER_DISABLED);
- }
- driver->bBusJacked = true;
- veh->bIsBeingCarJacked = false;
- PedSetInCarCB(nil, ped);
- if (ped->m_nPedType == PEDTYPE_COP
- || ped->m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT
- || ped->m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS) {
- ped->SetObjective(OBJECTIVE_LEAVE_CAR, veh);
- }
- ped->m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 400;
- return;
- }
- if (driver != ped && ped->m_vehEnterType != CAR_DOOR_LF) {
- if (!driver->IsPlayer()) {
- driver->bUsePedNodeSeek = true;
- driver->m_pLastPathNode = nil;
- if (driver->m_pedStats->m_temper <= driver->m_pedStats->m_fear
- || driver->CharCreatedBy == MISSION_CHAR
- || veh->VehicleCreatedBy == MISSION_VEHICLE) {
- driver->bFleeAfterExitingCar = true;
- } else {
- driver->bGonnaKillTheCarJacker = true;
- veh->pDriver->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, ped);
+ uint8 dir = 2; // from backward
+ if (m_vecMoveSpeed.x > 0.01f || m_vecMoveSpeed.x < -0.01f || m_vecMoveSpeed.y > 0.01f || m_vecMoveSpeed.y < -0.01f) {
+ CVector2D offset = -m_vecMoveSpeed;
+ dir = GetLocalDirection(offset);
+ }
+ InflictDamage(collidingEnt, WEAPONTYPE_FALL, 350.0f * sq(speedSqr), PEDPIECE_TORSO, dir);
- if (veh->pDriver->m_nPedType == PEDTYPE_COP && ped->IsPlayer()) {
- FindPlayerPed()->SetWantedLevelNoDrop(1);
+ } else if (!bWasStanding && fallAnim && -0.016f * CTimer::GetTimeStep() > m_vecMoveSpeed.z) {
+ InflictDamage(collidingEnt, WEAPONTYPE_FALL, 15.0f, PEDPIECE_TORSO, 2);
+ }
+#endif
+ m_vecMoveSpeed.z = 0.0f;
+ bIsStanding = true;
+#ifndef VC_PED_PORTS
+ } else {
+ bOnBoat = false;
}
- }
- }
- 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);
-#ifdef VC_PED_PORTS
- veh->pDriver->SetRadioStation();
#endif
- } else {
- ped->m_objective = OBJECTIVE_ENTER_CAR_AS_PASSENGER;
- }
- }
- }
- if (veh->IsDoorMissing(enterDoor) || isBus) {
- PedAnimDoorCloseCB(nil, ped);
- } else {
- AnimationId animToPlay;
- if (enterDoor != DOOR_FRONT_LEFT && enterDoor != DOOR_REAR_LEFT) {
- if (isVan) {
- animToPlay = ANIM_VAN_CLOSE;
- } else if (isLow) {
- animToPlay = ANIM_CAR_CLOSEDOOR_LOW_RHS;
- } else {
- animToPlay = ANIM_CAR_CLOSEDOOR_RHS;
+ } else {
+ bOnBoat = false;
+ }
}
- } else if (isVan) {
- animToPlay = ANIM_VAN_CLOSE_L;
- } else if (isLow) {
- animToPlay = ANIM_CAR_CLOSEDOOR_LOW_LHS;
- } else {
- animToPlay = ANIM_CAR_CLOSEDOOR_LHS;
}
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, animToPlay);
- ped->m_pVehicleAnim->SetFinishCallback(PedAnimDoorCloseCB, ped);
}
-}
-
-void
-CPed::SetPedPositionInTrain(void)
-{
- LineUpPedWithTrain();
-}
-
-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;
- }
- }
- }
+ int ourCollidedSpheres = CCollision::ProcessColModels(GetMatrix(), *ourCol, collidingEnt->GetMatrix(), *hisCol, collidingPoints, nil, nil);
+ if (ourCollidedSpheres > 0 || belowTorsoCollided) {
+ AddCollisionRecord(collidingEnt);
+ if (!collidingEnt->IsBuilding())
+ ((CPhysical*)collidingEnt)->AddCollisionRecord(this);
- if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) {
- AnimationId animToPlay;
- if (ped->m_vehEnterType != CAR_DOOR_LF && ped->m_vehEnterType != CAR_DOOR_LR) {
- if (isLow)
- animToPlay = ANIM_CAR_GETIN_LOW_RHS;
- else
- animToPlay = ANIM_CAR_GETIN_RHS;
- } else if (isLow) {
- animToPlay = ANIM_CAR_GETIN_LOW_LHS;
- } else {
- animToPlay = ANIM_CAR_GETIN_LHS;
- }
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, animToPlay);
- ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);
- } else {
- ped->QuitEnteringCar();
+ if (ourCollidedSpheres > 0 && (collidingEnt->IsBuilding() || collidingEnt->GetIsStatic())) {
+ bHasHitWall = true;
}
- } else {
- ped->QuitEnteringCar();
}
-}
-
-void
-CPed::PedAnimStepOutCarCB(CAnimBlendAssociation* animAssoc, void* arg)
-{
- CPed* ped = (CPed*)arg;
-
- CVehicle* veh = ped->m_pMyVehicle;
- if (animAssoc)
- animAssoc->blendDelta = -1000.0f;
+ if (collidingEnt->IsBuilding() || collidingEnt->GetIsStatic()) {
- if (!veh) {
- PedSetOutCarCB(nil, ped);
- return;
- }
+ if (bWasStanding) {
+ CVector sphereNormal;
+ float normalLength;
+ for(int sphere = 0; sphere < ourCollidedSpheres; sphere++) {
+ sphereNormal = collidingPoints[sphere].normal;
#ifdef VC_PED_PORTS
- CVector posForZ = ped->GetPosition();
- CPedPlacement::FindZCoorForPed(&posForZ);
- if (ped->GetPosition().z - 0.5f > posForZ.z) {
- PedSetOutCarCB(nil, ped);
- return;
- }
+ if (sphereNormal.z >= -1.0f || !IsPlayer()) {
#endif
- veh->m_nStaticFrames = 0;
- veh->m_vecMoveSpeed += CVector(0.001f, 0.001f, 0.001f);
- veh->m_vecTurnSpeed += CVector(0.001f, 0.001f, 0.001f);
- if (!veh->bIsBus)
- veh->ProcessOpenDoor(ped->m_vehEnterType, ANIM_CAR_GETOUT_LHS, 1.0f);
-
- /*
- // Duplicate and only in PC for some reason
- if (!veh) {
- PedSetOutCarCB(nil, ped);
- return;
- }
- */
- eDoors door;
- switch (ped->m_vehEnterType) {
- case CAR_DOOR_RF:
- door = DOOR_FRONT_RIGHT;
- break;
- case CAR_DOOR_RR:
- door = DOOR_REAR_RIGHT;
- break;
- case CAR_DOOR_LF:
- door = DOOR_FRONT_LEFT;
- break;
- case CAR_DOOR_LR:
- door = DOOR_REAR_LEFT;
- break;
- default:
- break;
- }
- bool closeDoor = !veh->IsDoorMissing(door);
-
- int padNo;
- if (ped->IsPlayer()) {
-
- // BUG? This will cause crash if m_nPedType is bigger then 1, there are only 2 pads
- switch (ped->m_nPedType) {
- case PEDTYPE_PLAYER1:
- padNo = 0;
- break;
- case PEDTYPE_PLAYER2:
- padNo = 1;
- break;
- case PEDTYPE_PLAYER3:
- padNo = 2;
- break;
- case PEDTYPE_PLAYER4:
- padNo = 3;
- break;
- }
- CPad* pad = CPad::GetPad(padNo);
- bool engineIsIntact = veh->IsCar() && ((CAutomobile*)veh)->Damage.GetEngineStatus() >= 225;
- if (!pad->ArePlayerControlsDisabled() && veh->m_nDoorLock != CARLOCK_FORCE_SHUT_DOORS
- && (pad->GetTarget()
- || pad->NewState.LeftStickX
- || pad->NewState.LeftStickY
- || pad->NewState.DPadUp
- || pad->NewState.DPadDown
- || pad->NewState.DPadLeft
- || pad->NewState.DPadRight)
- || veh->bIsBus
- || veh->m_pCarFire
- || engineIsIntact) {
- closeDoor = false;
- }
- }
-
+ normalLength = sphereNormal.Magnitude2D();
+ if (normalLength != 0.0f) {
+ sphereNormal.x = sphereNormal.x / normalLength;
+ sphereNormal.y = sphereNormal.y / normalLength;
+ }
#ifdef VC_PED_PORTS
- if (ped->m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE)
- closeDoor = false;
+ } else {
+ float speed = m_vecMoveSpeed.Magnitude2D();
+ sphereNormal.x = -m_vecMoveSpeed.x / Max(0.001f, speed);
+ sphereNormal.y = -m_vecMoveSpeed.y / Max(0.001f, speed);
+ GetMatrix().GetPosition().z -= 0.05f;
+ bSomeVCflag1 = true;
+ }
#endif
-
- if (!closeDoor) {
- if (!veh->IsDoorMissing(door) && !veh->bIsBus) {
- ((CAutomobile*)veh)->Damage.SetDoorStatus(door, DOOR_STATUS_SWINGING);
- }
- PedSetOutCarCB(nil, ped);
- return;
- }
-
- if (ped->bFleeAfterExitingCar || ped->bGonnaKillTheCarJacker) {
- // POTENTIAL BUG? Why DOOR_FRONT_LEFT instead of door variable? or vice versa?
- if (!veh->IsDoorMissing(door))
- ((CAutomobile*)veh)->Damage.SetDoorStatus(DOOR_FRONT_LEFT, DOOR_STATUS_SWINGING);
- } else {
- switch (door) {
- case DOOR_FRONT_LEFT:
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_CLOSE_LHS);
- break;
- case DOOR_FRONT_RIGHT:
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_CLOSE_RHS);
- break;
- case DOOR_REAR_LEFT:
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_CLOSE_LHS);
- break;
- case DOOR_REAR_RIGHT:
- ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_CLOSE_RHS);
- break;
- default:
- break;
- }
- }
-
- if (ped->m_pVehicleAnim)
- ped->m_pVehicleAnim->SetFinishCallback(PedSetOutCarCB, ped);
- return;
-}
-
-void
-CPed::PedEvadeCB(CAnimBlendAssociation* animAssoc, void* arg)
-{
- CPed* ped = (CPed*)arg;
-
- if (!animAssoc) {
- ped->ClearLookFlag();
- if (ped->m_nPedState == PED_DIVE_AWAY || ped->m_nPedState == PED_STEP_AWAY)
- ped->RestorePreviousState();
-
- } else if (animAssoc->animId == ANIM_EV_DIVE) {
- ped->bUpdateAnimHeading = true;
- ped->ClearLookFlag();
- if (ped->m_nPedState == PED_DIVE_AWAY)
- {
- ped->m_getUpTimer = CTimer::GetTimeInMilliseconds() + 1;
- ped->m_nPedState = PED_FALL;
- }
- animAssoc->flags &= ~ASSOC_FADEOUTWHENDONE;
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
-
- } else if (animAssoc->flags & ASSOC_FADEOUTWHENDONE) {
- ped->ClearLookFlag();
- if (ped->m_nPedState == PED_DIVE_AWAY || ped->m_nPedState == PED_STEP_AWAY)
- ped->RestorePreviousState();
-
- } else if (ped->m_nPedState != PED_ARRESTED) {
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- if (animAssoc->blendDelta >= 0.0f)
- animAssoc->blendDelta = -4.0f;
-
- ped->ClearLookFlag();
- if (ped->m_nPedState == PED_DIVE_AWAY || ped->m_nPedState == PED_STEP_AWAY) {
- ped->RestorePreviousState();
+ sphereNormal.Normalise();
+ collidingPoints[sphere].normal = sphereNormal;
+ if (collidingPoints[sphere].surfaceB == SURFACE_STEEP_CLIFF)
+ bHitSteepSlope = true;
+ }
}
}
+ return ourCollidedSpheres;
}
-void
-CPed::PedGetupCB(CAnimBlendAssociation* animAssoc, void* arg)
-{
- CPed* ped = (CPed*)arg;
-
- if (ped->m_nPedState == PED_GETUP)
- RpAnimBlendClumpSetBlendDeltas(ped->GetClump(), ASSOC_PARTIAL, -1000.0f);
-
- ped->bFallenDown = false;
- animAssoc->blendDelta = -1000.0f;
- if (ped->m_nPedState == PED_GETUP)
- ped->RestorePreviousState();
-
- if (ped->m_nPedState != PED_FLEE_POS && ped->m_nPedState != PED_FLEE_ENTITY)
- ped->SetMoveState(PEDMOVE_STILL);
- else
- ped->SetMoveState(PEDMOVE_RUN);
-
- ped->SetMoveAnim();
- ped->bGetUpAnimStarted = false;
-}
-
-void
-CPed::PedLandCB(CAnimBlendAssociation* animAssoc, void* arg)
-{
- CPed* ped = (CPed*)arg;
-
- animAssoc->blendDelta = -1000.0f;
- ped->bIsLanding = false;
-
- if (ped->m_nPedState == PED_JUMP)
- ped->RestorePreviousState();
-}
-
-void
-CPed::PedSetDraggedOutCarPositionCB(CAnimBlendAssociation* animAssoc, void* arg)
+static void
+particleProduceFootSplash(CPed *ped, CVector const &pos, float size, int times)
{
- CPed *ped = (CPed*)arg;
-
- ped->bUsesCollision = true;
- ped->RestartNonPartialAnims();
- bool itsRearDoor = false;
-
- if (ped->m_vehEnterType == CAR_DOOR_RF || ped->m_vehEnterType == CAR_DOOR_RR)
- itsRearDoor = true;
-
- CMatrix pedMat(ped->GetMatrix());
- CVector posAfterBeingDragged = Multiply3x3(pedMat, (itsRearDoor ? -vecPedDraggedOutCarAnimOffset : vecPedDraggedOutCarAnimOffset));
- posAfterBeingDragged += ped->GetPosition();
-#ifndef VC_PED_PORTS
- posAfterBeingDragged.z += 1.0f;
-#endif
- CPedPlacement::FindZCoorForPed(&posAfterBeingDragged);
- ped->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
- ped->SetPosition(posAfterBeingDragged);
+#ifdef PC_PARTICLE
+ for (int i = 0; i < times; i++) {
+ CVector adjustedPos = pos;
+ adjustedPos.x += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f);
+ adjustedPos.y += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f);
- if (ped->m_pMyVehicle && !ped->m_pMyVehicle->IsRoomForPedToLeaveCar(ped->m_vehEnterType, &vecPedDraggedOutCarAnimOffset)) {
- ped->PositionPedOutOfCollision();
+ CVector direction = ped->GetForward() * -0.05f;
+ CParticle::AddParticle(PARTICLE_RAIN_SPLASHUP, adjustedPos, direction, nil, size, CRGBA(32, 32, 32, 32), 0, 0, CGeneral::GetRandomNumber() & 1, 200);
}
-
- if (!ped->CanSetPedState())
- return;
+#else
+ for ( int32 i = 0; i < times; i++ )
+ {
+ CVector adjustedPos = pos;
+ adjustedPos.x += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f);
+ adjustedPos.y += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f);
- if (!ped->m_pMyVehicle) {
- ped->SetIdle();
- ped->SetGetUp();
- return;
+ CParticle::AddParticle(PARTICLE_RAIN_SPLASHUP, adjustedPos, CVector(0.0f, 0.0f, 0.0f), nil, size, CRGBA(0, 0, 0, 0), 0, 0, CGeneral::GetRandomNumber() & 1, 200);
}
-
- 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->m_nPedState = 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()) {
-
-#ifndef VC_PED_PORTS
- if (CGeneral::GetRandomNumber() & 1)
- ped->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, driver);
- else
-#endif
- ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, ped->m_pMyVehicle);
-
- } else {
-#ifdef VC_PED_PORTS
- 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
#endif
- {
- ped->m_nPedState = PED_NONE;
- ped->m_nLastPedState = PED_NONE;
- ped->SetFindPathAndFlee(ped->m_pMyVehicle->GetPosition(), 10000);
- }
- }
- ped->SetGetUp();
}
-void
-CPed::PedSetInCarCB(CAnimBlendAssociation *animAssoc, void *arg)
+static void
+particleProduceFootDust(CPed *ped, CVector const &pos, float size, int times)
{
- CPed *ped = (CPed*)arg;
-
- CVehicle *veh = ped->m_pMyVehicle;
-
- // Pointless code
- if (!veh)
- return;
-
-#ifdef VC_PED_PORTS
- // Situation of entering car as a driver while there is already a driver exiting atm.
- CPed *driver = veh->pDriver;
- if (driver && driver->m_nPedState == PED_DRIVING && !veh->bIsBus && driver->m_objective == OBJECTIVE_LEAVE_CAR
- && (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || ped->m_nPedState == PED_CARJACK)) {
-
- if (!ped->IsPlayer() && (ped->CharCreatedBy != MISSION_CHAR || driver->IsPlayer())) {
- ped->QuitEnteringCar();
- return;
- }
- if (driver->CharCreatedBy == MISSION_CHAR) {
- PedSetOutCarCB(nil, veh->pDriver);
- if (driver->m_pMyVehicle) {
- driver->PositionPedOutOfCollision();
- } else {
- driver->m_pMyVehicle = veh;
- driver->PositionPedOutOfCollision();
- driver->m_pMyVehicle = nil;
- }
- veh->pDriver = nil;
- } else {
- driver->SetDead();
- driver->FlagToDestroyWhenNextProcessed();
- veh->pDriver = nil;
- }
- }
-#endif
-
- if (!ped->IsNotInWreckedVehicle() || ped->DyingOrDead())
- return;
-
- ped->bInVehicle = true;
- if (ped->m_nPedType == PEDTYPE_PROSTITUTE) {
- if (veh->pDriver) {
- if (veh->pDriver->IsPlayer() && ped->CharCreatedBy == RANDOM_CHAR) {
- CWorld::Players[CWorld::PlayerInFocus].m_nSexFrequency = 1000;
- CWorld::Players[CWorld::PlayerInFocus].m_nNextSexMoneyUpdateTime = CTimer::GetTimeInMilliseconds() + 1000;
- CWorld::Players[CWorld::PlayerInFocus].m_nNextSexFrequencyUpdateTime = CTimer::GetTimeInMilliseconds() + 3000;
- CWorld::Players[CWorld::PlayerInFocus].m_pHooker = (CCivilianPed*)ped;
- }
- }
- }
- if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER
-#if defined VC_PED_PORTS || defined FIX_BUGS
- || ped->m_nPedState == PED_CARJACK
-#endif
- )
- veh->bIsBeingCarJacked = false;
-
- if (veh->m_nNumGettingIn)
- --veh->m_nNumGettingIn;
-
- if (ped->IsPlayer() && ((CPlayerPed*)ped)->m_bAdrenalineActive)
- ((CPlayerPed*)ped)->ClearAdrenaline();
-
- if (veh->IsBoat()) {
- if (ped->IsPlayer()) {
-#if defined VC_PED_PORTS || defined FIX_BUGS
- CCarCtrl::RegisterVehicleOfInterest(veh);
-#endif
- if (veh->GetStatus() == STATUS_SIMPLE) {
- veh->m_vecMoveSpeed = CVector(0.0f, 0.0f, -0.00001f);
- veh->m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);
- }
- veh->SetStatus(STATUS_PLAYER);
- AudioManager.PlayerJustGotInCar();
- }
- veh->SetDriver(ped);
- if (!veh->bEngineOn)
- veh->bEngineOn = true;
-
- ped->m_nPedState = PED_DRIVING;
- ped->StopNonPartialAnims();
- return;
- }
-
- if (ped->m_pVehicleAnim)
- ped->m_pVehicleAnim->blendDelta = -1000.0f;
-
- ped->bDoBloodyFootprints = false;
- if (veh->m_nAlarmState == -1)
- veh->m_nAlarmState = 15000;
-
- if (ped->IsPlayer()) {
- if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) {
- if (veh->GetStatus() == STATUS_SIMPLE) {
- veh->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
- veh->m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);
- }
- veh->SetStatus(STATUS_PLAYER);
- }
- AudioManager.PlayerJustGotInCar();
- } else if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) {
- if (veh->GetStatus() == STATUS_SIMPLE) {
- veh->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
- veh->m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);
- }
- veh->SetStatus(STATUS_PHYSICS);
- }
-
- if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) {
- for (int i = 0; i < veh->m_nNumMaxPassengers; ++i) {
- CPed *passenger = veh->pPassengers[i];
- if (passenger && passenger->CharCreatedBy == RANDOM_CHAR) {
- passenger->SetObjective(OBJECTIVE_LEAVE_CAR, veh);
-#ifdef VC_PED_PORTS
- passenger->m_leaveCarTimer = CTimer::GetTimeInMilliseconds();
-#endif
- }
- }
- }
- // This shouldn't happen at all. Passengers can't enter with PED_CARJACK. Even though they did, we shouldn't call AddPassenger in here and SetDriver in below.
-#if !defined VC_PED_PORTS && !defined FIX_BUGS
- else if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER) {
- if (ped->m_nPedState == PED_CARJACK) {
- veh->AddPassenger(ped, 0);
- ped->m_nPedState = PED_DRIVING;
- ped->RestorePreviousObjective();
- ped->SetObjective(OBJECTIVE_LEAVE_CAR, veh);
- } else if (veh->pDriver && ped->CharCreatedBy == RANDOM_CHAR) {
- veh->AutoPilot.m_nCruiseSpeed = 17;
- }
- }
-#endif
-
- if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || ped->m_nPedState == PED_CARJACK) {
- veh->SetDriver(ped);
- if (veh->VehicleCreatedBy == PARKED_VEHICLE) {
- veh->VehicleCreatedBy = RANDOM_VEHICLE;
- ++CCarCtrl::NumRandomCars;
- --CCarCtrl::NumParkedCars;
- }
- if (veh->bIsAmbulanceOnDuty) {
- veh->bIsAmbulanceOnDuty = false;
- --CCarCtrl::NumAmbulancesOnDuty;
- }
- if (veh->bIsFireTruckOnDuty) {
- veh->bIsFireTruckOnDuty = false;
- --CCarCtrl::NumFiretrucksOnDuty;
- }
- if (ped->m_nPedType == PEDTYPE_COP && veh->IsLawEnforcementVehicle())
- veh->ChangeLawEnforcerState(true);
-
- if (!veh->bEngineOn) {
- veh->bEngineOn = true;
- DMAudio.PlayOneShot(ped->m_audioEntityId, SOUND_CAR_ENGINE_START, 1.0f);
- }
- if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER && ped->CharCreatedBy == RANDOM_CHAR
- && ped != FindPlayerPed() && ped->m_nPedType != PEDTYPE_EMERGENCY) {
-
- CCarCtrl::JoinCarWithRoadSystem(veh);
- veh->AutoPilot.m_nCarMission = MISSION_CRUISE;
- veh->AutoPilot.m_nTempAction = TEMPACT_NONE;
- veh->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;
- veh->AutoPilot.m_nCruiseSpeed = 25;
- }
- ped->m_nPedState = PED_DRIVING;
- if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) {
-
- if (ped->m_prevObjective == OBJECTIVE_RUN_TO_AREA || ped->m_prevObjective == OBJECTIVE_GOTO_CHAR_ON_FOOT || ped->m_prevObjective == OBJECTIVE_KILL_CHAR_ON_FOOT)
- ped->m_prevObjective = OBJECTIVE_NONE;
-
- ped->RestorePreviousObjective();
- }
-
- } else if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER) {
- if (veh->bIsBus) {
- veh->AddPassenger(ped);
- } else {
- switch (ped->m_vehEnterType) {
- case CAR_DOOR_RF:
- veh->AddPassenger(ped, 0);
- break;
- case CAR_DOOR_RR:
- veh->AddPassenger(ped, 2);
- break;
- case CAR_DOOR_LR:
- veh->AddPassenger(ped, 1);
- break;
- default:
- veh->AddPassenger(ped);
- break;
+ switch (ped->m_nSurfaceTouched)
+ {
+ case SURFACE_TARMAC:
+ case SURFACE_GRAVEL:
+ case SURFACE_PAVEMENT:
+ case SURFACE_SAND:
+ for (int i = 0; i < times; ++i) {
+ CVector adjustedPos = pos;
+ adjustedPos.x += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f);
+ adjustedPos.y += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f);
+ CParticle::AddParticle(PARTICLE_PEDFOOT_DUST, adjustedPos, CVector(0.0f, 0.0f, 0.0f), nil, size, CRGBA(0, 0, 0, 0), 0, 0, 0, 0);
}
- }
- ped->m_nPedState = PED_DRIVING;
- if (ped->m_prevObjective == OBJECTIVE_RUN_TO_AREA || ped->m_prevObjective == OBJECTIVE_GOTO_CHAR_ON_FOOT || ped->m_prevObjective == OBJECTIVE_KILL_CHAR_ON_FOOT)
- ped->m_prevObjective = OBJECTIVE_NONE;
-
- ped->RestorePreviousObjective();
-#ifdef VC_PED_PORTS
- if(veh->pDriver && ped->CharCreatedBy == RANDOM_CHAR)
- veh->AutoPilot.m_nCruiseSpeed = 17;
-#endif
- }
-
- veh->m_nGettingInFlags &= ~GetCarDoorFlag(ped->m_vehEnterType);
-
- if (veh->bIsBus && !veh->m_nGettingInFlags)
- ((CAutomobile*)veh)->SetBusDoorTimer(1000, 1);
-
- switch (ped->m_objective) {
- case OBJECTIVE_KILL_CHAR_ON_FOOT:
- case OBJECTIVE_KILL_CHAR_ANY_MEANS:
- case OBJECTIVE_LEAVE_CAR:
- case OBJECTIVE_FOLLOW_CAR_IN_CAR:
- case OBJECTIVE_GOTO_AREA_ANY_MEANS:
- case OBJECTIVE_GOTO_AREA_ON_FOOT:
- case OBJECTIVE_RUN_TO_AREA:
break;
default:
- ped->SetObjective(OBJECTIVE_NONE);
- }
-
- if (veh->pDriver == ped) {
- if (veh->bLowVehicle) {
- ped->m_pVehicleAnim = CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_LSIT, 100.0f);
- } else {
- ped->m_pVehicleAnim = CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_SIT, 100.0f);
- }
- } else if (veh->bLowVehicle) {
- ped->m_pVehicleAnim = CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_SITPLO, 100.0f);
- } else {
- ped->m_pVehicleAnim = CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_SITP, 100.0f);
- }
-
- ped->StopNonPartialAnims();
- if (veh->bIsBus)
- ped->bRenderPedInCar = false;
-
- // FIX: RegisterVehicleOfInterest not just registers the vehicle, but also updates register time. So remove the IsThisVehicleInteresting check.
-#ifndef FIX_BUGS
- if (ped->IsPlayer() && !CCarCtrl::IsThisVehicleInteresting(veh) && veh->VehicleCreatedBy != MISSION_VEHICLE) {
-#else
- if (ped->IsPlayer() && veh->VehicleCreatedBy != MISSION_VEHICLE) {
-#endif
- CCarCtrl::RegisterVehicleOfInterest(veh);
-
- if (!veh->bHasBeenOwnedByPlayer && veh->VehicleCreatedBy != MISSION_VEHICLE)
- CEventList::RegisterEvent(EVENT_STEAL_CAR, EVENT_ENTITY_VEHICLE, veh, ped, 1500);
-
- veh->bHasBeenOwnedByPlayer = true;
- }
- ped->bChangedSeat = true;
-}
-
-void
-CPed::PedSetInTrainCB(CAnimBlendAssociation* animAssoc, void* arg)
-{
- CPed *ped = (CPed*)arg;
- CTrain *veh = (CTrain*)ped->m_pMyVehicle;
-
- if (!veh)
- return;
-
- ped->bInVehicle = true;
- ped->m_nPedState = PED_DRIVING;
- ped->RestorePreviousObjective();
- ped->SetMoveState(PEDMOVE_STILL);
- veh->AddPassenger(ped);
-}
-
-void
-CPed::PedStaggerCB(CAnimBlendAssociation* animAssoc, void* arg)
-{
- /*
- CPed *ped = (CPed*)arg;
-
- if (ped->m_nPedState == PED_STAGGER)
- // nothing
- */
-}
-
-// It's "CPhoneInfo::ProcessNearestFreePhone" in PC IDB but that's not true, someone made it up.
-bool
-CPed::RunToReportCrime(eCrimeType crimeToReport)
-{
-#ifdef PEDS_REPORT_CRIMES_ON_PHONE
- if (bRunningToPhone) {
- if (!isPhoneAvailable(m_phoneId)) {
- m_phoneId = -1;
- bIsRunning = false;
- ClearSeek(); // clears bRunningToPhone
- return false;
- }
-
- return true;
+ break;
}
-#else
- // They changed true into false to make this function unusable. So running to phone actually starts but first frame after that cancels it.
- if (m_nPedState == PED_SEEK_POS)
- return false;
-#endif
-
- CVector pos = GetPosition();
- int phoneId = gPhoneInfo.FindNearestFreePhone(&pos);
-
- if (phoneId == -1)
- return false;
-
- CPhone *phone = &gPhoneInfo.m_aPhones[phoneId];
-#ifndef PEDS_REPORT_CRIMES_ON_PHONE
- if (phone->m_nState != PHONE_STATE_FREE)
- return false;
-#endif
-
- bRunningToPhone = true;
- SetSeek(phone->m_pEntity->GetMatrix() * -phone->m_pEntity->GetForward(), 1.0f); // original: phone.m_vecPos, 0.3f
- SetMoveState(PEDMOVE_RUN);
- bIsRunning = true; // not there in original
- m_phoneId = phoneId;
- m_crimeToReportOnPhone = crimeToReport;
- return true;
}
void
-CPed::RegisterThreatWithGangPeds(CEntity *attacker)
+CPed::PlayFootSteps(void)
{
- CPed *attackerPed = nil;
- 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())
- return;
-
- attackerPed = ((CVehicle*)attacker)->pDriver;
- if (!attackerPed)
- 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 != 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_TOYZ) {
- int16 lastVehicle;
- CEntity *vehicles[8];
- CWorld::FindObjectsInRange(GetPosition(), ENTER_CAR_MAX_DIST, 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) {
+ if (bDoBloodyFootprints) {
+ if (m_bloodyFootprintCountOrDeathTime > 0 && m_bloodyFootprintCountOrDeathTime < 300) {
+ m_bloodyFootprintCountOrDeathTime--;
- if (nearVeh->IsVehicleNormal() && nearVeh->IsCar()) {
- nearVeh->AutoPilot.m_nCruiseSpeed = GAME_SPEED_TO_CARAI_SPEED * nearVeh->pHandling->Transmission.fUnkMaxVelocity * 0.8f;
- nearVeh->AutoPilot.m_nCarMission = MISSION_RAMPLAYER_FARAWAY;
- nearVeh->SetStatus(STATUS_PHYSICS);
- nearVeh->AutoPilot.m_nTempAction = TEMPACT_NONE;
- nearVeh->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;
- }
- }
- }
- }
+ if (m_bloodyFootprintCountOrDeathTime == 0)
+ bDoBloodyFootprints = false;
}
}
-}
-
-void
-CPed::ReactToPointGun(CEntity *entWithGun)
-{
- CPed *pedWithGun = (CPed*)entWithGun;
- int waitTime;
- if (IsPlayer() || !IsPedInControl() || CharCreatedBy == MISSION_CHAR)
- return;
-
- if (m_leader == pedWithGun)
- return;
-
- if (m_nWaitState == WAITSTATE_PLAYANIM_HANDSUP || m_nWaitState == WAITSTATE_PLAYANIM_HANDSCOWER ||
- (GetPosition() - pedWithGun->GetPosition()).MagnitudeSqr2D() > 225.0f)
+ if (!bIsStanding)
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);
- }
+ CAnimBlendAssociation *assoc = RpAnimBlendClumpGetFirstAssociation(GetClump());
+ CAnimBlendAssociation *walkRunAssoc = nil;
+ float walkRunAssocBlend = 0.0f, idleAssocBlend = 0.0f;
- 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;
- }
+ for (; assoc; assoc = RpAnimBlendGetNextAssociation(assoc)) {
+ if (assoc->flags & ASSOC_WALK) {
+ walkRunAssoc = assoc;
+ walkRunAssocBlend += assoc->blendAmount;
+ } else if ((assoc->flags & ASSOC_NOWALK) == 0) {
+ idleAssocBlend += assoc->blendAmount;
}
}
-}
-
-void
-CPed::PedSetOutCarCB(CAnimBlendAssociation *animAssoc, void *arg)
-{
- CPed *ped = (CPed*)arg;
-
- CVehicle *veh = ped->m_pMyVehicle;
-
- bool startedToRun = false;
- ped->bUsesCollision = true;
- ped->m_actionX = 0.0f;
- ped->m_actionY = 0.0f;
- ped->bVehExitWillBeInstant = false;
- if (veh && veh->IsBoat())
- ped->ApplyMoveSpeed();
-
- if (ped->m_objective == OBJECTIVE_LEAVE_CAR)
- ped->RestorePreviousObjective();
-#ifdef VC_PED_PORTS
- else if (ped->m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE) {
- ped->m_fHealth = 0.0f;
- ped->SetDie(ANIM_FLOOR_HIT, 4.0f, 0.5f);
- }
-#endif
-
- ped->bInVehicle = false;
- if (veh && veh->IsCar() && !veh->IsRoomForPedToLeaveCar(ped->m_vehEnterType, nil)) {
- ped->PositionPedOutOfCollision();
- }
-
- if (ped->m_nPedState == PED_EXIT_CAR) {
- if (ped->m_nPedType == PEDTYPE_COP)
- ped->SetIdle();
- else
- ped->RestorePreviousState();
- veh = ped->m_pMyVehicle;
- if (ped->bFleeAfterExitingCar && veh) {
- ped->bFleeAfterExitingCar = false;
- ped->SetFlee(veh->GetPosition(), 12000);
- ped->bUsePedNodeSeek = true;
- ped->m_pNextPathNode = nil;
- if (CGeneral::GetRandomNumber() & 1 || ped->m_pedStats->m_fear > 70) {
- ped->SetMoveState(PEDMOVE_SPRINT);
- ped->Say(SOUND_PED_FLEE_SPRINT);
- } else {
- ped->SetMoveState(PEDMOVE_RUN);
- ped->Say(SOUND_PED_FLEE_RUN);
- }
- startedToRun = true;
-
- // This is not a good way to do this...
- ped->m_nLastPedState = PED_WANDER_PATH;
-
- } else if (ped->bWanderPathAfterExitingCar) {
- ped->SetWanderPath(CGeneral::GetRandomNumberInRange(0.0f, 8.0f));
- ped->bWanderPathAfterExitingCar = false;
- if (ped->m_nPedType == PEDTYPE_PROSTITUTE)
- ped->SetObjectiveTimer(30000);
- ped->m_nLastPedState = PED_NONE;
-
- } else if (ped->bGonnaKillTheCarJacker) {
-
- // Kill objective is already given at this point.
- ped->bGonnaKillTheCarJacker = false;
- if (ped->m_pedInObjective) {
- if (!(CGeneral::GetRandomNumber() & 1)
- && ped->m_nPedType != PEDTYPE_COP
- && (!ped->m_pedInObjective->IsPlayer() || !CTheScripts::IsPlayerOnAMission())) {
- ped->ClearObjective();
- ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, veh);
- }
- ped->m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 1500;
- }
- int waitTime = 1500;
- ped->SetWaitState(WAITSTATE_PLAYANIM_COWER, &waitTime);
- ped->SetMoveState(PEDMOVE_RUN);
- startedToRun = true;
- } else if (ped->m_objective == OBJECTIVE_NONE && ped->CharCreatedBy != MISSION_CHAR && ped->m_nPedState == PED_IDLE && !ped->IsPlayer()) {
- ped->SetWanderPath(CGeneral::GetRandomNumberInRange(0.0f, 8.0f));
- }
- }
-#ifdef VC_PED_PORTS
- else {
- ped->m_nPedState = PED_IDLE;
+#ifdef GTA_PS2_STUFF
+ CAnimBlendAssociation *runStopAsoc = NULL;
+
+ if ( IsPlayer() )
+ {
+ runStopAsoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP);
+
+ if ( runStopAsoc == NULL )
+ runStopAsoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP_R);
}
-#endif
-
- if (animAssoc)
- animAssoc->blendDelta = -1000.0f;
-
- ped->RestartNonPartialAnims();
- ped->m_pVehicleAnim = nil;
- CVector posFromZ = ped->GetPosition();
- CPedPlacement::FindZCoorForPed(&posFromZ);
- ped->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
- ped->SetPosition(posFromZ);
- veh = ped->m_pMyVehicle;
- if (veh) {
- if (ped->m_nPedType == PEDTYPE_PROSTITUTE) {
- if (veh->pDriver) {
- if (veh->pDriver->IsPlayer() && ped->CharCreatedBy == RANDOM_CHAR) {
- CWorld::Players[CWorld::PlayerInFocus].m_nNextSexMoneyUpdateTime = 0;
- CWorld::Players[CWorld::PlayerInFocus].m_nNextSexFrequencyUpdateTime = 0;
- CWorld::Players[CWorld::PlayerInFocus].m_pHooker = nil;
- CWorld::Players[CWorld::PlayerInFocus].m_nMoney -= 100;
- if (CWorld::Players[CWorld::PlayerInFocus].m_nMoney < 0)
- CWorld::Players[CWorld::PlayerInFocus].m_nMoney = 0;
- }
- }
- }
- veh->m_nGettingOutFlags &= ~GetCarDoorFlag(ped->m_vehEnterType);
- if (veh->pDriver == ped) {
- veh->RemoveDriver();
- veh->SetStatus(STATUS_ABANDONED);
- if (veh->m_nDoorLock == CARLOCK_LOCKED_INITIALLY)
- veh->m_nDoorLock = CARLOCK_UNLOCKED;
- if (ped->m_nPedType == PEDTYPE_COP && veh->IsLawEnforcementVehicle())
- veh->ChangeLawEnforcerState(false);
- } else {
- veh->RemovePassenger(ped);
+
+ if ( runStopAsoc != NULL && runStopAsoc->blendAmount > 0.1f )
+ {
+ {
+ CVector pos(0.0f, 0.0f, 0.0f);
+ TransformToNode(pos, PED_FOOTL);
+
+ pos.z -= 0.1f;
+ pos += GetForward()*0.2f;
+ particleProduceFootDust(this, pos, 0.02f, 1);
}
- if (veh->bIsBus && !veh->IsUpsideDown() && !veh->IsOnItsSide()) {
- float angleAfterExit;
- if (ped->m_vehEnterType == CAR_DOOR_LF) {
- angleAfterExit = HALFPI + veh->GetForward().Heading();
- } else {
- angleAfterExit = veh->GetForward().Heading() - HALFPI;
- }
- ped->SetHeading(angleAfterExit);
- ped->m_fRotationDest = angleAfterExit;
- ped->m_fRotationCur = angleAfterExit;
- if (!ped->bBusJacked)
- ped->SetMoveState(PEDMOVE_WALK);
+ {
+ CVector pos(0.0f, 0.0f, 0.0f);
+ TransformToNode(pos, PED_FOOTR);
+
+ pos.z -= 0.1f;
+ pos += GetForward()*0.2f;
+ particleProduceFootDust(this, pos, 0.02f, 1);
}
- if (CGarages::IsPointWithinAnyGarage(ped->GetPosition()))
- veh->bLightsOn = false;
- }
-
- if (ped->IsPlayer())
- AudioManager.PlayerJustLeftCar();
-
- ped->ReplaceWeaponWhenExitingVehicle();
-
- ped->bOnBoat = false;
- if (ped->bBusJacked) {
- ped->SetFall(1500, ANIM_KO_SKID_BACK, false);
- ped->bBusJacked = false;
}
- ped->m_nStoredMoveState = PEDMOVE_NONE;
- if (!ped->IsPlayer()) {
- // It's a shame...
-#ifdef FIX_BUGS
- int createdBy = ped->CharCreatedBy;
-#else
- int createdBy = !ped->CharCreatedBy;
#endif
+
- if (createdBy == MISSION_CHAR && !startedToRun)
- ped->SetMoveState(PEDMOVE_WALK);
- }
-}
-
-// It was inlined in III but not in VC.
-inline void
-CPed::ReplaceWeaponWhenExitingVehicle(void)
-{
- eWeaponType weaponType = GetWeapon()->m_eWeaponType;
-
- // If it's Uzi, we may have stored weapon. Uzi is the only gun we can use in car.
- if (IsPlayer() && weaponType == WEAPONTYPE_UZI) {
- if (/*IsPlayer() && */ m_storedWeapon != WEAPONTYPE_UNIDENTIFIED) {
- SetCurrentWeapon(m_storedWeapon);
- m_storedWeapon = WEAPONTYPE_UNIDENTIFIED;
- }
- } else {
- AddWeaponModel(CWeaponInfo::GetWeaponInfo(weaponType)->m_nModelId);
- }
-}
-
-// Same, it's inlined in III.
-inline void
-CPed::RemoveWeaponWhenEnteringVehicle(void)
-{
- if (IsPlayer() && HasWeapon(WEAPONTYPE_UZI) && GetWeapon(WEAPONTYPE_UZI).m_nAmmoTotal > 0) {
- if (m_storedWeapon == WEAPONTYPE_UNIDENTIFIED)
- m_storedWeapon = GetWeapon()->m_eWeaponType;
- SetCurrentWeapon(WEAPONTYPE_UZI);
- } else {
- CWeaponInfo *ourWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
- RemoveWeaponModel(ourWeapon->m_nModelId);
- }
-}
-
-void
-CPed::PedSetOutTrainCB(CAnimBlendAssociation *animAssoc, void *arg)
-{
- CPed *ped = (CPed*)arg;
-
- CVehicle *veh = ped->m_pMyVehicle;
-
- if (ped->m_pVehicleAnim)
- ped->m_pVehicleAnim->blendDelta = -1000.0f;
-
- ped->bUsesCollision = true;
- ped->m_pVehicleAnim = nil;
- ped->bInVehicle = false;
- ped->m_nPedState = PED_IDLE;
- ped->RestorePreviousObjective();
- ped->SetMoveState(PEDMOVE_STILL);
-
- CMatrix pedMat(ped->GetMatrix());
- ped->m_fRotationCur = HALFPI + veh->GetForward().Heading();
- ped->m_fRotationDest = ped->m_fRotationCur;
- CVector posAfterExit = Multiply3x3(pedMat, vecPedTrainDoorAnimOffset);
- posAfterExit += ped->GetPosition();
- CPedPlacement::FindZCoorForPed(&posAfterExit);
- ped->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
- ped->SetPosition(posAfterExit);
- ped->SetHeading(ped->m_fRotationCur);
- veh->RemovePassenger(ped);
-}
-
-bool
-CPed::PlacePedOnDryLand(void)
-{
- float waterLevel = 0.0f;
- CEntity *foundEnt = nil;
- CColPoint foundCol;
- float foundColZ;
-
- CWaterLevel::GetWaterLevelNoWaves(GetPosition().x, GetPosition().y, GetPosition().z, &waterLevel);
-
- CVector potentialGround = GetPosition();
- potentialGround.z = waterLevel;
-
- if (!CWorld::TestSphereAgainstWorld(potentialGround, 5.0f, nil, true, false, false, false, false, false))
- return false;
-
- CVector potentialGroundDist = gaTempSphereColPoints[0].point - GetPosition();
- potentialGroundDist.z = 0.0f;
- potentialGroundDist.Normalise();
-
- CVector posToCheck = 0.5f * potentialGroundDist + gaTempSphereColPoints[0].point;
- posToCheck.z = 3.0f + waterLevel;
-
- if (CWorld::ProcessVerticalLine(posToCheck, waterLevel - 1.0f, foundCol, foundEnt, true, true, false, true, false, false, nil)) {
- foundColZ = foundCol.point.z;
- if (foundColZ >= waterLevel) {
- posToCheck.z = 0.8f + foundColZ;
- SetPosition(posToCheck);
- bIsStanding = true;
- bWasStanding = true;
- return true;
- }
- }
-
- posToCheck = 5.0f * potentialGroundDist + GetPosition();
- posToCheck.z = 3.0f + waterLevel;
-
- if (!CWorld::ProcessVerticalLine(posToCheck, waterLevel - 1.0f, foundCol, foundEnt, true, true, false, true, false, false, nil))
- return false;
-
- foundColZ = foundCol.point.z;
- if (foundColZ < waterLevel)
- return false;
-
- posToCheck.z = 0.8f + foundColZ;
- SetPosition(posToCheck);
- bIsStanding = true;
- bWasStanding = true;
- return true;
-}
-
-void
-CPed::PedSetQuickDraggedOutCarPositionCB(CAnimBlendAssociation *animAssoc, void *arg)
-{
- CPed *ped = (CPed*)arg;
-
- CVehicle *veh = ped->m_pMyVehicle;
-
- CVector finalPos;
- CVector draggedOutOffset;
-
- CMatrix pedMat(ped->GetMatrix());
- ped->bUsesCollision = true;
- ped->RestartNonPartialAnims();
- draggedOutOffset = vecPedQuickDraggedOutCarAnimOffset;
- if (ped->m_vehEnterType == CAR_DOOR_RF || ped->m_vehEnterType == CAR_DOOR_RR)
- draggedOutOffset.x = -draggedOutOffset.x;
-
- finalPos = Multiply3x3(pedMat, draggedOutOffset) + ped->GetPosition();
- CPedPlacement::FindZCoorForPed(&finalPos);
- ped->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
- ped->SetPosition(finalPos);
+ if (walkRunAssoc && walkRunAssocBlend > 0.5f && idleAssocBlend < 1.0f) {
+ float stepStart = 1 / 15.0f;
+ float stepEnd = walkRunAssoc->hierarchy->totalLength / 2.0f + stepStart;
+ float currentTime = walkRunAssoc->currentTime;
+ int stepPart = 0;
- if (veh) {
- ped->m_fRotationDest = veh->GetForward().Heading() - HALFPI;
- ped->m_fRotationCur = ped->m_fRotationDest;
- ped->CalculateNewOrientation();
+ if (currentTime >= stepStart && currentTime - walkRunAssoc->timeStep < stepStart)
+ stepPart = 1;
+ else if (currentTime >= stepEnd && currentTime - walkRunAssoc->timeStep < stepEnd)
+ stepPart = 2;
- if (!veh->IsRoomForPedToLeaveCar(ped->m_vehEnterType, &vecPedQuickDraggedOutCarAnimOffset))
- ped->PositionPedOutOfCollision();
- }
+ if (stepPart != 0) {
+ DMAudio.PlayOneShot(m_audioEntityId, stepPart == 1 ? SOUND_STEP_START : SOUND_STEP_END, 1.0f);
+ CVector footPos(0.0f, 0.0f, 0.0f);
+ TransformToNode(footPos, stepPart == 1 ? PED_FOOTL : PED_FOOTR);
- if (!ped->CanSetPedState())
- return;
+ CVector forward = GetForward();
- ped->SetIdle();
- if (veh) {
- if (ped->bFleeAfterExitingCar) {
- ped->bFleeAfterExitingCar = false;
- ped->SetFlee(veh->GetPosition(), 14000);
+ footPos.z -= 0.1f;
+ footPos += 0.2f * forward;
- } else if (ped->bWanderPathAfterExitingCar) {
- ped->SetWanderPath(CGeneral::GetRandomNumberInRange(0.0f, 8.0f));
- ped->bWanderPathAfterExitingCar = false;
+ if (bDoBloodyFootprints) {
+ CVector2D top(forward * 0.26f);
+ CVector2D right(GetRight() * 0.14f);
- } 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);
+ CShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpBloodPoolTex, &footPos,
+ top.x, top.y,
+ right.x, right.y,
+ 255, 255, 0, 0, 4.0f, 3000.0f, 1.0f);
- } else {
- CPed *driver = veh->pDriver;
- if (!driver || driver == ped || driver->IsPlayer() && CTheScripts::IsPlayerOnAMission()) {
- ped->SetFlee(veh->GetPosition(), 14000);
+ if (m_bloodyFootprintCountOrDeathTime <= 20) {
+ m_bloodyFootprintCountOrDeathTime = 0;
+ bDoBloodyFootprints = false;
} 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()) {
-
-#ifndef VC_PED_PORTS
- if (CGeneral::GetRandomNumber() < MYRAND_MAX / 2) {
- ped->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, veh->pDriver);
- } else
-#endif
- ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, veh);
-
-#ifdef VC_PED_PORTS
- } 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);
-#endif
- } 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;
-}
-
-bool
-CPed::PositionPedOutOfCollision(void)
-{
- CVehicle *veh;
- CVector posNearVeh;
- CVector posSomewhereClose;
- bool putNearVeh = false;
- bool putSomewhereClose = false;
- int smallestDistNearVeh = 999;
- int smallestDistSomewhereClose = 999;
-
- if (!m_pMyVehicle)
- return false;
-
- CVector vehPos = m_pMyVehicle->GetPosition();
- CVector potentialPos;
- potentialPos.y = GetPosition().y - 3.5f;
- potentialPos.z = GetPosition().z;
-
- for (int yTry = 0; yTry < 15; yTry++) {
- potentialPos.x = GetPosition().x - 3.5f;
-
- for (int xTry = 0; xTry < 15; xTry++) {
- CPedPlacement::FindZCoorForPed(&potentialPos);
- CVector distVec = potentialPos - vehPos;
- float dist = distVec.Magnitude();
-
- // Makes close distances bigger for some reason.
- float mult = (0.6f + dist) / dist;
- CVector adjustedPotentialPos = distVec * mult + vehPos;
- if (CWorld::GetIsLineOfSightClear(vehPos, adjustedPotentialPos, true, false, false, true, false, false, false)
- && !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;
+ m_bloodyFootprintCountOrDeathTime -= 20;
}
}
- 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::PossiblyFindBetterPosToSeekCar(CVector *pos, CVehicle *veh)
-{
- bool foundIt = false;
-
- CVector helperPos = GetPosition();
- helperPos.z = pos->z - 0.5f;
-
- CVector foundPos = *pos;
- foundPos.z -= 0.5f;
-
- // If there is another car between target car and us.
- if (CWorld::TestSphereAgainstWorld((foundPos + helperPos) / 2.0f, 0.25f, veh, false, true, false, false, false, false)) {
-
- CColModel *vehCol = veh->GetModelInfo()->GetColModel();
- CVector *colMin = &vehCol->boundingBox.min;
- CVector *colMax = &vehCol->boundingBox.max;
-
- CVector leftRearPos = CVector(colMin->x - 0.5f, colMin->y - 0.5f, 0.0f);
- CVector rightRearPos = CVector(0.5f + colMax->x, colMin->y - 0.5f, 0.0f);
- CVector leftFrontPos = CVector(colMin->x - 0.5f, 0.5f + colMax->y, 0.0f);
- CVector rightFrontPos = CVector(0.5f + colMax->x, 0.5f + colMax->y, 0.0f);
-
- leftRearPos = veh->GetMatrix() * leftRearPos;
- rightRearPos = veh->GetMatrix() * rightRearPos;
- leftFrontPos = veh->GetMatrix() * leftFrontPos;
- rightFrontPos = veh->GetMatrix() * rightFrontPos;
-
- // Makes helperPos veh-ped distance vector.
- helperPos -= veh->GetPosition();
-
- // ?!? I think it's absurd to use this unless another function like SeekCar finds next pos. with it and we're trying to simulate it's behaviour.
- // On every run it returns another pos. for ped, with same distance to the veh.
- // Sequence of positions are not guaranteed, it depends on global pos. (So sometimes it returns positions to make ped draw circle, sometimes don't)
- helperPos = veh->GetMatrix() * helperPos;
-
- float vehForwardHeading = veh->GetForward().Heading();
-
- // I'm absolutely not sure about these namings.
- // NTVF = needed turn if we're looking to vehicle front and wanna look to...
-
- float potentialLrHeading = Atan2(leftRearPos.x - helperPos.x, leftRearPos.y - helperPos.y);
- float NTVF_LR = CGeneral::LimitRadianAngle(potentialLrHeading - vehForwardHeading);
-
- float potentialRrHeading = Atan2(rightRearPos.x - helperPos.x, rightRearPos.y - helperPos.y);
- float NTVF_RR = CGeneral::LimitRadianAngle(potentialRrHeading - vehForwardHeading);
-
- float potentialLfHeading = Atan2(leftFrontPos.x - helperPos.x, leftFrontPos.y - helperPos.y);
- float NTVF_LF = CGeneral::LimitRadianAngle(potentialLfHeading - vehForwardHeading);
-
- float potentialRfHeading = Atan2(rightFrontPos.x - helperPos.x, rightFrontPos.y - helperPos.y);
- float NTVF_RF = CGeneral::LimitRadianAngle(potentialRfHeading - vehForwardHeading);
-
- bool canHeadToLr = NTVF_LR <= -PI || NTVF_LR >= -HALFPI;
-
- bool canHeadToRr = NTVF_RR <= HALFPI || NTVF_RR >= PI;
-
- bool canHeadToLf = NTVF_LF >= 0.0f || NTVF_LF <= -HALFPI;
-
- bool canHeadToRf = NTVF_RF <= 0.0f || NTVF_RF >= HALFPI;
-
- // Only order of conditions are different among enterTypes.
- if (m_vehEnterType == CAR_DOOR_RR) {
- if (canHeadToRr) {
- foundPos = rightRearPos;
- foundIt = true;
- } else if (canHeadToRf) {
- foundPos = rightFrontPos;
- foundIt = true;
- } else if (canHeadToLr) {
- foundPos = leftRearPos;
- foundIt = true;
- } else if (canHeadToLf) {
- foundPos = leftFrontPos;
- foundIt = true;
- }
- } else if(m_vehEnterType == CAR_DOOR_RF) {
- if (canHeadToRf) {
- foundPos = rightFrontPos;
- foundIt = true;
- } else if (canHeadToRr) {
- foundPos = rightRearPos;
- foundIt = true;
- } else if (canHeadToLf) {
- foundPos = leftFrontPos;
- foundIt = true;
- } else if (canHeadToLr) {
- foundPos = leftRearPos;
- foundIt = true;
- }
- } else if (m_vehEnterType == CAR_DOOR_LF) {
- if (canHeadToLf) {
- foundPos = leftFrontPos;
- foundIt = true;
- } else if (canHeadToLr) {
- foundPos = leftRearPos;
- foundIt = true;
- } else if (canHeadToRf) {
- foundPos = rightFrontPos;
- foundIt = true;
- } else if (canHeadToRr) {
- foundPos = rightRearPos;
- foundIt = true;
- }
- } else if (m_vehEnterType == CAR_DOOR_LR) {
- if (canHeadToLr) {
- foundPos = leftRearPos;
- foundIt = true;
- } else if (canHeadToLf) {
- foundPos = leftFrontPos;
- foundIt = true;
- } else if (canHeadToRr) {
- foundPos = rightRearPos;
- foundIt = true;
- } else if (canHeadToRf) {
- foundPos = rightFrontPos;
- foundIt = true;
+ if (CWeather::Rain <= 0.1f || CCullZones::CamNoRain() || CCullZones::PlayerNoRain()) {
+ if(IsPlayer())
+ particleProduceFootDust(this, footPos, 0.0f, 4);
}
- }
- }
- if (!foundIt)
- return false;
-
- helperPos = GetPosition() - foundPos;
- helperPos.z = 0.0f;
- if (helperPos.MagnitudeSqr() <= sq(0.5f))
- return false;
-
- pos->x = foundPos.x;
- pos->y = foundPos.y;
- return true;
-}
-
-void
-CPed::Render(void)
-{
- if (bInVehicle && m_nPedState != PED_EXIT_CAR && m_nPedState != PED_DRAG_FROM_CAR) {
- if (!bRenderPedInCar)
- return;
-
- float camDistSq = (TheCamera.GetPosition() - GetPosition()).MagnitudeSqr();
- if (camDistSq > SQR(25.0f * TheCamera.LODDistMultiplier))
- return;
- }
-
- CEntity::Render();
-
-#ifdef PED_SKIN
- if(IsClumpSkinned(GetClump())){
- renderLimb(PED_HEAD);
- renderLimb(PED_HANDL);
- renderLimb(PED_HANDR);
- }
- if(m_pWeaponModel && IsClumpSkinned(GetClump())){
- RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(GetClump());
- int idx = RpHAnimIDGetIndex(hier, m_pFrames[PED_HANDR]->nodeID);
- RwMatrix *mat = &RpHAnimHierarchyGetMatrixArray(hier)[idx];
- RwFrame *frame = RpAtomicGetFrame(m_pWeaponModel);
- *RwFrameGetMatrix(frame) = *mat;
- RwFrameUpdateObjects(frame);
- RpAtomicRender(m_pWeaponModel);
- }
-#endif
-}
-
-#ifdef PED_SKIN
-static RpMaterial*
-SetLimbAlphaCB(RpMaterial *material, void *data)
-{
- ((RwRGBA*)RpMaterialGetColor(material))->alpha = *(uint8*)data;
- return material;
-}
-
-void
-CPed::renderLimb(int node)
-{
- RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(GetClump());
- int idx = RpHAnimIDGetIndex(hier, m_pFrames[node]->nodeID);
- RwMatrix *mat = &RpHAnimHierarchyGetMatrixArray(hier)[idx];
- CPedModelInfo *mi = (CPedModelInfo *)CModelInfo::GetModelInfo(GetModelIndex());
- RpAtomic *atomic;
- switch(node){
- case PED_HEAD:
- atomic = mi->getHead();
- break;
- case PED_HANDL:
- atomic = mi->getLeftHand();
- break;
- case PED_HANDR:
- atomic = mi->getRightHand();
- break;
- default:
- return;
- }
- if(atomic == nil)
- return;
-
- RwFrame *frame = RpAtomicGetFrame(atomic);
- *RwFrameGetMatrix(frame) = *mat;
- RwFrameUpdateObjects(frame);
- int alpha = CVisibilityPlugins::GetClumpAlpha(GetClump());
- RpGeometryForAllMaterials(RpAtomicGetGeometry(atomic), SetLimbAlphaCB, &alpha);
- RpAtomicRender(atomic);
-}
+#ifdef PC_PARTICLE
+ else if(stepPart == 2)
+#else
+ else
#endif
-
-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_NONE:
- case OBJECTIVE_GUARD_AREA:
- case OBJECTIVE_FOLLOW_CAR_IN_CAR:
- case OBJECTIVE_FIRE_AT_OBJECT_FROM_VEHICLE:
- case OBJECTIVE_DESTROY_OBJECT:
- case OBJECTIVE_GOTO_AREA_IN_CAR:
- case OBJECTIVE_FOLLOW_CAR_ON_FOOT_WITH_OFFSET:
- case OBJECTIVE_SET_LEADER:
- break;
- case OBJECTIVE_WAIT_ON_FOOT:
- SetIdle();
- m_objective = OBJECTIVE_NONE;
- SetMoveState(PEDMOVE_STILL);
- break;
- case OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE:
- 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_vecSeekPosEx - 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_distanceToCountSeekDoneEx >= distWithTargetSc) {
- if (m_pedInObjective) {
- if (distWithTargetSc <= m_distanceToCountSeekDoneEx)
- SetIdle();
- else
- SetSeek(m_vecSeekPosEx, m_distanceToCountSeekDoneEx);
- } 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 {
- SetSeek(m_vecSeekPosEx, m_distanceToCountSeekDoneEx);
- }
- break;
- }
- case OBJECTIVE_WAIT_IN_CAR:
- m_nPedState = PED_DRIVING;
- break;
- case OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT:
- m_nPedState = 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->m_nGettingInFlags) {
- m_pMyVehicle->SetStatus(STATUS_PHYSICS);
- m_pMyVehicle->AutoPilot.m_nPrevRouteNode = 0;
- if (m_nPedType == PEDTYPE_COP) {
- m_pMyVehicle->AutoPilot.m_nCruiseSpeed = (FindPlayerPed()->m_pWanted->m_nWantedLevel * 0.1f + 0.6f) * (GAME_SPEED_TO_CARAI_SPEED * m_pMyVehicle->pHandling->Transmission.fUnkMaxVelocity);
- m_pMyVehicle->AutoPilot.m_nCarMission = CCarAI::FindPoliceCarMissionForWantedLevel();
- } else {
- m_pMyVehicle->AutoPilot.m_nCruiseSpeed = GAME_SPEED_TO_CARAI_SPEED * m_pMyVehicle->pHandling->Transmission.fUnkMaxVelocity * 0.8f;
- m_pMyVehicle->AutoPilot.m_nCarMission = MISSION_RAMPLAYER_FARAWAY;
- }
- m_pMyVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;
- }
- } else {
- bool targetHasVeh = m_pedInObjective->bInVehicle;
- if (!targetHasVeh
- || targetHasVeh && m_pedInObjective->m_pMyVehicle->CanPedExitCar()) {
- 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(), 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.Magnitude() < closestVehDist && m_pedInObjective->m_pMyVehicle != nearVeh
- && nearVeh->CanPedOpenLocks(this)) {
-
- 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, &ourPos, &chosenCarClass);
- CAutomobile *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:
- {
- bool killPlayerInNoPoliceZone = false;
- if (m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT && InVehicle()) {
- SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);
- break;
- }
- if (!m_pedInObjective || m_pedInObjective->DyingOrDead()) {
- ClearLookFlag();
- bObjectiveCompleted = true;
- SetMoveAnim();
- break;
- }
- if (m_pedInObjective->IsPlayer() && CCullZones::NoPolice())
- killPlayerInNoPoliceZone = true;
-
- if (!bNotAllowedToDuck || killPlayerInNoPoliceZone) {
- if (m_nPedType == PEDTYPE_COP && !m_pedInObjective->GetWeapon()->IsTypeMelee() && !GetWeapon()->IsTypeMelee())
- bNotAllowedToDuck = true;
- } else {
- if (!m_pedInObjective->bInVehicle) {
- if (m_pedInObjective->GetWeapon()->IsTypeMelee() || GetWeapon()->IsTypeMelee()) {
- bNotAllowedToDuck = false;
- bCrouchWhenShooting = false;
- } else if (DuckAndCover()) {
- break;
- }
- } else {
- bNotAllowedToDuck = false;
- bCrouchWhenShooting = false;
- }
- }
- if (m_leaveCarTimer > CTimer::GetTimeInMilliseconds() && !bKindaStayInSamePlace) {
- SetMoveState(PEDMOVE_STILL);
- break;
- }
- 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();
-
- break;
- }
- }
- CWeaponInfo *wepInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
- float wepRange = wepInfo->m_fRange;
- float wepRangeAdjusted;
- if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED) {
- wepRangeAdjusted = wepRange / 3.0f;
- } else {
- if (m_nPedState == PED_FIGHT) {
- if (!IsPlayer() && !(m_pedStats->m_flags & STAT_CAN_KICK))
- wepRange = 2.0f;
- } else {
- wepRange = 1.3f;
- }
- wepRangeAdjusted = wepRange;
- }
- if (m_pedInObjective->m_getUpTimer > CTimer::GetTimeInMilliseconds() && wepRangeAdjusted < 2.5f) {
- wepRangeAdjusted = 2.5f;
- }
- if (m_pedInObjective->IsPlayer() && m_nPedType != PEDTYPE_COP
- && CharCreatedBy != MISSION_CHAR && FindPlayerPed()->m_pWanted->m_CurrentCops) {
- SetObjective(OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE);
- break;
- }
- if (m_pedInObjective->m_fHealth <= 0.0f) {
- bObjectiveCompleted = true;
- bScriptObjectiveCompleted = true;
- SetMoveAnim();
- break;
- }
- 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;
- }
- SetLookFlag(vehOfTarget, false);
- if (m_nPedState != PED_CARJACK) {
- if (m_pedInObjective->m_nPedState != PED_ARRESTED) {
- if (m_attackTimer < CTimer::GetTimeInMilliseconds() && wepInfo->m_eWeaponFire != WEAPON_FIRE_MELEE
- && distWithTargetSc < wepRange && distWithTargetSc > 3.0f) {
-
- // I hope so
- CVector ourHead = GetMatrix() * CVector(0.5f, 0.0f, 0.6f);
- CVector maxShotPos = vehOfTarget->GetPosition() - ourHead;
- maxShotPos.Normalise();
- maxShotPos = maxShotPos * wepInfo->m_fRange + ourHead;
-
- CWorld::bIncludeDeadPeds = true;
- CColPoint foundCol;
- CEntity *foundEnt;
- CWorld::ProcessLineOfSight(ourHead, maxShotPos, foundCol, foundEnt,
- true, true, true, true, false, true, false);
- CWorld::bIncludeDeadPeds = false;
- if (foundEnt == vehOfTarget) {
- SetAttack(vehOfTarget);
- m_pPointGunAt = vehOfTarget;
- if (vehOfTarget)
- vehOfTarget->RegisterReference((CEntity **) &m_pPointGunAt);
-
- SetShootTimer(CGeneral::GetRandomNumberInRange(500, 2000));
- if (distWithTargetSc <= m_distanceToCountSeekDone) {
- SetAttackTimer(CGeneral::GetRandomNumberInRange(200, 500));
- SetMoveState(PEDMOVE_STILL);
- } else {
- SetAttackTimer(CGeneral::GetRandomNumberInRange(2000, 5000));
- }
- }
- }
- else if (m_nPedState != PED_ATTACK && !bKindaStayInSamePlace && !killPlayerInNoPoliceZone) {
- if (vehOfTarget) {
- if (m_nPedType == PEDTYPE_COP || vehOfTarget->bIsBus) {
- GoToNearestDoor(vehOfTarget);
- } else {
- m_vehEnterType = 0;
- if (m_pedInObjective == vehOfTarget->pDriver || vehOfTarget->bIsBus) {
- m_vehEnterType = CAR_DOOR_LF;
- } else if (m_pedInObjective == vehOfTarget->pPassengers[0]) {
- m_vehEnterType = CAR_DOOR_RF;
- } else if (m_pedInObjective == vehOfTarget->pPassengers[1]) {
- m_vehEnterType = CAR_DOOR_LR;
- } else if (m_pedInObjective == vehOfTarget->pPassengers[2]) {
- m_vehEnterType = CAR_DOOR_RR;
- }
- // Unused
- // GetPositionToOpenCarDoor(vehOfTarget, m_vehEnterType);
- SetSeekCar(vehOfTarget, m_vehEnterType);
- SetMoveState(PEDMOVE_RUN);
- }
- }
- }
- }
- }
- SetMoveAnim();
- break;
- }
- if (m_nMoveState == PEDMOVE_STILL && IsPedInControl()) {
- SetLookFlag(m_pedInObjective, false);
- TurnBody();
- }
- if (m_nPedType == PEDTYPE_COP && distWithTargetSc < 1.5f && m_pedInObjective->IsPlayer()) {
- if (m_pedInObjective->m_getUpTimer > CTimer::GetTimeInMilliseconds()
- || m_pedInObjective->m_nPedState == PED_DRAG_FROM_CAR) {
-
- ((CCopPed*)this)->SetArrestPlayer(m_pedInObjective);
- return;
- }
- }
- if (!bKindaStayInSamePlace && !bStopAndShoot && m_nPedState != PED_ATTACK && !killPlayerInNoPoliceZone) {
- if (distWithTargetSc > wepRange
- || m_pedInObjective->m_getUpTimer > CTimer::GetTimeInMilliseconds()
- || m_pedInObjective->m_nPedState == PED_ARRESTED
- || m_pedInObjective->EnteringCar() && distWithTargetSc < 3.0f
- || distWithTargetSc > m_distanceToCountSeekDone && !CanSeeEntity(m_pedInObjective)) {
-
- 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 = m_pNextPathNode->GetPosition();
-
- SetSeek(m_vecSeekPos, m_distanceToCountSeekDone);
- } else {
- SetSeek(m_pedInObjective, wepRangeAdjusted);
- }
- bCrouchWhenShooting = false;
- if (m_pedInObjective->m_pCurrentPhysSurface && distWithTargetSc < 5.0f) {
- if (wepRange <= 5.0f) {
- if (m_pedInObjective->IsPlayer()
- && FindPlayerPed()->m_bSpeedTimerFlag
- && (IsGangMember() || m_nPedType == PEDTYPE_COP)
- && GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED) {
- GiveWeapon(WEAPONTYPE_COLT45, 1000);
- SetCurrentWeapon(WEAPONTYPE_COLT45);
- }
- } else {
- bStopAndShoot = true;
- }
- SetMoveState(PEDMOVE_STILL);
- SetMoveAnim();
- break;
- }
- bStopAndShoot = false;
- SetMoveAnim();
- break;
- }
- }
- 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_DUCK_DOWN);
- if (duckAnim) {
- duckAnim->blendDelta = -2.0f;
- break;
- }
- bIsDucking = false;
- } else if (wepRange <= 5.0f) {
- 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.0f, 500.0f));
- SetAttackTimer(CGeneral::GetRandomNumberInRange(0.0f, 1500.0f));
- bObstacleShowedUpDuringKillObjective = false;
-
- } else {
- CVector target;
- CVector ourHead = GetMatrix() * CVector(0.5f, 0.0f, 0.6f);
- if (m_pedInObjective->IsPed())
- m_pedInObjective->m_pedIK.GetComponentPosition((RwV3d*)&target, PED_MID);
- else
- target = m_pedInObjective->GetPosition();
-
- target -= ourHead;
- target.Normalise();
- target = target * wepInfo->m_fRange + ourHead;
-
- CWorld::bIncludeDeadPeds = true;
- CEntity *foundEnt = nil;
- CColPoint foundCol;
-
- CWorld::ProcessLineOfSight(
- ourHead, target, foundCol, foundEnt,
- true, true, true, false, true, false);
- CWorld::bIncludeDeadPeds = 0;
- if (foundEnt == m_pedInObjective) {
- SetAttack(m_pedInObjective);
- m_pPointGunAt = m_pedInObjective;
- if (m_pedInObjective)
- m_pedInObjective->RegisterReference((CEntity **) &m_pPointGunAt);
-
- SetShootTimer(CGeneral::GetRandomNumberInRange(500.0f, 2000.0f));
-
- int time;
- if (distWithTargetSc <= wepRangeAdjusted)
- time = CGeneral::GetRandomNumberInRange(100.0f, 500.0f);
- else
- time = CGeneral::GetRandomNumberInRange(1500.0f, 3000.0f);
-
- SetAttackTimer(time);
- bObstacleShowedUpDuringKillObjective = false;
-
- } else if (foundEnt) {
- if (foundEnt->IsPed()) {
- SetAttackTimer(CGeneral::GetRandomNumberInRange(500.0f, 1000.0f));
- bObstacleShowedUpDuringKillObjective = false;
- } else {
- if (foundEnt->IsObject()) {
- SetAttackTimer(CGeneral::GetRandomNumberInRange(200.0f, 400.0f));
- bObstacleShowedUpDuringKillObjective = true;
- } else if (foundEnt->IsVehicle()) {
- SetAttackTimer(CGeneral::GetRandomNumberInRange(400.0f, 600.0f));
- bObstacleShowedUpDuringKillObjective = true;
- } else {
- SetAttackTimer(CGeneral::GetRandomNumberInRange(700.0f, 1200.0f));
- bObstacleShowedUpDuringKillObjective = true;
- }
- }
-
- m_fleeFrom = foundEnt;
- m_fleeFrom->RegisterReference((CEntity**) &m_fleeFrom);
- SetPointGunAt(m_pedInObjective);
- }
- }
- } else {
- if (!m_pedInObjective->m_pCurrentPhysSurface)
- bStopAndShoot = false;
-
- if (m_nPedState != PED_ATTACK && m_nPedState != PED_FIGHT) {
-
- // This is weird...
- if (bNotAllowedToDuck && bKindaStayInSamePlace) {
- if (!bIsDucking) {
- CAnimBlendAssociation* duckAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_DOWN);
- if (!duckAnim || duckAnim->blendDelta < 0.0f) {
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DUCK_DOWN, 4.0f);
- bIsDucking = true;
- }
- break;
- } else {
- CAnimBlendAssociation* duckAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_DOWN);
- if (!duckAnim || duckAnim->blendDelta < 0.0f) {
- bIsDucking = false;
- } else {
- break;
- }
- }
- }
- 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 (distWithTargetSc < 2.5f && wepRange > 5.0f
- && wepInfo->m_eWeaponFire != WEAPON_FIRE_MELEE) {
-
- SetAttack(m_pedInObjective);
- if (m_attackTimer < CTimer::GetTimeInMilliseconds()) {
- int time = CGeneral::GetRandomNumberInRange(500.0f, 1000.0f);
- SetAttackTimer(time);
- SetShootTimer(time - 500);
- }
- SetMoveState(PEDMOVE_STILL);
- }
- if (CTimer::GetTimeInMilliseconds() > m_nPedStateTimer)
- m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(m_pedInObjective->GetPosition().x, m_pedInObjective->GetPosition().y, GetPosition().x, GetPosition().y);
-
- 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);
- }
- break;
- }
- case OBJECTIVE_GOTO_CHAR_ON_FOOT:
{
- if (m_pedInObjective) {
- float safeDistance = 2.0f;
- if (m_pedInObjective->bInVehicle)
- safeDistance = 3.0f;
-
- float distWithTargetSc = distWithTarget.Magnitude();
- if (m_nPedStateTimer < CTimer::GetTimeInMilliseconds()) {
- if (distWithTargetSc <= safeDistance) {
- bScriptObjectiveCompleted = true;
- if (m_nPedState != PED_ATTACK) {
- SetIdle();
- m_pLookTarget = m_pedInObjective;
- m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);
- TurnBody();
- }
- if (distWithTargetSc > 2.0f)
- SetMoveState(m_pedInObjective->m_nMoveState);
- else
- SetMoveState(PEDMOVE_STILL);
- } 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);
- }
- }
- }
- }
- } 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_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->pPassengers[0] || m_carInObjective->m_nGettingInFlags & CAR_DOOR_FLAG_RF) {
- if (m_carInObjective->pPassengers[1] || m_carInObjective->m_nGettingInFlags & CAR_DOOR_FLAG_LR) {
- if (m_carInObjective->pPassengers[2] || m_carInObjective->m_nGettingInFlags & CAR_DOOR_FLAG_RR) {
- foundSeat = false;
- } else {
- m_vehEnterType = CAR_DOOR_RR;
- foundSeat = true;
- }
- } else {
- m_vehEnterType = CAR_DOOR_LR;
- foundSeat = true;
- }
- } else {
- m_vehEnterType = CAR_DOOR_RF;
- foundSeat = true;
- }
- for (int i = 2; i < m_carInObjective->m_nNumMaxPassengers; ++i) {
- if (!m_carInObjective->pPassengers[i] && !(m_carInObjective->m_nGettingInFlags & CAR_DOOR_FLAG_RF)) {
- m_vehEnterType = CAR_DOOR_RF;
- foundSeat = true;
- }
- }
- if (foundSeat) {
- SetPosition(GetPositionToOpenCarDoor(m_carInObjective, m_vehEnterType));
- SetEnterCar(m_carInObjective, m_vehEnterType);
- }
- }
- m_objectiveTimer = 0;
- }
- }
- // fall through
- }
- case OBJECTIVE_ENTER_CAR_AS_DRIVER:
- {
- if (!m_carInObjective || bInVehicle) {
-#ifdef VC_PED_PORTS
- if (bInVehicle && m_pMyVehicle != m_carInObjective) {
- SetExitCar(m_pMyVehicle, 0);
- } else
-#endif
- {
- 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
-#ifdef VC_PED_PORTS
- && !IsPlayer()
-#endif
- ) {
- 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
-#ifdef VC_PED_PORTS
- && (CharCreatedBy != MISSION_CHAR || m_carInObjective->pDriver->CharCreatedBy != RANDOM_CHAR)
-#endif
- ) {
- 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
-#ifdef VC_PED_PORTS
- || IsPlayer() && !CPad::GetPad(0)->ArePlayerControlsDisabled()
-#endif
- ) {
- RestorePreviousObjective();
- RestorePreviousState();
- if (IsPedInControl())
- m_pMyVehicle = nil;
- } else {
- SetIdle();
- SetMoveState(PEDMOVE_STILL);
- }
- }
- }
- } else if (!bInVehicle) {
- RestorePreviousObjective();
- RestorePreviousState();
- if (IsPedInControl())
- m_pMyVehicle = nil;
- }
- }
- }
- break;
+ particleProduceFootSplash(this, footPos, 0.15f, 4);
}
- 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() && wepInfo->m_eWeaponFire != WEAPON_FIRE_MELEE
- && distWithTargetSc < wepRange) {
-
- // I hope so
- CVector ourHead = GetMatrix() * CVector(0.5f, 0.0f, 0.6f);
- CVector maxShotPos = m_carInObjective->GetPosition() - ourHead;
- maxShotPos.Normalise();
- maxShotPos = maxShotPos * wepInfo->m_fRange + ourHead;
-
- CWorld::bIncludeDeadPeds = true;
- CColPoint foundCol;
- CEntity *foundEnt;
- CWorld::ProcessLineOfSight(ourHead, maxShotPos, foundCol, foundEnt,
- true, true, true, true, false, true, false);
- CWorld::bIncludeDeadPeds = false;
- if (foundEnt == m_carInObjective) {
- SetAttack(m_carInObjective);
- m_pPointGunAt = m_carInObjective;
- if (m_pPointGunAt)
- m_pPointGunAt->RegisterReference((CEntity **) &m_pPointGunAt);
-
- SetShootTimer(CGeneral::GetRandomNumberInRange(500, 2000));
- if (distWithTargetSc > 10.0f && !bKindaStayInSamePlace) {
- SetAttackTimer(CGeneral::GetRandomNumberInRange(2000, 5000));
- } else {
- SetAttackTimer(CGeneral::GetRandomNumberInRange(50, 300));
- SetMoveState(PEDMOVE_STILL);
- }
- }
- } else if (m_nPedState != PED_ATTACK && !bKindaStayInSamePlace) {
+ }
+ }
- float safeDistance;
- if (wepRange <= 5.0f)
- safeDistance = 3.0f;
- else
- safeDistance = wepRange * 0.25f;
+ if (m_nSurfaceTouched == SURFACE_WATER) {
+ float pedSpeed = CVector2D(m_vecMoveSpeed).Magnitude();
+ if (pedSpeed > 0.03f && CTimer::GetFrameCounter() % 2 == 0 && pedSpeed > 0.13f) {
+#ifdef PC_PARTICLE
+ float particleSize = pedSpeed * 2.0f;
- SetSeek(m_carInObjective, safeDistance);
- SetMoveState(PEDMOVE_RUN);
- }
- SetLookFlag(m_carInObjective, false);
- TurnBody();
- 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];
- 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;
- }
- // fall through
- }
- case OBJECTIVE_GOTO_AREA_ON_FOOT:
- case OBJECTIVE_RUN_TO_AREA:
- {
- if ((m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT || m_objective == OBJECTIVE_RUN_TO_AREA)
- && 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 (particleSize < 0.25f)
+ particleSize = 0.25f;
- if (!m_pNextPathNode)
- FindBestCoordsFromNodes(m_vecSeekPos, &bestCoords);
+ if (particleSize > 0.75f)
+ particleSize = 0.75f;
- if (m_pNextPathNode)
- m_vecSeekPos = m_pNextPathNode->GetPosition();
- }
- SetSeek(m_vecSeekPos, m_distanceToCountSeekDone);
- }
- }
+ CVector particlePos = GetPosition() + GetForward() * 0.3f;
+ particlePos.z -= 1.2f;
- 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 {
- SetSeek(m_nextRoutePointPos, 0.8f);
- }
- break;
- case OBJECTIVE_SOLICIT_VEHICLE:
- if (m_carInObjective) {
- if (m_objectiveTimer <= CTimer::GetTimeInMilliseconds()) {
- if (!bInVehicle) {
- SetObjective(OBJECTIVE_NONE);
- SetWanderPath(CGeneral::GetRandomNumber() & 7);
- m_objectiveTimer = CTimer::GetTimeInMilliseconds() + 10000;
- if (IsPedInControl())
- m_pMyVehicle = nil;
- }
- } else {
- if (m_nPedState != PED_FLEE_ENTITY && m_nPedState != PED_SOLICIT)
- SetSeekCar(m_carInObjective, 0);
- }
- } else {
- RestorePreviousObjective();
- RestorePreviousState();
- if (IsPedInControl())
- m_pMyVehicle = nil;
- }
- break;
- case OBJECTIVE_HAIL_TAXI:
- if (!RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_TAXI) && CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
- Say(SOUND_PED_TAXI_WAIT);
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_TAXI, 4.0f);
- m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 2000;
- }
- break;
- case OBJECTIVE_CATCH_TRAIN:
- {
- if (m_carInObjective) {
- SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, m_carInObjective);
- } else {
- CVehicle* trainToEnter = nil;
- float closestCarDist = CHECK_NEARBY_THINGS_MAX_DIST;
- CVector pos = GetPosition();
- int16 lastVehicle;
- CEntity* vehicles[8];
-
- CWorld::FindObjectsInRange(pos, 10.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false);
- for (int i = 0; i < lastVehicle; i++) {
- CVehicle* nearVeh = (CVehicle*)vehicles[i];
- if (nearVeh->IsTrain()) {
- CVector vehDistVec = GetPosition() - nearVeh->GetPosition();
- float vehDist = vehDistVec.Magnitude();
- if (vehDist < closestCarDist && m_pedInObjective->m_pMyVehicle != nearVeh)
- {
- trainToEnter = nearVeh;
- closestCarDist = vehDist;
- }
- }
- }
- if (trainToEnter) {
- m_carInObjective = trainToEnter;
- m_carInObjective->RegisterReference((CEntity **) &m_carInObjective);
- }
- }
- break;
- }
- case OBJECTIVE_BUY_ICE_CREAM:
- if (m_carInObjective) {
- if (m_nPedState != PED_FLEE_ENTITY && m_nPedState != PED_BUY_ICECREAM)
- SetSeekCar(m_carInObjective, 0);
- } else {
- RestorePreviousObjective();
- RestorePreviousState();
- if (IsPedInControl())
- m_pMyVehicle = nil;
- }
- break;
- case OBJECTIVE_STEAL_ANY_CAR:
- {
- if (bInVehicle) {
- bScriptObjectiveCompleted = true;
- RestorePreviousObjective();
- } else if (m_hitRecoverTimer < CTimer::GetTimeInMilliseconds()) {
- CVehicle *carToSteal = nil;
- float closestCarDist = ENTER_CAR_MAX_DIST;
- CVector pos = GetPosition();
- int16 lastVehicle;
- CEntity *vehicles[8];
-
- // NB: This should've been ENTER_CAR_MAX_DIST actually, and is fixed in VC.
- 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 *nearVeh = (CVehicle*)vehicles[i];
- if (nearVeh->VehicleCreatedBy != MISSION_VEHICLE) {
- if (nearVeh->m_vecMoveSpeed.Magnitude() <= 0.1f) {
- if (nearVeh->CanPedOpenLocks(this)) {
- CVector vehDistVec = GetPosition() - nearVeh->GetPosition();
- float vehDist = vehDistVec.Magnitude();
- if (vehDist < closestCarDist) {
- carToSteal = nearVeh;
- closestCarDist = vehDist;
- }
- }
- }
- }
- }
- if (carToSteal) {
- SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, carToSteal);
- m_hitRecoverTimer = CTimer::GetTimeInMilliseconds() + 5000;
- } else {
- RestorePreviousObjective();
- RestorePreviousState();
- }
- }
- break;
- }
- case OBJECTIVE_MUG_CHAR:
- {
- if (m_pedInObjective) {
- if (m_pedInObjective->IsPlayer() || m_pedInObjective->bInVehicle || m_pedInObjective->m_fHealth <= 0.0f) {
- ClearObjective();
- return;
- }
- if (m_pedInObjective->m_nMoveState > PEDMOVE_WALK) {
- ClearObjective();
- return;
- }
- if (m_pedInObjective->m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT && m_pedInObjective->m_pedInObjective == this) {
- SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, m_pedInObjective);
- SetMoveState(PEDMOVE_SPRINT);
- return;
- }
- if (m_pedInObjective->m_nPedState == PED_FLEE_ENTITY && m_fleeFrom == this
- || m_pedInObjective->m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE && m_pedInObjective->m_pedInObjective == this) {
- ClearObjective();
- SetFindPathAndFlee(m_pedInObjective, 15000, true);
- return;
- }
- float distWithTargetScSqr = distWithTarget.MagnitudeSqr();
- if (distWithTargetScSqr <= sq(10.0f)) {
- if (distWithTargetScSqr <= sq(1.4f)) {
- CAnimBlendAssociation *reloadAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_AK_RELOAD);
- 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->currentTime / reloadAssoc->hierarchy->totalLength > 0.8f)) {
- CAnimBlendAssociation *punchAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT_PPUNCH, 8.0f);
- punchAssoc->flags |= ASSOC_DELETEFADEDOUT;
- punchAssoc->flags |= ASSOC_FADEOUTWHENDONE;
- CVector2D offset(distWithTarget.x, distWithTarget.y);
- int dir = m_pedInObjective->GetLocalDirection(offset);
- m_pedInObjective->StartFightDefend(dir, HITLEVEL_HIGH, 5);
- m_pedInObjective->ReactToAttack(this);
- m_pedInObjective->Say(SOUND_PED_ROBBED);
- Say(SOUND_PED_MUGGING);
- bRichFromMugging = true;
-
- // VC FIX: ClearObjective() clears m_pedInObjective in VC (also same with VC_PED_PORTS), so get it before call
- CPed *victim = m_pedInObjective;
- ClearObjective();
- if (victim->m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT
- || victim->m_pedInObjective != this) {
- SetFindPathAndFlee(victim, 15000, true);
- m_nLastPedState = PED_WANDER_PATH;
- } else {
- SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, victim);
- SetMoveState(PEDMOVE_SPRINT);
- m_nLastPedState = PED_WANDER_PATH;
- }
- }
- } else {
- eWeaponType weaponType = GetWeapon()->m_eWeaponType;
- if (weaponType != WEAPONTYPE_UNARMED && weaponType != WEAPONTYPE_BASEBALLBAT)
- SetCurrentWeapon(WEAPONTYPE_UNARMED);
+ CVector particleDir = m_vecMoveSpeed * -0.75f;
- CAnimBlendAssociation *newReloadAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_AK_RELOAD, 8.0f);
- newReloadAssoc->flags |= ASSOC_DELETEFADEDOUT;
- newReloadAssoc->flags |= ASSOC_FADEOUTWHENDONE;
- }
- } else {
- SetSeek(m_pedInObjective, 1.0f);
- CAnimBlendAssociation *walkAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WALK);
+ particleDir.z = CGeneral::GetRandomNumberInRange(0.01f, 0.03f);
+ CParticle::AddParticle(PARTICLE_PED_SPLASH, particlePos, particleDir, nil, 0.8f * particleSize, CRGBA(155,155,185,128), 0, 0, 0, 0);
- if (walkAssoc)
- walkAssoc->speed = 1.3f;
- }
- } else {
- ClearObjective();
- SetWanderPath(CGeneral::GetRandomNumber() & 7);
- }
- } else {
-#ifdef VC_PED_PORTS
- m_objective = OBJECTIVE_NONE;
-#endif
- ClearObjective();
- }
- break;
- }
- 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()
-#ifdef VC_PED_PORTS
- && (FindPlayerPed() != this || !CPad::GetPad(0)->GetAccelerate()
- || bBusJacked)
-#endif
- ) {
- if (m_nPedState != PED_EXIT_CAR && m_nPedState != PED_DRAG_FROM_CAR && m_nPedState != PED_EXIT_TRAIN
- && (m_nPedType != PEDTYPE_COP
-#ifdef VC_PED_PORTS
- || m_pMyVehicle->IsBoat()
-#endif
- || m_pMyVehicle->m_vecMoveSpeed.MagnitudeSqr2D() < sq(0.005f))) {
- if (m_pMyVehicle->IsTrain())
- SetExitTrain(m_pMyVehicle);
-#ifdef VC_PED_PORTS
- else if (m_pMyVehicle->IsBoat())
- SetExitBoat(m_pMyVehicle);
-#endif
- else
- SetExitCar(m_pMyVehicle, 0);
- }
- } else {
- RestorePreviousObjective();
- }
- }
- break;
-#ifdef VC_PED_PORTS
- 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;
- }
+ particleDir.z = CGeneral::GetRandomNumberInRange(0.03f, 0.05f);
+ CParticle::AddParticle(PARTICLE_RUBBER_SMOKE, particlePos, particleDir, nil, particleSize, CRGBA(255,255,255,255), 0, 0, 0, 0);
+#else
+ CVector particlePos = (GetPosition() - 0.3f * GetUp()) + GetForward()*0.3f;
+ CVector particleDir = m_vecMoveSpeed * 0.45f;
+ particleDir.z = CGeneral::GetRandomNumberInRange(0.03f, 0.05f);
+ CParticle::AddParticle(PARTICLE_PED_SPLASH, particlePos-CVector(0.0f, 0.0f, 1.2f), particleDir, nil, 0.0f, CRGBA(155, 185, 155, 255));
#endif
}
- 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::SetShootTimer(uint32 time)
-{
- if (CTimer::GetTimeInMilliseconds() > m_shootTimer) {
- m_shootTimer = CTimer::GetTimeInMilliseconds() + time;
- }
-}
-
-void
-CPed::SetSeekCar(CVehicle *car, uint32 doorNode)
-{
- if (m_nPedState == PED_SEEK_CAR)
- return;
-
-#ifdef VC_PED_PORTS
- if (!CanSetPedState() || m_nPedState == PED_DRIVING)
- return;
-#endif
-
- SetStoredState();
- m_pSeekTarget = car;
- m_pSeekTarget->RegisterReference((CEntity**) &m_pSeekTarget);
- m_carInObjective = car;
- m_carInObjective->RegisterReference((CEntity**) &m_carInObjective);
- m_pMyVehicle = car;
- m_pMyVehicle->RegisterReference((CEntity**) &m_pMyVehicle);
- // m_pSeekTarget->RegisterReference((CEntity**) &m_pSeekTarget);
- m_vehEnterType = doorNode;
- m_distanceToCountSeekDone = 0.5f;
- m_nPedState = PED_SEEK_CAR;
-
-}
-
-void
-CPed::SetSeekBoatPosition(CVehicle *boat)
+// Actually GetLocalDirectionTo(Turn/Look)
+int
+CPed::GetLocalDirection(const CVector2D &posOffset)
{
- if (m_nPedState == PED_SEEK_IN_BOAT || boat->pDriver
-#if defined VC_PED_PORTS || defined FIX_BUGS
- || !IsPedInControl()
-#endif
- )
- return;
+ int direction;
+ float angle;
- SetStoredState();
- m_carInObjective = boat;
- m_carInObjective->RegisterReference((CEntity **) &m_carInObjective);
- m_pMyVehicle = boat;
- m_pMyVehicle->RegisterReference((CEntity **) &m_pMyVehicle);
- m_distanceToCountSeekDone = 0.5f;
- m_nPedState = PED_SEEK_IN_BOAT;
-}
+ for (angle = posOffset.Heading() - m_fRotationCur + DEGTORAD(45.0f); angle < 0.0f; angle += TWOPI);
-void
-CPed::SetExitTrain(CVehicle* train)
-{
- if (m_nPedState == PED_EXIT_TRAIN || train->GetStatus() != STATUS_TRAIN_NOT_MOVING || !((CTrain*)train)->Doors[0].IsFullyOpen())
- return;
+ for (direction = RADTODEG(angle)/90.0f; direction > 3; direction -= 4);
- /*
- // Not used
- CVector exitPos;
- GetNearestTrainPedPosition(train, exitPos);
- */
- m_nPedState = PED_EXIT_TRAIN;
- m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_TRAIN_GETOUT, 4.0f);
- m_pVehicleAnim->SetFinishCallback(PedSetOutTrainCB, this);
- bUsesCollision = false;
- LineUpPedWithTrain();
+ // 0-forward, 1-left, 2-backward, 3-right.
+ return direction;
}
#ifdef NEW_WALK_AROUND_ALGORITHM
@@ -14363,486 +4071,734 @@ CPed::SetDirectionToWalkAroundObject(CEntity *obj)
m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 280.0f * dist * checkIntervalInTime;
}
-int32
-CPed::ProcessEntityCollision(CEntity *collidingEnt, CColPoint *collidingPoints)
+bool
+CPed::IsPedInControl(void)
{
- bool collidedWithBoat = false;
- bool belowTorsoCollided = false;
- float gravityEffect = -0.15f * CTimer::GetTimeStep();
- CColPoint intersectionPoint;
- CColLine ourLine;
+ return m_nPedState <= PED_STATES_NO_AI
+ && !bIsInTheAir && !bIsLanding
+ && m_fHealth > 0.0f;
+}
- CColModel *ourCol = CModelInfo::GetModelInfo(GetModelIndex())->GetColModel();
- CColModel *hisCol = CModelInfo::GetModelInfo(collidingEnt->GetModelIndex())->GetColModel();
+bool
+CPed::IsPedShootable(void)
+{
+ return m_nPedState <= PED_STATES_NO_ST;
+}
- if (!bUsesCollision)
- return false;
+bool
+CPed::UseGroundColModel(void)
+{
+ return m_nPedState == PED_FALL ||
+ m_nPedState == PED_DIVE_AWAY ||
+ m_nPedState == PED_DIE ||
+ m_nPedState == PED_DEAD;
+}
- if (collidingEnt->IsVehicle() && ((CVehicle*)collidingEnt)->IsBoat())
- collidedWithBoat = true;
+bool
+CPed::CanPedReturnToState(void)
+{
+ return m_nPedState <= PED_STATES_NO_AI && m_nPedState != PED_AIM_GUN && m_nPedState != PED_ATTACK &&
+ m_nPedState != PED_FIGHT && m_nPedState != PED_STEP_AWAY && m_nPedState != PED_SNIPER_MODE && m_nPedState != PED_LOOK_ENTITY;
+}
- // ofc we're not vehicle
- if (!m_bIsVehicleBeingShifted && !bSkipLineCol
-#ifdef VC_PED_PORTS
- && !collidingEnt->IsPed()
+bool
+CPed::CanSetPedState(void)
+{
+ return !DyingOrDead() && m_nPedState != PED_ARRESTED && !EnteringCar() && m_nPedState != PED_STEAL_CAR;
+}
+
+bool
+CPed::CanStrafeOrMouseControl(void)
+{
+#ifdef FREE_CAM
+ if (CCamera::bFreeCam)
+ return false;
#endif
- ) {
- if (!bCollisionProcessed) {
+ return m_nPedState == PED_NONE || m_nPedState == PED_IDLE || m_nPedState == PED_FLEE_POS || m_nPedState == PED_FLEE_ENTITY ||
+ m_nPedState == PED_ATTACK || m_nPedState == PED_FIGHT || m_nPedState == PED_AIM_GUN || m_nPedState == PED_JUMP;
+}
+
+void
+CPed::PedGetupCB(CAnimBlendAssociation* animAssoc, void* arg)
+{
+ CPed* ped = (CPed*)arg;
+
+ if (ped->m_nPedState == PED_GETUP)
+ RpAnimBlendClumpSetBlendDeltas(ped->GetClump(), ASSOC_PARTIAL, -1000.0f);
+
+ ped->bFallenDown = false;
+ animAssoc->blendDelta = -1000.0f;
+ if (ped->m_nPedState == PED_GETUP)
+ ped->RestorePreviousState();
+
+ if (ped->m_nPedState != PED_FLEE_POS && ped->m_nPedState != PED_FLEE_ENTITY)
+ ped->SetMoveState(PEDMOVE_STILL);
+ else
+ ped->SetMoveState(PEDMOVE_RUN);
+
+ ped->SetMoveAnim();
+ ped->bGetUpAnimStarted = false;
+}
+
+void
+CPed::PedLandCB(CAnimBlendAssociation* animAssoc, void* arg)
+{
+ CPed* ped = (CPed*)arg;
+
+ animAssoc->blendDelta = -1000.0f;
+ ped->bIsLanding = false;
+
+ if (ped->m_nPedState == PED_JUMP)
+ ped->RestorePreviousState();
+}
+
+void
+CPed::PedStaggerCB(CAnimBlendAssociation* animAssoc, void* arg)
+{
+ /*
+ CPed *ped = (CPed*)arg;
+
+ if (ped->m_nPedState == PED_STAGGER)
+ // nothing
+ */
+}
+
+void
+CPed::PedSetOutCarCB(CAnimBlendAssociation *animAssoc, void *arg)
+{
+ CPed *ped = (CPed*)arg;
+
+ CVehicle *veh = ped->m_pMyVehicle;
+
+ bool startedToRun = false;
+ ped->bUsesCollision = true;
+ ped->m_actionX = 0.0f;
+ ped->m_actionY = 0.0f;
+ ped->bVehExitWillBeInstant = false;
+ if (veh && veh->IsBoat())
+ ped->ApplyMoveSpeed();
+
+ if (ped->m_objective == OBJECTIVE_LEAVE_CAR)
+ ped->RestorePreviousObjective();
#ifdef VC_PED_PORTS
- m_pCurrentPhysSurface = nil;
+ else if (ped->m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE) {
+ ped->m_fHealth = 0.0f;
+ ped->SetDie(ANIM_FLOOR_HIT, 4.0f, 0.5f);
+ }
#endif
- if (bIsStanding) {
- bIsStanding = false;
- bWasStanding = true;
- }
- bCollisionProcessed = true;
- m_fCollisionSpeed += m_vecMoveSpeed.Magnitude2D() * CTimer::GetTimeStep();
- bStillOnValidPoly = false;
- if (IsPlayer() || m_fCollisionSpeed >= 1.0f
- && (m_fCollisionSpeed >= 2.0f || m_nPedState != PED_WANDER_PATH)) {
- m_collPoly.valid = false;
- m_fCollisionSpeed = 0.0f;
- bHitSteepSlope = false;
+
+ ped->bInVehicle = false;
+ if (veh && veh->IsCar() && !veh->IsRoomForPedToLeaveCar(ped->m_vehEnterType, nil)) {
+ ped->PositionPedOutOfCollision();
+ }
+
+ if (ped->m_nPedState == PED_EXIT_CAR) {
+ if (ped->m_nPedType == PEDTYPE_COP)
+ ped->SetIdle();
+ else
+ ped->RestorePreviousState();
+
+ veh = ped->m_pMyVehicle;
+ if (ped->bFleeAfterExitingCar && veh) {
+ ped->bFleeAfterExitingCar = false;
+ ped->SetFlee(veh->GetPosition(), 12000);
+ ped->bUsePedNodeSeek = true;
+ ped->m_pNextPathNode = nil;
+ if (CGeneral::GetRandomNumber() & 1 || ped->m_pedStats->m_fear > 70) {
+ ped->SetMoveState(PEDMOVE_SPRINT);
+ ped->Say(SOUND_PED_FLEE_SPRINT);
} else {
- CVector pos = GetPosition();
- float potentialGroundZ = GetPosition().z - FEET_OFFSET;
- if (bWasStanding) {
- pos.z += -0.25f;
- potentialGroundZ += gravityEffect;
+ ped->SetMoveState(PEDMOVE_RUN);
+ ped->Say(SOUND_PED_FLEE_RUN);
+ }
+ startedToRun = true;
+
+ // This is not a good way to do this...
+ ped->m_nLastPedState = PED_WANDER_PATH;
+
+ } else if (ped->bWanderPathAfterExitingCar) {
+ ped->SetWanderPath(CGeneral::GetRandomNumberInRange(0.0f, 8.0f));
+ ped->bWanderPathAfterExitingCar = false;
+ if (ped->m_nPedType == PEDTYPE_PROSTITUTE)
+ ped->SetObjectiveTimer(30000);
+ ped->m_nLastPedState = PED_NONE;
+
+ } else if (ped->bGonnaKillTheCarJacker) {
+
+ // Kill objective is already given at this point.
+ ped->bGonnaKillTheCarJacker = false;
+ if (ped->m_pedInObjective) {
+ if (!(CGeneral::GetRandomNumber() & 1)
+ && ped->m_nPedType != PEDTYPE_COP
+ && (!ped->m_pedInObjective->IsPlayer() || !CTheScripts::IsPlayerOnAMission())) {
+ ped->ClearObjective();
+ ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, veh);
}
- if (CCollision::IsStoredPolyStillValidVerticalLine(pos, potentialGroundZ, intersectionPoint, &m_collPoly)) {
- bStillOnValidPoly = true;
+ ped->m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 1500;
+ }
+ int waitTime = 1500;
+ ped->SetWaitState(WAITSTATE_PLAYANIM_COWER, &waitTime);
+ ped->SetMoveState(PEDMOVE_RUN);
+ startedToRun = true;
+ } else if (ped->m_objective == OBJECTIVE_NONE && ped->CharCreatedBy != MISSION_CHAR && ped->m_nPedState == PED_IDLE && !ped->IsPlayer()) {
+ ped->SetWanderPath(CGeneral::GetRandomNumberInRange(0.0f, 8.0f));
+ }
+ }
#ifdef VC_PED_PORTS
- if(!bSomeVCflag1 || FEET_OFFSET + intersectionPoint.point.z < GetPosition().z) {
- GetMatrix().GetPosition().z = FEET_OFFSET + intersectionPoint.point.z;
- if (bSomeVCflag1)
- bSomeVCflag1 = false;
- }
-#else
- GetMatrix().GetPosition().z = FEET_OFFSET + intersectionPoint.point.z;
+ else {
+ ped->m_nPedState = PED_IDLE;
+ }
#endif
- m_vecMoveSpeed.z = 0.0f;
- bIsStanding = true;
- } else {
- m_collPoly.valid = false;
- m_fCollisionSpeed = 0.0f;
- bHitSteepSlope = false;
+ if (animAssoc)
+ animAssoc->blendDelta = -1000.0f;
+
+ ped->RestartNonPartialAnims();
+ ped->m_pVehicleAnim = nil;
+ CVector posFromZ = ped->GetPosition();
+ CPedPlacement::FindZCoorForPed(&posFromZ);
+ ped->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
+ ped->SetPosition(posFromZ);
+ veh = ped->m_pMyVehicle;
+ if (veh) {
+ if (ped->m_nPedType == PEDTYPE_PROSTITUTE) {
+ if (veh->pDriver) {
+ if (veh->pDriver->IsPlayer() && ped->CharCreatedBy == RANDOM_CHAR) {
+ CWorld::Players[CWorld::PlayerInFocus].m_nNextSexMoneyUpdateTime = 0;
+ CWorld::Players[CWorld::PlayerInFocus].m_nNextSexFrequencyUpdateTime = 0;
+ CWorld::Players[CWorld::PlayerInFocus].m_pHooker = nil;
+ CWorld::Players[CWorld::PlayerInFocus].m_nMoney -= 100;
+ if (CWorld::Players[CWorld::PlayerInFocus].m_nMoney < 0)
+ CWorld::Players[CWorld::PlayerInFocus].m_nMoney = 0;
}
}
}
+ veh->m_nGettingOutFlags &= ~GetCarDoorFlag(ped->m_vehEnterType);
+ if (veh->pDriver == ped) {
+ veh->RemoveDriver();
+ veh->SetStatus(STATUS_ABANDONED);
+ if (veh->m_nDoorLock == CARLOCK_LOCKED_INITIALLY)
+ veh->m_nDoorLock = CARLOCK_UNLOCKED;
+ if (ped->m_nPedType == PEDTYPE_COP && veh->IsLawEnforcementVehicle())
+ veh->ChangeLawEnforcerState(false);
+ } else {
+ veh->RemovePassenger(ped);
+ }
- if (!bStillOnValidPoly) {
- CVector potentialCenter = GetPosition();
- potentialCenter.z = GetPosition().z - 0.52f;
-
- // 0.52f should be a ped's approx. radius
- float totalRadiusWhenCollided = collidingEnt->GetBoundRadius() + 0.52f - gravityEffect;
- if (bWasStanding) {
- if (collidedWithBoat) {
- potentialCenter.z += 2.0f * gravityEffect;
- totalRadiusWhenCollided += Abs(gravityEffect);
- } else {
- potentialCenter.z += gravityEffect;
- }
+ if (veh->bIsBus && !veh->IsUpsideDown() && !veh->IsOnItsSide()) {
+ float angleAfterExit;
+ if (ped->m_vehEnterType == CAR_DOOR_LF) {
+ angleAfterExit = HALFPI + veh->GetForward().Heading();
+ } else {
+ angleAfterExit = veh->GetForward().Heading() - HALFPI;
}
- if (sq(totalRadiusWhenCollided) > (potentialCenter - collidingEnt->GetBoundCentre()).MagnitudeSqr()) {
- ourLine.p0 = GetPosition();
- ourLine.p1 = GetPosition();
- ourLine.p1.z = GetPosition().z - FEET_OFFSET;
- if (bWasStanding) {
- ourLine.p1.z = ourLine.p1.z + gravityEffect;
- ourLine.p0.z = ourLine.p0.z + -0.25f;
- }
- float minDist = 1.0f;
- belowTorsoCollided = CCollision::ProcessVerticalLine(ourLine, collidingEnt->GetMatrix(), *hisCol,
- intersectionPoint, minDist, false, &m_collPoly);
+ ped->SetHeading(angleAfterExit);
+ ped->m_fRotationDest = angleAfterExit;
+ ped->m_fRotationCur = angleAfterExit;
+ if (!ped->bBusJacked)
+ ped->SetMoveState(PEDMOVE_WALK);
+ }
+ if (CGarages::IsPointWithinAnyGarage(ped->GetPosition()))
+ veh->bLightsOn = false;
+ }
- if (collidedWithBoat && bWasStanding && !belowTorsoCollided) {
- ourLine.p0.z = ourLine.p1.z;
- ourLine.p1.z = ourLine.p1.z + gravityEffect;
- belowTorsoCollided = CCollision::ProcessVerticalLine(ourLine, collidingEnt->GetMatrix(), *hisCol,
- intersectionPoint, minDist, false, &m_collPoly);
- }
- if (belowTorsoCollided) {
-#ifndef VC_PED_PORTS
- if (!collidingEnt->IsPed()) {
-#endif
- if (!bIsStanding
- || FEET_OFFSET + intersectionPoint.point.z > GetPosition().z
- || collidedWithBoat && 3.12f + intersectionPoint.point.z > GetPosition().z) {
+ if (ped->IsPlayer())
+ AudioManager.PlayerJustLeftCar();
- if (!collidingEnt->IsVehicle() && !collidingEnt->IsObject()) {
- m_pCurSurface = collidingEnt;
- collidingEnt->RegisterReference((CEntity**)&m_pCurSurface);
- bTryingToReachDryLand = false;
- bOnBoat = false;
- } else {
- m_pCurrentPhysSurface = (CPhysical*)collidingEnt;
- collidingEnt->RegisterReference((CEntity**)&m_pCurrentPhysSurface);
- m_vecOffsetFromPhysSurface = intersectionPoint.point - collidingEnt->GetPosition();
- m_pCurSurface = collidingEnt;
- collidingEnt->RegisterReference((CEntity**)&m_pCurSurface);
- m_collPoly.valid = false;
- if (collidingEnt->IsVehicle() && ((CVehicle*)collidingEnt)->IsBoat()) {
- bOnBoat = true;
- } else {
- bOnBoat = false;
- }
- }
-#ifdef VC_PED_PORTS
- if (!bSomeVCflag1 || FEET_OFFSET + intersectionPoint.point.z < GetPosition().z) {
- GetMatrix().GetPosition().z = FEET_OFFSET + intersectionPoint.point.z;
- if (bSomeVCflag1)
- bSomeVCflag1 = false;
- }
+ ped->ReplaceWeaponWhenExitingVehicle();
+
+ ped->bOnBoat = false;
+ if (ped->bBusJacked) {
+ ped->SetFall(1500, ANIM_KO_SKID_BACK, false);
+ ped->bBusJacked = false;
+ }
+ ped->m_nStoredMoveState = PEDMOVE_NONE;
+ if (!ped->IsPlayer()) {
+ // It's a shame...
+#ifdef FIX_BUGS
+ int createdBy = ped->CharCreatedBy;
#else
- GetMatrix().GetPosition().z = FEET_OFFSET + intersectionPoint.point.z;
+ int createdBy = !ped->CharCreatedBy;
#endif
- m_nSurfaceTouched = intersectionPoint.surfaceB;
- if (m_nSurfaceTouched == SURFACE_STEEP_CLIFF) {
- bHitSteepSlope = true;
- m_vecDamageNormal = intersectionPoint.normal;
- }
- }
-#ifdef VC_PED_PORTS
- float upperSpeedLimit = 0.33f;
- float lowerSpeedLimit = -0.25f;
- float speed = m_vecMoveSpeed.Magnitude2D();
- if (m_nPedState == PED_IDLE) {
- upperSpeedLimit *= 2.0f;
- lowerSpeedLimit *= 1.5f;
- }
- CAnimBlendAssociation *fallAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FALL_FALL);
- if (!bWasStanding && speed > upperSpeedLimit && (/*!bPushedAlongByCar ||*/ m_vecMoveSpeed.z < lowerSpeedLimit)
- && m_pCollidingEntity != collidingEnt) {
- float damage = 100.0f * Max(speed - 0.25f, 0.0f);
- float damage2 = damage;
- if (m_vecMoveSpeed.z < -0.25f)
- damage += (-0.25f - m_vecMoveSpeed.z) * 150.0f;
+ if (createdBy == MISSION_CHAR && !startedToRun)
+ ped->SetMoveState(PEDMOVE_WALK);
+ }
+}
- uint8 dir = 2; // from backward
- if (m_vecMoveSpeed.x > 0.01f || m_vecMoveSpeed.x < -0.01f || m_vecMoveSpeed.y > 0.01f || m_vecMoveSpeed.y < -0.01f) {
- CVector2D offset = -m_vecMoveSpeed;
- dir = GetLocalDirection(offset);
- }
+void
+CPed::PedSetDraggedOutCarCB(CAnimBlendAssociation *dragAssoc, void *arg)
+{
+ CAnimBlendAssociation *quickJackedAssoc;
+ CVehicle *vehicle;
+ CPed *ped = (CPed*)arg;
- InflictDamage(collidingEnt, WEAPONTYPE_FALL, damage, PEDPIECE_TORSO, dir);
- if (IsPlayer() && damage2 > 5.0f)
- Say(SOUND_PED_LAND);
+ quickJackedAssoc = RpAnimBlendClumpGetAssociation(ped->GetClump(), ANIM_CAR_QJACKED);
+ if (ped->m_nPedState != PED_ARRESTED) {
+ ped->m_nLastPedState = PED_NONE;
+ if (dragAssoc)
+ dragAssoc->blendDelta = -1000.0f;
+ }
+ ped->RestartNonPartialAnims();
+ ped->m_pVehicleAnim = nil;
+ ped->m_pSeekTarget = nil;
+ vehicle = ped->m_pMyVehicle;
- } else if (!bWasStanding && fallAnim && -0.016f * CTimer::GetTimeStep() > m_vecMoveSpeed.z) {
- InflictDamage(collidingEnt, WEAPONTYPE_FALL, 15.0f, PEDPIECE_TORSO, 2);
- }
-#else
- float speedSqr = 0.0f;
- CAnimBlendAssociation *fallAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FALL_FALL);
- if (!bWasStanding && (m_vecMoveSpeed.z < -0.25f || (speedSqr = m_vecMoveSpeed.MagnitudeSqr()) > sq(0.5f))) {
- if (speedSqr == 0.0f)
- speedSqr = sq(m_vecMoveSpeed.z);
+ if (vehicle) {
+ vehicle->m_nGettingOutFlags &= ~GetCarDoorFlag(ped->m_vehEnterType);
- uint8 dir = 2; // from backward
- if (m_vecMoveSpeed.x > 0.01f || m_vecMoveSpeed.x < -0.01f || m_vecMoveSpeed.y > 0.01f || m_vecMoveSpeed.y < -0.01f) {
- CVector2D offset = -m_vecMoveSpeed;
- dir = GetLocalDirection(offset);
- }
- InflictDamage(collidingEnt, WEAPONTYPE_FALL, 350.0f * sq(speedSqr), PEDPIECE_TORSO, dir);
+ if (vehicle->pDriver == ped) {
+ vehicle->RemoveDriver();
+ if (vehicle->m_nDoorLock == CARLOCK_LOCKED_INITIALLY)
+ vehicle->m_nDoorLock = CARLOCK_UNLOCKED;
- } else if (!bWasStanding && fallAnim && -0.016f * CTimer::GetTimeStep() > m_vecMoveSpeed.z) {
- InflictDamage(collidingEnt, WEAPONTYPE_FALL, 15.0f, PEDPIECE_TORSO, 2);
- }
+ if (ped->m_nPedType == PEDTYPE_COP && vehicle->IsLawEnforcementVehicle())
+ vehicle->ChangeLawEnforcerState(false);
+ } else {
+ vehicle->RemovePassenger(ped);
+ }
+ }
+ ped->bInVehicle = false;
+ if (ped->IsPlayer())
+ AudioManager.PlayerJustLeftCar();
+
+#ifdef VC_PED_PORTS
+ if (ped->m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE) {
+ dragAssoc->SetDeleteCallback(PedSetDraggedOutCarPositionCB, ped);
+ ped->m_fHealth = 0.0f;
+ ped->SetDie(ANIM_FLOOR_HIT, 1000.0f, 0.5f);
+ return;
+ }
#endif
- m_vecMoveSpeed.z = 0.0f;
- bIsStanding = true;
-#ifndef VC_PED_PORTS
- } else {
- bOnBoat = false;
- }
+
+ if (quickJackedAssoc) {
+ dragAssoc->SetDeleteCallback(PedSetQuickDraggedOutCarPositionCB, ped);
+ } else {
+ dragAssoc->SetDeleteCallback(PedSetDraggedOutCarPositionCB, ped);
+ if (ped->CanSetPedState())
+ CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_GETUP1, 1000.0f);
+ }
+
+ ped->ReplaceWeaponWhenExitingVehicle();
+
+ ped->m_nStoredMoveState = PEDMOVE_NONE;
+ ped->bVehExitWillBeInstant = false;
+}
+
+void
+CPed::PedSetInCarCB(CAnimBlendAssociation *animAssoc, void *arg)
+{
+ CPed *ped = (CPed*)arg;
+
+ CVehicle *veh = ped->m_pMyVehicle;
+
+ // Pointless code
+ if (!veh)
+ return;
+
+#ifdef VC_PED_PORTS
+ // Situation of entering car as a driver while there is already a driver exiting atm.
+ CPed *driver = veh->pDriver;
+ if (driver && driver->m_nPedState == PED_DRIVING && !veh->bIsBus && driver->m_objective == OBJECTIVE_LEAVE_CAR
+ && (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || ped->m_nPedState == PED_CARJACK)) {
+
+ if (!ped->IsPlayer() && (ped->CharCreatedBy != MISSION_CHAR || driver->IsPlayer())) {
+ ped->QuitEnteringCar();
+ return;
+ }
+ if (driver->CharCreatedBy == MISSION_CHAR) {
+ PedSetOutCarCB(nil, veh->pDriver);
+ if (driver->m_pMyVehicle) {
+ driver->PositionPedOutOfCollision();
+ } else {
+ driver->m_pMyVehicle = veh;
+ driver->PositionPedOutOfCollision();
+ driver->m_pMyVehicle = nil;
+ }
+ veh->pDriver = nil;
+ } else {
+ driver->SetDead();
+ driver->FlagToDestroyWhenNextProcessed();
+ veh->pDriver = nil;
+ }
+ }
#endif
- } else {
- bOnBoat = false;
- }
+
+ if (!ped->IsNotInWreckedVehicle() || ped->DyingOrDead())
+ return;
+
+ ped->bInVehicle = true;
+ if (ped->m_nPedType == PEDTYPE_PROSTITUTE) {
+ if (veh->pDriver) {
+ if (veh->pDriver->IsPlayer() && ped->CharCreatedBy == RANDOM_CHAR) {
+ CWorld::Players[CWorld::PlayerInFocus].m_nSexFrequency = 1000;
+ CWorld::Players[CWorld::PlayerInFocus].m_nNextSexMoneyUpdateTime = CTimer::GetTimeInMilliseconds() + 1000;
+ CWorld::Players[CWorld::PlayerInFocus].m_nNextSexFrequencyUpdateTime = CTimer::GetTimeInMilliseconds() + 3000;
+ CWorld::Players[CWorld::PlayerInFocus].m_pHooker = (CCivilianPed*)ped;
}
}
}
+ if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER
+#if defined VC_PED_PORTS || defined FIX_BUGS
+ || ped->m_nPedState == PED_CARJACK
+#endif
+ )
+ veh->bIsBeingCarJacked = false;
- int ourCollidedSpheres = CCollision::ProcessColModels(GetMatrix(), *ourCol, collidingEnt->GetMatrix(), *hisCol, collidingPoints, nil, nil);
- if (ourCollidedSpheres > 0 || belowTorsoCollided) {
- AddCollisionRecord(collidingEnt);
- if (!collidingEnt->IsBuilding())
- ((CPhysical*)collidingEnt)->AddCollisionRecord(this);
+ if (veh->m_nNumGettingIn)
+ --veh->m_nNumGettingIn;
- if (ourCollidedSpheres > 0 && (collidingEnt->IsBuilding() || collidingEnt->GetIsStatic())) {
- bHasHitWall = true;
+ if (ped->IsPlayer() && ((CPlayerPed*)ped)->m_bAdrenalineActive)
+ ((CPlayerPed*)ped)->ClearAdrenaline();
+
+ if (veh->IsBoat()) {
+ if (ped->IsPlayer()) {
+#if defined VC_PED_PORTS || defined FIX_BUGS
+ CCarCtrl::RegisterVehicleOfInterest(veh);
+#endif
+ if (veh->GetStatus() == STATUS_SIMPLE) {
+ veh->m_vecMoveSpeed = CVector(0.0f, 0.0f, -0.00001f);
+ veh->m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);
+ }
+ veh->SetStatus(STATUS_PLAYER);
+ AudioManager.PlayerJustGotInCar();
}
+ veh->SetDriver(ped);
+ if (!veh->bEngineOn)
+ veh->bEngineOn = true;
+
+ ped->m_nPedState = PED_DRIVING;
+ ped->StopNonPartialAnims();
+ return;
}
- if (collidingEnt->IsBuilding() || collidingEnt->GetIsStatic()) {
- if (bWasStanding) {
- CVector sphereNormal;
- float normalLength;
- for(int sphere = 0; sphere < ourCollidedSpheres; sphere++) {
- sphereNormal = collidingPoints[sphere].normal;
+ if (ped->m_pVehicleAnim)
+ ped->m_pVehicleAnim->blendDelta = -1000.0f;
+
+ ped->bDoBloodyFootprints = false;
+ if (veh->m_nAlarmState == -1)
+ veh->m_nAlarmState = 15000;
+
+ if (ped->IsPlayer()) {
+ if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) {
+ if (veh->GetStatus() == STATUS_SIMPLE) {
+ veh->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
+ veh->m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);
+ }
+ veh->SetStatus(STATUS_PLAYER);
+ }
+ AudioManager.PlayerJustGotInCar();
+ } else if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) {
+ if (veh->GetStatus() == STATUS_SIMPLE) {
+ veh->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
+ veh->m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);
+ }
+ veh->SetStatus(STATUS_PHYSICS);
+ }
+
+ if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) {
+ for (int i = 0; i < veh->m_nNumMaxPassengers; ++i) {
+ CPed *passenger = veh->pPassengers[i];
+ if (passenger && passenger->CharCreatedBy == RANDOM_CHAR) {
+ passenger->SetObjective(OBJECTIVE_LEAVE_CAR, veh);
#ifdef VC_PED_PORTS
- if (sphereNormal.z >= -1.0f || !IsPlayer()) {
+ passenger->m_leaveCarTimer = CTimer::GetTimeInMilliseconds();
#endif
- normalLength = sphereNormal.Magnitude2D();
- if (normalLength != 0.0f) {
- sphereNormal.x = sphereNormal.x / normalLength;
- sphereNormal.y = sphereNormal.y / normalLength;
- }
-#ifdef VC_PED_PORTS
- } else {
- float speed = m_vecMoveSpeed.Magnitude2D();
- sphereNormal.x = -m_vecMoveSpeed.x / Max(0.001f, speed);
- sphereNormal.y = -m_vecMoveSpeed.y / Max(0.001f, speed);
- GetMatrix().GetPosition().z -= 0.05f;
- bSomeVCflag1 = true;
- }
+ }
+ }
+ }
+ // This shouldn't happen at all. Passengers can't enter with PED_CARJACK. Even though they did, we shouldn't call AddPassenger in here and SetDriver in below.
+#if !defined VC_PED_PORTS && !defined FIX_BUGS
+ else if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER) {
+ if (ped->m_nPedState == PED_CARJACK) {
+ veh->AddPassenger(ped, 0);
+ ped->m_nPedState = PED_DRIVING;
+ ped->RestorePreviousObjective();
+ ped->SetObjective(OBJECTIVE_LEAVE_CAR, veh);
+ } else if (veh->pDriver && ped->CharCreatedBy == RANDOM_CHAR) {
+ veh->AutoPilot.m_nCruiseSpeed = 17;
+ }
+ }
#endif
- sphereNormal.Normalise();
- collidingPoints[sphere].normal = sphereNormal;
- if (collidingPoints[sphere].surfaceB == SURFACE_STEEP_CLIFF)
- bHitSteepSlope = true;
+
+ if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || ped->m_nPedState == PED_CARJACK) {
+ veh->SetDriver(ped);
+ if (veh->VehicleCreatedBy == PARKED_VEHICLE) {
+ veh->VehicleCreatedBy = RANDOM_VEHICLE;
+ ++CCarCtrl::NumRandomCars;
+ --CCarCtrl::NumParkedCars;
+ }
+ if (veh->bIsAmbulanceOnDuty) {
+ veh->bIsAmbulanceOnDuty = false;
+ --CCarCtrl::NumAmbulancesOnDuty;
+ }
+ if (veh->bIsFireTruckOnDuty) {
+ veh->bIsFireTruckOnDuty = false;
+ --CCarCtrl::NumFiretrucksOnDuty;
+ }
+ if (ped->m_nPedType == PEDTYPE_COP && veh->IsLawEnforcementVehicle())
+ veh->ChangeLawEnforcerState(true);
+
+ if (!veh->bEngineOn) {
+ veh->bEngineOn = true;
+ DMAudio.PlayOneShot(ped->m_audioEntityId, SOUND_CAR_ENGINE_START, 1.0f);
+ }
+ if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER && ped->CharCreatedBy == RANDOM_CHAR
+ && ped != FindPlayerPed() && ped->m_nPedType != PEDTYPE_EMERGENCY) {
+
+ CCarCtrl::JoinCarWithRoadSystem(veh);
+ veh->AutoPilot.m_nCarMission = MISSION_CRUISE;
+ veh->AutoPilot.m_nTempAction = TEMPACT_NONE;
+ veh->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;
+ veh->AutoPilot.m_nCruiseSpeed = 25;
+ }
+ ped->m_nPedState = PED_DRIVING;
+ if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) {
+
+ if (ped->m_prevObjective == OBJECTIVE_RUN_TO_AREA || ped->m_prevObjective == OBJECTIVE_GOTO_CHAR_ON_FOOT || ped->m_prevObjective == OBJECTIVE_KILL_CHAR_ON_FOOT)
+ ped->m_prevObjective = OBJECTIVE_NONE;
+
+ ped->RestorePreviousObjective();
+ }
+
+ } else if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER) {
+ if (veh->bIsBus) {
+ veh->AddPassenger(ped);
+ } else {
+ switch (ped->m_vehEnterType) {
+ case CAR_DOOR_RF:
+ veh->AddPassenger(ped, 0);
+ break;
+ case CAR_DOOR_RR:
+ veh->AddPassenger(ped, 2);
+ break;
+ case CAR_DOOR_LR:
+ veh->AddPassenger(ped, 1);
+ break;
+ default:
+ veh->AddPassenger(ped);
+ break;
}
}
+ ped->m_nPedState = PED_DRIVING;
+ if (ped->m_prevObjective == OBJECTIVE_RUN_TO_AREA || ped->m_prevObjective == OBJECTIVE_GOTO_CHAR_ON_FOOT || ped->m_prevObjective == OBJECTIVE_KILL_CHAR_ON_FOOT)
+ ped->m_prevObjective = OBJECTIVE_NONE;
+
+ ped->RestorePreviousObjective();
+#ifdef VC_PED_PORTS
+ if(veh->pDriver && ped->CharCreatedBy == RANDOM_CHAR)
+ veh->AutoPilot.m_nCruiseSpeed = 17;
+#endif
}
- return ourCollidedSpheres;
-}
-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:
+ veh->m_nGettingInFlags &= ~GetCarDoorFlag(ped->m_vehEnterType);
+
+ if (veh->bIsBus && !veh->m_nGettingInFlags)
+ ((CAutomobile*)veh)->SetBusDoorTimer(1000, 1);
+
+ switch (ped->m_objective) {
+ case OBJECTIVE_KILL_CHAR_ON_FOOT:
+ case OBJECTIVE_KILL_CHAR_ANY_MEANS:
+ case OBJECTIVE_LEAVE_CAR:
+ case OBJECTIVE_FOLLOW_CAR_IN_CAR:
+ case OBJECTIVE_GOTO_AREA_ANY_MEANS:
+ case OBJECTIVE_GOTO_AREA_ON_FOOT:
+ case OBJECTIVE_RUN_TO_AREA:
break;
default:
- Error("Unknown formation type, PedAI.cpp");
- break;
+ ped->SetObjective(OBJECTIVE_NONE);
}
- m_pedFormation = type;
-}
-void
-CPed::SetFollowRoute(int16 currentPoint, int16 routeType)
-{
- m_routeLastPoint = currentPoint;
- m_routeStartPoint = CRouteNode::GetRouteStart(currentPoint);
- m_routePointsPassed = 0;
- m_routeType = routeType;
- m_routePointsBeingPassed = 1;
- m_objective = OBJECTIVE_FOLLOW_ROUTE;
- m_nextRoutePointPos = CRouteNode::GetPointPosition(GetNextPointOnRoute());
-}
-
-// "Wander range" state is unused in game, and you can't use it without SetWanderRange anyway
-void
-CPed::WanderRange(void)
-{
- bool arrived = Seek();
- if (arrived) {
- Idle();
- if ((m_randomSeed + 3 * CTimer::GetFrameCounter()) % 1000 > 997) {
- CVector2D newCoords2D = m_wanderRangeBounds->GetRandomPointInRange();
- SetSeek(CVector(newCoords2D.x, newCoords2D.y, GetPosition().z), 2.5f);
+ if (veh->pDriver == ped) {
+ if (veh->bLowVehicle) {
+ ped->m_pVehicleAnim = CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_LSIT, 100.0f);
+ } else {
+ ped->m_pVehicleAnim = CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_SIT, 100.0f);
}
+ } else if (veh->bLowVehicle) {
+ ped->m_pVehicleAnim = CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_SITPLO, 100.0f);
+ } else {
+ ped->m_pVehicleAnim = CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_SITP, 100.0f);
+ }
+
+ ped->StopNonPartialAnims();
+ if (veh->bIsBus)
+ ped->bRenderPedInCar = false;
+
+ // FIX: RegisterVehicleOfInterest not just registers the vehicle, but also updates register time. So remove the IsThisVehicleInteresting check.
+#ifndef FIX_BUGS
+ if (ped->IsPlayer() && !CCarCtrl::IsThisVehicleInteresting(veh) && veh->VehicleCreatedBy != MISSION_VEHICLE) {
+#else
+ if (ped->IsPlayer() && veh->VehicleCreatedBy != MISSION_VEHICLE) {
+#endif
+ CCarCtrl::RegisterVehicleOfInterest(veh);
+
+ if (!veh->bHasBeenOwnedByPlayer && veh->VehicleCreatedBy != MISSION_VEHICLE)
+ CEventList::RegisterEvent(EVENT_STEAL_CAR, EVENT_ENTITY_VEHICLE, veh, ped, 1500);
+
+ veh->bHasBeenOwnedByPlayer = true;
}
+ ped->bChangedSeat = true;
}
bool
-CPed::WillChat(CPed *stranger)
+CPed::CanBeDeleted(void)
{
- if (m_pNextPathNode && m_pLastPathNode) {
- if (m_pNextPathNode != m_pLastPathNode && ThePaths.TestCrossesRoad(m_pNextPathNode, m_pLastPathNode)) {
+ if (bInVehicle)
+ return false;
+
+ switch (CharCreatedBy) {
+ case RANDOM_CHAR:
+ return true;
+ case MISSION_CHAR:
return false;
- }
+ default:
+ return true;
}
- if (m_nSurfaceTouched == SURFACE_TARMAC)
- return false;
- if (stranger == this)
- return false;
- if (m_nPedType == stranger->m_nPedType)
- return true;
- if (m_nPedType == PEDTYPE_CRIMINAL)
- return false;
- if ((IsGangMember() || stranger->IsGangMember()) && m_nPedType != stranger->m_nPedType)
- return false;
- return true;
}
void
-CPed::SetEnterTrain(CVehicle *train, uint32 unused)
+CPed::AddWeaponModel(int id)
{
- if (m_nPedState == PED_ENTER_TRAIN || !((CTrain*)train)->Doors[0].IsFullyOpen())
- return;
+ RpAtomic *atm;
- /*
- // Not used
- CVector enterPos;
- GetNearestTrainPedPosition(train, enterPos);
- */
- m_fRotationCur = train->GetForward().Heading() - HALFPI;
- m_pMyVehicle = train;
- m_pMyVehicle->RegisterReference((CEntity **) &m_pMyVehicle);
+ if (id != -1) {
+#ifdef PED_SKIN
+ if (IsClumpSkinned(GetClump())) {
+ if (m_pWeaponModel)
+ RemoveWeaponModel(-1);
- m_nPedState = PED_ENTER_TRAIN;
- m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_TRAIN_GETIN, 4.0f);
- m_pVehicleAnim->SetFinishCallback(PedSetInTrainCB, this);
- bUsesCollision = false;
- LineUpPedWithTrain();
- if (IsPlayer()) {
- if (((CPlayerPed*)this)->m_bAdrenalineActive)
- ((CPlayerPed*)this)->ClearAdrenaline();
+ m_pWeaponModel = (RpAtomic*)CModelInfo::GetModelInfo(id)->CreateInstance();
+ } else
+#endif
+ {
+ atm = (RpAtomic*)CModelInfo::GetModelInfo(id)->CreateInstance();
+ RwFrameDestroy(RpAtomicGetFrame(atm));
+ RpAtomicSetFrame(atm, m_pFrames[PED_HANDR]->frame);
+ RpClumpAddAtomic(GetClump(), atm);
+ }
+ m_wepModelID = id;
}
}
-void
-CPed::SetDuck(uint32 time)
+static RwObject*
+RemoveAllModelCB(RwObject *object, void *data)
{
- if (bIsDucking || CTimer::GetTimeInMilliseconds() <= m_duckTimer)
- return;
+ RpAtomic *atomic = (RpAtomic*)object;
+ if (CVisibilityPlugins::GetAtomicModelInfo(atomic)) {
+ RpClumpRemoveAtomic(RpAtomicGetClump(atomic), atomic);
+ RpAtomicDestroy(atomic);
+ }
+ return object;
+}
- if (bCrouchWhenShooting && (m_nPedState == PED_ATTACK || m_nPedState == PED_AIM_GUN)) {
- CAnimBlendAssociation *duckAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_LOW);
- if (!duckAssoc || duckAssoc->blendDelta < 0.0f) {
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DUCK_LOW, 4.0f);
- bIsDucking = true;
- m_duckTimer = CTimer::GetTimeInMilliseconds() + time;
+void
+CPed::RemoveWeaponModel(int modelId)
+{
+ // modelId is not used!! This function just removes the current weapon.
+#ifdef PED_SKIN
+ if(IsClumpSkinned(GetClump())){
+ if(m_pWeaponModel){
+ RwFrame *frm = RpAtomicGetFrame(m_pWeaponModel);
+ RpAtomicDestroy(m_pWeaponModel);
+ RwFrameDestroy(frm);
+ m_pWeaponModel = nil;
}
+ }else
+#endif
+ RwFrameForAllObjects(m_pFrames[PED_HANDR]->frame,RemoveAllModelCB,nil);
+ m_wepModelID = -1;
+}
+
+uint32
+CPed::GiveWeapon(eWeaponType weaponType, uint32 ammo)
+{
+ CWeapon &weapon = GetWeapon(weaponType);
+
+ if (HasWeapon(weaponType)) {
+ if (weapon.m_nAmmoTotal + ammo > 99999)
+ weapon.m_nAmmoTotal = 99999;
+ else
+ weapon.m_nAmmoTotal += ammo;
+
+ weapon.Reload();
} else {
- CAnimBlendAssociation *duckAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_DOWN);
- if (!duckAssoc || duckAssoc->blendDelta < 0.0f) {
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DUCK_DOWN, 4.0f);
- bIsDucking = true;
- m_duckTimer = CTimer::GetTimeInMilliseconds() + time;
- }
+ weapon.Initialise(weaponType, ammo);
+ // TODO: It seems game uses this as both weapon count and max WeaponType we have, which is ofcourse erroneous.
+ m_maxWeaponTypeAllowed++;
}
+ if (weapon.m_eWeaponState == WEAPONSTATE_OUT_OF_AMMO)
+ weapon.m_eWeaponState = WEAPONSTATE_READY;
+
+ return weaponType;
+}
+
+// Some kind of VC leftover I think
+int
+CPed::GetWeaponSlot(eWeaponType weaponType)
+{
+ if (HasWeapon(weaponType))
+ return weaponType;
+ else
+ return -1;
}
void
-CPed::SeekBoatPosition(void)
+CPed::SetCurrentWeapon(uint32 weaponType)
{
- if (m_carInObjective && !m_carInObjective->pDriver) {
- CVehicleModelInfo *boatModel = m_carInObjective->GetModelInfo();
+ CWeaponInfo *weaponInfo;
+ if (HasWeapon(weaponType)) {
+ weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
+ RemoveWeaponModel(weaponInfo->m_nModelId);
- CVector enterOffset;
- enterOffset = boatModel->GetFrontSeatPosn();
- enterOffset.x = 0.0f;
- CMatrix boatMat(m_carInObjective->GetMatrix());
- SetMoveState(PEDMOVE_WALK);
- m_vecSeekPos = boatMat * enterOffset;
- if (Seek()) {
- // We arrived to the boat
- m_vehEnterType = 0;
- SetEnterCar(m_carInObjective, 0);
- }
- } else
- RestorePreviousState();
+ m_currentWeapon = weaponType;
+
+ weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
+ AddWeaponModel(weaponInfo->m_nModelId);
+ }
}
void
-CPed::SetEnterCar(CVehicle *car, uint32 unused)
+CPed::GrantAmmo(eWeaponType weaponType, uint32 ammo)
{
- if (CCranes::IsThisCarBeingCarriedByAnyCrane(car)) {
- RestorePreviousState();
- RestorePreviousObjective();
+ if (HasWeapon(weaponType)) {
+ GetWeapon(weaponType).m_nAmmoTotal += ammo;
} else {
- uint8 doorFlag;
- eDoors door;
- switch (m_vehEnterType) {
- case CAR_DOOR_RF:
- doorFlag = CAR_DOOR_FLAG_RF;
- door = DOOR_FRONT_RIGHT;
- break;
- case CAR_DOOR_RR:
- doorFlag = CAR_DOOR_FLAG_RR;
- door = DOOR_REAR_RIGHT;
- break;
- case CAR_DOOR_LF:
- doorFlag = CAR_DOOR_FLAG_LF;
- door = DOOR_FRONT_LEFT;
- break;
- case CAR_DOOR_LR:
- doorFlag = CAR_DOOR_FLAG_LR;
- door = DOOR_REAR_LEFT;
- break;
- default:
- doorFlag = CAR_DOOR_FLAG_UNKNOWN;
- break;
- }
- if (!IsPedInControl() || m_fHealth <= 0.0f
- || doorFlag & car->m_nGettingInFlags || doorFlag & car->m_nGettingOutFlags
- || car->bIsBeingCarJacked || m_pVehicleAnim
- || doorFlag && !car->IsDoorReady(door) && !car->IsDoorFullyOpen(door))
- SetMoveState(PEDMOVE_STILL);
- else
- SetEnterCar_AllClear(car, m_vehEnterType, doorFlag);
+ GetWeapon(weaponType).Initialise(weaponType, ammo);
+ m_maxWeaponTypeAllowed++;
}
}
void
-CPed::SetRadioStation(void)
+CPed::SetAmmo(eWeaponType weaponType, uint32 ammo)
{
- static const uint8 radiosPerRadioCategories[10][4] = {
- {JAH_RADIO, RISE_FM, GAME_FM, MSX_FM},
- {HEAD_RADIO, DOUBLE_CLEF, LIPS_106, FLASHBACK},
- {RISE_FM, GAME_FM, MSX_FM, FLASHBACK},
- {HEAD_RADIO, RISE_FM, LIPS_106, MSX_FM},
- {HEAD_RADIO, RISE_FM, MSX_FM, FLASHBACK},
- {JAH_RADIO, RISE_FM, LIPS_106, FLASHBACK},
- {HEAD_RADIO, RISE_FM, LIPS_106, FLASHBACK},
- {HEAD_RADIO, JAH_RADIO, LIPS_106, FLASHBACK},
- {HEAD_RADIO, DOUBLE_CLEF, LIPS_106, FLASHBACK},
- {CHATTERBOX, HEAD_RADIO, LIPS_106, GAME_FM}
- };
- uint8 orderInCat = 0; // BUG: this wasn't initialized
-
- if (IsPlayer() || !m_pMyVehicle || m_pMyVehicle->pDriver != this)
- return;
-
- uint8 category = GetPedRadioCategory(GetModelIndex());
- if (DMAudio.IsMP3RadioChannelAvailable()) {
- if (CGeneral::GetRandomNumber() & 15) {
- for (orderInCat = 0; orderInCat < 4; orderInCat++) {
- if (m_pMyVehicle->m_nRadioStation == radiosPerRadioCategories[category][orderInCat])
- break;
- }
- } else {
- m_pMyVehicle->m_nRadioStation = USERTRACK;
- }
+ if (HasWeapon(weaponType)) {
+ GetWeapon(weaponType).m_nAmmoTotal = ammo;
} else {
- for (orderInCat = 0; orderInCat < 4; orderInCat++) {
- if (m_pMyVehicle->m_nRadioStation == radiosPerRadioCategories[category][orderInCat])
- break;
- }
- }
- if (orderInCat == 4) {
- if (DMAudio.IsMP3RadioChannelAvailable()) {
- if (CGeneral::GetRandomNumber() & 15)
- m_pMyVehicle->m_nRadioStation = radiosPerRadioCategories[category][CGeneral::GetRandomNumber() & 3];
- else
- m_pMyVehicle->m_nRadioStation = USERTRACK;
- } else {
- m_pMyVehicle->m_nRadioStation = radiosPerRadioCategories[category][CGeneral::GetRandomNumber() & 3];
- }
+ GetWeapon(weaponType).Initialise(weaponType, ammo);
+ m_maxWeaponTypeAllowed++;
}
}
-inline bool
-CPed::IsNotInWreckedVehicle()
+void
+CPed::ClearWeapons(void)
{
- return m_pMyVehicle != nil && m_pMyVehicle->GetStatus() != STATUS_WRECKED;
+ CWeaponInfo *currentWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
+ RemoveWeaponModel(currentWeapon->m_nModelId);
+
+ m_maxWeaponTypeAllowed = WEAPONTYPE_BASEBALLBAT;
+ m_currentWeapon = WEAPONTYPE_UNARMED;
+
+ currentWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
+ AddWeaponModel(currentWeapon->m_nModelId);
+ for(int i = 0; i < WEAPONTYPE_TOTAL_INVENTORY_WEAPONS; i++) {
+ CWeapon &weapon = GetWeapon(i);
+ weapon.m_eWeaponType = WEAPONTYPE_UNARMED;
+ weapon.m_eWeaponState = WEAPONSTATE_READY;
+ weapon.m_nAmmoInClip = 0;
+ weapon.m_nAmmoTotal = 0;
+ weapon.m_nTimer = 0;
+ }
}
void
@@ -14938,691 +4894,1120 @@ CPed::PreRender(void)
}
void
-CPed::ProcessBuoyancy(void)
+CPed::Render(void)
{
- static uint32 nGenerateRaindrops = 0;
- static uint32 nGenerateWaterCircles = 0;
- CRGBA color(((0.5f * CTimeCycle::GetDirectionalRed() + CTimeCycle::GetAmbientRed()) * 127.5f),
- ((0.5f * CTimeCycle::GetDirectionalBlue() + CTimeCycle::GetAmbientBlue()) * 127.5f),
- ((0.5f * CTimeCycle::GetDirectionalGreen() + CTimeCycle::GetAmbientGreen()) * 127.5f),
- (CGeneral::GetRandomNumber() % 256 * 48.0f) + 48);
+ if (bInVehicle && m_nPedState != PED_EXIT_CAR && m_nPedState != PED_DRAG_FROM_CAR) {
+ if (!bRenderPedInCar)
+ return;
- if (bInVehicle)
- return;
+ float camDistSq = (TheCamera.GetPosition() - GetPosition()).MagnitudeSqr();
+ if (camDistSq > SQR(25.0f * TheCamera.LODDistMultiplier))
+ return;
+ }
- CVector buoyancyPoint;
- CVector buoyancyImpulse;
+ CEntity::Render();
-#ifndef VC_PED_PORTS
- float buoyancyLevel = (m_nPedState == PED_DEAD ? 1.5f : 1.3f);
-#else
- float buoyancyLevel = (m_nPedState == PED_DEAD ? 1.8f : 1.1f);
+#ifdef PED_SKIN
+ if(IsClumpSkinned(GetClump())){
+ renderLimb(PED_HEAD);
+ renderLimb(PED_HANDL);
+ renderLimb(PED_HANDR);
+ }
+ if(m_pWeaponModel && IsClumpSkinned(GetClump())){
+ RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(GetClump());
+ int idx = RpHAnimIDGetIndex(hier, m_pFrames[PED_HANDR]->nodeID);
+ RwMatrix *mat = &RpHAnimHierarchyGetMatrixArray(hier)[idx];
+ RwFrame *frame = RpAtomicGetFrame(m_pWeaponModel);
+ *RwFrameGetMatrix(frame) = *mat;
+ RwFrameUpdateObjects(frame);
+ RpAtomicRender(m_pWeaponModel);
+ }
#endif
+}
- if (mod_Buoyancy.ProcessBuoyancy(this, GRAVITY * m_fMass * buoyancyLevel, &buoyancyPoint, &buoyancyImpulse)) {
- bTouchingWater = true;
- CEntity *entity;
- CColPoint point;
- if (CWorld::ProcessVerticalLine(GetPosition(), GetPosition().z - 3.0f, point, entity, false, true, false, false, false, false, nil)
- && entity->IsVehicle() && ((CVehicle*)entity)->IsBoat()) {
- bIsInWater = false;
- return;
+void
+CPed::CheckAroundForPossibleCollisions(void)
+{
+ CVector ourCentre, objCentre;
+ CEntity *objects[8];
+ int16 maxObject;
+
+ if (CTimer::GetTimeInMilliseconds() <= m_nPedStateTimer)
+ return;
+
+ GetBoundCentre(ourCentre);
+
+ CWorld::FindObjectsInRange(ourCentre, 10.0f, true, &maxObject, 6, objects, false, true, false, true, false);
+ for (int i = 0; i < maxObject; i++) {
+ CEntity *object = objects[i];
+ if (bRunningToPhone) {
+ if (gPhoneInfo.PhoneAtThisPosition(object->GetPosition()))
+ break;
}
- bIsInWater = true;
- ApplyMoveForce(buoyancyImpulse);
- if (!DyingOrDead()) {
- if (bTryingToReachDryLand) {
- if (buoyancyImpulse.z / m_fMass > GRAVITY * 0.4f * CTimer::GetTimeStep()) {
- bTryingToReachDryLand = false;
- CVector pos = GetPosition();
- if (PlacePedOnDryLand()) {
- if (m_fHealth > 20.0f)
- InflictDamage(nil, WEAPONTYPE_DROWNING, 15.0f, PEDPIECE_TORSO, false);
+ object->GetBoundCentre(objCentre);
+ float radius = object->GetBoundRadius();
+ if (radius > 4.5f || radius < 1.0f)
+ radius = 1.0f;
- if (bIsInTheAir) {
- RpAnimBlendClumpSetBlendDeltas(GetClump(), ASSOC_PARTIAL, -1000.0f);
- bIsInTheAir = false;
- }
- pos.z = pos.z - 0.8f;
-#ifdef PC_PARTICLE
- CParticleObject::AddObject(POBJECT_PED_WATER_SPLASH, pos, CVector(0.0f, 0.0f, 0.0f), 0.0f, 50, color, true);
-#else
- CParticleObject::AddObject(POBJECT_PED_WATER_SPLASH, pos, CVector(0.0f, 0.0f, 0.0f), 0.0f, 50, CRGBA(0, 0, 0, 0), true);
-#endif
- m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
- m_nPedState = PED_IDLE;
- return;
- }
- }
- }
- float speedMult = 0.0f;
- if (buoyancyImpulse.z / m_fMass > GRAVITY * 0.75f * CTimer::GetTimeStep()
- || mod_Buoyancy.m_waterlevel > GetPosition().z) {
- speedMult = pow(0.9f, CTimer::GetTimeStep());
- m_vecMoveSpeed.x *= speedMult;
- m_vecMoveSpeed.y *= speedMult;
- m_vecMoveSpeed.z *= speedMult;
- bIsStanding = false;
- InflictDamage(nil, WEAPONTYPE_DROWNING, 3.0f * CTimer::GetTimeStep(), PEDPIECE_TORSO, 0);
- }
- if (buoyancyImpulse.z / m_fMass > GRAVITY * 0.25f * CTimer::GetTimeStep()) {
- if (speedMult == 0.0f) {
- speedMult = pow(0.9f, CTimer::GetTimeStep());
- }
- m_vecMoveSpeed.x *= speedMult;
- m_vecMoveSpeed.y *= speedMult;
- if (m_vecMoveSpeed.z >= -0.1f) {
- if (m_vecMoveSpeed.z < -0.04f)
- m_vecMoveSpeed.z = -0.02f;
- } else {
- m_vecMoveSpeed.z = -0.01f;
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_SPLASH, 0.0f);
-#ifdef PC_PARTICLE
- CVector aBitForward = 2.2f * m_vecMoveSpeed + GetPosition();
- float level = 0.0f;
- if (CWaterLevel::GetWaterLevel(aBitForward, &level, false))
- aBitForward.z = level;
+ // Developers gave up calculating Z diff. later according to asm.
+ float diff = CVector(ourCentre - objCentre).MagnitudeSqr2D();
- CParticleObject::AddObject(POBJECT_PED_WATER_SPLASH, aBitForward, CVector(0.0f, 0.0f, 0.1f), 0.0f, 200, color, true);
- nGenerateRaindrops = CTimer::GetTimeInMilliseconds() + 80;
- nGenerateWaterCircles = CTimer::GetTimeInMilliseconds() + 100;
-#else
- CVector aBitForward = 1.6f * m_vecMoveSpeed + GetPosition();
- float level = 0.0f;
- if (CWaterLevel::GetWaterLevel(aBitForward, &level, false))
- aBitForward.z = level + 0.5f;
-
- CVector vel = m_vecMoveSpeed * 0.1f;
- vel.z = 0.18f;
- CParticleObject::AddObject(POBJECT_PED_WATER_SPLASH, aBitForward, vel, 0.0f, 350, CRGBA(0, 0, 0, 0), true);
- nGenerateRaindrops = CTimer::GetTimeInMilliseconds() + 300;
- nGenerateWaterCircles = CTimer::GetTimeInMilliseconds() + 60;
+ if (sq(radius + 1.0f) > diff)
+ m_fRotationDest += DEGTORAD(22.5f);
+ }
+}
+
+void
+CPed::SetIdle(void)
+{
+ if (m_nPedState != PED_IDLE && m_nPedState != PED_MUG && m_nPedState != PED_FLEE_ENTITY) {
+#ifdef VC_PED_PORTS
+ if (m_nPedState == PED_AIM_GUN)
+ ClearPointGunAt();
+
+ m_nLastPedState = PED_NONE;
#endif
+ m_nPedState = PED_IDLE;
+ SetMoveState(PEDMOVE_STILL);
+ }
+ if (m_nWaitState == WAITSTATE_FALSE) {
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(2000, 4000);
+ }
+}
+
+void
+CPed::Idle(void)
+{
+ CVehicle *veh = m_pMyVehicle;
+ if (veh && veh->m_nGettingOutFlags && m_vehEnterType) {
+
+ if (veh->m_nGettingOutFlags & GetCarDoorFlag(m_vehEnterType)) {
+
+ if (m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT) {
+
+ CVector doorPos = GetPositionToOpenCarDoor(veh, m_vehEnterType);
+ CVector doorDist = GetPosition() - doorPos;
+
+ if (doorDist.MagnitudeSqr() < sq(0.5f)) {
+ SetMoveState(PEDMOVE_WALK);
+ return;
}
}
- } else
- return;
- } else
- bTouchingWater = false;
+ }
+ }
- if (nGenerateWaterCircles && CTimer::GetTimeInMilliseconds() >= nGenerateWaterCircles) {
- CVector pos = GetPosition();
- float level = 0.0f;
- if (CWaterLevel::GetWaterLevel(pos, &level, false))
- pos.z = level;
+ CAnimBlendAssociation *armedIdleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_ARMED);
+ CAnimBlendAssociation *unarmedIdleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE);
+ int waitTime;
- if (pos.z != 0.0f) {
- nGenerateWaterCircles = 0;
- for(int i = 0; i < 4; i++) {
-#ifdef PC_PARTICLE
- pos.x += CGeneral::GetRandomNumberInRange(-0.75f, 0.75f);
- pos.y += CGeneral::GetRandomNumberInRange(-0.75f, 0.75f);
- CParticle::AddParticle(PARTICLE_RAIN_SPLASH_BIGGROW, pos, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f, color, 0, 0, 0, 0);
-#else
- pos.x += CGeneral::GetRandomNumberInRange(-2.5f, 2.5f);
- pos.y += CGeneral::GetRandomNumberInRange(-2.5f, 2.5f);
- CParticle::AddParticle(PARTICLE_RAIN_SPLASH_BIGGROW, pos+CVector(0.0f, 0.0f, 1.0f), CVector(0.0f, 0.0f, 0.0f));
-#endif
+ if (m_nMoveState == PEDMOVE_STILL) {
+
+ eWeaponType curWeapon = GetWeapon()->m_eWeaponType;
+ if (!armedIdleAssoc ||
+ CTimer::GetTimeInMilliseconds() <= m_nWaitTimer && curWeapon != WEAPONTYPE_UNARMED && curWeapon != WEAPONTYPE_MOLOTOV && curWeapon != WEAPONTYPE_GRENADE) {
+
+ if ((!GetWeapon()->IsType2Handed() || curWeapon == WEAPONTYPE_SHOTGUN) && curWeapon != WEAPONTYPE_BASEBALLBAT
+ || !unarmedIdleAssoc || unarmedIdleAssoc->blendAmount <= 0.95f || m_nWaitState != WAITSTATE_FALSE || CTimer::GetTimeInMilliseconds() <= m_nWaitTimer) {
+
+ m_moved = CVector2D(0.0f, 0.0f);
+ return;
}
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_ARMED, 3.0f);
+ waitTime = CGeneral::GetRandomNumberInRange(4000, 7500);
+ } else {
+ armedIdleAssoc->blendDelta = -2.0f;
+ armedIdleAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ waitTime = CGeneral::GetRandomNumberInRange(3000, 8500);
}
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + waitTime;
+ } else {
+ if (armedIdleAssoc) {
+ armedIdleAssoc->blendDelta = -8.0f;
+ armedIdleAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ m_nWaitTimer = 0;
+ }
+ if (!IsPlayer())
+ SetMoveState(PEDMOVE_STILL);
}
+ m_moved = CVector2D(0.0f, 0.0f);
+}
- if (nGenerateRaindrops && CTimer::GetTimeInMilliseconds() >= nGenerateRaindrops) {
- CVector pos = GetPosition();
- float level = 0.0f;
- if (CWaterLevel::GetWaterLevel(pos, &level, false))
- pos.z = level;
+void
+CPed::ClearPause(void)
+{
+ RestorePreviousState();
+}
- if (pos.z >= 0.0f) {
-#ifdef PC_PARTICLE
- pos.z += 0.25f;
-#else
- pos.z += 0.5f;
+void
+CPed::Pause(void)
+{
+ m_moved = CVector2D(0.0f, 0.0f);
+ if (CTimer::GetTimeInMilliseconds() > m_leaveCarTimer)
+ ClearPause();
+}
+
+void
+CPed::SetFall(int extraTime, AnimationId animId, uint8 evenIfNotInControl)
+{
+ if (!IsPedInControl() && (!evenIfNotInControl || DyingOrDead()))
+ return;
+
+ ClearLookFlag();
+ ClearAimFlag();
+ SetStoredState();
+ m_nPedState = PED_FALL;
+ CAnimBlendAssociation *fallAssoc = RpAnimBlendClumpGetAssociation(GetClump(), animId);
+
+ if (fallAssoc) {
+ fallAssoc->SetCurrentTime(0.0f);
+ fallAssoc->blendAmount = 0.0f;
+ fallAssoc->blendDelta = 8.0f;
+ fallAssoc->SetRun();
+ } else {
+ fallAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animId, 8.0f);
+ }
+
+ if (extraTime == -1) {
+ m_getUpTimer = UINT32_MAX;
+ } else if (fallAssoc) {
+ if (IsPlayer()) {
+ m_getUpTimer = 1000.0f * fallAssoc->hierarchy->totalLength
+ + CTimer::GetTimeInMilliseconds()
+ + 500.0f;
+ } else {
+ m_getUpTimer = 1000.0f * fallAssoc->hierarchy->totalLength
+ + CTimer::GetTimeInMilliseconds()
+ + extraTime
+ + ((m_randomSeed + CTimer::GetFrameCounter()) % 1000);
+ }
+ } else {
+ m_getUpTimer = extraTime
+ + CTimer::GetTimeInMilliseconds()
+ + 1000
+ + ((m_randomSeed + CTimer::GetFrameCounter()) % 1000);
+ }
+ bFallenDown = true;
+}
+
+void
+CPed::ClearFall(void)
+{
+ SetGetUp();
+}
+
+void
+CPed::Fall(void)
+{
+ if (m_getUpTimer != UINT32_MAX && CTimer::GetTimeInMilliseconds() > m_getUpTimer
+#ifdef VC_PED_PORTS
+ && bIsStanding
#endif
- nGenerateRaindrops = 0;
-#ifdef PC_PARTICLE
- CParticleObject::AddObject(POBJECT_SPLASHES_AROUND, pos, CVector(0.0f, 0.0f, 0.0f), 4.5f, 1500, CRGBA(0,0,0,0), true);
-#else
- CParticleObject::AddObject(POBJECT_SPLASHES_AROUND, pos, CVector(0.0f, 0.0f, 0.0f), 4.5f, 2500, CRGBA(0,0,0,0), true);
+ )
+ ClearFall();
+
+ // VC plays animations ANIM_STD_FALL_ONBACK and ANIM_STD_FALL_ONFRONT in here, which doesn't exist in III.
+}
+
+bool
+CPed::CheckIfInTheAir(void)
+{
+ if (bInVehicle)
+ return false;
+
+ CVector pos = GetPosition();
+ CColPoint foundColPoint;
+ CEntity *foundEntity;
+
+ float startZ = pos.z - 1.54f;
+ bool foundGround = CWorld::ProcessVerticalLine(pos, startZ, foundColPoint, foundEntity, true, true, false, true, false, false, nil);
+ if (!foundGround && m_nPedState != PED_JUMP)
+ {
+ pos.z -= FEET_OFFSET;
+ if (CWorld::TestSphereAgainstWorld(pos, 0.15f, this, true, false, false, false, false, false))
+ foundGround = true;
+ }
+ return !foundGround;
+}
+
+void
+CPed::SetInTheAir(void)
+{
+ if (bIsInTheAir)
+ return;
+
+ bIsInTheAir = true;
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FALL_GLIDE, 4.0f);
+
+ if (m_nPedState == PED_ATTACK) {
+ ClearAttack();
+ ClearPointGunAt();
+ } else if (m_nPedState == PED_FIGHT) {
+ EndFight(ENDFIGHT_FAST);
+ }
+
+}
+
+void
+CPed::InTheAir(void)
+{
+ CColPoint foundCol;
+ CEntity *foundEnt;
+
+ CVector ourPos = GetPosition();
+ CVector bitBelow = GetPosition();
+ bitBelow.z -= 4.04f;
+
+ if (m_vecMoveSpeed.z < 0.0f && !bIsPedDieAnimPlaying) {
+ if (!DyingOrDead()) {
+ if (CWorld::ProcessLineOfSight(ourPos, bitBelow, foundCol, foundEnt, true, true, false, true, false, false, false)) {
+ if (GetPosition().z - foundCol.point.z < 1.3f
+#ifdef VC_PED_PORTS
+ || bIsStanding
#endif
+ )
+ SetLanding();
+ } else {
+ if (!RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FALL_FALL)) {
+ if (m_vecMoveSpeed.z < -0.1f)
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FALL_FALL, 4.0f);
+ }
+ }
}
}
}
void
-CPed::SetSolicit(uint32 time)
+CPed::SetLanding(void)
{
- if (m_nPedState == PED_SOLICIT || !IsPedInControl() || !m_carInObjective)
+ if (DyingOrDead())
return;
- if (CharCreatedBy != MISSION_CHAR && m_carInObjective->m_nNumGettingIn == 0
- && CTimer::GetTimeInMilliseconds() < m_objectiveTimer) {
- if (m_vehEnterType == CAR_DOOR_LF) {
- m_fRotationDest = m_carInObjective->GetForward().Heading() - HALFPI;
- } else {
- m_fRotationDest = m_carInObjective->GetForward().Heading() + HALFPI;
+ CAnimBlendAssociation *fallAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FALL_FALL);
+ CAnimBlendAssociation *landAssoc;
+
+ RpAnimBlendClumpSetBlendDeltas(GetClump(), ASSOC_PARTIAL, -1000.0f);
+ if (fallAssoc) {
+ landAssoc = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_FALL_COLLAPSE);
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_FALL_COLLAPSE, 1.0f);
+
+ if (IsPlayer())
+ Say(SOUND_PED_LAND);
+
+ } else {
+ landAssoc = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_FALL_LAND);
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_FALL_LAND, 1.0f);
+ }
+
+ landAssoc->SetFinishCallback(PedLandCB, this);
+ bIsInTheAir = false;
+ bIsLanding = true;
+}
+
+void
+CPed::SetGetUp(void)
+{
+ if (m_nPedState == PED_GETUP && bGetUpAnimStarted)
+ return;
+
+ if (!CanSetPedState())
+ return;
+
+ if (m_fHealth >= 1.0f || IsPedHeadAbovePos(-0.3f)) {
+ if (bUpdateAnimHeading) {
+ m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur);
+ m_fRotationCur -= HALFPI;
+ bUpdateAnimHeading = false;
+ }
+ if (m_nPedState != PED_GETUP) {
+ SetStoredState();
+ m_nPedState = PED_GETUP;
}
- if (Abs(m_fRotationDest - m_fRotationCur) < HALFPI) {
- m_standardTimer = CTimer::GetTimeInMilliseconds() + time;
+ CVehicle *collidingVeh = (CVehicle*)m_pCollidingEntity;
+ CVehicle *veh = (CVehicle*)CPedPlacement::IsPositionClearOfCars(&GetPosition());
+ if (veh && veh->m_vehType != VEHICLE_TYPE_BIKE ||
+ collidingVeh && collidingVeh->IsVehicle() && collidingVeh->m_vehType != VEHICLE_TYPE_BIKE
+ && ((uint8)(CTimer::GetFrameCounter() + m_randomSeed + 5) % 8 ||
+ CCollision::ProcessColModels(GetMatrix(), *GetColModel(), collidingVeh->GetMatrix(), *collidingVeh->GetColModel(),
+ aTempPedColPts, nil, nil) > 0)) {
- if(!m_carInObjective->bIsVan && !m_carInObjective->bIsBus)
- m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_HOOKERTALK, 4.0f);
+ bGetUpAnimStarted = false;
+ if (IsPlayer())
+ InflictDamage(nil, WEAPONTYPE_RUNOVERBYCAR, CTimer::GetTimeStep(), PEDPIECE_TORSO, 0);
+ else {
+ if (!CPad::GetPad(0)->ArePlayerControlsDisabled())
+ return;
- m_nPedState = PED_SOLICIT;
+ InflictDamage(nil, WEAPONTYPE_RUNOVERBYCAR, 1000.0f, PEDPIECE_TORSO, 0);
+ }
+ return;
}
+ bGetUpAnimStarted = true;
+ m_pCollidingEntity = nil;
+ bKnockedUpIntoAir = false;
+ CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_SPRINT);
+ if (animAssoc) {
+ if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN)) {
+ CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_RUN, 8.0f);
+ } else {
+ CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 8.0f);
+ }
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ }
+
+ if (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL))
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_GETUP_FRONT, 1000.0f);
+ else
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_GETUP1, 1000.0f);
+
+ animAssoc->SetFinishCallback(PedGetupCB,this);
+ } else {
+ m_fHealth = 0.0f;
+ SetDie(NUM_ANIMS, 4.0f, 0.0f);
}
}
-bool
-CPed::SetFollowPath(CVector dest)
+void
+CPed::Mug(void)
{
- if (m_nPedState == PED_FOLLOW_PATH)
- return false;
+ if (m_pSeekTarget && m_pSeekTarget->IsPed()) {
- if (FindPlayerPed() != this)
- return false;
+ if (CTimer::GetTimeInMilliseconds() <= m_attackTimer - 2000) {
+ if ((m_pSeekTarget->GetPosition() - GetPosition()).Magnitude() > 3.0f)
+ m_wepSkills = 50;
- if ((dest - GetPosition()).Magnitude() <= 2.0f)
- return false;
+ Say(SOUND_PED_MUGGING);
+ ((CPed*)m_pSeekTarget)->Say(SOUND_PED_ROBBED);
+ } else {
+ SetWanderPath(CGeneral::GetRandomNumber() & 7);
+ SetFlee(m_pSeekTarget, 20000);
+ }
- CVector pointPoses[7];
- int16 pointsFound;
- CPedPath::CalcPedRoute(0, GetPosition(), dest, pointPoses, &pointsFound, 7);
- for(int i = 0; i < pointsFound; i++) {
- m_stPathNodeStates[i].x = pointPoses[i].x;
- m_stPathNodeStates[i].y = pointPoses[i].y;
+ } else {
+ SetIdle();
}
+}
- m_nCurPathNode = 0;
- m_nPathNodes = pointsFound;
- if (m_nPathNodes < 1)
- return false;
+void
+CPed::SetLookTimer(int time)
+{
+ if (CTimer::GetTimeInMilliseconds() > m_lookTimer) {
+ m_lookTimer = CTimer::GetTimeInMilliseconds() + time;
+ }
+}
- SetStoredState();
- m_nPedState = PED_FOLLOW_PATH;
- SetMoveState(PEDMOVE_WALK);
- return true;
+void
+CPed::SetAttackTimer(uint32 time)
+{
+ if (CTimer::GetTimeInMilliseconds() > m_attackTimer)
+ m_attackTimer = Max(m_shootTimer, CTimer::GetTimeInMilliseconds()) + time;
}
void
-AddYardieDoorSmoke(CVehicle *veh, uint32 doorNode)
+CPed::SetShootTimer(uint32 time)
{
- eDoors door;
- switch (doorNode) {
- case CAR_DOOR_RF:
- door = DOOR_FRONT_RIGHT;
- break;
- case CAR_DOOR_LF:
- door = DOOR_FRONT_LEFT;
- break;
- default:
- break;
+ if (CTimer::GetTimeInMilliseconds() > m_shootTimer) {
+ m_shootTimer = CTimer::GetTimeInMilliseconds() + time;
}
+}
- if (!veh->IsDoorMissing(door) && veh->IsComponentPresent(doorNode)) {
- CVector pos;
-#ifdef FIX_BUGS
- veh->GetComponentWorldPosition(doorNode, pos);
-#else
- veh->GetComponentWorldPosition(CAR_DOOR_LF, pos);
-#endif
- CParticle::AddYardieDoorSmoke(pos, veh->GetMatrix());
+void
+CPed::ClearLook(void)
+{
+ RestorePreviousState();
+ ClearLookFlag();
+}
+
+void
+CPed::Look(void)
+{
+ // UNUSED: This is a perfectly empty function.
+}
+
+bool
+CPed::TurnBody(void)
+{
+ bool turnDone = true;
+
+ if (m_pLookTarget)
+ m_fLookDirection = CGeneral::GetRadianAngleBetweenPoints(
+ m_pLookTarget->GetPosition().x,
+ m_pLookTarget->GetPosition().y,
+ GetPosition().x,
+ GetPosition().y);
+
+ float limitedLookDir = CGeneral::LimitRadianAngle(m_fLookDirection);
+ float currentRot = m_fRotationCur;
+
+ if (currentRot - PI > limitedLookDir)
+ limitedLookDir += 2 * PI;
+ else if (PI + currentRot < limitedLookDir)
+ limitedLookDir -= 2 * PI;
+
+ float neededTurn = currentRot - limitedLookDir;
+ m_fRotationDest = limitedLookDir;
+
+ if (Abs(neededTurn) > 0.05f) {
+ turnDone = false;
+ currentRot -= neededTurn * 0.2f;
}
+
+ m_fRotationCur = currentRot;
+ m_fLookDirection = limitedLookDir;
+ return turnDone;
}
-// wantedDoorNode = 0 means that func. will determine it
void
-CPed::SetExitCar(CVehicle *veh, uint32 wantedDoorNode)
+CPed::SetSeek(CVector pos, float distanceToCountDone)
{
- uint32 optedDoorNode = wantedDoorNode;
- bool teleportNeeded = false;
- bool isLow = !!veh->bLowVehicle;
- if (!veh->CanPedExitCar()) {
- if (veh->pDriver && !veh->pDriver->IsPlayer()) {
- veh->AutoPilot.m_nCruiseSpeed = 0;
- veh->AutoPilot.m_nCarMission = MISSION_NONE;
- }
+ if (!IsPedInControl()
+ || (m_nPedState == PED_SEEK_POS && m_vecSeekPos.x == pos.x && m_vecSeekPos.y == pos.y))
return;
+
+ if (GetWeapon()->m_eWeaponType == WEAPONTYPE_M16
+ || GetWeapon()->m_eWeaponType == WEAPONTYPE_AK47
+ || GetWeapon()->m_eWeaponType == WEAPONTYPE_SNIPERRIFLE
+ || GetWeapon()->m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER
+ || GetWeapon()->m_eWeaponType == WEAPONTYPE_SHOTGUN) {
+ ClearPointGunAt();
}
- if (m_nPedState == PED_EXIT_CAR || m_nPedState == PED_DRAG_FROM_CAR)
+ if (m_nPedState != PED_SEEK_POS)
+ SetStoredState();
+
+ m_nPedState = PED_SEEK_POS;
+ m_distanceToCountSeekDone = distanceToCountDone;
+ m_vecSeekPos = pos;
+}
+
+void
+CPed::SetSeek(CEntity *seeking, float distanceToCountDone)
+{
+ if (!IsPedInControl())
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->bIsBus) {
- 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;
+ if (m_nPedState == PED_SEEK_ENTITY && m_pSeekTarget == seeking)
+ return;
- break;
+ if (!seeking)
+ return;
+
+ if (m_nPedState != PED_SEEK_ENTITY)
+ SetStoredState();
+
+ m_nPedState = PED_SEEK_ENTITY;
+ m_distanceToCountSeekDone = distanceToCountDone;
+ m_pSeekTarget = seeking;
+ m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget);
+ SetMoveState(PEDMOVE_STILL);
+}
+
+void
+CPed::ClearSeek(void)
+{
+ SetIdle();
+ bRunningToPhone = false;
+}
+
+bool
+CPed::Seek(void)
+{
+ float distanceToCountItDone = m_distanceToCountSeekDone;
+ eMoveState nextMove = PEDMOVE_NONE;
+
+ if (m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER) {
+
+ if (m_nPedState != PED_EXIT_TRAIN && m_nPedState != PED_ENTER_TRAIN && m_nPedState != PED_SEEK_IN_BOAT &&
+ m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER && m_objective != OBJECTIVE_SOLICIT_VEHICLE && !bDuckAndCover) {
+
+ if ((!m_pedInObjective || !m_pedInObjective->bInVehicle)
+ && !((CTimer::GetFrameCounter() + (m_randomSeed % 256) + 17) & 7)) {
+
+ CEntity *obstacle = CWorld::TestSphereAgainstWorld(m_vecSeekPos, 0.4f, nil,
+ false, true, false, false, false, false);
+
+ if (obstacle) {
+ if (!obstacle->IsVehicle() || ((CVehicle*)obstacle)->m_vehType == VEHICLE_TYPE_CAR) {
+ distanceToCountItDone = 2.5f;
+ } else {
+ CVehicleModelInfo *vehModel = (CVehicleModelInfo *)CModelInfo::GetModelInfo(obstacle->GetModelIndex());
+ float yLength = vehModel->GetColModel()->boundingBox.max.y
+ - vehModel->GetColModel()->boundingBox.min.y;
+ distanceToCountItDone = yLength * 0.55f;
}
}
}
}
}
- bool someoneExitsFromOurExitDoor = false;
- bool someoneEntersFromOurExitDoor = false;
- 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 (!m_pSeekTarget && m_nPedState == PED_SEEK_ENTITY)
+ ClearSeek();
+
+ float seekPosDist = (m_vecSeekPos - GetPosition()).Magnitude2D();
+ if (seekPosDist < 2.0f || m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT) {
+
+ if (m_objective == OBJECTIVE_FOLLOW_CHAR_IN_FORMATION) {
+
+ if (m_pedInObjective->m_nMoveState != PEDMOVE_STILL)
+ nextMove = m_pedInObjective->m_nMoveState;
+ } else
+ nextMove = PEDMOVE_WALK;
+
+ } else if (m_objective != OBJECTIVE_FOLLOW_CHAR_IN_FORMATION) {
+
+ if (m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS || m_objective == OBJECTIVE_RUN_TO_AREA || bIsRunning)
+ nextMove = PEDMOVE_RUN;
+ else
+ nextMove = PEDMOVE_WALK;
+
+ } else if (seekPosDist <= 2.0f) {
+
+ if (m_pedInObjective->m_nMoveState != PEDMOVE_STILL)
+ nextMove = m_pedInObjective->m_nMoveState;
+
+ } else {
+ nextMove = PEDMOVE_RUN;
}
- if (someoneEntersFromOurExitDoor && m_objective == OBJECTIVE_LEAVE_CAR) {
- RestorePreviousObjective();
- return;
+
+ if (m_nPedState == PED_SEEK_ENTITY) {
+ if (m_pSeekTarget->IsPed()) {
+ if (((CPed*)m_pSeekTarget)->bInVehicle)
+ distanceToCountItDone += 2.0f;
+ }
}
- if (!someoneExitsFromOurExitDoor || m_nPedType == PEDTYPE_COP && veh->bIsBus) {
- // Again, unused...
- // CVector exitPos = GetPositionToOpenCarDoor(veh, optedDoorNode);
- bool thereIsRoom = veh->IsRoomForPedToLeaveCar(optedDoorNode, nil);
- if (veh->IsOnItsSide()) {
- teleportNeeded = true;
- } else if (!thereIsRoom) {
- bool trySideSeat = false;
- CPed *pedOnSideSeat = nil;
- 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;
+ if (seekPosDist >= distanceToCountItDone) {
+ if (bIsRunning)
+ nextMove = PEDMOVE_RUN;
- 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;
+ if (CTimer::GetTimeInMilliseconds() <= m_nPedStateTimer) {
- 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;
+ if (m_actionX != 0.0f && m_actionY != 0.0f) {
- break;
- default:
- break;
- }
- if (trySideSeat) {
- if (!pedOnSideSeat || !IsPlayer() && CharCreatedBy != MISSION_CHAR)
- return;
+ m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(
+ m_actionX, m_actionY,
+ GetPosition().x, GetPosition().y);
- 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;
+ float neededTurn = Abs(m_fRotationDest - m_fRotationCur);
+
+ if (neededTurn > PI)
+ neededTurn = TWOPI - neededTurn;
+
+ if (neededTurn > HALFPI) {
+ if (seekPosDist >= 1.0f) {
+ if (seekPosDist < 2.0f) {
+ if (bIsRunning)
+ nextMove = PEDMOVE_RUN;
+ else
+ nextMove = PEDMOVE_WALK;
+ }
+ } else {
+ nextMove = PEDMOVE_STILL;
+ }
}
- }
- // ...
- // CVector exitPos = GetPositionToOpenCarDoor(veh, optedDoorNode);
- if (!veh->IsRoomForPedToLeaveCar(optedDoorNode, nil)) {
- if (!IsPlayer() && CharCreatedBy != MISSION_CHAR)
- return;
- teleportNeeded = true;
+ CVector2D moveDist(GetPosition().x - m_actionX, GetPosition().y - m_actionY);
+ if (moveDist.Magnitude() < 0.5f) {
+ m_nPedStateTimer = 0;
+ m_actionX = 0;
+ m_actionY = 0;
+ }
}
- }
- 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);
- }
+ m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(
+ m_vecSeekPos.x, m_vecSeekPos.y,
+ GetPosition().x, GetPosition().y);
- ReplaceWeaponWhenExitingVehicle();
- bUsesCollision = false;
- m_pSeekTarget = veh;
- m_pSeekTarget->RegisterReference((CEntity**) &m_pSeekTarget);
- m_vehEnterType = optedDoorNode;
- m_nPedState = PED_EXIT_CAR;
- if (m_pVehicleAnim && m_pVehicleAnim->flags & ASSOC_PARTIAL)
- m_pVehicleAnim->blendDelta = -1000.0f;
- SetMoveState(PEDMOVE_NONE);
- CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 100.0f);
- RemoveInCarAnims();
- veh->AutoPilot.m_nCruiseSpeed = 0;
- if (teleportNeeded) {
- PedSetOutCarCB(nil, this);
-
- // This is same code with CPedPlacement::FindZCoorForPed, except we start from z + 1.5 and also check vehicles.
- float zForPed;
- float startZ = GetPosition().z - 100.0f;
- float foundColZ = -100.0f;
- float foundColZ2 = -100.0f;
- CColPoint foundCol;
- CEntity* foundEnt;
-
- CVector vec = GetPosition();
- vec.z += 1.5f;
-
- if (CWorld::ProcessVerticalLine(vec, startZ, foundCol, foundEnt, true, true, false, false, true, false, nil))
- foundColZ = foundCol.point.z;
-
- // Adjust coords and do a second test
- vec.x += 0.1f;
- vec.y += 0.1f;
-
- if (CWorld::ProcessVerticalLine(vec, startZ, foundCol, foundEnt, true, true, false, false, true, false, nil))
- foundColZ2 = foundCol.point.z;
-
- zForPed = Max(foundColZ, foundColZ2);
-
- if (zForPed > -99.0f)
- GetMatrix().GetPosition().z = FEET_OFFSET + zForPed;
- } else {
- if (veh->GetUp().z > -0.8f) {
- bool addDoorSmoke = false;
- if (veh->GetModelIndex() == MI_YARDIE)
- addDoorSmoke = true;
-
- switch (m_vehEnterType) {
- case CAR_DOOR_RF:
- if (veh->bIsBus) {
- m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_COACH_OUT_L);
- } else {
- if (isLow)
- m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_LOW_RHS);
- else
- m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_RHS);
+ float neededTurn = Abs(m_fRotationDest - m_fRotationCur);
- if (addDoorSmoke)
- AddYardieDoorSmoke(veh, CAR_DOOR_RF);
- }
- break;
- case CAR_DOOR_RR:
- if (veh->bIsVan) {
- m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_VAN_GETOUT);
- } else if (isLow) {
- m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_LOW_RHS);
- } else {
- m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_RHS);
- }
- break;
- case CAR_DOOR_LF:
- if (veh->bIsBus) {
- m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_COACH_OUT_L);
- } else {
- if (isLow)
- m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_LOW_LHS);
- else
- m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_LHS);
+ if (neededTurn > PI)
+ neededTurn = TWOPI - neededTurn;
- if (addDoorSmoke)
- AddYardieDoorSmoke(veh, CAR_DOOR_LF);
- }
- break;
- case CAR_DOOR_LR:
- if (veh->bIsVan) {
- m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_VAN_GETOUT_L);
- } else if (isLow) {
- m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_LOW_LHS);
- } else {
- m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_LHS);
- }
- break;
- default:
- break;
- }
- if (!bBusJacked) {
- switch (m_vehEnterType) {
- case CAR_DOOR_RF:
- veh->m_nGettingOutFlags |= CAR_DOOR_FLAG_RF;
- break;
- case CAR_DOOR_RR:
- veh->m_nGettingOutFlags |= CAR_DOOR_FLAG_RR;
- break;
- case CAR_DOOR_LF:
- veh->m_nGettingOutFlags |= CAR_DOOR_FLAG_LF;
- break;
- case CAR_DOOR_LR:
- veh->m_nGettingOutFlags |= CAR_DOOR_FLAG_LR;
- break;
- default:
- break;
- }
- }
- m_pVehicleAnim->SetFinishCallback(PedAnimStepOutCarCB, this);
- } else {
- if (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR) {
- m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_CRAWLOUT_RHS2);
- } else if (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR) {
- m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_CRAWLOUT_RHS);
+ if (neededTurn > HALFPI) {
+ if (seekPosDist >= 1.0 && neededTurn <= DEGTORAD(135.0f)) {
+ if (seekPosDist < 2.0f)
+ nextMove = PEDMOVE_WALK;
+ } else {
+ nextMove = PEDMOVE_STILL;
}
- m_pVehicleAnim->SetFinishCallback(PedSetOutCarCB, 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);
+ if (((m_nPedState == PED_FLEE_POS || m_nPedState == PED_FLEE_ENTITY) && m_nMoveState < nextMove)
+ || (m_nPedState != PED_FLEE_POS && m_nPedState != PED_FLEE_ENTITY && m_objective != OBJECTIVE_GOTO_CHAR_ON_FOOT && m_nWaitState == WAITSTATE_FALSE)) {
+
+ SetMoveState(nextMove);
}
+
+ SetMoveAnim();
+ return false;
+ }
+
+ if ((m_objective != OBJECTIVE_FOLLOW_CHAR_IN_FORMATION || m_pedInObjective->m_nMoveState == PEDMOVE_STILL) && m_nMoveState != PEDMOVE_STILL) {
+ m_nPedStateTimer = 0;
+ m_actionX = 0;
+ m_actionY = 0;
+ }
+
+ if (m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT || m_objective == OBJECTIVE_RUN_TO_AREA || m_objective == OBJECTIVE_GOTO_AREA_ANY_MEANS) {
+ if (m_pNextPathNode)
+ m_pNextPathNode = nil;
+ else
+ bScriptObjectiveCompleted = true;
+
+ bUsePedNodeSeek = true;
}
+
+ if (SeekFollowingPath(nil))
+ m_nCurPathNode++;
+
+ return true;
}
void
-CPed::ScanForInterestingStuff(void)
+CPed::SetFlee(CVector2D const &from, int time)
{
- if (!IsPedInControl())
+ if (CTimer::GetTimeInMilliseconds() < m_nPedStateTimer || !IsPedInControl() || bKindaStayInSamePlace)
return;
- if (m_objective != OBJECTIVE_NONE)
- return;
+ if (m_nPedState != PED_FLEE_ENTITY) {
+ SetStoredState();
+ m_nPedState = PED_FLEE_POS;
+ SetMoveState(PEDMOVE_RUN);
+ m_fleeFromPosX = from.x;
+ m_fleeFromPosY = from.y;
+ }
- if (CharCreatedBy == MISSION_CHAR)
- return;
+ bUsePedNodeSeek = true;
+ m_pNextPathNode = nil;
+ m_fleeTimer = CTimer::GetTimeInMilliseconds() + time;
- LookForSexyPeds();
- LookForSexyCars();
- if (LookForInterestingNodes())
+ float angleToFace = CGeneral::GetRadianAngleBetweenPoints(
+ GetPosition().x, GetPosition().y,
+ from.x, from.y);
+
+ m_fRotationDest = CGeneral::LimitRadianAngle(angleToFace);
+ if (m_fRotationCur - PI > m_fRotationDest) {
+ m_fRotationDest += 2 * PI;
+ } else if (PI + m_fRotationCur < m_fRotationDest) {
+ m_fRotationDest -= 2 * PI;
+ }
+}
+
+void
+CPed::SetFlee(CEntity *fleeFrom, int time)
+{
+ if (!IsPedInControl() || bKindaStayInSamePlace || !fleeFrom)
return;
- if (m_nPedType == PEDTYPE_CRIMINAL && m_hitRecoverTimer < CTimer::GetTimeInMilliseconds()) {
- if (CGeneral::GetRandomNumber() % 100 < 10) {
- int mostExpensiveVehAround = -1;
- int bestMonetaryValue = 0;
+ SetStoredState();
+ m_nPedState = PED_FLEE_ENTITY;
+ bUsePedNodeSeek = true;
+ SetMoveState(PEDMOVE_RUN);
+ m_fleeFrom = fleeFrom;
+ m_fleeFrom->RegisterReference((CEntity **) &m_fleeFrom);
- CVector pos = GetPosition();
- int16 lastVehicle;
- CEntity *vehicles[8];
- CWorld::FindObjectsInRange(pos, 10.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false);
+ if (time <= 0)
+ m_fleeTimer = 0;
+ else
+ m_fleeTimer = CTimer::GetTimeInMilliseconds() + time;
- for (int i = 0; i < lastVehicle; i++) {
- CVehicle* veh = (CVehicle*)vehicles[i];
+ float angleToFace = CGeneral::GetRadianAngleBetweenPoints(
+ GetPosition().x, GetPosition().y,
+ fleeFrom->GetPosition().x, fleeFrom->GetPosition().y);
- if (veh->VehicleCreatedBy != MISSION_VEHICLE) {
- if (veh->m_vecMoveSpeed.Magnitude() <= 0.1f && veh->IsVehicleNormal()
- && veh->IsCar() && bestMonetaryValue < veh->pHandling->nMonetaryValue) {
- mostExpensiveVehAround = i;
- bestMonetaryValue = veh->pHandling->nMonetaryValue;
- }
- }
+ m_fRotationDest = CGeneral::LimitRadianAngle(angleToFace);
+ if (m_fRotationCur - PI > m_fRotationDest) {
+ m_fRotationDest += 2 * PI;
+ } else if (PI + m_fRotationCur < m_fRotationDest) {
+ m_fRotationDest -= 2 * PI;
+ }
+}
+
+void
+CPed::ClearFlee(void)
+{
+ RestorePreviousState();
+ bUsePedNodeSeek = false;
+ m_standardTimer = 0;
+ m_fleeTimer = 0;
+}
+
+void
+CPed::Flee(void)
+{
+ if (CTimer::GetTimeInMilliseconds() > m_fleeTimer && m_fleeTimer) {
+ bool mayFinishFleeing = true;
+ if (m_nPedState == PED_FLEE_ENTITY) {
+ if ((CVector2D(GetPosition()) - ms_vec2DFleePosition).MagnitudeSqr() < sq(30.0f))
+ mayFinishFleeing = false;
+ }
+
+ if (mayFinishFleeing) {
+ eMoveState moveState = m_nMoveState;
+ ClearFlee();
+
+ if (m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE || m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS)
+ RestorePreviousObjective();
+
+ if ((m_nPedState == PED_IDLE || m_nPedState == PED_WANDER_PATH) && CGeneral::GetRandomNumber() & 1) {
+ SetWaitState(moveState <= PEDMOVE_WALK ? WAITSTATE_CROSS_ROAD_LOOK : WAITSTATE_FINISH_FLEE, nil);
}
- if (bestMonetaryValue > 2000 && mostExpensiveVehAround != -1 && vehicles[mostExpensiveVehAround]) {
- SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, vehicles[mostExpensiveVehAround]);
- m_hitRecoverTimer = CTimer::GetTimeInMilliseconds() + 5000;
- return;
+ return;
+ }
+ m_fleeTimer = CTimer::GetTimeInMilliseconds() + 5000;
+ }
+
+ if (bUsePedNodeSeek) {
+ CPathNode *realLastNode = nil;
+ uint8 nextDirection = 0;
+ uint8 curDirectionShouldBe = 9; // means not defined yet
+
+ if (m_nPedStateTimer < CTimer::GetTimeInMilliseconds()
+ && m_collidingThingTimer < CTimer::GetTimeInMilliseconds()) {
+
+ if (m_pNextPathNode && CTimer::GetTimeInMilliseconds() > m_standardTimer) {
+
+ curDirectionShouldBe = CGeneral::GetNodeHeadingFromVector(GetPosition().x - ms_vec2DFleePosition.x, GetPosition().y - ms_vec2DFleePosition.y);
+ if (m_nPathDir < curDirectionShouldBe)
+ m_nPathDir += 8;
+
+ int dirDiff = m_nPathDir - curDirectionShouldBe;
+ if (dirDiff > 2 && dirDiff < 6) {
+ realLastNode = nil;
+ m_pLastPathNode = m_pNextPathNode;
+ m_pNextPathNode = nil;
+ }
}
- m_hitRecoverTimer = CTimer::GetTimeInMilliseconds() + 5000;
- } else if (m_objective != OBJECTIVE_MUG_CHAR && !(CGeneral::GetRandomNumber() & 7)) {
- CPed *charToMug = nil;
- for (int i = 0; i < m_numNearPeds; ++i) {
- CPed *nearPed = m_nearPeds[i];
- if ((nearPed->GetPosition() - GetPosition()).MagnitudeSqr() > sq(7.0f))
- break;
+ if (m_pNextPathNode) {
+ m_vecSeekPos = m_pNextPathNode->GetPosition();
+ if (m_nMoveState == PEDMOVE_RUN)
+ bIsRunning = true;
- if ((nearPed->m_nPedType == PEDTYPE_CIVFEMALE || nearPed->m_nPedType == PEDTYPE_CIVMALE
- || nearPed->m_nPedType == PEDTYPE_CRIMINAL || nearPed->m_nPedType == PEDTYPE_UNUSED1
- || nearPed->m_nPedType == PEDTYPE_PROSTITUTE)
- && nearPed->CharCreatedBy != MISSION_CHAR
- && nearPed->IsPedShootable()
- && nearPed->m_objective != OBJECTIVE_MUG_CHAR) {
- charToMug = nearPed;
- break;
+ eMoveState moveState = m_nMoveState;
+ if (Seek()) {
+ realLastNode = m_pLastPathNode;
+ m_pLastPathNode = m_pNextPathNode;
+ m_pNextPathNode = nil;
}
+ bIsRunning = false;
+ SetMoveState(moveState);
}
- if (charToMug)
- SetObjective(OBJECTIVE_MUG_CHAR, charToMug);
+ }
- m_hitRecoverTimer = CTimer::GetTimeInMilliseconds() + 5000;
+ if (!m_pNextPathNode) {
+ if (curDirectionShouldBe == 9) {
+ curDirectionShouldBe = CGeneral::GetNodeHeadingFromVector(GetPosition().x - ms_vec2DFleePosition.x, GetPosition().y - ms_vec2DFleePosition.y);
+ }
+ ThePaths.FindNextNodeWandering(PATH_PED, GetPosition(), &m_pLastPathNode, &m_pNextPathNode,
+ curDirectionShouldBe,
+ &nextDirection);
+
+ if (curDirectionShouldBe < nextDirection)
+ curDirectionShouldBe += 8;
+
+ if (m_pNextPathNode && m_pNextPathNode != realLastNode && m_pNextPathNode != m_pLastPathNode && curDirectionShouldBe - nextDirection != 4) {
+ m_nPathDir = nextDirection;
+ m_standardTimer = CTimer::GetTimeInMilliseconds() + 2000;
+ } else {
+ bUsePedNodeSeek = false;
+ SetMoveState(PEDMOVE_RUN);
+ Flee();
+ }
}
+ return;
}
- if (m_nPedState == PED_WANDER_PATH) {
-#ifndef VC_PED_PORTS
- if (CTimer::GetTimeInMilliseconds() > m_standardTimer) {
+ if ((m_nPedState == PED_FLEE_ENTITY || m_nPedState == PED_ON_FIRE) && m_nPedStateTimer < CTimer::GetTimeInMilliseconds()) {
- // += 2 is weird
- for (int i = 0; i < m_numNearPeds; i += 2) {
- if (m_nearPeds[i]->m_nPedState == PED_WANDER_PATH && WillChat(m_nearPeds[i])) {
- if (CGeneral::GetRandomNumberInRange(0, 100) >= 100)
- m_standardTimer = CTimer::GetTimeInMilliseconds() + 30000;
- else {
- if ((GetPosition() - m_nearPeds[i]->GetPosition()).Magnitude() >= 1.8f) {
- m_standardTimer = CTimer::GetTimeInMilliseconds() + 30000;
- } else if (CanSeeEntity(m_nearPeds[i])) {
- int time = CGeneral::GetRandomNumber() % 4000 + 10000;
- SetChat(m_nearPeds[i], time);
- m_nearPeds[i]->SetChat(this, time);
- return;
- }
- }
- }
- }
+ float angleToFleeFromPos = CGeneral::GetRadianAngleBetweenPoints(
+ GetPosition().x,
+ GetPosition().y,
+ ms_vec2DFleePosition.x,
+ ms_vec2DFleePosition.y);
+
+ m_fRotationDest = CGeneral::LimitRadianAngle(angleToFleeFromPos);
+
+ if (m_fRotationCur - PI > m_fRotationDest)
+ m_fRotationDest += TWOPI;
+ else if (PI + m_fRotationCur < m_fRotationDest)
+ m_fRotationDest -= TWOPI;
+ }
+
+ if (CTimer::GetTimeInMilliseconds() & 0x20) {
+ //CVector forwardPos = GetPosition();
+ CMatrix forwardMat(GetMatrix());
+ forwardMat.GetPosition() += Multiply3x3(forwardMat, CVector(0.0f, 4.0f, 0.0f));
+ CVector forwardPos = forwardMat.GetPosition();
+
+ CEntity *foundEnt;
+ CColPoint foundCol;
+ bool found = CWorld::ProcessVerticalLine(forwardPos, forwardMat.GetPosition().z - 100.0f, foundCol, foundEnt, 1, 0, 0, 0, 1, 0, 0);
+
+ if (!found || Abs(forwardPos.z - forwardMat.GetPosition().z) > 1.0f) {
+ m_fRotationDest += DEGTORAD(112.5f);
+ m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 2000;
}
-#else
- if (CGeneral::GetRandomNumberInRange(0.0f, 1.0f) < 0.5f) {
- if (CTimer::GetTimeInMilliseconds() > m_standardTimer) {
- for (int i = 0; i < m_numNearPeds; i ++) {
- if (m_nearPeds[i] && m_nearPeds[i]->m_nPedState == PED_WANDER_PATH) {
- if ((GetPosition() - m_nearPeds[i]->GetPosition()).Magnitude() < 1.8f
- && CanSeeEntity(m_nearPeds[i])
- && m_nearPeds[i]->CanSeeEntity(this)
- && WillChat(m_nearPeds[i])) {
+ }
- int time = CGeneral::GetRandomNumber() % 4000 + 10000;
- SetChat(m_nearPeds[i], time);
- m_nearPeds[i]->SetChat(this, time);
- return;
- }
- }
+ if (CTimer::GetTimeInMilliseconds() >= m_collidingThingTimer)
+ return;
+
+ if (!m_collidingEntityWhileFleeing)
+ return;
+
+ double collidingThingPriorityMult = (double)(m_collidingThingTimer - CTimer::GetTimeInMilliseconds()) * 2.0 / 2500;
+
+ if (collidingThingPriorityMult <= 1.5) {
+
+ double angleToFleeEntity = CGeneral::GetRadianAngleBetweenPoints(
+ GetPosition().x,
+ GetPosition().y,
+ m_collidingEntityWhileFleeing->GetPosition().x,
+ m_collidingEntityWhileFleeing->GetPosition().y);
+ angleToFleeEntity = CGeneral::LimitRadianAngle(angleToFleeEntity);
+
+ double angleToFleeCollidingThing = CGeneral::GetRadianAngleBetweenPoints(
+ m_vecDamageNormal.x,
+ m_vecDamageNormal.y,
+ 0.0f,
+ 0.0f);
+ angleToFleeCollidingThing = CGeneral::LimitRadianAngle(angleToFleeCollidingThing);
+
+ if (angleToFleeEntity - PI > angleToFleeCollidingThing)
+ angleToFleeCollidingThing += TWOPI;
+ else if (PI + angleToFleeEntity < angleToFleeCollidingThing)
+ angleToFleeCollidingThing -= TWOPI;
+
+ if (collidingThingPriorityMult <= 1.0f) {
+ // Range [0.0, 1.0]
+
+ float angleToFleeBoth = (angleToFleeCollidingThing + angleToFleeEntity) * 0.5f;
+
+ if (m_fRotationDest - PI > angleToFleeBoth)
+ angleToFleeBoth += TWOPI;
+ else if (PI + m_fRotationDest < angleToFleeBoth)
+ angleToFleeBoth -= TWOPI;
+
+ m_fRotationDest = (1.0f - collidingThingPriorityMult) * m_fRotationDest + collidingThingPriorityMult * angleToFleeBoth;
+ } else {
+ // Range (1.0, 1.5]
+
+ double adjustedMult = (collidingThingPriorityMult - 1.0f) * 2.0f;
+ m_fRotationDest = angleToFleeEntity * (1.0 - adjustedMult) + adjustedMult * angleToFleeCollidingThing;
+ }
+ } else {
+ m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(
+ m_vecDamageNormal.x,
+ m_vecDamageNormal.y,
+ 0.0f,
+ 0.0f);
+ m_fRotationDest = CGeneral::LimitRadianAngle(m_fRotationDest);
+ }
+
+ m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur);
+
+ if (m_fRotationCur - PI > m_fRotationDest)
+ m_fRotationDest += TWOPI;
+ else if (PI + m_fRotationCur < m_fRotationDest)
+ m_fRotationDest -= TWOPI;
+
+}
+
+// "Wander range" state is unused in game, and you can't use it without SetWanderRange anyway
+void
+CPed::WanderRange(void)
+{
+ bool arrived = Seek();
+ if (arrived) {
+ Idle();
+ if ((m_randomSeed + 3 * CTimer::GetFrameCounter()) % 1000 > 997) {
+ CVector2D newCoords2D = m_wanderRangeBounds->GetRandomPointInRange();
+ SetSeek(CVector(newCoords2D.x, newCoords2D.y, GetPosition().z), 2.5f);
+ }
+ }
+}
+
+bool
+CPed::SetWanderPath(int8 pathStateDest)
+{
+ uint8 nextPathState;
+
+ if (IsPedInControl()) {
+ if (bKindaStayInSamePlace) {
+ SetIdle();
+ return false;
+ } else {
+ m_nPathDir = pathStateDest;
+ if (pathStateDest == 0)
+ pathStateDest = CGeneral::GetRandomNumberInRange(1, 7);
+
+ ThePaths.FindNextNodeWandering(PATH_PED, GetPosition(), &m_pLastPathNode, &m_pNextPathNode,
+ m_nPathDir, &nextPathState);
+
+ // Circular loop until we find a node for current m_nPathDir
+ while (!m_pNextPathNode) {
+ m_nPathDir = (m_nPathDir+1) % 8;
+
+ // We're at where we started and couldn't find any node
+ if (m_nPathDir == pathStateDest) {
+ ClearAll();
+ SetIdle();
+ return false;
}
+ ThePaths.FindNextNodeWandering(PATH_PED, GetPosition(), &m_pLastPathNode, &m_pNextPathNode,
+ m_nPathDir, &nextPathState);
}
- } else {
- m_standardTimer = CTimer::GetTimeInMilliseconds() + 200;
+
+ // We did it, save next path state and return true
+ m_nPathDir = nextPathState;
+ m_nPedState = PED_WANDER_PATH;
+ SetMoveState(PEDMOVE_WALK);
+ bIsRunning = false;
+ return true;
}
-#endif
+ } else {
+ m_nPathDir = pathStateDest;
+ bStartWanderPathOnFoot = true;
+ return false;
}
+}
- // Parts below aren't there in VC, they're in somewhere else.
- if (!CGame::noProstitutes && m_nPedType == PEDTYPE_PROSTITUTE && CharCreatedBy != MISSION_CHAR
- && m_objectiveTimer < CTimer::GetTimeInMilliseconds() && !CTheScripts::IsPlayerOnAMission()) {
+void
+CPed::WanderPath(void)
+{
+ if (!m_pNextPathNode) {
+ printf("THIS SHOULDN@T HAPPEN TOO OFTEN\n");
+ SetIdle();
+ return;
+ }
+ if (m_nWaitState == WAITSTATE_FALSE) {
+ if (m_nMoveState == PEDMOVE_STILL || m_nMoveState == PEDMOVE_NONE)
+ SetMoveState(PEDMOVE_WALK);
+ }
+ m_vecSeekPos = m_pNextPathNode->GetPosition();
+ m_vecSeekPos.z += 1.0f;
- CVector pos = GetPosition();
- int16 lastVehicle;
- CEntity* vehicles[8];
- CWorld::FindObjectsInRange(pos, CHECK_NEARBY_THINGS_MAX_DIST, true, &lastVehicle, 6, vehicles, false, true, false, false, false);
+ // Only returns true when ped is stuck(not stopped) I think, then we should assign new direction or wait state to him.
+ if (!Seek())
+ return;
- for (int i = 0; i < lastVehicle; i++) {
- CVehicle* veh = (CVehicle*)vehicles[i];
+ CPathNode *previousLastNode = m_pLastPathNode;
+ uint8 randVal = (m_randomSeed + 3 * CTimer::GetFrameCounter()) % 100;
- if (veh->IsVehicleNormal()) {
- if (veh->IsCar()) {
- if ((GetPosition() - veh->GetPosition()).Magnitude() < 5.0f && veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, nil)) {
- SetObjective(OBJECTIVE_SOLICIT_VEHICLE, veh);
- Say(SOUND_PED_SOLICIT);
- return;
- }
+ // We don't prefer 180-degree turns in normal situations
+ uint8 dirWeWouldntPrefer = m_nPathDir;
+ if (dirWeWouldntPrefer <= 3)
+ dirWeWouldntPrefer += 4;
+ else
+ dirWeWouldntPrefer -= 4;
+
+ CPathNode *nodeWeWouldntPrefer = nil;
+ uint8 dirToSet = 9; // means undefined
+ uint8 dirWeWouldntPrefer2 = 9; // means undefined
+ if (randVal <= 90) {
+ if (randVal > 80) {
+ m_nPathDir += 2;
+ m_nPathDir %= 8;
+ }
+ } else {
+ m_nPathDir -= 2;
+ if (m_nPathDir < 0)
+ m_nPathDir += 8;
+ }
+
+ m_pLastPathNode = m_pNextPathNode;
+ ThePaths.FindNextNodeWandering(PATH_PED, GetPosition(), &m_pLastPathNode, &m_pNextPathNode,
+ m_nPathDir, &dirToSet);
+
+ uint8 tryCount = 0;
+
+ // NB: SetWanderPath checks for m_nPathDir == dirToStartWith, this one checks for tryCount > 7
+ while (!m_pNextPathNode) {
+ tryCount++;
+ m_nPathDir = (m_nPathDir + 1) % 8;
+
+ // We're at where we started and couldn't find any node
+ if (tryCount > 7) {
+ if (!nodeWeWouldntPrefer) {
+ ClearAll();
+ SetIdle();
+ // Probably this text carried over here after copy-pasting this loop from early version of SetWanderPath.
+ Error("Can't find valid path node, SetWanderPath, Ped.cpp");
+ return;
+ }
+ m_pNextPathNode = nodeWeWouldntPrefer;
+ dirToSet = dirWeWouldntPrefer2;
+ } else {
+ ThePaths.FindNextNodeWandering(PATH_PED, GetPosition(), &m_pLastPathNode, &m_pNextPathNode,
+ m_nPathDir, &dirToSet);
+ if (m_pNextPathNode) {
+ if (dirToSet == dirWeWouldntPrefer) {
+ nodeWeWouldntPrefer = m_pNextPathNode;
+ dirWeWouldntPrefer2 = dirToSet;
+ m_pNextPathNode = nil;
}
}
}
}
- if (m_nPedType == PEDTYPE_CIVMALE || m_nPedType == PEDTYPE_CIVFEMALE) {
- CVector pos = GetPosition();
- int16 lastVehicle;
- CEntity* vehicles[8];
- 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];
+ m_nPathDir = dirToSet;
+ if (m_pLastPathNode == m_pNextPathNode) {
+ m_pNextPathNode = previousLastNode;
+ SetWaitState(WAITSTATE_DOUBLEBACK, nil);
+ Say(SOUND_PED_WAIT_DOUBLEBACK);
+ } else if (ThePaths.TestForPedTrafficLight(m_pLastPathNode, m_pNextPathNode)) {
+ SetWaitState(WAITSTATE_TRAFFIC_LIGHTS, nil);
+ } else if (ThePaths.TestCrossesRoad(m_pLastPathNode, m_pNextPathNode)) {
+ SetWaitState(WAITSTATE_CROSS_ROAD, nil);
+ } else if (m_pNextPathNode == previousLastNode) {
+ SetWaitState(WAITSTATE_DOUBLEBACK, nil);
+ Say(SOUND_PED_WAIT_DOUBLEBACK);
+ }
+}
- if (veh->GetModelIndex() == MI_MRWHOOP) {
- if (veh->GetStatus() != STATUS_ABANDONED && veh->GetStatus() != STATUS_WRECKED) {
- if ((GetPosition() - veh->GetPosition()).Magnitude() < 5.0f) {
- SetObjective(OBJECTIVE_BUY_ICE_CREAM, veh);
- return;
+void
+CPed::Avoid(void)
+{
+ CPed *nearestPed;
+
+ if(m_pedStats->m_temper > m_pedStats->m_fear && m_pedStats->m_temper > 50)
+ return;
+
+ if (CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) {
+
+ if (m_nMoveState != PEDMOVE_NONE && m_nMoveState != PEDMOVE_STILL) {
+ nearestPed = m_nearPeds[0];
+
+ if (nearestPed && nearestPed->m_nPedState != PED_DEAD && nearestPed != m_pSeekTarget && nearestPed != m_pedInObjective) {
+
+ // Check if this ped wants to avoid the nearest one
+ if (CPedType::GetAvoid(m_nPedType) & CPedType::GetFlag(nearestPed->m_nPedType)) {
+
+ // Further codes checks whether the distance between us and ped will be equal or below 1.0, if we walk up to him by 1.25 meters.
+ // If so, we want to avoid it, so we turn our body 45 degree and look to somewhere else.
+
+ // Game converts from radians to degress and back again here, doesn't make much sense
+ CVector2D forward(-Sin(m_fRotationCur), Cos(m_fRotationCur));
+ forward.Normalise(); // this is kinda pointless
+
+ // Move forward 1.25 meters
+ CVector2D testPosition = CVector2D(GetPosition()) + forward*1.25f;
+
+ // Get distance to ped we want to avoid
+ CVector2D distToPed = CVector2D(nearestPed->GetPosition()) - testPosition;
+
+ if (distToPed.Magnitude() <= 1.0f && OurPedCanSeeThisOne((CEntity*)nearestPed)) {
+ m_nPedStateTimer = CTimer::GetTimeInMilliseconds()
+ + 500 + (m_randomSeed + 3 * CTimer::GetFrameCounter())
+ % 1000 / 5;
+
+ m_fRotationDest += DEGTORAD(45.0f);
+ if (!bIsLooking) {
+ SetLookFlag(nearestPed, false);
+ SetLookTimer(CGeneral::GetRandomNumberInRange(500, 800));
+ }
}
}
}
@@ -15630,183 +6015,651 @@ CPed::ScanForInterestingStuff(void)
}
}
-uint32
-CPed::ScanForThreats(void)
+bool
+CPed::SeekFollowingPath(CVector *unused)
{
- int fearFlags = m_fearFlags;
- CVector ourPos = GetPosition();
- float closestPedDist = 60.0f;
- CVector2D explosionPos = GetPosition();
- if (fearFlags & PED_FLAG_EXPLOSION && CheckForExplosions(explosionPos)) {
- m_eventOrThreat = explosionPos;
- return PED_FLAG_EXPLOSION;
+ return m_nCurPathNode <= m_nPathNodes && m_nPathNodes;
+}
+
+bool
+CPed::SetFollowPath(CVector dest)
+{
+ if (m_nPedState == PED_FOLLOW_PATH)
+ return false;
+
+ if (FindPlayerPed() != this)
+ return false;
+
+ if ((dest - GetPosition()).Magnitude() <= 2.0f)
+ return false;
+
+ CVector pointPoses[7];
+ int16 pointsFound;
+ CPedPath::CalcPedRoute(0, GetPosition(), dest, pointPoses, &pointsFound, 7);
+ for(int i = 0; i < pointsFound; i++) {
+ m_stPathNodeStates[i].x = pointPoses[i].x;
+ m_stPathNodeStates[i].y = pointPoses[i].y;
}
+
+ m_nCurPathNode = 0;
+ m_nPathNodes = pointsFound;
+ if (m_nPathNodes < 1)
+ return false;
+
+ SetStoredState();
+ m_nPedState = PED_FOLLOW_PATH;
+ SetMoveState(PEDMOVE_WALK);
+ return true;
+}
+
+void
+CPed::FollowPath(void)
+{
+ m_vecSeekPos.x = m_stPathNodeStates[m_nCurPathNode].x;
+ m_vecSeekPos.y = m_stPathNodeStates[m_nCurPathNode].y;
+ m_vecSeekPos.z = GetPosition().z;
- CPed *shooter = nil;
- if ((fearFlags & PED_FLAG_GUN) && (shooter = CheckForGunShots()) && (m_nPedType != shooter->m_nPedType || m_nPedType == PEDTYPE_CIVMALE || m_nPedType == PEDTYPE_CIVFEMALE)) {
- if (!IsGangMember()) {
- m_threatEntity = shooter;
- m_threatEntity->RegisterReference((CEntity **) &m_threatEntity);
- return PED_FLAG_GUN;
+ // Mysterious code
+/* int v4 = 0;
+ int maxNodeIndex = m_nPathNodes - 1;
+ if (maxNodeIndex > 0) {
+ if (maxNodeIndex > 8) {
+ while (v4 < maxNodeIndex - 8)
+ v4 += 8;
}
- if (CPedType::GetFlag(shooter->m_nPedType) & fearFlags) {
- m_threatEntity = shooter;
- m_threatEntity->RegisterReference((CEntity **) &m_threatEntity);
- return CPedType::GetFlag(shooter->m_nPedType);
+ while (v4 < maxNodeIndex)
+ v4++;
+
+ }
+*/
+ if (Seek()) {
+ m_nCurPathNode++;
+ if (m_nCurPathNode == m_nPathNodes)
+ RestorePreviousState();
+ }
+}
+
+void
+CPed::SetEvasiveStep(CEntity *reason, uint8 animType)
+{
+ AnimationId stepAnim;
+
+ if (m_nPedState == PED_STEP_AWAY || !IsPedInControl() || ((IsPlayer() || !bRespondsToThreats) && animType == 0))
+ return;
+
+ float angleToFace = CGeneral::GetRadianAngleBetweenPoints(
+ reason->GetPosition().x, reason->GetPosition().y,
+ GetPosition().x, GetPosition().y);
+ angleToFace = CGeneral::LimitRadianAngle(angleToFace);
+ m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur);
+ float neededTurn = Abs(angleToFace - m_fRotationCur);
+ bool vehPressedHorn = false;
+
+ if (neededTurn > PI)
+ neededTurn = TWOPI - neededTurn;
+
+ CVehicle *veh = (CVehicle*)reason;
+ if (reason->IsVehicle() && veh->m_vehType == VEHICLE_TYPE_CAR) {
+ if (veh->m_nCarHornTimer != 0) {
+ vehPressedHorn = true;
+ if (!IsPlayer())
+ animType = 1;
}
}
+ if (neededTurn <= DEGTORAD(90.0f) || veh->GetModelIndex() == MI_RCBANDIT || vehPressedHorn || animType != 0) {
+ SetLookFlag(veh, true);
+ if ((CGeneral::GetRandomNumber() & 1) && veh->GetModelIndex() != MI_RCBANDIT && animType == 0) {
+ stepAnim = ANIM_IDLE_TAXI;
+ } else {
- CPed *deadPed = nil;
- if (fearFlags & PED_FLAG_DEADPEDS && CharCreatedBy != MISSION_CHAR
- && (deadPed = CheckForDeadPeds()) != nil && (deadPed->GetPosition() - ourPos).MagnitudeSqr() < sq(20.0f)) {
- m_pEventEntity = deadPed;
- m_pEventEntity->RegisterReference((CEntity **) &m_pEventEntity);
- return PED_FLAG_DEADPEDS;
- } else {
- uint32 flagsOfSomePed = 0;
+ float vehDirection = CGeneral::GetRadianAngleBetweenPoints(
+ veh->m_vecMoveSpeed.x, veh->m_vecMoveSpeed.y,
+ 0.0f, 0.0f);
- CPed *pedToFearFrom = nil;
-#ifndef VC_PED_PORTS
- for (int i = 0; i < m_numNearPeds; i++) {
- if (CharCreatedBy != RANDOM_CHAR || m_nearPeds[i]->CharCreatedBy != MISSION_CHAR || m_nearPeds[i]->IsPlayer()) {
- CPed *nearPed = m_nearPeds[i];
+ // Let's turn our back to the "reason"
+ angleToFace += PI;
- // BUG: WTF Rockstar?! Putting this here will result in returning the flags of farthest ped to us, since m_nearPeds is sorted by distance.
- // Fixed at the bottom of the function.
- flagsOfSomePed = CPedType::GetFlag(nearPed->m_nPedType);
+ if (angleToFace > PI)
+ angleToFace -= TWOPI;
- if (CPedType::GetFlag(nearPed->m_nPedType) & fearFlags) {
- if (nearPed->m_fHealth > 0.0f && OurPedCanSeeThisOne(m_nearPeds[i])) {
- // FIX: Taken from VC
+ // We don't want to run towards car's direction
+ float dangerZone = angleToFace - vehDirection;
+ dangerZone = CGeneral::LimitRadianAngle(dangerZone);
+
+ // So, add or subtract 90deg (jump to left/right) according to that
+ if (dangerZone > 0.0f)
+ angleToFace = vehDirection - HALFPI;
+ else
+ angleToFace = vehDirection + HALFPI;
+
+ stepAnim = NUM_ANIMS;
+ if (animType == 0 || animType == 1)
+ stepAnim = ANIM_EV_STEP;
+ else if (animType == 2)
+ stepAnim = ANIM_HANDSCOWER;
+ }
+ if (!RpAnimBlendClumpGetAssociation(GetClump(), stepAnim)) {
+ CAnimBlendAssociation *stepAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, stepAnim, 8.0f);
+ stepAssoc->flags &= ~ASSOC_DELETEFADEDOUT;
+ stepAssoc->SetFinishCallback(PedEvadeCB, this);
+
+ if (animType == 0)
+ Say(SOUND_PED_EVADE);
+
+ m_fRotationCur = CGeneral::LimitRadianAngle(angleToFace);
+ ClearAimFlag();
+ SetStoredState();
+ m_nPedState = PED_STEP_AWAY;
+ }
+ }
+}
+
+void
+CPed::SetEvasiveDive(CPhysical *reason, uint8 onlyRandomJump)
+{
+ if (!IsPedInControl() || !bRespondsToThreats)
+ return;
+
+ CAnimBlendAssociation *animAssoc;
+ float angleToFace, neededTurn;
+ bool handsUp = false;
+
+ angleToFace = m_fRotationCur;
+ CVehicle *veh = (CVehicle*) reason;
+ if (reason->IsVehicle() && veh->m_vehType == VEHICLE_TYPE_CAR && veh->m_nCarHornTimer != 0 && !IsPlayer()) {
+ onlyRandomJump = true;
+ }
+
+ if (onlyRandomJump) {
+ if (reason) {
+ // Simple version of my bug fix below. Doesn't calculate "danger zone", selects jump direction randomly.
+ // Also doesn't include random hands up, sound etc. Only used on player ped and peds running from gun shots.
+
+ float vehDirection = CGeneral::GetRadianAngleBetweenPoints(
+ veh->m_vecMoveSpeed.x, veh->m_vecMoveSpeed.y,
+ 0.0f, 0.0f);
+ angleToFace = (CGeneral::GetRandomNumber() & 1) * PI + (-0.5f*PI) + vehDirection;
+ angleToFace = CGeneral::LimitRadianAngle(angleToFace);
+ }
+ } else {
+ if (IsPlayer()) {
+ ((CPlayerPed*)this)->m_nEvadeAmount = 5;
+ ((CPlayerPed*)this)->m_pEvadingFrom = reason;
+ reason->RegisterReference((CEntity**) &((CPlayerPed*)this)->m_pEvadingFrom);
+ return;
+ }
+
+ angleToFace = CGeneral::GetRadianAngleBetweenPoints(
+ reason->GetPosition().x, reason->GetPosition().y,
+ GetPosition().x, GetPosition().y);
+ angleToFace = CGeneral::LimitRadianAngle(angleToFace);
+ m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur);
+
+ // FIX: Peds no more dive into cars. Taken from SetEvasiveStep, last if statement inverted
#ifdef FIX_BUGS
- float nearPedDistSqr = (nearPed->GetPosition() - ourPos).MagnitudeSqr2D();
-#else
- float nearPedDistSqr = (CVector2D(ourPos) - explosionPos).MagnitudeSqr();
+ float vehDirection = CGeneral::GetRadianAngleBetweenPoints(
+ veh->m_vecMoveSpeed.x, veh->m_vecMoveSpeed.y,
+ 0.0f, 0.0f);
+
+ // Let's turn our back to the "reason"
+ angleToFace += PI;
+
+ if (angleToFace > PI)
+ angleToFace -= 2 * PI;
+
+ // We don't want to dive towards car's direction
+ float dangerZone = angleToFace - vehDirection;
+ dangerZone = CGeneral::LimitRadianAngle(dangerZone);
+
+ // So, add or subtract 90deg (jump to left/right) according to that
+ if (dangerZone > 0.0f)
+ angleToFace = 0.5f * PI + vehDirection;
+ else
+ angleToFace = vehDirection - 0.5f * PI;
#endif
- if (sq(closestPedDist) > nearPedDistSqr) {
- closestPedDist = Sqrt(nearPedDistSqr);
- pedToFearFrom = m_nearPeds[i];
- }
- }
- }
- }
+
+ neededTurn = Abs(angleToFace - m_fRotationCur);
+
+ if (neededTurn > PI)
+ neededTurn = 2 * PI - neededTurn;
+
+ if (neededTurn <= 0.5f*PI) {
+ if (CGeneral::GetRandomNumber() & 1)
+ handsUp = true;
+ } else {
+ if (CGeneral::GetRandomNumber() & 7)
+ return;
}
-#else
- bool weSawOurEnemy = false;
- bool weMaySeeOurEnemy = false;
- float closestEnemyDist = 60.0f;
- if ((CTimer::GetFrameCounter() + (uint8)m_randomSeed + 16) & 4) {
+ Say(SOUND_PED_EVADE);
+ }
- for (int i = 0; i < m_numNearPeds; ++i) {
- if (CharCreatedBy == RANDOM_CHAR && m_nearPeds[i]->CharCreatedBy == MISSION_CHAR && !m_nearPeds[i]->IsPlayer()) {
- continue;
- }
+ if (handsUp || !IsPlayer() && m_pedStats->m_flags & STAT_NO_DIVE) {
+ m_fRotationCur = angleToFace;
+ ClearLookFlag();
+ ClearAimFlag();
+ SetLookFlag(reason, true);
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_HANDSUP);
+ if (animAssoc)
+ return;
- // BUG: Explained at the same occurence of this bug above. Fixed at the bottom of the function.
- flagsOfSomePed = CPedType::GetFlag(m_nearPeds[i]->m_nPedType);
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_HANDSUP, 8.0f);
+ animAssoc->flags &= ~ASSOC_DELETEFADEDOUT;
+ animAssoc->SetFinishCallback(PedEvadeCB, this);
+ SetStoredState();
+ m_nPedState = PED_STEP_AWAY;
+ } else {
+ m_fRotationCur = angleToFace;
+ ClearLookFlag();
+ ClearAimFlag();
+ SetStoredState();
+ m_nPedState = PED_DIVE_AWAY;
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_EV_DIVE, 8.0f);
+ animAssoc->SetFinishCallback(PedEvadeCB, this);
+ }
- if (flagsOfSomePed & fearFlags) {
- if (m_nearPeds[i]->m_fHealth > 0.0f) {
+ if (reason->IsVehicle() && m_nPedType == PEDTYPE_COP) {
+ if (veh->pDriver && veh->pDriver->IsPlayer()) {
+ CWanted *wanted = FindPlayerPed()->m_pWanted;
+ wanted->RegisterCrime_Immediately(CRIME_RECKLESS_DRIVING, GetPosition(), (uintptr)this, false);
+ wanted->RegisterCrime_Immediately(CRIME_SPEEDING, GetPosition(), (uintptr)this, false);
+ }
+ }
+#ifdef PEDS_REPORT_CRIMES_ON_PHONE
+ else if (reason->IsVehicle()) {
+ if (veh->pDriver && veh->pDriver->IsPlayer()) {
+ CWanted* wanted = FindPlayerPed()->m_pWanted;
+ wanted->RegisterCrime(CRIME_RECKLESS_DRIVING, GetPosition(), (uintptr)this, false);
+ }
+ }
+#endif
+}
- // VC also has ability to include objects to line of sight check here (via last bit of flagsL)
- if (OurPedCanSeeThisOne(m_nearPeds[i])) {
- if (m_nearPeds[i]->m_nPedState == PED_ATTACK) {
- if (m_nearPeds[i]->m_pedInObjective == this) {
+void
+CPed::PedEvadeCB(CAnimBlendAssociation* animAssoc, void* arg)
+{
+ CPed* ped = (CPed*)arg;
- float enemyDistSqr = (m_nearPeds[i]->GetPosition() - ourPos).MagnitudeSqr2D();
- if (sq(closestEnemyDist) > enemyDistSqr) {
- float enemyDist = Sqrt(enemyDistSqr);
- weSawOurEnemy = true;
- closestPedDist = enemyDist;
- closestEnemyDist = enemyDist;
- pedToFearFrom = m_nearPeds[i];
- }
- }
- } else {
- float nearPedDistSqr = (m_nearPeds[i]->GetPosition() - ourPos).MagnitudeSqr2D();
- if (sq(closestPedDist) > nearPedDistSqr && !weSawOurEnemy) {
- closestPedDist = Sqrt(nearPedDistSqr);
- pedToFearFrom = m_nearPeds[i];
- }
- }
- } else if (!weSawOurEnemy) {
- CPed *nearPed = m_nearPeds[i];
- if (nearPed->m_nPedState == PED_ATTACK) {
- CColPoint foundCol;
- CEntity *foundEnt;
+ if (!animAssoc) {
+ ped->ClearLookFlag();
+ if (ped->m_nPedState == PED_DIVE_AWAY || ped->m_nPedState == PED_STEP_AWAY)
+ ped->RestorePreviousState();
+
+ } else if (animAssoc->animId == ANIM_EV_DIVE) {
+ ped->bUpdateAnimHeading = true;
+ ped->ClearLookFlag();
+ if (ped->m_nPedState == PED_DIVE_AWAY)
+ {
+ ped->m_getUpTimer = CTimer::GetTimeInMilliseconds() + 1;
+ ped->m_nPedState = PED_FALL;
+ }
+ animAssoc->flags &= ~ASSOC_FADEOUTWHENDONE;
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- // We don't see him yet but he's behind a ped, vehicle or object
- // VC also has ability to include objects to line of sight check here (via last bit of flagsL)
- if (!CWorld::ProcessLineOfSight(ourPos, nearPed->GetPosition(), foundCol, foundEnt,
- true, false, false, false, false, false, false)) {
+ } else if (animAssoc->flags & ASSOC_FADEOUTWHENDONE) {
+ ped->ClearLookFlag();
+ if (ped->m_nPedState == PED_DIVE_AWAY || ped->m_nPedState == PED_STEP_AWAY)
+ ped->RestorePreviousState();
- if (nearPed->m_pedInObjective == this) {
- float enemyDistSqr = (m_nearPeds[i]->GetPosition() - ourPos).MagnitudeSqr2D();
- if (sq(closestEnemyDist) > enemyDistSqr) {
- float enemyDist = Sqrt(enemyDistSqr);
- weMaySeeOurEnemy = true;
- closestPedDist = enemyDist;
- closestEnemyDist = enemyDist;
- pedToFearFrom = m_nearPeds[i];
- }
- } else if (!nearPed->GetWeapon()->IsTypeMelee() && !weMaySeeOurEnemy) {
- float nearPedDistSqr = (m_nearPeds[i]->GetPosition() - ourPos).MagnitudeSqr2D();
- if (sq(closestPedDist) > nearPedDistSqr) {
- weMaySeeOurEnemy = true;
- closestPedDist = Sqrt(nearPedDistSqr);
- pedToFearFrom = m_nearPeds[i];
- }
- }
- }
- }
- }
- }
- }
+ } else if (ped->m_nPedState != PED_ARRESTED) {
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ if (animAssoc->blendDelta >= 0.0f)
+ animAssoc->blendDelta = -4.0f;
+
+ ped->ClearLookFlag();
+ if (ped->m_nPedState == PED_DIVE_AWAY || ped->m_nPedState == PED_STEP_AWAY) {
+ ped->RestorePreviousState();
+ }
+ }
+}
+
+void
+CPed::SetDie(AnimationId animId, float delta, float speed)
+{
+ CPlayerPed *player = FindPlayerPed();
+ if (player == this) {
+ if (!player->m_bCanBeDamaged)
+ return;
+ }
+
+ m_threatEntity = nil;
+ if (DyingOrDead())
+ return;
+
+ if (m_nPedState == PED_FALL || m_nPedState == PED_GETUP)
+ delta *= 0.5f;
+
+ SetStoredState();
+ ClearAll();
+ m_fHealth = 0.0f;
+ if (m_nPedState == PED_DRIVING) {
+ if (!IsPlayer())
+ FlagToDestroyWhenNextProcessed();
+ } else if (bInVehicle) {
+ if (m_pVehicleAnim)
+ m_pVehicleAnim->blendDelta = -1000.0f;
+ } else if (EnteringCar()) {
+ QuitEnteringCar();
+ }
+
+ m_nPedState = PED_DIE;
+ if (animId == NUM_ANIMS) {
+ bIsPedDieAnimPlaying = false;
+ } else {
+ CAnimBlendAssociation *dieAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animId, delta);
+ if (speed > 0.0f)
+ dieAssoc->speed = speed;
+
+ dieAssoc->flags &= ~ASSOC_FADEOUTWHENDONE;
+ if (dieAssoc->IsRunning()) {
+ dieAssoc->SetFinishCallback(FinishDieAnimCB, this);
+ bIsPedDieAnimPlaying = true;
+ }
+ }
+
+ Say(SOUND_PED_DEATH);
+ if (m_nLastPedState == PED_ENTER_CAR || m_nLastPedState == PED_CARJACK)
+ QuitEnteringCar();
+ if (!bInVehicle)
+ StopNonPartialAnims();
+
+ m_bloodyFootprintCountOrDeathTime = CTimer::GetTimeInMilliseconds();
+}
+
+void
+CPed::FinishDieAnimCB(CAnimBlendAssociation *animAssoc, void *arg)
+{
+ CPed *ped = (CPed*)arg;
+
+ if (ped->bIsPedDieAnimPlaying)
+ ped->bIsPedDieAnimPlaying = false;
+}
+
+void
+CPed::SetDead(void)
+{
+ bUsesCollision = false;
+
+ m_fHealth = 0.0f;
+ if (m_nPedState == PED_DRIVING)
+ bIsVisible = false;
+
+ m_nPedState = PED_DEAD;
+ m_pVehicleAnim = nil;
+ m_pCollidingEntity = nil;
+
+ CWeaponInfo *weapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
+ RemoveWeaponModel(weapon->m_nModelId);
+
+ m_currentWeapon = WEAPONTYPE_UNARMED;
+ CEventList::RegisterEvent(EVENT_INJURED_PED, EVENT_ENTITY_PED, this, nil, 250);
+ if (this != FindPlayerPed()) {
+ CreateDeadPedWeaponPickups();
+ CreateDeadPedMoney();
+ }
+
+ m_bloodyFootprintCountOrDeathTime = CTimer::GetTimeInMilliseconds();
+ m_deadBleeding = false;
+ bDoBloodyFootprints = false;
+ bVehExitWillBeInstant = false;
+ CEventList::RegisterEvent(EVENT_DEAD_PED, EVENT_ENTITY_PED, this, nil, 1000);
+}
+
+void
+CPed::Die(void)
+{
+ // UNUSED: This is a perfectly empty function.
+}
+
+void
+CPed::SetChat(CEntity *chatWith, uint32 time)
+{
+ if(m_nPedState != PED_CHAT)
+ SetStoredState();
+
+ m_nPedState = PED_CHAT;
+ SetMoveState(PEDMOVE_STILL);
+#if defined VC_PED_PORTS || defined FIX_BUGS
+ m_lookTimer = 0;
+#endif
+ SetLookFlag(chatWith, true);
+ m_standardTimer = CTimer::GetTimeInMilliseconds() + time;
+ m_lookTimer = CTimer::GetTimeInMilliseconds() + 3000;
+}
+
+void
+CPed::Chat(void)
+{
+ // We're already looking to our partner
+ if (bIsLooking && TurnBody())
+ ClearLookFlag();
+
+ if (!m_pLookTarget || !m_pLookTarget->IsPed()) {
+ ClearChat();
+ return;
+ }
+
+ CPed *partner = (CPed*) m_pLookTarget;
+
+ if (partner->m_nPedState != PED_CHAT) {
+ ClearChat();
+ if (partner->m_pedInObjective) {
+ if (partner->m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT ||
+ partner->m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE)
+ ReactToAttack(partner->m_pedInObjective);
+ }
+ return;
+ }
+ if (bIsTalking) {
+ if (CGeneral::GetRandomNumber() < 512) {
+ CAnimBlendAssociation *chatAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_CHAT);
+ if (chatAssoc) {
+ chatAssoc->blendDelta = -4.0f;
+ chatAssoc->flags |= ASSOC_DELETEFADEDOUT;
}
+ bIsTalking = false;
+ } else
+ Say(SOUND_PED_CHAT);
+
+ } else {
+
+ if (CGeneral::GetRandomNumber() < 20 && !RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_IDLE)) {
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_XPRESS_SCRATCH, 4.0f);
+ }
+ if (!bIsTalking && !RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_IDLE)) {
+ CAnimBlendAssociation *chatAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_CHAT, 4.0f);
+ float chatTime = CGeneral::GetRandomNumberInRange(0.0f, 3.0f);
+ chatAssoc->SetCurrentTime(chatTime);
+
+ bIsTalking = true;
+ Say(SOUND_PED_CHAT);
}
+ }
+ if (m_standardTimer && CTimer::GetTimeInMilliseconds() > m_standardTimer) {
+ ClearChat();
+ m_standardTimer = CTimer::GetTimeInMilliseconds() + 30000;
+ }
+}
+
+void
+CPed::ClearChat(void)
+{
+ CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_CHAT);
+ if (animAssoc) {
+ animAssoc->blendDelta = -8.0f;
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ }
+ bIsTalking = false;
+ ClearLookFlag();
+ RestorePreviousState();
+}
+
+#ifdef PEDS_REPORT_CRIMES_ON_PHONE
+void
+ReportPhonePickUpCB(CAnimBlendAssociation* assoc, void* arg)
+{
+ CPed* ped = (CPed*)arg;
+ ped->m_nMoveState = PEDMOVE_STILL;
+ CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_IDLE_STANCE, 8.0f);
+
+ if (assoc->blendAmount > 0.5f && ped) {
+ CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_PHONE_TALK, 8.0f);
+ }
+}
+
+void
+ReportPhonePutDownCB(CAnimBlendAssociation* assoc, void* arg)
+{
+ assoc->flags |= ASSOC_DELETEFADEDOUT;
+ assoc->blendDelta = -1000.0f;
+ CPed* ped = (CPed*)arg;
+
+ if (ped->m_phoneId != -1 && crimeReporters[ped->m_phoneId] == ped) {
+ crimeReporters[ped->m_phoneId] = nil;
+ gPhoneInfo.m_aPhones[ped->m_phoneId].m_nState = PHONE_STATE_FREE;
+ ped->m_phoneId = -1;
+ }
+
+ if (assoc->blendAmount > 0.5f)
+ ped->bUpdateAnimHeading = true;
+
+ ped->SetWanderPath(CGeneral::GetRandomNumber() & 7);
+}
#endif
- int16 lastVehicle;
- CEntity* vehicles[8];
- CWorld::FindObjectsInRange(ourPos, 20.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];
- CPed *driver = nearVeh->pDriver;
- if (driver) {
+bool
+CPed::FacePhone(void)
+{
+ // This function was broken since it's left unused early in development.
+#ifdef PEDS_REPORT_CRIMES_ON_PHONE
+ float phoneDir = CGeneral::GetRadianAngleBetweenPoints(
+ gPhoneInfo.m_aPhones[m_phoneId].m_vecPos.x, gPhoneInfo.m_aPhones[m_phoneId].m_vecPos.y,
+ GetPosition().x, GetPosition().y);
- // BUG: Same bug as above. Fixed at the bottom of function.
- flagsOfSomePed = CPedType::GetFlag(driver->m_nPedType);
- if (CPedType::GetFlag(driver->m_nPedType) & fearFlags) {
- if (driver->m_fHealth > 0.0f && OurPedCanSeeThisOne(nearVeh->pDriver)) {
- // FIX: Taken from VC
-#ifdef FIX_BUGS
- float driverDistSqr = (driver->GetPosition() - ourPos).MagnitudeSqr2D();
+ if (m_facePhoneStart) {
+ m_lookTimer = 0;
+ SetLookFlag(phoneDir, true);
+ m_lookTimer = CTimer::GetTimeInMilliseconds() + 3000;
+ m_facePhoneStart = false;
+ }
+
+ if (bIsLooking && TurnBody()) {
+ ClearLookFlag();
+ SetIdle();
+ m_phoneTalkTimer = CTimer::GetTimeInMilliseconds() + 10000;
+ CAnimBlendAssociation* assoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_PHONE_IN, 4.0f);
+ assoc->SetFinishCallback(ReportPhonePickUpCB, this);
+ return true;
+ }
+
+ return false;
#else
- float driverDistSqr = (CVector2D(ourPos) - explosionPos).MagnitudeSqr();
+ float currentRot = RADTODEG(m_fRotationCur);
+ float phoneDir = CGeneral::GetRadianAngleBetweenPoints(
+ gPhoneInfo.m_aPhones[m_phoneId].m_vecPos.x,
+ gPhoneInfo.m_aPhones[m_phoneId].m_vecPos.y,
+ GetPosition().x,
+ GetPosition().y);
+
+ SetLookFlag(phoneDir, false);
+ phoneDir = CGeneral::LimitAngle(phoneDir);
+ m_moved = CVector2D(0.0f, 0.0f);
+
+ if (currentRot - 180.0f > phoneDir)
+ phoneDir += 2 * 180.0f;
+ else if (180.0f + currentRot < phoneDir)
+ phoneDir -= 2 * 180.0f;
+
+ float neededTurn = currentRot - phoneDir;
+
+ if (Abs(neededTurn) <= 0.75f) {
+ SetIdle();
+ ClearLookFlag();
+ m_phoneTalkTimer = CTimer::GetTimeInMilliseconds() + 10000;
+ return true;
+ } else {
+ m_fRotationCur = DEGTORAD(currentRot - neededTurn * 0.2f);
+ return false;
+ }
#endif
- if (sq(closestPedDist) > driverDistSqr) {
- closestPedDist = Sqrt(driverDistSqr);
- pedToFearFrom = nearVeh->pDriver;
- }
- }
- }
- }
- }
- m_threatEntity = pedToFearFrom;
- if (m_threatEntity)
- m_threatEntity->RegisterReference((CEntity **) &m_threatEntity);
+}
+bool
+CPed::MakePhonecall(void)
+{
+#ifdef PEDS_REPORT_CRIMES_ON_PHONE
+ if (!IsPlayer() && CTimer::GetTimeInMilliseconds() > m_phoneTalkTimer - 7000 && bRunningToPhone) {
-#ifdef FIX_BUGS
- if (pedToFearFrom)
- flagsOfSomePed = CPedType::GetFlag(((CPed*)m_threatEntity)->m_nPedType);
- else
- flagsOfSomePed = 0;
+ FindPlayerPed()->m_pWanted->RegisterCrime_Immediately(m_crimeToReportOnPhone, GetPosition(),
+ (m_crimeToReportOnPhone == CRIME_POSSESSION_GUN ? (uintptr)m_threatEntity : (uintptr)m_victimOfPlayerCrime), false);
+
+ if (m_crimeToReportOnPhone != CRIME_POSSESSION_GUN)
+ FindPlayerPed()->m_pWanted->SetWantedLevelNoDrop(1);
+
+ bRunningToPhone = false;
+ }
#endif
+ if (CTimer::GetTimeInMilliseconds() <= m_phoneTalkTimer)
+ return false;
- return flagsOfSomePed;
+#ifdef PEDS_REPORT_CRIMES_ON_PHONE
+ CAnimBlendAssociation* talkAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_PHONE_TALK);
+ if (talkAssoc && talkAssoc->blendAmount > 0.5f) {
+ CAnimBlendAssociation* endAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_PHONE_OUT, 8.0f);
+ endAssoc->flags &= ~ASSOC_DELETEFADEDOUT;
+ endAssoc->SetFinishCallback(ReportPhonePutDownCB, this);
}
+#endif
+ SetIdle();
+
+ gPhoneInfo.m_aPhones[m_phoneId].m_nState = PHONE_STATE_FREE;
+#ifndef PEDS_REPORT_CRIMES_ON_PHONE
+ m_phoneId = -1;
+#endif
+
+ // Because SetWanderPath is now done async in ReportPhonePutDownCB
+#ifdef PEDS_REPORT_CRIMES_ON_PHONE
+ return false;
+#else
+ return true;
+#endif
+}
+
+void
+CPed::Teleport(CVector pos)
+{
+ CWorld::Remove(this);
+ SetPosition(pos);
+ bIsStanding = false;
+ m_nPedStateTimer = 0;
+ m_actionX = 0.0f;
+ m_actionY = 0.0f;
+ m_pDamageEntity = nil;
+ CWorld::Add(this);
+}
+
+void
+CPed::SetSeekCar(CVehicle *car, uint32 doorNode)
+{
+ if (m_nPedState == PED_SEEK_CAR)
+ return;
+
+#ifdef VC_PED_PORTS
+ if (!CanSetPedState() || m_nPedState == PED_DRIVING)
+ return;
+#endif
+
+ SetStoredState();
+ m_pSeekTarget = car;
+ m_pSeekTarget->RegisterReference((CEntity**) &m_pSeekTarget);
+ m_carInObjective = car;
+ m_carInObjective->RegisterReference((CEntity**) &m_carInObjective);
+ m_pMyVehicle = car;
+ m_pMyVehicle->RegisterReference((CEntity**) &m_pMyVehicle);
+ // m_pSeekTarget->RegisterReference((CEntity**) &m_pSeekTarget);
+ m_vehEnterType = doorNode;
+ m_distanceToCountSeekDone = 0.5f;
+ m_nPedState = PED_SEEK_CAR;
+
}
void
@@ -15973,485 +6826,104 @@ CPed::SeekCar(void)
}
}
-void
-CPed::StartFightDefend(uint8 direction, uint8 hitLevel, uint8 unk)
+bool
+CPed::CheckForExplosions(CVector2D &area)
{
- if (m_nPedState == PED_DEAD) {
- if (CGame::nastyGame) {
- if (hitLevel == HITLEVEL_GROUND) {
- CAnimBlendAssociation *floorHitAssoc;
- if (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL)) {
- floorHitAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FLOOR_HIT_F, 8.0f);
- } else {
- floorHitAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[FIGHTMOVE_HITONFLOOR].animId, 8.0f);
- }
- if (floorHitAssoc) {
- floorHitAssoc->SetCurrentTime(0.0f);
- floorHitAssoc->SetRun();
- floorHitAssoc->flags &= ~ASSOC_FADEOUTWHENDONE;
- }
- }
- if (CGame::nastyGame) {
- CVector headPos = GetNodePosition(PED_HEAD);
- for(int i = 0; i < 4; ++i) {
- CVector bloodDir(0.0f, 0.0f, 0.1f);
- CVector bloodPos = headPos - 0.2f * GetForward();
- CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, bloodDir, nil, 0.0f, 0, 0, 0, 0);
- }
- }
- }
- } else if (m_nPedState == PED_FALL) {
- if (hitLevel == HITLEVEL_GROUND && !IsPedHeadAbovePos(-0.3f)) {
- CAnimBlendAssociation *floorHitAssoc = RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL) ?
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FLOOR_HIT_F, 8.0f) :
- CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FLOOR_HIT, 8.0f);
- if (floorHitAssoc) {
- floorHitAssoc->flags &= ~ASSOC_FADEOUTWHENDONE;
- floorHitAssoc->flags |= ASSOC_DELETEFADEDOUT;
- }
- }
- } else if (IsPedInControl()) {
- if ((IsPlayer() && m_nPedState != PED_FIGHT && ((CPlayerPed*)this)->m_fMoveSpeed > 1.0f)
- || (!IsPlayer() && m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE)) {
-#ifndef VC_PED_PORTS
- if (hitLevel != HITLEVEL_HIGH && hitLevel != HITLEVEL_LOW || (IsPlayer() || CGeneral::GetRandomNumber() & 3) && CGeneral::GetRandomNumber() & 7) {
- if (IsPlayer() || CGeneral::GetRandomNumber() & 3) {
-#else
- if (hitLevel != HITLEVEL_HIGH && hitLevel != HITLEVEL_LOW || (IsPlayer() || CGeneral::GetRandomNumber() & 1) && CGeneral::GetRandomNumber() & 7) {
- if (IsPlayer() || CGeneral::GetRandomNumber() & 1) {
-#endif
- AnimationId shotAnim;
- switch (direction) {
- case 1:
- shotAnim = ANIM_SHOT_LEFT_PARTIAL;
- break;
- case 2:
- shotAnim = ANIM_SHOT_BACK_PARTIAL;
- break;
- case 3:
- shotAnim = ANIM_SHOT_RIGHT_PARTIAL;
- break;
- default:
- shotAnim = ANIM_SHOT_FRONT_PARTIAL;
- break;
- }
- CAnimBlendAssociation *shotAssoc = RpAnimBlendClumpGetAssociation(GetClump(), shotAnim);
- if (!shotAssoc || shotAssoc->blendDelta < 0.0f)
- shotAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, shotAnim, 8.0f);
+ int event = 0;
+ if (CEventList::FindClosestEvent(EVENT_EXPLOSION, GetPosition(), &event)) {
+ area.x = gaEvent[event].posn.x;
+ area.y = gaEvent[event].posn.y;
+ CEntity *actualEntity = nil;
- shotAssoc->SetCurrentTime(0.0f);
- shotAssoc->SetRun();
- shotAssoc->flags |= ASSOC_FADEOUTWHENDONE;
- } else {
- int time = CGeneral::GetRandomNumberInRange(1000, 3000);
- SetWaitState(WAITSTATE_PLAYANIM_DUCK, &time);
- }
- } else {
-#ifndef VC_PED_PORTS
- switch (direction) {
- case 1:
- SetFall(500, ANIM_KO_SPIN_R, false);
- break;
- case 2:
- SetFall(500, ANIM_KO_SKID_BACK, false);
- break;
- case 3:
- SetFall(500, ANIM_KO_SPIN_L, false);
- break;
- default:
- SetFall(500, ANIM_KO_SHOT_STOM, false);
- break;
- }
-#else
- bool fall = true;
- AnimationId hitAnim;
- switch (direction) {
- case 1:
- hitAnim = ANIM_KO_SPIN_R;
- break;
- case 2:
- if (CGeneral::GetRandomNumber() & 1) {
- fall = false;
- hitAnim = ANIM_HIT_BACK;
- } else {
- hitAnim = ANIM_KO_SKID_BACK;
- }
- break;
- case 3:
- hitAnim = ANIM_KO_SPIN_L;
- break;
- default:
- if (hitLevel == HITLEVEL_LOW) {
- hitAnim = ANIM_KO_SHOT_STOM;
- } else if (CGeneral::GetRandomNumber() & 1) {
- fall = false;
- hitAnim = ANIM_HIT_WALK;
- } else if (CGeneral::GetRandomNumber() & 1) {
- fall = false;
- hitAnim = ANIM_HIT_HEAD;
- } else {
- hitAnim = ANIM_KO_SHOT_FACE;
- }
- break;
- }
- if (fall) {
- SetFall(500, hitAnim, false);
- } else {
- CAnimBlendAssociation *hitAssoc = RpAnimBlendClumpGetAssociation(GetClump(), hitAnim);
- if (!hitAssoc || hitAssoc->blendDelta < 0.0f)
- hitAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, hitAnim, 8.0f);
+ switch (gaEvent[event].entityType) {
+ case EVENT_ENTITY_PED:
+ actualEntity = CPools::GetPed(gaEvent[event].entityRef);
+ break;
+ case EVENT_ENTITY_VEHICLE:
+ actualEntity = CPools::GetVehicle(gaEvent[event].entityRef);
+ break;
+ case EVENT_ENTITY_OBJECT:
+ actualEntity = CPools::GetObject(gaEvent[event].entityRef);
+ break;
+ default:
+ break;
+ }
- hitAssoc->SetCurrentTime(0.0f);
- hitAssoc->SetRun();
- hitAssoc->flags |= ASSOC_FADEOUTWHENDONE;
- }
-#endif
- }
- Say(SOUND_PED_DEFEND);
- } else {
- Say(SOUND_PED_DEFEND);
- switch (hitLevel) {
- case HITLEVEL_GROUND:
- m_curFightMove = FIGHTMOVE_HITONFLOOR;
- break;
- case HITLEVEL_LOW:
-#ifndef VC_PED_PORTS
- if (direction == 2) {
- SetFall(1000, ANIM_KO_SKID_BACK, false);
- return;
- }
-#else
- if (direction == 2 && (!IsPlayer() || ((CGeneral::GetRandomNumber() & 1) && m_fHealth < 30.0f))) {
- SetFall(1000, ANIM_KO_SKID_BACK, false);
- return;
- } else if (direction != 2 && !IsPlayer() && (CGeneral::GetRandomNumber() & 1) && m_fHealth < 30.0f) {
- SetFall(1000, ANIM_KO_SHOT_STOM, false);
- return;
- }
-#endif
- m_curFightMove = FIGHTMOVE_HITBODY;
- break;
- case HITLEVEL_HIGH:
- switch (direction) {
- case 1:
- m_curFightMove = FIGHTMOVE_HITLEFT;
- break;
- case 2:
- m_curFightMove = FIGHTMOVE_HITBACK;
- break;
- case 3:
- m_curFightMove = FIGHTMOVE_HITRIGHT;
- break;
- default:
- if (unk <= 5)
- m_curFightMove = FIGHTMOVE_HITHEAD;
- else
- m_curFightMove = FIGHTMOVE_HITBIGSTEP;
- break;
- }
- break;
- default:
- switch (direction) {
- case 1:
- m_curFightMove = FIGHTMOVE_HITLEFT;
- break;
- case 2:
- m_curFightMove = FIGHTMOVE_HITBACK;
- break;
- case 3:
- m_curFightMove = FIGHTMOVE_HITRIGHT;
- break;
- default:
- if (unk <= 5)
- m_curFightMove = FIGHTMOVE_HITCHEST;
- else
- m_curFightMove = FIGHTMOVE_HITBIGSTEP;
- break;
- }
- break;
- }
- if (m_nPedState == PED_GETUP && !IsPedHeadAbovePos(0.0f))
- m_curFightMove = FIGHTMOVE_HITONFLOOR;
-
- if (m_nPedState == PED_FIGHT) {
- CAnimBlendAssociation *moveAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 8.0f);
- moveAssoc->SetCurrentTime(0.0f);
- moveAssoc->SetFinishCallback(FinishFightMoveCB, this);
- if (IsPlayer())
- moveAssoc->speed = 1.3f;
-
- m_takeAStepAfterAttack = 0;
- m_fightButtonPressure = 0;
- } else if (IsPlayer() && m_currentWeapon != WEAPONTYPE_UNARMED) {
- CAnimBlendAssociation *moveAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 4.0f);
- moveAssoc->SetCurrentTime(0.0f);
- moveAssoc->speed = 1.3f;
- } else {
- if (m_nPedState != PED_AIM_GUN && m_nPedState != PED_ATTACK)
- SetStoredState();
+ if (actualEntity) {
+ m_pEventEntity = actualEntity;
+ m_pEventEntity->RegisterReference((CEntity **) &m_pEventEntity);
+ bGonnaInvestigateEvent = true;
+ } else
+ bGonnaInvestigateEvent = false;
- if (m_nWaitState != WAITSTATE_FALSE) {
- m_nWaitState = WAITSTATE_FALSE;
- RestoreHeadingRate();
- }
- m_nPedState = PED_FIGHT;
- m_fightButtonPressure = 0;
- RpAnimBlendClumpRemoveAssociations(GetClump(), ASSOC_REPEAT);
- CAnimBlendAssociation *walkStartAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WALK_START);
- if (walkStartAssoc) {
- walkStartAssoc->flags |= ASSOC_DELETEFADEDOUT;
- walkStartAssoc->blendDelta = -1000.0f;
- }
- CAnimBlendAssociation *walkStopAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP);
- if (!walkStopAssoc)
- walkStopAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP_R);
- if (walkStopAssoc) {
- walkStopAssoc->flags |= ASSOC_DELETEFADEDOUT;
- walkStopAssoc->blendDelta = -1000.0f;
- RestoreHeadingRate();
- }
- SetMoveState(PEDMOVE_NONE);
- m_nStoredMoveState = PEDMOVE_NONE;
- CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT_IDLE)->blendAmount = 1.0f;
- CAnimBlendAssociation *moveAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 8.0f);
- moveAssoc->SetFinishCallback(FinishFightMoveCB, this);
- m_fightState = FIGHTSTATE_NO_MOVE;
- m_takeAStepAfterAttack = false;
- bIsAttacking = true;
- }
- }
+ CEventList::ClearEvent(event);
+ return true;
+ } else if (CEventList::FindClosestEvent(EVENT_FIRE, GetPosition(), &event)) {
+ area.x = gaEvent[event].posn.x;
+ area.y = gaEvent[event].posn.y;
+ CEventList::ClearEvent(event);
+ bGonnaInvestigateEvent = false;
+ return true;
}
+
+ bGonnaInvestigateEvent = false;
+ return false;
}
-void
-CPed::UpdateFromLeader(void)
+CPed *
+CPed::CheckForGunShots(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 (IsPedInControl()) {
- SetObjective(OBJECTIVE_NONE);
- SetIdle();
- SetMoveState(PEDMOVE_STILL);
+ int event;
+ if (CEventList::FindClosestEvent(EVENT_GUNSHOT, GetPosition(), &event)) {
+ if (gaEvent[event].entityType == EVENT_ENTITY_PED) {
+ // Probably due to we don't want peds to go gunshot area? (same on VC)
+ bGonnaInvestigateEvent = false;
+ return CPools::GetPed(gaEvent[event].entityRef);
}
- SetLeader(nil);
- return;
}
+ bGonnaInvestigateEvent = false;
+ return nil;
+}
- 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) {
- 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) {
-#ifndef VC_PED_PORTS
- SetObjective(OBJECTIVE_GOTO_CHAR_ON_FOOT, m_leader);
- SetObjectiveTimer(0);
-#else
- 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);
- }
-#endif
- }
- if (m_nPedState == PED_IDLE && m_leader->IsPlayer()) {
- if (ScanForThreats() && m_threatEntity) {
- m_pLookTarget = m_threatEntity;
- m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);
- TurnBody();
- if (m_attackTimer < CTimer::GetTimeInMilliseconds() && !GetWeapon()->IsTypeMelee()) {
- m_pPointGunAt = m_threatEntity;
- if (m_threatEntity)
- m_threatEntity->RegisterReference((CEntity **) &m_pPointGunAt);
- SetAttack(m_threatEntity);
- }
- }
- }
- }
- } else {
- switch (m_leader->m_objective) {
- case OBJECTIVE_WAIT_ON_FOOT:
- case OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE:
- case OBJECTIVE_WAIT_IN_CAR:
- case OBJECTIVE_FOLLOW_ROUTE:
- SetObjective(m_leader->m_objective);
- m_objectiveTimer = m_leader->m_objectiveTimer;
- break;
- case OBJECTIVE_GUARD_SPOT:
- SetObjective(OBJECTIVE_GUARD_SPOT, m_leader->m_vecSeekPosEx);
- 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:
- 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) {
- 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) {
-#ifdef VC_PED_PORTS
- m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 250;
-#endif
- SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);
- }
-
- break;
- }
+CPed *
+CPed::CheckForDeadPeds(void)
+{
+ int event;
+ if (CEventList::FindClosestEvent(EVENT_DEAD_PED, GetPosition(), &event)) {
+ int pedHandle = gaEvent[event].entityRef;
+ if (pedHandle && gaEvent[event].entityType == EVENT_ENTITY_PED) {
+ bGonnaInvestigateEvent = true;
+ return CPools::GetPed(pedHandle);
}
}
+ bGonnaInvestigateEvent = false;
+ return nil;
}
-void
-CPed::UpdatePosition(void)
+bool
+CPed::IsPlayer(void) const
{
- if (CReplay::IsPlayingBack() || !bIsStanding)
- return;
-
- CVector2D velocityChange;
-
- SetHeading(m_fRotationCur);
- if (m_pCurrentPhysSurface) {
- CVector2D velocityOfSurface;
- if (!IsPlayer() && m_pCurrentPhysSurface->IsVehicle() && ((CVehicle*)m_pCurrentPhysSurface)->IsBoat()) {
-
- // It seems R* didn't like m_vecOffsetFromPhysSurface for boats
- CVector offsetToSurface = GetPosition() - m_pCurrentPhysSurface->GetPosition();
- offsetToSurface.z -= FEET_OFFSET;
-
- CVector surfaceMoveVelocity = m_pCurrentPhysSurface->m_vecMoveSpeed;
- CVector surfaceTurnVelocity = CrossProduct(m_pCurrentPhysSurface->m_vecTurnSpeed, offsetToSurface);
+ return m_nPedType == PEDTYPE_PLAYER1 || m_nPedType == PEDTYPE_PLAYER2 ||
+ m_nPedType == PEDTYPE_PLAYER3 || m_nPedType == PEDTYPE_PLAYER4;
+}
- // Also we use that weird formula instead of friction if it's boat
- float slideMult = -m_pCurrentPhysSurface->m_vecTurnSpeed.MagnitudeSqr();
- velocityOfSurface = slideMult * offsetToSurface * CTimer::GetTimeStep() + (surfaceTurnVelocity + surfaceMoveVelocity);
- m_vecMoveSpeed.z = slideMult * offsetToSurface.z * CTimer::GetTimeStep() + (surfaceTurnVelocity.z + surfaceMoveVelocity.z);
- } else {
- velocityOfSurface = m_pCurrentPhysSurface->GetSpeed(m_vecOffsetFromPhysSurface);
- }
- // Reminder: m_moved is displacement from walking/running.
- velocityChange = m_moved + velocityOfSurface - m_vecMoveSpeed;
- m_fRotationCur += m_pCurrentPhysSurface->m_vecTurnSpeed.z * CTimer::GetTimeStep();
- m_fRotationDest += m_pCurrentPhysSurface->m_vecTurnSpeed.z * CTimer::GetTimeStep();
- } else if (m_nSurfaceTouched == SURFACE_STEEP_CLIFF && (m_vecDamageNormal.x != 0.0f || m_vecDamageNormal.y != 0.0f)) {
- // Ped got damaged by steep slope
- m_vecMoveSpeed = CVector(0.0f, 0.0f, -0.001f);
- // some kind of
- CVector2D reactionForce = m_vecDamageNormal;
- reactionForce.Normalise();
+bool
+CPed::IsGangMember(void) const
+{
+ return m_nPedType >= PEDTYPE_GANG1 && m_nPedType <= PEDTYPE_GANG9;
+}
- velocityChange = 0.02f * reactionForce + m_moved;
+bool
+CPed::IsPointerValid(void)
+{
+ int pedIndex = CPools::GetPedPool()->GetIndex(this) >> 8;
+ if (pedIndex < 0 || pedIndex >= NUMPEDS)
+ return false;
- float reactionAndVelocityDotProd = DotProduct2D(reactionForce, velocityChange);
- // they're in same direction
- if (reactionAndVelocityDotProd < 0.0f) {
- velocityChange -= reactionAndVelocityDotProd * reactionForce;
- }
- } else {
- velocityChange = m_moved - m_vecMoveSpeed;
- }
-
- // Take time step into account
- if (m_pCurrentPhysSurface) {
- float speedChange = velocityChange.Magnitude();
- float changeMult = speedChange;
- if (m_nPedState == PED_DIE && m_pCurrentPhysSurface->IsVehicle()) {
- changeMult = 0.002f * CTimer::GetTimeStep();
- } else if (!(m_pCurrentPhysSurface->IsVehicle() && ((CVehicle*)m_pCurrentPhysSurface)->IsBoat())) {
- changeMult = 0.01f * CTimer::GetTimeStep();
- }
+ if (m_entryInfoList.first || FindPlayerPed() == this)
+ return true;
- if (speedChange > changeMult) {
- velocityChange = velocityChange * (changeMult / speedChange);
- }
- }
- m_vecMoveSpeed.x += velocityChange.x;
- m_vecMoveSpeed.y += velocityChange.y;
+ return false;
}
void
@@ -16528,871 +7000,1469 @@ CPed::SetPedPositionInCar(void)
GetMatrix() = newMat;
}
-static RwObject*
-CloneAtomicToFrameCB(RwObject *frame, void *data)
-{
- RpAtomic *newAtomic = RpAtomicClone((RpAtomic*)frame);
- RpAtomicSetFrame(newAtomic, (RwFrame*)data);
- RpClumpAddAtomic(flyingClumpTemp, newAtomic);
- CVisibilityPlugins::SetAtomicRenderCallback(newAtomic, nil);
- return frame;
-}
-
-static RwFrame*
-RecurseFrameChildrenToCloneCB(RwFrame *frame, void *data)
-{
- RwFrame *newFrame = RwFrameCreate();
- RwFrameAddChild((RwFrame*)data, newFrame);
- RwFrameTransform(newFrame, RwFrameGetMatrix(frame), rwCOMBINEREPLACE);
- RwFrameForAllObjects(frame, CloneAtomicToFrameCB, newFrame);
- RwFrameForAllChildren(frame, RecurseFrameChildrenToCloneCB, newFrame);
- return newFrame;
-}
-
-CObject*
-CPed::SpawnFlyingComponent(int pedNode, int8 direction)
+void
+CPed::LookForSexyPeds(void)
{
- if (CObject::nNoTempObjects >= NUMTEMPOBJECTS)
- return nil;
-
-#ifdef PED_SKIN
- assert(!IsClumpSkinned(GetClump()));
-#endif
-
- CObject *obj = new CObject();
- if (!obj)
- return nil;
-
- RwFrame *frame = RwFrameCreate();
- RpClump *clump = RpClumpCreate();
- RpClumpSetFrame(clump, frame);
- RwMatrix *matrix = RwFrameGetLTM(m_pFrames[pedNode]->frame);
- *RwFrameGetMatrix(frame) = *matrix;
-
- flyingClumpTemp = clump;
- RwFrameForAllObjects(m_pFrames[pedNode]->frame, CloneAtomicToFrameCB, frame);
- RwFrameForAllChildren(m_pFrames[pedNode]->frame, RecurseFrameChildrenToCloneCB, frame);
- flyingClumpTemp = nil;
- switch (pedNode) {
- case PED_HEAD:
- // So popping head would have wheel collision. They disabled it anyway
- obj->SetModelIndexNoCreate(MI_CAR_WHEEL);
- break;
- case PED_UPPERARML:
- case PED_UPPERARMR:
- obj->SetModelIndexNoCreate(MI_BODYPARTB);
- obj->SetCenterOfMass(0.25f, 0.0f, 0.0f);
- break;
- case PED_UPPERLEGL:
- case PED_UPPERLEGR:
- obj->SetModelIndexNoCreate(MI_BODYPARTA);
- obj->SetCenterOfMass(0.4f, 0.0f, 0.0f);
- break;
- default:
- break;
- }
- obj->RefModelInfo(GetModelIndex());
- obj->AttachToRwObject((RwObject*)clump);
- obj->m_fMass = 15.0f;
- obj->m_fTurnMass = 5.0f;
- obj->m_fAirResistance = 0.99f;
- obj->m_fElasticity = 0.03f;
- obj->m_fBuoyancy = m_fMass*GRAVITY/0.75f;
- obj->ObjectCreatedBy = TEMP_OBJECT;
- obj->SetIsStatic(false);
- obj->bIsPickup = false;
- obj->m_nSpecialCollisionResponseCases = COLLRESPONSE_SMALLBOX;
-
- // life time - the more objects the are, the shorter this one will live
- CObject::nNoTempObjects++;
- if (CObject::nNoTempObjects > 20)
- obj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 12000;
- else if (CObject::nNoTempObjects > 10)
- obj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 30000;
- else
- obj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 60000;
+ if ((!IsPedInControl() && m_nPedState != PED_DRIVING)
+ || m_lookTimer >= CTimer::GetTimeInMilliseconds() || m_nPedType != PEDTYPE_CIVMALE)
+ return;
- CVector localForcePos, forceDir;
+ for (int i = 0; i < m_numNearPeds; i++) {
+ if (CanSeeEntity(m_nearPeds[i])) {
+ if ((GetPosition() - m_nearPeds[i]->GetPosition()).Magnitude() < 10.0f) {
+ CPed *nearPed = m_nearPeds[i];
+ if ((nearPed->m_pedStats->m_sexiness > m_pedStats->m_sexiness)
+ && nearPed->m_nPedType == PEDTYPE_CIVFEMALE) {
- if (direction == 2) {
- obj->m_vecMoveSpeed = 0.03f * GetForward();
- obj->m_vecMoveSpeed.z = (CGeneral::GetRandomNumber() & 0x3F) * 0.001f;
- obj->m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);
- localForcePos = CVector(0.0f, 0.0f, 0.0f);
- forceDir = GetForward();
- } else {
- obj->m_vecMoveSpeed = -0.03f * GetForward();
- obj->m_vecMoveSpeed.z = (CGeneral::GetRandomNumber() & 0x3F) * 0.001f;
- obj->m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);
- localForcePos = CVector(0.0f, 0.0f, 0.0f);
- forceDir = -GetForward();
+ SetLookFlag(nearPed, true);
+ m_lookTimer = CTimer::GetTimeInMilliseconds() + 4000;
+ Say(SOUND_PED_CHAT_SEXY);
+ return;
+ }
+ }
+ }
}
- obj->ApplyTurnForce(forceDir, localForcePos);
- CWorld::Add(obj);
-
- return obj;
+ m_lookTimer = CTimer::GetTimeInMilliseconds() + 10000;
}
void
-CPed::WarpPedIntoCar(CVehicle *car)
+CPed::LookForSexyCars(void)
{
- bInVehicle = true;
- m_pMyVehicle = car;
- m_pMyVehicle->RegisterReference((CEntity **) &m_pMyVehicle);
- m_carInObjective = car;
- m_carInObjective->RegisterReference((CEntity **) &m_carInObjective);
- m_nPedState = PED_DRIVING;
- bUsesCollision = false;
- bIsInTheAir = false;
- bVehExitWillBeInstant = true;
- if (m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) {
- car->SetDriver(this);
- car->pDriver->RegisterReference((CEntity **) &car->pDriver);
+ CEntity *vehicles[8];
+ CVehicle *veh;
+ int foundVehId = 0;
+ int bestPriceYet = 0;
+ int16 lastVehicle;
- } else if (m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER) {
- for (int i = 0; i < 4; i++) {
- if (!car->pPassengers[i]) {
- car->pPassengers[i] = this;
- car->pPassengers[i]->RegisterReference((CEntity **) &car->pPassengers[i]);
- break;
+ if (!IsPedInControl() && m_nPedState != PED_DRIVING)
+ return;
+
+ if (m_lookTimer < CTimer::GetTimeInMilliseconds()) {
+ CWorld::FindObjectsInRange(GetPosition(), 10.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false);
+
+ for (int vehId = 0; vehId < lastVehicle; vehId++) {
+ veh = (CVehicle*)vehicles[vehId];
+ if (veh != m_pMyVehicle && bestPriceYet < veh->pHandling->nMonetaryValue) {
+ foundVehId = vehId;
+ bestPriceYet = veh->pHandling->nMonetaryValue;
}
}
- } else
- return;
+ if (lastVehicle > 0 && bestPriceYet > 40000)
+ SetLookFlag(vehicles[foundVehId], false);
- if (IsPlayer()) {
- car->SetStatus(STATUS_PLAYER);
- AudioManager.PlayerJustGotInCar();
- CCarCtrl::RegisterVehicleOfInterest(car);
- } else {
- car->SetStatus(STATUS_PHYSICS);
+ m_lookTimer = CTimer::GetTimeInMilliseconds() + 10000;
}
+}
- CWorld::Remove(this);
- SetPosition(car->GetPosition());
- CWorld::Add(this);
+bool
+CPed::LookForInterestingNodes(void)
+{
+ CBaseModelInfo *model;
+ CPtrNode *ptrNode;
+ CVector effectDist;
+ C2dEffect *effect;
+ CMatrix *objMat;
- if (car->bIsAmbulanceOnDuty) {
- car->bIsAmbulanceOnDuty = false;
- --CCarCtrl::NumAmbulancesOnDuty;
- }
- if (car->bIsFireTruckOnDuty) {
- car->bIsFireTruckOnDuty = false;
- --CCarCtrl::NumFiretrucksOnDuty;
- }
- if (!car->bEngineOn) {
- car->bEngineOn = true;
- DMAudio.PlayOneShot(car->m_audioEntityId, SOUND_CAR_ENGINE_START, 1.0f);
+ if ((CTimer::GetFrameCounter() + (m_randomSeed % 256)) & 7 || CTimer::GetTimeInMilliseconds() <= m_standardTimer) {
+ return false;
}
+ bool found = false;
+ uint8 randVal = CGeneral::GetRandomNumber() % 256;
-#ifdef VC_PED_PORTS
- RpAnimBlendClumpSetBlendDeltas(GetClump(), ASSOC_PARTIAL, -1000.0f);
-
- // VC uses AddInCarAnims but we don't have that
- m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, car->GetDriverAnim(), 100.0f);
- RemoveWeaponWhenEnteringVehicle();
+ int minX = CWorld::GetSectorIndexX(GetPosition().x - CHECK_NEARBY_THINGS_MAX_DIST);
+ if (minX < 0) minX = 0;
+ int minY = CWorld::GetSectorIndexY(GetPosition().y - CHECK_NEARBY_THINGS_MAX_DIST);
+ if (minY < 0) minY = 0;
+ int maxX = CWorld::GetSectorIndexX(GetPosition().x + CHECK_NEARBY_THINGS_MAX_DIST);
+#ifdef FIX_BUGS
+ if (maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X - 1;
#else
- if (car->IsBoat()) {
-#ifndef FIX_BUGS
- m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_BOAT, 100.0f);
+ if (maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X;
+#endif
+
+ int maxY = CWorld::GetSectorIndexY(GetPosition().y + CHECK_NEARBY_THINGS_MAX_DIST);
+#ifdef FIX_BUGS
+ if (maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y - 1;
#else
- m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, car->GetDriverAnim(), 100.0f);
+ if (maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y;
#endif
- CWeaponInfo *ourWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
- RemoveWeaponModel(ourWeapon->m_nModelId);
- } else {
- // Because we can use Uzi for drive by
- RemoveWeaponWhenEnteringVehicle();
- if (car->bLowVehicle)
- m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_LSIT, 100.0f);
- else
- m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_SIT, 100.0f);
+ for (int curY = minY; curY <= maxY && !found; curY++) {
+ for (int curX = minX; curX <= maxX && !found; curX++) {
+ CSector *sector = CWorld::GetSector(curX, curY);
+
+ for (ptrNode = sector->m_lists[ENTITYLIST_VEHICLES].first; ptrNode && !found; ptrNode = ptrNode->next) {
+ CVehicle *veh = (CVehicle*)ptrNode->item;
+ model = veh->GetModelInfo();
+ if (model->GetNum2dEffects() != 0) {
+ for (int e = 0; e < model->GetNum2dEffects(); e++) {
+ effect = model->Get2dEffect(e);
+ if (effect->type == EFFECT_ATTRACTOR && effect->attractor.probability >= randVal) {
+ objMat = &veh->GetMatrix();
+ CVector effectPos = veh->GetMatrix() * effect->pos;
+ effectDist = effectPos - GetPosition();
+ if (effectDist.MagnitudeSqr() < sq(8.0f)) {
+ found = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ for (ptrNode = sector->m_lists[ENTITYLIST_OBJECTS].first; ptrNode && !found; ptrNode = ptrNode->next) {
+ CObject *obj = (CObject*)ptrNode->item;
+ model = CModelInfo::GetModelInfo(obj->GetModelIndex());
+ if (model->GetNum2dEffects() != 0) {
+ for (int e = 0; e < model->GetNum2dEffects(); e++) {
+ effect = model->Get2dEffect(e);
+ if (effect->type == EFFECT_ATTRACTOR && effect->attractor.probability >= randVal) {
+ objMat = &obj->GetMatrix();
+ CVector effectPos = obj->GetMatrix() * effect->pos;
+ effectDist = effectPos - GetPosition();
+ if (effectDist.MagnitudeSqr() < sq(8.0f)) {
+ found = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ for (ptrNode = sector->m_lists[ENTITYLIST_BUILDINGS].first; ptrNode && !found; ptrNode = ptrNode->next) {
+ CBuilding *building = (CBuilding*)ptrNode->item;
+ model = CModelInfo::GetModelInfo(building->GetModelIndex());
+ if (model->GetNum2dEffects() != 0) {
+ for (int e = 0; e < model->GetNum2dEffects(); e++) {
+ effect = model->Get2dEffect(e);
+ if (effect->type == EFFECT_ATTRACTOR && effect->attractor.probability >= randVal) {
+ objMat = &building->GetMatrix();
+ CVector effectPos = building->GetMatrix() * effect->pos;
+ effectDist = effectPos - GetPosition();
+ if (effectDist.MagnitudeSqr() < sq(8.0f)) {
+ found = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ for (ptrNode = sector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP].first; ptrNode && !found; ptrNode = ptrNode->next) {
+ CBuilding *building = (CBuilding*)ptrNode->item;
+ model = CModelInfo::GetModelInfo(building->GetModelIndex());
+ if (model->GetNum2dEffects() != 0) {
+ for (int e = 0; e < model->GetNum2dEffects(); e++) {
+ effect = model->Get2dEffect(e);
+ if (effect->type == EFFECT_ATTRACTOR && effect->attractor.probability >= randVal) {
+ objMat = &building->GetMatrix();
+ CVector effectPos = building->GetMatrix() * effect->pos;
+ effectDist = effectPos - GetPosition();
+ if (effectDist.MagnitudeSqr() < sq(8.0f)) {
+ found = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
}
-#endif
- StopNonPartialAnims();
- if (car->bIsBus)
- bRenderPedInCar = false;
+ if (!found)
+ return false;
- bChangedSeat = true;
+ CVector effectFrontLocal = Multiply3x3(*objMat, effect->attractor.dir);
+ float angleToFace = CGeneral::GetRadianAngleBetweenPoints(effectFrontLocal.x, effectFrontLocal.y, 0.0f, 0.0f);
+ randVal = CGeneral::GetRandomNumber() % 256;
+ if (randVal <= m_randomSeed % 256) {
+ m_standardTimer = CTimer::GetTimeInMilliseconds() + 2000;
+ SetLookFlag(angleToFace, true);
+ SetLookTimer(1000);
+ return false;
+ }
+
+ CVector2D effectPos = *objMat * effect->pos;
+ switch (effect->attractor.type) {
+ case ATTRACTORTYPE_ICECREAM:
+ SetInvestigateEvent(EVENT_ICECREAM, effectPos, 0.1f, 15000, angleToFace);
+ break;
+ case ATTRACTORTYPE_STARE:
+ SetInvestigateEvent(EVENT_SHOPSTALL, effectPos, 1.0f,
+ CGeneral::GetRandomNumberInRange(8000, 10 * effect->attractor.probability + 8500),
+ angleToFace);
+ break;
+ default:
+ return true;
+ }
+ return true;
}
void
-CPed::SetObjective(eObjective newObj, CVector dest)
+CPed::SetWaitState(eWaitState state, void *time)
{
- if (DyingOrDead())
- return;
+ AnimationId waitAnim = NUM_ANIMS;
+ CAnimBlendAssociation *animAssoc;
- if (m_prevObjective != OBJECTIVE_NONE && m_prevObjective == newObj)
+ if (!IsPedInControl())
return;
- SetObjectiveTimer(0);
- if (m_objective == newObj) {
- if (newObj == OBJECTIVE_GOTO_AREA_ANY_MEANS || newObj == OBJECTIVE_GOTO_AREA_ON_FOOT || newObj == OBJECTIVE_RUN_TO_AREA) {
- if (m_nextRoutePointPos == dest)
- return;
- } else if (newObj == OBJECTIVE_GUARD_SPOT) {
- if (m_vecSeekPosEx == dest)
- return;
- }
- }
+ if (state != m_nWaitState)
+ FinishedWaitCB(nil, this);
-#ifdef VC_PED_PORTS
- ClearPointGunAt();
-#endif
- bObjectiveCompleted = false;
- switch (newObj) {
- case OBJECTIVE_GUARD_SPOT:
- m_vecSeekPosEx = dest;
- m_distanceToCountSeekDoneEx = 5.0f;
+ switch (state) {
+ case WAITSTATE_TRAFFIC_LIGHTS:
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 500;
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_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 WAITSTATE_CROSS_ROAD:
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 1000;
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_HBHB, 4.0f);
break;
- case OBJECTIVE_GOTO_AREA_ANY_MEANS:
- case OBJECTIVE_GOTO_AREA_ON_FOOT:
- bIsRunning = false;
- 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;
+ case WAITSTATE_CROSS_ROAD_LOOK:
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_ROAD_CROSS, 8.0f);
+
+ if (time)
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + *(int*)time;
+ else
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(2000,5000);
+
break;
- case OBJECTIVE_RUN_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;
+ case WAITSTATE_LOOK_PED:
+ case WAITSTATE_LOOK_SHOP:
+ case WAITSTATE_LOOK_ACCIDENT:
+ case WAITSTATE_FACEOFF_GANG:
break;
- default: break;
- }
+ case WAITSTATE_DOUBLEBACK:
+ m_headingRate = 0.0f;
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 3500;
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_HBHB, 4.0f);
+#ifdef FIX_BUGS
+ animAssoc->SetFinishCallback(RestoreHeadingRateCB, this);
+#endif
+ break;
+ case WAITSTATE_HITWALL:
+ m_headingRate = 2.0f;
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 5000;
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_HIT_WALL, 16.0f);
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ animAssoc->flags |= ASSOC_FADEOUTWHENDONE;
+ animAssoc->SetDeleteCallback(FinishedWaitCB, this);
- if (IsTemporaryObjective(m_objective)) {
- m_prevObjective = newObj;
- } else {
- if (m_objective != newObj)
- SetStoredObjective();
+ if (m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER && CharCreatedBy == RANDOM_CHAR && m_nPedState == PED_SEEK_CAR) {
+ ClearObjective();
+ RestorePreviousState();
+ m_hitRecoverTimer = CTimer::GetTimeInMilliseconds() + 30000;
+ }
+ break;
+ case WAITSTATE_TURN180:
+ m_headingRate = 0.0f;
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 5000;
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_TURN_180, 4.0f);
+ animAssoc->SetFinishCallback(FinishedWaitCB, this);
+ animAssoc->SetDeleteCallback(RestoreHeadingRateCB, this);
+ break;
+ case WAITSTATE_SURPRISE:
+ m_headingRate = 0.0f;
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 2000;
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_HIT_WALL, 4.0f);
+ animAssoc->SetFinishCallback(FinishedWaitCB, this);
+ break;
+ case WAITSTATE_STUCK:
+ SetMoveState(PEDMOVE_STILL);
+ SetMoveAnim();
+ m_headingRate = 0.0f;
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 5000;
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_TIRED, 4.0f);
+#ifdef FIX_BUGS
+ animAssoc->SetFinishCallback(RestoreHeadingRateCB, this);
+#endif
- m_objective = newObj;
+ if (m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER && CharCreatedBy == RANDOM_CHAR && m_nPedState == PED_SEEK_CAR) {
+ ClearObjective();
+ RestorePreviousState();
+ m_hitRecoverTimer = CTimer::GetTimeInMilliseconds() + 30000;
+ }
+ break;
+ case WAITSTATE_LOOK_ABOUT:
+ SetMoveState(PEDMOVE_STILL);
+ SetMoveAnim();
+ m_headingRate = 0.0f;
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 5000;
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_HBHB, 4.0f);
+#ifdef FIX_BUGS
+ animAssoc->SetFinishCallback(RestoreHeadingRateCB, this);
+#endif
+
+ break;
+ case WAITSTATE_PLAYANIM_COWER:
+ waitAnim = ANIM_HANDSCOWER;
+ case WAITSTATE_PLAYANIM_HANDSUP:
+ if (waitAnim == NUM_ANIMS)
+ waitAnim = ANIM_HANDSUP;
+ case WAITSTATE_PLAYANIM_HANDSCOWER:
+ if (waitAnim == NUM_ANIMS)
+ waitAnim = ANIM_HANDSCOWER;
+ m_headingRate = 0.0f;
+ if (time)
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + *(int*)time;
+ else
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 3000;
+
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, waitAnim, 4.0f);
+ animAssoc->SetDeleteCallback(FinishedWaitCB, this);
+ break;
+ case WAITSTATE_PLAYANIM_DUCK:
+ waitAnim = ANIM_DUCK_DOWN;
+ case WAITSTATE_PLAYANIM_TAXI:
+ if (waitAnim == NUM_ANIMS)
+ waitAnim = ANIM_IDLE_TAXI;
+ case WAITSTATE_PLAYANIM_CHAT:
+ if (waitAnim == NUM_ANIMS)
+ waitAnim = ANIM_IDLE_CHAT;
+ if (time)
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + *(int*)time;
+ else
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 3000;
+
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, waitAnim, 4.0f);
+ animAssoc->flags &= ~ASSOC_FADEOUTWHENDONE;
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ animAssoc->SetDeleteCallback(FinishedWaitCB, this);
+ break;
+ case WAITSTATE_FINISH_FLEE:
+ SetMoveState(PEDMOVE_STILL);
+ SetMoveAnim();
+ m_headingRate = 0.0f;
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 2500;
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_TIRED, 4.0f);
+#ifdef FIX_BUGS
+ animAssoc->SetFinishCallback(RestoreHeadingRateCB, this);
+#endif
+ break;
+ default:
+ m_nWaitState = WAITSTATE_FALSE;
+ RestoreHeadingRate();
+ return;
}
+ m_nWaitState = state;
}
void
-CPed::SetMoveAnim(void)
+CPed::Wait(void)
{
- if (m_nStoredMoveState == m_nMoveState || !IsPedInControl())
- return;
+ AnimationId mustHaveAnim = NUM_ANIMS;
+ CAnimBlendAssociation *animAssoc;
+ CPed *pedWeLook;
- if (m_nMoveState == PEDMOVE_NONE) {
- m_nStoredMoveState = PEDMOVE_NONE;
+ if (DyingOrDead()) {
+ m_nWaitState = WAITSTATE_FALSE;
+ RestoreHeadingRate();
return;
}
- AssocGroupId animGroupToUse;
- if (m_leader && m_leader->IsPlayer())
- animGroupToUse = ASSOCGRP_PLAYER;
- else
- animGroupToUse = m_animGroup;
+ switch (m_nWaitState) {
- CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_BLOCK);
- if (!animAssoc) {
- CAnimBlendAssociation *fightIdleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FIGHT_IDLE);
- animAssoc = fightIdleAssoc;
- if (fightIdleAssoc && m_nPedState == PED_FIGHT)
- return;
+ case WAITSTATE_TRAFFIC_LIGHTS:
+ if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
+ if (CTrafficLights::LightForPeds() == PED_LIGHTS_WALK) {
+ m_nWaitState = WAITSTATE_FALSE;
+ SetMoveState(PEDMOVE_WALK);
+ }
+ }
+ break;
- if (fightIdleAssoc) {
- CAnimBlendAssociation *idleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE);
- if (!idleAssoc || idleAssoc->blendDelta <= 0.0f) {
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- animAssoc = CAnimManager::BlendAnimation(GetClump(), animGroupToUse, ANIM_IDLE_STANCE, 8.0f);
+ case WAITSTATE_CROSS_ROAD:
+ if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
+ if (CGeneral::GetRandomNumber() & 1 || !m_nWaitTimer)
+ m_nWaitState = WAITSTATE_FALSE;
+ else
+ SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, nil);
+
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_HBHB);
+ if (animAssoc) {
+ animAssoc->blendDelta = -8.0f;
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ }
}
- }
- }
- if (!animAssoc) {
- animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_TIRED);
- if (animAssoc)
- if (m_nWaitState == WAITSTATE_STUCK || m_nWaitState == WAITSTATE_FINISH_FLEE)
- return;
+ break;
- if (animAssoc) {
- CAnimBlendAssociation *idleAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE);
- if (!idleAssoc || idleAssoc->blendDelta <= 0.0f) {
- animAssoc->flags |= ASSOC_DELETEFADEDOUT;
- animAssoc = CAnimManager::BlendAnimation(GetClump(), animGroupToUse, ANIM_IDLE_STANCE, 4.0f);
+ case WAITSTATE_CROSS_ROAD_LOOK:
+ if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
+ m_nWaitState = WAITSTATE_FALSE;
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_ROAD_CROSS);
+ if (animAssoc) {
+ animAssoc->blendDelta = -8.0f;
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ }
}
- }
- }
- if (!animAssoc) {
- m_nStoredMoveState = m_nMoveState;
- if (m_nMoveState == PEDMOVE_WALK || m_nMoveState == PEDMOVE_RUN || m_nMoveState == PEDMOVE_SPRINT) {
- for (CAnimBlendAssociation *assoc = RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_PARTIAL);
- assoc; assoc = RpAnimBlendGetNextAssociation(assoc, ASSOC_PARTIAL)) {
+ break;
- if (!(assoc->flags & ASSOC_FADEOUTWHENDONE)) {
- assoc->blendDelta = -2.0f;
- assoc->flags |= ASSOC_DELETEFADEDOUT;
+ case WAITSTATE_DOUBLEBACK:
+ if (CTimer::GetTimeInMilliseconds() <= m_nWaitTimer) {
+ uint32 timeLeft = m_nWaitTimer - CTimer::GetTimeInMilliseconds();
+ if (timeLeft < 2500 && timeLeft > 2000) {
+ m_nWaitTimer -= 500;
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_XPRESS_SCRATCH, 4.0f);
}
+ } else {
+ m_nWaitState = WAITSTATE_FALSE;
+ SetMoveState(PEDMOVE_WALK);
}
+ break;
- ClearAimFlag();
- ClearLookFlag();
- }
+ case WAITSTATE_HITWALL:
+ if (CTimer::GetTimeInMilliseconds() <= m_nWaitTimer) {
+ if (m_collidingThingTimer > CTimer::GetTimeInMilliseconds()) {
+ m_collidingThingTimer = CTimer::GetTimeInMilliseconds() + 2500;
+ }
+ } else {
+ m_nWaitState = WAITSTATE_FALSE;
+ }
+ break;
- switch (m_nMoveState) {
- case PEDMOVE_STILL:
- animAssoc = CAnimManager::BlendAnimation(GetClump(), animGroupToUse, ANIM_IDLE_STANCE, 4.0f);
- break;
- case PEDMOVE_WALK:
- animAssoc = CAnimManager::BlendAnimation(GetClump(), animGroupToUse, ANIM_WALK, 1.0f);
- break;
- case PEDMOVE_RUN:
- if (m_nPedState == PED_FLEE_ENTITY) {
- animAssoc = CAnimManager::BlendAnimation(GetClump(), animGroupToUse, ANIM_RUN, 3.0f);
+ case WAITSTATE_TURN180:
+ if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
+ m_nWaitState = WAITSTATE_FALSE;
+ SetMoveState(PEDMOVE_WALK);
+ m_fRotationCur = m_fRotationCur + PI;
+ if (m_nPedState == PED_INVESTIGATE)
+ ClearInvestigateEvent();
+ }
+
+ if (m_collidingThingTimer > CTimer::GetTimeInMilliseconds()) {
+ m_collidingThingTimer = CTimer::GetTimeInMilliseconds() + 2500;
+ }
+ break;
+
+ case WAITSTATE_SURPRISE:
+ if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
+ if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_HIT_WALL)) {
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_XPRESS_SCRATCH, 4.0f);
+ animAssoc->SetFinishCallback(FinishedWaitCB, this);
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 5000;
} else {
- animAssoc = CAnimManager::BlendAnimation(GetClump(), animGroupToUse, ANIM_RUN, 1.0f);
+ m_nWaitState = WAITSTATE_FALSE;
}
+ }
+ break;
+
+ case WAITSTATE_STUCK:
+ if (CTimer::GetTimeInMilliseconds() <= m_nWaitTimer)
break;
- case PEDMOVE_SPRINT:
- animAssoc = CAnimManager::BlendAnimation(GetClump(), animGroupToUse, ANIM_SPRINT, 1.0f);
- break;
- default:
- break;
- }
- if (animAssoc) {
- if (m_leader) {
- CAnimBlendAssociation *walkAssoc = RpAnimBlendClumpGetAssociation(m_leader->GetClump(), ANIM_WALK);
- if (!walkAssoc)
- walkAssoc = RpAnimBlendClumpGetAssociation(m_leader->GetClump(), ANIM_RUN);
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_TIRED);
- if (!walkAssoc)
- walkAssoc = RpAnimBlendClumpGetAssociation(m_leader->GetClump(), ANIM_SPRINT);
+ if (!animAssoc)
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_TURN_180);
+ if (!animAssoc)
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_XPRESS_SCRATCH);
+ if (!animAssoc)
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_ROAD_CROSS);
- if (walkAssoc) {
- animAssoc->speed = walkAssoc->speed;
+ if (animAssoc) {
+ if (animAssoc->IsPartial()) {
+ animAssoc->blendDelta = -8.0f;
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
} else {
- if (CharCreatedBy == MISSION_CHAR)
- animAssoc->speed = 1.0f;
- else
- animAssoc->speed = 1.2f - m_randomSeed * 0.4f / MYRAND_MAX;
-
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 4.0f);
+ }
+
+ if (animAssoc->animId == ANIM_TURN_180) {
+ m_fRotationCur = CGeneral::LimitRadianAngle(PI + m_fRotationCur);
+ m_nWaitState = WAITSTATE_FALSE;
+ SetMoveState(PEDMOVE_WALK);
+ m_nStoredMoveState = PEDMOVE_NONE;
+ m_panicCounter = 0;
+ return;
}
- } else {
- if (CharCreatedBy == MISSION_CHAR)
- animAssoc->speed = 1.0f;
- else
- animAssoc->speed = 1.2f - m_randomSeed * 0.4f / MYRAND_MAX;
}
- }
- }
-}
-void
-CPed::SetEnterCar_AllClear(CVehicle *car, uint32 doorNode, uint32 doorFlag)
-{
- float zDiff = 0.0f;
- RemoveWeaponWhenEnteringVehicle();
- car->m_nGettingInFlags |= doorFlag;
- bVehEnterDoorIsBlocked = false;
- if (m_nPedState != PED_SEEK_CAR && m_nPedState != PED_SEEK_IN_BOAT)
- SetStoredState();
+ AnimationId animToPlay;
- m_pSeekTarget = car;
- m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget);
- m_vehEnterType = doorNode;
- m_nPedState = PED_ENTER_CAR;
- if (m_vehEnterType == CAR_DOOR_RF && m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER && car->m_vehType != VEHICLE_TYPE_BIKE) {
- car->bIsBeingCarJacked = true;
- }
+ switch (CGeneral::GetRandomNumber() & 3) {
+ case 0:
+ animToPlay = ANIM_ROAD_CROSS;
+ break;
+ case 1:
+ animToPlay = ANIM_IDLE_TIRED;
+ break;
+ case 2:
+ animToPlay = ANIM_XPRESS_SCRATCH;
+ break;
+ case 3:
+ animToPlay = ANIM_TURN_180;
+ break;
+ default:
+ break;
+ }
- m_pMyVehicle = (CVehicle*)m_pSeekTarget;
- m_pMyVehicle->RegisterReference((CEntity**) &m_pMyVehicle);
- ((CVehicle*)m_pSeekTarget)->m_nNumGettingIn++;
- bUsesCollision = false;
- CVector doorOpenPos = GetPositionToOpenCarDoor(car, m_vehEnterType);
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animToPlay, 4.0f);
- // Because buses have stairs
- if (!m_pMyVehicle->bIsBus)
- zDiff = Max(0.0f, doorOpenPos.z - GetPosition().z);
+ if (animToPlay == ANIM_TURN_180)
+ animAssoc->SetFinishCallback(FinishedWaitCB, this);
- m_vecOffsetSeek = doorOpenPos - GetPosition();
- m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 600;
- if (car->IsBoat()) {
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(1500, 5000);
+ break;
+
+ case WAITSTATE_LOOK_ABOUT:
+ if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
+ m_nWaitState = WAITSTATE_FALSE;
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_HBHB);
+ if (animAssoc) {
+ animAssoc->blendDelta = -8.0f;
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ }
+ }
+ break;
+
+ case WAITSTATE_PLAYANIM_HANDSUP:
+ mustHaveAnim = ANIM_HANDSUP;
+
+ case WAITSTATE_PLAYANIM_HANDSCOWER:
+ if (mustHaveAnim == NUM_ANIMS)
+ mustHaveAnim = ANIM_HANDSCOWER;
+
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), mustHaveAnim);
+ pedWeLook = (CPed*) m_pLookTarget;
+
+ if ((!m_pLookTarget || !m_pLookTarget->IsPed() || pedWeLook->m_pPointGunAt)
+ && m_nPedState != PED_FLEE_ENTITY
+ && m_nPedState != PED_ATTACK
+ && CTimer::GetTimeInMilliseconds() <= m_nWaitTimer
+ && animAssoc) {
+
+ TurnBody();
+ } else {
+ m_nWaitState = WAITSTATE_FALSE;
+ m_nWaitTimer = 0;
+ if (m_pLookTarget && m_pLookTarget->IsPed()) {
+
+ if (m_nPedState != PED_FLEE_ENTITY && m_nPedState != PED_ATTACK) {
+
+ if (m_pedStats->m_fear <= 100 - pedWeLook->m_pedStats->m_temper) {
+
+ if (GetWeapon()->IsTypeMelee()) {
#ifdef VC_PED_PORTS
- // VC checks for handling flag, but we can't do that
- if(car->GetModelIndex() == MI_SPEEDER)
- m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_SIT, 100.0f);
- else
- m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_BOAT, 100.0f);
+ if(m_pedStats->m_flags & STAT_GUN_PANIC) {
+#endif
+ SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, m_pLookTarget);
+ if (m_nPedState == PED_FLEE_ENTITY || m_nPedState == PED_FLEE_POS) {
- PedSetInCarCB(nil, this);
- bVehExitWillBeInstant = true;
-#else
+ bUsePedNodeSeek = true;
+ m_pNextPathNode = nil;
+ }
+ if (m_nMoveState != PEDMOVE_RUN)
+ SetMoveState(PEDMOVE_WALK);
-#ifndef FIX_BUGS
- m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_BOAT, 100.0f);
-#else
- m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, car->GetDriverAnim(), 100.0f);
+ if (m_nPedType != PEDTYPE_COP) {
+ ProcessObjective();
+ SetMoveState(PEDMOVE_WALK);
+ }
+#ifdef VC_PED_PORTS
+ } else {
+ SetObjective(OBJECTIVE_NONE);
+ SetWanderPath(CGeneral::GetRandomNumberInRange(0.0f, 8.0f));
+ }
#endif
+ } else {
+ SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, m_pLookTarget);
+ SetObjectiveTimer(20000);
+ }
+ } else {
+ SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, m_pLookTarget);
+ if (m_nPedState == PED_FLEE_ENTITY || m_nPedState == PED_FLEE_POS)
+ {
+ bUsePedNodeSeek = true;
+ m_pNextPathNode = nil;
+ }
+ SetMoveState(PEDMOVE_RUN);
+ Say(SOUND_PED_FLEE_RUN);
+ }
+ }
+ }
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), mustHaveAnim);
+ if (animAssoc) {
+ animAssoc->blendDelta = -4.0f;
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ }
+ }
+ break;
+ case WAITSTATE_PLAYANIM_COWER:
+ mustHaveAnim = ANIM_HANDSCOWER;
+
+ case WAITSTATE_PLAYANIM_DUCK:
+ if (mustHaveAnim == NUM_ANIMS)
+ mustHaveAnim = ANIM_DUCK_DOWN;
+
+ case WAITSTATE_PLAYANIM_TAXI:
+ if (mustHaveAnim == NUM_ANIMS)
+ mustHaveAnim = ANIM_IDLE_TAXI;
- m_pVehicleAnim->SetFinishCallback(PedSetInCarCB, this);
+ case WAITSTATE_PLAYANIM_CHAT:
+ if (mustHaveAnim == NUM_ANIMS)
+ mustHaveAnim = ANIM_IDLE_CHAT;
+
+ if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), mustHaveAnim);
+ if (animAssoc) {
+ animAssoc->blendDelta = -4.0f;
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ }
+ m_nWaitState = WAITSTATE_FALSE;
+ }
+#ifdef VC_PED_PORTS
+ else if (m_nWaitState == WAITSTATE_PLAYANIM_TAXI) {
+ if (m_pedInObjective) {
+ if (m_objective == OBJECTIVE_GOTO_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT) {
+
+ // VC also calls CleanUpOldReference here for old LookTarget.
+ m_pLookTarget = m_pedInObjective;
+ m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);
+ TurnBody();
+ }
+ }
+ }
#endif
- if (IsPlayer())
- CWaterLevel::AllocateBoatWakeArray();
- } else {
- if (zDiff > 4.4f) {
- if (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR)
- m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ALIGNHI_RHS, 4.0f);
- else
- m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ALIGNHI_LHS, 4.0f);
+ break;
- } else {
- if (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR)
- m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ALIGN_RHS, 4.0f);
- else
- m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ALIGN_LHS, 4.0f);
- }
- m_pVehicleAnim->SetFinishCallback(PedAnimAlignCB, this);
- car->AutoPilot.m_nCruiseSpeed = 0;
+ case WAITSTATE_FINISH_FLEE:
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_TIRED);
+ if (animAssoc) {
+ if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 4.0f);
+ int timer = 2000;
+ m_nWaitState = WAITSTATE_FALSE;
+ SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, &timer);
+ }
+ } else {
+ m_nWaitState = WAITSTATE_FALSE;
+ }
+ break;
+ default:
+ break;
}
+
+ if(!m_nWaitState)
+ RestoreHeadingRate();
}
void
-CPed::WanderPath(void)
+CPed::FinishedWaitCB(CAnimBlendAssociation *animAssoc, void *arg)
{
- if (!m_pNextPathNode) {
- printf("THIS SHOULDN@T HAPPEN TOO OFTEN\n");
- SetIdle();
+ CPed *ped = (CPed*)arg;
+
+ ped->m_nWaitTimer = 0;
+ ped->RestoreHeadingRate();
+ ped->Wait();
+}
+
+void
+CPed::RestoreHeadingRate(void)
+{
+ m_headingRate = m_pedStats->m_headingChangeRate;
+}
+
+void
+CPed::RestoreHeadingRateCB(CAnimBlendAssociation *assoc, void *arg)
+{
+ ((CPed*)arg)->m_headingRate = ((CPed*)arg)->m_pedStats->m_headingChangeRate;
+}
+
+void
+CPed::FlagToDestroyWhenNextProcessed(void)
+{
+ bRemoveFromWorld = true;
+ if (!InVehicle())
return;
+ if (m_pMyVehicle->pDriver == this){
+ m_pMyVehicle->pDriver = nil;
+ if (IsPlayer() && m_pMyVehicle->GetStatus() != STATUS_WRECKED)
+ m_pMyVehicle->SetStatus(STATUS_ABANDONED);
+ }else{
+ m_pMyVehicle->RemovePassenger(this);
}
- if (m_nWaitState == WAITSTATE_FALSE) {
- if (m_nMoveState == PEDMOVE_STILL || m_nMoveState == PEDMOVE_NONE)
- SetMoveState(PEDMOVE_WALK);
- }
- m_vecSeekPos = m_pNextPathNode->GetPosition();
- m_vecSeekPos.z += 1.0f;
+ bInVehicle = false;
+ m_pMyVehicle = nil;
+ if (CharCreatedBy == MISSION_CHAR)
+ m_nPedState = PED_DEAD;
+ else
+ m_nPedState = PED_NONE;
+ m_pVehicleAnim = nil;
+}
- // Only returns true when ped is stuck(not stopped) I think, then we should assign new direction or wait state to him.
- if (!Seek())
+void
+CPed::SetSolicit(uint32 time)
+{
+ if (m_nPedState == PED_SOLICIT || !IsPedInControl() || !m_carInObjective)
return;
- CPathNode *previousLastNode = m_pLastPathNode;
- uint8 randVal = (m_randomSeed + 3 * CTimer::GetFrameCounter()) % 100;
+ if (CharCreatedBy != MISSION_CHAR && m_carInObjective->m_nNumGettingIn == 0
+ && CTimer::GetTimeInMilliseconds() < m_objectiveTimer) {
+ if (m_vehEnterType == CAR_DOOR_LF) {
+ m_fRotationDest = m_carInObjective->GetForward().Heading() - HALFPI;
+ } else {
+ m_fRotationDest = m_carInObjective->GetForward().Heading() + HALFPI;
+ }
- // We don't prefer 180-degree turns in normal situations
- uint8 dirWeWouldntPrefer = m_nPathDir;
- if (dirWeWouldntPrefer <= 3)
- dirWeWouldntPrefer += 4;
- else
- dirWeWouldntPrefer -= 4;
+ if (Abs(m_fRotationDest - m_fRotationCur) < HALFPI) {
+ m_standardTimer = CTimer::GetTimeInMilliseconds() + time;
- CPathNode *nodeWeWouldntPrefer = nil;
- uint8 dirToSet = 9; // means undefined
- uint8 dirWeWouldntPrefer2 = 9; // means undefined
- if (randVal <= 90) {
- if (randVal > 80) {
- m_nPathDir += 2;
- m_nPathDir %= 8;
+ if(!m_carInObjective->bIsVan && !m_carInObjective->bIsBus)
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_HOOKERTALK, 4.0f);
+
+ m_nPedState = PED_SOLICIT;
}
- } else {
- m_nPathDir -= 2;
- if (m_nPathDir < 0)
- m_nPathDir += 8;
}
+}
- m_pLastPathNode = m_pNextPathNode;
- ThePaths.FindNextNodeWandering(PATH_PED, GetPosition(), &m_pLastPathNode, &m_pNextPathNode,
- m_nPathDir, &dirToSet);
+void
+CPed::Solicit(void)
+{
+ if (m_standardTimer >= CTimer::GetTimeInMilliseconds() && m_carInObjective) {
+ CVector doorPos = GetPositionToOpenCarDoor(m_carInObjective, m_vehEnterType, 0.0f);
+ SetMoveState(PEDMOVE_STILL);
- uint8 tryCount = 0;
+ // Game uses GetAngleBetweenPoints and converts it to radian
+ m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(
+ doorPos.x, doorPos.y,
+ GetPosition().x, GetPosition().y);
- // NB: SetWanderPath checks for m_nPathDir == dirToStartWith, this one checks for tryCount > 7
- while (!m_pNextPathNode) {
- tryCount++;
- m_nPathDir = (m_nPathDir + 1) % 8;
+ if (m_fRotationDest < 0.0f) {
+ m_fRotationDest = m_fRotationDest + TWOPI;
+ } else if (m_fRotationDest > TWOPI) {
+ m_fRotationDest = m_fRotationDest - TWOPI;
+ }
- // We're at where we started and couldn't find any node
- if (tryCount > 7) {
- if (!nodeWeWouldntPrefer) {
- ClearAll();
- SetIdle();
- // Probably this text carried over here after copy-pasting this loop from early version of SetWanderPath.
- Error("Can't find valid path node, SetWanderPath, Ped.cpp");
- return;
- }
- m_pNextPathNode = nodeWeWouldntPrefer;
- dirToSet = dirWeWouldntPrefer2;
- } else {
- ThePaths.FindNextNodeWandering(PATH_PED, GetPosition(), &m_pLastPathNode, &m_pNextPathNode,
- m_nPathDir, &dirToSet);
- if (m_pNextPathNode) {
- if (dirToSet == dirWeWouldntPrefer) {
- nodeWeWouldntPrefer = m_pNextPathNode;
- dirWeWouldntPrefer2 = dirToSet;
- m_pNextPathNode = nil;
- }
- }
+ if ((GetPosition() - doorPos).MagnitudeSqr() <= 1.0f)
+ return;
+ CAnimBlendAssociation *talkAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_HOOKERTALK);
+ if (talkAssoc) {
+ talkAssoc->blendDelta = -1000.0f;
+ talkAssoc->flags |= ASSOC_DELETEFADEDOUT;
}
+ RestorePreviousState();
+ RestorePreviousObjective();
+ SetObjectiveTimer(10000);
+ } else if (!m_carInObjective) {
+ RestorePreviousState();
+ RestorePreviousObjective();
+ SetObjectiveTimer(10000);
+ } else if (CWorld::Players[CWorld::PlayerInFocus].m_nMoney <= 100) {
+ m_carInObjective = nil;
+ } else {
+ m_pVehicleAnim = nil;
+ SetLeader(m_carInObjective->pDriver);
}
+}
- m_nPathDir = dirToSet;
- if (m_pLastPathNode == m_pNextPathNode) {
- m_pNextPathNode = previousLastNode;
- SetWaitState(WAITSTATE_DOUBLEBACK, nil);
- Say(SOUND_PED_WAIT_DOUBLEBACK);
- } else if (ThePaths.TestForPedTrafficLight(m_pLastPathNode, m_pNextPathNode)) {
- SetWaitState(WAITSTATE_TRAFFIC_LIGHTS, nil);
- } else if (ThePaths.TestCrossesRoad(m_pLastPathNode, m_pNextPathNode)) {
- SetWaitState(WAITSTATE_CROSS_ROAD, nil);
- } else if (m_pNextPathNode == previousLastNode) {
- SetWaitState(WAITSTATE_DOUBLEBACK, nil);
- Say(SOUND_PED_WAIT_DOUBLEBACK);
+void
+CPed::SetBuyIceCream(void)
+{
+ if (m_nPedState == PED_BUY_ICECREAM || !IsPedInControl())
+ return;
+
+ if (!m_carInObjective)
+ return;
+
+#ifdef FIX_ICECREAM
+
+ // Simulating BuyIceCream
+ CPed* driver = m_carInObjective->pDriver;
+ if (driver) {
+ m_nPedState = PED_BUY_ICECREAM;
+ bFindNewNodeAfterStateRestore = true;
+ SetObjectiveTimer(8000);
+ SetChat(driver, 8000);
+ driver->SetChat(this, 8000);
+ return;
+ }
+#endif
+
+ // Side of the Ice Cream van
+ m_fRotationDest = m_carInObjective->GetForward().Heading() - HALFPI;
+
+ if (Abs(m_fRotationDest - m_fRotationCur) < HALFPI) {
+ m_standardTimer = CTimer::GetTimeInMilliseconds() + 3000;
+ m_nPedState = PED_BUY_ICECREAM;
}
}
bool
-CPed::WarpPedToNearEntityOffScreen(CEntity *warpTo)
+CPed::PossiblyFindBetterPosToSeekCar(CVector *pos, CVehicle *veh)
{
- bool teleported = false;
- if (GetIsOnScreen() || m_leaveCarTimer > CTimer::GetTimeInMilliseconds())
- return false;
+ bool foundIt = false;
- CVector warpToPos = warpTo->GetPosition();
- CVector distVec = warpToPos - GetPosition();
- float halfOfDist = distVec.Magnitude() * 0.5f;
- CVector halfNormalizedDist = distVec / halfOfDist;
+ CVector helperPos = GetPosition();
+ helperPos.z = pos->z - 0.5f;
- CVector appropriatePos = GetPosition();
- CVector zCorrectedPos = appropriatePos;
- int tryCount = Min(10, halfOfDist);
- for (int i = 0; i < tryCount; ++i) {
- appropriatePos += halfNormalizedDist;
- CPedPlacement::FindZCoorForPed(&zCorrectedPos);
+ CVector foundPos = *pos;
+ foundPos.z -= 0.5f;
- if (Abs(zCorrectedPos.z - warpToPos.z) >= 3.0f && Abs(zCorrectedPos.z - appropriatePos.z) >= 3.0f)
- continue;
+ // If there is another car between target car and us.
+ if (CWorld::TestSphereAgainstWorld((foundPos + helperPos) / 2.0f, 0.25f, veh, false, true, false, false, false, false)) {
+
+ CColModel *vehCol = veh->GetModelInfo()->GetColModel();
+ CVector *colMin = &vehCol->boundingBox.min;
+ CVector *colMax = &vehCol->boundingBox.max;
+
+ CVector leftRearPos = CVector(colMin->x - 0.5f, colMin->y - 0.5f, 0.0f);
+ CVector rightRearPos = CVector(0.5f + colMax->x, colMin->y - 0.5f, 0.0f);
+ CVector leftFrontPos = CVector(colMin->x - 0.5f, 0.5f + colMax->y, 0.0f);
+ CVector rightFrontPos = CVector(0.5f + colMax->x, 0.5f + colMax->y, 0.0f);
+
+ leftRearPos = veh->GetMatrix() * leftRearPos;
+ rightRearPos = veh->GetMatrix() * rightRearPos;
+ leftFrontPos = veh->GetMatrix() * leftFrontPos;
+ rightFrontPos = veh->GetMatrix() * rightFrontPos;
+
+ // Makes helperPos veh-ped distance vector.
+ helperPos -= veh->GetPosition();
+
+ // ?!? I think it's absurd to use this unless another function like SeekCar finds next pos. with it and we're trying to simulate it's behaviour.
+ // On every run it returns another pos. for ped, with same distance to the veh.
+ // Sequence of positions are not guaranteed, it depends on global pos. (So sometimes it returns positions to make ped draw circle, sometimes don't)
+ helperPos = veh->GetMatrix() * helperPos;
+
+ float vehForwardHeading = veh->GetForward().Heading();
+
+ // I'm absolutely not sure about these namings.
+ // NTVF = needed turn if we're looking to vehicle front and wanna look to...
+
+ float potentialLrHeading = Atan2(leftRearPos.x - helperPos.x, leftRearPos.y - helperPos.y);
+ float NTVF_LR = CGeneral::LimitRadianAngle(potentialLrHeading - vehForwardHeading);
+
+ float potentialRrHeading = Atan2(rightRearPos.x - helperPos.x, rightRearPos.y - helperPos.y);
+ float NTVF_RR = CGeneral::LimitRadianAngle(potentialRrHeading - vehForwardHeading);
+
+ float potentialLfHeading = Atan2(leftFrontPos.x - helperPos.x, leftFrontPos.y - helperPos.y);
+ float NTVF_LF = CGeneral::LimitRadianAngle(potentialLfHeading - vehForwardHeading);
+
+ float potentialRfHeading = Atan2(rightFrontPos.x - helperPos.x, rightFrontPos.y - helperPos.y);
+ float NTVF_RF = CGeneral::LimitRadianAngle(potentialRfHeading - vehForwardHeading);
+
+ bool canHeadToLr = NTVF_LR <= -PI || NTVF_LR >= -HALFPI;
+
+ bool canHeadToRr = NTVF_RR <= HALFPI || NTVF_RR >= PI;
+
+ bool canHeadToLf = NTVF_LF >= 0.0f || NTVF_LF <= -HALFPI;
- 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);
+ bool canHeadToRf = NTVF_RF <= 0.0f || NTVF_RF >= HALFPI;
+
+ // Only order of conditions are different among enterTypes.
+ if (m_vehEnterType == CAR_DOOR_RR) {
+ if (canHeadToRr) {
+ foundPos = rightRearPos;
+ foundIt = true;
+ } else if (canHeadToRf) {
+ foundPos = rightFrontPos;
+ foundIt = true;
+ } else if (canHeadToLr) {
+ foundPos = leftRearPos;
+ foundIt = true;
+ } else if (canHeadToLf) {
+ foundPos = leftFrontPos;
+ foundIt = true;
+ }
+ } else if(m_vehEnterType == CAR_DOOR_RF) {
+ if (canHeadToRf) {
+ foundPos = rightFrontPos;
+ foundIt = true;
+ } else if (canHeadToRr) {
+ foundPos = rightRearPos;
+ foundIt = true;
+ } else if (canHeadToLf) {
+ foundPos = leftFrontPos;
+ foundIt = true;
+ } else if (canHeadToLr) {
+ foundPos = leftRearPos;
+ foundIt = true;
+ }
+ } else if (m_vehEnterType == CAR_DOOR_LF) {
+ if (canHeadToLf) {
+ foundPos = leftFrontPos;
+ foundIt = true;
+ } else if (canHeadToLr) {
+ foundPos = leftRearPos;
+ foundIt = true;
+ } else if (canHeadToRf) {
+ foundPos = rightFrontPos;
+ foundIt = true;
+ } else if (canHeadToRr) {
+ foundPos = rightRearPos;
+ foundIt = true;
+ }
+ } else if (m_vehEnterType == CAR_DOOR_LR) {
+ if (canHeadToLr) {
+ foundPos = leftRearPos;
+ foundIt = true;
+ } else if (canHeadToLf) {
+ foundPos = leftFrontPos;
+ foundIt = true;
+ } else if (canHeadToRr) {
+ foundPos = rightRearPos;
+ foundIt = true;
+ } else if (canHeadToRf) {
+ foundPos = rightFrontPos;
+ foundIt = true;
+ }
}
}
- m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 3000;
- return teleported;
+ if (!foundIt)
+ return false;
+
+ helperPos = GetPosition() - foundPos;
+ helperPos.z = 0.0f;
+ if (helperPos.MagnitudeSqr() <= sq(0.5f))
+ return false;
+
+ pos->x = foundPos.x;
+ pos->y = foundPos.y;
+ return true;
}
-bool
-CPed::WarpPedToNearLeaderOffScreen(void)
+void
+CPed::SetLeader(CEntity *leader)
{
- bool teleported = false;
- if (GetIsOnScreen() || m_leaveCarTimer > CTimer::GetTimeInMilliseconds())
- return false;
+ m_leader = (CPed*)leader;
- CVector warpToPos = m_leader->GetPosition();
- CVector distVec = warpToPos - GetPosition();
- float halfOfDist = distVec.Magnitude() * 0.5f;
- CVector halfNormalizedDist = distVec / halfOfDist;
+ if(m_leader)
+ m_leader->RegisterReference((CEntity **)&m_leader);
+}
- CVector appropriatePos = GetPosition();
- CVector zCorrectedPos = appropriatePos;
- int tryCount = Min(10, halfOfDist);
- for (int i = 0; i < tryCount; ++i) {
- appropriatePos += halfNormalizedDist;
- CPedPlacement::FindZCoorForPed(&zCorrectedPos);
+#ifdef VC_PED_PORTS
+bool
+CPed::CanPedJumpThis(CEntity *unused, CVector *damageNormal)
+{
+ if (m_nSurfaceTouched == SURFACE_WATER)
+ return true;
- if (Abs(zCorrectedPos.z - warpToPos.z) >= 3.0f && Abs(zCorrectedPos.z - appropriatePos.z) >= 3.0f)
- continue;
+ CVector pos = GetPosition();
+ CVector forwardOffset = GetForward();
+ if (damageNormal && damageNormal->z > 0.17f) {
+ if (damageNormal->z > 0.9f)
+ return false;
- 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);
+ CColModel *ourCol = CModelInfo::GetModelInfo(m_modelIndex)->GetColModel();
+ pos.z = ourCol->spheres->center.z - ourCol->spheres->radius * damageNormal->z + pos.z;
+ pos.z = pos.z + 0.05f;
+ float collPower = damageNormal->Magnitude2D();
+ if (damageNormal->z > 0.5f) {
+ CVector invDamageNormal(-damageNormal->x, -damageNormal->y, 0.0f);
+ invDamageNormal *= 1.0f / collPower;
+ CVector estimatedJumpDist = invDamageNormal + collPower * invDamageNormal * ourCol->spheres->radius;
+ forwardOffset = estimatedJumpDist * Min(2.0f / collPower, 4.0f);
+ } else {
+ forwardOffset += collPower * ourCol->spheres->radius * forwardOffset;
}
+ } else {
+ pos.z -= 0.15f;
}
- m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 3000;
- return teleported;
+
+ CVector forwardPos = pos + forwardOffset;
+ return CWorld::GetIsLineOfSightClear(pos, forwardPos, true, false, false, true, false, false, false);
+}
+#else
+bool
+CPed::CanPedJumpThis(CEntity *unused)
+{
+ CVector2D forward(-Sin(m_fRotationCur), Cos(m_fRotationCur));
+ CVector pos = GetPosition();
+ CVector forwardPos(
+ forward.x + pos.x,
+ forward.y + pos.y,
+ pos.z);
+
+ return CWorld::GetIsLineOfSightClear(pos, forwardPos, true, false, false, true, false, false, false);
}
+#endif
void
-CPed::SetCarJack_AllClear(CVehicle *car, uint32 doorNode, uint32 doorFlag)
+CPed::SetJump(void)
{
- RemoveWeaponWhenEnteringVehicle();
- if (m_nPedState != PED_SEEK_CAR)
+ if (!bInVehicle &&
+#if defined VC_PED_PORTS || defined FIX_BUGS
+ m_nPedState != PED_JUMP && !RpAnimBlendClumpGetAssociation(GetClump(), ANIM_JUMP_LAUNCH) &&
+#endif
+ (m_nSurfaceTouched != SURFACE_STEEP_CLIFF || DotProduct(GetForward(), m_vecDamageNormal) >= 0.0f)) {
SetStoredState();
-
- m_pSeekTarget = car;
- m_pSeekTarget->RegisterReference((CEntity**)&m_pSeekTarget);
- m_nPedState = PED_CARJACK;
- car->bIsBeingCarJacked = true;
- m_pMyVehicle = (CVehicle*)m_pSeekTarget;
- m_pMyVehicle->RegisterReference((CEntity**)&m_pMyVehicle);
- ((CVehicle*)m_pSeekTarget)->m_nNumGettingIn++;
-
- Say(m_nPedType == PEDTYPE_COP ? SOUND_PED_ARREST_COP : SOUND_PED_CAR_JACKING);
- CVector carEnterPos;
- carEnterPos = GetPositionToOpenCarDoor(car, m_vehEnterType);
-
- car->m_nGettingInFlags |= doorFlag;
- m_vecOffsetSeek = carEnterPos - GetPosition();
- m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 600;
- float zDiff = Max(0.0f, carEnterPos.z - GetPosition().z);
- bUsesCollision = false;
-
- if (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR)
- m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, zDiff > 4.4f ? ANIM_CAR_ALIGNHI_LHS : ANIM_CAR_ALIGN_LHS, 4.0f);
- else
- m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, zDiff > 4.4f ? ANIM_CAR_ALIGNHI_RHS : ANIM_CAR_ALIGN_RHS, 4.0f);
-
- m_pVehicleAnim->SetFinishCallback(PedAnimAlignCB, this);
+ m_nPedState = PED_JUMP;
+ CAnimBlendAssociation *jumpAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_JUMP_LAUNCH, 8.0f);
+ jumpAssoc->SetFinishCallback(FinishLaunchCB, this);
+ m_fRotationDest = m_fRotationCur;
+ }
}
void
-CPed::SetObjective(eObjective newObj, CVector dest, float safeDist)
+CPed::FinishLaunchCB(CAnimBlendAssociation *animAssoc, void *arg)
{
- if (DyingOrDead())
+ CPed *ped = (CPed*)arg;
+
+ if (ped->m_nPedState != PED_JUMP)
return;
- if (m_prevObjective != OBJECTIVE_NONE && m_prevObjective == newObj)
+ CVector forward(0.15f * ped->GetForward() + ped->GetPosition());
+ forward.z += CModelInfo::GetModelInfo(ped->GetModelIndex())->GetColModel()->spheres->center.z + 0.25f;
+
+ CEntity *obstacle = CWorld::TestSphereAgainstWorld(forward, 0.25f, nil, true, true, false, true, false, false);
+ if (!obstacle) {
+ // Forward of forward
+ forward += 0.15f * ped->GetForward();
+ forward.z += 0.15f;
+ obstacle = CWorld::TestSphereAgainstWorld(forward, 0.25f, nil, true, true, false, true, false, false);
+ }
+
+ if (obstacle) {
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+
+ // ANIM_HIT_WALL in VC (which makes more sense)
+ CAnimBlendAssociation *handsCoverAssoc = CAnimManager::BlendAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_HANDSCOWER, 8.0f);
+ handsCoverAssoc->flags &= ~ASSOC_FADEOUTWHENDONE;
+ handsCoverAssoc->SetFinishCallback(FinishHitHeadCB, ped);
+ ped->bIsLanding = true;
return;
+ }
- SetObjectiveTimer(0);
- if (m_objective == newObj) {
- if (newObj == OBJECTIVE_GOTO_AREA_ANY_MEANS || newObj == OBJECTIVE_GOTO_AREA_ON_FOOT || newObj == OBJECTIVE_RUN_TO_AREA) {
- if (m_nextRoutePointPos == dest && m_distanceToCountSeekDone == safeDist)
- return;
- } else if (newObj == OBJECTIVE_GUARD_SPOT) {
- if (m_vecSeekPosEx == dest && m_distanceToCountSeekDoneEx == safeDist)
- return;
+ float velocityFromAnim = 0.1f;
+ CAnimBlendAssociation *sprintAssoc = RpAnimBlendClumpGetAssociation(ped->GetClump(), ANIM_SPRINT);
+
+ if (sprintAssoc) {
+ velocityFromAnim = 0.05f * sprintAssoc->blendAmount + 0.17f;
+ } else {
+ CAnimBlendAssociation *runAssoc = RpAnimBlendClumpGetAssociation(ped->GetClump(), ANIM_RUN);
+ if (runAssoc) {
+ velocityFromAnim = 0.07f * runAssoc->blendAmount + 0.1f;
}
}
+ if (ped->IsPlayer()
#ifdef VC_PED_PORTS
- ClearPointGunAt();
+ || ped->m_pedInObjective && ped->m_pedInObjective->IsPlayer()
#endif
- bObjectiveCompleted = false;
- if (IsTemporaryObjective(m_objective)) {
- m_prevObjective = newObj;
- } else {
- if (m_objective != newObj)
- SetStoredObjective();
+ )
+ ped->ApplyMoveForce(0.0f, 0.0f, 8.5f);
+ else
+ ped->ApplyMoveForce(0.0f, 0.0f, 4.5f);
+
+ if (sq(velocityFromAnim) > ped->m_vecMoveSpeed.MagnitudeSqr2D()
+#ifdef VC_PED_PORTS
+ || ped->m_pCurrentPhysSurface
+#endif
+ ) {
- m_objective = newObj;
+#ifdef FREE_CAM
+ if (TheCamera.Cams[0].Using3rdPersonMouseCam() && !CCamera::bFreeCam) {
+#else
+ if (TheCamera.Cams[0].Using3rdPersonMouseCam()) {
+#endif
+ float fpsAngle = ped->WorkOutHeadingForMovingFirstPerson(ped->m_fRotationCur);
+ ped->m_vecMoveSpeed.x = -velocityFromAnim * Sin(fpsAngle);
+ ped->m_vecMoveSpeed.y = velocityFromAnim * Cos(fpsAngle);
+ } else {
+ ped->m_vecMoveSpeed.x = -velocityFromAnim * Sin(ped->m_fRotationCur);
+ ped->m_vecMoveSpeed.y = velocityFromAnim * Cos(ped->m_fRotationCur);
+ }
+#ifdef VC_PED_PORTS
+ if (ped->m_pCurrentPhysSurface) {
+ ped->m_vecMoveSpeed.x += ped->m_pCurrentPhysSurface->m_vecMoveSpeed.x;
+ ped->m_vecMoveSpeed.y += ped->m_pCurrentPhysSurface->m_vecMoveSpeed.y;
+ }
+#endif
}
-
- if (newObj == OBJECTIVE_GUARD_SPOT) {
- m_vecSeekPosEx = dest;
- m_distanceToCountSeekDoneEx = safeDist;
- } else if (newObj == OBJECTIVE_GOTO_AREA_ANY_MEANS || newObj == OBJECTIVE_GOTO_AREA_ON_FOOT || newObj == OBJECTIVE_RUN_TO_AREA) {
- m_pNextPathNode = nil;
- m_nextRoutePointPos = dest;
- m_vecSeekPos = m_nextRoutePointPos;
- bUsePedNodeSeek = true;
+
+ ped->bIsStanding = false;
+ ped->bIsInTheAir = true;
+ animAssoc->blendDelta = -1000.0f;
+ CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_JUMP_GLIDE);
+
+ if (ped->bDoBloodyFootprints) {
+ CVector bloodPos(0.0f, 0.0f, 0.0f);
+ ped->TransformToNode(bloodPos, PED_FOOTL);
+
+ bloodPos.z -= 0.1f;
+ bloodPos += 0.2f * ped->GetForward();
+
+ CShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpBloodPoolTex, &bloodPos,
+ 0.26f * ped->GetForward().x,
+ 0.26f * ped->GetForward().y,
+ 0.14f * ped->GetRight().x,
+ 0.14f * ped->GetRight().y,
+ 255, 255, 0, 0, 4.0f, 3000, 1.0f);
+
+ bloodPos = CVector(0.0f, 0.0f, 0.0f);
+ ped->TransformToNode(bloodPos, PED_FOOTR);
+
+ bloodPos.z -= 0.1f;
+ bloodPos += 0.2f * ped->GetForward();
+ CShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpBloodPoolTex, &bloodPos,
+ 0.26f * ped->GetForward().x,
+ 0.26f * ped->GetForward().y,
+ 0.14f * ped->GetRight().x,
+ 0.14f * ped->GetRight().y,
+ 255, 255, 0, 0, 4.0f, 3000, 1.0f);
+
+ if (ped->m_bloodyFootprintCountOrDeathTime <= 40) {
+ ped->m_bloodyFootprintCountOrDeathTime = 0;
+ ped->bDoBloodyFootprints = false;
+ } else {
+ ped->m_bloodyFootprintCountOrDeathTime -= 40;
+ }
}
}
void
-CPed::SetCarJack(CVehicle* car)
+CPed::FinishJumpCB(CAnimBlendAssociation *animAssoc, void *arg)
{
- uint8 doorFlag;
- eDoors door;
- CPed *pedInSeat = nil;
+ CPed *ped = (CPed*)arg;
- if (car->IsBoat())
- return;
+ ped->bResetWalkAnims = true;
+ ped->bIsLanding = false;
- switch (m_vehEnterType) {
- case CAR_DOOR_RF:
- doorFlag = CAR_DOOR_FLAG_RF;
- door = DOOR_FRONT_RIGHT;
- if (car->pPassengers[0]) {
- pedInSeat = car->pPassengers[0];
- } else if (m_nPedType == PEDTYPE_COP) {
- pedInSeat = car->pDriver;
- }
- break;
- case CAR_DOOR_RR:
- doorFlag = CAR_DOOR_FLAG_RR;
- door = DOOR_REAR_RIGHT;
- pedInSeat = car->pPassengers[2];
- break;
- case CAR_DOOR_LF:
- doorFlag = CAR_DOOR_FLAG_LF;
- door = DOOR_FRONT_LEFT;
- pedInSeat = car->pDriver;
- break;
- case CAR_DOOR_LR:
- doorFlag = CAR_DOOR_FLAG_LR;
- door = DOOR_REAR_LEFT;
- pedInSeat = car->pPassengers[1];
- break;
- default:
- doorFlag = CAR_DOOR_FLAG_UNKNOWN;
- break;
+ animAssoc->blendDelta = -1000.0f;
+}
+
+void
+CPed::FinishHitHeadCB(CAnimBlendAssociation *animAssoc, void *arg)
+{
+ CPed *ped = (CPed*)arg;
+
+ if (animAssoc) {
+ animAssoc->blendDelta = -4.0f;
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
}
- if(car->bIsBus)
- pedInSeat = car->pDriver;
+ if (ped->m_nPedState == PED_JUMP)
+ ped->RestorePreviousState();
- if (m_fHealth > 0.0f && (IsPlayer() || m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS ||
- (car->VehicleCreatedBy != MISSION_VEHICLE && car->GetModelIndex() != MI_DODO)))
- if (pedInSeat && !pedInSeat->IsPedDoingDriveByShooting() && pedInSeat->m_nPedState == PED_DRIVING)
- if (m_nPedState != PED_CARJACK && !m_pVehicleAnim)
- if ((car->IsDoorReady(door) || car->IsDoorFullyOpen(door)))
- if (!car->bIsBeingCarJacked && !(doorFlag & car->m_nGettingInFlags) && !(doorFlag & car->m_nGettingOutFlags))
- SetCarJack_AllClear(car, m_vehEnterType, doorFlag);
+ ped->bIsLanding = false;
}
-void
-CPed::Solicit(void)
+bool
+CPed::CanPedDriveOff(void)
{
- if (m_standardTimer >= CTimer::GetTimeInMilliseconds() && m_carInObjective) {
- CVector doorPos = GetPositionToOpenCarDoor(m_carInObjective, m_vehEnterType, 0.0f);
- SetMoveState(PEDMOVE_STILL);
-
- // Game uses GetAngleBetweenPoints and converts it to radian
- m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(
- doorPos.x, doorPos.y,
- GetPosition().x, GetPosition().y);
+ if (m_nPedState != PED_DRIVING || m_lookTimer > CTimer::GetTimeInMilliseconds())
+ return false;
- if (m_fRotationDest < 0.0f) {
- m_fRotationDest = m_fRotationDest + TWOPI;
- } else if (m_fRotationDest > TWOPI) {
- m_fRotationDest = m_fRotationDest - TWOPI;
+ for (int i = 0; i < m_numNearPeds; i++) {
+ CPed *nearPed = m_nearPeds[i];
+ if (nearPed->m_nPedType == m_nPedType && nearPed->m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER && nearPed->m_carInObjective == m_carInObjective) {
+ m_lookTimer = CTimer::GetTimeInMilliseconds() + 1000;
+ return false;
}
+ }
+ return true;
+}
- if ((GetPosition() - doorPos).MagnitudeSqr() <= 1.0f)
- return;
- CAnimBlendAssociation *talkAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_HOOKERTALK);
- if (talkAssoc) {
- talkAssoc->blendDelta = -1000.0f;
- talkAssoc->flags |= ASSOC_DELETEFADEDOUT;
+// These categories are purely random, most of ped models have no correlation. So I don't think making an enum.
+uint8
+CPed::GetPedRadioCategory(uint32 modelIndex)
+{
+ switch (modelIndex) {
+ case MI_MALE01:
+ case MI_FEMALE03:
+ case MI_PROSTITUTE2:
+ case MI_WORKER1:
+ case MI_MOD_MAN:
+ case MI_MOD_WOM:
+ case MI_ST_WOM:
+ case MI_FAN_WOM:
+ return 3;
+ case MI_TAXI_D:
+ case MI_PIMP:
+ case MI_MALE02:
+ case MI_FEMALE02:
+ case MI_FATFEMALE01:
+ case MI_FATFEMALE02:
+ case MI_DOCKER1:
+ case MI_WORKER2:
+ case MI_FAN_MAN2:
+ return 9;
+ case MI_GANG01:
+ case MI_GANG02:
+ case MI_SCUM_MAN:
+ case MI_SCUM_WOM:
+ case MI_HOS_WOM:
+ case MI_CONST1:
+ return 1;
+ case MI_GANG03:
+ case MI_GANG04:
+ case MI_GANG07:
+ case MI_GANG08:
+ case MI_CT_MAN2:
+ case MI_CT_WOM2:
+ case MI_B_MAN3:
+ case MI_SHOPPER3:
+ return 4;
+ case MI_GANG05:
+ case MI_GANG06:
+ case MI_GANG11:
+ case MI_GANG12:
+ case MI_CRIMINAL02:
+ case MI_B_WOM2:
+ case MI_ST_MAN:
+ case MI_HOS_MAN:
+ return 5;
+ case MI_FATMALE01:
+ case MI_LI_MAN2:
+ case MI_SHOPPER1:
+ case MI_CAS_MAN:
+ return 6;
+ case MI_PROSTITUTE:
+ case MI_P_WOM2:
+ case MI_LI_WOM2:
+ case MI_B_WOM3:
+ case MI_CAS_WOM:
+ return 2;
+ case MI_P_WOM1:
+ case MI_DOCKER2:
+ case MI_STUD_MAN:
+ return 7;
+ case MI_CT_MAN1:
+ case MI_CT_WOM1:
+ case MI_LI_MAN1:
+ case MI_LI_WOM1:
+ case MI_B_MAN1:
+ case MI_B_MAN2:
+ case MI_B_WOM1:
+ case MI_SHOPPER2:
+ case MI_STUD_WOM:
+ return 8;
+ default:
+ return 0;
+ }
+}
+
+void
+CPed::SetRadioStation(void)
+{
+ static const uint8 radiosPerRadioCategories[10][4] = {
+ {JAH_RADIO, RISE_FM, GAME_FM, MSX_FM},
+ {HEAD_RADIO, DOUBLE_CLEF, LIPS_106, FLASHBACK},
+ {RISE_FM, GAME_FM, MSX_FM, FLASHBACK},
+ {HEAD_RADIO, RISE_FM, LIPS_106, MSX_FM},
+ {HEAD_RADIO, RISE_FM, MSX_FM, FLASHBACK},
+ {JAH_RADIO, RISE_FM, LIPS_106, FLASHBACK},
+ {HEAD_RADIO, RISE_FM, LIPS_106, FLASHBACK},
+ {HEAD_RADIO, JAH_RADIO, LIPS_106, FLASHBACK},
+ {HEAD_RADIO, DOUBLE_CLEF, LIPS_106, FLASHBACK},
+ {CHATTERBOX, HEAD_RADIO, LIPS_106, GAME_FM}
+ };
+ uint8 orderInCat = 0; // BUG: this wasn't initialized
+
+ if (IsPlayer() || !m_pMyVehicle || m_pMyVehicle->pDriver != this)
+ return;
+
+ uint8 category = GetPedRadioCategory(GetModelIndex());
+ if (DMAudio.IsMP3RadioChannelAvailable()) {
+ if (CGeneral::GetRandomNumber() & 15) {
+ for (orderInCat = 0; orderInCat < 4; orderInCat++) {
+ if (m_pMyVehicle->m_nRadioStation == radiosPerRadioCategories[category][orderInCat])
+ break;
+ }
+ } else {
+ m_pMyVehicle->m_nRadioStation = USERTRACK;
}
- RestorePreviousState();
- RestorePreviousObjective();
- SetObjectiveTimer(10000);
- } else if (!m_carInObjective) {
- RestorePreviousState();
- RestorePreviousObjective();
- SetObjectiveTimer(10000);
- } else if (CWorld::Players[CWorld::PlayerInFocus].m_nMoney <= 100) {
- m_carInObjective = nil;
} else {
- m_pVehicleAnim = nil;
- SetLeader(m_carInObjective->pDriver);
+ for (orderInCat = 0; orderInCat < 4; orderInCat++) {
+ if (m_pMyVehicle->m_nRadioStation == radiosPerRadioCategories[category][orderInCat])
+ break;
+ }
+ }
+ if (orderInCat == 4) {
+ if (DMAudio.IsMP3RadioChannelAvailable()) {
+ if (CGeneral::GetRandomNumber() & 15)
+ m_pMyVehicle->m_nRadioStation = radiosPerRadioCategories[category][CGeneral::GetRandomNumber() & 3];
+ else
+ m_pMyVehicle->m_nRadioStation = USERTRACK;
+ } else {
+ m_pMyVehicle->m_nRadioStation = radiosPerRadioCategories[category][CGeneral::GetRandomNumber() & 3];
+ }
}
}
-// Seperate function in VC, more logical. Not sure is it inlined in III.
void
-CPed::SetExitBoat(CVehicle *boat)
+CPed::WarpPedIntoCar(CVehicle *car)
{
-#ifndef VC_PED_PORTS
- m_nPedState = PED_IDLE;
- CVector firstPos = GetPosition();
- CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 100.0f);
- if (boat->GetModelIndex() == MI_SPEEDER && boat->IsUpsideDown()) {
- m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_CRAWLOUT_RHS, 8.0f);
- m_pVehicleAnim->SetFinishCallback(PedSetOutCarCB, this);
- m_vehEnterType = CAR_DOOR_RF;
- m_nPedState = PED_EXIT_CAR;
+ bInVehicle = true;
+ m_pMyVehicle = car;
+ m_pMyVehicle->RegisterReference((CEntity **) &m_pMyVehicle);
+ m_carInObjective = car;
+ m_carInObjective->RegisterReference((CEntity **) &m_carInObjective);
+ m_nPedState = PED_DRIVING;
+ bUsesCollision = false;
+ bIsInTheAir = false;
+ bVehExitWillBeInstant = true;
+ if (m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) {
+ car->SetDriver(this);
+ car->pDriver->RegisterReference((CEntity **) &car->pDriver);
+
+ } else if (m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER) {
+ for (int i = 0; i < 4; i++) {
+ if (!car->pPassengers[i]) {
+ car->pPassengers[i] = this;
+ car->pPassengers[i]->RegisterReference((CEntity **) &car->pPassengers[i]);
+ break;
+ }
+ }
+ } else
+ return;
+
+ if (IsPlayer()) {
+ car->SetStatus(STATUS_PLAYER);
+ AudioManager.PlayerJustGotInCar();
+ CCarCtrl::RegisterVehicleOfInterest(car);
} else {
- m_vehEnterType = CAR_DOOR_RF;
- PedSetOutCarCB(nil, this);
- bIsStanding = true;
- m_pCurSurface = boat;
- m_pCurSurface->RegisterReference((CEntity**)&m_pCurSurface);
+ car->SetStatus(STATUS_PHYSICS);
}
- SetPosition(firstPos);
- SetMoveState(PEDMOVE_STILL);
- m_vecMoveSpeed = boat->m_vecMoveSpeed;
- bTryingToReachDryLand = true;
+
+ CWorld::Remove(this);
+ SetPosition(car->GetPosition());
+ CWorld::Add(this);
+
+ if (car->bIsAmbulanceOnDuty) {
+ car->bIsAmbulanceOnDuty = false;
+ --CCarCtrl::NumAmbulancesOnDuty;
+ }
+ if (car->bIsFireTruckOnDuty) {
+ car->bIsFireTruckOnDuty = false;
+ --CCarCtrl::NumFiretrucksOnDuty;
+ }
+ if (!car->bEngineOn) {
+ car->bEngineOn = true;
+ DMAudio.PlayOneShot(car->m_audioEntityId, SOUND_CAR_ENGINE_START, 1.0f);
+ }
+
+#ifdef VC_PED_PORTS
+ RpAnimBlendClumpSetBlendDeltas(GetClump(), ASSOC_PARTIAL, -1000.0f);
+
+ // VC uses AddInCarAnims but we don't have that
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, car->GetDriverAnim(), 100.0f);
+ RemoveWeaponWhenEnteringVehicle();
#else
- m_nPedState = PED_IDLE;
- CVector newPos = GetPosition();
- RemoveInCarAnims();
- CColModel* boatCol = boat->GetColModel();
- if (boat->IsUpsideDown()) {
- newPos = { 0.0f, 0.0f, boatCol->boundingBox.min.z };
- newPos = boat->GetMatrix() * newPos;
- newPos.z += 1.0f;
- m_vehEnterType = CAR_DOOR_RF;
- PedSetOutCarCB(nil, this);
- bIsStanding = true;
- m_pCurSurface = boat;
- m_pCurSurface->RegisterReference((CEntity**)&m_pCurSurface);
- m_pCurrentPhysSurface = boat;
+ if (car->IsBoat()) {
+#ifndef FIX_BUGS
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_BOAT, 100.0f);
+#else
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, car->GetDriverAnim(), 100.0f);
+#endif
+ CWeaponInfo *ourWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
+ RemoveWeaponModel(ourWeapon->m_nModelId);
} else {
-/* if (boat->m_modelIndex != MI_SKIMMER || boat->bIsInWater) {
- if (boat->m_modelIndex == MI_SKIMMER)
- newPos.z += 2.0f
-*/
- m_vehEnterType = CAR_DOOR_RF;
- PedSetOutCarCB(nil, this);
- bIsStanding = true;
- m_pCurSurface = boat;
- m_pCurSurface->RegisterReference((CEntity**)&m_pCurSurface);
- m_pCurrentPhysSurface = boat;
- CColPoint foundCol;
- CEntity *foundEnt = nil;
- if (CWorld::ProcessVerticalLine(newPos, newPos.z - 1.4f, foundCol, foundEnt, false, true, false, false, false, false, nil))
- newPos.z = FEET_OFFSET + foundCol.point.z;
-/* // VC specific
+ // Because we can use Uzi for drive by
+ RemoveWeaponWhenEnteringVehicle();
+
+ if (car->bLowVehicle)
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_LSIT, 100.0f);
+ else
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_SIT, 100.0f);
+ }
+#endif
+
+ StopNonPartialAnims();
+ if (car->bIsBus)
+ bRenderPedInCar = false;
+
+ bChangedSeat = true;
+}
+
+
+#ifdef PEDS_REPORT_CRIMES_ON_PHONE
+// returns event id, parameter is optional
+int32
+CPed::CheckForPlayerCrimes(CPed *victim)
+{
+ int i;
+ float dist;
+ float mindist = 60.0f;
+ CPlayerPed *player = FindPlayerPed();
+ int32 victimRef = (victim ? CPools::GetPedRef(victim) : 0);
+ int event = -1;
+
+ for (i = 0; i < NUMEVENTS; i++) {
+ if (gaEvent[i].type == EVENT_NULL || gaEvent[i].type > EVENT_CAR_SET_ON_FIRE)
+ continue;
+
+ // those are already handled in game, also DEAD_PED isn't registered alone, most of the time there is SHOOT_PED etc.
+ if (gaEvent[i].type == EVENT_DEAD_PED || gaEvent[i].type == EVENT_GUNSHOT || gaEvent[i].type == EVENT_EXPLOSION)
+ continue;
+
+ if (victim && gaEvent[i].entityRef != victimRef)
+ continue;
+
+ if (gaEvent[i].criminal != player)
+ continue;
+
+ dist = (GetPosition() - gaEvent[i].posn).Magnitude();
+ if (dist < mindist) {
+ mindist = dist;
+ event = i;
+ }
+ }
+
+ if (event != -1) {
+ if (victim) {
+ m_victimOfPlayerCrime = victim;
} else {
- m_vehEnterType = CAR_DOOR_RF;
- PedSetOutCarCB(nil, this);
- bIsStanding = true;
- SetMoveState(PEDMOVE_STILL);
- bTryingToReachDryLand = true;
- float upMult = 1.04f + boatCol->boundingBox.min.z;
- float rightMult = 0.6f * boatCol->boundingBox.max.x;
- newPos = upMult * boat->GetUp() + rightMult * boat->GetRight() + boat->GetPosition();
- GetPosition() = newPos;
- if (m_pMyVehicle) {
- PositionPedOutOfCollision();
- } else {
- m_pMyVehicle = boat;
- PositionPedOutOfCollision();
- m_pMyVehicle = nil;
+ switch (gaEvent[event].entityType) {
+ case EVENT_ENTITY_PED:
+ m_victimOfPlayerCrime = CPools::GetPed(gaEvent[event].entityRef);
+ break;
+ case EVENT_ENTITY_VEHICLE:
+ m_victimOfPlayerCrime = CPools::GetVehicle(gaEvent[event].entityRef);
+ break;
+ case EVENT_ENTITY_OBJECT:
+ m_victimOfPlayerCrime = CPools::GetObject(gaEvent[event].entityRef);
+ break;
+ default:
+ break;
}
- return;
}
-*/ }
- SetPosition(newPos);
- SetMoveState(PEDMOVE_STILL);
- m_vecMoveSpeed = boat->m_vecMoveSpeed;
+ }
+
+ return event;
+}
#endif
- // Not there in VC.
- CWaterLevel::FreeBoatWakeArray();
+
+#ifdef PED_SKIN
+static RpMaterial*
+SetLimbAlphaCB(RpMaterial *material, void *data)
+{
+ ((RwRGBA*)RpMaterialGetColor(material))->alpha = *(uint8*)data;
+ return material;
}
+void
+CPed::renderLimb(int node)
+{
+ RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(GetClump());
+ int idx = RpHAnimIDGetIndex(hier, m_pFrames[node]->nodeID);
+ RwMatrix *mat = &RpHAnimHierarchyGetMatrixArray(hier)[idx];
+ CPedModelInfo *mi = (CPedModelInfo *)CModelInfo::GetModelInfo(GetModelIndex());
+ RpAtomic *atomic;
+ switch(node){
+ case PED_HEAD:
+ atomic = mi->getHead();
+ break;
+ case PED_HANDL:
+ atomic = mi->getLeftHand();
+ break;
+ case PED_HANDR:
+ atomic = mi->getRightHand();
+ break;
+ default:
+ return;
+ }
+ if(atomic == nil)
+ return;
+
+ RwFrame *frame = RpAtomicGetFrame(atomic);
+ *RwFrameGetMatrix(frame) = *mat;
+ RwFrameUpdateObjects(frame);
+ int alpha = CVisibilityPlugins::GetClumpAlpha(GetClump());
+ RpGeometryForAllMaterials(RpAtomicGetGeometry(atomic), SetLimbAlphaCB, &alpha);
+ RpAtomicRender(atomic);
+}
+#endif
+
#ifdef COMPATIBLE_SAVES
#define CopyFromBuf(buf, data) memcpy(&data, buf, sizeof(data)); SkipSaveBuf(buf, sizeof(data));
#define CopyToBuf(buf, data) memcpy(buf, &data, sizeof(data)); SkipSaveBuf(buf, sizeof(data));
diff --git a/src/peds/Ped.h b/src/peds/Ped.h
index dbe61572..a3d4997d 100644
--- a/src/peds/Ped.h
+++ b/src/peds/Ped.h
@@ -5,7 +5,7 @@
#include "Crime.h"
#include "EventList.h"
#include "PedIK.h"
-#include "PedStats.h"
+#include "PedType.h"
#include "Physical.h"
#include "Weapon.h"
#include "WeaponInfo.h"
@@ -13,6 +13,7 @@
#define FEET_OFFSET 1.04f
#define CHECK_NEARBY_THINGS_MAX_DIST 15.0f
#define ENTER_CAR_MAX_DIST 30.0f
+#define CAN_SEE_ENTITY_ANGLE_THRESHOLD DEGTORAD(60.0f)
struct CPathNode;
class CAccident;
@@ -568,7 +569,7 @@ public:
void CalculateNewOrientation(void);
float WorkOutHeadingForMovingFirstPerson(float);
void CalculateNewVelocity(void);
- bool CanSeeEntity(CEntity*, float);
+ bool CanSeeEntity(CEntity*, float threshold = CAN_SEE_ENTITY_ANGLE_THRESHOLD);
void RestorePreviousObjective(void);
void SetIdle(void);
#ifdef _MSC_VER
@@ -747,7 +748,7 @@ public:
static void PedSetQuickDraggedOutCarPositionCB(CAnimBlendAssociation *assoc, void *arg);
static void PedSetDraggedOutCarPositionCB(CAnimBlendAssociation *assoc, void *arg);
- bool IsPlayer(void);
+ bool IsPlayer(void) const;
bool UseGroundColModel(void);
bool CanSetPedState(void);
bool IsPedInControl(void);
@@ -765,7 +766,7 @@ public:
void SetStoredObjective(void);
void SetLeader(CEntity* leader);
void SetPedStats(ePedStats);
- bool IsGangMember(void);
+ bool IsGangMember(void) const;
void Die(void);
void EnterTrain(void);
void ExitTrain(void);
@@ -788,7 +789,7 @@ public:
CObject *SpawnFlyingComponent(int, int8);
void SetCarJack_AllClear(CVehicle*, uint32, uint32);
#ifdef VC_PED_PORTS
- bool CanPedJumpThis(CEntity*, CVector*);
+ bool CanPedJumpThis(CEntity *unused, CVector *damageNormal = nil);
#else
bool CanPedJumpThis(CEntity*);
#endif
@@ -809,9 +810,40 @@ public:
bool InVehicle(void) { return bInVehicle && m_pMyVehicle; } // True when ped is sitting/standing in vehicle, not in enter/exit state.
bool EnteringCar(void) { return m_nPedState == PED_ENTER_CAR || m_nPedState == PED_CARJACK; }
- void ReplaceWeaponWhenExitingVehicle(void);
- void RemoveWeaponWhenEnteringVehicle(void);
- bool IsNotInWreckedVehicle();
+ // It was inlined in III but not in VC.
+ inline void
+ ReplaceWeaponWhenExitingVehicle(void)
+ {
+ eWeaponType weaponType = GetWeapon()->m_eWeaponType;
+
+ // If it's Uzi, we may have stored weapon. Uzi is the only gun we can use in car.
+ if (IsPlayer() && weaponType == WEAPONTYPE_UZI) {
+ if (/*IsPlayer() && */ m_storedWeapon != WEAPONTYPE_UNIDENTIFIED) {
+ SetCurrentWeapon(m_storedWeapon);
+ m_storedWeapon = WEAPONTYPE_UNIDENTIFIED;
+ }
+ } else {
+ AddWeaponModel(CWeaponInfo::GetWeaponInfo(weaponType)->m_nModelId);
+ }
+ }
+
+ // It was inlined in III but not in VC.
+ inline void
+ RemoveWeaponWhenEnteringVehicle(void)
+ {
+ if (IsPlayer() && HasWeapon(WEAPONTYPE_UZI) && GetWeapon(WEAPONTYPE_UZI).m_nAmmoTotal > 0) {
+ if (m_storedWeapon == WEAPONTYPE_UNIDENTIFIED)
+ m_storedWeapon = GetWeapon()->m_eWeaponType;
+ SetCurrentWeapon(WEAPONTYPE_UZI);
+ } else {
+ CWeaponInfo *ourWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
+ RemoveWeaponModel(ourWeapon->m_nModelId);
+ }
+ }
+ bool IsNotInWreckedVehicle()
+ {
+ return m_pMyVehicle != nil && ((CEntity*)m_pMyVehicle)->GetStatus() != STATUS_WRECKED;
+ }
// My additions, because there were many, many instances of that.
inline void SetFindPathAndFlee(CEntity *fleeFrom, int time, bool walk = false)
{
diff --git a/src/peds/PedAI.cpp b/src/peds/PedAI.cpp
new file mode 100644
index 00000000..38303473
--- /dev/null
+++ b/src/peds/PedAI.cpp
@@ -0,0 +1,5413 @@
+#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"
+
+CVector vecPedCarDoorAnimOffset;
+CVector vecPedCarDoorLoAnimOffset;
+CVector vecPedVanRearDoorAnimOffset;
+CVector vecPedQuickDraggedOutCarAnimOffset;
+CVector vecPedDraggedOutCarAnimOffset;
+CVector vecPedTrainDoorAnimOffset;
+
+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_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:
+ 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_ENTER_CAR_AS_PASSENGER:
+ case OBJECTIVE_ENTER_CAR_AS_DRIVER:
+ case OBJECTIVE_GOTO_AREA_ON_FOOT:
+ case OBJECTIVE_RUN_TO_AREA:
+ return;
+ default:
+ m_prevObjective = m_objective;
+ }
+}
+
+bool
+CPed::IsTemporaryObjective(eObjective objective)
+{
+ return objective == OBJECTIVE_LEAVE_CAR || objective == OBJECTIVE_SET_LEADER ||
+#ifdef VC_PED_PORTS
+ objective == OBJECTIVE_LEAVE_CAR_AND_DIE ||
+#endif
+ objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER;
+}
+
+void
+CPed::SetObjective(eObjective newObj)
+{
+ if (DyingOrDead())
+ 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
+#ifdef VC_PED_PORTS
+ || m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE)
+ && !IsPlayer()
+#else
+ )
+#endif
+ && !IsPedInControl()) {
+
+ bStartWanderPathOnFoot = true;
+ return;
+ }
+ // Unused code from assembly...
+ /*
+ else if(m_objective == OBJECTIVE_FLEE_CAR) {
+
+ } 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) {
+ // Why?
+ if (m_prevObjective != OBJECTIVE_NONE)
+ return;
+ }
+
+ if (entity == this)
+ return;
+
+ SetObjectiveTimer(0);
+ 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_FOLLOW_CHAR_IN_FORMATION:
+ case OBJECTIVE_GOTO_AREA_ANY_MEANS:
+ case OBJECTIVE_GUARD_ATTACK:
+ if (m_pedInObjective == entity)
+ return;
+
+ break;
+ case OBJECTIVE_LEAVE_CAR:
+ case OBJECTIVE_FLEE_CAR:
+#ifdef VC_PED_PORTS
+ case OBJECTIVE_LEAVE_CAR_AND_DIE:
+#endif
+ 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;
+
+ break;
+ case OBJECTIVE_SET_LEADER:
+ if (m_leader == entity)
+ return;
+
+ break;
+ default:
+ break;
+ }
+ } else {
+ if ((newObj == OBJECTIVE_LEAVE_CAR
+#ifdef VC_PED_PORTS
+ || newObj == OBJECTIVE_LEAVE_CAR_AND_DIE
+#endif
+ ) && !bInVehicle)
+ return;
+ }
+
+#ifdef VC_PED_PORTS
+ ClearPointGunAt();
+#endif
+ bObjectiveCompleted = false;
+ 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_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:
+ m_pNextPathNode = nil;
+ bUsePedNodeSeek = false;
+ m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f);
+ m_pedInObjective = (CPed*)entity;
+ m_pedInObjective->RegisterReference((CEntity**)&m_pedInObjective);
+ m_pLookTarget = (CEntity*)entity;
+ 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_GUARD_ATTACK:
+ m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f);
+ m_pedInObjective = (CPed*)entity;
+ 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:
+#ifdef VC_PED_PORTS
+ case OBJECTIVE_LEAVE_CAR_AND_DIE:
+#endif
+ 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_ENTER_CAR_AS_PASSENGER:
+ case OBJECTIVE_ENTER_CAR_AS_DRIVER:
+ if (m_nMoveState == PEDMOVE_STILL)
+ SetMoveState(PEDMOVE_RUN);
+
+ if (((CVehicle*)entity)->m_vehType == VEHICLE_TYPE_BOAT && !IsPlayer()) {
+ 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;
+ default:
+ break;
+ }
+}
+
+void
+CPed::SetObjective(eObjective newObj, CVector dest, float safeDist)
+{
+ if (DyingOrDead())
+ return;
+
+ if (m_prevObjective != OBJECTIVE_NONE && m_prevObjective == newObj)
+ return;
+
+ SetObjectiveTimer(0);
+ if (m_objective == newObj) {
+ if (newObj == OBJECTIVE_GOTO_AREA_ANY_MEANS || newObj == OBJECTIVE_GOTO_AREA_ON_FOOT || newObj == OBJECTIVE_RUN_TO_AREA) {
+ if (m_nextRoutePointPos == dest && m_distanceToCountSeekDone == safeDist)
+ return;
+ } else if (newObj == OBJECTIVE_GUARD_SPOT) {
+ if (m_vecSeekPosEx == dest && m_distanceToCountSeekDoneEx == safeDist)
+ return;
+ }
+ }
+
+#ifdef VC_PED_PORTS
+ ClearPointGunAt();
+#endif
+ bObjectiveCompleted = false;
+ if (IsTemporaryObjective(m_objective)) {
+ m_prevObjective = newObj;
+ } else {
+ if (m_objective != newObj)
+ SetStoredObjective();
+
+ m_objective = newObj;
+ }
+
+ if (newObj == OBJECTIVE_GUARD_SPOT) {
+ m_vecSeekPosEx = dest;
+ m_distanceToCountSeekDoneEx = safeDist;
+ } else if (newObj == OBJECTIVE_GOTO_AREA_ANY_MEANS || newObj == OBJECTIVE_GOTO_AREA_ON_FOOT || newObj == OBJECTIVE_RUN_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;
+
+ SetObjectiveTimer(0);
+
+ if (m_objective == newObj && newObj == OBJECTIVE_FOLLOW_ROUTE && m_routeLastPoint == routePoint && m_routeType == routeType)
+ return;
+
+ 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;
+
+ SetObjectiveTimer(0);
+ if (m_objective == newObj) {
+ if (newObj == OBJECTIVE_GOTO_AREA_ANY_MEANS || newObj == OBJECTIVE_GOTO_AREA_ON_FOOT || newObj == OBJECTIVE_RUN_TO_AREA) {
+ if (m_nextRoutePointPos == dest)
+ return;
+ } else if (newObj == OBJECTIVE_GUARD_SPOT) {
+ if (m_vecSeekPosEx == dest)
+ return;
+ }
+ }
+
+#ifdef VC_PED_PORTS
+ ClearPointGunAt();
+#endif
+ bObjectiveCompleted = false;
+ switch (newObj) {
+ case OBJECTIVE_GUARD_SPOT:
+ m_vecSeekPosEx = dest;
+ m_distanceToCountSeekDoneEx = 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_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:
+ break;
+ case OBJECTIVE_GOTO_AREA_ANY_MEANS:
+ case OBJECTIVE_GOTO_AREA_ON_FOOT:
+ bIsRunning = false;
+ 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;
+ case OBJECTIVE_RUN_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::ClearObjective(void)
+{
+ if (IsPedInControl() || m_nPedState == PED_DRIVING) {
+ m_objective = OBJECTIVE_NONE;
+#ifdef VC_PED_PORTS
+ m_pedInObjective = nil;
+ m_carInObjective = nil;
+#endif
+ if (m_nPedState == PED_DRIVING && m_pMyVehicle) {
+
+ if (m_pMyVehicle->pDriver != this) {
+#if defined VC_PED_PORTS || defined FIX_BUGS
+ if(!IsPlayer())
+#endif
+ bWanderPathAfterExitingCar = true;
+
+ SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);
+ }
+#ifdef VC_PED_PORTS
+ m_nLastPedState = PED_NONE;
+#endif
+ } 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 (IsPedInControl()) {
+ SetObjective(OBJECTIVE_NONE);
+ SetIdle();
+ SetMoveState(PEDMOVE_STILL);
+ }
+ SetLeader(nil);
+ return;
+ }
+
+ 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) {
+ 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) {
+#ifndef VC_PED_PORTS
+ SetObjective(OBJECTIVE_GOTO_CHAR_ON_FOOT, m_leader);
+ SetObjectiveTimer(0);
+#else
+ 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);
+ }
+#endif
+ }
+ if (m_nPedState == PED_IDLE && m_leader->IsPlayer()) {
+ if (ScanForThreats() && m_threatEntity) {
+ m_pLookTarget = m_threatEntity;
+ m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);
+ TurnBody();
+ if (m_attackTimer < CTimer::GetTimeInMilliseconds() && !GetWeapon()->IsTypeMelee()) {
+ m_pPointGunAt = m_threatEntity;
+ if (m_threatEntity)
+ m_threatEntity->RegisterReference((CEntity **) &m_pPointGunAt);
+ SetAttack(m_threatEntity);
+ }
+ }
+ }
+ }
+ } else {
+ switch (m_leader->m_objective) {
+ case OBJECTIVE_WAIT_ON_FOOT:
+ case OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE:
+ case OBJECTIVE_WAIT_IN_CAR:
+ case OBJECTIVE_FOLLOW_ROUTE:
+ SetObjective(m_leader->m_objective);
+ m_objectiveTimer = m_leader->m_objectiveTimer;
+ break;
+ case OBJECTIVE_GUARD_SPOT:
+ SetObjective(OBJECTIVE_GUARD_SPOT, m_leader->m_vecSeekPosEx);
+ 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:
+ 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) {
+ 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) {
+#ifdef VC_PED_PORTS
+ m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 250;
+#endif
+ 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
+#if defined VC_PED_PORTS || defined FIX_BUGS
+ && m_nPedState != PED_CARJACK
+#endif
+ )
+ 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_NONE:
+ case OBJECTIVE_GUARD_AREA:
+ case OBJECTIVE_FOLLOW_CAR_IN_CAR:
+ case OBJECTIVE_FIRE_AT_OBJECT_FROM_VEHICLE:
+ case OBJECTIVE_DESTROY_OBJECT:
+ case OBJECTIVE_GOTO_AREA_IN_CAR:
+ case OBJECTIVE_FOLLOW_CAR_ON_FOOT_WITH_OFFSET:
+ case OBJECTIVE_SET_LEADER:
+ break;
+ case OBJECTIVE_WAIT_ON_FOOT:
+ SetIdle();
+ m_objective = OBJECTIVE_NONE;
+ SetMoveState(PEDMOVE_STILL);
+ break;
+ case OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE:
+ 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_vecSeekPosEx - 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_distanceToCountSeekDoneEx >= distWithTargetSc) {
+ if (m_pedInObjective) {
+ if (distWithTargetSc <= m_distanceToCountSeekDoneEx)
+ SetIdle();
+ else
+ SetSeek(m_vecSeekPosEx, m_distanceToCountSeekDoneEx);
+ } 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 {
+ SetSeek(m_vecSeekPosEx, m_distanceToCountSeekDoneEx);
+ }
+ break;
+ }
+ case OBJECTIVE_WAIT_IN_CAR:
+ m_nPedState = PED_DRIVING;
+ break;
+ case OBJECTIVE_WAIT_IN_CAR_THEN_GET_OUT:
+ m_nPedState = 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->m_nGettingInFlags) {
+ m_pMyVehicle->SetStatus(STATUS_PHYSICS);
+ m_pMyVehicle->AutoPilot.m_nPrevRouteNode = 0;
+ if (m_nPedType == PEDTYPE_COP) {
+ m_pMyVehicle->AutoPilot.m_nCruiseSpeed = (FindPlayerPed()->m_pWanted->m_nWantedLevel * 0.1f + 0.6f) * (GAME_SPEED_TO_CARAI_SPEED * m_pMyVehicle->pHandling->Transmission.fUnkMaxVelocity);
+ m_pMyVehicle->AutoPilot.m_nCarMission = CCarAI::FindPoliceCarMissionForWantedLevel();
+ } else {
+ m_pMyVehicle->AutoPilot.m_nCruiseSpeed = GAME_SPEED_TO_CARAI_SPEED * m_pMyVehicle->pHandling->Transmission.fUnkMaxVelocity * 0.8f;
+ m_pMyVehicle->AutoPilot.m_nCarMission = MISSION_RAMPLAYER_FARAWAY;
+ }
+ m_pMyVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;
+ }
+ } else {
+ bool targetHasVeh = m_pedInObjective->bInVehicle;
+ if (!targetHasVeh
+ || targetHasVeh && m_pedInObjective->m_pMyVehicle->CanPedExitCar()) {
+ 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(), 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.Magnitude() < closestVehDist && m_pedInObjective->m_pMyVehicle != nearVeh
+ && nearVeh->CanPedOpenLocks(this)) {
+
+ 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, &ourPos, &chosenCarClass);
+ CAutomobile *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:
+ {
+ bool killPlayerInNoPoliceZone = false;
+ if (m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT && InVehicle()) {
+ SetObjective(OBJECTIVE_LEAVE_CAR, m_pMyVehicle);
+ break;
+ }
+ if (!m_pedInObjective || m_pedInObjective->DyingOrDead()) {
+ ClearLookFlag();
+ bObjectiveCompleted = true;
+ SetMoveAnim();
+ break;
+ }
+ if (m_pedInObjective->IsPlayer() && CCullZones::NoPolice())
+ killPlayerInNoPoliceZone = true;
+
+ if (!bNotAllowedToDuck || killPlayerInNoPoliceZone) {
+ if (m_nPedType == PEDTYPE_COP && !m_pedInObjective->GetWeapon()->IsTypeMelee() && !GetWeapon()->IsTypeMelee())
+ bNotAllowedToDuck = true;
+ } else {
+ if (!m_pedInObjective->bInVehicle) {
+ if (m_pedInObjective->GetWeapon()->IsTypeMelee() || GetWeapon()->IsTypeMelee()) {
+ bNotAllowedToDuck = false;
+ bCrouchWhenShooting = false;
+ } else if (DuckAndCover()) {
+ break;
+ }
+ } else {
+ bNotAllowedToDuck = false;
+ bCrouchWhenShooting = false;
+ }
+ }
+ if (m_leaveCarTimer > CTimer::GetTimeInMilliseconds() && !bKindaStayInSamePlace) {
+ SetMoveState(PEDMOVE_STILL);
+ break;
+ }
+ 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();
+
+ break;
+ }
+ }
+ CWeaponInfo *wepInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
+ float wepRange = wepInfo->m_fRange;
+ float wepRangeAdjusted;
+ if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED) {
+ wepRangeAdjusted = wepRange / 3.0f;
+ } else {
+ if (m_nPedState == PED_FIGHT) {
+ if (!IsPlayer() && !(m_pedStats->m_flags & STAT_CAN_KICK))
+ wepRange = 2.0f;
+ } else {
+ wepRange = 1.3f;
+ }
+ wepRangeAdjusted = wepRange;
+ }
+ if (m_pedInObjective->m_getUpTimer > CTimer::GetTimeInMilliseconds() && wepRangeAdjusted < 2.5f) {
+ wepRangeAdjusted = 2.5f;
+ }
+ if (m_pedInObjective->IsPlayer() && m_nPedType != PEDTYPE_COP
+ && CharCreatedBy != MISSION_CHAR && FindPlayerPed()->m_pWanted->m_CurrentCops) {
+ SetObjective(OBJECTIVE_FLEE_ON_FOOT_TILL_SAFE);
+ break;
+ }
+ if (m_pedInObjective->m_fHealth <= 0.0f) {
+ bObjectiveCompleted = true;
+ bScriptObjectiveCompleted = true;
+ SetMoveAnim();
+ break;
+ }
+ 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;
+ }
+ SetLookFlag(vehOfTarget, false);
+ if (m_nPedState != PED_CARJACK) {
+ if (m_pedInObjective->m_nPedState != PED_ARRESTED) {
+ if (m_attackTimer < CTimer::GetTimeInMilliseconds() && wepInfo->m_eWeaponFire != WEAPON_FIRE_MELEE
+ && distWithTargetSc < wepRange && distWithTargetSc > 3.0f) {
+
+ // I hope so
+ CVector ourHead = GetMatrix() * CVector(0.5f, 0.0f, 0.6f);
+ CVector maxShotPos = vehOfTarget->GetPosition() - ourHead;
+ maxShotPos.Normalise();
+ maxShotPos = maxShotPos * wepInfo->m_fRange + ourHead;
+
+ CWorld::bIncludeDeadPeds = true;
+ CColPoint foundCol;
+ CEntity *foundEnt;
+ CWorld::ProcessLineOfSight(ourHead, maxShotPos, foundCol, foundEnt,
+ true, true, true, true, false, true, false);
+ CWorld::bIncludeDeadPeds = false;
+ if (foundEnt == vehOfTarget) {
+ SetAttack(vehOfTarget);
+ m_pPointGunAt = vehOfTarget;
+ if (vehOfTarget)
+ vehOfTarget->RegisterReference((CEntity **) &m_pPointGunAt);
+
+ SetShootTimer(CGeneral::GetRandomNumberInRange(500, 2000));
+ if (distWithTargetSc <= m_distanceToCountSeekDone) {
+ SetAttackTimer(CGeneral::GetRandomNumberInRange(200, 500));
+ SetMoveState(PEDMOVE_STILL);
+ } else {
+ SetAttackTimer(CGeneral::GetRandomNumberInRange(2000, 5000));
+ }
+ }
+ }
+ else if (m_nPedState != PED_ATTACK && !bKindaStayInSamePlace && !killPlayerInNoPoliceZone) {
+ if (vehOfTarget) {
+ if (m_nPedType == PEDTYPE_COP || vehOfTarget->bIsBus) {
+ GoToNearestDoor(vehOfTarget);
+ } else {
+ m_vehEnterType = 0;
+ if (m_pedInObjective == vehOfTarget->pDriver || vehOfTarget->bIsBus) {
+ m_vehEnterType = CAR_DOOR_LF;
+ } else if (m_pedInObjective == vehOfTarget->pPassengers[0]) {
+ m_vehEnterType = CAR_DOOR_RF;
+ } else if (m_pedInObjective == vehOfTarget->pPassengers[1]) {
+ m_vehEnterType = CAR_DOOR_LR;
+ } else if (m_pedInObjective == vehOfTarget->pPassengers[2]) {
+ m_vehEnterType = CAR_DOOR_RR;
+ }
+ // Unused
+ // GetPositionToOpenCarDoor(vehOfTarget, m_vehEnterType);
+ SetSeekCar(vehOfTarget, m_vehEnterType);
+ SetMoveState(PEDMOVE_RUN);
+ }
+ }
+ }
+ }
+ }
+ SetMoveAnim();
+ break;
+ }
+ if (m_nMoveState == PEDMOVE_STILL && IsPedInControl()) {
+ SetLookFlag(m_pedInObjective, false);
+ TurnBody();
+ }
+ if (m_nPedType == PEDTYPE_COP && distWithTargetSc < 1.5f && m_pedInObjective->IsPlayer()) {
+ if (m_pedInObjective->m_getUpTimer > CTimer::GetTimeInMilliseconds()
+ || m_pedInObjective->m_nPedState == PED_DRAG_FROM_CAR) {
+
+ ((CCopPed*)this)->SetArrestPlayer(m_pedInObjective);
+ return;
+ }
+ }
+ if (!bKindaStayInSamePlace && !bStopAndShoot && m_nPedState != PED_ATTACK && !killPlayerInNoPoliceZone) {
+ if (distWithTargetSc > wepRange
+ || m_pedInObjective->m_getUpTimer > CTimer::GetTimeInMilliseconds()
+ || m_pedInObjective->m_nPedState == PED_ARRESTED
+ || m_pedInObjective->EnteringCar() && distWithTargetSc < 3.0f
+ || distWithTargetSc > m_distanceToCountSeekDone && !CanSeeEntity(m_pedInObjective)) {
+
+ 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 = m_pNextPathNode->GetPosition();
+
+ SetSeek(m_vecSeekPos, m_distanceToCountSeekDone);
+ } else {
+ SetSeek(m_pedInObjective, wepRangeAdjusted);
+ }
+ bCrouchWhenShooting = false;
+ if (m_pedInObjective->m_pCurrentPhysSurface && distWithTargetSc < 5.0f) {
+ if (wepRange <= 5.0f) {
+ if (m_pedInObjective->IsPlayer()
+ && FindPlayerPed()->m_bSpeedTimerFlag
+ && (IsGangMember() || m_nPedType == PEDTYPE_COP)
+ && GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED) {
+ GiveWeapon(WEAPONTYPE_COLT45, 1000);
+ SetCurrentWeapon(WEAPONTYPE_COLT45);
+ }
+ } else {
+ bStopAndShoot = true;
+ }
+ SetMoveState(PEDMOVE_STILL);
+ SetMoveAnim();
+ break;
+ }
+ bStopAndShoot = false;
+ SetMoveAnim();
+ break;
+ }
+ }
+ 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_DUCK_DOWN);
+ if (duckAnim) {
+ duckAnim->blendDelta = -2.0f;
+ break;
+ }
+ bIsDucking = false;
+ } else if (wepRange <= 5.0f) {
+ 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.0f, 500.0f));
+ SetAttackTimer(CGeneral::GetRandomNumberInRange(0.0f, 1500.0f));
+ bObstacleShowedUpDuringKillObjective = false;
+
+ } else {
+ CVector target;
+ CVector ourHead = GetMatrix() * CVector(0.5f, 0.0f, 0.6f);
+ if (m_pedInObjective->IsPed())
+ m_pedInObjective->m_pedIK.GetComponentPosition((RwV3d*)&target, PED_MID);
+ else
+ target = m_pedInObjective->GetPosition();
+
+ target -= ourHead;
+ target.Normalise();
+ target = target * wepInfo->m_fRange + ourHead;
+
+ CWorld::bIncludeDeadPeds = true;
+ CEntity *foundEnt = nil;
+ CColPoint foundCol;
+
+ CWorld::ProcessLineOfSight(
+ ourHead, target, foundCol, foundEnt,
+ true, true, true, false, true, false);
+ CWorld::bIncludeDeadPeds = 0;
+ if (foundEnt == m_pedInObjective) {
+ SetAttack(m_pedInObjective);
+ m_pPointGunAt = m_pedInObjective;
+ if (m_pedInObjective)
+ m_pedInObjective->RegisterReference((CEntity **) &m_pPointGunAt);
+
+ SetShootTimer(CGeneral::GetRandomNumberInRange(500.0f, 2000.0f));
+
+ int time;
+ if (distWithTargetSc <= wepRangeAdjusted)
+ time = CGeneral::GetRandomNumberInRange(100.0f, 500.0f);
+ else
+ time = CGeneral::GetRandomNumberInRange(1500.0f, 3000.0f);
+
+ SetAttackTimer(time);
+ bObstacleShowedUpDuringKillObjective = false;
+
+ } else if (foundEnt) {
+ if (foundEnt->IsPed()) {
+ SetAttackTimer(CGeneral::GetRandomNumberInRange(500.0f, 1000.0f));
+ bObstacleShowedUpDuringKillObjective = false;
+ } else {
+ if (foundEnt->IsObject()) {
+ SetAttackTimer(CGeneral::GetRandomNumberInRange(200.0f, 400.0f));
+ bObstacleShowedUpDuringKillObjective = true;
+ } else if (foundEnt->IsVehicle()) {
+ SetAttackTimer(CGeneral::GetRandomNumberInRange(400.0f, 600.0f));
+ bObstacleShowedUpDuringKillObjective = true;
+ } else {
+ SetAttackTimer(CGeneral::GetRandomNumberInRange(700.0f, 1200.0f));
+ bObstacleShowedUpDuringKillObjective = true;
+ }
+ }
+
+ m_fleeFrom = foundEnt;
+ m_fleeFrom->RegisterReference((CEntity**) &m_fleeFrom);
+ SetPointGunAt(m_pedInObjective);
+ }
+ }
+ } else {
+ if (!m_pedInObjective->m_pCurrentPhysSurface)
+ bStopAndShoot = false;
+
+ if (m_nPedState != PED_ATTACK && m_nPedState != PED_FIGHT) {
+
+ // This is weird...
+ if (bNotAllowedToDuck && bKindaStayInSamePlace) {
+ if (!bIsDucking) {
+ CAnimBlendAssociation* duckAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_DOWN);
+ if (!duckAnim || duckAnim->blendDelta < 0.0f) {
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DUCK_DOWN, 4.0f);
+ bIsDucking = true;
+ }
+ break;
+ } else {
+ CAnimBlendAssociation* duckAnim = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_DOWN);
+ if (!duckAnim || duckAnim->blendDelta < 0.0f) {
+ bIsDucking = false;
+ } else {
+ break;
+ }
+ }
+ }
+ 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 (distWithTargetSc < 2.5f && wepRange > 5.0f
+ && wepInfo->m_eWeaponFire != WEAPON_FIRE_MELEE) {
+
+ SetAttack(m_pedInObjective);
+ if (m_attackTimer < CTimer::GetTimeInMilliseconds()) {
+ int time = CGeneral::GetRandomNumberInRange(500.0f, 1000.0f);
+ SetAttackTimer(time);
+ SetShootTimer(time - 500);
+ }
+ SetMoveState(PEDMOVE_STILL);
+ }
+ if (CTimer::GetTimeInMilliseconds() > m_nPedStateTimer)
+ m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(m_pedInObjective->GetPosition().x, m_pedInObjective->GetPosition().y, GetPosition().x, GetPosition().y);
+
+ 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);
+ }
+ break;
+ }
+ case OBJECTIVE_GOTO_CHAR_ON_FOOT:
+ {
+ if (m_pedInObjective) {
+ float safeDistance = 2.0f;
+ if (m_pedInObjective->bInVehicle)
+ safeDistance = 3.0f;
+
+ float distWithTargetSc = distWithTarget.Magnitude();
+ if (m_nPedStateTimer < CTimer::GetTimeInMilliseconds()) {
+ if (distWithTargetSc <= safeDistance) {
+ bScriptObjectiveCompleted = true;
+ if (m_nPedState != PED_ATTACK) {
+ SetIdle();
+ m_pLookTarget = m_pedInObjective;
+ m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);
+ TurnBody();
+ }
+ if (distWithTargetSc > 2.0f)
+ SetMoveState(m_pedInObjective->m_nMoveState);
+ else
+ SetMoveState(PEDMOVE_STILL);
+ } 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);
+ }
+ }
+ }
+ }
+ } 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_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->pPassengers[0] || m_carInObjective->m_nGettingInFlags & CAR_DOOR_FLAG_RF) {
+ if (m_carInObjective->pPassengers[1] || m_carInObjective->m_nGettingInFlags & CAR_DOOR_FLAG_LR) {
+ if (m_carInObjective->pPassengers[2] || m_carInObjective->m_nGettingInFlags & CAR_DOOR_FLAG_RR) {
+ foundSeat = false;
+ } else {
+ m_vehEnterType = CAR_DOOR_RR;
+ foundSeat = true;
+ }
+ } else {
+ m_vehEnterType = CAR_DOOR_LR;
+ foundSeat = true;
+ }
+ } else {
+ m_vehEnterType = CAR_DOOR_RF;
+ foundSeat = true;
+ }
+ for (int i = 2; i < m_carInObjective->m_nNumMaxPassengers; ++i) {
+ if (!m_carInObjective->pPassengers[i] && !(m_carInObjective->m_nGettingInFlags & CAR_DOOR_FLAG_RF)) {
+ m_vehEnterType = CAR_DOOR_RF;
+ foundSeat = true;
+ }
+ }
+ if (foundSeat) {
+ SetPosition(GetPositionToOpenCarDoor(m_carInObjective, m_vehEnterType));
+ SetEnterCar(m_carInObjective, m_vehEnterType);
+ }
+ }
+ m_objectiveTimer = 0;
+ }
+ }
+ // fall through
+ }
+ case OBJECTIVE_ENTER_CAR_AS_DRIVER:
+ {
+ if (!m_carInObjective || bInVehicle) {
+#ifdef VC_PED_PORTS
+ if (bInVehicle && m_pMyVehicle != m_carInObjective) {
+ SetExitCar(m_pMyVehicle, 0);
+ } else
+#endif
+ {
+ 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
+#ifdef VC_PED_PORTS
+ && !IsPlayer()
+#endif
+ ) {
+ 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
+#ifdef VC_PED_PORTS
+ && (CharCreatedBy != MISSION_CHAR || m_carInObjective->pDriver->CharCreatedBy != RANDOM_CHAR)
+#endif
+ ) {
+ 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
+#ifdef VC_PED_PORTS
+ || IsPlayer() && !CPad::GetPad(0)->ArePlayerControlsDisabled()
+#endif
+ ) {
+ 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_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() && wepInfo->m_eWeaponFire != WEAPON_FIRE_MELEE
+ && distWithTargetSc < wepRange) {
+
+ // I hope so
+ CVector ourHead = GetMatrix() * CVector(0.5f, 0.0f, 0.6f);
+ CVector maxShotPos = m_carInObjective->GetPosition() - ourHead;
+ maxShotPos.Normalise();
+ maxShotPos = maxShotPos * wepInfo->m_fRange + ourHead;
+
+ CWorld::bIncludeDeadPeds = true;
+ CColPoint foundCol;
+ CEntity *foundEnt;
+ CWorld::ProcessLineOfSight(ourHead, maxShotPos, foundCol, foundEnt,
+ true, true, true, true, false, true, false);
+ CWorld::bIncludeDeadPeds = false;
+ if (foundEnt == m_carInObjective) {
+ SetAttack(m_carInObjective);
+ m_pPointGunAt = m_carInObjective;
+ if (m_pPointGunAt)
+ m_pPointGunAt->RegisterReference((CEntity **) &m_pPointGunAt);
+
+ SetShootTimer(CGeneral::GetRandomNumberInRange(500, 2000));
+ if (distWithTargetSc > 10.0f && !bKindaStayInSamePlace) {
+ SetAttackTimer(CGeneral::GetRandomNumberInRange(2000, 5000));
+ } else {
+ SetAttackTimer(CGeneral::GetRandomNumberInRange(50, 300));
+ SetMoveState(PEDMOVE_STILL);
+ }
+ }
+ } else if (m_nPedState != PED_ATTACK && !bKindaStayInSamePlace) {
+
+ float safeDistance;
+ if (wepRange <= 5.0f)
+ safeDistance = 3.0f;
+ else
+ safeDistance = wepRange * 0.25f;
+
+ SetSeek(m_carInObjective, safeDistance);
+ SetMoveState(PEDMOVE_RUN);
+ }
+ SetLookFlag(m_carInObjective, false);
+ TurnBody();
+ 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];
+ 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;
+ }
+ // fall through
+ }
+ case OBJECTIVE_GOTO_AREA_ON_FOOT:
+ case OBJECTIVE_RUN_TO_AREA:
+ {
+ if ((m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT || m_objective == OBJECTIVE_RUN_TO_AREA)
+ && 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)
+ FindBestCoordsFromNodes(m_vecSeekPos, &bestCoords);
+
+ if (m_pNextPathNode)
+ m_vecSeekPos = m_pNextPathNode->GetPosition();
+ }
+ 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 {
+ SetSeek(m_nextRoutePointPos, 0.8f);
+ }
+ break;
+ case OBJECTIVE_SOLICIT_VEHICLE:
+ if (m_carInObjective) {
+ if (m_objectiveTimer <= CTimer::GetTimeInMilliseconds()) {
+ if (!bInVehicle) {
+ SetObjective(OBJECTIVE_NONE);
+ SetWanderPath(CGeneral::GetRandomNumber() & 7);
+ m_objectiveTimer = CTimer::GetTimeInMilliseconds() + 10000;
+ if (IsPedInControl())
+ m_pMyVehicle = nil;
+ }
+ } else {
+ if (m_nPedState != PED_FLEE_ENTITY && m_nPedState != PED_SOLICIT)
+ SetSeekCar(m_carInObjective, 0);
+ }
+ } else {
+ RestorePreviousObjective();
+ RestorePreviousState();
+ if (IsPedInControl())
+ m_pMyVehicle = nil;
+ }
+ break;
+ case OBJECTIVE_HAIL_TAXI:
+ if (!RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_TAXI) && CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
+ Say(SOUND_PED_TAXI_WAIT);
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_TAXI, 4.0f);
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 2000;
+ }
+ break;
+ case OBJECTIVE_CATCH_TRAIN:
+ {
+ if (m_carInObjective) {
+ SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, m_carInObjective);
+ } else {
+ CVehicle* trainToEnter = nil;
+ float closestCarDist = CHECK_NEARBY_THINGS_MAX_DIST;
+ CVector pos = GetPosition();
+ int16 lastVehicle;
+ CEntity* vehicles[8];
+
+ CWorld::FindObjectsInRange(pos, 10.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false);
+ for (int i = 0; i < lastVehicle; i++) {
+ CVehicle* nearVeh = (CVehicle*)vehicles[i];
+ if (nearVeh->IsTrain()) {
+ CVector vehDistVec = GetPosition() - nearVeh->GetPosition();
+ float vehDist = vehDistVec.Magnitude();
+ if (vehDist < closestCarDist && m_pedInObjective->m_pMyVehicle != nearVeh)
+ {
+ trainToEnter = nearVeh;
+ closestCarDist = vehDist;
+ }
+ }
+ }
+ if (trainToEnter) {
+ m_carInObjective = trainToEnter;
+ m_carInObjective->RegisterReference((CEntity **) &m_carInObjective);
+ }
+ }
+ break;
+ }
+ case OBJECTIVE_BUY_ICE_CREAM:
+ if (m_carInObjective) {
+ if (m_nPedState != PED_FLEE_ENTITY && m_nPedState != PED_BUY_ICECREAM)
+ SetSeekCar(m_carInObjective, 0);
+ } else {
+ RestorePreviousObjective();
+ RestorePreviousState();
+ if (IsPedInControl())
+ m_pMyVehicle = nil;
+ }
+ break;
+ case OBJECTIVE_STEAL_ANY_CAR:
+ {
+ if (bInVehicle) {
+ bScriptObjectiveCompleted = true;
+ RestorePreviousObjective();
+ } else if (m_hitRecoverTimer < CTimer::GetTimeInMilliseconds()) {
+ CVehicle *carToSteal = nil;
+ float closestCarDist = ENTER_CAR_MAX_DIST;
+ CVector pos = GetPosition();
+ int16 lastVehicle;
+ CEntity *vehicles[8];
+
+ // NB: This should've been ENTER_CAR_MAX_DIST actually, and is fixed in VC.
+ 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 *nearVeh = (CVehicle*)vehicles[i];
+ if (nearVeh->VehicleCreatedBy != MISSION_VEHICLE) {
+ if (nearVeh->m_vecMoveSpeed.Magnitude() <= 0.1f) {
+ if (nearVeh->CanPedOpenLocks(this)) {
+ CVector vehDistVec = GetPosition() - nearVeh->GetPosition();
+ float vehDist = vehDistVec.Magnitude();
+ if (vehDist < closestCarDist) {
+ carToSteal = nearVeh;
+ closestCarDist = vehDist;
+ }
+ }
+ }
+ }
+ }
+ if (carToSteal) {
+ SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, carToSteal);
+ m_hitRecoverTimer = CTimer::GetTimeInMilliseconds() + 5000;
+ } else {
+ RestorePreviousObjective();
+ RestorePreviousState();
+ }
+ }
+ break;
+ }
+ case OBJECTIVE_MUG_CHAR:
+ {
+ if (m_pedInObjective) {
+ if (m_pedInObjective->IsPlayer() || m_pedInObjective->bInVehicle || m_pedInObjective->m_fHealth <= 0.0f) {
+ ClearObjective();
+ return;
+ }
+ if (m_pedInObjective->m_nMoveState > PEDMOVE_WALK) {
+ ClearObjective();
+ return;
+ }
+ if (m_pedInObjective->m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT && m_pedInObjective->m_pedInObjective == this) {
+ SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, m_pedInObjective);
+ SetMoveState(PEDMOVE_SPRINT);
+ return;
+ }
+ if (m_pedInObjective->m_nPedState == PED_FLEE_ENTITY && m_fleeFrom == this
+ || m_pedInObjective->m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE && m_pedInObjective->m_pedInObjective == this) {
+ ClearObjective();
+ SetFindPathAndFlee(m_pedInObjective, 15000, true);
+ return;
+ }
+ float distWithTargetScSqr = distWithTarget.MagnitudeSqr();
+ if (distWithTargetScSqr <= sq(10.0f)) {
+ if (distWithTargetScSqr <= sq(1.4f)) {
+ CAnimBlendAssociation *reloadAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_AK_RELOAD);
+ 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->currentTime / reloadAssoc->hierarchy->totalLength > 0.8f)) {
+ CAnimBlendAssociation *punchAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT_PPUNCH, 8.0f);
+ punchAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ punchAssoc->flags |= ASSOC_FADEOUTWHENDONE;
+ CVector2D offset(distWithTarget.x, distWithTarget.y);
+ int dir = m_pedInObjective->GetLocalDirection(offset);
+ m_pedInObjective->StartFightDefend(dir, HITLEVEL_HIGH, 5);
+ m_pedInObjective->ReactToAttack(this);
+ m_pedInObjective->Say(SOUND_PED_ROBBED);
+ Say(SOUND_PED_MUGGING);
+ bRichFromMugging = true;
+
+ // VC FIX: ClearObjective() clears m_pedInObjective in VC (also same with VC_PED_PORTS), so get it before call
+ CPed *victim = m_pedInObjective;
+ ClearObjective();
+ if (victim->m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT
+ || victim->m_pedInObjective != this) {
+ SetFindPathAndFlee(victim, 15000, true);
+ m_nLastPedState = PED_WANDER_PATH;
+ } else {
+ SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, victim);
+ SetMoveState(PEDMOVE_SPRINT);
+ m_nLastPedState = PED_WANDER_PATH;
+ }
+ }
+ } else {
+ eWeaponType weaponType = GetWeapon()->m_eWeaponType;
+ if (weaponType != WEAPONTYPE_UNARMED && weaponType != WEAPONTYPE_BASEBALLBAT)
+ SetCurrentWeapon(WEAPONTYPE_UNARMED);
+
+ CAnimBlendAssociation *newReloadAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_AK_RELOAD, 8.0f);
+ newReloadAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ newReloadAssoc->flags |= ASSOC_FADEOUTWHENDONE;
+ }
+ } else {
+ SetSeek(m_pedInObjective, 1.0f);
+ CAnimBlendAssociation *walkAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WALK);
+
+ if (walkAssoc)
+ walkAssoc->speed = 1.3f;
+ }
+ } else {
+ ClearObjective();
+ SetWanderPath(CGeneral::GetRandomNumber() & 7);
+ }
+ } else {
+#ifdef VC_PED_PORTS
+ m_objective = OBJECTIVE_NONE;
+#endif
+ ClearObjective();
+ }
+ break;
+ }
+ 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()
+#ifdef VC_PED_PORTS
+ && (FindPlayerPed() != this || !CPad::GetPad(0)->GetAccelerate()
+ || bBusJacked)
+#endif
+ ) {
+ if (m_nPedState != PED_EXIT_CAR && m_nPedState != PED_DRAG_FROM_CAR && m_nPedState != PED_EXIT_TRAIN
+ && (m_nPedType != PEDTYPE_COP
+#ifdef VC_PED_PORTS
+ || m_pMyVehicle->IsBoat()
+#endif
+ || m_pMyVehicle->m_vecMoveSpeed.MagnitudeSqr2D() < sq(0.005f))) {
+ if (m_pMyVehicle->IsTrain())
+ SetExitTrain(m_pMyVehicle);
+#ifdef VC_PED_PORTS
+ else if (m_pMyVehicle->IsBoat())
+ SetExitBoat(m_pMyVehicle);
+#endif
+ else
+ SetExitCar(m_pMyVehicle, 0);
+ }
+ } else {
+ RestorePreviousObjective();
+ }
+ }
+ break;
+#ifdef VC_PED_PORTS
+ 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;
+ }
+#endif
+ }
+ 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_routeStartPoint = CRouteNode::GetRouteStart(currentPoint);
+ m_routePointsPassed = 0;
+ m_routeType = routeType;
+ m_routePointsBeingPassed = 1;
+ m_objective = OBJECTIVE_FOLLOW_ROUTE;
+ 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)
+ return false;
+
+ m_routePointsPassed += m_routePointsBeingPassed;
+ return true;
+}
+
+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 < m_maxWeaponTypeAllowed; i++) {
+ if (GetWeapon(i).m_nAmmoTotal > 0) {
+ eWeaponType weaponType = GetWeapon(i).m_eWeaponType;
+ if (weaponType >= WEAPONTYPE_COLT45 && weaponType != WEAPONTYPE_M16 && 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)
+ return;
+
+ if (m_leader == pedWithGun)
+ return;
+
+ if (m_nWaitState == WAITSTATE_PLAYANIM_HANDSUP || m_nWaitState == WAITSTATE_PLAYANIM_HANDSCOWER ||
+ (GetPosition() - pedWithGun->GetPosition()).MagnitudeSqr2D() > 225.0f)
+ 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;
+ }
+
+#ifdef VC_PED_PORTS
+ if (m_nPedState == PED_DRIVING && InVehicle()
+ && (m_pMyVehicle->pDriver == this || m_pMyVehicle->pDriver && m_pMyVehicle->pDriver->m_nPedState == PED_DRIVING && m_pMyVehicle->pDriver->m_objective != OBJECTIVE_LEAVE_CAR_AND_DIE)) {
+
+ if (m_pMyVehicle->VehicleCreatedBy == RANDOM_VEHICLE
+ && (m_pMyVehicle->GetStatus() == STATUS_SIMPLE || m_pMyVehicle->GetStatus() == STATUS_PHYSICS)
+ && m_pMyVehicle->AutoPilot.m_nCarMission == MISSION_CRUISE) {
+
+ CCarCtrl::SwitchVehicleToRealPhysics(m_pMyVehicle);
+ m_pMyVehicle->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;
+ m_pMyVehicle->AutoPilot.m_nCruiseSpeed = GAME_SPEED_TO_CARAI_SPEED * m_pMyVehicle->pHandling->Transmission.fUnkMaxVelocity;
+ m_pMyVehicle->SetStatus(STATUS_PHYSICS);
+ }
+ } else
+#endif
+ if (IsPedInControl() && (CharCreatedBy != MISSION_CHAR || bRespondsToThreats)) {
+ CPed *ourLeader = m_leader;
+ if (ourLeader != attacker && (!ourLeader || FindPlayerPed() != ourLeader)
+ && 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_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()) {
+#ifdef VC_PED_PORTS
+ if (ped->m_nPedState != PED_DRIVING)
+#endif
+ ped->QuitEnteringCar();
+
+ return;
+ }
+ if (ped->m_fHealth == 0.0f) {
+ ped->QuitEnteringCar();
+ return;
+ }
+ bool itsVan = !!veh->bIsVan;
+ bool itsBus = !!veh->bIsBus;
+#ifdef FIX_BUGS
+ bool itsLow = !!veh->bLowVehicle;
+#endif
+ eDoors enterDoor;
+ AnimationId enterAnim;
+
+ switch (ped->m_vehEnterType) {
+ case CAR_DOOR_RF:
+ itsVan = false;
+ enterDoor = DOOR_FRONT_RIGHT;
+ break;
+ case CAR_DOOR_RR:
+ enterDoor = DOOR_REAR_RIGHT;
+ break;
+ case CAR_DOOR_LF:
+ itsVan = false;
+ enterDoor = DOOR_FRONT_LEFT;
+ break;
+ case CAR_DOOR_LR:
+ enterDoor = DOOR_REAR_LEFT;
+ break;
+ default:
+ break;
+ }
+
+ if (veh->IsDoorMissing(enterDoor) || veh->IsDoorFullyOpen(enterDoor)) {
+
+ veh->AutoPilot.m_nCruiseSpeed = 0;
+ if (ped->m_nPedState == PED_CARJACK) {
+ ped->PedAnimDoorOpenCB(nil, ped);
+ return;
+ }
+ if (enterDoor != DOOR_FRONT_LEFT && enterDoor != DOOR_REAR_LEFT) {
+ if (itsVan) {
+ enterAnim = ANIM_VAN_GETIN;
+ } else if (itsBus) {
+ enterAnim = ANIM_COACH_IN_R;
+#ifdef FIX_BUGS
+ } else if (itsLow) {
+ enterAnim = ANIM_CAR_GETIN_LOW_RHS;
+#endif
+ } else {
+ enterAnim = ANIM_CAR_GETIN_RHS;
+ }
+ } else if (itsVan) {
+ enterAnim = ANIM_VAN_GETIN_L;
+ } else if (itsBus) {
+ enterAnim = ANIM_COACH_IN_L;
+#ifdef FIX_BUGS
+ } else if (itsLow) {
+ enterAnim = ANIM_CAR_GETIN_LOW_LHS;
+#endif
+ } else {
+ enterAnim = ANIM_CAR_GETIN_LHS;
+ }
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, enterAnim);
+ ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);
+
+ } else if (veh->CanPedOpenLocks(ped)) {
+
+ veh->AutoPilot.m_nCruiseSpeed = 0;
+ if (enterDoor != DOOR_FRONT_LEFT && enterDoor != DOOR_REAR_LEFT) {
+ if (itsVan) {
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_VAN_OPEN);
+ } else if (itsBus) {
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_COACH_OPEN_R);
+ } else {
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_OPEN_RHS);
+ }
+ } else if (itsVan) {
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_VAN_OPEN_L);
+ } else if (itsBus) {
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_COACH_OPEN_L);
+ } else {
+
+ if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER && veh->pDriver) {
+
+ if (!veh->bLowVehicle
+ && veh->pDriver->CharCreatedBy != MISSION_CHAR
+ && veh->pDriver->m_nPedState == PED_DRIVING) {
+
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_QJACK);
+ ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);
+ veh->pDriver->SetBeingDraggedFromCar(veh, ped->m_vehEnterType, true);
+
+ if (veh->pDriver->IsGangMember())
+ veh->pDriver->RegisterThreatWithGangPeds(ped);
+ return;
+ }
+ }
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_OPEN_LHS);
+ }
+ ped->m_pVehicleAnim->SetFinishCallback(PedAnimDoorOpenCB, ped);
+
+ } else {
+ if (enterDoor != DOOR_FRONT_LEFT && enterDoor != DOOR_REAR_LEFT)
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_DOORLOCKED_RHS);
+ else
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_DOORLOCKED_LHS);
+
+ ped->bCancelEnteringCar = true;
+ ped->m_pVehicleAnim->SetFinishCallback(PedAnimDoorOpenCB, ped);
+ }
+}
+
+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()) {
+#ifdef VC_PED_PORTS
+ if (ped->m_nPedState != PED_DRIVING)
+#endif
+ ped->QuitEnteringCar();
+
+ return;
+ }
+
+ eDoors door;
+ CPed *pedInSeat = nil;
+ switch (ped->m_vehEnterType) {
+ case CAR_DOOR_RF: door = DOOR_FRONT_RIGHT; pedInSeat = veh->pPassengers[0]; 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; 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) {
+ ped->QuitEnteringCar();
+ if (ped->m_vehEnterType != CAR_DOOR_LF && ped->m_vehEnterType != CAR_DOOR_LR)
+ ped->SetFall(1000, ANIM_KO_SPIN_R, false);
+ else
+ ped->SetFall(1000, ANIM_KO_SPIN_L, false);
+
+ return;
+ }
+ veh->ProcessOpenDoor(ped->m_vehEnterType, ANIM_CAR_OPEN_LHS, 1.0f);
+
+ if (ped->m_vehEnterType == CAR_DOOR_LF || ped->m_vehEnterType == CAR_DOOR_RF)
+ isVan = false;
+
+ if (ped->m_nPedState != PED_CARJACK || isBus) {
+ AnimationId animToPlay;
+ if (ped->m_vehEnterType != CAR_DOOR_LF && ped->m_vehEnterType != CAR_DOOR_LR) {
+
+ if (isVan) {
+ animToPlay = ANIM_VAN_GETIN;
+ } else if (isBus) {
+ animToPlay = ANIM_COACH_IN_R;
+ } else if (isLow) {
+ animToPlay = ANIM_CAR_GETIN_LOW_RHS;
+ } else {
+ animToPlay = ANIM_CAR_GETIN_RHS;
+ }
+ } else if (isVan) {
+ animToPlay = ANIM_VAN_GETIN_L;
+ } else if (isBus) {
+ animToPlay = ANIM_COACH_IN_L;
+ } else if (isLow) {
+ animToPlay = ANIM_CAR_GETIN_LOW_LHS;
+ } else {
+ animToPlay = ANIM_CAR_GETIN_LHS;
+ }
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, animToPlay);
+ ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);
+ } else {
+ CPed *pedToDragOut = nil;
+ switch (ped->m_vehEnterType) {
+ case CAR_DOOR_RF: pedToDragOut = veh->pPassengers[0]; break;
+ case CAR_DOOR_RR: pedToDragOut = veh->pPassengers[2]; break;
+ case CAR_DOOR_LF: pedToDragOut = veh->pDriver; break;
+ case CAR_DOOR_LR: pedToDragOut = veh->pPassengers[1]; break;
+ default: assert(0);
+ }
+
+ if (vehUpsideDown) {
+ ped->QuitEnteringCar();
+ if (ped->m_nPedType == PEDTYPE_COP)
+ ((CCopPed*)ped)->SetArrestPlayer(ped->m_pedInObjective);
+ }
+
+ if (ped->m_vehEnterType != CAR_DOOR_LF && ped->m_vehEnterType != CAR_DOOR_LR) {
+ if (pedToDragOut && !pedToDragOut->bDontDragMeOutCar) {
+ if (pedToDragOut->m_nPedState != PED_DRIVING) {
+ ped->QuitEnteringCar();
+ pedToDragOut = nil;
+ } else {
+ if (isLow)
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_PULLOUT_LOW_RHS);
+ else
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_PULLOUT_RHS);
+
+ ped->m_pVehicleAnim->SetFinishCallback(PedAnimPullPedOutCB, ped);
+ }
+ } else if (ped->m_nPedType == PEDTYPE_COP) {
+ ped->QuitEnteringCar();
+ if (ped->m_pedInObjective && ped->m_pedInObjective->m_nPedState == PED_DRIVING) {
+ veh->SetStatus(STATUS_PLAYER_DISABLED);
+ ((CCopPed*)ped)->SetArrestPlayer(ped->m_pedInObjective);
+ } else if (!veh->IsDoorMissing(DOOR_FRONT_RIGHT)) {
+ ((CAutomobile*)veh)->Damage.SetDoorStatus(DOOR_FRONT_RIGHT, DOOR_STATUS_SWINGING);
+ }
+ } else {
+ // BUG: Probably we will sit on top of the passenger if his m_ped_flagF4 is true.
+ if (isLow)
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_GETIN_LOW_LHS);
+ else
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_GETIN_LHS);
+
+ ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);
+ }
+ } else {
+ if (pedToDragOut) {
+ if (pedToDragOut->m_nPedState != PED_DRIVING || pedToDragOut->bDontDragMeOutCar) {
+
+ // BUG: Player freezes in that condition due to its objective isn't restored. It's an unfinished feature, used in VC.
+ ped->QuitEnteringCar();
+ pedToDragOut = nil;
+ } else {
+ if (isLow)
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_PULLOUT_LOW_LHS);
+ else
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_PULLOUT_LHS);
+
+ ped->m_pVehicleAnim->SetFinishCallback(PedAnimPullPedOutCB, ped);
+ }
+ } else {
+ if (isLow)
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_GETIN_LOW_LHS);
+ else
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_GETIN_LHS);
+
+ ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);
+ }
+ }
+
+ if (pedToDragOut) {
+ pedToDragOut->SetBeingDraggedFromCar(veh, ped->m_vehEnterType, false);
+ if (pedToDragOut->IsGangMember())
+ pedToDragOut->RegisterThreatWithGangPeds(ped);
+ }
+ }
+
+ if (veh->pDriver && ped) {
+ veh->pDriver->SetLookFlag(ped, true);
+ veh->pDriver->SetLookTimer(1000);
+ }
+ 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) {
+ AnimationId animToPlay;
+ if (ped->m_vehEnterType != CAR_DOOR_LF && ped->m_vehEnterType != CAR_DOOR_LR) {
+ if (isLow)
+ animToPlay = ANIM_CAR_GETIN_LOW_RHS;
+ else
+ animToPlay = ANIM_CAR_GETIN_RHS;
+ } else if (isLow) {
+ animToPlay = ANIM_CAR_GETIN_LOW_LHS;
+ } else {
+ animToPlay = ANIM_CAR_GETIN_LHS;
+ }
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, animToPlay);
+ ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);
+ } else {
+ ped->QuitEnteringCar();
+ }
+ } else {
+ 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()) {
+#ifdef VC_PED_PORTS
+ if(ped->m_nPedState != PED_DRIVING)
+#endif
+ ped->QuitEnteringCar();
+ return;
+ }
+
+ if (ped->IsPlayer() && ped->bGonnaKillTheCarJacker && ((CPlayerPed*)ped)->m_pArrestingCop) {
+ PedSetInCarCB(nil, ped);
+ ped->m_nLastPedState = ped->m_nPedState;
+ ped->m_nPedState = PED_ARRESTED;
+ ped->bGonnaKillTheCarJacker = false;
+ if (veh) {
+ veh->m_nNumGettingIn = 0;
+ veh->m_nGettingInFlags = 0;
+ veh->bIsHandbrakeOn = true;
+ veh->SetStatus(STATUS_PLAYER_DISABLED);
+ }
+ return;
+ }
+ if (ped->IsPlayer() && ped->m_vehEnterType == CAR_DOOR_LF
+ && (Pads[0].GetAccelerate() >= 255.0f || Pads[0].GetBrake() >= 255.0f)
+ && veh->IsCar()) {
+ 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;
+ }
+ bool isVan = !!veh->bIsVan;
+ bool isBus = !!veh->bIsBus;
+ bool isLow = !!veh->bLowVehicle;
+ eDoors enterDoor;
+ switch (ped->m_vehEnterType) {
+ case CAR_DOOR_RF:
+ isVan = false;
+ enterDoor = DOOR_FRONT_RIGHT;
+ break;
+ case CAR_DOOR_RR:
+ enterDoor = DOOR_REAR_RIGHT;
+ break;
+ case CAR_DOOR_LF:
+ isVan = false;
+ enterDoor = DOOR_FRONT_LEFT;
+ break;
+ case CAR_DOOR_LR:
+ enterDoor = DOOR_REAR_LEFT;
+ break;
+ default:
+ break;
+ }
+ if (!veh->IsDoorMissing(enterDoor)) {
+ if (veh->IsCar())
+ ((CAutomobile*)veh)->Damage.SetDoorStatus(enterDoor, DOOR_STATUS_SWINGING);
+ }
+ CPed *driver = veh->pDriver;
+ if (driver && (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || ped->m_nPedState == PED_CARJACK)) {
+ if (veh->bIsBus) {
+ driver->SetObjective(OBJECTIVE_LEAVE_CAR, veh);
+ if (driver->IsPlayer()) {
+ veh->bIsHandbrakeOn = true;
+ veh->SetStatus(STATUS_PLAYER_DISABLED);
+ }
+ driver->bBusJacked = true;
+ veh->bIsBeingCarJacked = false;
+ PedSetInCarCB(nil, ped);
+ if (ped->m_nPedType == PEDTYPE_COP
+ || ped->m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT
+ || ped->m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS) {
+ ped->SetObjective(OBJECTIVE_LEAVE_CAR, veh);
+ }
+ ped->m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 400;
+ return;
+ }
+ if (driver != ped && ped->m_vehEnterType != CAR_DOOR_LF) {
+ if (!driver->IsPlayer()) {
+ driver->bUsePedNodeSeek = true;
+ driver->m_pLastPathNode = nil;
+ if (driver->m_pedStats->m_temper <= driver->m_pedStats->m_fear
+ || driver->CharCreatedBy == MISSION_CHAR
+ || veh->VehicleCreatedBy == MISSION_VEHICLE) {
+ driver->bFleeAfterExitingCar = true;
+ } else {
+ driver->bGonnaKillTheCarJacker = true;
+ veh->pDriver->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, ped);
+
+ if (veh->pDriver->m_nPedType == PEDTYPE_COP && ped->IsPlayer()) {
+ FindPlayerPed()->SetWantedLevelNoDrop(1);
+ }
+ }
+ }
+ if ((ped->m_nPedType != PEDTYPE_EMERGENCY || veh->pDriver->m_nPedType != PEDTYPE_EMERGENCY)
+ && (ped->m_nPedType != PEDTYPE_COP || veh->pDriver->m_nPedType != PEDTYPE_COP)) {
+ veh->pDriver->SetObjective(OBJECTIVE_LEAVE_CAR, veh);
+ veh->pDriver->Say(SOUND_PED_CAR_JACKED);
+#ifdef VC_PED_PORTS
+ veh->pDriver->SetRadioStation();
+#endif
+ } else {
+ ped->m_objective = OBJECTIVE_ENTER_CAR_AS_PASSENGER;
+ }
+ }
+ }
+ if (veh->IsDoorMissing(enterDoor) || isBus) {
+ PedAnimDoorCloseCB(nil, ped);
+ } else {
+ AnimationId animToPlay;
+ if (enterDoor != DOOR_FRONT_LEFT && enterDoor != DOOR_REAR_LEFT) {
+ if (isVan) {
+ animToPlay = ANIM_VAN_CLOSE;
+ } else if (isLow) {
+ animToPlay = ANIM_CAR_CLOSEDOOR_LOW_RHS;
+ } else {
+ animToPlay = ANIM_CAR_CLOSEDOOR_RHS;
+ }
+ } else if (isVan) {
+ animToPlay = ANIM_VAN_CLOSE_L;
+ } else if (isLow) {
+ animToPlay = ANIM_CAR_CLOSEDOOR_LOW_LHS;
+ } else {
+ animToPlay = ANIM_CAR_CLOSEDOOR_LHS;
+ }
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, animToPlay);
+ ped->m_pVehicleAnim->SetFinishCallback(PedAnimDoorCloseCB, ped);
+ }
+}
+
+void
+CPed::PedAnimDoorCloseCB(CAnimBlendAssociation *animAssoc, void *arg)
+{
+ CPed *ped = (CPed*)arg;
+
+ CAutomobile *veh = (CAutomobile*)(ped->m_pMyVehicle);
+
+ if (!ped->IsNotInWreckedVehicle() || ped->DyingOrDead())
+ return;
+
+ if (ped->EnteringCar()) {
+ bool isLow = !!veh->bLowVehicle;
+
+ if (!veh->bIsBus)
+ veh->ProcessOpenDoor(ped->m_vehEnterType, ANIM_CAR_CLOSEDOOR_LHS, 1.0f);
+
+ eDoors door;
+ switch (ped->m_vehEnterType) {
+ case CAR_DOOR_RF: door = DOOR_FRONT_RIGHT; break;
+ case CAR_DOOR_RR: door = DOOR_REAR_RIGHT; break;
+ case CAR_DOOR_LF: door = DOOR_FRONT_LEFT; break;
+ case CAR_DOOR_LR: door = DOOR_REAR_LEFT; break;
+ default: assert(0);
+ }
+
+ if (veh->Damage.GetDoorStatus(door) == DOOR_STATUS_SWINGING)
+ veh->Damage.SetDoorStatus(door, DOOR_STATUS_OK);
+
+ if (door == DOOR_FRONT_LEFT || ped->m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER || veh->bIsBus) {
+ PedSetInCarCB(nil, ped);
+ } else if (ped->m_vehEnterType == CAR_DOOR_RF
+ && (veh->m_nGettingInFlags & CAR_DOOR_FLAG_LF ||
+ (veh->pDriver != nil &&
+ (veh->pDriver->m_objective != OBJECTIVE_LEAVE_CAR
+#ifdef VC_PED_PORTS
+ && veh->pDriver->m_objective != OBJECTIVE_LEAVE_CAR_AND_DIE
+#endif
+ || !veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, nil))))) {
+
+ if (ped->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER
+#if defined VC_PED_PORTS || defined FIX_BUGS
+ || ped->m_nPedState == PED_CARJACK
+#endif
+ )
+ veh->bIsBeingCarJacked = false;
+
+ ped->m_objective = OBJECTIVE_ENTER_CAR_AS_PASSENGER;
+ PedSetInCarCB(nil, ped);
+
+ ped->SetObjective(OBJECTIVE_LEAVE_CAR, veh);
+ if (!ped->IsPlayer())
+ ped->bFleeAfterExitingCar = true;
+
+ ped->bUsePedNodeSeek = true;
+ ped->m_pNextPathNode = nil;
+
+ } else {
+ if (animAssoc)
+ animAssoc->blendDelta = -1000.0f;
+
+ if (isLow)
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_LSHUFFLE_RHS);
+ else
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_SHUFFLE_RHS);
+
+ ped->m_pVehicleAnim->SetFinishCallback(PedSetInCarCB, ped);
+ }
+ } else {
+#ifdef VC_PED_PORTS
+ if (ped->m_nPedState != PED_DRIVING)
+#endif
+ 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->m_nPedState == PED_DEAD) {
+ if (!m_pedInObjective->m_pedInObjective) {
+ m_pedInObjective = nil;
+ return GetPosition();
+ }
+ m_pedInObjective = m_pedInObjective->m_pedInObjective;
+ }
+
+ CVector formationOffset;
+ switch (m_pedFormation) {
+ case FORMATION_REAR:
+ formationOffset = CVector(0.0f, -1.5f, 0.0f);
+ break;
+ case FORMATION_REAR_LEFT:
+ formationOffset = CVector(-1.5f, -1.5f, 0.0f);
+ break;
+ case FORMATION_REAR_RIGHT:
+ formationOffset = CVector(1.5f, -1.5f, 0.0f);
+ break;
+ case FORMATION_FRONT_LEFT:
+ formationOffset = CVector(-1.5f, 1.5f, 0.0f);
+ break;
+ case FORMATION_FRONT_RIGHT:
+ formationOffset = CVector(1.5f, 1.5f, 0.0f);
+ break;
+ case FORMATION_LEFT:
+ formationOffset = CVector(-1.5f, 0.0f, 0.0f);
+ break;
+ case FORMATION_RIGHT:
+ formationOffset = CVector(1.5f, 0.0f, 0.0f);
+ break;
+ case FORMATION_FRONT:
+ formationOffset = CVector(0.0f, 1.5f, 0.0f);
+ break;
+ default:
+ formationOffset = CVector(0.0f, 0.0f, 0.0f);
+ break;
+ }
+ return formationOffset + m_pedInObjective->GetPosition();
+}
+
+void
+CPed::PedAnimStepOutCarCB(CAnimBlendAssociation* animAssoc, void* arg)
+{
+ CPed* ped = (CPed*)arg;
+
+ CVehicle* veh = ped->m_pMyVehicle;
+ if (animAssoc)
+ animAssoc->blendDelta = -1000.0f;
+
+ if (!veh) {
+ PedSetOutCarCB(nil, ped);
+ return;
+ }
+#ifdef VC_PED_PORTS
+ CVector posForZ = ped->GetPosition();
+ CPedPlacement::FindZCoorForPed(&posForZ);
+ if (ped->GetPosition().z - 0.5f > posForZ.z) {
+ PedSetOutCarCB(nil, ped);
+ return;
+ }
+#endif
+ veh->m_nStaticFrames = 0;
+ veh->m_vecMoveSpeed += CVector(0.001f, 0.001f, 0.001f);
+ veh->m_vecTurnSpeed += CVector(0.001f, 0.001f, 0.001f);
+ if (!veh->bIsBus)
+ veh->ProcessOpenDoor(ped->m_vehEnterType, ANIM_CAR_GETOUT_LHS, 1.0f);
+
+ /*
+ // Duplicate and only in PC for some reason
+ if (!veh) {
+ PedSetOutCarCB(nil, ped);
+ return;
+ }
+ */
+ eDoors door;
+ switch (ped->m_vehEnterType) {
+ case CAR_DOOR_RF:
+ door = DOOR_FRONT_RIGHT;
+ break;
+ case CAR_DOOR_RR:
+ door = DOOR_REAR_RIGHT;
+ break;
+ case CAR_DOOR_LF:
+ door = DOOR_FRONT_LEFT;
+ break;
+ case CAR_DOOR_LR:
+ door = DOOR_REAR_LEFT;
+ break;
+ default:
+ break;
+ }
+ bool closeDoor = !veh->IsDoorMissing(door);
+
+ int padNo;
+ if (ped->IsPlayer()) {
+
+ // BUG? This will cause crash if m_nPedType is bigger then 1, there are only 2 pads
+ switch (ped->m_nPedType) {
+ case PEDTYPE_PLAYER1:
+ padNo = 0;
+ break;
+ case PEDTYPE_PLAYER2:
+ padNo = 1;
+ break;
+ case PEDTYPE_PLAYER3:
+ padNo = 2;
+ break;
+ case PEDTYPE_PLAYER4:
+ padNo = 3;
+ break;
+ }
+ CPad* pad = CPad::GetPad(padNo);
+ bool engineIsIntact = veh->IsCar() && ((CAutomobile*)veh)->Damage.GetEngineStatus() >= 225;
+ if (!pad->ArePlayerControlsDisabled() && veh->m_nDoorLock != CARLOCK_FORCE_SHUT_DOORS
+ && (pad->GetTarget()
+ || pad->NewState.LeftStickX
+ || pad->NewState.LeftStickY
+ || pad->NewState.DPadUp
+ || pad->NewState.DPadDown
+ || pad->NewState.DPadLeft
+ || pad->NewState.DPadRight)
+ || veh->bIsBus
+ || veh->m_pCarFire
+ || engineIsIntact) {
+ closeDoor = false;
+ }
+ }
+
+#ifdef VC_PED_PORTS
+ if (ped->m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE)
+ closeDoor = false;
+#endif
+
+ if (!closeDoor) {
+ if (!veh->IsDoorMissing(door) && !veh->bIsBus) {
+ ((CAutomobile*)veh)->Damage.SetDoorStatus(door, DOOR_STATUS_SWINGING);
+ }
+ PedSetOutCarCB(nil, ped);
+ return;
+ }
+
+ if (ped->bFleeAfterExitingCar || ped->bGonnaKillTheCarJacker) {
+ // POTENTIAL BUG? Why DOOR_FRONT_LEFT instead of door variable? or vice versa?
+ if (!veh->IsDoorMissing(door))
+ ((CAutomobile*)veh)->Damage.SetDoorStatus(DOOR_FRONT_LEFT, DOOR_STATUS_SWINGING);
+ } else {
+ switch (door) {
+ case DOOR_FRONT_LEFT:
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_CLOSE_LHS);
+ break;
+ case DOOR_FRONT_RIGHT:
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_CLOSE_RHS);
+ break;
+ case DOOR_REAR_LEFT:
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_CLOSE_LHS);
+ break;
+ case DOOR_REAR_RIGHT:
+ ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_CAR_CLOSE_RHS);
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (ped->m_pVehicleAnim)
+ ped->m_pVehicleAnim->SetFinishCallback(PedSetOutCarCB, ped);
+ return;
+}
+
+void
+CPed::LineUpPedWithCar(PedLineUpPhase phase)
+{
+ bool vehIsUpsideDown = false;
+ int vehAnim;
+ float seatPosMult = 0.0f;
+ float currentZ;
+ float adjustedTimeStep;
+
+ if (CReplay::IsPlayingBack())
+ return;
+
+ if (!bChangedSeat && phase != LINE_UP_TO_CAR_2) {
+ if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SIT)) {
+ SetPedPositionInCar();
+ return;
+ }
+ if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_LSIT)) {
+ SetPedPositionInCar();
+ return;
+ }
+ if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SITP)) {
+ SetPedPositionInCar();
+ return;
+ }
+ if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SITPLO)) {
+ SetPedPositionInCar();
+ return;
+ }
+ bChangedSeat = true;
+ }
+ if (phase == LINE_UP_TO_CAR_START) {
+ m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
+ }
+ CVehicle *veh = m_pMyVehicle;
+
+ // Not quite right, IsUpsideDown func. checks for <= -0.9f.
+ if (veh->GetUp().z <= -0.8f)
+ vehIsUpsideDown = true;
+
+ if (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR) {
+ if (vehIsUpsideDown) {
+ m_fRotationDest = -PI + veh->GetForward().Heading();
+ } else if (veh->bIsBus) {
+ m_fRotationDest = 0.5f * PI + veh->GetForward().Heading();
+ } else {
+ m_fRotationDest = veh->GetForward().Heading();
+ }
+ } else if (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR) {
+ if (vehIsUpsideDown) {
+ m_fRotationDest = veh->GetForward().Heading();
+ } else if (veh->bIsBus) {
+ m_fRotationDest = -0.5f * PI + veh->GetForward().Heading();
+ } else {
+ m_fRotationDest = veh->GetForward().Heading();
+ }
+ } else {
+ // I don't know will this part ever run(maybe boats?), but the game also handles that. I don't know is it intentional.
+
+ if (vehIsUpsideDown) {
+ m_fRotationDest = veh->GetForward().Heading();
+ } else if (veh->bIsBus) {
+ m_fRotationDest = 0.5f * PI + veh->GetForward().Heading();
+ } else {
+ m_fRotationDest = veh->GetForward().Heading();
+ }
+ }
+
+ if (!bInVehicle)
+ seatPosMult = 1.0f;
+
+#ifdef VC_PED_PORTS
+ bool multExtractedFromAnim = false;
+ bool multExtractedFromAnimBus = false;
+ float zBlend;
+#endif
+ if (m_pVehicleAnim) {
+ vehAnim = m_pVehicleAnim->animId;
+
+ switch (vehAnim) {
+ case ANIM_CAR_JACKED_RHS:
+ case ANIM_CAR_LJACKED_RHS:
+ case ANIM_CAR_JACKED_LHS:
+ case ANIM_CAR_LJACKED_LHS:
+ case ANIM_VAN_GETIN_L:
+ case ANIM_VAN_GETIN:
+#ifdef VC_PED_PORTS
+ multExtractedFromAnim = true;
+ zBlend = Max(m_pVehicleAnim->currentTime / m_pVehicleAnim->hierarchy->totalLength - 0.3f, 0.0f) / (1.0f - 0.3f);
+ // fall through
+#endif
+ case ANIM_CAR_QJACKED:
+ case ANIM_CAR_GETOUT_LHS:
+ case ANIM_CAR_GETOUT_LOW_LHS:
+ case ANIM_CAR_GETOUT_RHS:
+ case ANIM_CAR_GETOUT_LOW_RHS:
+#ifdef VC_PED_PORTS
+ if (!multExtractedFromAnim) {
+ multExtractedFromAnim = true;
+ zBlend = Max(m_pVehicleAnim->currentTime / m_pVehicleAnim->hierarchy->totalLength - 0.5f, 0.0f) / (1.0f - 0.5f);
+ }
+ // fall through
+#endif
+ case ANIM_CAR_CRAWLOUT_RHS:
+ case ANIM_CAR_CRAWLOUT_RHS2:
+ case ANIM_VAN_GETOUT_L:
+ case ANIM_VAN_GETOUT:
+ seatPosMult = m_pVehicleAnim->currentTime / m_pVehicleAnim->hierarchy->totalLength;
+ break;
+ case ANIM_CAR_GETIN_RHS:
+ case ANIM_CAR_GETIN_LHS:
+#ifdef VC_PED_PORTS
+ if (veh && veh->IsCar() && veh->bIsBus) {
+ multExtractedFromAnimBus = true;
+ zBlend = Min(m_pVehicleAnim->currentTime / m_pVehicleAnim->hierarchy->totalLength, 0.5f) / 0.5f;
+ }
+ // fall through
+#endif
+ case ANIM_CAR_QJACK:
+ case ANIM_CAR_GETIN_LOW_LHS:
+ case ANIM_CAR_GETIN_LOW_RHS:
+ case ANIM_DRIVE_BOAT:
+ seatPosMult = m_pVehicleAnim->GetTimeLeft() / m_pVehicleAnim->hierarchy->totalLength;
+ break;
+ case ANIM_CAR_CLOSEDOOR_LHS:
+ case ANIM_CAR_CLOSEDOOR_LOW_LHS:
+ case ANIM_CAR_CLOSEDOOR_RHS:
+ case ANIM_CAR_CLOSEDOOR_LOW_RHS:
+ case ANIM_CAR_SHUFFLE_RHS:
+ case ANIM_CAR_LSHUFFLE_RHS:
+ seatPosMult = 0.0f;
+ break;
+ case ANIM_CAR_CLOSE_LHS:
+ case ANIM_CAR_CLOSE_RHS:
+ case ANIM_COACH_OPEN_L:
+ case ANIM_COACH_OPEN_R:
+ case ANIM_COACH_IN_L:
+ case ANIM_COACH_IN_R:
+ case ANIM_COACH_OUT_L:
+ seatPosMult = 1.0f;
+ break;
+ default:
+ break;
+ }
+ }
+
+ CVector neededPos;
+
+ if (phase == LINE_UP_TO_CAR_2) {
+ neededPos = GetPosition();
+ } else {
+ neededPos = GetPositionToOpenCarDoor(veh, m_vehEnterType, seatPosMult);
+ }
+
+ CVector 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) {
+#ifdef VC_PED_PORTS
+ if (multExtractedFromAnim) {
+ neededPos.z += (autoZPos.z - neededPos.z) * zBlend;
+ } else {
+#endif
+ currentZ = GetPosition().z;
+ if (m_pVehicleAnim && vehAnim != ANIM_VAN_GETIN_L && vehAnim != ANIM_VAN_CLOSE_L && vehAnim != ANIM_VAN_CLOSE && vehAnim != ANIM_VAN_GETIN) {
+ neededPos.z = autoZPos.z;
+ m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
+ } else if (neededPos.z <= currentZ && m_pVehicleAnim && vehAnim != ANIM_VAN_CLOSE_L && vehAnim != ANIM_VAN_CLOSE) {
+ adjustedTimeStep = Min(m_pVehicleAnim->timeStep, 0.1f);
+
+ // Smoothly change ped position
+ neededPos.z = currentZ - (currentZ - neededPos.z) / (m_pVehicleAnim->GetTimeLeft() / adjustedTimeStep);
+ }
+#ifdef VC_PED_PORTS
+ }
+#endif
+ } else {
+ // We may need to raise up the ped
+ if (phase == LINE_UP_TO_CAR_START) {
+ currentZ = GetPosition().z;
+
+ if (neededPos.z > currentZ) {
+#ifdef VC_PED_PORTS
+ if (multExtractedFromAnimBus) {
+ neededPos.z = (neededPos.z - currentZ) * zBlend + currentZ;
+ } else {
+#endif
+ if (m_pVehicleAnim &&
+ (vehAnim == ANIM_CAR_GETIN_RHS || vehAnim == ANIM_CAR_GETIN_LOW_RHS || vehAnim == ANIM_CAR_GETIN_LHS || vehAnim == ANIM_CAR_GETIN_LOW_LHS
+ || vehAnim == ANIM_CAR_QJACK || vehAnim == ANIM_VAN_GETIN_L || vehAnim == ANIM_VAN_GETIN)) {
+ adjustedTimeStep = Min(m_pVehicleAnim->timeStep, 0.1f);
+
+ // Smoothly change ped position
+ neededPos.z = (neededPos.z - currentZ) / (m_pVehicleAnim->GetTimeLeft() / adjustedTimeStep) + currentZ;
+ } else if (EnteringCar()) {
+ neededPos.z = Max(currentZ, autoZPos.z);
+ }
+#ifdef VC_PED_PORTS
+ }
+#endif
+ }
+ }
+ }
+
+ bool stillGettingInOut = false;
+ if (CTimer::GetTimeInMilliseconds() < m_nPedStateTimer)
+ stillGettingInOut = veh->m_vehType != VEHICLE_TYPE_BOAT || bOnBoat;
+
+ if (!stillGettingInOut) {
+ m_fRotationCur = m_fRotationDest;
+ } else {
+ float limitedDest = CGeneral::LimitRadianAngle(m_fRotationDest);
+ float timeUntilStateChange = (m_nPedStateTimer - CTimer::GetTimeInMilliseconds())/600.0f;
+
+ if (timeUntilStateChange <= 0.0f) {
+ m_vecOffsetSeek.x = 0.0f;
+ m_vecOffsetSeek.y = 0.0f;
+ }
+ m_vecOffsetSeek.z = 0.0f;
+
+ neededPos -= timeUntilStateChange * m_vecOffsetSeek;
+
+ if (PI + m_fRotationCur < limitedDest) {
+ limitedDest -= 2 * PI;
+ } else if (m_fRotationCur - PI > limitedDest) {
+ limitedDest += 2 * PI;
+ }
+ m_fRotationCur -= (m_fRotationCur - limitedDest) * (1.0f - timeUntilStateChange);
+ }
+
+ if (seatPosMult > 0.2f || vehIsUpsideDown) {
+ SetPosition(neededPos);
+ SetHeading(m_fRotationCur);
+ } else {
+ CMatrix vehDoorMat(veh->GetMatrix());
+ vehDoorMat.GetPosition() += Multiply3x3(vehDoorMat, GetLocalPositionToOpenCarDoor(veh, m_vehEnterType, 0.0f));
+ // VC couch anims are inverted, so they're fixing it here.
+ GetMatrix() = vehDoorMat;
+ }
+
+}
+
+void
+CPed::SetCarJack(CVehicle* car)
+{
+ uint8 doorFlag;
+ eDoors door;
+ CPed *pedInSeat = nil;
+
+ if (car->IsBoat())
+ return;
+
+ switch (m_vehEnterType) {
+ case CAR_DOOR_RF:
+ doorFlag = CAR_DOOR_FLAG_RF;
+ door = DOOR_FRONT_RIGHT;
+ if (car->pPassengers[0]) {
+ pedInSeat = car->pPassengers[0];
+ } else if (m_nPedType == PEDTYPE_COP) {
+ pedInSeat = car->pDriver;
+ }
+ break;
+ case CAR_DOOR_RR:
+ doorFlag = CAR_DOOR_FLAG_RR;
+ door = DOOR_REAR_RIGHT;
+ pedInSeat = car->pPassengers[2];
+ break;
+ case CAR_DOOR_LF:
+ doorFlag = CAR_DOOR_FLAG_LF;
+ door = DOOR_FRONT_LEFT;
+ pedInSeat = car->pDriver;
+ break;
+ case CAR_DOOR_LR:
+ doorFlag = CAR_DOOR_FLAG_LR;
+ door = DOOR_REAR_LEFT;
+ pedInSeat = car->pPassengers[1];
+ break;
+ default:
+ doorFlag = CAR_DOOR_FLAG_UNKNOWN;
+ break;
+ }
+
+ if(car->bIsBus)
+ pedInSeat = car->pDriver;
+
+ if (m_fHealth > 0.0f && (IsPlayer() || m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS ||
+ (car->VehicleCreatedBy != MISSION_VEHICLE && car->GetModelIndex() != MI_DODO)))
+ if (pedInSeat && !pedInSeat->IsPedDoingDriveByShooting() && pedInSeat->m_nPedState == PED_DRIVING)
+ if (m_nPedState != PED_CARJACK && !m_pVehicleAnim)
+ if ((car->IsDoorReady(door) || car->IsDoorFullyOpen(door)))
+ if (!car->bIsBeingCarJacked && !(doorFlag & car->m_nGettingInFlags) && !(doorFlag & car->m_nGettingOutFlags))
+ SetCarJack_AllClear(car, m_vehEnterType, doorFlag);
+}
+
+void
+CPed::SetCarJack_AllClear(CVehicle *car, uint32 doorNode, uint32 doorFlag)
+{
+ RemoveWeaponWhenEnteringVehicle();
+ if (m_nPedState != PED_SEEK_CAR)
+ SetStoredState();
+
+ m_pSeekTarget = car;
+ m_pSeekTarget->RegisterReference((CEntity**)&m_pSeekTarget);
+ m_nPedState = PED_CARJACK;
+ car->bIsBeingCarJacked = true;
+ m_pMyVehicle = (CVehicle*)m_pSeekTarget;
+ m_pMyVehicle->RegisterReference((CEntity**)&m_pMyVehicle);
+ ((CVehicle*)m_pSeekTarget)->m_nNumGettingIn++;
+
+ Say(m_nPedType == PEDTYPE_COP ? SOUND_PED_ARREST_COP : SOUND_PED_CAR_JACKING);
+ CVector carEnterPos;
+ carEnterPos = GetPositionToOpenCarDoor(car, m_vehEnterType);
+
+ car->m_nGettingInFlags |= doorFlag;
+ m_vecOffsetSeek = carEnterPos - GetPosition();
+ m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 600;
+ float zDiff = Max(0.0f, carEnterPos.z - GetPosition().z);
+ bUsesCollision = false;
+
+ if (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR)
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, zDiff > 4.4f ? ANIM_CAR_ALIGNHI_LHS : ANIM_CAR_ALIGN_LHS, 4.0f);
+ else
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, zDiff > 4.4f ? ANIM_CAR_ALIGNHI_RHS : ANIM_CAR_ALIGN_RHS, 4.0f);
+
+ m_pVehicleAnim->SetFinishCallback(PedAnimAlignCB, this);
+}
+
+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);
+ m_vehEnterType = vehEnterType;
+ if (m_vehEnterType == CAR_DOOR_LF) {
+ if (veh->pDriver && veh->pDriver->IsPlayer())
+ veh->SetStatus(STATUS_PLAYER_DISABLED);
+ else
+ veh->SetStatus(STATUS_ABANDONED);
+ }
+ RemoveInCarAnims();
+ SetMoveState(PEDMOVE_NONE);
+ LineUpPedWithCar(LINE_UP_TO_CAR_START);
+ m_pVehicleAnim = nil;
+ m_nPedState = PED_DRAG_FROM_CAR;
+ bChangedSeat = false;
+ bWillBeQuickJacked = quickJack;
+
+ SetHeading(m_fRotationCur);
+
+ Say(SOUND_PED_CAR_JACKED);
+ SetRadioStation();
+ veh->m_nGettingOutFlags |= GetCarDoorFlag(m_vehEnterType);
+}
+
+void
+CPed::BeingDraggedFromCar(void)
+{
+ CAnimBlendAssociation *animAssoc;
+ AnimationId enterAnim;
+ bool dontRunAnim = false;
+ PedLineUpPhase lineUpType;
+
+ if (!m_pVehicleAnim) {
+ CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 100.0f);
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SIT);
+ if (!animAssoc) {
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_LSIT);
+ if (!animAssoc) {
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SITP);
+ if (!animAssoc)
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SITPLO);
+ }
+ }
+ if (animAssoc)
+ animAssoc->blendDelta = -1000.0f;
+
+ if (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR) {
+ if (bWillBeQuickJacked) {
+ enterAnim = ANIM_CAR_QJACKED;
+ } else if (m_pMyVehicle->bLowVehicle) {
+ enterAnim = ANIM_CAR_LJACKED_LHS;
+ } else {
+ enterAnim = ANIM_CAR_JACKED_LHS;
+ }
+ } else if (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR) {
+ if (m_pMyVehicle->bLowVehicle)
+ enterAnim = ANIM_CAR_LJACKED_RHS;
+ else
+ enterAnim = ANIM_CAR_JACKED_RHS;
+ } else
+ dontRunAnim = true;
+
+
+ if (!dontRunAnim)
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, enterAnim);
+
+ m_pVehicleAnim->SetFinishCallback(PedSetDraggedOutCarCB, this);
+ lineUpType = LINE_UP_TO_CAR_START;
+ } else if (m_pVehicleAnim->currentTime <= 1.4f) {
+ m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
+ lineUpType = LINE_UP_TO_CAR_START;
+ } else {
+ lineUpType = LINE_UP_TO_CAR_2;
+ }
+
+ LineUpPedWithCar(lineUpType);
+#ifdef VC_PED_PORTS
+ if (m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE) {
+ if (m_pMyVehicle) {
+ m_pMyVehicle->ProcessOpenDoor(m_vehEnterType, NUM_ANIMS, m_pVehicleAnim->currentTime * 5.0f);
+ }
+ }
+#endif
+}
+
+void
+CPed::SetEnterCar(CVehicle *car, uint32 unused)
+{
+ if (CCranes::IsThisCarBeingCarriedByAnyCrane(car)) {
+ RestorePreviousState();
+ RestorePreviousObjective();
+ } else {
+ uint8 doorFlag;
+ eDoors door;
+ switch (m_vehEnterType) {
+ case CAR_DOOR_RF:
+ doorFlag = CAR_DOOR_FLAG_RF;
+ door = DOOR_FRONT_RIGHT;
+ break;
+ case CAR_DOOR_RR:
+ doorFlag = CAR_DOOR_FLAG_RR;
+ door = DOOR_REAR_RIGHT;
+ break;
+ case CAR_DOOR_LF:
+ doorFlag = CAR_DOOR_FLAG_LF;
+ door = DOOR_FRONT_LEFT;
+ break;
+ case CAR_DOOR_LR:
+ doorFlag = CAR_DOOR_FLAG_LR;
+ door = DOOR_REAR_LEFT;
+ break;
+ default:
+ doorFlag = CAR_DOOR_FLAG_UNKNOWN;
+ break;
+ }
+ if (!IsPedInControl() || m_fHealth <= 0.0f
+ || doorFlag & car->m_nGettingInFlags || doorFlag & car->m_nGettingOutFlags
+ || car->bIsBeingCarJacked || m_pVehicleAnim
+ || doorFlag && !car->IsDoorReady(door) && !car->IsDoorFullyOpen(door))
+ SetMoveState(PEDMOVE_STILL);
+ else
+ SetEnterCar_AllClear(car, m_vehEnterType, doorFlag);
+ }
+}
+
+void
+CPed::SetEnterCar_AllClear(CVehicle *car, uint32 doorNode, uint32 doorFlag)
+{
+ float zDiff = 0.0f;
+ RemoveWeaponWhenEnteringVehicle();
+ car->m_nGettingInFlags |= doorFlag;
+ bVehEnterDoorIsBlocked = false;
+ if (m_nPedState != PED_SEEK_CAR && m_nPedState != PED_SEEK_IN_BOAT)
+ SetStoredState();
+
+ m_pSeekTarget = car;
+ m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget);
+ m_vehEnterType = doorNode;
+ m_nPedState = PED_ENTER_CAR;
+ if (m_vehEnterType == CAR_DOOR_RF && m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER && car->m_vehType != VEHICLE_TYPE_BIKE) {
+ car->bIsBeingCarJacked = true;
+ }
+
+ m_pMyVehicle = (CVehicle*)m_pSeekTarget;
+ m_pMyVehicle->RegisterReference((CEntity**) &m_pMyVehicle);
+ ((CVehicle*)m_pSeekTarget)->m_nNumGettingIn++;
+ bUsesCollision = false;
+ CVector doorOpenPos = GetPositionToOpenCarDoor(car, m_vehEnterType);
+
+ // Because buses have stairs
+ if (!m_pMyVehicle->bIsBus)
+ zDiff = Max(0.0f, doorOpenPos.z - GetPosition().z);
+
+ m_vecOffsetSeek = doorOpenPos - GetPosition();
+ m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 600;
+ if (car->IsBoat()) {
+#ifdef VC_PED_PORTS
+ // VC checks for handling flag, but we can't do that
+ if(car->GetModelIndex() == MI_SPEEDER)
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_SIT, 100.0f);
+ else
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_BOAT, 100.0f);
+
+ PedSetInCarCB(nil, this);
+ bVehExitWillBeInstant = true;
+#else
+
+#ifndef FIX_BUGS
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DRIVE_BOAT, 100.0f);
+#else
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, car->GetDriverAnim(), 100.0f);
+#endif
+
+ m_pVehicleAnim->SetFinishCallback(PedSetInCarCB, this);
+#endif
+ if (IsPlayer())
+ CWaterLevel::AllocateBoatWakeArray();
+ } else {
+ if (zDiff > 4.4f) {
+ if (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR)
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ALIGNHI_RHS, 4.0f);
+ else
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ALIGNHI_LHS, 4.0f);
+
+ } else {
+ if (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR)
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ALIGN_RHS, 4.0f);
+ else
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ALIGN_LHS, 4.0f);
+ }
+ m_pVehicleAnim->SetFinishCallback(PedAnimAlignCB, this);
+ car->AutoPilot.m_nCruiseSpeed = 0;
+ }
+}
+
+void
+CPed::EnterCar(void)
+{
+ if (IsNotInWreckedVehicle() && m_fHealth > 0.0f) {
+ CVehicle *veh = (CVehicle*)m_pSeekTarget;
+
+ // Not used.
+ // CVector posForDoor = GetPositionToOpenCarDoor(veh, m_vehEnterType);
+
+ if (veh->CanPedOpenLocks(this)) {
+ if (m_vehEnterType && m_pVehicleAnim) {
+ veh->ProcessOpenDoor(m_vehEnterType, m_pVehicleAnim->animId, m_pVehicleAnim->currentTime);
+ }
+ }
+ bIsInTheAir = false;
+ LineUpPedWithCar(LINE_UP_TO_CAR_START);
+ } else {
+ QuitEnteringCar();
+ SetDie(ANIM_KO_SHOT_FRONT1, 4.0f, 0.0f);
+ }
+}
+
+void
+CPed::QuitEnteringCar(void)
+{
+ CVehicle *veh = m_pMyVehicle;
+ if (m_pVehicleAnim)
+ m_pVehicleAnim->blendDelta = -1000.0f;
+
+ RestartNonPartialAnims();
+
+ if (!RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE))
+ CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 100.0f);
+
+ if (veh) {
+ if (m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || m_nPedState == PED_CARJACK)
+ veh->bIsBeingCarJacked = false;
+
+ if (veh->m_nNumGettingIn != 0)
+ veh->m_nNumGettingIn--;
+
+#ifdef VC_PED_PORTS
+ if (m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER)
+ RestorePreviousObjective();
+#endif
+
+ veh->m_nGettingInFlags &= ~GetCarDoorFlag(m_vehEnterType);
+ }
+
+ bUsesCollision = true;
+
+ ReplaceWeaponWhenExitingVehicle();
+
+ 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) {
+#ifdef VC_PED_PORTS
+ if (veh->AutoPilot.m_nCruiseSpeed == 0 && veh->VehicleCreatedBy == RANDOM_VEHICLE)
+#else
+ if (veh->AutoPilot.m_nCruiseSpeed == 0)
+#endif
+ veh->AutoPilot.m_nCruiseSpeed = 17;
+ }
+}
+
+void
+AddYardieDoorSmoke(CVehicle *veh, uint32 doorNode)
+{
+ eDoors door;
+ switch (doorNode) {
+ case CAR_DOOR_RF:
+ door = DOOR_FRONT_RIGHT;
+ break;
+ case CAR_DOOR_LF:
+ door = DOOR_FRONT_LEFT;
+ break;
+ default:
+ break;
+ }
+
+ if (!veh->IsDoorMissing(door) && veh->IsComponentPresent(doorNode)) {
+ CVector pos;
+#ifdef FIX_BUGS
+ veh->GetComponentWorldPosition(doorNode, pos);
+#else
+ veh->GetComponentWorldPosition(CAR_DOOR_LF, pos);
+#endif
+ CParticle::AddYardieDoorSmoke(pos, veh->GetMatrix());
+ }
+}
+
+// Seperate function in VC, more logical. Not sure is it inlined in III.
+void
+CPed::SetExitBoat(CVehicle *boat)
+{
+#ifndef VC_PED_PORTS
+ m_nPedState = PED_IDLE;
+ CVector firstPos = GetPosition();
+ CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 100.0f);
+ if (boat->GetModelIndex() == MI_SPEEDER && boat->IsUpsideDown()) {
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_CRAWLOUT_RHS, 8.0f);
+ m_pVehicleAnim->SetFinishCallback(PedSetOutCarCB, this);
+ m_vehEnterType = CAR_DOOR_RF;
+ m_nPedState = PED_EXIT_CAR;
+ } else {
+ m_vehEnterType = CAR_DOOR_RF;
+ PedSetOutCarCB(nil, this);
+ bIsStanding = true;
+ m_pCurSurface = boat;
+ m_pCurSurface->RegisterReference((CEntity**)&m_pCurSurface);
+ }
+ SetPosition(firstPos);
+ SetMoveState(PEDMOVE_STILL);
+ m_vecMoveSpeed = boat->m_vecMoveSpeed;
+ bTryingToReachDryLand = true;
+#else
+ m_nPedState = PED_IDLE;
+ CVector newPos = GetPosition();
+ RemoveInCarAnims();
+ CColModel* boatCol = boat->GetColModel();
+ if (boat->IsUpsideDown()) {
+ newPos = { 0.0f, 0.0f, boatCol->boundingBox.min.z };
+ newPos = boat->GetMatrix() * newPos;
+ newPos.z += 1.0f;
+ m_vehEnterType = CAR_DOOR_RF;
+ PedSetOutCarCB(nil, this);
+ bIsStanding = true;
+ m_pCurSurface = boat;
+ m_pCurSurface->RegisterReference((CEntity**)&m_pCurSurface);
+ m_pCurrentPhysSurface = boat;
+ } else {
+/* if (boat->m_modelIndex != MI_SKIMMER || boat->bIsInWater) {
+ if (boat->m_modelIndex == MI_SKIMMER)
+ newPos.z += 2.0f
+*/
+ m_vehEnterType = CAR_DOOR_RF;
+ PedSetOutCarCB(nil, this);
+ bIsStanding = true;
+ m_pCurSurface = boat;
+ m_pCurSurface->RegisterReference((CEntity**)&m_pCurSurface);
+ m_pCurrentPhysSurface = boat;
+ CColPoint foundCol;
+ CEntity *foundEnt = nil;
+ if (CWorld::ProcessVerticalLine(newPos, newPos.z - 1.4f, foundCol, foundEnt, false, true, false, false, false, false, nil))
+ newPos.z = FEET_OFFSET + foundCol.point.z;
+/* // VC specific
+ } else {
+ m_vehEnterType = CAR_DOOR_RF;
+ PedSetOutCarCB(nil, this);
+ bIsStanding = true;
+ SetMoveState(PEDMOVE_STILL);
+ bTryingToReachDryLand = true;
+ float upMult = 1.04f + boatCol->boundingBox.min.z;
+ float rightMult = 0.6f * boatCol->boundingBox.max.x;
+ newPos = upMult * boat->GetUp() + rightMult * boat->GetRight() + boat->GetPosition();
+ GetPosition() = newPos;
+ if (m_pMyVehicle) {
+ PositionPedOutOfCollision();
+ } else {
+ m_pMyVehicle = boat;
+ PositionPedOutOfCollision();
+ m_pMyVehicle = nil;
+ }
+ return;
+ }
+*/ }
+ SetPosition(newPos);
+ SetMoveState(PEDMOVE_STILL);
+ m_vecMoveSpeed = boat->m_vecMoveSpeed;
+#endif
+ // Not there in VC.
+ CWaterLevel::FreeBoatWakeArray();
+}
+
+// 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;
+ if (!veh->CanPedExitCar()) {
+ if (veh->pDriver && !veh->pDriver->IsPlayer()) {
+ 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->bIsBus) {
+ 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;
+ 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) {
+ // Again, unused...
+ // CVector exitPos = GetPositionToOpenCarDoor(veh, optedDoorNode);
+ bool thereIsRoom = veh->IsRoomForPedToLeaveCar(optedDoorNode, nil);
+ if (veh->IsOnItsSide()) {
+ teleportNeeded = true;
+ } else if (!thereIsRoom) {
+ bool trySideSeat = false;
+ CPed *pedOnSideSeat = nil;
+ 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;
+
+ 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);
+ }
+
+ ReplaceWeaponWhenExitingVehicle();
+ bUsesCollision = false;
+ m_pSeekTarget = veh;
+ m_pSeekTarget->RegisterReference((CEntity**) &m_pSeekTarget);
+ m_vehEnterType = optedDoorNode;
+ m_nPedState = PED_EXIT_CAR;
+ if (m_pVehicleAnim && m_pVehicleAnim->flags & ASSOC_PARTIAL)
+ m_pVehicleAnim->blendDelta = -1000.0f;
+ SetMoveState(PEDMOVE_NONE);
+ CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 100.0f);
+ RemoveInCarAnims();
+ veh->AutoPilot.m_nCruiseSpeed = 0;
+ if (teleportNeeded) {
+ PedSetOutCarCB(nil, this);
+
+ // This is same code with CPedPlacement::FindZCoorForPed, except we start from z + 1.5 and also check vehicles.
+ float zForPed;
+ float startZ = GetPosition().z - 100.0f;
+ float foundColZ = -100.0f;
+ float foundColZ2 = -100.0f;
+ CColPoint foundCol;
+ CEntity* foundEnt;
+
+ CVector vec = GetPosition();
+ vec.z += 1.5f;
+
+ if (CWorld::ProcessVerticalLine(vec, startZ, foundCol, foundEnt, true, true, false, false, true, false, nil))
+ foundColZ = foundCol.point.z;
+
+ // Adjust coords and do a second test
+ vec.x += 0.1f;
+ vec.y += 0.1f;
+
+ if (CWorld::ProcessVerticalLine(vec, startZ, foundCol, foundEnt, true, true, false, false, true, false, nil))
+ foundColZ2 = foundCol.point.z;
+
+ zForPed = Max(foundColZ, foundColZ2);
+
+ if (zForPed > -99.0f)
+ GetMatrix().GetPosition().z = FEET_OFFSET + zForPed;
+ } else {
+ if (veh->GetUp().z > -0.8f) {
+ bool addDoorSmoke = false;
+ if (veh->GetModelIndex() == MI_YARDIE)
+ addDoorSmoke = true;
+
+ switch (m_vehEnterType) {
+ case CAR_DOOR_RF:
+ if (veh->bIsBus) {
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_COACH_OUT_L);
+ } else {
+ if (isLow)
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_LOW_RHS);
+ else
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_RHS);
+
+ if (addDoorSmoke)
+ AddYardieDoorSmoke(veh, CAR_DOOR_RF);
+ }
+ break;
+ case CAR_DOOR_RR:
+ if (veh->bIsVan) {
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_VAN_GETOUT);
+ } else if (isLow) {
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_LOW_RHS);
+ } else {
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_RHS);
+ }
+ break;
+ case CAR_DOOR_LF:
+ if (veh->bIsBus) {
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_COACH_OUT_L);
+ } else {
+ if (isLow)
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_LOW_LHS);
+ else
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_LHS);
+
+ if (addDoorSmoke)
+ AddYardieDoorSmoke(veh, CAR_DOOR_LF);
+ }
+ break;
+ case CAR_DOOR_LR:
+ if (veh->bIsVan) {
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_VAN_GETOUT_L);
+ } else if (isLow) {
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_LOW_LHS);
+ } else {
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_GETOUT_LHS);
+ }
+ break;
+ default:
+ break;
+ }
+ if (!bBusJacked) {
+ switch (m_vehEnterType) {
+ case CAR_DOOR_RF:
+ veh->m_nGettingOutFlags |= CAR_DOOR_FLAG_RF;
+ break;
+ case CAR_DOOR_RR:
+ veh->m_nGettingOutFlags |= CAR_DOOR_FLAG_RR;
+ break;
+ case CAR_DOOR_LF:
+ veh->m_nGettingOutFlags |= CAR_DOOR_FLAG_LF;
+ break;
+ case CAR_DOOR_LR:
+ veh->m_nGettingOutFlags |= CAR_DOOR_FLAG_LR;
+ break;
+ default:
+ break;
+ }
+ }
+ m_pVehicleAnim->SetFinishCallback(PedAnimStepOutCarCB, this);
+ } else {
+ if (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR) {
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_CRAWLOUT_RHS2);
+ } else if (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR) {
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_CRAWLOUT_RHS);
+ }
+ m_pVehicleAnim->SetFinishCallback(PedSetOutCarCB, this);
+ }
+ }
+ 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)
+ return;
+
+ AnimationId exitAnim = (AnimationId) m_pVehicleAnim->animId;
+ float animTime = m_pVehicleAnim->currentTime;
+
+ m_pMyVehicle->ProcessOpenDoor(m_vehEnterType, exitAnim, animTime);
+
+ if (m_pSeekTarget) {
+ // Car is upside down
+ if (m_pMyVehicle->GetUp().z > -0.8f) {
+ if (exitAnim == ANIM_CAR_CLOSE_RHS || exitAnim == ANIM_CAR_CLOSE_LHS || animTime > 0.3f)
+ LineUpPedWithCar(LINE_UP_TO_CAR_END);
+ else
+ LineUpPedWithCar((m_pMyVehicle->GetModelIndex() == MI_DODO ? LINE_UP_TO_CAR_END : LINE_UP_TO_CAR_START));
+ } else {
+ LineUpPedWithCar(LINE_UP_TO_CAR_END);
+ }
+ }
+
+ // If there is someone in front of the door, make him fall while we exit.
+ if (m_nPedState == PED_EXIT_CAR) {
+ CPed *foundPed = nil;
+ for (int i = 0; i < m_numNearPeds; i++) {
+ if ((m_nearPeds[i]->GetPosition() - GetPosition()).MagnitudeSqr2D() < 0.04f) {
+ foundPed = m_nearPeds[i];
+ break;
+ }
+ }
+ if (foundPed && animTime > 0.4f && foundPed->IsPedInControl())
+ foundPed->SetFall(1000, ANIM_KO_SKID_FRONT, 1);
+ }
+}
+
+// This function was mostly duplicate of GetLocalPositionToOpenCarDoor, so I've used it.
+CVector
+CPed::GetPositionToOpenCarDoor(CVehicle *veh, uint32 component)
+{
+ CVector localPos;
+ CVector vehDoorPos;
+
+ localPos = GetLocalPositionToOpenCarDoor(veh, component, 1.0f);
+ vehDoorPos = Multiply3x3(veh->GetMatrix(), localPos) + veh->GetPosition();
+
+/*
+ // Not used.
+ CVector localVehDoorOffset;
+
+ if (veh->bIsVan && (component == VEHICLE_ENTER_REAR_LEFT || component == VEHICLE_ENTER_REAR_RIGHT)) {
+ localVehDoorOffset = vecPedVanRearDoorAnimOffset;
+ } else {
+ if (veh->bIsLow) {
+ localVehDoorOffset = vecPedCarDoorLoAnimOffset;
+ } else {
+ localVehDoorOffset = vecPedCarDoorAnimOffset;
+ }
+ }
+
+ vehDoorPosWithoutOffset = Multiply3x3(veh->GetMatrix(), localPos + localVehDoorOffset) + veh->GetPosition();
+*/
+ return vehDoorPos;
+}
+
+void
+CPed::GetNearestDoor(CVehicle *veh, CVector &posToOpen)
+{
+ CVector *enterOffset = nil;
+ if (m_vehEnterType == CAR_DOOR_LF && veh->pDriver
+ || m_vehEnterType == CAR_DOOR_RF && veh->pPassengers[0]
+ || m_vehEnterType == CAR_DOOR_LR && veh->pPassengers[1]
+ || m_vehEnterType == CAR_DOOR_RR && veh->pPassengers[2])
+ {
+ enterOffset = &vecPedQuickDraggedOutCarAnimOffset;
+ }
+
+ CVector lfPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_LF);
+ CVector rfPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_RF);
+
+ // Left front door is closer
+ if ((lfPos - GetPosition()).MagnitudeSqr2D() < (rfPos - GetPosition()).MagnitudeSqr2D()) {
+
+ if (veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, enterOffset)) {
+ m_vehEnterType = CAR_DOOR_LF;
+ posToOpen = lfPos;
+ } else if (veh->IsRoomForPedToLeaveCar(CAR_DOOR_RF, enterOffset)) {
+ m_vehEnterType = CAR_DOOR_RF;
+ posToOpen = rfPos;
+ }
+ } else {
+
+ if (veh->IsRoomForPedToLeaveCar(CAR_DOOR_RF, enterOffset)) {
+
+ CPed *rfPassenger = veh->pPassengers[0];
+ if (rfPassenger && (rfPassenger->m_leader == this || rfPassenger->bDontDragMeOutCar ||
+ veh->VehicleCreatedBy == MISSION_VEHICLE && m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER)
+ && veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, enterOffset)
+ || (veh->m_nGettingInFlags & CAR_DOOR_FLAG_RF) && veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, enterOffset)) {
+
+ m_vehEnterType = CAR_DOOR_LF;
+ posToOpen = lfPos;
+ } else {
+ m_vehEnterType = CAR_DOOR_RF;
+ posToOpen = rfPos;
+ }
+ } else if (veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, enterOffset)) {
+ m_vehEnterType = CAR_DOOR_LF;
+ posToOpen = lfPos;
+ }
+ }
+}
+
+bool
+CPed::GetNearestPassengerDoor(CVehicle *veh, CVector &posToOpen)
+{
+ CVector rfPos, lrPos, rrPos;
+ bool canEnter = false;
+
+ CVehicleModelInfo *vehModel = (CVehicleModelInfo *)CModelInfo::GetModelInfo(veh->GetModelIndex());
+
+ switch (veh->GetModelIndex()) {
+ case MI_BUS:
+ m_vehEnterType = CAR_DOOR_RF;
+ posToOpen = GetPositionToOpenCarDoor(veh, CAR_DOOR_RF);
+ return true;
+ case MI_RHINO:
+ default:
+ break;
+ }
+
+ CVector2D rfPosDist(999.0f, 999.0f);
+ CVector2D lrPosDist(999.0f, 999.0f);
+ CVector2D rrPosDist(999.0f, 999.0f);
+
+ if (!veh->pPassengers[0]
+ && !(veh->m_nGettingInFlags & CAR_DOOR_FLAG_RF)
+ && veh->IsRoomForPedToLeaveCar(CAR_DOOR_RF, nil)) {
+
+ rfPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_RF);
+ canEnter = true;
+ rfPosDist = rfPos - GetPosition();
+ }
+ if (vehModel->m_numDoors == 4) {
+ if (!veh->pPassengers[1]
+ && !(veh->m_nGettingInFlags & CAR_DOOR_FLAG_LR)
+ && veh->IsRoomForPedToLeaveCar(CAR_DOOR_LR, nil)) {
+ lrPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_LR);
+ canEnter = true;
+ lrPosDist = lrPos - GetPosition();
+ }
+ if (!veh->pPassengers[2]
+ && !(veh->m_nGettingInFlags & CAR_DOOR_FLAG_RR)
+ && veh->IsRoomForPedToLeaveCar(CAR_DOOR_RR, nil)) {
+ rrPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_RR);
+ canEnter = true;
+ rrPosDist = rrPos - GetPosition();
+ }
+
+ // When the door we should enter is blocked by some object.
+ if (!canEnter)
+ veh->ShufflePassengersToMakeSpace();
+ }
+
+ CVector2D nextToCompare = rfPosDist;
+ posToOpen = rfPos;
+ m_vehEnterType = CAR_DOOR_RF;
+ if (lrPosDist.MagnitudeSqr() < nextToCompare.MagnitudeSqr()) {
+ m_vehEnterType = CAR_DOOR_LR;
+ posToOpen = lrPos;
+ nextToCompare = lrPosDist;
+ }
+
+ if (rrPosDist.MagnitudeSqr() < nextToCompare.MagnitudeSqr()) {
+ m_vehEnterType = CAR_DOOR_RR;
+ posToOpen = rrPos;
+ }
+ return canEnter;
+}
+
+void
+CPed::GoToNearestDoor(CVehicle *veh)
+{
+ CVector posToOpen;
+ GetNearestDoor(veh, posToOpen);
+ SetSeek(posToOpen, 0.5f);
+ SetMoveState(PEDMOVE_RUN);
+}
+
+void
+CPed::SetAnimOffsetForEnterOrExitVehicle(void)
+{
+ // FIX: If there were no translations on enter anims, there were overflows all over this function.
+
+ CAnimBlendHierarchy *enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, ANIM_CAR_JACKED_LHS)->hierarchy;
+ CAnimBlendSequence *seq = enterAssoc->sequences;
+ CAnimManager::UncompressAnimation(enterAssoc);
+ if (seq->numFrames > 0) {
+ if (!seq->HasTranslation())
+ vecPedDraggedOutCarAnimOffset = CVector(0.0f, 0.0f, 0.0f);
+ else {
+ KeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);
+ vecPedDraggedOutCarAnimOffset = lastFrame->translation;
+ }
+ }
+
+ enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, ANIM_CAR_GETIN_LHS)->hierarchy;
+ seq = enterAssoc->sequences;
+ CAnimManager::UncompressAnimation(enterAssoc);
+ if (seq->numFrames > 0) {
+ if (!seq->HasTranslation())
+ vecPedCarDoorAnimOffset = CVector(0.0f, 0.0f, 0.0f);
+ else {
+ KeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);
+ vecPedCarDoorAnimOffset = lastFrame->translation;
+ }
+ }
+
+ enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, ANIM_CAR_GETIN_LOW_LHS)->hierarchy;
+ seq = enterAssoc->sequences;
+ CAnimManager::UncompressAnimation(enterAssoc);
+ if (seq->numFrames > 0) {
+ if (!seq->HasTranslation())
+ vecPedCarDoorLoAnimOffset = CVector(0.0f, 0.0f, 0.0f);
+ else {
+ KeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);
+ vecPedCarDoorLoAnimOffset = lastFrame->translation;
+ }
+ }
+
+ enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, ANIM_CAR_QJACKED)->hierarchy;
+ seq = enterAssoc->sequences;
+ CAnimManager::UncompressAnimation(enterAssoc);
+ if (seq->numFrames > 0) {
+ if (!seq->HasTranslation())
+ vecPedQuickDraggedOutCarAnimOffset = CVector(0.0f, 0.0f, 0.0f);
+ else {
+ KeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);
+ vecPedQuickDraggedOutCarAnimOffset = lastFrame->translation;
+ }
+ }
+
+ enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, ANIM_VAN_GETIN_L)->hierarchy;
+ seq = enterAssoc->sequences;
+ CAnimManager::UncompressAnimation(enterAssoc);
+ if (seq->numFrames > 0) {
+ if (!seq->HasTranslation())
+ vecPedVanRearDoorAnimOffset = CVector(0.0f, 0.0f, 0.0f);
+ else {
+ KeyFrameTrans *lastFrame = (KeyFrameTrans*)seq->GetKeyFrame(seq->numFrames - 1);
+ vecPedVanRearDoorAnimOffset = lastFrame->translation;
+ }
+ }
+
+ enterAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, ANIM_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;
+ }
+ }
+}
+
+void
+CPed::PedSetQuickDraggedOutCarPositionCB(CAnimBlendAssociation *animAssoc, void *arg)
+{
+ CPed *ped = (CPed*)arg;
+
+ CVehicle *veh = ped->m_pMyVehicle;
+
+ CVector finalPos;
+ CVector draggedOutOffset;
+
+ CMatrix pedMat(ped->GetMatrix());
+ ped->bUsesCollision = true;
+ ped->RestartNonPartialAnims();
+ draggedOutOffset = vecPedQuickDraggedOutCarAnimOffset;
+ if (ped->m_vehEnterType == CAR_DOOR_RF || ped->m_vehEnterType == CAR_DOOR_RR)
+ draggedOutOffset.x = -draggedOutOffset.x;
+
+ finalPos = Multiply3x3(pedMat, draggedOutOffset) + ped->GetPosition();
+ CPedPlacement::FindZCoorForPed(&finalPos);
+ ped->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
+ ped->SetPosition(finalPos);
+
+ if (veh) {
+ ped->m_fRotationDest = veh->GetForward().Heading() - HALFPI;
+ ped->m_fRotationCur = ped->m_fRotationDest;
+ ped->CalculateNewOrientation();
+
+ if (!veh->IsRoomForPedToLeaveCar(ped->m_vehEnterType, &vecPedQuickDraggedOutCarAnimOffset))
+ ped->PositionPedOutOfCollision();
+ }
+
+ if (!ped->CanSetPedState())
+ return;
+
+ ped->SetIdle();
+ if (veh) {
+ if (ped->bFleeAfterExitingCar) {
+ ped->bFleeAfterExitingCar = false;
+ ped->SetFlee(veh->GetPosition(), 14000);
+
+ } else if (ped->bWanderPathAfterExitingCar) {
+ ped->SetWanderPath(CGeneral::GetRandomNumberInRange(0.0f, 8.0f));
+ ped->bWanderPathAfterExitingCar = false;
+
+ } else if (ped->bGonnaKillTheCarJacker) {
+ ped->bGonnaKillTheCarJacker = false;
+ if (ped->m_pedInObjective && CGeneral::GetRandomNumber() & 1) {
+ if (ped->m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT)
+ ped->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, ped->m_pedInObjective);
+
+ } else {
+ CPed *driver = veh->pDriver;
+ if (!driver || driver == ped || driver->IsPlayer() && CTheScripts::IsPlayerOnAMission()) {
+ ped->SetFlee(veh->GetPosition(), 14000);
+ } else {
+ ped->ClearObjective();
+ ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, veh);
+ }
+ ped->bUsePedNodeSeek = true;
+ ped->m_pNextPathNode = nil;
+ ped->Say(SOUND_PED_FLEE_RUN);
+ }
+ } else if (ped->m_pedStats->m_temper > ped->m_pedStats->m_fear
+ && ped->CharCreatedBy != MISSION_CHAR && veh->VehicleCreatedBy != MISSION_VEHICLE
+ && veh->pDriver && veh->pDriver->IsPlayer()
+ && !CTheScripts::IsPlayerOnAMission()) {
+
+#ifndef VC_PED_PORTS
+ if (CGeneral::GetRandomNumber() < MYRAND_MAX / 2) {
+ ped->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, veh->pDriver);
+ } else
+#endif
+ ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, veh);
+
+#ifdef VC_PED_PORTS
+ } 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);
+#endif
+ } 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();
+ bool itsRearDoor = false;
+
+ if (ped->m_vehEnterType == CAR_DOOR_RF || ped->m_vehEnterType == CAR_DOOR_RR)
+ itsRearDoor = true;
+
+ CMatrix pedMat(ped->GetMatrix());
+ CVector posAfterBeingDragged = Multiply3x3(pedMat, (itsRearDoor ? -vecPedDraggedOutCarAnimOffset : vecPedDraggedOutCarAnimOffset));
+ posAfterBeingDragged += ped->GetPosition();
+#ifndef VC_PED_PORTS
+ posAfterBeingDragged.z += 1.0f;
+#endif
+ CPedPlacement::FindZCoorForPed(&posAfterBeingDragged);
+ ped->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
+ ped->SetPosition(posAfterBeingDragged);
+
+ if (ped->m_pMyVehicle && !ped->m_pMyVehicle->IsRoomForPedToLeaveCar(ped->m_vehEnterType, &vecPedDraggedOutCarAnimOffset)) {
+ ped->PositionPedOutOfCollision();
+ }
+
+ if (!ped->CanSetPedState())
+ return;
+
+ if (!ped->m_pMyVehicle) {
+ ped->SetIdle();
+ ped->SetGetUp();
+ return;
+ }
+
+ CPed *driver = ped->m_pMyVehicle->pDriver;
+
+ if (ped->IsPlayer()) {
+ ped->SetIdle();
+
+ } else if (ped->bFleeAfterExitingCar) {
+ ped->bFleeAfterExitingCar = false;
+ ped->SetFlee(ped->m_pMyVehicle->GetPosition(), 4000);
+
+ } else if (ped->bWanderPathAfterExitingCar) {
+ ped->SetWanderPath(CGeneral::GetRandomNumberInRange(0.0f, 8.0f));
+ ped->bWanderPathAfterExitingCar = false;
+
+ } else if (ped->bGonnaKillTheCarJacker) {
+ // Kill objective is already set at this point.
+
+ ped->bGonnaKillTheCarJacker = false;
+ if (!ped->m_pedInObjective || !(CGeneral::GetRandomNumber() & 1)) {
+ if (!driver || driver == ped || driver->IsPlayer() && CTheScripts::IsPlayerOnAMission()) {
+ ped->m_nPedState = 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()) {
+
+#ifndef VC_PED_PORTS
+ if (CGeneral::GetRandomNumber() & 1)
+ ped->SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, driver);
+ else
+#endif
+ ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, ped->m_pMyVehicle);
+
+ } else {
+#ifdef VC_PED_PORTS
+ 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
+#endif
+ {
+ ped->m_nPedState = 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_vehEnterType];
+ 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_vehEnterType = TRAIN_POS_MID_ENTRY;
+ } else {
+ enterPos = rightEntryPos;
+ m_vehEnterType = TRAIN_POS_RIGHT_ENTRY;
+ }
+ } else if (distRightEntry < distLeftEntry) {
+ enterPos = rightEntryPos;
+ m_vehEnterType = TRAIN_POS_RIGHT_ENTRY;
+ } else {
+ enterPos = leftEntryPos;
+ m_vehEnterType = TRAIN_POS_LEFT_ENTRY;
+ }
+
+ return 1;
+}
+
+void
+CPed::PedSetInTrainCB(CAnimBlendAssociation* animAssoc, void* arg)
+{
+ CPed *ped = (CPed*)arg;
+ CTrain *veh = (CTrain*)ped->m_pMyVehicle;
+
+ if (!veh)
+ return;
+
+ ped->bInVehicle = true;
+ ped->m_nPedState = PED_DRIVING;
+ ped->RestorePreviousObjective();
+ ped->SetMoveState(PEDMOVE_STILL);
+ veh->AddPassenger(ped);
+}
+
+void
+CPed::SetEnterTrain(CVehicle *train, uint32 unused)
+{
+ if (m_nPedState == PED_ENTER_TRAIN || !((CTrain*)train)->Doors[0].IsFullyOpen())
+ return;
+
+ /*
+ // Not used
+ CVector enterPos;
+ GetNearestTrainPedPosition(train, enterPos);
+ */
+ m_fRotationCur = train->GetForward().Heading() - HALFPI;
+ m_pMyVehicle = train;
+ m_pMyVehicle->RegisterReference((CEntity **) &m_pMyVehicle);
+
+ m_nPedState = PED_ENTER_TRAIN;
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_TRAIN_GETIN, 4.0f);
+ m_pVehicleAnim->SetFinishCallback(PedSetInTrainCB, this);
+ bUsesCollision = false;
+ LineUpPedWithTrain();
+ if (IsPlayer()) {
+ if (((CPlayerPed*)this)->m_bAdrenalineActive)
+ ((CPlayerPed*)this)->ClearAdrenaline();
+ }
+}
+
+void
+CPed::EnterTrain(void)
+{
+ LineUpPedWithTrain();
+}
+
+void
+CPed::SetPedPositionInTrain(void)
+{
+ LineUpPedWithTrain();
+}
+
+void
+CPed::LineUpPedWithTrain(void)
+{
+ CVector lineUpPos;
+ CVehicleModelInfo *trainModel = (CVehicleModelInfo *)CModelInfo::GetModelInfo(m_pMyVehicle->GetModelIndex());
+ CVector enterOffset(1.5f, 0.0f, -0.2f);
+
+ m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
+ m_fRotationCur = m_pMyVehicle->GetForward().Heading() - HALFPI;
+ m_fRotationDest = m_fRotationCur;
+
+ if (!bInVehicle) {
+ GetNearestTrainDoor(m_pMyVehicle, lineUpPos);
+ lineUpPos.z += 0.2f;
+ } else {
+ if (m_pMyVehicle->pPassengers[TRAIN_POS_LEFT_ENTRY] == this) {
+
+ lineUpPos = trainModel->m_positions[TRAIN_POS_LEFT_ENTRY] - enterOffset;
+
+ } else if (m_pMyVehicle->pPassengers[TRAIN_POS_MID_ENTRY] == this) {
+
+ lineUpPos = trainModel->m_positions[TRAIN_POS_MID_ENTRY] - enterOffset;
+
+ } else if (m_pMyVehicle->pPassengers[TRAIN_POS_RIGHT_ENTRY] == this) {
+
+ lineUpPos = trainModel->m_positions[TRAIN_POS_RIGHT_ENTRY] - enterOffset;
+ }
+ lineUpPos = Multiply3x3(m_pMyVehicle->GetMatrix(), lineUpPos);
+ lineUpPos += m_pMyVehicle->GetPosition();
+ }
+
+ if (m_pVehicleAnim) {
+ float percentageLeft = m_pVehicleAnim->GetTimeLeft() / m_pVehicleAnim->hierarchy->totalLength;
+ lineUpPos += (GetPosition() - lineUpPos) * percentageLeft;
+ }
+
+ SetPosition(lineUpPos);
+ SetHeading(m_fRotationCur);
+}
+
+void
+CPed::SetExitTrain(CVehicle* train)
+{
+ if (m_nPedState == PED_EXIT_TRAIN || train->GetStatus() != STATUS_TRAIN_NOT_MOVING || !((CTrain*)train)->Doors[0].IsFullyOpen())
+ return;
+
+ /*
+ // Not used
+ CVector exitPos;
+ GetNearestTrainPedPosition(train, exitPos);
+ */
+ m_nPedState = PED_EXIT_TRAIN;
+ m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_TRAIN_GETOUT, 4.0f);
+ m_pVehicleAnim->SetFinishCallback(PedSetOutTrainCB, this);
+ bUsesCollision = false;
+ LineUpPedWithTrain();
+}
+
+void
+CPed::ExitTrain(void)
+{
+ LineUpPedWithTrain();
+}
+
+void
+CPed::PedSetOutTrainCB(CAnimBlendAssociation *animAssoc, void *arg)
+{
+ CPed *ped = (CPed*)arg;
+
+ CVehicle *veh = ped->m_pMyVehicle;
+
+ if (ped->m_pVehicleAnim)
+ ped->m_pVehicleAnim->blendDelta = -1000.0f;
+
+ ped->bUsesCollision = true;
+ ped->m_pVehicleAnim = nil;
+ ped->bInVehicle = false;
+ ped->m_nPedState = PED_IDLE;
+ ped->RestorePreviousObjective();
+ ped->SetMoveState(PEDMOVE_STILL);
+
+ CMatrix pedMat(ped->GetMatrix());
+ ped->m_fRotationCur = HALFPI + veh->GetForward().Heading();
+ ped->m_fRotationDest = ped->m_fRotationCur;
+ CVector posAfterExit = Multiply3x3(pedMat, vecPedTrainDoorAnimOffset);
+ posAfterExit += ped->GetPosition();
+ CPedPlacement::FindZCoorForPed(&posAfterExit);
+ ped->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
+ ped->SetPosition(posAfterExit);
+ ped->SetHeading(ped->m_fRotationCur);
+ veh->RemovePassenger(ped);
+}
+
+void
+CPed::RegisterThreatWithGangPeds(CEntity *attacker)
+{
+ CPed *attackerPed = nil;
+ 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())
+ return;
+
+ attackerPed = ((CVehicle*)attacker)->pDriver;
+ if (!attackerPed)
+ 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 != 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_TOYZ) {
+ int16 lastVehicle;
+ CEntity *vehicles[8];
+ CWorld::FindObjectsInRange(GetPosition(), ENTER_CAR_MAX_DIST, 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) {
+
+ if (nearVeh->IsVehicleNormal() && nearVeh->IsCar()) {
+ nearVeh->AutoPilot.m_nCruiseSpeed = GAME_SPEED_TO_CARAI_SPEED * nearVeh->pHandling->Transmission.fUnkMaxVelocity * 0.8f;
+ nearVeh->AutoPilot.m_nCarMission = MISSION_RAMPLAYER_FARAWAY;
+ nearVeh->SetStatus(STATUS_PHYSICS);
+ nearVeh->AutoPilot.m_nTempAction = TEMPACT_NONE;
+ nearVeh->AutoPilot.m_nDrivingStyle = DRIVINGSTYLE_AVOID_CARS;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+// 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 = closeNode;
+ closeDist = posDiff;
+ } else {
+ ped->m_pNextPathNode = (closeNode2 ? closeNode2 : testNode);
+ farDist = 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;
+
+ 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);
+
+ // Above function decided that going to the next node is more logical than seeking the object.
+ if (m_pNextPathNode) {
+
+ CVector pathToNextNode = m_pNextPathNode->GetPosition() - ourPos;
+ if (pathToNextNode.MagnitudeSqr2D() < seekPosDist.MagnitudeSqr()) {
+ *bestCoords = m_pNextPathNode->GetPosition();
+ 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 {
+ bCrouchWhenShooting = false;
+ bKindaStayInSamePlace = false;
+ bIsDucking = 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;
+ }
+
+ bool justDucked = false;
+ CVehicle *foundVeh = nil;
+ float maxDist = 225.0f;
+ bIsDucking = false;
+ bCrouchWhenShooting = false;
+ if (CTimer::GetTimeInMilliseconds() > m_leaveCarTimer) {
+ CVector pos = GetPosition();
+ int16 lastVehicle;
+ CEntity *vehicles[8];
+ 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->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)
+ && CWorld::GetIsLineOfSightClear(GetPosition(), duckPos, 1, 0, 0, 1, 0, 0, 0)) {
+ 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;
+
+ // BUG? Shouldn't we register the reference?
+ m_pSeekTarget = foundVeh;
+ ClearPointGunAt();
+ } else {
+ m_duckAndCoverTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(10000, 15000);
+ bDuckAndCover = false;
+ }
+ } else {
+ bDuckAndCover = false;
+ }
+ }
+
+ if (!justDucked && !bDuckAndCover)
+ return false;
+
+ if (!Seek())
+ 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);
+ return false;
+}
+
+CVector
+CPed::GetPositionToOpenCarDoor(CVehicle *veh, uint32 component, float offset)
+{
+ CVector doorPos;
+ CMatrix vehMat(veh->GetMatrix());
+
+ 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->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;
+}
+
+void
+CPed::SetDuck(uint32 time)
+{
+ if (bIsDucking || CTimer::GetTimeInMilliseconds() <= m_duckTimer)
+ return;
+
+ if (bCrouchWhenShooting && (m_nPedState == PED_ATTACK || m_nPedState == PED_AIM_GUN)) {
+ CAnimBlendAssociation *duckAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_LOW);
+ if (!duckAssoc || duckAssoc->blendDelta < 0.0f) {
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DUCK_LOW, 4.0f);
+ bIsDucking = true;
+ m_duckTimer = CTimer::GetTimeInMilliseconds() + time;
+ }
+ } else {
+ CAnimBlendAssociation *duckAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_DOWN);
+ if (!duckAssoc || duckAssoc->blendDelta < 0.0f) {
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_DUCK_DOWN, 4.0f);
+ bIsDucking = true;
+ m_duckTimer = CTimer::GetTimeInMilliseconds() + time;
+ }
+ }
+}
+
+void
+CPed::Duck(void)
+{
+ if (CTimer::GetTimeInMilliseconds() > m_duckTimer)
+ ClearDuck();
+}
+
+void
+CPed::ClearDuck(void)
+{
+ CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_DOWN);
+ if (!animAssoc) {
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DUCK_LOW);
+
+ if (!animAssoc) {
+ bIsDucking = false;
+ return;
+ }
+ }
+
+ if (!bCrouchWhenShooting)
+ return;
+
+ if (m_nPedState != PED_ATTACK && m_nPedState != PED_AIM_GUN)
+ return;
+
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RBLOCK_CSHOOT);
+ if (!animAssoc || animAssoc->blendDelta < 0.0f) {
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_RBLOCK_CSHOOT, 4.0f);
+ }
+}
+
+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_CAR_ROLLDOOR_LOW, 1.0f);
+ } else {
+ veh->ProcessOpenDoor(CAR_DOOR_LF, ANIM_CAR_ROLLDOOR, 1.0f);
+ }
+
+ veh->m_nGettingOutFlags &= ~CAR_DOOR_FLAG_LF;
+
+ if (veh->Damage.GetDoorStatus(DOOR_FRONT_LEFT) == DOOR_STATUS_SWINGING)
+ veh->Damage.SetDoorStatus(DOOR_FRONT_LEFT, DOOR_STATUS_OK);
+}
+
+void
+CPed::SetSeekBoatPosition(CVehicle *boat)
+{
+ if (m_nPedState == PED_SEEK_IN_BOAT || boat->pDriver
+#if defined VC_PED_PORTS || defined FIX_BUGS
+ || !IsPedInControl()
+#endif
+ )
+ return;
+
+ SetStoredState();
+ m_carInObjective = boat;
+ m_carInObjective->RegisterReference((CEntity **) &m_carInObjective);
+ m_pMyVehicle = boat;
+ m_pMyVehicle->RegisterReference((CEntity **) &m_pMyVehicle);
+ m_distanceToCountSeekDone = 0.5f;
+ m_nPedState = 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_vehEnterType = 0;
+ SetEnterCar(m_carInObjective, 0);
+ }
+ } else
+ RestorePreviousState();
+}
+
+bool
+CPed::IsRoomToBeCarJacked(void)
+{
+ if (!m_pMyVehicle)
+ return false;
+
+ CVector offset;
+ 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::RemoveInCarAnims(void)
+{
+ if (!IsPlayer())
+ return;
+
+ CAnimBlendAssociation *animAssoc;
+
+ if (m_pMyVehicle && m_pMyVehicle->bLowVehicle) {
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVE_LOW_L);
+ if (animAssoc)
+ animAssoc->blendDelta = -1000.0f;
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVE_LOW_R);
+ if (animAssoc)
+ animAssoc->blendDelta = -1000.0f;
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVEBY_L);
+ if (animAssoc)
+ animAssoc->blendDelta = -1000.0f;
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVEBY_R);
+ if (animAssoc)
+ animAssoc->blendDelta = -1000.0f;
+ } else {
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVE_L);
+ if (animAssoc)
+ animAssoc->blendDelta = -1000.0f;
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVE_R);
+ if (animAssoc)
+ animAssoc->blendDelta = -1000.0f;
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVEBY_L);
+ if (animAssoc)
+ animAssoc->blendDelta = -1000.0f;
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVEBY_R);
+ if (animAssoc)
+ animAssoc->blendDelta = -1000.0f;
+ }
+
+#ifdef VC_PED_PORTS
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_DRIVE_BOAT);
+ if (animAssoc)
+ animAssoc->blendDelta = -1000.0f;
+#endif
+
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_LB);
+ if (animAssoc)
+ animAssoc->blendDelta = -1000.0f;
+}
+
+bool
+CPed::PositionPedOutOfCollision(void)
+{
+ CVehicle *veh;
+ CVector posNearVeh;
+ CVector posSomewhereClose;
+ bool putNearVeh = false;
+ bool putSomewhereClose = false;
+ int smallestDistNearVeh = 999;
+ int smallestDistSomewhereClose = 999;
+
+ if (!m_pMyVehicle)
+ return false;
+
+ CVector vehPos = m_pMyVehicle->GetPosition();
+ CVector potentialPos;
+ potentialPos.y = GetPosition().y - 3.5f;
+ potentialPos.z = GetPosition().z;
+
+ for (int yTry = 0; yTry < 15; yTry++) {
+ potentialPos.x = GetPosition().x - 3.5f;
+
+ for (int xTry = 0; xTry < 15; xTry++) {
+ CPedPlacement::FindZCoorForPed(&potentialPos);
+ CVector distVec = potentialPos - vehPos;
+ float dist = distVec.Magnitude();
+
+ // Makes close distances bigger for some reason.
+ float mult = (0.6f + dist) / dist;
+ CVector adjustedPotentialPos = distVec * mult + vehPos;
+ if (CWorld::GetIsLineOfSightClear(vehPos, adjustedPotentialPos, true, false, false, true, false, false, false)
+ && !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();
+ CVector zCorrectedPos = appropriatePos;
+ int tryCount = Min(10, halfOfDist);
+ for (int i = 0; i < tryCount; ++i) {
+ appropriatePos += halfNormalizedDist;
+ CPedPlacement::FindZCoorForPed(&zCorrectedPos);
+
+ if (Abs(zCorrectedPos.z - warpToPos.z) >= 3.0f && Abs(zCorrectedPos.z - appropriatePos.z) >= 3.0f)
+ continue;
+
+ 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;
+}
+
+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();
+ CVector zCorrectedPos = appropriatePos;
+ int tryCount = Min(10, halfOfDist);
+ for (int i = 0; i < tryCount; ++i) {
+ appropriatePos += halfNormalizedDist;
+ CPedPlacement::FindZCoorForPed(&zCorrectedPos);
+
+ if (Abs(zCorrectedPos.z - warpToPos.z) >= 3.0f && Abs(zCorrectedPos.z - appropriatePos.z) >= 3.0f)
+ continue;
+
+ 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;
+} \ No newline at end of file
diff --git a/src/peds/PedFight.cpp b/src/peds/PedFight.cpp
new file mode 100644
index 00000000..21310aaa
--- /dev/null
+++ b/src/peds/PedFight.cpp
@@ -0,0 +1,3250 @@
+#include "common.h"
+
+#include "main.h"
+#include "RpAnimBlend.h"
+#include "AnimBlendClumpData.h"
+#include "AnimBlendAssociation.h"
+#include "Camera.h"
+#include "CarCtrl.h"
+#include "Darkel.h"
+#include "DMAudio.h"
+#include "FileMgr.h"
+#include "General.h"
+#include "Object.h"
+#include "Pad.h"
+#include "Particle.h"
+#include "Ped.h"
+#include "PlayerPed.h"
+#include "Stats.h"
+#include "TempColModels.h"
+#include "VisibilityPlugins.h"
+#include "Vehicle.h"
+#include "Automobile.h"
+#include "WaterLevel.h"
+#include "World.h"
+
+uint16 nPlayerInComboMove;
+
+RpClump *flyingClumpTemp;
+
+// This is beta fistfite.dat array. Not used anymore since they're being fetched from fistfite.dat.
+FightMove tFightMoves[NUM_FIGHTMOVES] = {
+ {NUM_ANIMS, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
+ {ANIM_PUNCH_R, 0.2f, 8.0f / 30.0f, 0.0f, 0.3f, HITLEVEL_HIGH, 1, 0},
+ {ANIM_FIGHT_IDLE, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
+ {ANIM_FIGHT_SH_F, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
+ {ANIM_FIGHT_KNEE, 4.0f / 30.0f, 0.2f, 0.0f, 0.6f, HITLEVEL_LOW, 2, 0},
+ {ANIM_FIGHT_HEAD, 4.0f / 30.0f, 0.2f, 0.0f, 0.7f, HITLEVEL_HIGH, 3, 0},
+ {ANIM_FIGHT_PUNCH, 4.0f / 30.0f, 7.0f / 30.0f, 10.0f / 30.0f, 0.4f, HITLEVEL_HIGH, 1, 0},
+ {ANIM_FIGHT_LHOOK, 8.0f / 30.0f, 10.0f / 30.0f, 0.0f, 0.4f, HITLEVEL_HIGH, 3, 0},
+ {ANIM_FIGHT_KICK, 8.0f / 30.0f, 10.0f / 30.0f, 0.0f, 0.5, HITLEVEL_MEDIUM, 2, 0},
+ {ANIM_FIGHT_LONGKICK, 8.0f / 30.0f, 10.0f / 30.0f, 0.0f, 0.5, HITLEVEL_MEDIUM, 4, 0},
+ {ANIM_FIGHT_ROUNDHOUSE, 8.0f / 30.0f, 10.0f / 30.0f, 0.0f, 0.6f, HITLEVEL_MEDIUM, 4, 0},
+ {ANIM_FIGHT_BODYBLOW, 5.0f / 30.0f, 7.0f / 30.0f, 0.0f, 0.35f, HITLEVEL_LOW, 2, 0},
+ {ANIM_KICK_FLOOR, 10.0f / 30.0f, 14.0f / 30.0f, 0.0f, 0.4f, HITLEVEL_GROUND, 1, 0},
+ {ANIM_HIT_FRONT, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
+ {ANIM_HIT_BACK, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
+ {ANIM_HIT_RIGHT, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
+ {ANIM_HIT_LEFT, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
+ {ANIM_HIT_BODYBLOW, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
+ {ANIM_HIT_CHEST, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
+ {ANIM_HIT_HEAD, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
+ {ANIM_HIT_WALK, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
+ {ANIM_FLOOR_HIT, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
+ {ANIM_HIT_BEHIND, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
+ {ANIM_FIGHT2_IDLE, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0},
+};
+
+static PedOnGroundState
+CheckForPedsOnGroundToAttack(CPed *attacker, CPed **pedOnGround)
+{
+ PedOnGroundState stateToReturn;
+ float angleToFace;
+ CPed *currentPed = nil;
+ PedState currentPedState;
+ CPed *pedOnTheFloor = nil;
+ CPed *deadPed = nil;
+ CPed *pedBelow = nil;
+ bool foundDead = false;
+ bool foundOnTheFloor = false;
+ bool foundBelow = false;
+ float angleDiff;
+ float distance;
+
+ if (!CGame::nastyGame)
+ return NO_PED;
+
+ for (int currentPedId = 0; currentPedId < attacker->m_numNearPeds; currentPedId++) {
+
+ currentPed = attacker->m_nearPeds[currentPedId];
+
+ CVector posDifference = currentPed->GetPosition() - attacker->GetPosition();
+ distance = posDifference.Magnitude();
+
+ if (distance < 2.0f) {
+ angleToFace = CGeneral::GetRadianAngleBetweenPoints(
+ currentPed->GetPosition().x, currentPed->GetPosition().y,
+ attacker->GetPosition().x, attacker->GetPosition().y);
+
+ angleToFace = CGeneral::LimitRadianAngle(angleToFace);
+ attacker->m_fRotationCur = CGeneral::LimitRadianAngle(attacker->m_fRotationCur);
+
+ angleDiff = Abs(angleToFace - attacker->m_fRotationCur);
+
+ if (angleDiff > PI)
+ angleDiff = 2 * PI - angleDiff;
+
+ currentPedState = currentPed->m_nPedState;
+
+ if (currentPed->OnGroundOrGettingUp()) {
+ if (distance < 2.0f && angleDiff < DEGTORAD(65.0f)) {
+ if (currentPedState == PED_DEAD) {
+ foundDead = 1;
+ if (!deadPed)
+ deadPed = currentPed;
+ } else if (!currentPed->IsPedHeadAbovePos(-0.6f)) {
+ foundOnTheFloor = 1;
+ if (!pedOnTheFloor)
+ pedOnTheFloor = currentPed;
+ }
+ }
+ } else if ((distance < 0.8f && angleDiff < DEGTORAD(75.0f))
+ || (distance < 1.3f && angleDiff < DEGTORAD(55.0f))
+ || (distance < 1.7f && angleDiff < DEGTORAD(35.0f))
+ || (distance < 2.0f && angleDiff < DEGTORAD(30.0f))) {
+
+ // Either this condition or below one was probably returning 4 early in development. See Fight().
+ foundBelow = 1;
+ pedBelow = currentPed;
+ break;
+ } else {
+ if (angleDiff < DEGTORAD(75.0f)) {
+ foundBelow = 1;
+ if (!pedBelow)
+ pedBelow = currentPed;
+ }
+ }
+ }
+ }
+
+ if (foundOnTheFloor) {
+ currentPed = pedOnTheFloor;
+ stateToReturn = PED_ON_THE_FLOOR;
+ } else if (foundDead) {
+ currentPed = deadPed;
+ stateToReturn = PED_DEAD_ON_THE_FLOOR;
+ } else if (foundBelow) {
+ currentPed = pedBelow;
+ stateToReturn = PED_IN_FRONT_OF_ATTACKER;
+ } else {
+ currentPed = nil;
+ stateToReturn = NO_PED;
+ }
+
+ if (pedOnGround)
+ *pedOnGround = currentPed;
+
+ return stateToReturn;
+}
+
+void
+CPed::SetPointGunAt(CEntity *to)
+{
+ if (to) {
+ SetLookFlag(to, true);
+ SetAimFlag(to);
+#ifdef VC_PED_PORTS
+ SetLookTimer(INT32_MAX);
+#endif
+ }
+
+ if (m_nPedState == PED_AIM_GUN || bIsDucking || m_nWaitState == WAITSTATE_PLAYANIM_DUCK)
+ return;
+
+ if (m_nPedState != PED_ATTACK)
+ SetStoredState();
+
+ m_nPedState = PED_AIM_GUN;
+ bIsPointingGunAt = true;
+ CWeaponInfo *curWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
+ SetMoveState(PEDMOVE_NONE);
+
+ CAnimBlendAssociation *aimAssoc;
+
+ if (bCrouchWhenShooting)
+ aimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), curWeapon->m_Anim2ToPlay);
+ else
+ aimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), curWeapon->m_AnimToPlay);
+
+ if (!aimAssoc || aimAssoc->blendDelta < 0.0f) {
+ if (bCrouchWhenShooting)
+ aimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, curWeapon->m_Anim2ToPlay, 4.0f);
+ else
+ aimAssoc = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, curWeapon->m_AnimToPlay);
+
+ aimAssoc->blendAmount = 0.0f;
+ aimAssoc->blendDelta = 8.0f;
+ }
+ if (to)
+ Say(SOUND_PED_ATTACK);
+}
+
+void
+CPed::PointGunAt(void)
+{
+ CWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
+ CAnimBlendAssociation *weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), weaponInfo->m_AnimToPlay);
+ if (!weaponAssoc || weaponAssoc->blendDelta < 0.0f)
+ weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), weaponInfo->m_Anim2ToPlay);
+
+ if (weaponAssoc && weaponAssoc->currentTime > weaponInfo->m_fAnimLoopStart) {
+ weaponAssoc->SetCurrentTime(weaponInfo->m_fAnimLoopStart);
+ weaponAssoc->flags &= ~ASSOC_RUNNING;
+
+ if (weaponInfo->m_bCanAimWithArm)
+ m_pedIK.m_flags |= CPedIK::AIMS_WITH_ARM;
+ else
+ m_pedIK.m_flags &= ~CPedIK::AIMS_WITH_ARM;
+ }
+}
+
+void
+CPed::ClearPointGunAt(void)
+{
+ CAnimBlendAssociation *animAssoc;
+ CWeaponInfo *weaponInfo;
+
+ ClearLookFlag();
+ ClearAimFlag();
+ bIsPointingGunAt = false;
+#ifndef VC_PED_PORTS
+ if (m_nPedState == PED_AIM_GUN) {
+ RestorePreviousState();
+#else
+ if (m_nPedState == PED_AIM_GUN || m_nPedState == PED_ATTACK) {
+ m_nPedState = PED_IDLE;
+ RestorePreviousState();
+ }
+#endif
+ weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), weaponInfo->m_AnimToPlay);
+ if (!animAssoc || animAssoc->blendDelta < 0.0f) {
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), weaponInfo->m_Anim2ToPlay);
+ }
+ if (animAssoc) {
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ animAssoc->blendDelta = -4.0f;
+ }
+#ifndef VC_PED_PORTS
+ }
+#endif
+}
+
+void
+CPed::SetAttack(CEntity *victim)
+{
+ CPed *victimPed = nil;
+ if (victim && victim->IsPed())
+ victimPed = (CPed*)victim;
+
+ CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_ARMED);
+ if (animAssoc) {
+ animAssoc->blendDelta = -1000.0f;
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ }
+
+ if (m_attackTimer > CTimer::GetTimeInMilliseconds() || m_nWaitState == WAITSTATE_SURPRISE)
+ return;
+
+ if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_HGUN_RELOAD)) {
+ bIsAttacking = false;
+ return;
+ }
+
+ if (RpAnimBlendClumpGetAssociation(GetClump(), ANIM_AK_RELOAD)) {
+ if (!IsPlayer() || m_nPedState != PED_ATTACK || ((CPlayerPed*)this)->m_bHaveTargetSelected)
+ bIsAttacking = false;
+ else
+ bIsAttacking = true;
+
+ return;
+ }
+
+ CWeaponInfo *curWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
+ if (curWeapon->m_eWeaponFire == WEAPON_FIRE_INSTANT_HIT && !IsPlayer()) {
+ if (GetWeapon()->HitsGround(this, nil, victim))
+ return;
+ }
+
+ if (GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED) {
+ if (IsPlayer() ||
+ (m_nPedState != PED_FIGHT && m_nMoveState != PEDMOVE_NONE && m_nMoveState != PEDMOVE_STILL && !(m_pedStats->m_flags & STAT_SHOPPING_BAGS))) {
+
+ if (m_nPedState != PED_ATTACK) {
+ m_nPedState = PED_ATTACK;
+ bIsAttacking = false;
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, curWeapon->m_AnimToPlay, 8.0f);
+ animAssoc->SetRun();
+ if (animAssoc->currentTime == animAssoc->hierarchy->totalLength)
+ animAssoc->SetCurrentTime(0.0f);
+
+ animAssoc->SetFinishCallback(FinishedAttackCB, this);
+ }
+ } else {
+ StartFightAttack(CGeneral::GetRandomNumber() % 256);
+ }
+ return;
+ }
+
+ m_pSeekTarget = victim;
+ if (m_pSeekTarget)
+ m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget);
+
+ if (curWeapon->m_bCanAim) {
+ CVector aimPos = GetRight() * 0.1f + GetForward() * 0.2f + GetPosition();
+ CEntity *obstacle = CWorld::TestSphereAgainstWorld(aimPos, 0.2f, nil, true, false, false, true, false, false);
+ if (obstacle)
+ return;
+
+ m_pLookTarget = victim;
+ if (victim) {
+ m_pLookTarget->RegisterReference((CEntity **) &m_pLookTarget);
+ m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget);
+ }
+ if (m_pLookTarget) {
+ SetAimFlag(m_pLookTarget);
+ } else {
+ SetAimFlag(m_fRotationCur);
+
+ if (FindPlayerPed() == this && TheCamera.Cams[0].Using3rdPersonMouseCam())
+ ((CPlayerPed*)this)->m_fFPSMoveHeading = TheCamera.Find3rdPersonQuickAimPitch();
+ }
+ }
+ if (m_nPedState == PED_ATTACK) {
+ bIsAttacking = true;
+ return;
+ }
+
+ if (IsPlayer() || !victimPed || victimPed->IsPedInControl()) {
+ if (IsPlayer())
+ CPad::GetPad(0)->ResetAverageWeapon();
+
+ PointBlankNecessity pointBlankStatus;
+ if ((curWeapon->m_eWeaponFire == WEAPON_FIRE_INSTANT_HIT || GetWeapon()->m_eWeaponType == WEAPONTYPE_FLAMETHROWER)
+ && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_M16_1STPERSON
+ && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_M16_1STPERSON_RUNABOUT
+ && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_SNIPER
+ && TheCamera.PlayerWeaponMode.Mode != CCam::MODE_SNIPER_RUNABOUT
+ && (pointBlankStatus = CheckForPointBlankPeds(victimPed)) != NO_POINT_BLANK_PED) {
+ ClearAimFlag();
+
+ // This condition is pointless
+ if (pointBlankStatus == POINT_BLANK_FOR_WANTED_PED || !victimPed)
+ StartFightAttack(200);
+ } else {
+ if (!curWeapon->m_bCanAim)
+ m_pSeekTarget = nil;
+
+ if (m_nPedState != PED_AIM_GUN)
+ SetStoredState();
+
+ m_nPedState = PED_ATTACK;
+ SetMoveState(PEDMOVE_NONE);
+ if (bCrouchWhenShooting) {
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_RBLOCK_CSHOOT, 4.0f);
+ } else {
+ float animDelta = 8.0f;
+ if (curWeapon->m_eWeaponFire == WEAPON_FIRE_MELEE)
+ animDelta = 1000.0f;
+
+ if (GetWeapon()->m_eWeaponType != WEAPONTYPE_BASEBALLBAT
+ || CheckForPedsOnGroundToAttack(this, nil) < PED_ON_THE_FLOOR) {
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, curWeapon->m_AnimToPlay, animDelta);
+ } else {
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, curWeapon->m_Anim2ToPlay, animDelta);
+ }
+ }
+
+ animAssoc->SetRun();
+ if (animAssoc->currentTime == animAssoc->hierarchy->totalLength)
+ animAssoc->SetCurrentTime(0.0f);
+
+ animAssoc->SetFinishCallback(FinishedAttackCB, this);
+ }
+ return;
+ }
+
+ if (GetWeapon()->m_eWeaponType == WEAPONTYPE_BASEBALLBAT && victimPed->m_nPedState == PED_GETUP)
+ SetWaitState(WAITSTATE_SURPRISE, nil);
+
+ SetLookFlag(victim, false);
+ SetLookTimer(100);
+}
+
+void
+CPed::ClearAttack(void)
+{
+ if (m_nPedState != PED_ATTACK || bIsDucking || m_nWaitState == WAITSTATE_PLAYANIM_DUCK)
+ return;
+
+#ifdef VC_PED_PORTS
+ // VC uses CCamera::Using1stPersonWeaponMode
+ if (FindPlayerPed() == this && (TheCamera.PlayerWeaponMode.Mode == CCam::MODE_SNIPER ||
+ TheCamera.PlayerWeaponMode.Mode == CCam::MODE_M16_1STPERSON || TheCamera.PlayerWeaponMode.Mode == CCam::MODE_ROCKETLAUNCHER)) {
+ SetPointGunAt(nil);
+ } else
+#endif
+ if (bIsPointingGunAt) {
+ if (m_pLookTarget)
+ SetPointGunAt(m_pLookTarget);
+ else
+ ClearPointGunAt();
+ } else if (m_objective != OBJECTIVE_NONE) {
+ SetIdle();
+ } else {
+ RestorePreviousState();
+ }
+}
+
+void
+CPed::ClearAttackByRemovingAnim(void)
+{
+ if (m_nPedState != PED_ATTACK || bIsDucking)
+ return;
+
+ CWeaponInfo *weapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
+ CAnimBlendAssociation *weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), weapon->m_AnimToPlay);
+ if (!weaponAssoc) {
+ weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), weapon->m_Anim2ToPlay);
+
+ if (!weaponAssoc && weapon->m_bThrow)
+ weaponAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_THROWU);
+
+ if (!weaponAssoc) {
+ ClearAttack();
+ return;
+ }
+ }
+ weaponAssoc->blendDelta = -8.0f;
+ weaponAssoc->flags &= ~ASSOC_RUNNING;
+ weaponAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ weaponAssoc->SetDeleteCallback(FinishedAttackCB, this);
+}
+
+void
+CPed::FinishedAttackCB(CAnimBlendAssociation *attackAssoc, void *arg)
+{
+ CWeaponInfo *currentWeapon;
+ CAnimBlendAssociation *newAnim;
+ CPed *ped = (CPed*)arg;
+
+ if (attackAssoc) {
+ switch (attackAssoc->animId) {
+ case ANIM_WEAPON_START_THROW:
+ // what?!
+ if ((!ped->IsPlayer() || ((CPlayerPed*)ped)->m_bHaveTargetSelected) && ped->IsPlayer()) {
+ attackAssoc->blendDelta = -1000.0f;
+ newAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_WEAPON_THROWU);
+ } else {
+ attackAssoc->blendDelta = -1000.0f;
+ newAnim = CAnimManager::AddAnimation(ped->GetClump(), ASSOCGRP_STD, ANIM_WEAPON_THROW);
+ }
+
+ newAnim->SetFinishCallback(FinishedAttackCB, ped);
+ return;
+
+ case ANIM_FIGHT_PPUNCH:
+ attackAssoc->blendDelta = -8.0f;
+ attackAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ ped->ClearAttack();
+ return;
+
+ case ANIM_WEAPON_THROW:
+ case ANIM_WEAPON_THROWU:
+ if (ped->GetWeapon()->m_nAmmoTotal > 0) {
+ currentWeapon = CWeaponInfo::GetWeaponInfo(ped->GetWeapon()->m_eWeaponType);
+ ped->AddWeaponModel(currentWeapon->m_nModelId);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (!ped->bIsAttacking)
+ ped->ClearAttack();
+}
+
+PointBlankNecessity
+CPed::CheckForPointBlankPeds(CPed *pedToVerify)
+{
+ float pbDistance = 1.1f;
+ if (GetWeapon()->IsType2Handed())
+ pbDistance = 1.6f;
+
+ for (int i = 0; i < m_numNearPeds; i++) {
+ CPed *nearPed = m_nearPeds[i];
+
+ if (!pedToVerify || pedToVerify == nearPed) {
+
+ CVector diff = nearPed->GetPosition() - GetPosition();
+ if (diff.Magnitude() < pbDistance) {
+
+ float neededAngle = CGeneral::GetRadianAngleBetweenPoints(
+ nearPed->GetPosition().x, nearPed->GetPosition().y,
+ GetPosition().x, GetPosition().y);
+ neededAngle = CGeneral::LimitRadianAngle(neededAngle);
+ m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur);
+
+ float neededTurn = Abs(neededAngle - m_fRotationCur);
+
+ if (neededTurn > PI)
+ neededTurn = 2*PI - neededTurn;
+
+ if (nearPed->OnGroundOrGettingUp() || nearPed->m_nPedState == PED_DIVE_AWAY)
+ return NO_POINT_BLANK_PED;
+
+ if (neededTurn < CAN_SEE_ENTITY_ANGLE_THRESHOLD) {
+ if (pedToVerify == nearPed)
+ return POINT_BLANK_FOR_WANTED_PED;
+ else
+ return POINT_BLANK_FOR_SOMEONE_ELSE;
+ }
+ }
+ }
+ }
+ return NO_POINT_BLANK_PED;
+}
+
+void
+CPed::Attack(void)
+{
+ CAnimBlendAssociation *weaponAnimAssoc;
+ int32 weaponAnim;
+ float animStart;
+ eWeaponType ourWeaponType;
+ float weaponAnimTime;
+ eWeaponFire ourWeaponFire;
+ float animLoopEnd;
+ CWeaponInfo *ourWeapon;
+ bool attackShouldContinue;
+ AnimationId reloadAnim;
+ CAnimBlendAssociation *reloadAnimAssoc;
+ float delayBetweenAnimAndFire;
+ CVector firePos;
+
+ ourWeaponType = GetWeapon()->m_eWeaponType;
+ ourWeapon = CWeaponInfo::GetWeaponInfo(ourWeaponType);
+ ourWeaponFire = ourWeapon->m_eWeaponFire;
+ weaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ourWeapon->m_AnimToPlay);
+ attackShouldContinue = bIsAttacking;
+ reloadAnimAssoc = nil;
+ reloadAnim = NUM_ANIMS;
+ delayBetweenAnimAndFire = ourWeapon->m_fAnimFrameFire;
+ weaponAnim = ourWeapon->m_AnimToPlay;
+
+ if (weaponAnim == ANIM_WEAPON_HGUN_BODY)
+ reloadAnim = ANIM_HGUN_RELOAD;
+ else if (weaponAnim == ANIM_WEAPON_AK_BODY)
+ reloadAnim = ANIM_AK_RELOAD;
+
+ if (reloadAnim != NUM_ANIMS)
+ reloadAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), reloadAnim);
+
+ if (bIsDucking)
+ return;
+
+ if (reloadAnimAssoc) {
+ if (!IsPlayer() || ((CPlayerPed*)this)->m_bHaveTargetSelected)
+ ClearAttack();
+
+ return;
+ }
+
+ if (CTimer::GetTimeInMilliseconds() < m_shootTimer)
+ attackShouldContinue = true;
+
+ if (!weaponAnimAssoc) {
+ weaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ourWeapon->m_Anim2ToPlay);
+ delayBetweenAnimAndFire = ourWeapon->m_fAnim2FrameFire;
+
+ // Long throw granade, molotov
+ if (!weaponAnimAssoc && ourWeapon->m_bThrow) {
+ weaponAnimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_THROWU);
+ delayBetweenAnimAndFire = 0.2f;
+ }
+
+ if (!weaponAnimAssoc) {
+ if (attackShouldContinue) {
+ if (ourWeaponFire != WEAPON_FIRE_PROJECTILE || !IsPlayer() || ((CPlayerPed*)this)->m_bHaveTargetSelected) {
+ if (!CGame::nastyGame || ourWeaponFire != WEAPON_FIRE_MELEE || CheckForPedsOnGroundToAttack(this, nil) < PED_ON_THE_FLOOR) {
+ weaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ourWeapon->m_AnimToPlay, 8.0f);
+ }
+ else {
+ weaponAnimAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ourWeapon->m_Anim2ToPlay, 8.0f);
+ }
+
+ weaponAnimAssoc->SetFinishCallback(FinishedAttackCB, this);
+ weaponAnimAssoc->SetRun();
+
+ if (weaponAnimAssoc->currentTime == weaponAnimAssoc->hierarchy->totalLength)
+ weaponAnimAssoc->SetCurrentTime(0.0f);
+
+ if (IsPlayer()) {
+ ((CPlayerPed*)this)->m_fAttackButtonCounter = 0.0f;
+ ((CPlayerPed*)this)->m_bHaveTargetSelected = false;
+ }
+ }
+ } else
+ FinishedAttackCB(nil, this);
+
+ return;
+ }
+ }
+
+ animStart = ourWeapon->m_fAnimLoopStart;
+ weaponAnimTime = weaponAnimAssoc->currentTime;
+ if (weaponAnimTime > animStart && weaponAnimTime - weaponAnimAssoc->timeStep <= animStart) {
+ if (ourWeapon->m_bCanAimWithArm)
+ m_pedIK.m_flags |= CPedIK::AIMS_WITH_ARM;
+ else
+ m_pedIK.m_flags &= ~CPedIK::AIMS_WITH_ARM;
+ }
+
+ if (weaponAnimTime <= delayBetweenAnimAndFire || weaponAnimTime - weaponAnimAssoc->timeStep > delayBetweenAnimAndFire || !weaponAnimAssoc->IsRunning()) {
+ if (weaponAnimAssoc->speed < 1.0f)
+ weaponAnimAssoc->speed = 1.0f;
+
+ } else {
+ firePos = ourWeapon->m_vecFireOffset;
+ if (ourWeaponType == WEAPONTYPE_BASEBALLBAT) {
+ if (weaponAnimAssoc->animId == ourWeapon->m_Anim2ToPlay)
+ firePos.z = 0.7f * ourWeapon->m_fRadius - 1.0f;
+
+ firePos = GetMatrix() * firePos;
+ } else if (ourWeaponType != WEAPONTYPE_UNARMED) {
+ TransformToNode(firePos, weaponAnimAssoc->animId == ANIM_KICK_FLOOR ? PED_FOOTR : PED_HANDR);
+ } else {
+ firePos = GetMatrix() * firePos;
+ }
+
+ GetWeapon()->Fire(this, &firePos);
+
+ if (ourWeaponType == WEAPONTYPE_MOLOTOV || ourWeaponType == WEAPONTYPE_GRENADE) {
+ RemoveWeaponModel(ourWeapon->m_nModelId);
+ }
+ if (!GetWeapon()->m_nAmmoTotal && ourWeaponFire != WEAPON_FIRE_MELEE && FindPlayerPed() != this) {
+ SelectGunIfArmed();
+ }
+
+ if (GetWeapon()->m_eWeaponState != WEAPONSTATE_MELEE_MADECONTACT) {
+ // If reloading just began, start the animation
+ // Last condition will always return true, even IDA hides it
+ if (GetWeapon()->m_eWeaponState == WEAPONSTATE_RELOADING && reloadAnim != NUM_ANIMS /* && !reloadAnimAssoc*/) {
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, reloadAnim, 8.0f);
+ ClearLookFlag();
+ ClearAimFlag();
+ bIsAttacking = false;
+ bIsPointingGunAt = false;
+ m_shootTimer = CTimer::GetTimeInMilliseconds();
+ return;
+ }
+ } else {
+ if (weaponAnimAssoc->animId == ANIM_WEAPON_BAT_V || weaponAnimAssoc->animId == ANIM_WEAPON_BAT_H) {
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_BAT_ATTACK, 1.0f);
+ } else if (weaponAnimAssoc->animId == ANIM_FIGHT_PPUNCH) {
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_FIGHT_PUNCH_39, 0.0f);
+ }
+
+ weaponAnimAssoc->speed = 0.5f;
+
+ if (bIsAttacking || CTimer::GetTimeInMilliseconds() < m_shootTimer) {
+ weaponAnimAssoc->callbackType = 0;
+ }
+ }
+
+ attackShouldContinue = false;
+ }
+
+ if (ourWeaponType == WEAPONTYPE_SHOTGUN) {
+ weaponAnimTime = weaponAnimAssoc->currentTime;
+ firePos = ourWeapon->m_vecFireOffset;
+
+ if (weaponAnimTime > 1.0f && weaponAnimTime - weaponAnimAssoc->timeStep <= 1.0f && weaponAnimAssoc->IsRunning()) {
+ TransformToNode(firePos, PED_HANDR);
+
+ CVector gunshellPos(
+ firePos.x - 0.6f * GetForward().x,
+ firePos.y - 0.6f * GetForward().y,
+ firePos.z - 0.15f * GetUp().z
+ );
+
+ CVector2D gunshellRot(
+ GetRight().x,
+ GetRight().y
+ );
+
+ gunshellRot.Normalise();
+ GetWeapon()->AddGunshell(this, gunshellPos, gunshellRot, 0.025f);
+ }
+ }
+#ifdef VC_PED_PORTS
+ if (IsPlayer()) {
+ if (CPad::GetPad(0)->GetSprint()) {
+ // animBreakout is a member of WeaponInfo in VC, so it's me that added the below line.
+ float animBreakOut = ((ourWeaponType == WEAPONTYPE_FLAMETHROWER || ourWeaponType == WEAPONTYPE_UZI || ourWeaponType == WEAPONTYPE_SHOTGUN) ? 25 / 30.0f : 99 / 30.0f);
+ if (!attackShouldContinue && weaponAnimAssoc->currentTime > animBreakOut) {
+ weaponAnimAssoc->blendDelta = -4.0f;
+ FinishedAttackCB(nil, this);
+ return;
+ }
+ }
+ }
+#endif
+ animLoopEnd = ourWeapon->m_fAnimLoopEnd;
+ if (ourWeaponFire == WEAPON_FIRE_MELEE && weaponAnimAssoc->animId == ourWeapon->m_Anim2ToPlay)
+ animLoopEnd = 3.4f/6.0f;
+
+ weaponAnimTime = weaponAnimAssoc->currentTime;
+
+ // Anim loop end, either start the loop again or finish the attack
+ if (weaponAnimTime > animLoopEnd || !weaponAnimAssoc->IsRunning() && ourWeaponFire != WEAPON_FIRE_PROJECTILE) {
+
+ if (weaponAnimTime - 2.0f * weaponAnimAssoc->timeStep <= animLoopEnd
+ && (bIsAttacking || CTimer::GetTimeInMilliseconds() < m_shootTimer)
+ && GetWeapon()->m_eWeaponState != WEAPONSTATE_RELOADING) {
+
+ weaponAnim = weaponAnimAssoc->animId;
+ if (ourWeaponFire != WEAPON_FIRE_MELEE || CheckForPedsOnGroundToAttack(this, nil) < PED_ON_THE_FLOOR) {
+ if (weaponAnim != ourWeapon->m_Anim2ToPlay || weaponAnim == ANIM_RBLOCK_CSHOOT) {
+ weaponAnimAssoc->Start(ourWeapon->m_fAnimLoopStart);
+ } else {
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ourWeapon->m_AnimToPlay, 8.0f);
+ }
+ } else {
+ if (weaponAnim == ourWeapon->m_Anim2ToPlay)
+ weaponAnimAssoc->SetCurrentTime(0.1f);
+ else
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ourWeapon->m_Anim2ToPlay, 8.0f);
+ }
+#ifdef VC_PED_PORTS
+ } else if (IsPlayer() && m_pPointGunAt && bIsAimingGun && GetWeapon()->m_eWeaponState != WEAPONSTATE_RELOADING) {
+ weaponAnimAssoc->SetCurrentTime(ourWeapon->m_fAnimLoopEnd);
+ weaponAnimAssoc->flags &= ~ASSOC_RUNNING;
+ SetPointGunAt(m_pPointGunAt);
+#endif
+ } else {
+ ClearAimFlag();
+
+ // Echoes of bullets, at the end of the attack. (Bug: doesn't play while reloading)
+ if (weaponAnimAssoc->currentTime - weaponAnimAssoc->timeStep <= ourWeapon->m_fAnimLoopEnd) {
+ switch (ourWeaponType) {
+ case WEAPONTYPE_UZI:
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_UZI_BULLET_ECHO, 0.0f);
+ break;
+ case WEAPONTYPE_AK47:
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_AK47_BULLET_ECHO, 0.0f);
+ break;
+ case WEAPONTYPE_M16:
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_M16_BULLET_ECHO, 0.0f);
+ break;
+ default:
+ break;
+ }
+ }
+
+ // Fun fact: removing this part leds to reloading flamethrower
+ if (ourWeaponType == WEAPONTYPE_FLAMETHROWER && weaponAnimAssoc->IsRunning()) {
+ weaponAnimAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ weaponAnimAssoc->flags &= ~ASSOC_RUNNING;
+ weaponAnimAssoc->blendDelta = -4.0f;
+ }
+ }
+ }
+ if (weaponAnimAssoc->currentTime > delayBetweenAnimAndFire)
+ attackShouldContinue = false;
+
+ bIsAttacking = attackShouldContinue;
+}
+
+void
+CPed::StartFightAttack(uint8 buttonPressure)
+{
+ if (!IsPedInControl() || m_attackTimer > CTimer::GetTimeInMilliseconds())
+ return;
+
+ if (m_nPedState == PED_FIGHT) {
+ m_fightButtonPressure = buttonPressure;
+ return;
+ }
+
+ if (m_nPedState != PED_AIM_GUN)
+ SetStoredState();
+
+ if (m_nWaitState != WAITSTATE_FALSE) {
+ m_nWaitState = WAITSTATE_FALSE;
+ RestoreHeadingRate();
+ }
+
+ m_nPedState = PED_FIGHT;
+ m_fightButtonPressure = 0;
+ RpAnimBlendClumpRemoveAssociations(GetClump(), ASSOC_REPEAT);
+ CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WALK_START);
+
+ if (animAssoc) {
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ animAssoc->blendDelta = -1000.0f;
+ }
+
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP);
+ if (!animAssoc)
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP_R);
+
+ if (animAssoc) {
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ animAssoc->blendDelta = -1000.0f;
+ RestoreHeadingRate();
+ }
+
+ SetMoveState(PEDMOVE_NONE);
+ m_nStoredMoveState = PEDMOVE_NONE;
+
+ CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT_IDLE)->blendAmount = 1.0f;
+
+ CPed *pedOnGround = nil;
+ if (IsPlayer() && CheckForPedsOnGroundToAttack(this, &pedOnGround) > PED_IN_FRONT_OF_ATTACKER) {
+ m_curFightMove = FIGHTMOVE_GROUNDKICK;
+ } else if (m_pedStats->m_flags & STAT_SHOPPING_BAGS) {
+ m_curFightMove = FIGHTMOVE_ROUNDHOUSE;
+ } else {
+ m_curFightMove = FIGHTMOVE_STDPUNCH;
+ }
+
+ if (pedOnGround && IsPlayer()) {
+ m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(
+ pedOnGround->GetPosition().x, pedOnGround->GetPosition().y,
+ GetPosition().x, GetPosition().y);
+
+ m_fRotationDest = CGeneral::LimitRadianAngle(m_fRotationDest);
+ m_fRotationCur = m_fRotationDest;
+ m_lookTimer = 0;
+ SetLookFlag(pedOnGround, true);
+ SetLookTimer(1500);
+ }
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 4.0f);
+ animAssoc->SetFinishCallback(FinishFightMoveCB, this);
+ m_fightState = FIGHTSTATE_NO_MOVE;
+ m_takeAStepAfterAttack = false;
+ bIsAttacking = true;
+
+ if (IsPlayer())
+ nPlayerInComboMove = 0;
+}
+
+void
+CPed::StartFightDefend(uint8 direction, uint8 hitLevel, uint8 unk)
+{
+ if (m_nPedState == PED_DEAD) {
+ if (CGame::nastyGame) {
+ if (hitLevel == HITLEVEL_GROUND) {
+ CAnimBlendAssociation *floorHitAssoc;
+ if (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL)) {
+ floorHitAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FLOOR_HIT_F, 8.0f);
+ } else {
+ floorHitAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[FIGHTMOVE_HITONFLOOR].animId, 8.0f);
+ }
+ if (floorHitAssoc) {
+ floorHitAssoc->SetCurrentTime(0.0f);
+ floorHitAssoc->SetRun();
+ floorHitAssoc->flags &= ~ASSOC_FADEOUTWHENDONE;
+ }
+ }
+ if (CGame::nastyGame) {
+ CVector headPos = GetNodePosition(PED_HEAD);
+ for(int i = 0; i < 4; ++i) {
+ CVector bloodDir(0.0f, 0.0f, 0.1f);
+ CVector bloodPos = headPos - 0.2f * GetForward();
+ CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, bloodDir, nil, 0.0f, 0, 0, 0, 0);
+ }
+ }
+ }
+ } else if (m_nPedState == PED_FALL) {
+ if (hitLevel == HITLEVEL_GROUND && !IsPedHeadAbovePos(-0.3f)) {
+ CAnimBlendAssociation *floorHitAssoc = RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL) ?
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FLOOR_HIT_F, 8.0f) :
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FLOOR_HIT, 8.0f);
+ if (floorHitAssoc) {
+ floorHitAssoc->flags &= ~ASSOC_FADEOUTWHENDONE;
+ floorHitAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ }
+ }
+ } else if (IsPedInControl()) {
+ if ((IsPlayer() && m_nPedState != PED_FIGHT && ((CPlayerPed*)this)->m_fMoveSpeed > 1.0f)
+ || (!IsPlayer() && m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE)) {
+#ifndef VC_PED_PORTS
+ if (hitLevel != HITLEVEL_HIGH && hitLevel != HITLEVEL_LOW || (IsPlayer() || CGeneral::GetRandomNumber() & 3) && CGeneral::GetRandomNumber() & 7) {
+ if (IsPlayer() || CGeneral::GetRandomNumber() & 3) {
+#else
+ if (hitLevel != HITLEVEL_HIGH && hitLevel != HITLEVEL_LOW || (IsPlayer() || CGeneral::GetRandomNumber() & 1) && CGeneral::GetRandomNumber() & 7) {
+ if (IsPlayer() || CGeneral::GetRandomNumber() & 1) {
+#endif
+ AnimationId shotAnim;
+ switch (direction) {
+ case 1:
+ shotAnim = ANIM_SHOT_LEFT_PARTIAL;
+ break;
+ case 2:
+ shotAnim = ANIM_SHOT_BACK_PARTIAL;
+ break;
+ case 3:
+ shotAnim = ANIM_SHOT_RIGHT_PARTIAL;
+ break;
+ default:
+ shotAnim = ANIM_SHOT_FRONT_PARTIAL;
+ break;
+ }
+ CAnimBlendAssociation *shotAssoc = RpAnimBlendClumpGetAssociation(GetClump(), shotAnim);
+ if (!shotAssoc || shotAssoc->blendDelta < 0.0f)
+ shotAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, shotAnim, 8.0f);
+
+ shotAssoc->SetCurrentTime(0.0f);
+ shotAssoc->SetRun();
+ shotAssoc->flags |= ASSOC_FADEOUTWHENDONE;
+ } else {
+ int time = CGeneral::GetRandomNumberInRange(1000, 3000);
+ SetWaitState(WAITSTATE_PLAYANIM_DUCK, &time);
+ }
+ } else {
+#ifndef VC_PED_PORTS
+ switch (direction) {
+ case 1:
+ SetFall(500, ANIM_KO_SPIN_R, false);
+ break;
+ case 2:
+ SetFall(500, ANIM_KO_SKID_BACK, false);
+ break;
+ case 3:
+ SetFall(500, ANIM_KO_SPIN_L, false);
+ break;
+ default:
+ SetFall(500, ANIM_KO_SHOT_STOM, false);
+ break;
+ }
+#else
+ bool fall = true;
+ AnimationId hitAnim;
+ switch (direction) {
+ case 1:
+ hitAnim = ANIM_KO_SPIN_R;
+ break;
+ case 2:
+ if (CGeneral::GetRandomNumber() & 1) {
+ fall = false;
+ hitAnim = ANIM_HIT_BACK;
+ } else {
+ hitAnim = ANIM_KO_SKID_BACK;
+ }
+ break;
+ case 3:
+ hitAnim = ANIM_KO_SPIN_L;
+ break;
+ default:
+ if (hitLevel == HITLEVEL_LOW) {
+ hitAnim = ANIM_KO_SHOT_STOM;
+ } else if (CGeneral::GetRandomNumber() & 1) {
+ fall = false;
+ hitAnim = ANIM_HIT_WALK;
+ } else if (CGeneral::GetRandomNumber() & 1) {
+ fall = false;
+ hitAnim = ANIM_HIT_HEAD;
+ } else {
+ hitAnim = ANIM_KO_SHOT_FACE;
+ }
+ break;
+ }
+ if (fall) {
+ SetFall(500, hitAnim, false);
+ } else {
+ CAnimBlendAssociation *hitAssoc = RpAnimBlendClumpGetAssociation(GetClump(), hitAnim);
+ if (!hitAssoc || hitAssoc->blendDelta < 0.0f)
+ hitAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, hitAnim, 8.0f);
+
+ hitAssoc->SetCurrentTime(0.0f);
+ hitAssoc->SetRun();
+ hitAssoc->flags |= ASSOC_FADEOUTWHENDONE;
+ }
+#endif
+ }
+ Say(SOUND_PED_DEFEND);
+ } else {
+ Say(SOUND_PED_DEFEND);
+ switch (hitLevel) {
+ case HITLEVEL_GROUND:
+ m_curFightMove = FIGHTMOVE_HITONFLOOR;
+ break;
+ case HITLEVEL_LOW:
+#ifndef VC_PED_PORTS
+ if (direction == 2) {
+ SetFall(1000, ANIM_KO_SKID_BACK, false);
+ return;
+ }
+#else
+ if (direction == 2 && (!IsPlayer() || ((CGeneral::GetRandomNumber() & 1) && m_fHealth < 30.0f))) {
+ SetFall(1000, ANIM_KO_SKID_BACK, false);
+ return;
+ } else if (direction != 2 && !IsPlayer() && (CGeneral::GetRandomNumber() & 1) && m_fHealth < 30.0f) {
+ SetFall(1000, ANIM_KO_SHOT_STOM, false);
+ return;
+ }
+#endif
+ m_curFightMove = FIGHTMOVE_HITBODY;
+ break;
+ case HITLEVEL_HIGH:
+ switch (direction) {
+ case 1:
+ m_curFightMove = FIGHTMOVE_HITLEFT;
+ break;
+ case 2:
+ m_curFightMove = FIGHTMOVE_HITBACK;
+ break;
+ case 3:
+ m_curFightMove = FIGHTMOVE_HITRIGHT;
+ break;
+ default:
+ if (unk <= 5)
+ m_curFightMove = FIGHTMOVE_HITHEAD;
+ else
+ m_curFightMove = FIGHTMOVE_HITBIGSTEP;
+ break;
+ }
+ break;
+ default:
+ switch (direction) {
+ case 1:
+ m_curFightMove = FIGHTMOVE_HITLEFT;
+ break;
+ case 2:
+ m_curFightMove = FIGHTMOVE_HITBACK;
+ break;
+ case 3:
+ m_curFightMove = FIGHTMOVE_HITRIGHT;
+ break;
+ default:
+ if (unk <= 5)
+ m_curFightMove = FIGHTMOVE_HITCHEST;
+ else
+ m_curFightMove = FIGHTMOVE_HITBIGSTEP;
+ break;
+ }
+ break;
+ }
+ if (m_nPedState == PED_GETUP && !IsPedHeadAbovePos(0.0f))
+ m_curFightMove = FIGHTMOVE_HITONFLOOR;
+
+ if (m_nPedState == PED_FIGHT) {
+ CAnimBlendAssociation *moveAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 8.0f);
+ moveAssoc->SetCurrentTime(0.0f);
+ moveAssoc->SetFinishCallback(FinishFightMoveCB, this);
+ if (IsPlayer())
+ moveAssoc->speed = 1.3f;
+
+ m_takeAStepAfterAttack = 0;
+ m_fightButtonPressure = 0;
+ } else if (IsPlayer() && m_currentWeapon != WEAPONTYPE_UNARMED) {
+ CAnimBlendAssociation *moveAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 4.0f);
+ moveAssoc->SetCurrentTime(0.0f);
+ moveAssoc->speed = 1.3f;
+ } else {
+ if (m_nPedState != PED_AIM_GUN && m_nPedState != PED_ATTACK)
+ SetStoredState();
+
+ if (m_nWaitState != WAITSTATE_FALSE) {
+ m_nWaitState = WAITSTATE_FALSE;
+ RestoreHeadingRate();
+ }
+ m_nPedState = PED_FIGHT;
+ m_fightButtonPressure = 0;
+ RpAnimBlendClumpRemoveAssociations(GetClump(), ASSOC_REPEAT);
+ CAnimBlendAssociation *walkStartAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WALK_START);
+ if (walkStartAssoc) {
+ walkStartAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ walkStartAssoc->blendDelta = -1000.0f;
+ }
+ CAnimBlendAssociation *walkStopAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP);
+ if (!walkStopAssoc)
+ walkStopAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RUN_STOP_R);
+ if (walkStopAssoc) {
+ walkStopAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ walkStopAssoc->blendDelta = -1000.0f;
+ RestoreHeadingRate();
+ }
+ SetMoveState(PEDMOVE_NONE);
+ m_nStoredMoveState = PEDMOVE_NONE;
+ CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT_IDLE)->blendAmount = 1.0f;
+ CAnimBlendAssociation *moveAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 8.0f);
+ moveAssoc->SetFinishCallback(FinishFightMoveCB, this);
+ m_fightState = FIGHTSTATE_NO_MOVE;
+ m_takeAStepAfterAttack = false;
+ bIsAttacking = true;
+ }
+ }
+ }
+}
+
+void
+CPed::Fight(void)
+{
+ CAnimBlendAssociation *currentAssoc, *animAssoc;
+ bool hasShoppingBags, punchOnly, canKick, canKneeHead, canRoundhouse;
+ float angleToFace, nextAngle;
+ bool goForward = false;
+ int nextFightMove;
+
+ switch (m_curFightMove) {
+ case FIGHTMOVE_NULL:
+ return;
+ case FIGHTMOVE_IDLE2NORM:
+ m_curFightMove = FIGHTMOVE_NULL;
+ RestorePreviousState();
+
+ // FIX: Uninitialized
+ currentAssoc = nil;
+ break;
+ case FIGHTMOVE_IDLE:
+ currentAssoc = nil;
+ break;
+ default:
+ currentAssoc = RpAnimBlendClumpGetAssociation(GetClump(), tFightMoves[m_curFightMove].animId);
+ break;
+ }
+
+ if (!bIsAttacking && IsPlayer()) {
+ if (currentAssoc) {
+ currentAssoc->blendDelta = -1000.0f;
+ currentAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ currentAssoc->flags &= ~ASSOC_RUNNING;
+ }
+ if (m_takeAStepAfterAttack)
+ EndFight(ENDFIGHT_WITH_A_STEP);
+ else
+ EndFight(ENDFIGHT_FAST);
+
+ } else if (currentAssoc && m_fightState > FIGHTSTATE_MOVE_FINISHED) {
+ float animTime = currentAssoc->currentTime;
+ FightMove &curMove = tFightMoves[m_curFightMove];
+ if (curMove.hitLevel != HITLEVEL_NULL && animTime > curMove.startFireTime && animTime <= curMove.endFireTime && m_fightState >= FIGHTSTATE_NO_MOVE) {
+
+ CVector touchingNodePos(0.0f, 0.0f, 0.0f);
+
+ switch (m_curFightMove) {
+ case FIGHTMOVE_STDPUNCH:
+ case FIGHTMOVE_PUNCHHOOK:
+ case FIGHTMOVE_BODYBLOW:
+ TransformToNode(touchingNodePos, PED_HANDR);
+ break;
+ case FIGHTMOVE_IDLE:
+ case FIGHTMOVE_SHUFFLE_F:
+ break;
+ case FIGHTMOVE_KNEE:
+ TransformToNode(touchingNodePos, PED_LOWERLEGR);
+ break;
+ case FIGHTMOVE_HEADBUTT:
+ TransformToNode(touchingNodePos, PED_HEAD);
+ break;
+ case FIGHTMOVE_PUNCHJAB:
+ TransformToNode(touchingNodePos, PED_HANDL);
+ break;
+ case FIGHTMOVE_KICK:
+ case FIGHTMOVE_LONGKICK:
+ case FIGHTMOVE_ROUNDHOUSE:
+ case FIGHTMOVE_GROUNDKICK:
+ TransformToNode(touchingNodePos, PED_FOOTR);
+ break;
+ }
+
+ if (m_curFightMove == FIGHTMOVE_PUNCHJAB) {
+ touchingNodePos += 0.1f * GetForward();
+ } else if (m_curFightMove == FIGHTMOVE_PUNCHHOOK) {
+ touchingNodePos += 0.22f * GetForward();
+ }
+ FightStrike(touchingNodePos);
+ m_fightButtonPressure = 0;
+ return;
+ }
+
+ if (curMove.hitLevel != HITLEVEL_NULL) {
+ if (animTime > curMove.endFireTime) {
+ if (IsPlayer())
+ currentAssoc->speed = 1.0f;
+ else
+ currentAssoc->speed = 0.8f;
+ }
+
+ if (IsPlayer() && !nPlayerInComboMove) {
+ if (curMove.comboFollowOnTime > 0.0f && m_fightButtonPressure != 0 && animTime > curMove.comboFollowOnTime) {
+
+ // Notice that it increases fight move index, because we're in combo!
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[++m_curFightMove].animId, 8.0f);
+ animAssoc->SetFinishCallback(FinishFightMoveCB, this);
+ animAssoc->SetCurrentTime(0.1f * animAssoc->hierarchy->totalLength);
+ m_fightButtonPressure = 0;
+ nPlayerInComboMove = 1;
+ }
+ }
+ } else {
+ if (curMove.startFireTime > 0.0f && m_curFightMove != FIGHTMOVE_SHUFFLE_F && animTime > curMove.startFireTime) {
+ if (IsPlayer())
+ currentAssoc->speed = 1.3f;
+ else
+ currentAssoc->speed = 0.8f;
+ }
+ }
+ } else if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED) {
+ EndFight(ENDFIGHT_FAST);
+
+ } else if (m_fightButtonPressure != 0) {
+ bool canAffectMultiplePeople = true;
+ nextAngle = m_fRotationCur;
+ bool kickGround = false;
+ float angleForGroundKick = 0.0f;
+ CPed *pedOnGround = nil;
+
+ Say(SOUND_PED_ATTACK);
+
+ if (IsPlayer()) {
+ canRoundhouse = false;
+ punchOnly = false;
+ canKick = true;
+ nextFightMove = (m_fightButtonPressure > 190 ? FIGHTMOVE_HEADBUTT : FIGHTMOVE_KNEE);
+ hasShoppingBags = false;
+ canKneeHead = true;
+ nPlayerInComboMove = 0;
+ } else {
+ nextFightMove = (m_fightButtonPressure > 120 ? FIGHTMOVE_HEADBUTT : FIGHTMOVE_KNEE);
+ uint16 pedFeatures = m_pedStats->m_flags;
+ punchOnly = pedFeatures & STAT_PUNCH_ONLY;
+ canRoundhouse = pedFeatures & STAT_CAN_ROUNDHOUSE;
+ canKneeHead = pedFeatures & STAT_CAN_KNEE_HEAD;
+ canKick = pedFeatures & STAT_CAN_KICK;
+ hasShoppingBags = pedFeatures & STAT_SHOPPING_BAGS;
+ }
+
+ // Attack isn't scripted, find the victim
+ if (IsPlayer() || !m_pedInObjective) {
+
+ for (int i = 0; i < m_numNearPeds; i++) {
+
+ CPed *nearPed = m_nearPeds[i];
+ float nearPedDist = (nearPed->GetPosition() - GetPosition()).Magnitude();
+ if (nearPedDist < 3.0f) {
+ float angleToFace = CGeneral::GetRadianAngleBetweenPoints(
+ nearPed->GetPosition().x, nearPed->GetPosition().y,
+ GetPosition().x, GetPosition().y);
+
+ nextAngle = CGeneral::LimitRadianAngle(angleToFace);
+ m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur);
+
+ float neededTurn = Abs(nextAngle - m_fRotationCur);
+ if (neededTurn > PI)
+ neededTurn = TWOPI - neededTurn;
+
+ if (!nearPed->OnGroundOrGettingUp()) {
+
+ if (nearPedDist < 0.8f && neededTurn < DEGTORAD(75.0f) && canKneeHead) {
+ canAffectMultiplePeople = false;
+ } else if (nearPedDist >= 1.3f || neededTurn >= DEGTORAD(55.0f) || hasShoppingBags) {
+
+ if (nearPedDist < 1.7f
+ && neededTurn < DEGTORAD(35.0f)
+ && (canKick || hasShoppingBags)) {
+
+ nextFightMove = FIGHTMOVE_KICK;
+ if (hasShoppingBags) {
+ nextFightMove = FIGHTMOVE_ROUNDHOUSE;
+ } else if (canRoundhouse && CGeneral::GetRandomNumber() & 1) {
+ nextFightMove = FIGHTMOVE_ROUNDHOUSE;
+ }
+ canAffectMultiplePeople = false;
+ } else if (nearPedDist < 2.0f && neededTurn < DEGTORAD(30.0f) && canKick) {
+ canAffectMultiplePeople = false;
+ nextFightMove = FIGHTMOVE_LONGKICK;
+ } else if (neededTurn < DEGTORAD(30.0f)) {
+ goForward = true;
+ }
+ } else {
+ nextFightMove += 2; // Makes it 6 or 7
+ if (punchOnly)
+ nextFightMove = FIGHTMOVE_PUNCHJAB;
+
+ canAffectMultiplePeople = false;
+ }
+ } else if (!CGame::nastyGame
+ || nearPedDist >= 1.3f
+ || neededTurn >= DEGTORAD(55.0f)
+ || punchOnly) {
+
+ if (nearPedDist > 0.8f
+ && nearPedDist < 3.0f
+ && neededTurn < DEGTORAD(30.0f)) {
+ goForward = true;
+ }
+
+ } else if (nearPed->m_nPedState != PED_DEAD || pedOnGround) {
+ if (!nearPed->IsPedHeadAbovePos(-0.3f)) {
+ canAffectMultiplePeople = false;
+ nextFightMove = FIGHTMOVE_GROUNDKICK;
+ }
+
+ } else {
+ pedOnGround = nearPed;
+ kickGround = true;
+ angleForGroundKick = nextAngle;
+ }
+ }
+
+ if (!canAffectMultiplePeople) {
+ m_fRotationDest = nextAngle;
+ if (IsPlayer()) {
+ m_fRotationCur = m_fRotationDest;
+ m_lookTimer = 0;
+ SetLookFlag(nearPed, true);
+ SetLookTimer(1500);
+ }
+ break;
+ }
+ }
+ } else {
+ // Because we're in a scripted fight with some particular ped.
+ canAffectMultiplePeople = false;
+
+ float fightingPedDist = (m_pedInObjective->GetPosition() - GetPosition()).Magnitude();
+ if (hasShoppingBags) {
+ if (fightingPedDist >= 1.7f)
+ nextFightMove = FIGHTMOVE_SHUFFLE_F;
+ else
+ nextFightMove = FIGHTMOVE_ROUNDHOUSE;
+
+ } else if (punchOnly) {
+ if (fightingPedDist >= 1.3f)
+ nextFightMove = FIGHTMOVE_SHUFFLE_F;
+ else
+ nextFightMove = FIGHTMOVE_PUNCHJAB;
+
+ } else if (fightingPedDist >= 3.0f) {
+ nextFightMove = FIGHTMOVE_STDPUNCH;
+
+ } else {
+ angleToFace = CGeneral::GetRadianAngleBetweenPoints(
+ m_pedInObjective->GetPosition().x,
+ m_pedInObjective->GetPosition().y,
+ GetPosition().x,
+ GetPosition().y);
+
+ nextAngle = CGeneral::LimitRadianAngle(angleToFace);
+ m_fRotationDest = nextAngle;
+ m_fRotationCur = m_fRotationDest;
+ if (!m_pedInObjective->OnGroundOrGettingUp()) {
+
+ if (fightingPedDist >= 0.8f || !canKneeHead) {
+
+ if (fightingPedDist >= 1.3f) {
+
+ if (fightingPedDist < 1.7f && canKick) {
+ nextFightMove = FIGHTMOVE_KICK;
+ if (canRoundhouse && CGeneral::GetRandomNumber() & 1)
+ nextFightMove = FIGHTMOVE_ROUNDHOUSE;
+
+ } else if (fightingPedDist < 2.0f && canKick) {
+ nextFightMove += 5; // Makes it 9 or 10
+
+ } else {
+ nextFightMove = FIGHTMOVE_SHUFFLE_F;
+
+ }
+ } else {
+ nextFightMove += 2; // Makes it 6 or 7
+ }
+ }
+ } else if (!CGame::nastyGame
+ || fightingPedDist >= 1.3f
+ || m_pedInObjective->IsPlayer()
+ || m_pedInObjective->m_nPedState != PED_DEAD && m_pedInObjective->IsPedHeadAbovePos(-0.3f)) {
+ nextFightMove = FIGHTMOVE_IDLE;
+ } else {
+ nextFightMove = FIGHTMOVE_GROUNDKICK;
+ }
+ }
+ }
+
+ if (canAffectMultiplePeople) {
+ if (kickGround && IsPlayer()) {
+ m_fRotationDest = angleForGroundKick;
+ nextFightMove = FIGHTMOVE_GROUNDKICK;
+ m_fRotationCur = m_fRotationDest;
+ m_lookTimer = 0;
+ SetLookFlag(pedOnGround, true);
+ SetLookTimer(1500);
+ } else if (goForward) {
+ nextFightMove = FIGHTMOVE_SHUFFLE_F;
+ } else {
+ nextFightMove = FIGHTMOVE_STDPUNCH;
+ }
+ }
+
+ if (nextFightMove != FIGHTMOVE_IDLE) {
+ m_curFightMove = nextFightMove;
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 4.0f);
+
+ animAssoc->SetFinishCallback(FinishFightMoveCB, this);
+ if (m_fightState == FIGHTSTATE_MOVE_FINISHED && animAssoc->currentTime != 0.0f) {
+ animAssoc->SetCurrentTime(0.0f);
+ animAssoc->SetRun();
+ }
+ m_fightButtonPressure = 0;
+ }
+ m_fightState = FIGHTSTATE_NO_MOVE;
+ } else if (m_takeAStepAfterAttack && m_curFightMove != FIGHTMOVE_SHUFFLE_F
+#ifndef FIX_BUGS
+ && CheckForPedsOnGroundToAttack(this, nil) == 4) {
+#else
+ && CheckForPedsOnGroundToAttack(this, nil) == PED_IN_FRONT_OF_ATTACKER) {
+#endif
+ m_curFightMove = FIGHTMOVE_SHUFFLE_F;
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), tFightMoves[m_curFightMove].animId);
+
+ if (animAssoc) {
+ animAssoc->SetCurrentTime(0.0f);
+ animAssoc->blendDelta = 4.0f;
+ animAssoc->SetRun();
+ } else {
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_curFightMove].animId, 32.0f);
+ }
+ animAssoc->SetFinishCallback(FinishFightMoveCB, this);
+ m_fightState = FIGHTSTATE_NO_MOVE;
+ m_fightButtonPressure = 0;
+ m_takeAStepAfterAttack = false;
+
+ } else if (m_takeAStepAfterAttack) {
+ EndFight(ENDFIGHT_FAST);
+
+ } else if (m_curFightMove == FIGHTMOVE_IDLE) {
+ if (CTimer::GetTimeInMilliseconds() > m_nWaitTimer) {
+ EndFight(ENDFIGHT_NORMAL);
+ }
+
+ } else {
+ m_curFightMove = FIGHTMOVE_IDLE;
+ if (IsPlayer())
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 500;
+ else
+ m_nWaitTimer = CTimer::GetTimeInMilliseconds() + 2000;
+ }
+}
+
+void
+CPed::EndFight(uint8 endType)
+{
+ if (m_nPedState != PED_FIGHT)
+ return;
+
+ m_curFightMove = FIGHTMOVE_NULL;
+ RestorePreviousState();
+ CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_FIGHT_IDLE);
+ if (animAssoc)
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+
+ switch (endType) {
+ case ENDFIGHT_NORMAL:
+ CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 8.0f);
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT2_IDLE, 8.0f);
+ break;
+ case ENDFIGHT_WITH_A_STEP:
+ CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 1.0f);
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_WALK_START, 8.0f);
+ break;
+ case ENDFIGHT_FAST:
+ CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 8.0f);
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT2_IDLE, 8.0f)->speed = 2.0f;
+ break;
+ default:
+ break;
+ }
+ m_nWaitTimer = 0;
+}
+
+
+void
+CPed::PlayHitSound(CPed *hitTo)
+{
+ // That was very complicated to reverse for me...
+ // First index is our fight move ID (from 1 to 12, total 12), second is the one of we fight with (from 13 to 22, total 10).
+ enum {
+ S33 = SOUND_FIGHT_PUNCH_33,
+ S34 = SOUND_FIGHT_KICK_34,
+ S35 = SOUND_FIGHT_HEADBUTT_35,
+ S36 = SOUND_FIGHT_PUNCH_36,
+ S37 = SOUND_FIGHT_PUNCH_37,
+ S38 = SOUND_FIGHT_CLOSE_PUNCH_38,
+ S39 = SOUND_FIGHT_PUNCH_39,
+ S40 = SOUND_FIGHT_PUNCH_OR_KICK_BELOW_40 ,
+ S41 = SOUND_FIGHT_PUNCH_41,
+ S42 = SOUND_FIGHT_PUNCH_FROM_BEHIND_42,
+ S43 = SOUND_FIGHT_KNEE_OR_KICK_43,
+ S44 = SOUND_FIGHT_KICK_44,
+ NO_SND = SOUND_NO_SOUND
+ };
+ uint16 hitSoundsByFightMoves[12][10] = {
+ {S39,S42,S43,S43,S39,S39,S39,S39,S39,S42},
+ {NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND},
+ {NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND,NO_SND},
+ {S39,S39,S39,S39,S33,S43,S39,S39,S39,S39},
+ {S39,S39,S39,S39,S35,S39,S38,S38,S39,S39},
+ {S39,S39,S39,S39,S33,S39,S41,S36,S39,S39},
+ {S39,S39,S39,S39,S37,S40,S38,S38,S39,S39},
+ {S39,S39,S39,S39,S34,S43,S44,S37,S39,S39},
+ {S39,S39,S39,S39,S34,S43,S44,S37,S39,S39},
+ {S39,S39,S39,S39,S34,S43,S44,S37,S39,S40},
+ {S39,S39,S39,S39,S33,S39,S41,S37,S39,S40},
+ {S39,S39,S39,S39,S39,S39,S39,S39,S33,S33}
+ };
+
+ // This is why first dimension is between FightMove 1 and 12.
+ if (m_curFightMove == FIGHTMOVE_NULL || m_curFightMove >= FIGHTMOVE_HITFRONT)
+ return;
+
+ uint16 soundId;
+
+ // And this is why second dimension is between 13 and 22.
+ if (hitTo->m_curFightMove > FIGHTMOVE_GROUNDKICK && hitTo->m_curFightMove < FIGHTMOVE_IDLE2NORM) {
+ soundId = hitSoundsByFightMoves[m_curFightMove - FIGHTMOVE_STDPUNCH][hitTo->m_curFightMove - FIGHTMOVE_HITFRONT];
+
+ } else {
+ if (hitTo->m_nPedState == PED_DEAD || hitTo->UseGroundColModel()) {
+ soundId = hitSoundsByFightMoves[m_curFightMove - FIGHTMOVE_STDPUNCH][FIGHTMOVE_HITONFLOOR - FIGHTMOVE_HITFRONT];
+ } else {
+ soundId = hitSoundsByFightMoves[m_curFightMove - FIGHTMOVE_STDPUNCH][FIGHTMOVE_HITFRONT - FIGHTMOVE_HITFRONT];
+ }
+ }
+
+ if (soundId != NO_SND)
+ DMAudio.PlayOneShot(m_audioEntityId, soundId, 0.0f);
+}
+
+bool
+CPed::FightStrike(CVector &touchedNodePos)
+{
+ CColModel *ourCol;
+ CVector attackDistance;
+ ePedPieceTypes closestPedPiece = PEDPIECE_TORSO;
+ float maxDistanceToBeBeaten;
+ CPed *nearPed;
+ int state = m_fightState;
+ bool pedFound = false;
+
+ if (state == FIGHTSTATE_JUST_ATTACKED)
+ return false;
+
+ // Pointless code
+ if (state > FIGHTSTATE_NO_MOVE)
+ attackDistance = touchedNodePos - m_vecHitLastPos;
+
+ for (int i = 0; i < m_numNearPeds; i++) {
+ nearPed = m_nearPeds[i];
+ if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED)
+ maxDistanceToBeBeaten = nearPed->GetBoundRadius() + tFightMoves[m_curFightMove].strikeRadius + 0.1f;
+ else
+ maxDistanceToBeBeaten = nearPed->GetBoundRadius() + tFightMoves[m_curFightMove].strikeRadius;
+
+ if (nearPed->bUsesCollision || nearPed->m_nPedState == PED_DEAD) {
+ CVector nearPedCentre;
+ nearPed->GetBoundCentre(nearPedCentre);
+ CVector potentialAttackDistance = nearPedCentre - touchedNodePos;
+
+ // He can beat us
+ if (sq(maxDistanceToBeBeaten) > potentialAttackDistance.MagnitudeSqr()) {
+
+#ifdef PED_SKIN
+ // Have to animate a skinned clump because the initial col model is useless
+ if(IsClumpSkinned(GetClump()))
+ ourCol = ((CPedModelInfo *)CModelInfo::GetModelInfo(GetModelIndex()))->AnimatePedColModelSkinned(GetClump());
+ else
+#endif
+ if (nearPed->OnGround() || !nearPed->IsPedHeadAbovePos(-0.3f)) {
+ ourCol = &CTempColModels::ms_colModelPedGroundHit;
+ } else {
+#ifdef ANIMATE_PED_COL_MODEL
+ ourCol = CPedModelInfo::AnimatePedColModel(((CPedModelInfo *)CModelInfo::GetModelInfo(GetModelIndex()))->GetHitColModel(),
+ RpClumpGetFrame(GetClump()));
+#else
+ ourCol = ((CPedModelInfo*)CModelInfo::GetModelInfo(m_modelIndex))->GetHitColModel();
+#endif
+ }
+
+ for (int j = 0; j < ourCol->numSpheres; j++) {
+ attackDistance = nearPed->GetPosition() + ourCol->spheres[j].center;
+ attackDistance -= touchedNodePos;
+ CColSphere *ourPieces = ourCol->spheres;
+ float maxDistanceToBeat = ourPieces[j].radius + tFightMoves[m_curFightMove].strikeRadius;
+
+ // We can beat him too
+ if (sq(maxDistanceToBeat) > attackDistance.MagnitudeSqr()) {
+ pedFound = true;
+ closestPedPiece = (ePedPieceTypes) ourPieces[j].piece;
+ break;
+ }
+ }
+ }
+ }
+ if (pedFound)
+ break;
+ }
+
+ if (pedFound) {
+ if (nearPed->IsPlayer() && nearPed->m_nPedState == PED_GETUP)
+ return false;
+
+ float oldVictimHealth = nearPed->m_fHealth;
+ CVector bloodPos = 0.5f * attackDistance + touchedNodePos;
+ int damageMult = tFightMoves[m_curFightMove].damage * ((CGeneral::GetRandomNumber() & 1) + 2) + 1;
+
+ CVector2D diff (GetPosition() - nearPed->GetPosition());
+ int direction = nearPed->GetLocalDirection(diff);
+ if (IsPlayer()) {
+ if (((CPlayerPed*)this)->m_bAdrenalineActive)
+ damageMult = 20;
+ } else {
+ damageMult *= m_pedStats->m_attackStrength;
+ }
+
+ // Change direction if we used kick.
+ if (m_curFightMove == FIGHTMOVE_KICK) {
+ if (CGeneral::GetRandomNumber() & 1) {
+ direction++;
+ if (direction > 3)
+ direction -= 4;
+ }
+ }
+ nearPed->ReactToAttack(this);
+
+ // Mostly unused. if > 5, ANIM_HIT_WALK will be run, that's it.
+ int unk2;
+ if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED && !nearPed->IsPlayer())
+ unk2 = 101;
+ else
+ unk2 = damageMult;
+
+ nearPed->StartFightDefend(direction, tFightMoves[m_curFightMove].hitLevel, unk2);
+ PlayHitSound(nearPed);
+ m_fightState = FIGHTSTATE_JUST_ATTACKED;
+ RpAnimBlendClumpGetAssociation(GetClump(), tFightMoves[m_curFightMove].animId)->speed = 0.6f;
+ if (!nearPed->DyingOrDead()) {
+ nearPed->InflictDamage(this, WEAPONTYPE_UNARMED, damageMult * 3.0f, closestPedPiece, direction);
+ }
+
+ if (CGame::nastyGame
+ && tFightMoves[m_curFightMove].hitLevel > HITLEVEL_MEDIUM
+ && nearPed->m_nPedState == PED_DIE
+ && nearPed->GetIsOnScreen()) {
+
+ // Just for blood particle. We will restore it below.
+ attackDistance /= (10.0f * attackDistance.Magnitude());
+ for(int i=0; i<4; i++) {
+ CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, attackDistance, nil, 0.0f, 0, 0, 0, 0);
+ }
+ }
+ if (!nearPed->OnGround()) {
+ float curVictimHealth = nearPed->m_fHealth;
+ if (curVictimHealth > 0.0f
+ && (curVictimHealth < 40.0f && oldVictimHealth > 40.0f && !nearPed->IsPlayer()
+ || nearPed->m_fHealth < 20.0f && oldVictimHealth > 20.0f
+ || GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED && IsPlayer()
+ || nearPed->m_pedStats->m_flags & STAT_ONE_HIT_KNOCKDOWN)) {
+
+ nearPed->SetFall(0, (AnimationId)(direction + ANIM_KO_SKID_FRONT), 0);
+ if (nearPed->m_nPedState == PED_FALL)
+ nearPed->bIsStanding = false;
+ }
+ }
+ if (nearPed->m_nPedState == PED_DIE || !nearPed->bIsStanding) {
+ attackDistance = nearPed->GetPosition() - GetPosition();
+ attackDistance.Normalise();
+ attackDistance.z = 1.0f;
+ nearPed->bIsStanding = false;
+
+ float moveMult;
+ if (m_curFightMove == FIGHTMOVE_GROUNDKICK) {
+ moveMult = Min(damageMult * 0.6f, 4.0f);
+ } else {
+ if (nearPed->m_nPedState != PED_DIE || damageMult >= 20) {
+ moveMult = damageMult;
+ } else {
+ moveMult = Min(damageMult * 2.0f, 14.0f);
+ }
+ }
+
+ nearPed->ApplyMoveForce(moveMult * 0.6f * attackDistance);
+ }
+ CEventList::RegisterEvent(nearPed->m_nPedType == PEDTYPE_COP ? EVENT_ASSAULT_POLICE : EVENT_ASSAULT, EVENT_ENTITY_PED, nearPed, this, 2000);
+ }
+
+ if (m_fightState == FIGHTSTATE_NO_MOVE)
+ m_fightState = FIGHTSTATE_1;
+
+ m_vecHitLastPos = *touchedNodePos;
+ return false;
+}
+
+void
+CPed::FinishFightMoveCB(CAnimBlendAssociation *animAssoc, void *arg)
+{
+ CPed *ped = (CPed*)arg;
+
+ if (tFightMoves[ped->m_curFightMove].animId == animAssoc->animId) {
+ ped->m_fightState = FIGHTSTATE_MOVE_FINISHED;
+ animAssoc->blendDelta = -1000.0f;
+ }
+}
+
+void
+CPed::LoadFightData(void)
+{
+ float startFireTime, endFireTime, comboFollowOnTime, strikeRadius;
+ int damage, flags;
+ char line[256], moveName[32], animName[32], hitLevel;
+ int moveId = 0;
+
+ CAnimBlendAssociation *animAssoc;
+
+ size_t bp, buflen;
+ int lp, linelen;
+
+ buflen = CFileMgr::LoadFile("DATA\\fistfite.dat", work_buff, sizeof(work_buff), "r");
+
+ for (bp = 0; bp < buflen; ) {
+ // read file line by line
+ for (linelen = 0; work_buff[bp] != '\n' && bp < buflen; bp++) {
+ line[linelen++] = work_buff[bp];
+ }
+ bp++;
+ line[linelen] = '\0';
+
+ // skip white space
+ for (lp = 0; line[lp] <= ' ' && line[lp] != '\0'; lp++);
+
+ if (line[lp] == '\0' ||
+ line[lp] == '#')
+ continue;
+
+ sscanf(
+ &line[lp],
+ "%s %f %f %f %f %c %s %d %d",
+ moveName,
+ &startFireTime,
+ &endFireTime,
+ &comboFollowOnTime,
+ &strikeRadius,
+ &hitLevel,
+ animName,
+ &damage,
+ &flags);
+
+ if (strncmp(moveName, "ENDWEAPONDATA", 13) == 0)
+ return;
+
+ tFightMoves[moveId].startFireTime = startFireTime / 30.0f;
+ tFightMoves[moveId].endFireTime = endFireTime / 30.0f;
+ tFightMoves[moveId].comboFollowOnTime = comboFollowOnTime / 30.0f;
+ tFightMoves[moveId].strikeRadius = strikeRadius;
+ tFightMoves[moveId].damage = damage;
+ tFightMoves[moveId].flags = flags;
+
+ switch (hitLevel) {
+ case 'G':
+ tFightMoves[moveId].hitLevel = HITLEVEL_GROUND;
+ break;
+ case 'H':
+ tFightMoves[moveId].hitLevel = HITLEVEL_HIGH;
+ break;
+ case 'L':
+ tFightMoves[moveId].hitLevel = HITLEVEL_LOW;
+ break;
+ case 'M':
+ tFightMoves[moveId].hitLevel = HITLEVEL_MEDIUM;
+ break;
+ case 'N':
+ tFightMoves[moveId].hitLevel = HITLEVEL_NULL;
+ break;
+ default:
+ break;
+ }
+
+ if (strncmp(animName, "null", 4) != 0) {
+ animAssoc = CAnimManager::GetAnimAssociation(ASSOCGRP_STD, animName);
+ tFightMoves[moveId].animId = (AnimationId)animAssoc->animId;
+ } else {
+ tFightMoves[moveId].animId = ANIM_WALK;
+ }
+ moveId++;
+ }
+}
+
+void
+CPed::SetInvestigateEvent(eEventType event, CVector2D pos, float distanceToCountDone, uint16 time, float angle)
+{
+ if (!IsPedInControl() || CharCreatedBy == MISSION_CHAR)
+ return;
+
+ SetStoredState();
+ bFindNewNodeAfterStateRestore = false;
+ m_nPedState = PED_INVESTIGATE;
+ m_standardTimer = CTimer::GetTimeInMilliseconds() + time;
+ m_eventType = event;
+ m_eventOrThreat = pos;
+ m_distanceToCountSeekDone = distanceToCountDone;
+ m_fAngleToEvent = angle;
+
+ if (m_eventType >= EVENT_ICECREAM)
+ m_lookTimer = 0;
+ else
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_HANDSCOWER, 4.0f);
+
+}
+
+void
+CPed::InvestigateEvent(void)
+{
+ CAnimBlendAssociation *animAssoc;
+ AnimationId animToPlay;
+ AssocGroupId animGroup;
+
+ if (m_nWaitState == WAITSTATE_TURN180)
+ return;
+
+ if (CTimer::GetTimeInMilliseconds() > m_standardTimer) {
+
+ if (m_standardTimer) {
+ if (m_eventType < EVENT_ASSAULT_NASTYWEAPON)
+ SetWaitState(WAITSTATE_TURN180, nil);
+
+ m_standardTimer = 0;
+ } else {
+ ClearInvestigateEvent();
+ }
+ return;
+ }
+
+ CVector2D vecDist = m_eventOrThreat - GetPosition();
+ float distSqr = vecDist.MagnitudeSqr();
+ if (sq(m_distanceToCountSeekDone) >= distSqr) {
+
+ m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(vecDist.x, vecDist.y, 0.0f, 0.0f);
+ SetMoveState(PEDMOVE_STILL);
+
+ switch (m_eventType) {
+ case EVENT_DEAD_PED:
+ case EVENT_HIT_AND_RUN:
+ case EVENT_HIT_AND_RUN_COP:
+
+ if (CTimer::GetTimeInMilliseconds() > m_lookTimer) {
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_ROAD_CROSS);
+
+ if (animAssoc) {
+ animAssoc->blendDelta = -8.0f;
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ if (m_pEventEntity)
+ SetLookFlag(m_pEventEntity, true);
+
+ SetLookTimer(CGeneral::GetRandomNumberInRange(1500, 4000));
+
+ } else if (CGeneral::GetRandomNumber() & 3) {
+ ClearLookFlag();
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_ROAD_CROSS, 4.0f);
+
+ SetLookTimer(CGeneral::GetRandomNumberInRange(1000, 2500));
+ Say(SOUND_PED_CHAT_EVENT);
+
+ } else {
+ ClearInvestigateEvent();
+ }
+ }
+ break;
+ case EVENT_FIRE:
+ case EVENT_EXPLOSION:
+
+ if (bHasACamera && CTimer::GetTimeInMilliseconds() > m_lookTimer) {
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_CAM);
+ if (!animAssoc)
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE);
+
+ if (animAssoc && animAssoc->animId == ANIM_IDLE_CAM) {
+ CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 4.0f);
+ SetLookTimer(CGeneral::GetRandomNumberInRange(1000, 2500));
+
+ } else if (CGeneral::GetRandomNumber() & 3) {
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_IDLE_CAM, 4.0f);
+ SetLookTimer(CGeneral::GetRandomNumberInRange(2500, 5000));
+ Say(SOUND_PED_CHAT_EVENT);
+
+ } else {
+ m_standardTimer = 0;
+ }
+
+ } else if (CTimer::GetTimeInMilliseconds() > m_lookTimer) {
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_STANCE);
+ if (!animAssoc)
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_HBHB);
+
+ if (!animAssoc)
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_XPRESS_SCRATCH);
+
+ if (animAssoc && animAssoc->animId == ANIM_IDLE_STANCE) {
+ if (CGeneral::GetRandomNumber() & 1)
+ animToPlay = ANIM_IDLE_HBHB;
+ else
+ animToPlay = ANIM_XPRESS_SCRATCH;
+
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animToPlay, 4.0f);
+ SetLookTimer(CGeneral::GetRandomNumberInRange(1500, 4000));
+
+ } else if (animAssoc && animAssoc->animId == ANIM_IDLE_HBHB) {
+ animAssoc->blendDelta = -8.0f;
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ if (CGeneral::GetRandomNumber() & 1) {
+ animToPlay = ANIM_IDLE_STANCE;
+ animGroup = m_animGroup;
+ } else {
+ animToPlay = ANIM_XPRESS_SCRATCH;
+ animGroup = ASSOCGRP_STD;
+ }
+
+ CAnimManager::BlendAnimation(GetClump(), animGroup, animToPlay, 4.0f);
+ SetLookTimer(CGeneral::GetRandomNumberInRange(1000, 2500));
+
+ } else {
+ if (CGeneral::GetRandomNumber() & 1) {
+ animToPlay = ANIM_IDLE_STANCE;
+ animGroup = m_animGroup;
+ } else {
+ animToPlay = ANIM_IDLE_HBHB;
+ animGroup = ASSOCGRP_STD;
+ }
+
+ CAnimManager::BlendAnimation(GetClump(), animGroup, animToPlay, 4.0f);
+ SetLookTimer(CGeneral::GetRandomNumberInRange(1000, 2500));
+ }
+ Say(SOUND_PED_CHAT_EVENT);
+ }
+ break;
+ case EVENT_ICECREAM:
+ case EVENT_SHOPSTALL:
+
+ m_fRotationDest = m_fAngleToEvent;
+ if (CTimer::GetTimeInMilliseconds() > m_lookTimer) {
+
+ if (m_lookTimer) {
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_ROAD_CROSS);
+
+ if (animAssoc) {
+ animAssoc->blendDelta = -8.0f;
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ if (m_eventType == EVENT_ICECREAM)
+ animToPlay = ANIM_IDLE_CHAT;
+ else
+ animToPlay = ANIM_XPRESS_SCRATCH;
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animToPlay,4.0f);
+ SetLookTimer(CGeneral::GetRandomNumberInRange(2000, 5000));
+
+ } else {
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_CHAT);
+ if (animAssoc) {
+ animAssoc->blendDelta = -8.0f;
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ ClearInvestigateEvent();
+ } else {
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_XPRESS_SCRATCH);
+ if (animAssoc) {
+ animAssoc->blendDelta = -8.0f;
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ }
+ ClearInvestigateEvent();
+ }
+ }
+ } else {
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_ROAD_CROSS, 4.0f);
+ SetLookTimer(CGeneral::GetRandomNumberInRange(1000, 2500));
+ }
+ }
+ break;
+ default:
+ return;
+ }
+ } else {
+ m_vecSeekPos.x = m_eventOrThreat.x;
+ m_vecSeekPos.y = m_eventOrThreat.y;
+ m_vecSeekPos.z = GetPosition().z;
+ Seek();
+
+ if (m_eventType < EVENT_ICECREAM) {
+ if (sq(5.0f + m_distanceToCountSeekDone) < distSqr) {
+ SetMoveState(PEDMOVE_RUN);
+ return;
+ }
+ }
+ if (m_eventType <= EVENT_EXPLOSION || m_eventType >= EVENT_SHOPSTALL) {
+ SetMoveState(PEDMOVE_WALK);
+ return;
+ }
+ if (distSqr > sq(1.2f)) {
+ SetMoveState(PEDMOVE_WALK);
+ return;
+ }
+
+ for (int i = 0; i < m_numNearPeds; i++) {
+ if ((m_eventOrThreat - m_nearPeds[i]->GetPosition()).MagnitudeSqr() < sq(0.4f)) {
+ SetMoveState(PEDMOVE_STILL);
+ return;
+ }
+ }
+
+ SetMoveState(PEDMOVE_WALK);
+ }
+}
+
+void
+CPed::ClearInvestigateEvent(void)
+{
+ CAnimBlendAssociation *animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_ROAD_CROSS);
+ if (!animAssoc)
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_XPRESS_SCRATCH);
+ if (!animAssoc)
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_HBHB);
+ if (!animAssoc)
+ animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_IDLE_CHAT);
+ if (animAssoc) {
+ animAssoc->blendDelta = -8.0f;
+ animAssoc->flags |= ASSOC_DELETEFADEDOUT;
+ }
+ if (m_eventType > EVENT_EXPLOSION)
+ m_standardTimer = CTimer::GetTimeInMilliseconds() + 15000;
+
+ bGonnaInvestigateEvent = false;
+ m_pEventEntity = nil;
+ ClearLookFlag();
+ RestorePreviousState();
+ if(m_nMoveState == PEDMOVE_NONE || m_nMoveState == PEDMOVE_STILL)
+ SetMoveState(PEDMOVE_WALK);
+}
+
+bool
+CPed::InflictDamage(CEntity *damagedBy, eWeaponType method, float damage, ePedPieceTypes pedPiece, uint8 direction)
+{
+ CPlayerPed *player = FindPlayerPed();
+ float dieDelta = 4.0f;
+ float dieSpeed = 0.0f;
+ AnimationId dieAnim = ANIM_KO_SHOT_FRONT1;
+ bool headShot = false;
+ bool willLinger = false;
+ int random;
+
+ if (player == this) {
+ if (!player->m_bCanBeDamaged)
+ return false;
+
+ player->AnnoyPlayerPed(false);
+ }
+
+ if (DyingOrDead())
+ return false;
+
+ if (!bUsesCollision && method != WEAPONTYPE_DROWNING)
+ return false;
+
+ if (bOnlyDamagedByPlayer && damagedBy != player && damagedBy != FindPlayerVehicle() &&
+ method != WEAPONTYPE_DROWNING && method != WEAPONTYPE_EXPLOSION)
+ return false;
+
+ float healthImpact;
+ if (IsPlayer())
+ healthImpact = damage * 0.33f;
+ else
+ healthImpact = damage * m_pedStats->m_defendWeakness;
+
+ bool detectDieAnim = true;
+ if (m_nPedState == PED_FALL || m_nPedState == PED_GETUP) {
+ if (!IsPedHeadAbovePos(-0.3f)) {
+ if (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL))
+ dieAnim = ANIM_FLOOR_HIT_F;
+ else
+ dieAnim = ANIM_FLOOR_HIT;
+ dieDelta *= 2.0f;
+ dieSpeed = 0.5f;
+ detectDieAnim = false;
+ } else if (m_nPedState == PED_FALL) {
+ dieAnim = NUM_ANIMS;
+ detectDieAnim = false;
+ }
+ }
+ if (detectDieAnim) {
+ switch (method) {
+ case WEAPONTYPE_UNARMED:
+ if (bMeleeProof)
+ return false;
+
+ if (m_nPedState == PED_FALL) {
+ if (IsPedHeadAbovePos(-0.3f)) {
+ dieAnim = NUM_ANIMS;
+ } else {
+ if (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL))
+ dieAnim = ANIM_FLOOR_HIT_F;
+ else
+ dieAnim = ANIM_FLOOR_HIT;
+ dieDelta = dieDelta * 2.0f;
+ dieSpeed = 0.5f;
+ }
+ } else {
+ switch (direction) {
+ case 0:
+ dieAnim = ANIM_KO_SKID_FRONT;
+ break;
+ case 1:
+ dieAnim = ANIM_KO_SPIN_R;
+ break;
+ case 2:
+ dieAnim = ANIM_KO_SKID_BACK;
+ break;
+ case 3:
+ dieAnim = ANIM_KO_SPIN_L;
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ case WEAPONTYPE_BASEBALLBAT:
+ if (bMeleeProof)
+ return false;
+
+ if (m_nPedState == PED_FALL) {
+ if (IsPedHeadAbovePos(-0.3f)) {
+ dieAnim = NUM_ANIMS;
+ } else {
+ if (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FRONTAL))
+ dieAnim = ANIM_FLOOR_HIT_F;
+ else
+ dieAnim = ANIM_FLOOR_HIT;
+ dieDelta = dieDelta * 2.0f;
+ dieSpeed = 0.5f;
+ }
+ } else {
+ switch (direction) {
+ case 0:
+ dieAnim = ANIM_KO_SKID_FRONT;
+ break;
+ case 1:
+ dieAnim = ANIM_KO_SPIN_R;
+ break;
+ case 2:
+ dieAnim = ANIM_KO_SKID_BACK;
+ break;
+ case 3:
+ dieAnim = ANIM_KO_SPIN_L;
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ case WEAPONTYPE_COLT45:
+ case WEAPONTYPE_UZI:
+ case WEAPONTYPE_SHOTGUN:
+ case WEAPONTYPE_AK47:
+ case WEAPONTYPE_M16:
+ case WEAPONTYPE_SNIPERRIFLE:
+ if (bBulletProof)
+ return false;
+
+ bool dontRemoveLimb;
+ if (IsPlayer() || bNoCriticalHits)
+ dontRemoveLimb = true;
+ else {
+ switch (method) {
+ case WEAPONTYPE_SNIPERRIFLE:
+ dontRemoveLimb = false;
+ break;
+ case WEAPONTYPE_M16:
+ dontRemoveLimb = false;
+ break;
+ case WEAPONTYPE_SHOTGUN:
+ dontRemoveLimb = CGeneral::GetRandomNumber() & 7;
+ break;
+ default:
+ dontRemoveLimb = CGeneral::GetRandomNumber() & 15;
+ break;
+ }
+ }
+
+ if (dontRemoveLimb) {
+ if (method == WEAPONTYPE_SHOTGUN) {
+ switch (direction) {
+ case 0:
+ dieAnim = ANIM_KO_SKID_FRONT;
+ break;
+ case 1:
+ dieAnim = ANIM_KO_SPIN_R;
+ break;
+ case 2:
+ dieAnim = ANIM_KO_SKID_BACK;
+ break;
+ case 3:
+ dieAnim = ANIM_KO_SPIN_L;
+ break;
+ default:
+ break;
+ }
+ } else
+ dieAnim = ANIM_KO_SHOT_FRONT1;
+
+ willLinger = false;
+ } else {
+ switch (pedPiece) {
+ case PEDPIECE_TORSO:
+ willLinger = false;
+ dieAnim = ANIM_KO_SHOT_FRONT1;
+ break;
+ case PEDPIECE_MID:
+ willLinger = false;
+ dieAnim = ANIM_KO_SHOT_STOM;
+ break;
+ case PEDPIECE_LEFTARM:
+ dieAnim = ANIM_KO_SHOT_ARML;
+ RemoveBodyPart(PED_UPPERARML, direction);
+ willLinger = true;
+ break;
+ case PEDPIECE_RIGHTARM:
+ dieAnim = ANIM_KO_SHOT_ARMR;
+ RemoveBodyPart(PED_UPPERARMR, direction);
+ willLinger = true;
+ break;
+ case PEDPIECE_LEFTLEG:
+ dieAnim = ANIM_KO_SHOT_LEGL;
+ RemoveBodyPart(PED_UPPERLEGL, direction);
+ willLinger = true;
+ break;
+ case PEDPIECE_RIGHTLEG:
+ dieAnim = ANIM_KO_SHOT_LEGR;
+ RemoveBodyPart(PED_UPPERLEGR, direction);
+ willLinger = true;
+ break;
+ case PEDPIECE_HEAD:
+ dieAnim = ANIM_KO_SHOT_FACE;
+ RemoveBodyPart(PED_HEAD, direction);
+ headShot = true;
+ willLinger = true;
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ case WEAPONTYPE_ROCKETLAUNCHER:
+ case WEAPONTYPE_GRENADE:
+ case WEAPONTYPE_EXPLOSION:
+ if (bExplosionProof)
+ return false;
+
+ if (CGame::nastyGame && !IsPlayer() && !bInVehicle &&
+ 1.0f + healthImpact > m_fArmour + m_fHealth) {
+
+ random = CGeneral::GetRandomNumber();
+ if (random & 1)
+ RemoveBodyPart(PED_UPPERARML, direction);
+ if (random & 2)
+ RemoveBodyPart(PED_UPPERLEGR, direction);
+ if (random & 4)
+ RemoveBodyPart(PED_HEAD, direction);
+ if (random & 8)
+ RemoveBodyPart(PED_UPPERARMR, direction);
+ if (random & 0x10)
+ RemoveBodyPart(PED_UPPERLEGL, direction);
+ if (bBodyPartJustCameOff)
+ willLinger = true;
+ }
+ // fall through
+ case WEAPONTYPE_MOLOTOV:
+ if (bExplosionProof)
+ return false;
+
+ switch (direction) {
+ case 0:
+ dieAnim = ANIM_KO_SKID_FRONT;
+ break;
+ case 1:
+ dieAnim = ANIM_KO_SPIN_R;
+ break;
+ case 2:
+ dieAnim = ANIM_KO_SKID_BACK;
+ break;
+ case 3:
+ dieAnim = ANIM_KO_SPIN_L;
+ break;
+ default:
+ break;
+ }
+ break;
+ case WEAPONTYPE_FLAMETHROWER:
+ if (bFireProof)
+ return false;
+
+ dieAnim = ANIM_KO_SHOT_FRONT1;
+ break;
+ case WEAPONTYPE_RAMMEDBYCAR:
+ case WEAPONTYPE_RUNOVERBYCAR:
+ if (bCollisionProof)
+ return false;
+
+ random = CGeneral::GetRandomNumber() & 3;
+ switch (random) {
+ case 0:
+ if ((pedPiece != PEDPIECE_LEFTARM || random <= 1)
+ && (pedPiece != PEDPIECE_MID || random != 1)) {
+ if (pedPiece == PEDPIECE_RIGHTARM && random > 1
+ || pedPiece == PEDPIECE_MID && random == 2)
+
+ dieAnim = ANIM_KO_SPIN_L;
+ else
+ dieAnim = ANIM_KO_SKID_FRONT;
+ } else
+ dieAnim = ANIM_KO_SPIN_R;
+
+ break;
+ case 1:
+ if (m_nPedState == PED_DIVE_AWAY)
+ dieAnim = ANIM_KD_LEFT;
+ else
+ dieAnim = ANIM_KO_SPIN_R;
+ break;
+ case 2:
+ if ((pedPiece != PEDPIECE_LEFTARM || random <= 1)
+ && (pedPiece != PEDPIECE_MID || random != 1)) {
+ if ((pedPiece != PEDPIECE_RIGHTARM || random <= 1)
+ && (pedPiece != PEDPIECE_MID || random != 2)) {
+ dieAnim = ANIM_KO_SKID_BACK;
+ } else {
+ dieAnim = ANIM_KD_RIGHT;
+ }
+ } else
+ dieAnim = ANIM_KD_LEFT;
+ break;
+ case 3:
+ if (m_nPedState == PED_DIVE_AWAY)
+ dieAnim = ANIM_KD_RIGHT;
+ else
+ dieAnim = ANIM_KO_SPIN_L;
+ break;
+ default:
+ break;
+ }
+ if (damagedBy) {
+ CVehicle *vehicle = (CVehicle*)damagedBy;
+ if (method == WEAPONTYPE_RAMMEDBYCAR) {
+ float vehSpeed = vehicle->m_vecMoveSpeed.Magnitude();
+ dieDelta = 8.0f * vehSpeed + 4.0f;
+ } else {
+ float vehSpeed = vehicle->m_vecMoveSpeed.Magnitude();
+ dieDelta = 12.0f * vehSpeed + 4.0f;
+ dieSpeed = 16.0f * vehSpeed + 1.0f;
+ }
+ }
+ break;
+ case WEAPONTYPE_DROWNING:
+ dieAnim = ANIM_DROWN;
+ break;
+ case WEAPONTYPE_FALL:
+ if (bCollisionProof)
+ return false;
+
+ switch (direction) {
+ case 0:
+ dieAnim = ANIM_KO_SKID_FRONT;
+ break;
+ case 1:
+ dieAnim = ANIM_KO_SPIN_R;
+ break;
+ case 2:
+ dieAnim = ANIM_KO_SKID_BACK;
+ break;
+ case 3:
+ dieAnim = ANIM_KO_SPIN_L;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (m_fArmour != 0.0f && method != WEAPONTYPE_DROWNING) {
+ if (player == this)
+ CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastArmourLoss = CTimer::GetTimeInMilliseconds();
+
+ if (healthImpact < m_fArmour) {
+ m_fArmour = m_fArmour - healthImpact;
+ healthImpact = 0.0f;
+ } else {
+ healthImpact = healthImpact - m_fArmour;
+ m_fArmour = 0.0f;
+ }
+ }
+
+ if (healthImpact != 0.0f) {
+ if (player == this)
+ CWorld::Players[CWorld::PlayerInFocus].m_nTimeLastHealthLoss = CTimer::GetTimeInMilliseconds();
+
+ m_lastWepDam = method;
+ }
+
+ if (m_fHealth - healthImpact >= 1.0f && !willLinger) {
+ m_fHealth -= healthImpact;
+ return false;
+ }
+
+ if (bInVehicle) {
+ if (method != WEAPONTYPE_DROWNING) {
+#ifdef VC_PED_PORTS
+ if (m_pMyVehicle) {
+ if (m_pMyVehicle->IsCar() && m_pMyVehicle->pDriver == this) {
+ if (m_pMyVehicle->GetStatus() == STATUS_SIMPLE) {
+ m_pMyVehicle->SetStatus(STATUS_PHYSICS);
+ CCarCtrl::SwitchVehicleToRealPhysics(m_pMyVehicle);
+ }
+ m_pMyVehicle->AutoPilot.m_nCarMission = MISSION_NONE;
+ m_pMyVehicle->AutoPilot.m_nCruiseSpeed = 0;
+ m_pMyVehicle->AutoPilot.m_nTempAction = TEMPACT_HANDBRAKESTRAIGHT;
+ m_pMyVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 2000;
+ }
+ if (m_pMyVehicle->CanPedExitCar()) {
+ SetObjective(OBJECTIVE_LEAVE_CAR_AND_DIE, m_pMyVehicle);
+ } else {
+ m_fHealth = 0.0f;
+ if (m_pMyVehicle && m_pMyVehicle->pDriver == this) {
+ SetRadioStation();
+ m_pMyVehicle->SetStatus(STATUS_ABANDONED);
+ }
+ SetDie(dieAnim, dieDelta, dieSpeed);
+ /*
+ if (damagedBy == FindPlayerPed() && damagedBy != this) {
+ // PlayerInfo stuff
+ }
+ */
+ }
+ for (int i = 0; i < ARRAY_SIZE(m_pMyVehicle->pPassengers); i++) {
+ CPed* passenger = m_pMyVehicle->pPassengers[i];
+ if (passenger && passenger != this && damagedBy)
+ passenger->ReactToAttack(damagedBy);
+ }
+
+ CPed *driverOfVeh = m_pMyVehicle->pDriver;
+ if (driverOfVeh && driverOfVeh != this && damagedBy)
+ driverOfVeh->ReactToAttack(damagedBy);
+
+ if (damagedBy == FindPlayerPed() || damagedBy && damagedBy == FindPlayerVehicle()) {
+ CDarkel::RegisterKillByPlayer(this, method, headShot);
+ m_threatEntity = FindPlayerPed();
+ } else {
+ CDarkel::RegisterKillNotByPlayer(this, method);
+ }
+ }
+#endif
+ m_fHealth = 1.0f;
+ return false;
+ }
+ m_fHealth = 0.0f;
+ if (player == this)
+ m_pMyVehicle->SetStatus(STATUS_PLAYER_DISABLED);
+
+ SetDie(NUM_ANIMS, 4.0f, 0.0f);
+ return true;
+ } else {
+ m_fHealth = 0.0f;
+ SetDie(dieAnim, dieDelta, dieSpeed);
+
+ if (damagedBy == player || damagedBy && damagedBy == FindPlayerVehicle()) {
+
+ // There are PlayerInfo stuff here in VC
+ CDarkel::RegisterKillByPlayer(this, method, headShot);
+ m_threatEntity = player;
+ } else {
+ CDarkel::RegisterKillNotByPlayer(this, method);
+ }
+ if (method == WEAPONTYPE_DROWNING)
+ bIsInTheAir = false;
+
+ return true;
+ }
+}
+
+static RwObject*
+SetPedAtomicVisibilityCB(RwObject* object, void* data)
+{
+ if (data == nil)
+ RpAtomicSetFlags((RpAtomic*)object, 0);
+ return object;
+}
+
+static RwFrame*
+RecurseFrameChildrenVisibilityCB(RwFrame* frame, void* data)
+{
+ RwFrameForAllObjects(frame, SetPedAtomicVisibilityCB, data);
+ RwFrameForAllChildren(frame, RecurseFrameChildrenVisibilityCB, nil);
+ return frame;
+}
+
+static RwObject*
+CloneAtomicToFrameCB(RwObject *frame, void *data)
+{
+ RpAtomic *newAtomic = RpAtomicClone((RpAtomic*)frame);
+ RpAtomicSetFrame(newAtomic, (RwFrame*)data);
+ RpClumpAddAtomic(flyingClumpTemp, newAtomic);
+ CVisibilityPlugins::SetAtomicRenderCallback(newAtomic, nil);
+ return frame;
+}
+
+static RwFrame*
+RecurseFrameChildrenToCloneCB(RwFrame *frame, void *data)
+{
+ RwFrame *newFrame = RwFrameCreate();
+ RwFrameAddChild((RwFrame*)data, newFrame);
+ RwFrameTransform(newFrame, RwFrameGetMatrix(frame), rwCOMBINEREPLACE);
+ RwFrameForAllObjects(frame, CloneAtomicToFrameCB, newFrame);
+ RwFrameForAllChildren(frame, RecurseFrameChildrenToCloneCB, newFrame);
+ return newFrame;
+}
+
+void
+CPed::RemoveBodyPart(PedNode nodeId, int8 direction)
+{
+ RwFrame *frame;
+ CVector pos;
+
+ frame = m_pFrames[nodeId]->frame;
+ if (frame) {
+ if (CGame::nastyGame) {
+#ifdef PED_SKIN
+ if(!IsClumpSkinned(GetClump()))
+#endif
+ {
+#ifdef DEBUGMENU
+ if (bPopHeadsOnHeadshot || nodeId != PED_HEAD)
+#else
+ if (nodeId != PED_HEAD)
+#endif
+ SpawnFlyingComponent(nodeId, direction);
+
+ RecurseFrameChildrenVisibilityCB(frame, nil);
+ }
+ pos.x = 0.0f;
+ pos.y = 0.0f;
+ pos.z = 0.0f;
+ TransformToNode(pos, PED_HEAD);
+
+ if (CEntity::GetIsOnScreen()) {
+ CParticle::AddParticle(PARTICLE_TEST, pos,
+ CVector(0.0f, 0.0f, 0.0f),
+ nil, 0.1f, 0, 0, 0, 0);
+
+ for (int i = 0; i < 16; i++) {
+ CParticle::AddParticle(PARTICLE_BLOOD_SMALL,
+ pos,
+ CVector(0.0f, 0.0f, 0.03f),
+ nil, 0.0f, 0, 0, 0, 0);
+ }
+ }
+ bBodyPartJustCameOff = true;
+ m_bodyPartBleeding = nodeId;
+ }
+ } else {
+ printf("Trying to remove ped component");
+ }
+}
+
+CObject*
+CPed::SpawnFlyingComponent(int pedNode, int8 direction)
+{
+ if (CObject::nNoTempObjects >= NUMTEMPOBJECTS)
+ return nil;
+
+#ifdef PED_SKIN
+ assert(!IsClumpSkinned(GetClump()));
+#endif
+
+ CObject *obj = new CObject();
+ if (!obj)
+ return nil;
+
+ RwFrame *frame = RwFrameCreate();
+ RpClump *clump = RpClumpCreate();
+ RpClumpSetFrame(clump, frame);
+ RwMatrix *matrix = RwFrameGetLTM(m_pFrames[pedNode]->frame);
+ *RwFrameGetMatrix(frame) = *matrix;
+
+ flyingClumpTemp = clump;
+ RwFrameForAllObjects(m_pFrames[pedNode]->frame, CloneAtomicToFrameCB, frame);
+ RwFrameForAllChildren(m_pFrames[pedNode]->frame, RecurseFrameChildrenToCloneCB, frame);
+ flyingClumpTemp = nil;
+ switch (pedNode) {
+ case PED_HEAD:
+ // So popping head would have wheel collision. They disabled it anyway
+ obj->SetModelIndexNoCreate(MI_CAR_WHEEL);
+ break;
+ case PED_UPPERARML:
+ case PED_UPPERARMR:
+ obj->SetModelIndexNoCreate(MI_BODYPARTB);
+ obj->SetCenterOfMass(0.25f, 0.0f, 0.0f);
+ break;
+ case PED_UPPERLEGL:
+ case PED_UPPERLEGR:
+ obj->SetModelIndexNoCreate(MI_BODYPARTA);
+ obj->SetCenterOfMass(0.4f, 0.0f, 0.0f);
+ break;
+ default:
+ break;
+ }
+ obj->RefModelInfo(GetModelIndex());
+ obj->AttachToRwObject((RwObject*)clump);
+ obj->m_fMass = 15.0f;
+ obj->m_fTurnMass = 5.0f;
+ obj->m_fAirResistance = 0.99f;
+ obj->m_fElasticity = 0.03f;
+ obj->m_fBuoyancy = m_fMass*GRAVITY/0.75f;
+ obj->ObjectCreatedBy = TEMP_OBJECT;
+ obj->SetIsStatic(false);
+ obj->bIsPickup = false;
+ obj->m_nSpecialCollisionResponseCases = COLLRESPONSE_SMALLBOX;
+
+ // life time - the more objects the are, the shorter this one will live
+ CObject::nNoTempObjects++;
+ if (CObject::nNoTempObjects > 20)
+ obj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 12000;
+ else if (CObject::nNoTempObjects > 10)
+ obj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 30000;
+ else
+ obj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 60000;
+
+ CVector localForcePos, forceDir;
+
+ if (direction == 2) {
+ obj->m_vecMoveSpeed = 0.03f * GetForward();
+ obj->m_vecMoveSpeed.z = (CGeneral::GetRandomNumber() & 0x3F) * 0.001f;
+ obj->m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);
+ localForcePos = CVector(0.0f, 0.0f, 0.0f);
+ forceDir = GetForward();
+ } else {
+ obj->m_vecMoveSpeed = -0.03f * GetForward();
+ obj->m_vecMoveSpeed.z = (CGeneral::GetRandomNumber() & 0x3F) * 0.001f;
+ obj->m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);
+ localForcePos = CVector(0.0f, 0.0f, 0.0f);
+ forceDir = -GetForward();
+ }
+ obj->ApplyTurnForce(forceDir, localForcePos);
+ CWorld::Add(obj);
+
+ return obj;
+}
+
+void
+CPed::ApplyHeadShot(eWeaponType weaponType, CVector pos, bool evenOnPlayer)
+{
+ CVector pos2 = CVector(
+ pos.x,
+ pos.y,
+ pos.z + 0.1f
+ );
+
+ if (!IsPlayer() || evenOnPlayer) {
+ ++CStats::HeadsPopped;
+
+ // BUG: This condition will always return true. Even fixing it won't work, because these states are unused.
+ // if (m_nPedState != PED_PASSENGER || m_nPedState != PED_TAXI_PASSENGER) {
+ SetDie(ANIM_KO_SHOT_FRONT1, 4.0f, 0.0f);
+ // }
+
+ bBodyPartJustCameOff = true;
+ m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 150;
+
+ CParticle::AddParticle(PARTICLE_TEST, pos2,
+ CVector(0.0f, 0.0f, 0.0f), nil, 0.2f, 0, 0, 0, 0);
+
+ if (CEntity::GetIsOnScreen()) {
+ for(int i=0; i < 32; i++) {
+ CParticle::AddParticle(PARTICLE_BLOOD_SMALL,
+ pos2, CVector(0.0f, 0.0f, 0.03f),
+ nil, 0.0f, 0, 0, 0, 0);
+ }
+
+ for (int i = 0; i < 16; i++) {
+ CParticle::AddParticle(PARTICLE_DEBRIS2,
+ pos2,
+ CVector(0.0f, 0.0f, 0.01f),
+ nil, 0.0f, 0, 0, 0, 0);
+ }
+ }
+ }
+}
+
+uint8
+CPed::DoesLOSBulletHitPed(CColPoint &colPoint)
+{
+#ifdef FIX_BUGS
+ return 1;
+#else
+ uint8 retVal = 2;
+
+ float headZ = GetNodePosition(PED_HEAD).z;
+
+ if (m_nPedState == PED_FALL)
+ retVal = 1;
+
+ float colZ = colPoint.point.z;
+ if (colZ < headZ)
+ retVal = 1;
+
+ if (headZ + 0.2f <= colZ)
+ retVal = 0;
+
+ return retVal;
+#endif
+}
+
+bool
+CPed::IsPedHeadAbovePos(float zOffset)
+{
+ return zOffset + GetPosition().z < GetNodePosition(PED_HEAD).z;
+}
+
+bool
+CPed::PlacePedOnDryLand(void)
+{
+ float waterLevel = 0.0f;
+ CEntity *foundEnt = nil;
+ CColPoint foundCol;
+ float foundColZ;
+
+ CWaterLevel::GetWaterLevelNoWaves(GetPosition().x, GetPosition().y, GetPosition().z, &waterLevel);
+
+ CVector potentialGround = GetPosition();
+ potentialGround.z = waterLevel;
+
+ if (!CWorld::TestSphereAgainstWorld(potentialGround, 5.0f, nil, true, false, false, false, false, false))
+ return false;
+
+ CVector potentialGroundDist = gaTempSphereColPoints[0].point - GetPosition();
+ potentialGroundDist.z = 0.0f;
+ potentialGroundDist.Normalise();
+
+ CVector posToCheck = 0.5f * potentialGroundDist + gaTempSphereColPoints[0].point;
+ posToCheck.z = 3.0f + waterLevel;
+
+ if (CWorld::ProcessVerticalLine(posToCheck, waterLevel - 1.0f, foundCol, foundEnt, true, true, false, true, false, false, nil)) {
+ foundColZ = foundCol.point.z;
+ if (foundColZ >= waterLevel) {
+ posToCheck.z = 0.8f + foundColZ;
+ SetPosition(posToCheck);
+ bIsStanding = true;
+ bWasStanding = true;
+ return true;
+ }
+ }
+
+ posToCheck = 5.0f * potentialGroundDist + GetPosition();
+ posToCheck.z = 3.0f + waterLevel;
+
+ if (!CWorld::ProcessVerticalLine(posToCheck, waterLevel - 1.0f, foundCol, foundEnt, true, true, false, true, false, false, nil))
+ return false;
+
+ foundColZ = foundCol.point.z;
+ if (foundColZ < waterLevel)
+ return false;
+
+ posToCheck.z = 0.8f + foundColZ;
+ SetPosition(posToCheck);
+ bIsStanding = true;
+ bWasStanding = true;
+ return true;
+}
+
+void
+CPed::CollideWithPed(CPed *collideWith)
+{
+ CAnimBlendAssociation *animAssoc;
+ AnimationId animToPlay;
+
+ bool weAreMissionChar = CharCreatedBy == MISSION_CHAR;
+ bool heIsMissionChar = collideWith->CharCreatedBy == MISSION_CHAR;
+ CVector posDiff = collideWith->GetPosition() - GetPosition();
+ int waitTime = 0;
+
+ if (weAreMissionChar || !collideWith->IsPlayer() || collideWith->m_nPedState != PED_MAKE_CALL) {
+ bool weDontLookToHim = DotProduct(posDiff, GetForward()) > 0.0f;
+ bool heLooksToUs = DotProduct(posDiff, collideWith->GetForward()) < 0.0f;
+
+ if (m_nMoveState != PEDMOVE_NONE && m_nMoveState != PEDMOVE_STILL) {
+
+ if ((!IsPlayer() || ((CPlayerPed*)this)->m_fMoveSpeed <= 1.8f)
+ && (IsPlayer() || heIsMissionChar && weAreMissionChar || m_nMoveState != PEDMOVE_RUN && m_nMoveState != PEDMOVE_SPRINT
+#ifdef VC_PED_PORTS
+ || m_objective == OBJECTIVE_FOLLOW_CHAR_IN_FORMATION && m_pedInObjective == collideWith
+ || collideWith->m_objective == OBJECTIVE_FOLLOW_CHAR_IN_FORMATION && collideWith->m_pedInObjective == this
+#endif
+ )) {
+
+ if (m_objective != OBJECTIVE_FOLLOW_CHAR_IN_FORMATION && m_objective != OBJECTIVE_GOTO_CHAR_ON_FOOT) {
+
+ if (CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) {
+
+ if (heIsMissionChar || !weAreMissionChar && collideWith->m_nMoveState != PEDMOVE_STILL) {
+
+ if (weAreMissionChar && (m_nPedState == PED_SEEK_POS || m_nPedState == PED_SEEK_ENTITY)) {
+
+ if (collideWith->m_nMoveState != PEDMOVE_STILL
+ && (!collideWith->IsPlayer() || collideWith->IsPlayer() && CPad::GetPad(0)->ArePlayerControlsDisabled())) {
+ float seekPosDist = (GetPosition() - m_vecSeekPos).MagnitudeSqr2D();
+ float heAndSeekPosDist = (collideWith->GetPosition() - m_vecSeekPos).MagnitudeSqr2D();
+
+ if (seekPosDist <= heAndSeekPosDist) {
+ waitTime = 1000;
+ collideWith->SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, &waitTime);
+ collideWith->m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + waitTime;
+ } else {
+ waitTime = 500;
+ SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, &waitTime);
+ m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + waitTime;
+ }
+ } else if (collideWith->m_nMoveState == PEDMOVE_STILL) {
+ SetDirectionToWalkAroundObject(collideWith);
+ }
+ } else {
+ if (weAreMissionChar || m_pedStats->m_fear <= 100 - collideWith->m_pedStats->m_temper
+ || (collideWith->IsPlayer() || collideWith->m_nMoveState == PEDMOVE_NONE || collideWith->m_nMoveState == PEDMOVE_STILL) &&
+ (!collideWith->IsPlayer() || ((CPlayerPed*)collideWith)->m_fMoveSpeed <= 1.0f)) {
+ SetDirectionToWalkAroundObject(collideWith);
+ if (!weAreMissionChar)
+ Say(SOUND_PED_CHAT);
+ } else {
+ SetEvasiveStep(collideWith, 2);
+ }
+ }
+ } else {
+ if (m_pedStats->m_temper <= m_pedStats->m_fear
+ || GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED
+ || weAreMissionChar
+ || collideWith->m_nPedType == PEDTYPE_CIVFEMALE
+ || collideWith->m_nPedType == m_nPedType
+ || collideWith->GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED) {
+ SetDirectionToWalkAroundObject(collideWith);
+ Say(SOUND_PED_CHAT);
+ } else {
+ TurnBody();
+ SetAttack(collideWith);
+#ifdef VC_PED_PORTS
+ m_fRotationCur = 0.3f + m_fRotationCur;
+ m_fRotationDest = m_fRotationCur;
+#endif
+ }
+ m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(250, 450);
+ }
+ }
+ } else {
+#ifdef VC_PED_PORTS
+ if (m_pedInObjective && (collideWith == m_pedInObjective || collideWith->m_pedInObjective == m_pedInObjective) && CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) {
+#else
+ if (m_pedInObjective && collideWith == m_pedInObjective && CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) {
+#endif
+ if (heLooksToUs) {
+ SetEvasiveStep(collideWith, 1);
+ m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 3000;
+ }
+ } else if (weDontLookToHim && IsPedInControl()) {
+
+ if (m_pedStats != collideWith->m_pedStats) {
+
+ if (collideWith->m_pedStats->m_fear <= 100 - m_pedStats->m_temper
+#ifdef VC_PED_PORTS
+ || collideWith->IsPlayer() || CTimer::GetTimeInMilliseconds() < m_nPedStateTimer
+#endif
+ ) {
+
+ if (collideWith->IsPlayer()) {
+ // He's on our right side
+ if (DotProduct(posDiff,GetRight()) <= 0.0f)
+ m_fRotationCur -= m_headingRate;
+ else
+ m_fRotationCur += m_headingRate;
+ } else {
+ // He's on our right side
+ if (DotProduct(posDiff, collideWith->GetRight()) <= 0.0f)
+ collideWith->m_fRotationCur -= collideWith->m_headingRate;
+ else
+ collideWith->m_fRotationCur += collideWith->m_headingRate;
+ }
+ } else {
+ SetLookFlag(collideWith, false);
+ TurnBody();
+ animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT_PPUNCH, 8.0f);
+ animAssoc->flags |= ASSOC_FADEOUTWHENDONE;
+#ifdef VC_PED_PORTS
+ m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 2000;
+#endif
+ if (!heIsMissionChar) {
+ CVector2D posDiff2D(posDiff);
+ int direction = collideWith->GetLocalDirection(posDiff2D);
+ collideWith->StartFightDefend(direction, HITLEVEL_HIGH, 5);
+ }
+ }
+ }
+ }
+ }
+ } else if (collideWith->m_pedStats->m_defendWeakness <= 1.5f || heIsMissionChar
+#ifdef VC_PED_PORTS
+ || m_pedStats->m_defendWeakness <= collideWith->m_pedStats->m_defendWeakness
+#endif
+ ) {
+ // He looks us and we're not at his right side
+ if (heLooksToUs && DotProduct(posDiff,collideWith->GetRight()) > 0.0f) {
+ CVector moveForce = GetRight();
+ moveForce.z += 0.1f;
+ ApplyMoveForce(moveForce);
+ if (collideWith->m_nMoveState != PEDMOVE_RUN && collideWith->m_nMoveState != PEDMOVE_SPRINT)
+ animToPlay = ANIM_HIT_LEFT;
+ else
+ animToPlay = ANIM_SHOT_LEFT_PARTIAL;
+ } else if (heLooksToUs) {
+ CVector moveForce = GetRight() * -1.0f;
+ moveForce.z += 0.1f;
+ ApplyMoveForce(moveForce);
+ if (collideWith->m_nMoveState != PEDMOVE_RUN && collideWith->m_nMoveState != PEDMOVE_SPRINT)
+ animToPlay = ANIM_HIT_RIGHT;
+ else
+ animToPlay = ANIM_SHOT_RIGHT_PARTIAL;
+ } else {
+ if (collideWith->m_nMoveState != PEDMOVE_RUN && collideWith->m_nMoveState != PEDMOVE_SPRINT)
+ animToPlay = ANIM_HIT_BACK;
+ else
+ animToPlay = ANIM_SHOT_BACK_PARTIAL;
+ }
+
+ if (collideWith->IsPedInControl() && CTimer::GetTimeInMilliseconds() > collideWith->m_nPedStateTimer) {
+ animAssoc = CAnimManager::BlendAnimation(collideWith->GetClump(), ASSOCGRP_STD, animToPlay, 8.0f);
+ animAssoc->flags |= ASSOC_FADEOUTWHENDONE;
+ collideWith->m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 1000;
+ if (m_nPedState == PED_ATTACK)
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_FIGHT_PUNCH_39, 0.0f);
+ }
+ } else {
+ // We're at his right side
+ if (DotProduct(posDiff, collideWith->GetRight()) <= 0.0f) {
+ CVector moveForce = GetRight() * -1.0f;
+ moveForce.z += 0.1f;
+ ApplyMoveForce(moveForce);
+ if (heLooksToUs)
+ animToPlay = ANIM_KO_SPIN_L;
+ else
+ animToPlay = ANIM_KD_RIGHT;
+ } else {
+ CVector moveForce = GetRight();
+ moveForce.z += 0.1f;
+ ApplyMoveForce(moveForce);
+ if (heLooksToUs)
+ animToPlay = ANIM_KO_SPIN_R;
+ else
+ animToPlay = ANIM_KD_LEFT;
+ }
+
+ if (m_nPedState == PED_ATTACK && collideWith->IsPedInControl())
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_FIGHT_PUNCH_39, 0.0f);
+
+ collideWith->SetFall(3000, animToPlay, 0);
+ }
+ } else {
+ if (!IsPedInControl())
+ return;
+
+ if (collideWith->m_nMoveState == PEDMOVE_NONE || collideWith->m_nMoveState == PEDMOVE_STILL)
+ return;
+
+ if (m_nPedType != collideWith->m_nPedType || m_nPedType == PEDTYPE_CIVMALE || m_nPedType == PEDTYPE_CIVFEMALE) {
+
+ if (!weAreMissionChar && heLooksToUs && m_pedStats->m_fear > 100 - collideWith->m_pedStats->m_temper) {
+
+ if (CGeneral::GetRandomNumber() & 1 && CTimer::GetTimeInMilliseconds() < m_nPedStateTimer){
+ SetEvasiveStep(collideWith, 2);
+ m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 3000;
+ } else if (collideWith->m_nMoveState > PEDMOVE_WALK) {
+ waitTime = 2000;
+ SetWaitState(WAITSTATE_PLAYANIM_DUCK, &waitTime);
+ }
+ }
+ } else if (heLooksToUs
+ && collideWith->m_nPedState != PED_STEP_AWAY
+ && m_nPedState != PED_STEP_AWAY
+ && CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) {
+
+ SetEvasiveStep(collideWith, 1);
+ m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 3000;
+ }
+ }
+
+ if (IsPlayer()) {
+ SetLookFlag(collideWith, true);
+ SetLookTimer(800);
+ }
+ } else {
+ bool isRunning = m_nMoveState == PEDMOVE_RUN || m_nMoveState == PEDMOVE_SPRINT;
+ SetFindPathAndFlee(collideWith, 5000, !isRunning);
+ }
+}
+
+void
+CPed::KillPedWithCar(CVehicle *car, float impulse)
+{
+ CVehicleModelInfo *vehModel;
+ CColModel *vehColModel;
+ uint8 damageDir;
+ PedNode nodeToDamage;
+ eWeaponType killMethod;
+
+ if (m_nPedState == PED_FALL || m_nPedState == PED_DIE) {
+ if (!this->m_pCollidingEntity || car->GetStatus() == STATUS_PLAYER)
+ this->m_pCollidingEntity = car;
+ return;
+ }
+
+ if (m_nPedState == PED_DEAD)
+ return;
+
+ if (m_pCurSurface) {
+ if (m_pCurSurface->IsVehicle() && (((CVehicle*)m_pCurSurface)->m_vehType == VEHICLE_TYPE_BOAT || IsPlayer()))
+ return;
+ }
+
+ CVector distVec = GetPosition() - car->GetPosition();
+
+ if ((impulse > 12.0f || car->GetModelIndex() == MI_TRAIN) && !IsPlayer()) {
+ nodeToDamage = PED_TORSO;
+ killMethod = WEAPONTYPE_RAMMEDBYCAR;
+ uint8 randVal = CGeneral::GetRandomNumber() & 3;
+
+ if (car == FindPlayerVehicle()) {
+ float carSpeed = car->m_vecMoveSpeed.Magnitude();
+ uint8 shakeFreq;
+ if (100.0f * carSpeed * 2000.0f / car->m_fMass + 80.0f <= 250.0f) {
+ shakeFreq = 100.0f * carSpeed * 2000.0f / car->m_fMass + 80.0f;
+ } else {
+ shakeFreq = 250.0f;
+ }
+ CPad::GetPad(0)->StartShake(40000 / shakeFreq, shakeFreq);
+ }
+ bIsStanding = false;
+ damageDir = GetLocalDirection(-m_vecMoveSpeed);
+ vehModel = (CVehicleModelInfo *)CModelInfo::GetModelInfo(car->GetModelIndex());
+ vehColModel = vehModel->GetColModel();
+ float carRightAndDistDotProd = DotProduct(distVec, car->GetRight());
+
+ if (car->GetModelIndex() == MI_TRAIN) {
+ killMethod = WEAPONTYPE_RUNOVERBYCAR;
+ nodeToDamage = PED_HEAD;
+ m_vecMoveSpeed = 0.9f * car->m_vecMoveSpeed;
+ m_vecMoveSpeed.z = 0.0f;
+ if (damageDir == 1 || damageDir == 3)
+ damageDir = 2;
+ if (CGame::nastyGame)
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_SPLATTER, 0.0f);
+
+ // Car doesn't look to us
+ } else if (DotProduct(car->m_vecMoveSpeed, car->GetForward()) >= 0.0f){
+
+ if (0.99f * vehColModel->boundingBox.max.x < Abs(carRightAndDistDotProd)) {
+
+ // We're at the right of the car
+ if (carRightAndDistDotProd <= 0.0f)
+ nodeToDamage = PED_UPPERARML;
+ else
+ nodeToDamage = PED_UPPERARMR;
+
+ if (Abs(DotProduct(distVec, car->GetForward())) < 0.85f * vehColModel->boundingBox.max.y) {
+ killMethod = WEAPONTYPE_RUNOVERBYCAR;
+ m_vecMoveSpeed = 0.9f * car->m_vecMoveSpeed;
+ m_vecMoveSpeed.z = 0.0f;
+ if (damageDir == 1 || damageDir == 3)
+ damageDir = 2;
+ if (CGame::nastyGame)
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_SPLATTER, 0.0f);
+
+ }
+ } else {
+ float carFrontAndDistDotProd = DotProduct(distVec, car->GetForward());
+
+ // carFrontAndDistDotProd <= 0.0 car looks to us
+ if ((carFrontAndDistDotProd <= 0.1 || randVal == 1) && randVal != 0) {
+ killMethod = WEAPONTYPE_RUNOVERBYCAR;
+ nodeToDamage = PED_HEAD;
+ m_vecMoveSpeed = 0.9f * car->m_vecMoveSpeed;
+ m_vecMoveSpeed.z = 0.0f;
+ if (damageDir == 1 || damageDir == 3)
+ damageDir = 2;
+
+ if (CGame::nastyGame)
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_SPLATTER, 0.0f);
+
+ } else {
+ nodeToDamage = PED_MID;
+ float vehColMaxY = vehColModel->boundingBox.max.y;
+ float vehColMinY = vehColModel->boundingBox.min.y;
+ float vehColMaxZ = vehColModel->boundingBox.max.z;
+ float carFrontZ = car->GetForward().z;
+ float carHighestZ, carLength;
+
+ if (carFrontZ < -0.2f) {
+ // Highest point of car's back
+ carHighestZ = (car->GetMatrix() * CVector(0.0f, vehColMinY, vehColMaxZ)).z;
+ carLength = vehColMaxY - vehColMinY;
+
+ } else if (carFrontZ > 0.1f) {
+ // Highest point of car's front
+ carHighestZ = (car->GetMatrix() * CVector(0.0f, vehColMaxY, vehColMaxZ)).z;
+ float highestZDist = carHighestZ - GetPosition().z;
+ if (highestZDist > 0.0f) {
+ GetMatrix().GetPosition().z += 0.5f * highestZDist;
+ carHighestZ += highestZDist * 0.25f;
+ }
+ carLength = vehColMaxY;
+
+ } else {
+ // Highest point of car's front
+ carHighestZ = (car->GetMatrix() * CVector(0.0f, vehColMaxY, vehColMaxZ)).z;
+ carLength = vehColMaxY;
+ }
+
+ float pedJumpSpeedToReachHighestZ = (carHighestZ - GetPosition().z) / (carLength / car->m_vecMoveSpeed.Magnitude());
+
+ // TODO: What are we doing down here?
+ float unknown = ((CGeneral::GetRandomNumber() % 256) * 0.002 + 1.5) * pedJumpSpeedToReachHighestZ;
+
+ // After this point, distVec isn't distVec anymore.
+ distVec = car->m_vecMoveSpeed;
+ distVec.Normalise();
+ distVec *= 0.2 * unknown;
+
+ if (damageDir != 1 && damageDir != 3)
+ distVec.z += unknown;
+ else
+ distVec.z += 1.5f * unknown;
+
+ m_vecMoveSpeed = distVec;
+ damageDir += 2;
+ if (damageDir > 3)
+ damageDir = damageDir - 4;
+
+ if (car->m_vehType == VEHICLE_TYPE_CAR) {
+ CObject *bonnet = ((CAutomobile*)car)->RemoveBonnetInPedCollision();
+
+ if (bonnet) {
+ if (CGeneral::GetRandomNumber() & 1) {
+ bonnet->m_vecMoveSpeed += Multiply3x3(car->GetMatrix(), CVector(0.1f, 0.0f, 0.5f));
+ } else {
+ bonnet->m_vecMoveSpeed += Multiply3x3(car->GetMatrix(), CVector(-0.1f, 0.0f, 0.5f));
+ }
+ CVector forceDir = car->GetUp() * 10.0f;
+ bonnet->ApplyTurnForce(forceDir, car->GetForward());
+ }
+ }
+ }
+ }
+ }
+
+ if (car->pDriver) {
+ CEventList::RegisterEvent((m_nPedType == PEDTYPE_COP ? EVENT_HIT_AND_RUN_COP : EVENT_HIT_AND_RUN), EVENT_ENTITY_PED, this, car->pDriver, 1000);
+ }
+
+ ePedPieceTypes pieceToDamage;
+ switch (nodeToDamage) {
+ case PED_HEAD:
+ pieceToDamage = PEDPIECE_HEAD;
+ break;
+ case PED_UPPERARML:
+ pieceToDamage = PEDPIECE_LEFTARM;
+ break;
+ case PED_UPPERARMR:
+ pieceToDamage = PEDPIECE_RIGHTARM;
+ break;
+ default:
+ pieceToDamage = PEDPIECE_MID;
+ break;
+ }
+ InflictDamage(car, killMethod, 1000.0f, pieceToDamage, damageDir);
+
+ if (DyingOrDead()
+ && bIsPedDieAnimPlaying && !m_pCollidingEntity) {
+ m_pCollidingEntity = car;
+ }
+ if (nodeToDamage == PED_MID)
+ bKnockedUpIntoAir = true;
+ else
+ bKnockedUpIntoAir = false;
+
+ distVec.Normalise();
+
+#ifdef VC_PED_PORTS
+ distVec *= Min(car->m_fMass / 1400.0f, 1.0f);
+#endif
+ car->ApplyMoveForce(distVec * -100.0f);
+ Say(SOUND_PED_DEFEND);
+
+ } else if (m_vecDamageNormal.z < -0.8f && impulse > 3.0f
+ || impulse > 6.0f && (!IsPlayer() || impulse > 10.0f)) {
+
+ bIsStanding = false;
+ uint8 fallDirection = GetLocalDirection(-car->m_vecMoveSpeed);
+ float damage;
+ if (IsPlayer() && car->GetModelIndex() == MI_TRAIN)
+ damage = 150.0f;
+ else
+ damage = 30.0f;
+
+ InflictDamage(car, WEAPONTYPE_RAMMEDBYCAR, damage, PEDPIECE_TORSO, fallDirection);
+ SetFall(1000, (AnimationId)(fallDirection + ANIM_KO_SKID_FRONT), true);
+
+ if (OnGround() && !m_pCollidingEntity &&
+ (!IsPlayer() || bHasHitWall || car->GetModelIndex() == MI_TRAIN || m_vecDamageNormal.z < -0.8f)) {
+
+ m_pCollidingEntity = car;
+ }
+
+ bKnockedUpIntoAir = false;
+ if (car->GetModelIndex() != MI_TRAIN && !bHasHitWall) {
+ m_vecMoveSpeed = car->m_vecMoveSpeed * 0.75f;
+ }
+ m_vecMoveSpeed.z = 0.0f;
+ distVec.Normalise();
+#ifdef VC_PED_PORTS
+ distVec *= Min(car->m_fMass / 1400.0f, 1.0f);
+#endif
+ car->ApplyMoveForce(distVec * -60.0f);
+ Say(SOUND_PED_DEFEND);
+ }
+
+#ifdef VC_PED_PORTS
+ // Killing gang members with car wasn't triggering a fight, until now... Taken from VC.
+ if (IsGangMember()) {
+ CPed *driver = car->pDriver;
+ if (driver && driver->IsPlayer()
+#ifdef FIX_BUGS
+ && (CharCreatedBy != MISSION_CHAR || bRespondsToThreats) && (!m_leader || m_leader != driver)
+#endif
+ ) {
+ RegisterThreatWithGangPeds(driver);
+ }
+ }
+#endif
+} \ No newline at end of file
diff --git a/src/peds/PedStats.cpp b/src/peds/PedStats.cpp
deleted file mode 100644
index 1f7a95b4..00000000
--- a/src/peds/PedStats.cpp
+++ /dev/null
@@ -1,118 +0,0 @@
-#include "common.h"
-
-#include "General.h"
-#include "FileMgr.h"
-#include "PedStats.h"
-
-CPedStats *CPedStats::ms_apPedStats[NUM_PEDSTATS];
-
-void
-CPedStats::Initialise(void)
-{
- int i;
-
- debug("Initialising CPedStats...\n");
- for(i = 0; i < NUM_PEDSTATS; i++){
- ms_apPedStats[i] = new CPedStats;
- ms_apPedStats[i]->m_type = PEDSTAT_PLAYER;
- ms_apPedStats[i]->m_name[8] = 'R'; // WHAT?
- ms_apPedStats[i]->m_fleeDistance = 20.0f;
- ms_apPedStats[i]->m_headingChangeRate = 15.0f;
- ms_apPedStats[i]->m_fear = 50;
- ms_apPedStats[i]->m_temper = 50;
- ms_apPedStats[i]->m_lawfulness = 50;
- ms_apPedStats[i]->m_sexiness = 50;
- ms_apPedStats[i]->m_attackStrength = 1.0f;
- ms_apPedStats[i]->m_defendWeakness = 1.0f;
- ms_apPedStats[i]->m_flags = 0;
- }
- debug("Loading pedstats data...\n");
- CPedStats::LoadPedStats();
- debug("CPedStats ready\n");
-}
-
-void
-CPedStats::Shutdown(void)
-{
- int i;
- debug("Shutting down CPedStats...\n");
- for(i = 0; i < NUM_PEDSTATS; i++)
- delete ms_apPedStats[i];
- debug("CPedStats shut down\n");
-}
-
-void
-CPedStats::LoadPedStats(void)
-{
- char *buf;
- char line[256];
- char name[32];
- size_t bp, buflen;
- int lp, linelen;
- int type;
- float fleeDist, headingChangeRate, attackStrength, defendWeakness;
- int fear, temper, lawfullness, sexiness, flags;
-
-
- type = 0;
- buf = new char[16 * 1024];
-
- CFileMgr::SetDir("DATA");
- buflen = CFileMgr::LoadFile("PEDSTATS.DAT", (uint8*)buf, 16 * 1024, "r");
- CFileMgr::SetDir("");
-
- for(bp = 0; bp < buflen; ){
- // read file line by line
- for(linelen = 0; buf[bp] != '\n' && bp < buflen; bp++){
- if(buf[bp] == '\r' || buf[bp] == ',' || buf[bp] == '\t')
- line[linelen++] = ' ';
- else
- line[linelen++] = buf[bp];
- }
- bp++;
- line[linelen] = '\0';
-
- // skip white space
- for(lp = 0; line[lp] <= ' '; lp++);
-
- if(lp >= linelen || // FIX: game uses == here, but this is safer if we have empty lines
- line[lp] == '#')
- continue;
-
- sscanf(&line[lp], "%s %f %f %d %d %d %d %f %f %d",
- name,
- &fleeDist,
- &headingChangeRate,
- &fear,
- &temper,
- &lawfullness,
- &sexiness,
- &attackStrength,
- &defendWeakness,
- &flags);
- ms_apPedStats[type]->m_type = (ePedStats)type;
- strncpy(ms_apPedStats[type]->m_name, name, 24); // FIX: game uses strcpy
- ms_apPedStats[type]->m_fleeDistance = fleeDist;
- ms_apPedStats[type]->m_headingChangeRate = headingChangeRate;
- ms_apPedStats[type]->m_fear = fear;
- ms_apPedStats[type]->m_temper = temper;
- ms_apPedStats[type]->m_lawfulness = lawfullness;
- ms_apPedStats[type]->m_sexiness = sexiness;
- ms_apPedStats[type]->m_attackStrength = attackStrength;
- ms_apPedStats[type]->m_defendWeakness = defendWeakness;
- ms_apPedStats[type]->m_flags = flags;
- type++;
- }
-
- delete[] buf;
-}
-
-ePedStats
-CPedStats::GetPedStatType(char *name)
-{
- for(uint16 type = 0; type < NUM_PEDSTATS; type++)
- if(!CGeneral::faststrcmp(ms_apPedStats[type]->m_name, name))
- return (ePedStats) type;
-
- return NUM_PEDSTATS;
-}
diff --git a/src/peds/PedStats.h b/src/peds/PedStats.h
deleted file mode 100644
index df97bdb8..00000000
--- a/src/peds/PedStats.h
+++ /dev/null
@@ -1,80 +0,0 @@
-#pragma once
-
-enum ePedStats
-{
- PEDSTAT_PLAYER,
- PEDSTAT_COP,
- PEDSTAT_MEDIC,
- PEDSTAT_FIREMAN,
- PEDSTAT_GANG1,
- PEDSTAT_GANG2,
- PEDSTAT_GANG3,
- PEDSTAT_GANG4,
- PEDSTAT_GANG5,
- PEDSTAT_GANG6,
- PEDSTAT_GANG7,
- PEDSTAT_STREET_GUY,
- PEDSTAT_SUIT_GUY,
- PEDSTAT_SENSIBLE_GUY,
- PEDSTAT_GEEK_GUY,
- PEDSTAT_OLD_GUY,
- PEDSTAT_TOUGH_GUY,
- PEDSTAT_STREET_GIRL,
- PEDSTAT_SUIT_GIRL,
- PEDSTAT_SENSIBLE_GIRL,
- PEDSTAT_GEEK_GIRL,
- PEDSTAT_OLD_GIRL,
- PEDSTAT_TOUGH_GIRL,
- PEDSTAT_TRAMP_MALE,
- PEDSTAT_TRAMP_FEMALE,
- PEDSTAT_TOURIST,
- PEDSTAT_PROSTITUTE,
- PEDSTAT_CRIMINAL,
- PEDSTAT_BUSKER,
- PEDSTAT_TAXIDRIVER,
- PEDSTAT_PSYCHO,
- PEDSTAT_STEWARD,
- PEDSTAT_SPORTSFAN,
- PEDSTAT_SHOPPER,
- PEDSTAT_OLDSHOPPER,
-
- NUM_PEDSTATS
-};
-
-// flags
-enum
-{
- STAT_PUNCH_ONLY = 1,
- STAT_CAN_KNEE_HEAD = 2,
- STAT_CAN_KICK = 4,
- STAT_CAN_ROUNDHOUSE = 8,
- STAT_NO_DIVE = 0x10,
- STAT_ONE_HIT_KNOCKDOWN = 0x20,
- STAT_SHOPPING_BAGS = 0x40,
- STAT_GUN_PANIC = 0x80
-};
-
-class CPedStats
-{
-public:
- ePedStats m_type;
- char m_name[24];
- float m_fleeDistance;
- float m_headingChangeRate;
- int8 m_fear;
- int8 m_temper;
- int8 m_lawfulness;
- int8 m_sexiness;
- float m_attackStrength;
- float m_defendWeakness;
- int16 m_flags;
-
- static CPedStats *ms_apPedStats[NUM_PEDSTATS];
-
- static void Initialise(void);
- static void Shutdown(void);
- static void LoadPedStats(void);
- static ePedStats GetPedStatType(char *name);
-};
-
-VALIDATE_SIZE(CPedStats, 0x34);
diff --git a/src/peds/PedType.cpp b/src/peds/PedType.cpp
index 397cd71d..6e745bd7 100644
--- a/src/peds/PedType.cpp
+++ b/src/peds/PedType.cpp
@@ -1,9 +1,11 @@
#include "common.h"
+#include "General.h"
#include "FileMgr.h"
#include "PedType.h"
CPedType *CPedType::ms_apPedType[NUM_PEDTYPES];
+CPedStats *CPedStats::ms_apPedStats[NUM_PEDSTATS];
void
CPedType::Initialise(void)
@@ -202,3 +204,114 @@ INITSAVEBUF
*ms_apPedType[i] = ReadSaveBuf<CPedType>(buf);
VALIDATESAVEBUF(size)
}
+
+void
+CPedStats::Initialise(void)
+{
+ int i;
+
+ debug("Initialising CPedStats...\n");
+ for(i = 0; i < NUM_PEDSTATS; i++){
+ ms_apPedStats[i] = new CPedStats;
+ ms_apPedStats[i]->m_type = PEDSTAT_PLAYER;
+ ms_apPedStats[i]->m_name[8] = 'R'; // WHAT?
+ ms_apPedStats[i]->m_fleeDistance = 20.0f;
+ ms_apPedStats[i]->m_headingChangeRate = 15.0f;
+ ms_apPedStats[i]->m_fear = 50;
+ ms_apPedStats[i]->m_temper = 50;
+ ms_apPedStats[i]->m_lawfulness = 50;
+ ms_apPedStats[i]->m_sexiness = 50;
+ ms_apPedStats[i]->m_attackStrength = 1.0f;
+ ms_apPedStats[i]->m_defendWeakness = 1.0f;
+ ms_apPedStats[i]->m_flags = 0;
+ }
+ debug("Loading pedstats data...\n");
+ CPedStats::LoadPedStats();
+ debug("CPedStats ready\n");
+}
+
+void
+CPedStats::Shutdown(void)
+{
+ int i;
+ debug("Shutting down CPedStats...\n");
+ for(i = 0; i < NUM_PEDSTATS; i++)
+ delete ms_apPedStats[i];
+ debug("CPedStats shut down\n");
+}
+
+void
+CPedStats::LoadPedStats(void)
+{
+ char *buf;
+ char line[256];
+ char name[32];
+ size_t bp, buflen;
+ int lp, linelen;
+ int type;
+ float fleeDist, headingChangeRate, attackStrength, defendWeakness;
+ int fear, temper, lawfullness, sexiness, flags;
+
+
+ type = 0;
+ buf = new char[16 * 1024];
+
+ CFileMgr::SetDir("DATA");
+ buflen = CFileMgr::LoadFile("PEDSTATS.DAT", (uint8*)buf, 16 * 1024, "r");
+ CFileMgr::SetDir("");
+
+ for(bp = 0; bp < buflen; ){
+ // read file line by line
+ for(linelen = 0; buf[bp] != '\n' && bp < buflen; bp++){
+ if(buf[bp] == '\r' || buf[bp] == ',' || buf[bp] == '\t')
+ line[linelen++] = ' ';
+ else
+ line[linelen++] = buf[bp];
+ }
+ bp++;
+ line[linelen] = '\0';
+
+ // skip white space
+ for(lp = 0; line[lp] <= ' '; lp++);
+
+ if(lp >= linelen || // FIX: game uses == here, but this is safer if we have empty lines
+ line[lp] == '#')
+ continue;
+
+ sscanf(&line[lp], "%s %f %f %d %d %d %d %f %f %d",
+ name,
+ &fleeDist,
+ &headingChangeRate,
+ &fear,
+ &temper,
+ &lawfullness,
+ &sexiness,
+ &attackStrength,
+ &defendWeakness,
+ &flags);
+ ms_apPedStats[type]->m_type = (ePedStats)type;
+ strncpy(ms_apPedStats[type]->m_name, name, 24); // FIX: game uses strcpy
+ ms_apPedStats[type]->m_fleeDistance = fleeDist;
+ ms_apPedStats[type]->m_headingChangeRate = headingChangeRate;
+ ms_apPedStats[type]->m_fear = fear;
+ ms_apPedStats[type]->m_temper = temper;
+ ms_apPedStats[type]->m_lawfulness = lawfullness;
+ ms_apPedStats[type]->m_sexiness = sexiness;
+ ms_apPedStats[type]->m_attackStrength = attackStrength;
+ ms_apPedStats[type]->m_defendWeakness = defendWeakness;
+ ms_apPedStats[type]->m_flags = flags;
+ type++;
+ }
+
+ delete[] buf;
+}
+
+ePedStats
+CPedStats::GetPedStatType(char *name)
+{
+ for(uint16 type = 0; type < NUM_PEDSTATS; type++)
+ if(!CGeneral::faststrcmp(ms_apPedStats[type]->m_name, name))
+ return (ePedStats) type;
+
+ return NUM_PEDSTATS;
+}
diff --git a/src/peds/PedType.h b/src/peds/PedType.h
index 3a765da1..3e23c249 100644
--- a/src/peds/PedType.h
+++ b/src/peds/PedType.h
@@ -92,3 +92,82 @@ public:
};
VALIDATE_SIZE(CPedType, 0x20);
+
+enum ePedStats
+{
+ PEDSTAT_PLAYER,
+ PEDSTAT_COP,
+ PEDSTAT_MEDIC,
+ PEDSTAT_FIREMAN,
+ PEDSTAT_GANG1,
+ PEDSTAT_GANG2,
+ PEDSTAT_GANG3,
+ PEDSTAT_GANG4,
+ PEDSTAT_GANG5,
+ PEDSTAT_GANG6,
+ PEDSTAT_GANG7,
+ PEDSTAT_STREET_GUY,
+ PEDSTAT_SUIT_GUY,
+ PEDSTAT_SENSIBLE_GUY,
+ PEDSTAT_GEEK_GUY,
+ PEDSTAT_OLD_GUY,
+ PEDSTAT_TOUGH_GUY,
+ PEDSTAT_STREET_GIRL,
+ PEDSTAT_SUIT_GIRL,
+ PEDSTAT_SENSIBLE_GIRL,
+ PEDSTAT_GEEK_GIRL,
+ PEDSTAT_OLD_GIRL,
+ PEDSTAT_TOUGH_GIRL,
+ PEDSTAT_TRAMP_MALE,
+ PEDSTAT_TRAMP_FEMALE,
+ PEDSTAT_TOURIST,
+ PEDSTAT_PROSTITUTE,
+ PEDSTAT_CRIMINAL,
+ PEDSTAT_BUSKER,
+ PEDSTAT_TAXIDRIVER,
+ PEDSTAT_PSYCHO,
+ PEDSTAT_STEWARD,
+ PEDSTAT_SPORTSFAN,
+ PEDSTAT_SHOPPER,
+ PEDSTAT_OLDSHOPPER,
+
+ NUM_PEDSTATS
+};
+
+// flags
+enum
+{
+ STAT_PUNCH_ONLY = 1,
+ STAT_CAN_KNEE_HEAD = 2,
+ STAT_CAN_KICK = 4,
+ STAT_CAN_ROUNDHOUSE = 8,
+ STAT_NO_DIVE = 0x10,
+ STAT_ONE_HIT_KNOCKDOWN = 0x20,
+ STAT_SHOPPING_BAGS = 0x40,
+ STAT_GUN_PANIC = 0x80
+};
+
+class CPedStats
+{
+public:
+ ePedStats m_type;
+ char m_name[24];
+ float m_fleeDistance;
+ float m_headingChangeRate;
+ int8 m_fear;
+ int8 m_temper;
+ int8 m_lawfulness;
+ int8 m_sexiness;
+ float m_attackStrength;
+ float m_defendWeakness;
+ int16 m_flags;
+
+ static CPedStats *ms_apPedStats[NUM_PEDSTATS];
+
+ static void Initialise(void);
+ static void Shutdown(void);
+ static void LoadPedStats(void);
+ static ePedStats GetPedStatType(char *name);
+};
+
+VALIDATE_SIZE(CPedStats, 0x34); \ No newline at end of file