summaryrefslogtreecommitdiffstats
path: root/src/peds
diff options
context:
space:
mode:
Diffstat (limited to 'src/peds')
-rw-r--r--src/peds/Ped.cpp1492
-rw-r--r--src/peds/Ped.h40
-rw-r--r--src/peds/PedChat.cpp102
-rw-r--r--src/peds/PedIK.h1
-rw-r--r--src/peds/PlayerPed.cpp14
-rw-r--r--src/peds/PlayerPed.h3
6 files changed, 1222 insertions, 430 deletions
diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp
index 1c895551..14aa312a 100644
--- a/src/peds/Ped.cpp
+++ b/src/peds/Ped.cpp
@@ -78,8 +78,40 @@ uint16 nPlayerInComboMove;
RpClump *flyingClumpTemp;
-FightMove tFightMoves[NUM_FIGHTMOVES] = {
- // TODO(Miami)
+FightMove tFightMoves[NUM_FIGHTMOVES] =
+{
+ { NUM_STD_ANIMS, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, HITLEVEL_NULL, 0, 0 },
+ { ANIM_PUNCH_R, 0.2f, 8.f/30.f, 0.0f, 0.3f, 1.0f, HITLEVEL_HIGH, 1, 0 },
+ { ANIM_FIGHT_IDLE, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, HITLEVEL_NULL, 0, 0 },
+ { ANIM_FIGHT_SH_F, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, HITLEVEL_NULL, 0, 0 },
+ { ANIM_FIGHT_KNEE, 4.f/30.f, 0.2f, 0.0f, 0.6f, 1.0f, HITLEVEL_LOW, 2, 0 },
+ { ANIM_FIGHT_LHOOK, 8.f/30.f, 10.f/30.f, 0.0f, 0.4f, 1.0f, HITLEVEL_HIGH, 3, 0 },
+ { ANIM_FIGHT_JAB, 4.f/30.f, 0.2f, 0.0f, 0.7f, 1.0f, HITLEVEL_HIGH, 3, 0 },
+ { ANIM_FIGHT_PUNCH, 4.f/30.f, 7.f/30.f, 10.f/30.f, 0.4f, 1.0f, HITLEVEL_HIGH, 1, 0 },
+ { ANIM_FIGHT_LONGKICK, 8.f/30.f, 10.f/30.f, 0.0f, 0.5f, 1.0f, HITLEVEL_MEDIUM, 4, 0 },
+ { ANIM_FIGHT_ROUNDHOUSE, 8.f/30.f, 10.f/30.f, 0.0f, 0.6f, 1.0f, HITLEVEL_MEDIUM, 4, 0 },
+ { ANIM_FIGHT_KICK, 8.f/30.f, 10.f/30.f, 0.0f, 0.5f, 1.0f, HITLEVEL_HIGH, 2, 0 },
+ { ANIM_FIGHT_HEAD, 8.f/30.f, 10.f/30.f, 0.0f, 0.5f, 1.0f, HITLEVEL_MEDIUM, 2, 0 },
+ { ANIM_FIGHT_BKICK_L, 8.f/30.f, 10.f/30.f, 0.0f, 0.5f, 1.0f, HITLEVEL_LOW, 2, 0 },
+ { ANIM_FIGHT_BKICK_L, 8.f/30.f, 10.f/30.f, 0.0f, 0.5f, 1.0f, HITLEVEL_LOW, 2, 0 },
+ { ANIM_FIGHT_ELBOW_L, 8.f/30.f, 10.f/30.f, 0.0f, 0.5f, 1.0f, HITLEVEL_MEDIUM, 2, 0 },
+ { ANIM_FIGHT_BKICK_R, 8.f/30.f, 10.f/30.f, 0.0f, 0.5f, 1.0f, HITLEVEL_MEDIUM, 2, 0 },
+ { ANIM_FIGHT_ELBOW_R, 8.f/30.f, 10.f/30.f, 0.0f, 0.5f, 1.0f, HITLEVEL_HIGH, 2, 0 },
+ { ANIM_KICK_FLOOR, 10.f/30.f, 14.f/30.f, 0.0f, 0.4f, 1.0f, HITLEVEL_GROUND, 1, 0 },
+ { ANIM_HIT_FRONT, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, HITLEVEL_NULL, 0, 0 },
+ { ANIM_HIT_BACK, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, HITLEVEL_NULL, 0, 0 },
+ { ANIM_HIT_RIGHT, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, HITLEVEL_NULL, 0, 0 },
+ { ANIM_HIT_LEFT, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, HITLEVEL_NULL, 0, 0 },
+ { ANIM_HIT_BODYBLOW, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, HITLEVEL_NULL, 0, 0 },
+ { ANIM_HIT_CHEST, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, HITLEVEL_NULL, 0, 0 },
+ { ANIM_HIT_HEAD, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, HITLEVEL_NULL, 0, 0 },
+ { ANIM_HIT_WALK, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, HITLEVEL_NULL, 0, 0 },
+ { ANIM_FLOOR_HIT, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, HITLEVEL_NULL, 0, 0 },
+ { ANIM_HIT_BEHIND, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, HITLEVEL_NULL, 0, 0 },
+ { ANIM_WEAPON_FIRE, 4.f/30.f, 7.f/30.f, 10.f/30.f, 0.4f, 1.0f, HITLEVEL_HIGH, 1, 0 },
+ { ANIM_WEAPON_CROUCHFIRE, 4.f/30.f, 7.f/30.f, 10.f/30.f, 0.4f, 1.0f, HITLEVEL_HIGH, 1, 0 },
+ { ANIM_WEAPON_SPECIAL, 4.f / 30.f, 7.f / 30.f, 10.f / 30.f, 0.4f, 1.0f, HITLEVEL_HIGH, 1, 0 },
+ { ANIM_FIGHT2_IDLE, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, HITLEVEL_NULL, 0, 0 }
};
uint16 CPed::nThreatReactionRangeMultiplier = 1;
@@ -103,6 +135,9 @@ bool CPed::bPedCheat2;
bool CPed::bPedCheat3;
CVector2D CPed::ms_vec2DFleePosition;
+CVector vecNextPathNode;
+bool vecNextPathNodeInitialized;
+
void *CPed::operator new(size_t sz) { return CPools::GetPedPool()->New(); }
void *CPed::operator new(size_t sz, int handle) { return CPools::GetPedPool()->New(handle); }
void CPed::operator delete(void *p, size_t sz) { CPools::GetPedPool()->Delete((CPed*)p); }
@@ -113,6 +148,7 @@ bool CPed::bPopHeadsOnHeadshot = false;
bool CPed::bMakePedsRunToPhonesToReportCrimes = false;
#endif
+// --MIAMI: Done
CPed::~CPed(void)
{
CWorld::Remove(this);
@@ -124,7 +160,7 @@ CPed::~CPed(void)
if (m_pMyVehicle->pDriver == this)
m_pMyVehicle->pDriver = nil;
else {
- // FIX: Passenger counter now decreasing after removing ourself from vehicle.
+ // FIX: Passenger counter now being decreased after removing ourself from vehicle.
m_pMyVehicle->RemovePassenger(this);
}
if (m_nPedState == PED_EXIT_CAR || m_nPedState == PED_DRAG_FROM_CAR)
@@ -146,6 +182,7 @@ CPed::~CPed(void)
DMAudio.DestroyEntity(m_audioEntityId);
}
+// --MIAMI: Done
void
CPed::FlagToDestroyWhenNextProcessed(void)
{
@@ -232,6 +269,9 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
m_wepSkills = 0;
m_distanceToCountSeekDone = 1.0f;
m_acceptableHeadingOffset = 0.1f;
+ m_followPathDestPos = CVector(0.f, 0.f, 0.f);
+ m_followPathAbortDist = 0.0f;
+ m_followPathMoveState = PEDMOVE_NONE;
bRunningToPhone = false;
m_phoneId = -1;
m_lastAccident = 0;
@@ -258,11 +298,20 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
m_fLookDirection = 0.0f;
m_pCurSurface = nil;
m_wanderRangeBounds = nil;
- m_nPathNodes = 0;
- m_nCurPathNode = 0;
+
+ for (int i = 0; i < ARRAY_SIZE(m_pathNodesToGo); i++) {
+ m_pathNodesToGo[i] = nil;
+ }
+ m_nNumPathNodes = 0;
+ m_nCurPathNodeId = 0;
m_nPathDir = 0;
m_pLastPathNode = nil;
m_pNextPathNode = nil;
+ m_followPathWalkAroundEnt = nil;
+ m_followPathTargetEnt = nil;
+ m_pathNodeTimer = 0;
+ m_pCurPathNode = nil;
+
m_routeLastPoint = -1;
m_routeStartPoint = 0;
m_routePointsPassed = 0;
@@ -399,9 +448,6 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
for (int i = 0; i < ARRAY_SIZE(m_nearPeds); i++) {
m_nearPeds[i] = nil;
- if (i < ARRAY_SIZE(m_pPathNodesStates)) {
- m_pPathNodesStates[i] = nil;
- }
}
m_maxWeaponTypeAllowed = WEAPONTYPE_UNARMED;
m_currentWeapon = WEAPONTYPE_UNARMED;
@@ -417,7 +463,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
weapon.m_nTimer = 0;
}
- m_lastFightMove = FIGHTMOVE_NULL;
+ m_lastFightMove = m_lastHitState = 0;
GiveWeapon(WEAPONTYPE_UNARMED, 0, true);
m_wepAccuracy = 60;
m_lastWepDam = -1;
@@ -948,6 +994,7 @@ CPed::ClearLookFlag(void) {
}
}
+// --MIAMI: Done
bool
CPed::IsPedHeadAbovePos(float zOffset)
{
@@ -996,7 +1043,7 @@ CPed::FinishedReloadCB(CAnimBlendAssociation *reloadAssoc, void *arg)
void
CPed::FinishedAttackCB(CAnimBlendAssociation *attackAssoc, void *arg)
{
- CAnimBlendAssociation *newAnim, *reloadAnimAssoc;
+ CAnimBlendAssociation *newAnim, *reloadAnimAssoc = nil;
CPed *ped = (CPed*)arg;
CWeaponInfo *currentWeapon = CWeaponInfo::GetWeaponInfo(ped->GetWeapon()->m_eWeaponType);
@@ -1651,65 +1698,70 @@ CPed::ClearPointGunAt(void)
}
}
+// --MIAMI: Done
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;
+ AssocGroupId assocGroup;
+ if (m_pMyVehicle->IsBike()) {
+ enterAnim = ANIM_BIKE_HIT;
+ assocGroup = ((CBike*)m_pMyVehicle)->m_bikeAnimType;
+ } else {
+ if (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR) {
+ if (bWillBeQuickJacked && m_vehEnterType == CAR_DOOR_LF) {
+ enterAnim = ANIM_CAR_QJACKED;
+ } else if (m_pMyVehicle->bLowVehicle) {
+ enterAnim = ANIM_CAR_LJACKED_LHS;
+ } else {
+ enterAnim = ANIM_CAR_JACKED_LHS;
+ }
+ } else if (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR) {
+ if (m_pMyVehicle->bLowVehicle)
+ enterAnim = ANIM_CAR_LJACKED_RHS;
+ else
+ enterAnim = ANIM_CAR_JACKED_RHS;
+ } else
+ dontRunAnim = true;
+
+ assocGroup = ASSOCGRP_STD;
+ }
if (!dontRunAnim)
- m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, enterAnim);
+ m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), assocGroup, enterAnim);
m_pVehicleAnim->SetFinishCallback(PedSetDraggedOutCarCB, this);
- lineUpType = LINE_UP_TO_CAR_START;
+
+ if (m_pMyVehicle && m_pMyVehicle->IsBike()) {
+ LineUpPedWithCar(LINE_UP_TO_CAR_FALL);
+ } else {
+ LineUpPedWithCar(LINE_UP_TO_CAR_START);
+ }
+ return;
+
+ } else if (m_pVehicleAnim->animId == ANIM_BIKE_HIT) {
+ LineUpPedWithCar(LINE_UP_TO_CAR_FALL);
+
} else if (m_pVehicleAnim->currentTime <= 1.4f) {
m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
- lineUpType = LINE_UP_TO_CAR_START;
+ LineUpPedWithCar(LINE_UP_TO_CAR_START);
+
} else {
- lineUpType = LINE_UP_TO_CAR_2;
+ LineUpPedWithCar(LINE_UP_TO_CAR_2);
}
-
- LineUpPedWithCar(lineUpType);
-#ifdef VC_PED_PORTS
+
+ static float mult = 5.f;
if (m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE) {
if (m_pMyVehicle) {
- m_pMyVehicle->ProcessOpenDoor(m_vehEnterType, NUM_STD_ANIMS, m_pVehicleAnim->currentTime * 5.0f);
+ m_pMyVehicle->ProcessOpenDoor(m_vehEnterType, NUM_STD_ANIMS, m_pVehicleAnim->currentTime * mult);
}
}
-#endif
}
void
@@ -1785,6 +1837,7 @@ CPed::PedSetDraggedOutCarCB(CAnimBlendAssociation *dragAssoc, void *arg)
ped->bVehExitWillBeInstant = false;
}
+// --MIAMI: Done
CVector
CPed::GetLocalPositionToOpenCarDoor(CVehicle *veh, uint32 component, float seatPosMult)
{
@@ -1794,83 +1847,138 @@ CPed::GetLocalPositionToOpenCarDoor(CVehicle *veh, uint32 component, float seatP
float seatOffset;
vehModel = (CVehicleModelInfo *)CModelInfo::GetModelInfo(veh->GetModelIndex());
- if (veh->bIsVan && (component == CAR_DOOR_LR || component == CAR_DOOR_RR)) {
- seatOffset = 0.0f;
- vehDoorOffset = vecPedVanRearDoorAnimOffset;
+
+ if (veh->IsBike()) {
+ CBike *bike = (CBike*)veh;
+ vehDoorPos = vehModel->GetFrontSeatPosn();
+
+ if (component == CAR_WINDSCREEN) {
+ return bike->GetMatrix() * (vehDoorPos + vecPedBikeKickAnimOffset);
+ } else {
+ switch (bike->m_bikeAnimType) {
+ case ASSOCGRP_BIKE_VESPA:
+ vehDoorOffset = vecPedVespaBikeJumpRhsAnimOffset;
+ break;
+ case ASSOCGRP_BIKE_HARLEY:
+ vehDoorOffset = vecPedHarleyBikeJumpRhsAnimOffset;
+ break;
+ case ASSOCGRP_BIKE_DIRT:
+ vehDoorOffset = vecPedDirtBikeJumpRhsAnimOffset;
+ break;
+ default:
+ vehDoorOffset = vecPedStdBikeJumpRhsAnimOffset;
+ break;
+ }
+ float xOffsetFromAnim = vehDoorOffset.x + seatPosMult * bike->pHandling->fSeatOffsetDistance;
+ if (component == CAR_DOOR_LR || component == CAR_DOOR_RR) {
+ vehDoorPos = vehModel->m_positions[CAR_POS_BACKSEAT];
+ }
+
+ if (component == CAR_DOOR_LR || component == CAR_DOOR_LF)
+ xOffsetFromAnim *= -1.f;
+
+ return bike->GetMatrix() * (vehDoorPos + CVector(xOffsetFromAnim, vehDoorOffset.y, vehDoorOffset.z));
+ }
} else {
- seatOffset = veh->pHandling->fSeatOffsetDistance * seatPosMult;
- if (veh->bLowVehicle) {
- vehDoorOffset = vecPedCarDoorLoAnimOffset;
+ if (veh->bIsVan && (component == CAR_DOOR_LR || component == CAR_DOOR_RR)) {
+ seatOffset = 0.0f;
+ vehDoorOffset = vecPedVanRearDoorAnimOffset;
} else {
- vehDoorOffset = vecPedCarDoorAnimOffset;
+ 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;
+ 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_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_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;
+ 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);
+ default:
+ vehDoorPos = vehModel->GetFrontSeatPosn();
+ vehDoorOffset = CVector(0.0f, 0.0f, 0.0f);
+ }
+ return vehDoorPos - vehDoorOffset;
}
- return vehDoorPos - vehDoorOffset;
}
-// This function was mostly duplicate of GetLocalPositionToOpenCarDoor, so I've used it.
+// --MIAMI: Done
CVector
CPed::GetPositionToOpenCarDoor(CVehicle *veh, uint32 component)
{
- CVector localPos;
- CVector vehDoorPos;
-
- localPos = GetLocalPositionToOpenCarDoor(veh, component, 1.0f);
- vehDoorPos = Multiply3x3(veh->GetMatrix(), localPos) + veh->GetPosition();
+ CVector vehDoorPos = GetPositionToOpenCarDoor(veh, component, 1.0f);
/*
- // 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();
+ // Unused
+ vehDoorPosWithoutOffset = veh->GetMatrix() * localVehDoorPos;
*/
return vehDoorPos;
}
+// --MIAMI: Done
CVector
CPed::GetPositionToOpenCarDoor(CVehicle *veh, uint32 component, float offset)
{
CVector doorPos;
CMatrix vehMat(veh->GetMatrix());
+ if (veh->IsBike()) {
+ CVehicleModelInfo* vehModel = (CVehicleModelInfo*)CModelInfo::GetModelInfo(veh->GetModelIndex());
+ CVector vehDoorOffset;
+ CBike* bike = (CBike*)veh;
+ doorPos = vehModel->GetFrontSeatPosn();
+
+ if (component == CAR_WINDSCREEN) {
+ return bike->GetMatrix() * (doorPos + vecPedBikeKickAnimOffset);
+ } else {
+ switch (bike->m_bikeAnimType) {
+ case ASSOCGRP_BIKE_VESPA:
+ vehDoorOffset = vecPedVespaBikeJumpRhsAnimOffset;
+ break;
+ case ASSOCGRP_BIKE_HARLEY:
+ vehDoorOffset = vecPedHarleyBikeJumpRhsAnimOffset;
+ break;
+ case ASSOCGRP_BIKE_DIRT:
+ vehDoorOffset = vecPedDirtBikeJumpRhsAnimOffset;
+ break;
+ default:
+ vehDoorOffset = vecPedStdBikeJumpRhsAnimOffset;
+ break;
+ }
+ vehDoorOffset.x += offset * bike->pHandling->fSeatOffsetDistance;
+ if (component == CAR_DOOR_LR || component == CAR_DOOR_RR) {
+ doorPos = vehModel->m_positions[CAR_POS_BACKSEAT];
+ }
+
+ if (component == CAR_DOOR_LR || component == CAR_DOOR_LF)
+ vehDoorOffset.x *= -1.f;
+
+ CVector correctedPos;
+ bike->GetCorrectedWorldDoorPosition(correctedPos, vehDoorOffset, doorPos);
+ return correctedPos;
+ }
+ }
doorPos = Multiply3x3(vehMat, GetLocalPositionToOpenCarDoor(veh, component, offset));
return veh->GetPosition() + doorPos;
@@ -2453,21 +2561,25 @@ CPed::SortPeds(CPed **list, int min, int max)
SortPeds(list, right, max);
}
+// --MIAMI: Done
void
CPed::BuildPedLists(void)
{
- if ((CTimer::GetFrameCounter() + (m_randomSeed % 256)) % 16) {
+ if ((CTimer::GetFrameCounter() + m_randomSeed) % 16) {
for(int i = 0; i < ARRAY_SIZE(m_nearPeds); ) {
+ bool removePed = false;
if (m_nearPeds[i]) {
if (m_nearPeds[i]->IsPointerValid()) {
float distSqr = (GetPosition() - m_nearPeds[i]->GetPosition()).MagnitudeSqr2D();
- if (distSqr < 900.0f) {
- i++;
- continue;
+ if (distSqr > sq(nThreatReactionRangeMultiplier * 30.f)) {
+ removePed = true;
}
+ } else {
+ removePed = true;
}
-
+ }
+ if (removePed) {
// If we arrive here, the ped we're checking isn't "near", so we should remove it.
for (int j = i; j < ARRAY_SIZE(m_nearPeds) - 1; j++) {
m_nearPeds[j] = m_nearPeds[j + 1];
@@ -2481,10 +2593,11 @@ CPed::BuildPedLists(void)
}
} else {
CVector centre = CEntity::GetBoundCentre();
- CRect rect(centre.x - 20.0f,
- centre.y - 20.0f,
- centre.x + 20.0f,
- centre.y + 20.0f);
+ int deadsRegistered = 0;
+ CRect rect(centre.x - 20.f * nThreatReactionRangeMultiplier,
+ centre.y - 20.f * nThreatReactionRangeMultiplier,
+ centre.x + 20.f * nThreatReactionRangeMultiplier,
+ centre.y + 20.f * nThreatReactionRangeMultiplier);
int xstart = CWorld::GetSectorIndexX(rect.left);
int ystart = CWorld::GetSectorIndexY(rect.top);
int xend = CWorld::GetSectorIndexX(rect.right);
@@ -2495,9 +2608,14 @@ CPed::BuildPedLists(void)
for(int x = xstart; x <= xend; x++) {
for (CPtrNode *pedPtrNode = CWorld::GetSector(x,y)->m_lists[ENTITYLIST_PEDS].first; pedPtrNode; pedPtrNode = pedPtrNode->next) {
CPed *ped = (CPed*)pedPtrNode->item;
- if (ped != this && !ped->bInVehicle) {
- float dist = (ped->GetPosition() - GetPosition()).Magnitude2D();
- if (nThreatReactionRangeMultiplier * 30.0f > dist) {
+ if (ped != this && (!ped->bInVehicle || (ped->m_pMyVehicle && ped->m_pMyVehicle->IsBike()))) {
+
+ if (nThreatReactionRangeMultiplier * 30.0f > (ped->GetPosition() - GetPosition()).Magnitude2D()) {
+ if (ped->m_nPedState == PED_DEAD) {
+ if (deadsRegistered > 3)
+ continue;
+ deadsRegistered++;
+ }
gapTempPedList[gnNumTempPedList] = ped;
gnNumTempPedList++;
assert(gnNumTempPedList < ARRAY_SIZE(gapTempPedList));
@@ -4576,6 +4694,7 @@ CPed::ClearInvestigateEvent(void)
SetMoveState(PEDMOVE_WALK);
}
+// --MIAMI: Done
void
CPed::ClearLeader(void)
{
@@ -4837,19 +4956,15 @@ CPed::SetPointGunAt(CEntity *to)
CAnimBlendAssociation *aimAssoc;
- if (bCrouchWhenShooting && bIsDucking) {
- if (!!curWeapon->m_bCrouchFire) {
- aimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetCrouchFireAnim(curWeapon));
- }
+ if (bCrouchWhenShooting && bIsDucking && GetCrouchFireAnim(curWeapon)) {
+ aimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetCrouchFireAnim(curWeapon));
} else {
aimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_FIRE);
}
if (!aimAssoc || aimAssoc->blendDelta < 0.0f) {
- if (bCrouchWhenShooting && bIsDucking) {
- if (!!curWeapon->m_bCrouchFire) {
- aimAssoc = CAnimManager::BlendAnimation(GetClump(), curWeapon->m_AnimToPlay, GetCrouchFireAnim(curWeapon), 4.0f);
- }
+ if (bCrouchWhenShooting && bIsDucking && GetCrouchFireAnim(curWeapon)) {
+ aimAssoc = CAnimManager::BlendAnimation(GetClump(), curWeapon->m_AnimToPlay, GetCrouchFireAnim(curWeapon), 4.0f);
} else {
aimAssoc = CAnimManager::AddAnimation(GetClump(), curWeapon->m_AnimToPlay, ANIM_WEAPON_FIRE);
}
@@ -5440,6 +5555,7 @@ CPed::LoadFightData(void)
}
}
+// --MIAMI: Done
// Actually GetLocalDirectionTo(Turn/Look)
int
CPed::GetLocalDirection(const CVector2D &posOffset)
@@ -5454,32 +5570,35 @@ CPed::GetLocalDirection(const CVector2D &posOffset)
return direction;
}
+// --MIAMI: Done
bool
-CPed::FightStrike(CVector &touchedNodePos)
+CPed::FightStrike(CVector &touchedNodePos, bool unk = false)
{
CColModel *hisCol;
CVector attackDistance;
- ePedPieceTypes closestPedPiece = PEDPIECE_TORSO;
- float maxDistanceToBeBeaten;
+ float maxDistanceToBeat;
CPed *nearPed;
- int state = m_fightState;
- bool pedFound = false;
+ CVector extendedTouchPoint;
- if (state == FIGHTSTATE_JUST_ATTACKED)
- return false;
+ CWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
+ float radius = tFightMoves[m_lastFightMove].strikeRadius;
+ if (unk)
+ radius = weaponInfo->m_fRadius;
- // Pointless code
- if (state > FIGHTSTATE_NO_MOVE)
- attackDistance = touchedNodePos - m_vecHitLastPos;
+ if (m_fightState == FIGHTSTATE_JUST_ATTACKED)
+ return false;
+
+ // TODO(Miami): BreakGlassPhysically
for (int i = 0; i < m_numNearPeds; i++) {
+ int8 pedFound = 0;
nearPed = m_nearPeds[i];
- if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED)
- maxDistanceToBeBeaten = nearPed->GetBoundRadius() + tFightMoves[m_lastFightMove].strikeRadius + 0.1f;
+ if (!unk && GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED && GetWeapon()->m_eWeaponType != WEAPONTYPE_BRASSKNUCKLE)
+ maxDistanceToBeat = nearPed->GetBoundRadius() + radius + 0.1f;
else
- maxDistanceToBeBeaten = nearPed->GetBoundRadius() + tFightMoves[m_lastFightMove].strikeRadius;
+ maxDistanceToBeat = nearPed->GetBoundRadius() + radius;
- if (nearPed->bUsesCollision || nearPed->m_nPedState == PED_DEAD) {
+ if ((nearPed->bUsesCollision || nearPed->m_nPedState == PED_DEAD) && (m_pedInObjective != FindPlayerPed() || nearPed == FindPlayerPed())) {
CVector nearPedCentre;
// Have to animate a skinned clump because the initial col model is useless
@@ -5489,121 +5608,185 @@ CPed::FightStrike(CVector &touchedNodePos)
CVector potentialAttackDistance = nearPedCentre - touchedNodePos;
// He can beat us
- if (sq(maxDistanceToBeBeaten) > potentialAttackDistance.MagnitudeSqr()) {
+ if (sq(maxDistanceToBeat) > potentialAttackDistance.MagnitudeSqr()) {
for (int j = 0; j < hisCol->numSpheres; j++) {
attackDistance = hisCol->spheres[j].center;
attackDistance -= touchedNodePos;
CColSphere *hisPieces = hisCol->spheres;
- float maxDistanceToBeat = hisPieces[j].radius + tFightMoves[m_lastFightMove].strikeRadius;
+ maxDistanceToBeat = hisPieces[j].radius + radius;
// We can beat him too
if (sq(maxDistanceToBeat) > attackDistance.MagnitudeSqr()) {
- pedFound = true;
- closestPedPiece = (ePedPieceTypes) hisPieces[j].piece;
+ FightHitPed(nearPed, touchedNodePos, attackDistance, hisPieces[j].piece);
+ pedFound = 1;
break;
}
}
}
+ if (!pedFound && !unk) {
+ extendedTouchPoint = touchedNodePos - GetPosition();
+ if (DotProduct(touchedNodePos - GetPosition(), nearPed->GetPosition() - GetPosition()) > 0.f) {
+ if (m_lastFightMove == FIGHTMOVE_GROUNDKICK) {
+ extendedTouchPoint += tFightMoves[FIGHTMOVE_GROUNDKICK].extendReachMultiplier * GetForward();
+ } else {
+ extendedTouchPoint.x *= tFightMoves[m_lastFightMove].extendReachMultiplier;
+ extendedTouchPoint.y *= tFightMoves[m_lastFightMove].extendReachMultiplier;
+ }
+ pedFound = -1;
+ extendedTouchPoint += GetPosition();
+ }
+ }
+ if (pedFound == -1) {
+ CVector nearPedCentre = nearPed->GetBoundCentre();
+ if (sq(maxDistanceToBeat) > (nearPedCentre - extendedTouchPoint).MagnitudeSqr()) {
+
+ for (int j = 0; j < hisCol->numSpheres; j++) {
+ attackDistance = hisCol->spheres[j].center;
+ attackDistance -= extendedTouchPoint;
+ CColSphere* hisPieces = hisCol->spheres;
+ float maxDistanceToBeat2 = hisPieces[j].radius + tFightMoves[m_lastFightMove].strikeRadius;
+
+ // We can beat him too
+ if (sq(maxDistanceToBeat2) > attackDistance.MagnitudeSqr()) {
+ FightHitPed(nearPed, extendedTouchPoint, attackDistance, hisPieces[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_lastFightMove].damage * ((CGeneral::GetRandomNumber() & 1) + 2) + 1;
+ if (m_fightState == FIGHTSTATE_NO_MOVE)
+ m_fightState = FIGHTSTATE_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;
- }
+ m_vecHitLastPos = *touchedNodePos;
+ return false;
+}
- /*
- // Change direction if we used kick.
- if (m_lastFightMove == 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;
+// TODO(Miami)
+void
+CPed::FightHitPed(CPed *victim, CVector &touchPoint, CVector &dist, int16 piece)
+{
+ if (victim->IsPlayer() && victim->m_nPedState == PED_GETUP)
+ return;
+
+ CWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
+ bool fightingWithWeapon = false;
+ int damageMult = tFightMoves[m_lastFightMove].damage * ((CGeneral::GetRandomNumber() & 1) + 2) + 1;
- nearPed->StartFightDefend(direction, tFightMoves[m_lastFightMove].hitLevel, unk2);
- PlayHitSound(nearPed);
- m_fightState = FIGHTSTATE_JUST_ATTACKED;
- RpAnimBlendClumpGetAssociation(GetClump(), tFightMoves[m_lastFightMove].animId)->speed = 0.6f;
- if (!nearPed->DyingOrDead()) {
- nearPed->InflictDamage(this, WEAPONTYPE_UNARMED, damageMult * 3.0f, closestPedPiece, direction);
+ if (weaponInfo->m_bFightMode) {
+ fightingWithWeapon = true;
+ if (m_lastFightMove >= FIGHTMOVE_MELEE1) {
+ damageMult = weaponInfo->m_nDamage;
+ if (m_lastFightMove == FIGHTMOVE_MELEE3 && GetWeapon()->m_eWeaponType != WEAPONTYPE_SCREWDRIVER)
+ damageMult *= 5;
}
+ }
- if (CGame::nastyGame
- && tFightMoves[m_lastFightMove].hitLevel > HITLEVEL_MEDIUM
- && nearPed->m_nPedState == PED_DIE
- && nearPed->GetIsOnScreen()) {
+ if (IsPlayer()) {
+ if (((CPlayerPed*)this)->m_bAdrenalineActive)
+ damageMult = 20;
+ } else if (!fightingWithWeapon) {
+ damageMult *= m_pedStats->m_attackStrength;
+ }
- // 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);
- }
+ float oldVictimHealth = victim->m_fHealth;
+ CVector bloodPos = 0.5f * dist + touchPoint;
+ CVector2D diff(GetPosition() - victim->GetPosition());
+ int direction = victim->GetLocalDirection(diff);
+
+ /*
+ // Change direction if we used kick.
+ if (m_lastFightMove == FIGHTMOVE_KICK) {
+ if (CGeneral::GetRandomNumber() & 1) {
+ direction++;
+ if (direction > 3)
+ direction -= 4;
+ }
+ } */
+ victim->ReactToAttack(this);
+
+ // Mostly unused. if > 5, ANIM_HIT_WALK will be run, that's it.
+ int unk2;
+ if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED && !victim->IsPlayer())
+ unk2 = 101;
+ else
+ unk2 = damageMult;
+
+ victim->StartFightDefend(direction, tFightMoves[m_lastFightMove].hitLevel, unk2);
+ PlayHitSound(victim);
+ m_fightState = FIGHTSTATE_JUST_ATTACKED;
+ RpAnimBlendClumpGetAssociation(GetClump(), tFightMoves[m_lastFightMove].animId)->speed = 0.6f;
+ if (!victim->DyingOrDead()) {
+ victim->InflictDamage(this, WEAPONTYPE_UNARMED, damageMult * 3.0f, (ePedPieceTypes)piece, direction);
+ }
+
+ if (CGame::nastyGame
+ && tFightMoves[m_lastFightMove].hitLevel > HITLEVEL_MEDIUM
+ && victim->m_nPedState == PED_DIE
+ && victim->GetIsOnScreen()) {
+
+ // Just for blood particle. We will restore it below.
+ dist /= (10.0f * dist.Magnitude());
+ for(int i=0; i<4; i++) {
+ CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dist, nil, 0.0f, 0, 0, 0, 0);
}
- if (nearPed->m_nPedState != PED_FALL && nearPed->m_nPedState != PED_DIE && nearPed->m_nPedState != PED_DEAD) {
- float curVictimHealth = nearPed->m_fHealth;
+ }
+
+ eWeaponType weaponType = GetWeapon()->m_eWeaponType;
+ if (!fightingWithWeapon) {
+ if (victim->m_nPedState != PED_FALL && victim->m_nPedState != PED_DIE && victim->m_nPedState != PED_DEAD) {
+ float curVictimHealth = victim->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)) {
+ && (curVictimHealth < 30.0f && oldVictimHealth > 30.0f
+ || weaponType != WEAPONTYPE_UNARMED && weaponType != WEAPONTYPE_BRASSKNUCKLE && IsPlayer()
+ || victim->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;
+ victim->SetFall(0, (AnimationId)(direction + ANIM_KO_SKID_FRONT), 0);
+ if (victim->m_nPedState == PED_FALL)
+ victim->bIsStanding = false;
}
}
- if (nearPed->m_nPedState == PED_DIE || !nearPed->bIsStanding) {
- attackDistance = nearPed->GetPosition() - GetPosition();
- attackDistance.Normalise();
- attackDistance.z = 1.0f;
- nearPed->bIsStanding = false;
+ }
+
+ if (victim->m_nPedState == PED_DIE || !victim->bIsStanding) {
+ dist = victim->GetPosition() - GetPosition();
+ dist.Normalise();
+ dist.z = 1.0f;
+ victim->bIsStanding = false;
- float moveMult;
- if (m_lastFightMove == FIGHTMOVE_GROUNDKICK) {
- moveMult = Min(damageMult * 0.6f, 4.0f);
+ float moveMult;
+ if (fightingWithWeapon) {
+ moveMult = Min(damageMult * 0.02f, 1.0f);
+ } else if (m_lastFightMove == FIGHTMOVE_GROUNDKICK) {
+ moveMult = Min(damageMult * 0.6f, 4.0f);
+ } else {
+ if (victim->m_nPedState != PED_DIE || damageMult >= 20) {
+ moveMult = damageMult;
} else {
- if (nearPed->m_nPedState != PED_DIE || damageMult >= 20) {
- moveMult = damageMult;
- } else {
- moveMult = Min(damageMult * 2.0f, 14.0f);
- }
+ 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);
+
+ victim->ApplyMoveForce(moveMult * 0.6f * dist);
}
- if (m_fightState == FIGHTSTATE_NO_MOVE)
- m_fightState = FIGHTSTATE_1;
+ if (weaponType != WEAPONTYPE_KNIFE && weaponType != WEAPONTYPE_MACHETE
+ && weaponType != WEAPONTYPE_KATANA && weaponType != WEAPONTYPE_CHAINSAW) {
- m_vecHitLastPos = *touchedNodePos;
- return false;
+ if (victim->m_nPedType == PEDTYPE_COP)
+ CEventList::RegisterEvent(EVENT_ASSAULT_POLICE, EVENT_ENTITY_PED, victim, this, 2000);
+ else
+ CEventList::RegisterEvent(EVENT_ASSAULT, EVENT_ENTITY_PED, victim, this, 2000);
+ } else {
+ if (victim->m_nPedType == PEDTYPE_COP)
+ CEventList::RegisterEvent(EVENT_ASSAULT_NASTYWEAPON_POLICE, EVENT_ENTITY_PED, victim, this, 2000);
+ else
+ CEventList::RegisterEvent(EVENT_ASSAULT_NASTYWEAPON, EVENT_ENTITY_PED, victim, this, 2000);
+ }
}
// --MIAMI: Done
@@ -5742,7 +5925,7 @@ CPed::SetWaitState(eWaitState state, void *time)
if (!IsPedInControl())
return;
- if (m_nWaitState == WAITSTATE_RIOT && state == WAITSTATE_FALSE)
+ if (m_nWaitState == WAITSTATE_RIOT && state != WAITSTATE_FALSE)
return;
if (state != m_nWaitState)
@@ -5988,6 +6171,7 @@ CPed::PlayHitSound(CPed *hitTo)
DMAudio.PlayOneShot(m_audioEntityId, soundId, 0.0f);
}
+// --MIAMI: Done
void
CPed::CollideWithPed(CPed *collideWith)
{
@@ -6000,6 +6184,15 @@ CPed::CollideWithPed(CPed *collideWith)
int waitTime = 0;
if (weAreMissionChar || !collideWith->IsPlayer() || collideWith->m_nPedState != PED_MAKE_CALL) {
+ if (m_nWaitState == WAITSTATE_SUN_BATHE_IDLE) {
+ SetGetUp();
+ return;
+ }
+ if (collideWith->m_nWaitState == WAITSTATE_SUN_BATHE_IDLE) {
+ collideWith->SetGetUp();
+ return;
+ }
+
bool weDontLookToHim = DotProduct(posDiff, GetForward()) > 0.0f;
bool heLooksToUs = DotProduct(posDiff, collideWith->GetForward()) < 0.0f;
@@ -6007,10 +6200,8 @@ CPed::CollideWithPed(CPed *collideWith)
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_PED_IN_FORMATION && m_pedInObjective == collideWith
- || collideWith->m_objective == OBJECTIVE_FOLLOW_PED_IN_FORMATION && collideWith->m_pedInObjective == this
-#endif
+ || collideWith->m_objective == OBJECTIVE_FOLLOW_PED_IN_FORMATION && collideWith->m_pedInObjective == this
)) {
if (m_objective != OBJECTIVE_FOLLOW_PED_IN_FORMATION && m_objective != OBJECTIVE_GOTO_CHAR_ON_FOOT) {
@@ -6039,11 +6230,10 @@ CPed::CollideWithPed(CPed *collideWith)
SetDirectionToWalkAroundObject(collideWith);
}
} else {
-#ifdef VC_PED_PORTS
if (FindPlayerPed() != m_pedInObjective
|| m_objective != OBJECTIVE_KILL_CHAR_ANY_MEANS && m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT
|| collideWith == m_pedInObjective) {
-#endif
+
if (weAreMissionChar || m_pedStats->m_fear <= 100 - collideWith->m_pedStats->m_temper
|| (collideWith->IsPlayer() || collideWith->m_nMoveState == PEDMOVE_NONE || collideWith->m_nMoveState == PEDMOVE_STILL) &&
(!collideWith->IsPlayer() || ((CPlayerPed*)collideWith)->m_fMoveSpeed <= 1.0f)) {
@@ -6053,47 +6243,43 @@ CPed::CollideWithPed(CPed *collideWith)
} else {
SetEvasiveStep(collideWith, 2);
}
-#ifdef VC_PED_PORTS
} else if (collideWith->m_nMoveState != PEDMOVE_STILL && GetWeapon()->IsTypeMelee()
&& collideWith->m_pedInObjective == m_pedInObjective) {
- int colliderIsAtPlayerSafePosID = -1;
- int weAreAtPlayerSafePosID = -1;
- for (int i = 0; i < ARRAY_SIZE(((CPlayerPed*)m_pedInObjective)->m_pPedAtSafePos); i++) {
- CPed *pedAtSafePos = ((CPlayerPed*)m_pedInObjective)->m_pPedAtSafePos[i];
- if (pedAtSafePos == this) {
- weAreAtPlayerSafePosID = i;
- } else if (pedAtSafePos == collideWith) {
- colliderIsAtPlayerSafePosID = i;
+ int colliderIndexAtPlayersKillList = -1;
+ int ourIndexAtPlayersKillList = -1;
+ for (int i = 0; i < ARRAY_SIZE(((CPlayerPed*)m_pedInObjective)->m_pMeleeList); i++) {
+ CPed *pedInKillList = ((CPlayerPed*)m_pedInObjective)->m_pMeleeList[i];
+ if (pedInKillList == this) {
+ ourIndexAtPlayersKillList = i;
+ } else if (pedInKillList == collideWith) {
+ colliderIndexAtPlayersKillList = i;
}
}
bool weAreCloserToTargetThenCollider = false;
if ((GetPosition() - m_vecSeekPos).MagnitudeSqr2D() < (collideWith->GetPosition() - m_vecSeekPos).MagnitudeSqr2D())
weAreCloserToTargetThenCollider = true;
- if (weAreAtPlayerSafePosID <= 0 || weAreCloserToTargetThenCollider) {
- if (!weAreCloserToTargetThenCollider) {
+ if (ourIndexAtPlayersKillList > 0 && !weAreCloserToTargetThenCollider) {
+ if (colliderIndexAtPlayersKillList > 0) {
int time = 300;
SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, &time);
m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + time;
- }
- } else if (colliderIsAtPlayerSafePosID <= 0) {
- if (collideWith->m_pedInObjective == FindPlayerPed()) {
- // VC specific
- // ((CPlayerPed*)m_pedInObjective)->RemovePedFromMeleeList(this);
+
+ } else if (collideWith->m_pedInObjective == FindPlayerPed()) {
+ ((CPlayerPed*)m_pedInObjective)->RemovePedFromMeleeList(this);
int time = 500;
SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, &time);
m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + time;
}
- } else {
+ } else if (!weAreCloserToTargetThenCollider) {
int time = 300;
SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, &time);
m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + time;
- }
+ }
} else {
SetDirectionToWalkAroundObject(collideWith);
}
-#endif
}
} else {
if (m_pedStats->m_temper <= m_pedStats->m_fear
@@ -6107,12 +6293,14 @@ CPed::CollideWithPed(CPed *collideWith)
} else {
TurnBody();
SetAttack(collideWith);
+ m_fRotationCur = 0.3f + m_fRotationCur;
+ m_fRotationDest = m_fRotationCur;
}
m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(250, 450);
}
}
} else {
- if (m_pedInObjective && collideWith == m_pedInObjective && CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) {
+ if (m_pedInObjective && (collideWith == m_pedInObjective || collideWith->m_pedInObjective == m_pedInObjective) && CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) {
if (heLooksToUs) {
SetEvasiveStep(collideWith, 1);
m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 3000;
@@ -6121,7 +6309,8 @@ CPed::CollideWithPed(CPed *collideWith)
if (m_pedStats != collideWith->m_pedStats) {
- if (collideWith->m_pedStats->m_fear <= 100 - m_pedStats->m_temper) {
+ if (collideWith->m_pedStats->m_fear <= 100 - m_pedStats->m_temper || collideWith->IsPlayer()
+ || CTimer::GetTimeInMilliseconds() < m_nPedStateTimer) {
if (collideWith->IsPlayer()) {
// He's on our right side
@@ -6131,16 +6320,17 @@ CPed::CollideWithPed(CPed *collideWith)
m_fRotationCur += m_headingRate;
} else {
// He's on our right side
- if (DotProduct(posDiff, GetRight()) <= 0.0f)
- m_fRotationCur -= m_headingRate;
+ if (DotProduct(posDiff, collideWith->GetRight()) <= 0.0f)
+ collideWith->m_fRotationCur -= collideWith->m_headingRate;
else
- m_fRotationCur += m_headingRate;
+ 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;
+ m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 2000;
if (!heIsMissionChar) {
CVector2D posDiff2D(posDiff);
int direction = collideWith->GetLocalDirection(posDiff2D);
@@ -6150,11 +6340,9 @@ CPed::CollideWithPed(CPed *collideWith)
}
}
}
- } else if (collideWith->m_pedStats->m_defendWeakness <= 1.5f || heIsMissionChar
-#ifdef VC_PED_PORTS
- || m_pedStats->m_defendWeakness <= collideWith->m_pedStats->m_defendWeakness
-#endif
- ) {
+ } else if (collideWith->m_pedStats->m_defendWeakness <= 1.5f || heIsMissionChar ||
+ m_pedStats->m_defendWeakness <= collideWith->m_pedStats->m_defendWeakness) {
+
// He looks us and we're not at his right side
if (heLooksToUs && DotProduct(posDiff,collideWith->GetRight()) > 0.0f) {
CVector moveForce = GetRight();
@@ -6207,7 +6395,7 @@ CPed::CollideWithPed(CPed *collideWith)
}
if (m_nPedState == PED_ATTACK && collideWith->IsPedInControl())
- DMAudio.PlayOneShot(m_audioEntityId, SOUND_FIGHT_PUNCH_39, 0.0f);
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_49, 0.0f);
collideWith->SetFall(3000, animToPlay, 0);
}
@@ -6356,6 +6544,7 @@ CPed::SetAttackTimer(uint32 time)
m_attackTimer = Max(m_shootTimer, CTimer::GetTimeInMilliseconds()) + time;
}
+// --MIAMI: Done
void
CPed::SetBeingDraggedFromCar(CVehicle *veh, uint32 vehEnterType, bool quickJack)
{
@@ -6368,7 +6557,17 @@ CPed::SetBeingDraggedFromCar(CVehicle *veh, uint32 vehEnterType, bool quickJack)
SetMoveState(PEDMOVE_STILL);
m_pSeekTarget = veh;
m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget);
- m_vehEnterType = vehEnterType;
+
+ if (veh->IsBike()) {
+ ((CBike*)veh)->bIsBeingPickedUp = true;
+ if (veh->pPassengers[0] != this && (vehEnterType != CAR_WINDSCREEN || veh->pPassengers[0]))
+ m_vehEnterType = CAR_DOOR_LF;
+ else
+ m_vehEnterType = CAR_DOOR_LR;
+ } else {
+ m_vehEnterType = vehEnterType;
+ }
+
if (m_vehEnterType == CAR_DOOR_LF) {
if (veh->pDriver && veh->pDriver->IsPlayer())
veh->SetStatus(STATUS_PLAYER_DISABLED);
@@ -6377,9 +6576,9 @@ CPed::SetBeingDraggedFromCar(CVehicle *veh, uint32 vehEnterType, bool quickJack)
}
RemoveInCarAnims();
SetMoveState(PEDMOVE_NONE);
- LineUpPedWithCar(LINE_UP_TO_CAR_START);
+ LineUpPedWithCar(veh->IsBike() ? LINE_UP_TO_CAR_FALL : LINE_UP_TO_CAR_START);
m_pVehicleAnim = nil;
- m_nPedState = PED_DRAG_FROM_CAR;
+ SetPedState(PED_DRAG_FROM_CAR);
bChangedSeat = false;
bWillBeQuickJacked = quickJack;
@@ -6430,8 +6629,10 @@ CPed::SetBuyIceCream(void)
void
CPed::SetChat(CEntity *chatWith, uint32 time)
{
- if(m_nPedState != PED_CHAT)
+ if (m_nPedState != PED_CHAT) {
+ m_nLastPedState = PED_NONE;
SetStoredState();
+ }
SetPedState(PED_CHAT);
SetMoveState(PEDMOVE_STILL);
@@ -6511,6 +6712,7 @@ CPed::SetDead(void)
CEventList::RegisterEvent(EVENT_DEAD_PED, EVENT_ENTITY_PED, this, nil, 1000);
}
+// --MIAMI: Done
void
CPed::SetSeek(CEntity *seeking, float distanceToCountDone)
{
@@ -6520,24 +6722,25 @@ CPed::SetSeek(CEntity *seeking, float distanceToCountDone)
if (m_nPedState == PED_SEEK_ENTITY && m_pSeekTarget == seeking)
return;
- if (!seeking)
+ if (!seeking || m_nPedState == PED_FOLLOW_PATH)
return;
if (m_nPedState != PED_SEEK_ENTITY)
SetStoredState();
- m_nPedState = PED_SEEK_ENTITY;
+ SetPedState(PED_SEEK_ENTITY);
m_distanceToCountSeekDone = distanceToCountDone;
m_pSeekTarget = seeking;
m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget);
SetMoveState(PEDMOVE_STILL);
}
+// --MIAMI: Done
void
CPed::SetSeek(CVector pos, float distanceToCountDone)
{
if (!IsPedInControl()
- || (m_nPedState == PED_SEEK_POS && m_vecSeekPos.x == pos.x && m_vecSeekPos.y == pos.y))
+ || (m_nPedState == PED_SEEK_POS && m_vecSeekPos.x == pos.x && m_vecSeekPos.y == pos.y) || m_nPedState == PED_FOLLOW_PATH)
return;
if (!CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_bCanAimWithArm) {
@@ -6547,7 +6750,7 @@ CPed::SetSeek(CVector pos, float distanceToCountDone)
if (m_nPedState != PED_SEEK_POS)
SetStoredState();
- m_nPedState = PED_SEEK_POS;
+ SetPedState(PED_SEEK_POS);
m_distanceToCountSeekDone = distanceToCountDone;
m_vecSeekPos = pos;
}
@@ -7480,6 +7683,7 @@ CPed::Fight(void)
}
}
+// --MIAMI: Done
// Some helper function which doesn't exist in og game.
inline void
SelectClosestNodeForSeek(CPed *ped, CPathNode *node, CVector2D closeDist, CVector2D farDist, CPathNode *closeNode, CPathNode *closeNode2, int runCount = 3)
@@ -7509,6 +7713,7 @@ SelectClosestNodeForSeek(CPed *ped, CPathNode *node, CVector2D closeDist, CVecto
}
}
+// --MIAMI: Done
bool
CPed::FindBestCoordsFromNodes(CVector unused, CVector *bestCoords)
{
@@ -7534,12 +7739,14 @@ CPed::FindBestCoordsFromNodes(CVector unused, CVector *bestCoords)
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();
+ // Function above decided that directly going to next node makes more sense then seeking the object.
+ CVector correctedCoords = CPathFind::TakeWidthIntoAccountForWandering(m_pNextPathNode, m_randomSeed);
+
+ if ((correctedCoords - ourPos).MagnitudeSqr2D() < seekPosDist.MagnitudeSqr()) {
+ correctedCoords = CPathFind::TakeWidthIntoAccountForWandering(m_pNextPathNode, m_randomSeed);
+ *bestCoords = correctedCoords;
return true;
}
m_pNextPathNode = nil;
@@ -8095,6 +8302,7 @@ CPed::Wait(void)
RestoreHeadingRate();
}
+// --MIAMI: Done
bool
CPed::Seek(void)
{
@@ -8113,7 +8321,7 @@ CPed::Seek(void)
false, true, false, false, false, false);
if (obstacle) {
- if (!obstacle->IsVehicle() || ((CVehicle*)obstacle)->m_vehType == VEHICLE_TYPE_CAR) {
+ if (!obstacle->IsVehicle() || ((CVehicle*)obstacle)->IsCar()) {
distanceToCountItDone = 2.5f;
} else {
CVehicleModelInfo *vehModel = (CVehicleModelInfo *)CModelInfo::GetModelInfo(obstacle->GetModelIndex());
@@ -8129,6 +8337,13 @@ CPed::Seek(void)
if (!m_pSeekTarget && m_nPedState == PED_SEEK_ENTITY)
ClearSeek();
+ if (m_objective == OBJECTIVE_FOLLOW_PED_IN_FORMATION && !m_pedInObjective) {
+ m_objective = OBJECTIVE_NONE;
+ ClearObjective();
+ SetWanderPath(0);
+ return false;
+ }
+
float seekPosDist = (m_vecSeekPos - GetPosition()).Magnitude2D();
if (seekPosDist < 2.0f || m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT) {
@@ -8164,7 +8379,9 @@ CPed::Seek(void)
}
}
- if (seekPosDist >= distanceToCountItDone) {
+ CVector *nextNode = SeekFollowingPath();
+
+ if (nextNode || seekPosDist >= distanceToCountItDone) {
if (bIsRunning && nextMove != PEDMOVE_SPRINT)
nextMove = PEDMOVE_RUN;
@@ -8201,10 +8418,17 @@ CPed::Seek(void)
m_actionY = 0;
}
}
+
} else {
- m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(
- m_vecSeekPos.x, m_vecSeekPos.y,
- GetPosition().x, GetPosition().y);
+ if (nextNode) {
+ m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(
+ nextNode->x, nextNode->y,
+ GetPosition().x, GetPosition().y);
+ } else {
+ m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(
+ m_vecSeekPos.x, m_vecSeekPos.y,
+ GetPosition().x, GetPosition().y);
+ }
float neededTurn = Abs(m_fRotationDest - m_fRotationCur);
@@ -8238,7 +8462,7 @@ CPed::Seek(void)
}
if (m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT || m_objective == OBJECTIVE_RUN_TO_AREA || m_objective == OBJECTIVE_SPRINT_TO_COORD ||
- m_objective == OBJECTIVE_GOTO_AREA_ANY_MEANS) {
+ m_objective == OBJECTIVE_GOTO_AREA_ANY_MEANS || IsUseAttractorObjective(m_objective)) {
if (m_pNextPathNode)
m_pNextPathNode = nil;
@@ -8248,16 +8472,30 @@ CPed::Seek(void)
bUsePedNodeSeek = true;
}
- if (SeekFollowingPath(nil))
- m_nCurPathNode++;
-
return true;
}
-bool
-CPed::SeekFollowingPath(CVector *unused)
+CVector*
+CPed::SeekFollowingPath(void)
{
- return m_nCurPathNode <= m_nPathNodes && m_nPathNodes;
+ // unused
+ if (!vecNextPathNodeInitialized)
+ vecNextPathNodeInitialized = true;
+
+ if (m_nCurPathNodeId >= m_nNumPathNodes || m_nNumPathNodes == 0)
+ return nil;
+
+ vecNextPathNode = m_pathNodesToGo[m_nCurPathNodeId]->GetPosition();
+
+ if ((vecNextPathNode - GetPosition()).Magnitude2D() < m_distanceToCountSeekDone) {
+ m_nCurPathNodeId++;
+ if (m_nCurPathNodeId < m_nNumPathNodes)
+ m_pCurPathNode = m_pathNodesToGo[m_nCurPathNodeId];
+ }
+ if (m_nCurPathNodeId == m_nNumPathNodes)
+ return nil;
+ else
+ return &vecNextPathNode;
}
void
@@ -8443,39 +8681,46 @@ CPed::Flee(void)
}
+// --MIAMI: Done
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++;
+ m_pCurPathNode = m_pathNodesToGo[m_nCurPathNodeId];
+ if (m_pathNodeTimer && CTimer::GetTimeInMilliseconds() > m_pathNodeTimer) {
+ RestorePreviousState();
+ ClearFollowPath();
+ m_pathNodeTimer = 0;
+ } else {
+ if (m_pathNodesToGo[m_nCurPathNodeId]) {
+ m_vecSeekPos.x = m_pathNodesToGo[m_nCurPathNodeId]->GetPosition().x;
+ m_vecSeekPos.y = m_pathNodesToGo[m_nCurPathNodeId]->GetPosition().y;
+ m_vecSeekPos.z = GetPosition().z;
- }
-*/
- if (Seek()) {
- m_nCurPathNode++;
- if (m_nCurPathNode == m_nPathNodes)
+ if (Seek()) {
+ if (m_nCurPathNodeId == m_nNumPathNodes) {
+ RestorePreviousState();
+ ClearFollowPath();
+ SetFollowPath(m_followPathDestPos, m_followPathAbortDist, m_followPathMoveState, m_followPathWalkAroundEnt,
+ m_followPathTargetEnt, m_pathNodeTimer - CTimer::GetTimeInMilliseconds());
+ }
+ }
+ } else {
RestorePreviousState();
+ ClearFollowPath();
+ m_pathNodeTimer = 0;
+ }
}
}
+// --MIAMI: Done
CVector
CPed::GetFormationPosition(void)
{
CPed *referencePed = m_pedInObjective;
+ if (!referencePed)
+ return GetPosition();
+
if (referencePed->m_nPedState == PED_DEAD) {
CPed *referencePedOfReference = referencePed->m_pedInObjective;
if (!referencePedOfReference) {
@@ -8486,36 +8731,37 @@ CPed::GetFormationPosition(void)
}
CVector formationOffset;
+ float offset = CGeneral::GetRandomNumberInRange(1.f, 1.25f) * 1.75f;
switch (m_pedFormation) {
case FORMATION_REAR:
- formationOffset = CVector(0.0f, -1.5f, 0.0f);
+ formationOffset = CVector(0.0f, -offset, 0.0f);
break;
case FORMATION_REAR_LEFT:
- formationOffset = CVector(-1.5f, -1.5f, 0.0f);
+ formationOffset = CVector(-offset, -offset, 0.0f);
break;
case FORMATION_REAR_RIGHT:
- formationOffset = CVector(1.5f, -1.5f, 0.0f);
+ formationOffset = CVector(offset, -offset, 0.0f);
break;
case FORMATION_FRONT_LEFT:
- formationOffset = CVector(-1.5f, 1.5f, 0.0f);
+ formationOffset = CVector(-offset, offset, 0.0f);
break;
case FORMATION_FRONT_RIGHT:
- formationOffset = CVector(1.5f, 1.5f, 0.0f);
+ formationOffset = CVector(offset, offset, 0.0f);
break;
case FORMATION_LEFT:
- formationOffset = CVector(-1.5f, 0.0f, 0.0f);
+ formationOffset = CVector(-offset, 0.0f, 0.0f);
break;
case FORMATION_RIGHT:
- formationOffset = CVector(1.5f, 0.0f, 0.0f);
+ formationOffset = CVector(offset, 0.0f, 0.0f);
break;
case FORMATION_FRONT:
- formationOffset = CVector(0.0f, 1.5f, 0.0f);
+ formationOffset = CVector(0.0f, offset, 0.0f);
break;
default:
formationOffset = CVector(0.0f, 0.0f, 0.0f);
break;
}
- return formationOffset + referencePed->GetPosition();
+ return m_pedInObjective->GetMatrix() * formationOffset;
}
// --MIAMI: Done
@@ -9268,7 +9514,7 @@ CPed::KillPedWithCar(CVehicle *car, float impulse)
CPad::GetPad(0)->StartShake(40000 / shakeFreq, shakeFreq);
}
bIsStanding = false;
- damageDir = CPed::GetLocalDirection(-m_vecMoveSpeed);
+ damageDir = GetLocalDirection(-m_vecMoveSpeed);
vehModel = (CVehicleModelInfo *)CModelInfo::GetModelInfo(car->GetModelIndex());
vehColModel = vehModel->GetColModel();
float carRightAndDistDotProd = DotProduct(distVec, car->GetRight());
@@ -9992,6 +10238,7 @@ CPed::PedAnimAlignCB(CAnimBlendAssociation *animAssoc, void *arg)
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ((CBike*)veh)->m_bikeAnimType,
enterDoor == DOOR_FRONT_LEFT || enterDoor == DOOR_REAR_LEFT ? ANIM_BIKE_JUMPON_R : ANIM_BIKE_JUMPON_L);
ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);
+ ((CBike*)veh)->bIsBeingPickedUp = true;
}
} else if (ped->m_vehEnterType == CAR_WINDSCREEN) {
if (veh->pDriver->m_nPedState != PED_DRIVING || veh->pDriver->bDontDragMeOutCar) {
@@ -10001,6 +10248,7 @@ CPed::PedAnimAlignCB(CAnimBlendAssociation *animAssoc, void *arg)
ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);
pedToDragOut = veh->pDriver;
}
+ ((CBike*)veh)->bIsBeingPickedUp = true;
} else {
if (enterDoor == DOOR_FRONT_LEFT || enterDoor == DOOR_FRONT_RIGHT) {
if (veh->pDriver) {
@@ -10021,6 +10269,7 @@ CPed::PedAnimAlignCB(CAnimBlendAssociation *animAssoc, void *arg)
} else {
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(), ((CBike*)veh)->m_bikeAnimType, enterDoor == DOOR_FRONT_LEFT ? ANIM_BIKE_JUMPON_R : ANIM_BIKE_JUMPON_L);
ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);
+ ((CBike*)veh)->bIsBeingPickedUp = true;
}
} else {
if (veh->pPassengers[0]) {
@@ -10043,10 +10292,10 @@ CPed::PedAnimAlignCB(CAnimBlendAssociation *animAssoc, void *arg)
ped->m_pVehicleAnim = CAnimManager::AddAnimation(ped->GetClump(),
((CBike*)veh)->m_bikeAnimType, enterDoor == DOOR_REAR_LEFT ? ANIM_BIKE_JUMPON_R : ANIM_BIKE_JUMPON_L);
ped->m_pVehicleAnim->SetFinishCallback(PedAnimGetInCB, ped);
+ ((CBike*)veh)->bIsBeingPickedUp = true;
}
}
}
- ((CBike*)veh)->bIsBeingPickedUp = true;
// TODO(Miami): This looks like something inlined
if (pedToDragOut) {
@@ -10535,17 +10784,22 @@ CPed::ProcessControl(void)
if (!bVehEnterDoorIsBlocked) {
if (collidingVeh->GetStatus() != STATUS_PLAYER || CharCreatedBy == MISSION_CHAR) {
- // VC calls SetDirectionToWalkAroundVehicle instead if ped is in PED_SEEK_CAR.
- SetDirectionToWalkAroundObject(collidingVeh);
- CWorld::Players[CWorld::PlayerInFocus].m_nLastBumpPlayerCarTimer = m_nPedStateTimer;
+ if (m_nPedState == PED_SEEK_CAR) {
+ SetDirectionToWalkAroundObject(collidingVeh);
+ CWorld::Players[CWorld::PlayerInFocus].m_nLastBumpPlayerCarTimer = m_nPedStateTimer;
+ } else {
+ SetDirectionToWalkAroundVehicle(collidingVeh);
+ }
} else {
if (CTimer::GetTimeInMilliseconds() >= CWorld::Players[CWorld::PlayerInFocus].m_nLastBumpPlayerCarTimer
|| m_nPedStateTimer >= CTimer::GetTimeInMilliseconds()) {
- // VC calls SetDirectionToWalkAroundVehicle instead if ped is in PED_SEEK_CAR.
- SetDirectionToWalkAroundObject(collidingVeh);
- CWorld::Players[CWorld::PlayerInFocus].m_nLastBumpPlayerCarTimer = m_nPedStateTimer;
-
+ if (m_nPedState == PED_SEEK_CAR) {
+ SetDirectionToWalkAroundObject(collidingVeh);
+ CWorld::Players[CWorld::PlayerInFocus].m_nLastBumpPlayerCarTimer = m_nPedStateTimer;
+ } else {
+ SetDirectionToWalkAroundVehicle(collidingVeh);
+ }
} else if (m_fleeFrom != collidingVeh) {
SetFlee(collidingVeh, 4000);
bUsePedNodeSeek = false;
@@ -14932,6 +15186,9 @@ CPed::SetSeekCar(CVehicle *car, uint32 doorNode)
if (m_nPedState == PED_SEEK_CAR)
return;
+ if (!CanSetPedState() || m_nPedState == PED_DRIVING)
+ return;
+
SetStoredState();
m_pSeekTarget = car;
m_pSeekTarget->RegisterReference((CEntity**) &m_pSeekTarget);
@@ -15030,7 +15287,13 @@ CanWeSeeTheCorner(CVector2D dist, CVector2D fwdOffset)
}
#endif
-// This function looks completely same on VC.
+// --MIAMI: Done
+bool
+CPed::SetDirectionToWalkAroundVehicle(CVehicle* veh)
+{
+ return SetFollowPath(m_vecSeekPos, 0.0f, m_nMoveState, veh, m_pedInObjective, m_nMoveState == PEDMOVE_WALK ? 2000 : 250);
+}
+
void
CPed::SetDirectionToWalkAroundObject(CEntity *obj)
{
@@ -16361,36 +16624,519 @@ CPed::SetSolicit(uint32 time)
}
}
+// --MIAMI: Done
bool
-CPed::SetFollowPath(CVector dest, float radius, eMoveState state, CEntity* pFollowedPed, CEntity*, int time)
+CPed::SetFollowPathStatic(void)
{
- // TODO(MIAMI): new follow
- if (m_nPedState == PED_FOLLOW_PATH)
- return false;
+ ClearFollowPath();
+ if (sq(m_followPathAbortDist) > (GetPosition() - m_followPathDestPos).MagnitudeSqr()
+ && CWorld::IsWanderPathClear(GetPosition(), m_followPathDestPos, 0.5f, 4)) {
- if (FindPlayerPed() != this)
- return false;
+ RestorePreviousState();
+ if (m_objective == OBJECTIVE_NONE) {
+ if (m_followPathMoveState == PEDMOVE_RUN)
+ SetObjective(OBJECTIVE_RUN_TO_AREA, m_followPathDestPos);
+ else
+ SetObjective(OBJECTIVE_GOTO_AREA_ON_FOOT, m_followPathDestPos);
+ }
+ SetPedState(PED_NONE);
+ return true;
+ } else {
+ ThePaths.DoPathSearch(PATH_PED, GetPosition(), -1, m_followPathDestPos, m_pathNodesToGo, &m_nNumPathNodes,
+ ARRAY_SIZE(m_pathNodesToGo), nil, nil, 999999.0f, -1);
- if ((dest - GetPosition()).Magnitude() <= 2.0f)
- return false;
+ if (m_nNumPathNodes != 0) {
+ if (m_nNumPathNodes > 0 && m_pathNodesToGo[0] != m_pCurPathNode) {
+ for (int i = 0; i < ARRAY_SIZE(m_pathNodesToGo) - 1; i++) {
+ m_pathNodesToGo[i] = m_pathNodesToGo[i+1];
+ }
+ --m_nNumPathNodes;
+ }
+ for (int i = 0; i < m_nNumPathNodes; ++i) {
+ CVector nodePos = m_pathNodesToGo[i]->GetPosition();
+ if (sq(m_followPathAbortDist) > (nodePos - m_followPathDestPos).MagnitudeSqr()
+ && CWorld::IsWanderPathClear(nodePos, m_followPathDestPos, 0.5f, 4)) {
+
+ m_nNumPathNodes = i + 1;
+ break;
+ }
+ }
+
+ m_nCurPathNodeId = 0;
+ if (m_pCurPathNode) {
+ for (int j = 0; j < m_nNumPathNodes; ++j) {
+ if (m_pathNodesToGo[j] == m_pCurPathNode) {
+ m_nCurPathNodeId = j;
+ break;
+ }
+ }
+ }
+ m_pCurPathNode = m_pathNodesToGo[m_nCurPathNodeId];
+ PedState oldLastState = m_nLastPedState;
+ m_nLastPedState = PED_NONE;
+ SetStoredState();
+ if (m_nLastPedState == PED_NONE)
+ m_nLastPedState = oldLastState;
+
+ m_nPedState = PED_FOLLOW_PATH;
+ m_nMoveState = m_followPathMoveState;
+ return true;
+ } else {
+ RestorePreviousState();
+ if (m_objective == OBJECTIVE_NONE) {
+ if (m_followPathMoveState == PEDMOVE_RUN)
+ SetObjective(OBJECTIVE_RUN_TO_AREA, m_followPathDestPos);
+ else
+ SetObjective(OBJECTIVE_GOTO_AREA_ON_FOOT, m_followPathDestPos);
+ }
+ SetPedState(PED_NONE);
+ return true;
+ }
+ }
+}
+
+// --MIAMI: Done
+bool
+CPed::SetFollowPath(CVector dest, float radius, eMoveState state, CEntity* walkAroundEnt, CEntity* targetEnt, int time)
+{
+ if (m_nPedState == PED_FOLLOW_PATH) {
+ bool stopFollow = false;
+ if (walkAroundEnt && walkAroundEnt != m_followPathWalkAroundEnt || !walkAroundEnt && m_followPathWalkAroundEnt
+ || targetEnt && targetEnt != m_followPathTargetEnt || !targetEnt && m_followPathTargetEnt) {
+ stopFollow = true;
+
+ } else if (targetEnt) {
+ if ((targetEnt->GetPosition() - m_followPathDestPos).MagnitudeSqr() > 1.f)
+ stopFollow = true;
+
+ } else if (!walkAroundEnt && !targetEnt) {
+ if ((dest - m_followPathDestPos).MagnitudeSqr() > 1.f)
+ stopFollow = true;
+ }
- 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;
+ if (!stopFollow)
+ return false;
}
+ m_pathNodeTimer = CTimer::GetTimeInMilliseconds() + time;
+ m_followPathWalkAroundEnt = walkAroundEnt;
+ m_followPathTargetEnt = targetEnt;
+ m_distanceToCountSeekDone = 0.5f;
- m_nCurPathNode = 0;
- m_nPathNodes = pointsFound;
- if (m_nPathNodes < 1)
- return false;
+ bool weHaveTargetPed = targetEnt && targetEnt->IsPed();
+ bool useDestVec = !weHaveTargetPed;
- SetStoredState();
- m_nPedState = PED_FOLLOW_PATH;
- SetMoveState(PEDMOVE_WALK);
- return true;
+ CVector targetPos;
+ if (useDestVec)
+ targetPos = dest;
+ else
+ targetPos = targetEnt->GetPosition();
+
+ m_followPathDestPos = targetPos;
+ if (targetEnt && m_nPedState == PED_SEEK_POS) {
+ m_followPathDestPos = m_vecSeekPos;
+ }
+
+ float newRadius = radius > 0.f ? radius : 20.f;
+ bool useGivenPedMove = true;
+
+ m_followPathAbortDist = newRadius;
+
+ if (state != PEDMOVE_RUN && state != PEDMOVE_WALK)
+ useGivenPedMove = false;
+
+ if (useGivenPedMove)
+ m_followPathMoveState = state;
+ else
+ m_followPathMoveState = PEDMOVE_WALK;
+
+ if (m_followPathWalkAroundEnt)
+ return SetFollowPathDynamic();
+ else
+ return SetFollowPathStatic();
+}
+
+// --MIAMI: Done
+bool
+CPed::SetFollowPathDynamic(void)
+{
+ CVector colBoxMin = m_followPathWalkAroundEnt->GetColModel()->boundingBox.min + CVector(-0.35f, -0.35f, 0.f);
+ CVector colBoxMax = m_followPathWalkAroundEnt->GetColModel()->boundingBox.max + CVector(0.35f, 0.35f, 0.f);
+
+ CVector colCornerOffsets[4]; // BL, BR, TR, TL
+ colCornerOffsets[0] = CVector(colBoxMin.x, colBoxMin.y, 0.f);
+ colCornerOffsets[1] = CVector(colBoxMax.x, colBoxMin.y, 0.f);
+ colCornerOffsets[2] = CVector(colBoxMax.x, colBoxMax.y, 0.f);
+ colCornerOffsets[3] = CVector(colBoxMin.x, colBoxMax.y, 0.f);
+
+ if (m_followPathWalkAroundEnt->IsVehicle() && ((CVehicle*)m_followPathWalkAroundEnt)->IsUpsideDown()) {
+ CVector old0 = colCornerOffsets[0];
+ colCornerOffsets[0] = colCornerOffsets[1];
+ colCornerOffsets[1] = old0;
+ CVector old2 = colCornerOffsets[2];
+ colCornerOffsets[2] = colCornerOffsets[3];
+ colCornerOffsets[3] = old2;
+ }
+
+ CVector colCornerPos[4]; // global. again BL, BR, TR, TL
+ float dotProdCorrection[4];
+ CVector colBoxPlaneNormal[4];
+
+ for (int i=0; i<4; i++) {
+ colCornerPos[i] = m_followPathWalkAroundEnt->GetMatrix() * colCornerOffsets[i];
+ colCornerPos[i].z = GetPosition().z;
+ }
+
+ CVector prevColCorner = colCornerPos[3]; // top left
+ CVector *curCornerPos;
+ CVector fwdToNextCorner;
+
+ for (int i=0; i<4; i++) {
+ curCornerPos = &colCornerPos[i];
+ fwdToNextCorner = *curCornerPos - prevColCorner;
+ fwdToNextCorner.Normalise();
+ colBoxPlaneNormal[i] = CrossProduct(fwdToNextCorner, CVector(0.f, 0.f, 1.f));
+ dotProdCorrection[i] = -DotProduct(prevColCorner, colBoxPlaneNormal[i]); // yes, dp with global coord, as if in distance to plane calculation
+ prevColCorner = *curCornerPos;
+ }
+
+ bool weReGoingGreat = false;
+ CVector startVecCandidate = GetPosition();
+ CVector targetVecCandidate = m_followPathDestPos;
+ CVector dirToGo = targetVecCandidate - startVecCandidate;
+ dirToGo.Normalise();
+ CVector ourPos = startVecCandidate;
+
+ for (int i=0; i<4; i++) {
+ CVector curPlaneNormal = colBoxPlaneNormal[i];
+ float minusGlobalCornerPos = dotProdCorrection[i];
+ float startVecDistToPlane = DotProduct(curPlaneNormal, startVecCandidate) + minusGlobalCornerPos;
+
+#define FRONT_OF_PLANE 1
+#define ON_THE_PLANE 0
+#define BEHIND_THE_PLANE -1
+
+ int8 startVecStatus;
+ int8 targetVecStatus;
+
+ if (startVecDistToPlane > 0.1f)
+ startVecStatus = FRONT_OF_PLANE;
+ else if (startVecDistToPlane < -0.1f)
+ startVecStatus = BEHIND_THE_PLANE;
+ else
+ startVecStatus = ON_THE_PLANE;
+
+ float targetVecDistToPlane = DotProduct(curPlaneNormal, targetVecCandidate) + minusGlobalCornerPos;
+ if (targetVecDistToPlane > 0.1f)
+ targetVecStatus = FRONT_OF_PLANE;
+ else if (targetVecDistToPlane < -0.1f)
+ targetVecStatus = BEHIND_THE_PLANE;
+ else
+ targetVecStatus = ON_THE_PLANE;
+
+
+ if (startVecStatus == BEHIND_THE_PLANE || targetVecStatus == BEHIND_THE_PLANE) {
+ if (startVecStatus == BEHIND_THE_PLANE && targetVecStatus == FRONT_OF_PLANE) {
+ targetVecCandidate = -(DotProduct(ourPos, curPlaneNormal) + minusGlobalCornerPos) / DotProduct(dirToGo, curPlaneNormal) * dirToGo + ourPos;
+
+ } else if (startVecStatus == FRONT_OF_PLANE && targetVecStatus == BEHIND_THE_PLANE) {
+ startVecCandidate = -(DotProduct(ourPos, curPlaneNormal) + minusGlobalCornerPos) / DotProduct(dirToGo, curPlaneNormal) * dirToGo + ourPos;
+ }
+ } else {
+ weReGoingGreat = true;
+ if (startVecStatus == ON_THE_PLANE)
+ startVecCandidate += (0.1f - startVecDistToPlane) * curPlaneNormal;
+
+ if (targetVecStatus == ON_THE_PLANE)
+ targetVecCandidate += (0.1f - targetVecDistToPlane) * curPlaneNormal;
+ }
+#undef FRONT_OF_PLANE
+#undef ON_THE_PLANE
+#undef BEHIND_THE_PLANE
+ }
+
+ if (!weReGoingGreat) {
+ CVector avgOfColPoints = (colCornerPos[0] + colCornerPos[1] + colCornerPos[2] + colCornerPos[3]) / 4.f;
+ float radius = 0.0f;
+
+ // Find radius of col box of the entity we follow
+ for (int i=0; i<4; i++) {
+ float cornerDist = (colCornerPos[i] - avgOfColPoints).MagnitudeSqr();
+
+ if (cornerDist > radius)
+ radius = cornerDist;
+ }
+ CColSphere followedEntSphere;
+ followedEntSphere.Set(Sqrt(radius) * 1.1f, avgOfColPoints, 0, 0);
+ CVector distToDest = m_followPathDestPos - GetPosition();
+ distToDest.z = 0.f;
+
+ if (distToDest.Magnitude() == 0.0f)
+ return false;
+
+ distToDest.Normalise();
+
+ // Entity we follow doesn't go toward destination anymore, abort the following.
+ if (!followedEntSphere.IntersectRay(GetPosition(), distToDest, startVecCandidate, targetVecCandidate)) {
+ m_pathNodeTimer = 0;
+ if (m_nPedState == PED_FOLLOW_PATH)
+ RestorePreviousState();
+
+ return false;
+ }
+ }
+
+ int lastPlaneBehindUs = -1;
+ int lastPlaneInFrontOfUs = -1;
+ CVector oldstartVecCandidate = startVecCandidate;
+ CVector oldDirToGo = targetVecCandidate - startVecCandidate;
+ oldDirToGo.Normalise();
+
+
+ // At least one plane should be between target and us.
+ for (int i=0; i<4; i++) {
+ CVector curPlaneNormal = colBoxPlaneNormal[i];
+ float minusGlobalCornerPos = dotProdCorrection[i];
+ float startVecDistToPlane = DotProduct(curPlaneNormal, startVecCandidate) + minusGlobalCornerPos;
+ float targetVecDistToPlane = DotProduct(curPlaneNormal, targetVecCandidate) + minusGlobalCornerPos;
+
+ if (startVecDistToPlane > 0.0f && targetVecDistToPlane < 0.0f) {
+ lastPlaneInFrontOfUs = i;
+ startVecCandidate = -(DotProduct(oldstartVecCandidate, curPlaneNormal) + minusGlobalCornerPos) / DotProduct(oldDirToGo, curPlaneNormal) * oldDirToGo + oldstartVecCandidate;
+
+ } else if (startVecDistToPlane < 0.0f && targetVecDistToPlane > 0.0f) {
+ lastPlaneBehindUs = i;
+ targetVecCandidate = -(DotProduct(oldstartVecCandidate, curPlaneNormal) + minusGlobalCornerPos) / DotProduct(oldDirToGo, curPlaneNormal) * oldDirToGo + oldstartVecCandidate;
+ }
+ }
+
+ CVector destsVariant1[5];
+ CVector destsVariant2[5];
+
+ // If not, followed entity diverged from route and we should abort the following.
+ if (lastPlaneBehindUs >= 0 && lastPlaneInFrontOfUs >= 0) {
+
+ int planeInFrontCircular = (lastPlaneInFrontOfUs + 4) % -4;
+ int planeInFrontCircularMinusOne = (lastPlaneInFrontOfUs + 3) % -4;
+ int planeInBehindCircular = (lastPlaneBehindUs + 4) % -4;
+ int planeInBehindCircularMinusOne = (lastPlaneBehindUs + 3) % -4;
+
+ destsVariant1[0] = GetPosition();
+ destsVariant1[1] = colCornerPos[planeInFrontCircularMinusOne];
+
+ int destsVar1LastNode = 2;
+ for(; planeInFrontCircularMinusOne != planeInBehindCircular; destsVar1LastNode++) {
+ planeInFrontCircularMinusOne = (planeInFrontCircularMinusOne + 3) % -4;
+ destsVariant1[destsVar1LastNode] = colCornerPos[planeInFrontCircularMinusOne];
+ }
+ destsVariant1[destsVar1LastNode] = m_followPathDestPos;
+
+ destsVariant2[0] = GetPosition();
+ destsVariant2[1] = colCornerPos[planeInFrontCircular];
+
+ int destsVar2LastNode = 2;
+ for (; planeInFrontCircular != planeInBehindCircularMinusOne; destsVar2LastNode++) {
+ planeInFrontCircular = (planeInFrontCircular + 5) % -4;
+ destsVariant2[destsVar2LastNode] = colCornerPos[planeInFrontCircular];
+ }
+ destsVariant2[destsVar2LastNode] = m_followPathDestPos;
+ CEntity *foundEnt1 = nil;
+ int dests1isOk = true;
+ int nodeToStopDestsVar1 = destsVar1LastNode + 1;
+ CVector avgOfColPoints2 = (colCornerPos[0] + colCornerPos[1] + colCornerPos[2] + colCornerPos[3]) / 4.f;
+
+ CVector prevDestVar1 = destsVariant1[0];
+
+ for (int i = 1; i < destsVar1LastNode + 1; i++) {
+ CVector *curDestVar1 = &destsVariant1[i];
+
+ CVector routeNormalHalf = *curDestVar1 - prevDestVar1;
+ routeNormalHalf.z = 0.f;
+ routeNormalHalf.Normalise();
+ routeNormalHalf *= 0.5f;
+
+ float oldX = -routeNormalHalf.x;
+ routeNormalHalf.z = 0.0f;
+ routeNormalHalf.x = routeNormalHalf.y;
+ routeNormalHalf.y = oldX;
+
+ if (DotProduct(*curDestVar1 - avgOfColPoints2, routeNormalHalf) < 0.0f)
+ routeNormalHalf *= -1.f;
+
+ CColPoint foundCol;
+ bool foundObstacle = CWorld::ProcessLineOfSight(prevDestVar1, *curDestVar1, foundCol, foundEnt1,
+ true, true, true, true, false, false, false, false);
+
+ if (!foundObstacle)
+ foundObstacle = CWorld::ProcessLineOfSight(prevDestVar1 + routeNormalHalf, *curDestVar1 + routeNormalHalf, foundCol, foundEnt1, true, true, true, true, false, false, false, false);
+
+ if (foundObstacle) {
+ if (foundEnt1 == m_followPathWalkAroundEnt || foundEnt1 == this || foundEnt1 == m_pSeekTarget) {
+ foundEnt1 = nil;
+
+ } else {
+ if (!foundEnt1->IsPed()) {
+ dests1isOk = false;
+ nodeToStopDestsVar1 = i;
+ break;
+ }
+ if (((CPed*)foundEnt1)->m_nPedState == PED_IDLE) {
+ dests1isOk = false;
+ nodeToStopDestsVar1 = i;
+ break;
+ }
+ if (DotProduct(*curDestVar1 - prevDestVar1, foundEnt1->GetForward()) < 0.f) {
+ dests1isOk = false;
+ nodeToStopDestsVar1 = i;
+ break;
+ }
+ if (((CPed*)foundEnt1)->m_pedInObjective == this) {
+ dests1isOk = false;
+ nodeToStopDestsVar1 = i;
+ break;
+ }
+ }
+ }
+ prevDestVar1 = *curDestVar1;
+ }
+ CEntity *foundEnt2 = nil;
+ int dests2isOk = true;
+ int nodeToStopDestsVar2 = destsVar2LastNode + 1;
+
+ CVector prevDestVar2 = destsVariant2[0];
+
+ for (int i = 1; i < destsVar2LastNode + 1; i++) {
+ CVector *curDestVar2 = &destsVariant2[i];
+
+ CVector routeNormalHalf = *curDestVar2 - prevDestVar2;
+ routeNormalHalf.z = 0.f;
+ routeNormalHalf.Normalise();
+ routeNormalHalf *= 0.5f;
+
+ float oldX = -routeNormalHalf.x;
+ routeNormalHalf.z = 0.0f;
+ routeNormalHalf.x = routeNormalHalf.y;
+ routeNormalHalf.y = oldX;
+
+ if (DotProduct(*curDestVar2 - avgOfColPoints2, routeNormalHalf) < 0.0f)
+ routeNormalHalf *= -1.f;
+
+ CColPoint foundCol;
+ bool foundObstacle = CWorld::ProcessLineOfSight(prevDestVar2, *curDestVar2, foundCol, foundEnt2,
+ true, true, true, true, false, false, false, false);
+
+ if (!foundObstacle)
+ foundObstacle = CWorld::ProcessLineOfSight(prevDestVar2 + routeNormalHalf, *curDestVar2 + routeNormalHalf, foundCol, foundEnt2, true, true, true, true, false, false, false, false);
+
+ if (foundObstacle) {
+ if (foundEnt2 == m_followPathWalkAroundEnt || foundEnt2 == this || foundEnt2 == m_pSeekTarget) {
+ foundEnt2 = 0;
+ } else {
+ if (!foundEnt2->IsPed()) {
+ dests2isOk = false;
+ nodeToStopDestsVar2 = i;
+ break;
+ }
+ if (((CPed*)foundEnt2)->m_nPedState == PED_IDLE) {
+ dests2isOk = false;
+ nodeToStopDestsVar2 = i;
+ break;
+ }
+ if (DotProduct(*curDestVar2 - prevDestVar2, foundEnt2->GetForward()) < 0.f) {
+ dests2isOk = false;
+ nodeToStopDestsVar2 = i;
+ break;
+ }
+ if (((CPed*)foundEnt2)->m_pedInObjective == this) {
+ dests2isOk = false;
+ nodeToStopDestsVar2 = i;
+ break;
+ }
+ }
+ }
+ prevDestVar2 = *curDestVar2;
+ }
+
+ float destTotalLengthVar1 = 0.0f;
+ for(int i=0; i < destsVar1LastNode; i++){
+ destTotalLengthVar1 += (destsVariant1[i + 1] - destsVariant1[i]).Magnitude();
+ }
+
+ float destTotalLengthVar2 = 0.0f;
+ for (int i = 0; i < destsVar2LastNode; i++) {
+ destTotalLengthVar2 += (destsVariant2[i + 1] - destsVariant2[i]).Magnitude();
+ }
+
+ int destVariantToUse;
+ if (dests1isOk && dests2isOk) {
+ if (destTotalLengthVar1 < destTotalLengthVar2)
+ destVariantToUse = 1;
+ else
+ destVariantToUse = 2;
+
+ } else if (dests1isOk) {
+ destVariantToUse = 1;
+
+ } else if (dests2isOk) {
+ destVariantToUse = 2;
+
+ } else if (nodeToStopDestsVar1 == 1 && nodeToStopDestsVar2 > 1) {
+ destVariantToUse = 2;
+
+ } else if (nodeToStopDestsVar1 > 1 && nodeToStopDestsVar2 == 1) {
+ destVariantToUse = 1;
+
+ } else if (foundEnt1 == foundEnt2) {
+ if (destTotalLengthVar1 < destTotalLengthVar2)
+ destVariantToUse = 1;
+ else
+ destVariantToUse = 2;
+
+ } else if (foundEnt1->GetColModel()->boundingSphere.radius >= foundEnt2->GetColModel()->boundingSphere.radius) {
+ destVariantToUse = 2;
+ } else {
+ destVariantToUse = 1;
+ }
+
+ if (destVariantToUse == 1) {
+ ClearFollowPath();
+ for (int i = 1; i < destsVar1LastNode; i++) {
+ CPathNode* nextNode = &m_pathNodeObjPool[m_nNumPathNodes];
+ nextNode->SetPosition(destsVariant1[i]);
+ m_pathNodesToGo[m_nNumPathNodes++] = nextNode;
+ }
+ } else if (destVariantToUse == 2) {
+ ClearFollowPath();
+ for (int i = 1; i < destsVar2LastNode; i++) {
+ CPathNode *nextNode = &m_pathNodeObjPool[m_nNumPathNodes];
+ nextNode->SetPosition(destsVariant2[i]);
+ m_pathNodesToGo[m_nNumPathNodes++] = nextNode;
+ }
+ }
+ if (m_nNumPathNodes != 0) {
+ PedState oldLastState = m_nLastPedState;
+ m_nLastPedState = PED_NONE;
+ SetStoredState();
+ if (m_nLastPedState == PED_NONE)
+ m_nLastPedState = oldLastState;
+
+ m_nPedState = PED_FOLLOW_PATH;
+ m_nMoveState = m_followPathMoveState;
+ return true;
+
+ } else {
+ m_pathNodeTimer = 0;
+ if (m_nPedState == PED_FOLLOW_PATH)
+ RestorePreviousState();
+
+ return false;
+ }
+ } else {
+ m_pathNodeTimer = 0;
+ if (m_nPedState == PED_FOLLOW_PATH)
+ RestorePreviousState();
+
+ return false;
+ }
}
void
@@ -17217,6 +17963,7 @@ CPed::SeekCar(void)
}
}
+// --MIAMI: Done
void
CPed::StartFightDefend(uint8 direction, uint8 hitLevel, uint8 unk)
{
@@ -17257,13 +18004,9 @@ CPed::StartFightDefend(uint8 direction, uint8 hitLevel, uint8 unk)
} 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:
@@ -17291,22 +18034,6 @@ CPed::StartFightDefend(uint8 direction, uint8 hitLevel, uint8 unk)
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) {
@@ -17349,7 +18076,6 @@ CPed::StartFightDefend(uint8 direction, uint8 hitLevel, uint8 unk)
hitAssoc->SetRun();
hitAssoc->flags |= ASSOC_FADEOUTWHENDONE;
}
-#endif
}
Say(SOUND_PED_DEFEND);
} else {
@@ -17359,20 +18085,15 @@ CPed::StartFightDefend(uint8 direction, uint8 hitLevel, uint8 unk)
m_lastFightMove = FIGHTMOVE_HITONFLOOR;
break;
case HITLEVEL_LOW:
-#ifndef VC_PED_PORTS
- if (direction == 2) {
- CPed::SetFall(1000, ANIM_KO_SKID_BACK, false);
- return;
- }
-#else
if (direction == 2 && (!IsPlayer() || ((CGeneral::GetRandomNumber() & 1) && m_fHealth < 30.0f))) {
- CPed::SetFall(1000, ANIM_KO_SKID_BACK, false);
+ SetFall(1000, ANIM_KO_SKID_BACK, false);
+ Say(SOUND_PED_DEFEND);
return;
} else if (direction != 2 && !IsPlayer() && (CGeneral::GetRandomNumber() & 1) && m_fHealth < 30.0f) {
- CPed::SetFall(1000, ANIM_KO_SHOT_STOM, false);
+ SetFall(1000, ANIM_KO_SHOT_STOM, false);
+ Say(SOUND_PED_DEFEND);
return;
}
-#endif
m_lastFightMove = FIGHTMOVE_HITBODY;
break;
case HITLEVEL_HIGH:
@@ -17422,24 +18143,28 @@ CPed::StartFightDefend(uint8 direction, uint8 hitLevel, uint8 unk)
moveAssoc->SetCurrentTime(0.0f);
moveAssoc->SetFinishCallback(FinishFightMoveCB, this);
if (IsPlayer())
- moveAssoc->speed = 1.3f;
+ moveAssoc->speed = 1.2f;
m_takeAStepAfterAttack = 0;
m_fightButtonPressure = 0;
- } else if (IsPlayer() && m_currentWeapon != WEAPONTYPE_UNARMED) {
+
+ } else if (IsPlayer() && GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED && GetWeapon()->m_eWeaponType != WEAPONTYPE_BRASSKNUCKLE &&
+ !CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_bFightMode) {
CAnimBlendAssociation *moveAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_lastFightMove].animId, 4.0f);
moveAssoc->SetCurrentTime(0.0f);
- moveAssoc->speed = 1.3f;
+ moveAssoc->speed = 1.2f;
+
} else {
if (m_nPedState != PED_AIM_GUN && m_nPedState != PED_ATTACK)
SetStoredState();
if (m_nWaitState != WAITSTATE_FALSE) {
- m_nWaitState = WAITSTATE_FALSE;
+ ClearWaitState();
RestoreHeadingRate();
}
- m_nPedState = PED_FIGHT;
+ SetPedState(PED_FIGHT);
m_fightButtonPressure = 0;
+ m_lastHitState = 2;
RpAnimBlendClumpRemoveAssociations(GetClump(), ASSOC_REPEAT);
CAnimBlendAssociation *walkStartAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WALK_START);
if (walkStartAssoc) {
@@ -17456,13 +18181,28 @@ CPed::StartFightDefend(uint8 direction, uint8 hitLevel, uint8 unk)
}
SetMoveState(PEDMOVE_NONE);
m_nStoredMoveState = PEDMOVE_NONE;
- CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT_IDLE)->blendAmount = 1.0f;
+ CAnimBlendAssociation *fightIdleAssoc;
+
+ if (GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED) {
+ CWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
+ if (GetFightIdleWithMeleeAnim(weaponInfo)) {
+ fightIdleAssoc = CAnimManager::AddAnimation(GetClump(), weaponInfo->m_AnimToPlay, GetFightIdleWithMeleeAnim(weaponInfo));
+ } else {
+ fightIdleAssoc = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT_IDLE);
+ }
+ } else {
+ fightIdleAssoc = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT_IDLE);
+ }
+ fightIdleAssoc->blendAmount = 1.0f;
CAnimBlendAssociation *moveAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_lastFightMove].animId, 8.0f);
moveAssoc->SetFinishCallback(FinishFightMoveCB, this);
m_fightState = FIGHTSTATE_NO_MOVE;
m_takeAStepAfterAttack = false;
bIsAttacking = true;
}
+
+ if (m_pedInObjective && m_pedInObjective->IsPlayer() && !IsPlayer())
+ ((CPlayerPed*)m_pedInObjective)->RemovePedFromMeleeList(this);
}
}
}
@@ -18948,11 +19688,11 @@ CPed::RequestDelayedWeapon()
void
CPed::ClearFollowPath()
{
- for (int i = 0; i < ARRAY_SIZE(m_pPathNodesStates); i++) {
- m_pPathNodesStates[i] = nil;
+ for (int i = 0; i < ARRAY_SIZE(m_pathNodesToGo); i++) {
+ m_pathNodesToGo[i] = nil;
}
- m_nPathNodes = 0;
- m_nCurPathNode = 0;
+ m_nNumPathNodes = 0;
+ m_nCurPathNodeId = 0;
}
// --MIAMI: Done
@@ -19309,7 +20049,7 @@ CPed::DriveVehicle(void)
(0.0f == bike->m_aWheelTimer[2] && 0.0f == bike->m_aWheelTimer[3])) {
if (0.0f == bike->m_aWheelTimer[2] && 0.0f == bike->m_aWheelTimer[3] &&
- (bike->GetForward().y < 0.0f && (bike->m_aWheelTimer[0] != 0.0f || bike->m_aWheelTimer[1] != 0.0f))) {
+ (bike->GetForward().z < 0.0f && (bike->m_aWheelTimer[0] != 0.0f || bike->m_aWheelTimer[1] != 0.0f))) {
stoppieAng = bike->pBikeHandling->fStoppieAng;
if (stoppieAng - bike->GetForward().z > 0.6f * stoppieAng)
diff --git a/src/peds/Ped.h b/src/peds/Ped.h
index f1a0a45f..a268d912 100644
--- a/src/peds/Ped.h
+++ b/src/peds/Ped.h
@@ -10,11 +10,11 @@
#include "Weapon.h"
#include "WeaponInfo.h"
#include "AnimationId.h"
+#include "PathFind.h"
#define FEET_OFFSET 1.04f
#define CHECK_NEARBY_THINGS_MAX_DIST 15.0f
-struct CPathNode;
class CAccident;
class CObject;
class CFire;
@@ -346,6 +346,9 @@ enum eMoveState {
PEDMOVE_NONE,
PEDMOVE_STILL,
PEDMOVE_WALK,
+
+ PEDMOVE_UNK,
+
PEDMOVE_RUN,
PEDMOVE_SPRINT,
};
@@ -521,13 +524,20 @@ public:
int32 m_nPrevMoveState;
eWaitState m_nWaitState;
uint32 m_nWaitTimer;
- void *m_pPathNodesStates[8]; // unused, probably leftover from VC
- CVector2D m_stPathNodeStates[10];
- uint16 m_nPathNodes;
- int16 m_nCurPathNode;
- int8 m_nPathDir;
- CPathNode *m_pLastPathNode;
- CPathNode *m_pNextPathNode;
+ CPathNode* m_pathNodesToGo[8];
+ int16 m_nNumPathNodes;
+ int16 m_nCurPathNodeId;
+ CEntity* m_followPathWalkAroundEnt;
+ CEntity* m_followPathTargetEnt;
+ uint32 m_pathNodeTimer;
+ CPathNode m_pathNodeObjPool[8];
+ CPathNode* m_pCurPathNode;
+ char m_nPathDir;
+ CPathNode* m_pLastPathNode;
+ CPathNode* m_pNextPathNode;
+ CVector m_followPathDestPos;
+ float m_followPathAbortDist;
+ eMoveState m_followPathMoveState;
float m_fHealth;
float m_fArmour;
uint32 m_nExtendedRangeTimer;
@@ -584,6 +594,7 @@ public:
CEntity *m_pPointGunAt;
CVector m_vecHitLastPos;
uint32 m_lastFightMove;
+ uint32 m_lastHitState; // TODO(Miami): What's this?
uint8 m_fightButtonPressure;
FightState m_fightState;
bool m_takeAStepAfterAttack;
@@ -746,7 +757,8 @@ public:
void SetAttack(CEntity*);
void StartFightAttack(uint8);
void SetWaitState(eWaitState, void*);
- bool FightStrike(CVector&);
+ bool FightStrike(CVector&, bool);
+ void FightHitPed(CPed*, CVector&, CVector&, int16);
int GetLocalDirection(const CVector2D &);
void StartFightDefend(uint8, uint8, uint8);
void PlayHitSound(CPed*);
@@ -756,6 +768,7 @@ public:
void RemoveInCarAnims(void);
void CollideWithPed(CPed*);
void SetDirectionToWalkAroundObject(CEntity*);
+ bool SetDirectionToWalkAroundVehicle(CVehicle*);
void RemoveWeaponAnims(int, float);
void CreateDeadPedMoney(void);
void CreateDeadPedWeaponPickups(void);
@@ -778,7 +791,7 @@ public:
bool FindBestCoordsFromNodes(CVector, CVector*);
void Wait(void);
void ProcessObjective(void);
- bool SeekFollowingPath(CVector*);
+ CVector *SeekFollowingPath(void);
void Flee(void);
void FollowPath(void);
CVector GetFormationPosition(void);
@@ -1009,6 +1022,13 @@ public:
else
return (AnimationId)0;
}
+
+ static AnimationId GetFightIdleWithMeleeAnim(CWeaponInfo* weapon) {
+ if (!!weapon->m_bFightMode)
+ return ANIM_MELEE_IDLE_FIGHTMODE;
+ else
+ return (AnimationId)0;
+ }
// --
// My additions, because there were many, many instances of that.
diff --git a/src/peds/PedChat.cpp b/src/peds/PedChat.cpp
index 78302844..ee639a50 100644
--- a/src/peds/PedChat.cpp
+++ b/src/peds/PedChat.cpp
@@ -4,47 +4,65 @@
#include "General.h"
#include "Ped.h"
+// --MIAMI: Done
// Corresponds to ped sounds (from SOUND_PED_DEATH to SOUND_PED_TAXI_CALL)
-PedAudioData CommentWaitTime[39] = {
- {500, 800, 500, 2},
- {500, 800, 500, 2},
- {500, 800, 500, 2},
- {500, 800, 500, 2},
- {100, 2, 100, 2},
- {700, 500, 1000, 500},
- {700, 500, 1000, 500},
- {5000, 2000, 15000, 3000},
- {5000, 2000, 15000, 3000},
- {5000, 2000, 15000, 3000},
- {6000, 6000, 6000, 6000},
- {1000, 1000, 2000, 2000},
- {1000, 500, 2000, 1500},
- {1000, 500, 2000, 1500},
- {800, 200, 1000, 500},
- {800, 200, 1000, 500},
- {800, 400, 2000, 1000},
- {800, 400, 2000, 1000},
- {400, 300, 2000, 1000},
- {2000, 1000, 2500, 1500},
- {200, 200, 200, 200},
- {6000, 3000, 5000, 6000},
- {6000, 3000, 9000, 5000},
- {6000, 3000, 9000, 5000},
- {6000, 3000, 9000, 5000},
- {400, 300, 4000, 1000},
- {400, 300, 4000, 1000},
- {400, 300, 4000, 1000},
- {1000, 500, 3000, 1000},
- {1000, 500, 1000, 1000},
- {3000, 2000, 3000, 2000},
- {1000, 500, 3000, 6000},
- {1000, 500, 2000, 4000},
- {1000, 500, 2000, 5000},
- {1000, 500, 3000, 2000},
- {1600, 1000, 2000, 2000},
- {3000, 2000, 5000, 3000},
- {1000, 1000, 1000, 1000},
- {1000, 1000, 5000, 5000},
+PedAudioData CommentWaitTime[56] = {
+ { 500, 800, 500, 2 },
+ { 500, 800, 500, 2 },
+ { 500, 800, 500, 2 },
+ { 500, 800, 500, 2 },
+ { 100, 2, 100, 2 },
+ { 500, 500, 2000, 1000 },
+ { 2000, 50, 2050, 1000 },
+ { 5000, 2000, 7000, 3000 },
+ { 5000, 2000, 7000, 3000 },
+ { 300, 200, 500, 200 },
+ { 3000, 1000, 4000, 1000 },
+ { 6000, 6000, 6000, 6000 },
+ { 4000, 1000, 5000, 1000 },
+ { 3000, 1000, 4000, 1000 },
+ { 1000, 1000, 2000, 2000 },
+ { 1000, 500, 2000, 1500 },
+ { 1700, 1000, 3000, 1000 },
+ { 800, 200, 1000, 500 },
+ { 800, 200, 1000, 500 },
+ { 800, 400, 2000, 1000 },
+ { 800, 400, 2000, 1000 },
+ { 2000, 2000, 4000, 4000 },
+ { 2000, 2000, 4000, 1000 },
+ { 4000, 1000, 5000, 1000 },
+ { 800, 400, 1200, 500 },
+ { 5000, 1000, 6000, 2000 },
+ { 5000, 1000, 6000, 2000 },
+ { 5000, 1000, 6000, 2000 },
+ { 5000, 1000, 6000, 2000 },
+ { 5000, 1000, 6000, 2000 },
+ { 5000, 1000, 6000, 2000 },
+ { 5000, 1000, 6000, 2000 },
+ { 4000, 2000, 7000, 2000 },
+ { 1000, 300, 2000, 1000 },
+ { 1500, 1000, 2500, 1000 },
+ { 200, 200, 200, 200 },
+ { 2000, 1000, 4000, 1000 },
+ { 2000, 1000, 4000, 1000 },
+ { 1000, 500, 3000, 1000 },
+ { 1000, 500, 1000, 1000 },
+ { 3000, 2000, 5000, 1000 },
+ { 3000, 2000, 5000, 1000 },
+ { 3000, 2000, 3000, 2000 },
+ { 2000, 1000, 3000, 1000 },
+ { 2500, 1000, 5000, 5000 },
+ { 2000, 1000, 3000, 2000 },
+ { 4000, 1000, 5000, 1000 },
+ { 1000, 500, 2000, 4000 },
+ { 1000, 500, 2000, 5000 },
+ { 2000, 500, 2500, 500 },
+ { 1000, 500, 3000, 2000 },
+ { 1600, 1000, 2000, 2000 },
+ { 2000, 1000, 4000, 2000 },
+ { 1500, 1000, 2500, 1000 },
+ { 1000, 1000, 5000, 5000 },
+ { 0, 0, 0, 0 }
};
// --MIAMI: Done
@@ -54,7 +72,7 @@ CPed::ServiceTalkingWhenDead(void)
return m_queuedSound == SOUND_PED_DEATH;
}
-// --MIAMI: Done except ifdef
+// --MIAMI: Done
void
CPed::ServiceTalking(void)
{
@@ -84,7 +102,7 @@ CPed::ServiceTalking(void)
}
}
-// --MIAMI: Done except ifdef
+// --MIAMI: Done
void
CPed::Say(uint16 audio)
{
diff --git a/src/peds/PedIK.h b/src/peds/PedIK.h
index ee719fea..7dcf0ef3 100644
--- a/src/peds/PedIK.h
+++ b/src/peds/PedIK.h
@@ -52,6 +52,7 @@ public:
bool PointGunInDirectionUsingArm(float targetYaw, float targetPitch);
bool PointGunAtPosition(CVector const& position);
void GetComponentPosition(RwV3d &pos, uint32 node);
+ void GetComponentPosition(CVector &pos, uint32 node) { GetComponentPosition(*(RwV3d*)pos, node); }
void RotateTorso(AnimBlendFrameData* animBlend, LimbOrientation* limb, bool changeRoll);
void ExtractYawAndPitchLocal(RwMatrix *mat, float *yaw, float *pitch);
void ExtractYawAndPitchLocalSkinned(AnimBlendFrameData *node, float *yaw, float *pitch);
diff --git a/src/peds/PlayerPed.cpp b/src/peds/PlayerPed.cpp
index 08f79c7e..ee6891c7 100644
--- a/src/peds/PlayerPed.cpp
+++ b/src/peds/PlayerPed.cpp
@@ -81,7 +81,7 @@ CPlayerPed::CPlayerPed(void) : CPed(PEDTYPE_PLAYER1)
for (int i = 0; i < 6; i++) {
m_vecSafePos[i] = CVector(0.0f, 0.0f, 0.0f);
m_pPedAtSafePos[i] = nil;
- m_pCheckPlayers[i] = nil;
+ m_pMeleeList[i] = nil;
}
m_nCheckPlayersIndex = 0;
m_nPadUpPressedInMilliseconds = 0;
@@ -1711,6 +1711,18 @@ CPlayerPed::PlayIdleAnimations(CPad *padUsed)
}
}
+void
+CPlayerPed::RemovePedFromMeleeList(CPed *ped)
+{
+ int i = 0;
+ for (; m_pMeleeList[i] != ped; i++) {
+ if (i >= ARRAY_SIZE(m_pMeleeList))
+ return;
+ }
+ m_pMeleeList[i] = nil;
+ ped->m_attackTimer = 0;
+}
+
#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/PlayerPed.h b/src/peds/PlayerPed.h
index cc56af9f..7ff95ff3 100644
--- a/src/peds/PlayerPed.h
+++ b/src/peds/PlayerPed.h
@@ -34,7 +34,7 @@ public:
bool m_bDrunkVisualsWearOff; // TODO(Miami): That may be something else
CVector m_vecSafePos[6]; // safe places from the player, for example behind a tree
CPed *m_pPedAtSafePos[6];
- CPlayerPed* m_pCheckPlayers[6]; //checks something with players, could be a leftover from original multiplayer
+ CPlayerPed* m_pMeleeList[6];
char unused1;
int16 m_nCheckPlayersIndex;
float m_fWalkAngle; //angle between heading and walking direction
@@ -84,6 +84,7 @@ public:
void PlayerControlZelda(CPad*);
bool DoesPlayerWantNewWeapon(eWeaponType, bool);
void PlayIdleAnimations(CPad*);
+ void RemovePedFromMeleeList(CPed*);
static void SetupPlayerPed(int32);
static void DeactivatePlayerPed(int32);