summaryrefslogtreecommitdiffstats
path: root/src/peds
diff options
context:
space:
mode:
Diffstat (limited to 'src/peds')
-rw-r--r--src/peds/CivilianPed.cpp2
-rw-r--r--src/peds/CopPed.cpp289
-rw-r--r--src/peds/CopPed.h5
-rw-r--r--src/peds/EmergencyPed.cpp2
-rw-r--r--src/peds/Ped.cpp14
-rw-r--r--src/peds/PlayerPed.cpp2
-rw-r--r--src/peds/Population.cpp2
7 files changed, 306 insertions, 10 deletions
diff --git a/src/peds/CivilianPed.cpp b/src/peds/CivilianPed.cpp
index bb61e086..2e6166be 100644
--- a/src/peds/CivilianPed.cpp
+++ b/src/peds/CivilianPed.cpp
@@ -377,6 +377,8 @@ CCivilianPed::ProcessControl(void)
Avoid();
}
+#include <new>
+
class CCivilianPed_ : public CCivilianPed
{
public:
diff --git a/src/peds/CopPed.cpp b/src/peds/CopPed.cpp
index 53ae1747..94acac05 100644
--- a/src/peds/CopPed.cpp
+++ b/src/peds/CopPed.cpp
@@ -7,8 +7,11 @@
#include "Vehicle.h"
#include "RpAnimBlend.h"
#include "General.h"
+#include "ZoneCull.h"
+#include "PathFind.h"
+#include "RoadBlocks.h"
-WRAPPER void CCopPed::ProcessControl() { EAXJMP(0x4C1400); }
+WRAPPER void CCopPed::ProcessControl() { EAXJMP(0x4C1400); }
CCopPed::CCopPed(eCopType copType) : CPed(PEDTYPE_COP)
{
@@ -58,11 +61,16 @@ CCopPed::CCopPed(eCopType copType) : CPed(PEDTYPE_COP)
m_bIsDisabledCop = false;
field_1356 = 0;
m_attackTimer = 0;
- field_1351 = 0;
+ m_bBeatingSuspect = false;
m_bZoneDisabledButClose = false;
m_bZoneDisabled = false;
field_1364 = -1;
m_pPointGunAt = nil;
+
+ // VC also initializes in here, but it keeps object
+#ifdef FIX_BUGS
+ m_wRoadblockNode = -1;
+#endif
}
CCopPed::~CCopPed()
@@ -181,15 +189,15 @@ CCopPed::ClearPursuit(void)
}
}
-// TO-DO: m_MaxCops in for loop may be a bug, check it out after CopAI
+// TODO: I don't know why they needed that parameter.
void
-CCopPed::SetPursuit(bool iMayAlreadyBeInPursuit)
+CCopPed::SetPursuit(bool ignoreCopLimit)
{
CWanted *wanted = FindPlayerPed()->m_pWanted;
if (m_bIsInPursuit || !IsPedInControl())
return;
- if (wanted->m_CurrentCops < wanted->m_MaxCops || iMayAlreadyBeInPursuit) {
+ if (wanted->m_CurrentCops < wanted->m_MaxCops || ignoreCopLimit) {
for (int i = 0; i < wanted->m_MaxCops; ++i) {
if (!wanted->m_pCops[i]) {
m_bIsInPursuit = true;
@@ -275,6 +283,276 @@ CCopPed::ScanForCrimes(void)
}
}
+void
+CCopPed::CopAI(void)
+{
+ CWanted *wanted = FindPlayerPed()->m_pWanted;
+ int wantedLevel = wanted->m_nWantedLevel;
+ CPhysical *playerOrHisVeh = FindPlayerVehicle() ? (CPhysical*)FindPlayerVehicle() : (CPhysical*)FindPlayerPed();
+
+ if (wanted->m_bIgnoredByEveryone || wanted->m_bIgnoredByCops) {
+ if (m_nPedState != PED_ARREST_PLAYER)
+ ClearPursuit();
+
+ return;
+ }
+ if (CCullZones::NoPolice() && m_bIsInPursuit && !m_bIsDisabledCop) {
+ if (bHitSomethingLastFrame) {
+ m_bZoneDisabled = true;
+ m_bIsDisabledCop = true;
+#ifdef FIX_BUGS
+ m_wRoadblockNode = -1;
+#else
+ m_wRoadblockNode = 0;
+#endif
+ bKindaStayInSamePlace = true;
+ bIsRunning = false;
+ bNotAllowedToDuck = false;
+ bCrouchWhenShooting = false;
+ SetIdle();
+ ClearObjective();
+ ClearPursuit();
+ m_prevObjective = OBJECTIVE_NONE;
+ m_nLastPedState = PED_NONE;
+ SetAttackTimer(0);
+ if (m_fDistanceToTarget > 15.0f)
+ m_bZoneDisabledButClose = true;
+ }
+ } else if (m_bZoneDisabled && !CCullZones::NoPolice()) {
+ m_bZoneDisabled = false;
+ m_bIsDisabledCop = false;
+ m_bZoneDisabledButClose = false;
+ bKindaStayInSamePlace = false;
+ bCrouchWhenShooting = false;
+ bDuckAndCover = false;
+ ClearPursuit();
+ }
+ if (wantedLevel > 0) {
+ if (!m_bIsDisabledCop) {
+ if (!m_bIsInPursuit || wanted->m_CurrentCops > wanted->m_MaxCops) {
+ CCopPed *copFarthestToTarget = nil;
+ float copFarthestToTargetDist = m_fDistanceToTarget;
+
+ int oldCopNum = wanted->m_CurrentCops;
+ int maxCops = wanted->m_MaxCops;
+
+ for (int i = 0; i < max(maxCops, oldCopNum); i++) {
+ CCopPed *cop = wanted->m_pCops[i];
+ if (cop && cop->m_fDistanceToTarget > copFarthestToTargetDist) {
+ copFarthestToTargetDist = cop->m_fDistanceToTarget;
+ copFarthestToTarget = wanted->m_pCops[i];
+ }
+ }
+
+ if (m_bIsInPursuit) {
+ if (copFarthestToTarget && oldCopNum > maxCops) {
+ if (copFarthestToTarget == this && m_fDistanceToTarget > 10.0f) {
+ ClearPursuit();
+ } else if(copFarthestToTargetDist > 10.0f)
+ copFarthestToTarget->ClearPursuit();
+ }
+ } else {
+ if (oldCopNum < maxCops) {
+ SetPursuit(true);
+ } else {
+ if (m_fDistanceToTarget <= 10.0f || copFarthestToTarget && m_fDistanceToTarget < copFarthestToTargetDist) {
+ if (copFarthestToTarget && copFarthestToTargetDist > 10.0f)
+ copFarthestToTarget->ClearPursuit();
+
+ SetPursuit(true);
+ }
+ }
+ }
+ } else
+ SetPursuit(false);
+
+ if (!m_bIsInPursuit)
+ return;
+
+ if (wantedLevel > 1 && GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED)
+ SetCurrentWeapon(WEAPONTYPE_COLT45);
+ else if (wantedLevel == 1 && GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED && !FindPlayerPed()->m_pCurrentPhysSurface) {
+ // i.e. if player is on top of car, cop will still use colt45.
+ SetCurrentWeapon(WEAPONTYPE_UNARMED);
+ }
+
+ if (FindPlayerVehicle()) {
+ if (m_bBeatingSuspect) {
+ --wanted->m_CopsBeatingSuspect;
+ m_bBeatingSuspect = false;
+ }
+ if (m_fDistanceToTarget * FindPlayerSpeed().Magnitude() > 4.0f)
+ ClearPursuit();
+ }
+ return;
+ }
+ float weaponRange = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_fRange;
+ SetLookFlag(playerOrHisVeh, true);
+ TurnBody();
+ SetCurrentWeapon(WEAPONTYPE_COLT45);
+ if (!bIsDucking) {
+ if (m_attackTimer >= CTimer::GetTimeInMilliseconds()) {
+ if (m_nPedState != PED_ATTACK && m_nPedState != PED_FIGHT && !m_bZoneDisabled) {
+ CVector targetDist = playerOrHisVeh->GetPosition() - GetPosition();
+ if (m_fDistanceToTarget > 30.0f) {
+ CAnimBlendAssociation* crouchShootAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_RBLOCK_CSHOOT);
+ if (crouchShootAssoc)
+ crouchShootAssoc->blendDelta = -1000.0f;
+
+ // Target is coming onto us
+ if (DotProduct(playerOrHisVeh->m_vecMoveSpeed, targetDist) > 0.0f) {
+ m_bIsDisabledCop = false;
+ bKindaStayInSamePlace = false;
+ bNotAllowedToDuck = false;
+ bDuckAndCover = false;
+ SetPursuit(false);
+ SetObjective(OBJECTIVE_KILL_CHAR_ANY_MEANS, FindPlayerPed());
+ }
+ } else if (m_fDistanceToTarget < 5.0f
+ && (!FindPlayerVehicle() || FindPlayerVehicle()->m_vecMoveSpeed.MagnitudeSqr() < sq(1.f/200.f))) {
+ m_bIsDisabledCop = false;
+ bKindaStayInSamePlace = false;
+ bNotAllowedToDuck = false;
+ bDuckAndCover = false;
+ } else {
+ // VC checks for != nil compared to buggy behaviour of III. I check for != -1 here.
+#ifdef VC_PED_PORTS
+ float dotProd;
+ if (m_wRoadblockNode != -1) {
+ CTreadable *roadBlockRoad = ThePaths.m_mapObjects[CRoadBlocks::RoadBlockObjects[m_wRoadblockNode]];
+ dotProd = DotProduct2D(playerOrHisVeh->GetPosition() - roadBlockRoad->GetPosition(), GetPosition() - roadBlockRoad->GetPosition());
+ } else
+ dotProd = -1.0f;
+
+ if(dotProd >= 0.0f) {
+#else
+
+#ifndef FIX_BUGS
+ float copRoadDotProd, targetRoadDotProd;
+#else
+ float copRoadDotProd = 1.0f, targetRoadDotProd = 1.0f;
+ if (m_wRoadblockNode != -1)
+#endif
+ {
+ CTreadable* roadBlockRoad = ThePaths.m_mapObjects[CRoadBlocks::RoadBlockObjects[m_wRoadblockNode]];
+ CVector2D roadFwd = roadBlockRoad->GetForward();
+ copRoadDotProd = DotProduct2D(GetPosition() - roadBlockRoad->GetPosition(), roadFwd);
+ targetRoadDotProd = DotProduct2D(playerOrHisVeh->GetPosition() - roadBlockRoad->GetPosition(), roadFwd);
+ }
+ // Roadblock may be towards road's fwd or opposite, so check both
+ if ((copRoadDotProd >= 0.0f || targetRoadDotProd >= 0.0f)
+ && (copRoadDotProd <= 0.0f || targetRoadDotProd <= 0.0f)) {
+#endif
+ bIsPointingGunAt = true;
+ } else {
+ m_bIsDisabledCop = false;
+ bKindaStayInSamePlace = false;
+ bNotAllowedToDuck = false;
+ bCrouchWhenShooting = false;
+ bIsDucking = false;
+ bDuckAndCover = false;
+ SetPursuit(false);
+ }
+ }
+ }
+ } else {
+ if (m_fDistanceToTarget < weaponRange) {
+ CWeaponInfo *weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
+ CVector gunPos = weaponInfo->m_vecFireOffset;
+ for (RwFrame *i = GetNodeFrame(PED_HANDR); i; i = RwFrameGetParent(i))
+ RwV3dTransformPoints((RwV3d*)&gunPos, (RwV3d*)&gunPos, 1, RwFrameGetMatrix(i));
+
+ CColPoint foundCol;
+ CEntity *foundEnt;
+ if (!CWorld::ProcessLineOfSight(gunPos, playerOrHisVeh->GetPosition(), foundCol, foundEnt,
+ false, true, false, false, true, false, false)
+ || foundEnt && foundEnt == playerOrHisVeh) {
+ m_pPointGunAt = playerOrHisVeh;
+ if (playerOrHisVeh)
+ playerOrHisVeh->RegisterReference((CEntity**) &m_pPointGunAt);
+
+ SetAttack(playerOrHisVeh);
+ SetShootTimer(CGeneral::GetRandomNumberInRange(500, 1000));
+ }
+ SetAttackTimer(CGeneral::GetRandomNumberInRange(100, 300));
+ }
+ SetMoveState(PEDMOVE_STILL);
+ }
+ }
+ } else {
+ if (!m_bIsDisabledCop || m_bZoneDisabled) {
+ if (m_nPedState != PED_AIM_GUN) {
+ if (m_bIsInPursuit)
+ ClearPursuit();
+
+ if (IsPedInControl()) {
+ // Entering the vehicle
+ if (m_pMyVehicle && !bInVehicle) {
+ if (m_pMyVehicle->IsLawEnforcementVehicle()) {
+ if (m_pMyVehicle->pDriver) {
+ if (m_pMyVehicle->pDriver->m_nPedType == PEDTYPE_COP) {
+ if (m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER)
+ SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, m_pMyVehicle);
+ } else if (m_pMyVehicle->pDriver->IsPlayer()) {
+ FindPlayerPed()->SetWantedLevelNoDrop(1);
+ }
+ } else if (m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER) {
+ SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, m_pMyVehicle);
+ }
+ } else {
+ m_pMyVehicle = nil;
+ ClearObjective();
+ SetWanderPath(CGeneral::GetRandomNumber() & 7);
+ }
+ }
+#ifdef VC_PED_PORTS
+ else {
+ if (m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT && CharCreatedBy == RANDOM_CHAR) {
+ for (int i = 0; i < m_numNearPeds; i++) {
+ CPed *nearPed = m_nearPeds[i];
+ if (nearPed->CharCreatedBy == RANDOM_CHAR) {
+ if ((nearPed->m_nPedType == PEDTYPE_CRIMINAL || nearPed->IsGangMember())
+ && nearPed->IsPedInControl()) {
+
+ bool anotherCopChasesHim = false;
+ if (nearPed->m_nPedState == PED_FLEE_ENTITY) {
+ if (nearPed->m_fleeFrom && nearPed->m_fleeFrom->IsPed() &&
+ ((CPed*)nearPed->m_fleeFrom)->m_nPedType == PEDTYPE_COP) {
+ anotherCopChasesHim = true;
+ }
+ }
+ if (!anotherCopChasesHim) {
+ SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, nearPed);
+ nearPed->SetObjective(OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE, this);
+ nearPed->m_ped_flagE2 = true;
+ return;
+ }
+ }
+ }
+ }
+ }
+ }
+#endif
+ }
+ }
+ } else {
+ if (m_bIsInPursuit && m_nPedState != PED_AIM_GUN)
+ ClearPursuit();
+
+ m_bIsDisabledCop = false;
+ bKindaStayInSamePlace = false;
+ bNotAllowedToDuck = false;
+ bCrouchWhenShooting = false;
+ bIsDucking = false;
+ bDuckAndCover = false;
+ if (m_pMyVehicle)
+ SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, m_pMyVehicle);
+ }
+ }
+}
+
+#include <new>
+
class CCopPed_ : public CCopPed
{
public:
@@ -290,4 +568,5 @@ STARTPATCHES
InjectHook(0x4C27D0, &CCopPed::SetPursuit, PATCH_JUMP);
InjectHook(0x4C2C90, &CCopPed::ArrestPlayer, PATCH_JUMP);
InjectHook(0x4C26A0, &CCopPed::ScanForCrimes, PATCH_JUMP);
+ InjectHook(0x4C1B50, &CCopPed::CopAI, PATCH_JUMP);
ENDPATCHES
diff --git a/src/peds/CopPed.h b/src/peds/CopPed.h
index 7705eb12..142be56a 100644
--- a/src/peds/CopPed.h
+++ b/src/peds/CopPed.h
@@ -17,9 +17,9 @@ public:
int8 field_1343;
float m_fDistanceToTarget;
int8 m_bIsInPursuit;
- int8 m_bIsDisabledCop;
+ int8 m_bIsDisabledCop; // What disabled cop actually is?
int8 field_1350;
- int8 field_1351;
+ bool m_bBeatingSuspect;
int8 m_bZoneDisabledButClose;
int8 m_bZoneDisabled;
int8 field_1354;
@@ -40,6 +40,7 @@ public:
void SetPursuit(bool);
void ArrestPlayer(void);
void ScanForCrimes(void);
+ void CopAI(void);
};
static_assert(sizeof(CCopPed) == 0x558, "CCopPed: error");
diff --git a/src/peds/EmergencyPed.cpp b/src/peds/EmergencyPed.cpp
index ee559f57..0d27a532 100644
--- a/src/peds/EmergencyPed.cpp
+++ b/src/peds/EmergencyPed.cpp
@@ -413,6 +413,8 @@ CEmergencyPed::MedicAI(void)
}
}
+#include <new>
+
class CEmergencyPed_ : public CEmergencyPed
{
public:
diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp
index db6b7ee2..05cac3a7 100644
--- a/src/peds/Ped.cpp
+++ b/src/peds/Ped.cpp
@@ -2720,6 +2720,10 @@ CPed::SetObjective(eObjective newObj, void *entity)
return;
}
+#ifdef VC_PED_PORTS
+ SetObjectiveTimer(0);
+ ClearPointGunAt();
+#endif
bObjectiveCompleted = false;
if (!IsTemporaryObjective(m_objective) || IsTemporaryObjective(newObj)) {
if (m_objective != newObj) {
@@ -3444,8 +3448,12 @@ CPed::ClearAll(void)
m_fleeFrom = nil;
m_fleeTimer = 0;
bUsesCollision = true;
+#ifdef VC_PED_PORTS
+ ClearPointGunAt();
+#else
ClearAimFlag();
ClearLookFlag();
+#endif
bIsPointingGunAt = false;
bRenderPedInCar = true;
bKnockedUpIntoAir = false;
@@ -12169,11 +12177,11 @@ CPed::PlacePedOnDryLand(void)
if (!CWorld::TestSphereAgainstWorld(potentialGround, 5.0f, nil, true, false, false, false, false, false))
return false;
- CVector potentialGroundDist = CWorld::ms_testSpherePoint.point - GetPosition();
+ CVector potentialGroundDist = gaTempSphereColPoints[0].point - GetPosition();
potentialGroundDist.z = 0.0f;
potentialGroundDist.Normalise();
- CVector posToCheck = 0.5f * potentialGroundDist + CWorld::ms_testSpherePoint.point;
+ 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, false)) {
@@ -17447,6 +17455,8 @@ CPed::SetExitBoat(CVehicle *boat)
CWaterLevel::FreeBoatWakeArray();
}
+#include <new>
+
class CPed_ : public CPed
{
public:
diff --git a/src/peds/PlayerPed.cpp b/src/peds/PlayerPed.cpp
index c6580d32..49d0183e 100644
--- a/src/peds/PlayerPed.cpp
+++ b/src/peds/PlayerPed.cpp
@@ -1414,6 +1414,8 @@ CPlayerPed::ProcessControl(void)
}
}
+#include <new>
+
class CPlayerPed_ : public CPlayerPed
{
public:
diff --git a/src/peds/Population.cpp b/src/peds/Population.cpp
index d87764ff..6b674dd3 100644
--- a/src/peds/Population.cpp
+++ b/src/peds/Population.cpp
@@ -576,7 +576,7 @@ CPopulation::AddToPopulation(float minDist, float maxDist, float minDistOffScree
}
// Yeah, float
float maxPossiblePedsForArea = (zoneInfo.pedDensity + zoneInfo.carDensity) * playerInfo->m_fRoadDensity * PedDensityMultiplier * CIniFile::PedNumberMultiplier;
- // maxPossiblePedsForArea = min(maxPossiblePedsForArea, MaxNumberOfPedsInUse);
+ maxPossiblePedsForArea = min(maxPossiblePedsForArea, MaxNumberOfPedsInUse);
if (ms_nTotalPeds < maxPossiblePedsForArea || addCop) {
int decisionThreshold = CGeneral::GetRandomNumberInRange(0, 1000);