summaryrefslogtreecommitdiffstats
path: root/src/peds/CopPed.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/peds/CopPed.cpp')
-rw-r--r--src/peds/CopPed.cpp216
1 files changed, 214 insertions, 2 deletions
diff --git a/src/peds/CopPed.cpp b/src/peds/CopPed.cpp
index 40481ad9..bf0cc59c 100644
--- a/src/peds/CopPed.cpp
+++ b/src/peds/CopPed.cpp
@@ -1,10 +1,14 @@
#include "common.h"
#include "patcher.h"
+#include "World.h"
+#include "PlayerPed.h"
#include "CopPed.h"
#include "ModelIndices.h"
+#include "Vehicle.h"
+#include "RpAnimBlend.h"
+#include "General.h"
WRAPPER void CCopPed::ProcessControl() { EAXJMP(0x4C1400); }
-WRAPPER void CCopPed::SetArrestPlayer(CPed*) { EAXJMP(0x4C2B00); }
CCopPed::CCopPed(eCopType copType) : CPed(PEDTYPE_COP)
{
@@ -66,7 +70,210 @@ CCopPed::~CCopPed()
ClearPursuit();
}
-WRAPPER void CCopPed::ClearPursuit(void) { EAXJMP(0x4C28C0); }
+// Parameter should always be CPlayerPed, but it seems they considered making civilians arrestable at some point
+void
+CCopPed::SetArrestPlayer(CPed *player)
+{
+ if (!IsPedInControl() || !player)
+ return;
+
+ switch (m_nCopType) {
+ case COP_FBI:
+ Say(SOUND_PED_ARREST_FBI);
+ break;
+ case COP_SWAT:
+ Say(SOUND_PED_ARREST_SWAT);
+ break;
+ default:
+ Say(SOUND_PED_ARREST_COP);
+ break;
+ }
+ if (player->EnteringCar()) {
+ if (CTimer::GetTimeInMilliseconds() > m_nPedStateTimer)
+ return;
+
+ // why?
+ player->bGonnaKillTheCarJacker = true;
+
+ // Genius
+ FindPlayerPed()->m_bCanBeDamaged = false;
+ ((CPlayerPed*)player)->m_pArrestingCop = this;
+ this->RegisterReference((CEntity**) &((CPlayerPed*)player)->m_pArrestingCop);
+
+ } else if (player->m_nPedState != PED_DIE && player->m_nPedState != PED_DEAD && player->m_nPedState != PED_ARRESTED) {
+ player->m_nLastPedState = player->m_nPedState;
+ player->m_nPedState = PED_ARRESTED;
+
+ FindPlayerPed()->m_bCanBeDamaged = false;
+ ((CPlayerPed*)player)->m_pArrestingCop = this;
+ this->RegisterReference((CEntity**) &((CPlayerPed*)player)->m_pArrestingCop);
+ }
+
+ m_nPedState = PED_ARREST_PLAYER;
+ SetObjective(OBJECTIVE_NONE);
+ m_prevObjective = OBJECTIVE_NONE;
+ bIsPointingGunAt = false;
+ m_pSeekTarget = player;
+ m_pSeekTarget->RegisterReference((CEntity**) &m_pSeekTarget);
+ SetCurrentWeapon(WEAPONTYPE_COLT45);
+ if (player->InVehicle()) {
+ player->m_pMyVehicle->m_nNumGettingIn = 0;
+ player->m_pMyVehicle->m_nGettingInFlags = 0;
+ player->m_pMyVehicle->bIsHandbrakeOn = true;
+ player->m_pMyVehicle->m_status = STATUS_PLAYER_DISABLED;
+ }
+ if (GetWeapon()->m_eWeaponType == WEAPONTYPE_UNARMED)
+ SetCurrentWeapon(WEAPONTYPE_COLT45);
+}
+
+void
+CCopPed::ClearPursuit(void)
+{
+ CPlayerPed *player = FindPlayerPed();
+ if (!player)
+ return;
+
+ CWanted *wanted = player->m_pWanted;
+ int ourCopId = 0;
+ bool foundMyself = false;
+ int biggestCopId = 0;
+ if (!m_bIsInPursuit)
+ return;
+
+ m_bIsInPursuit = false;
+ for (int i = 0; i < max(wanted->m_MaxCops, wanted->m_CurrentCops); ++i) {
+ if (!foundMyself && wanted->m_pCops[i] == this) {
+ wanted->m_pCops[i] = nil;
+ --wanted->m_CurrentCops;
+ foundMyself = true;
+ ourCopId = i;
+ biggestCopId = i;
+ } else {
+ if (wanted->m_pCops[i])
+ biggestCopId = i;
+ }
+ }
+ if (foundMyself && biggestCopId > ourCopId) {
+ wanted->m_pCops[ourCopId] = wanted->m_pCops[biggestCopId];
+ wanted->m_pCops[biggestCopId] = nil;
+ }
+ m_objective = OBJECTIVE_NONE;
+ m_prevObjective = OBJECTIVE_NONE;
+ m_nLastPedState = PED_NONE;
+ bIsRunning = false;
+ bNotAllowedToDuck = false;
+ bKindaStayInSamePlace = false;
+ m_bZoneDisabledButClose = false;
+ m_bZoneDisabled = false;
+ ClearObjective();
+ if (IsPedInControl()) {
+ if (!m_pMyVehicle || wanted->m_nWantedLevel != 0) {
+ if (m_pMyVehicle && (m_pMyVehicle->GetPosition() - GetPosition()).MagnitudeSqr() < sq(5.0f)) {
+ m_nLastPedState = PED_IDLE;
+ SetSeek((CEntity*)m_pMyVehicle, 2.5f);
+ } else {
+ m_nLastPedState = PED_WANDER_PATH;
+ SetFindPathAndFlee(FindPlayerPed()->GetPosition(), 10000, true);
+ }
+ } else {
+ SetObjective(OBJECTIVE_ENTER_CAR_AS_DRIVER, m_pMyVehicle);
+ }
+ }
+}
+
+// TO-DO: m_MaxCops in for loop may be a bug, check it out after CopAI
+void
+CCopPed::SetPursuit(bool iMayAlreadyBeInPursuit)
+{
+ CWanted *wanted = FindPlayerPed()->m_pWanted;
+ if (m_bIsInPursuit || !IsPedInControl())
+ return;
+
+ if (wanted->m_CurrentCops < wanted->m_MaxCops || iMayAlreadyBeInPursuit) {
+ for (int i = 0; i < wanted->m_MaxCops; ++i) {
+ if (!wanted->m_pCops[i]) {
+ m_bIsInPursuit = true;
+ ++wanted->m_CurrentCops;
+ wanted->m_pCops[i] = this;
+ break;
+ }
+ }
+ if (m_bIsInPursuit) {
+ ClearObjective();
+ m_prevObjective = OBJECTIVE_NONE;
+ SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, FindPlayerPed());
+ SetObjectiveTimer(0);
+ bNotAllowedToDuck = true;
+ bIsRunning = true;
+ m_bZoneDisabledButClose = false;
+ }
+ }
+}
+
+void
+CCopPed::ArrestPlayer(void)
+{
+ m_pVehicleAnim = nil;
+ CPed *suspect = (CPed*)m_pSeekTarget;
+ if (suspect) {
+ if (suspect->CanSetPedState())
+ suspect->m_nPedState = PED_ARRESTED;
+
+ if (suspect->bInVehicle && m_pMyVehicle && suspect->m_pMyVehicle == m_pMyVehicle) {
+
+ // BUG? I will never understand why they used LINE_UP_TO_CAR_2...
+ LineUpPedWithCar(LINE_UP_TO_CAR_2);
+ }
+
+ if (suspect && (suspect->m_nPedState == PED_ARRESTED || suspect->DyingOrDead() || suspect->EnteringCar())) {
+
+ CAnimBlendAssociation *arrestAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_ARREST_GUN);
+ if (!arrestAssoc || arrestAssoc->blendDelta < 0.0f)
+ CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_ARREST_GUN, 4.0f);
+
+ CVector suspMidPos;
+ suspect->m_pedIK.GetComponentPosition((RwV3d*)suspMidPos, PED_MID);
+ m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(suspMidPos.x, suspMidPos.y,
+ GetPosition().x, GetPosition().y);
+
+ m_fRotationCur = m_fRotationDest;
+ SetOrientation(0.0f, 0.0f, m_fRotationCur);
+ } else {
+ ClearPursuit();
+ }
+ } else {
+ ClearPursuit();
+ }
+}
+
+void
+CCopPed::ScanForCrimes(void)
+{
+ CVehicle *playerVeh = FindPlayerVehicle();
+
+ // Look for car alarms
+ if (playerVeh && playerVeh->IsCar()) {
+ if (playerVeh->IsAlarmOn()) {
+ if ((playerVeh->GetPosition() - GetPosition()).MagnitudeSqr() < sq(20.0f))
+ FindPlayerPed()->SetWantedLevelNoDrop(1);
+ }
+ }
+
+ // Look for stolen cop cars (it was broken until now)
+ if (!m_bIsInPursuit) {
+ CPlayerPed *player = FindPlayerPed();
+#ifdef FIX_BUGS
+ if ((player->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || player->m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER)
+#else
+ if ((m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER)
+#endif
+ && player->m_pWanted->m_nWantedLevel == 0 && player->m_pMyVehicle) {
+
+ if (player->m_pMyVehicle->bIsLawEnforcer)
+ player->SetWantedLevelNoDrop(1);
+ }
+ }
+}
class CCopPed_ : public CCopPed
{
@@ -78,4 +285,9 @@ public:
STARTPATCHES
InjectHook(0x4C11B0, &CCopPed_::ctor, PATCH_JUMP);
InjectHook(0x4C13E0, &CCopPed_::dtor, PATCH_JUMP);
+ InjectHook(0x4C28C0, &CCopPed::ClearPursuit, PATCH_JUMP);
+ InjectHook(0x4C2B00, &CCopPed::SetArrestPlayer, PATCH_JUMP);
+ InjectHook(0x4C27D0, &CCopPed::SetPursuit, PATCH_JUMP);
+ InjectHook(0x4C2C90, &CCopPed::ArrestPlayer, PATCH_JUMP);
+ InjectHook(0x4C26A0, &CCopPed::ScanForCrimes, PATCH_JUMP);
ENDPATCHES