more CWanted; added CEventList

This commit is contained in:
aap 2019-07-12 18:01:22 +02:00
parent 0548476ba6
commit 60711154ba
13 changed files with 666 additions and 89 deletions

View File

@ -33,4 +33,5 @@ WRAPPER int32 cDMAudio::CreateEntity(int, void*) { EAXJMP(0x57C7C0); }
WRAPPER void cDMAudio::SetEntityStatus(int32 id, uint8 enable) { EAXJMP(0x57C810); }
WRAPPER void cDMAudio::SetRadioInCar(int32) { EAXJMP(0x57CE60); }
WRAPPER void cDMAudio::DestroyEntity(int32) { EAXJMP(0x57C7F0); }
WRAPPER void cDMAudio::ClearMissionAudio(void) { EAXJMP(0x57CE20); }
WRAPPER void cDMAudio::ClearMissionAudio(void) { EAXJMP(0x57CE20); }
WRAPPER void cDMAudio::ReportCrime(eCrimeType crime, const CVector &pos) { EAXJMP(0x57CAD0); }

View File

@ -173,6 +173,7 @@ enum eSound : int16
};
class CEntity;
enum eCrimeType;
class cDMAudio
{
@ -204,5 +205,6 @@ public:
uint8 IsMP3RadioChannelAvailable();
void DestroyEntity(int32);
void ClearMissionAudio(void);
void ReportCrime(eCrimeType crime, const CVector &pos);
};
extern cDMAudio &DMAudio;

View File

@ -300,7 +300,7 @@ void CDarkel::Update()
TimeOfFrenzyStart = CTimer::GetTimeInMilliseconds();
FindPlayerPed()->m_pWanted->SetWantedLevel(NOTWANTED);
FindPlayerPed()->m_pWanted->SetWantedLevel(0);
if (WeaponType == WEAPONTYPE_UZI_DRIVEBY)
WeaponType = WEAPONTYPE_UZI;

View File

@ -124,8 +124,8 @@ void CMissionCleanup::Process()
CHud::m_ItemToFlash = -1;
CHud::SetHelpMessage(nil, false);
CUserDisplay::OnscnTimer.m_bDisabled = false;
CWorld::Players[0].m_pPed->m_pWanted->m_IsIgnoredByCops = false;
CWorld::Players[0].m_pPed->m_pWanted->m_IsIgnoredByEveryOne = false;
CWorld::Players[0].m_pPed->m_pWanted->m_bIgnoredByCops = false;
CWorld::Players[0].m_pPed->m_pWanted->m_bIgnoredByEveryone = false;
CWorld::Players[0].MakePlayerSafe(false);
CTheScripts::StoreVehicleIndex = -1;
CTheScripts::StoreVehicleWasRandom = true;

238
src/core/EventList.cpp Normal file
View File

@ -0,0 +1,238 @@
#include "common.h"
#include "patcher.h"
#include "Pools.h"
#include "ModelIndices.h"
#include "World.h"
#include "Wanted.h"
#include "Eventlist.h"
int32 CEventList::ms_nFirstFreeSlotIndex;
//CEvent gaEvent[NUMEVENTS];
CEvent *gaEvent = (CEvent*)0x6EF830;
enum
{
EVENT_STATE_0,
EVENT_STATE_CANDELETE,
EVENT_STATE_CLEAR,
};
void
CEventList::Initialise(void)
{
int i;
debug("Initialising CEventList...");
for(i = 0; i < NUMEVENTS; i++){
gaEvent[i].type = EVENT_NULL;
gaEvent[i].entityType = EVENT_ENTITY_NONE;
gaEvent[i].entityRef = 0;
gaEvent[i].posn.x = 0.0f;
gaEvent[i].posn.y = 0.0f;
gaEvent[i].posn.z = 0.0f;
gaEvent[i].timeout = 0;
gaEvent[i].state = EVENT_STATE_0;
}
ms_nFirstFreeSlotIndex = 0;
}
void
CEventList::Update(void)
{
int i;
ms_nFirstFreeSlotIndex = 0;
for(i = 0; i < NUMEVENTS; i++){
if(gaEvent[i].type == EVENT_NULL)
continue;
if(CTimer::GetTimeInMilliseconds() > gaEvent[i].timeout || gaEvent[i].state == EVENT_STATE_CANDELETE){
gaEvent[i].type = EVENT_NULL;
gaEvent[i].state = EVENT_STATE_0;
}
if(gaEvent[i].state == EVENT_STATE_CLEAR)
gaEvent[i].state = EVENT_STATE_CANDELETE;
}
}
void
CEventList::RegisterEvent(eEventType type, eEventEntity entityType, CEntity *ent, CPed *criminal, int32 timeout)
{
int i;
int ref;
bool copsDontCare;
copsDontCare = false;
switch(entityType){
case EVENT_ENTITY_PED:
ref = CPools::GetPedRef((CPed*)ent);
if(ent->GetModelIndex() >= MI_GANG01 && ent->GetModelIndex() <= MI_CRIMINAL02)
copsDontCare = true;
break;
case EVENT_ENTITY_VEHICLE:
ref = CPools::GetVehicleRef((CVehicle*)ent);
break;
case EVENT_ENTITY_OBJECT:
ref = CPools::GetObjectRef((CObject*)ent);
break;
default:
Error("Undefined entity type, RegisterEvent, EventList.cpp");
ref = 0;
break;
}
// only update time if event exists already
for(i = 0; i < NUMEVENTS; i++)
if(gaEvent[i].type == type &&
gaEvent[i].entityType == entityType &&
gaEvent[i].entityRef == ref){
gaEvent[i].timeout = CTimer::GetTimeInMilliseconds() + timeout;
return;
}
for(i = ms_nFirstFreeSlotIndex; i < NUMEVENTS; i++)
if(gaEvent[i].type == EVENT_NULL){
ms_nFirstFreeSlotIndex = i;
break;
}
if(i < NUMEVENTS){
gaEvent[i].type = type;
gaEvent[i].entityType = entityType;
gaEvent[i].timeout = CTimer::GetTimeInMilliseconds() + timeout;
gaEvent[i].entityRef = ref;
gaEvent[i].posn = ent->GetPosition();
gaEvent[i].criminal = criminal;
if(gaEvent[i].criminal)
gaEvent[i].criminal->RegisterReference((CEntity**)&gaEvent[i].criminal);
if(type == EVENT_GUNSHOT)
gaEvent[i].state = EVENT_STATE_CLEAR;
else
gaEvent[i].state = EVENT_STATE_0;
}
if(criminal == FindPlayerPed())
ReportCrimeForEvent(type, (uintptr)ent, copsDontCare);
}
void
CEventList::RegisterEvent(eEventType type, CVector posn, int32 timeout)
{
int i;
// only update time if event exists already
for(i = 0; i < NUMEVENTS; i++)
if(gaEvent[i].type == type &&
gaEvent[i].posn.x == posn.x &&
gaEvent[i].posn.y == posn.y &&
gaEvent[i].posn.z == posn.z &&
gaEvent[i].entityType == EVENT_ENTITY_NONE){
gaEvent[i].timeout = CTimer::GetTimeInMilliseconds() + timeout;
return;
}
for(i = ms_nFirstFreeSlotIndex; i < NUMEVENTS; i++)
if(gaEvent[i].type == EVENT_NULL){
ms_nFirstFreeSlotIndex = i;
break;
}
if(i < NUMEVENTS){
gaEvent[i].type = type;
gaEvent[i].entityType = EVENT_ENTITY_NONE;
gaEvent[i].timeout = CTimer::GetTimeInMilliseconds() + timeout;
gaEvent[i].posn = posn;
gaEvent[i].entityRef = 0;
if(type == EVENT_GUNSHOT)
gaEvent[i].state = EVENT_STATE_CLEAR;
else
gaEvent[i].state = EVENT_STATE_0;
}
}
bool
CEventList::GetEvent(eEventType type, int32 *event)
{
int i;
for(i = 0; i < NUMEVENTS; i++)
if(gaEvent[i].type == type){
*event = i;
return true;
}
return false;
}
void
CEventList::ClearEvent(int32 event)
{
if(gaEvent[event].state != EVENT_STATE_CANDELETE)
gaEvent[event].state = EVENT_STATE_CLEAR;
}
bool
CEventList::FindClosestEvent(eEventType type, CVector posn, int32 *event)
{
int i;
float dist;
bool found = false;
float mindist = 60.0f;
for(i = 0; i < NUMEVENTS; i++){
if(gaEvent[i].type == EVENT_NULL)
continue;
dist = (posn - gaEvent[i].posn).Magnitude();
if(dist < mindist){
mindist = dist;
found = true;
*event = i;
}
}
return found;
}
void
CEventList::ReportCrimeForEvent(eEventType type, int32 crimeId, bool copsDontCare)
{
eCrimeType crime;
switch(type){
case EVENT_ASSAULT: crime = CRIME_HIT_PED; break;
case EVENT_RUN_REDLIGHT: crime = CRIME_RUN_REDLIGHT; break;
case EVENT_ASSAULT_POLICE: crime = CRIME_HIT_COP; break;
case EVENT_GUNSHOT: crime = CRIME_POSSESSION_GUN; break;
case EVENT_STEAL_CAR: crime = CRIME_STEAL_CAR; break;
case EVENT_HIT_AND_RUN: crime = CRIME_RUNOVER_PED; break;
case EVENT_HIT_AND_RUN_COP: crime = CRIME_RUNOVER_COP; break;
case EVENT_SHOOT_PED: crime = CRIME_SHOOT_PED; break;
case EVENT_SHOOT_COP: crime = CRIME_SHOOT_COP; break;
case EVENT_PED_SET_ON_FIRE: crime = CRIME_PED_BURNED; break;
case EVENT_COP_SET_ON_FIRE: crime = CRIME_COP_BURNED; break;
case EVENT_CAR_SET_ON_FIRE: crime = CRIME_VEHICLE_BURNED; break;
default: crime = CRIME_NONE; break;
}
if(crime == CRIME_NONE)
return;
CVector playerPedCoors = FindPlayerPed()->GetPosition();
CVector playerCoors = FindPlayerCoors();
if(CWanted::WorkOutPolicePresence(playerCoors, 14.0f) != 0){
FindPlayerPed()->m_pWanted->RegisterCrime_Immediately(crime, playerPedCoors, crimeId, copsDontCare);
FindPlayerPed()->m_pWanted->SetWantedLevelNoDrop(1);
}else
FindPlayerPed()->m_pWanted->RegisterCrime(crime, playerPedCoors, crimeId, copsDontCare);
if(type == EVENT_ASSAULT_POLICE)
FindPlayerPed()->SetWantedLevelNoDrop(1);
if(type == EVENT_SHOOT_COP)
FindPlayerPed()->SetWantedLevelNoDrop(2);
}
STARTPATCHES
InjectHook(0x475B60, CEventList::Initialise, PATCH_JUMP);
InjectHook(0x475BE0, CEventList::Update, PATCH_JUMP);
InjectHook(0x475C50, (void (*)(eEventType,eEventEntity,CEntity *,CPed *,int32))CEventList::RegisterEvent, PATCH_JUMP);
InjectHook(0x475E10, (void (*)(eEventType,CVector,int32))CEventList::RegisterEvent, PATCH_JUMP);
InjectHook(0x475F40, CEventList::GetEvent, PATCH_JUMP);
InjectHook(0x475F70, CEventList::ClearEvent, PATCH_JUMP);
InjectHook(0x475F90, CEventList::FindClosestEvent, PATCH_JUMP);
InjectHook(0x476070, CEventList::ReportCrimeForEvent, PATCH_JUMP);
ENDPATCHES

65
src/core/EventList.h Normal file
View File

@ -0,0 +1,65 @@
#pragma once
class CEntity;
class CPed;
enum eEventType
{
EVENT_NULL,
EVENT_ASSAULT,
EVENT_RUN_REDLIGHT,
EVENT_ASSAULT_POLICE,
EVENT_GUNSHOT,
EVENT_INJURED_PED,
EVENT_DEAD_PED,
EVENT_FIRE,
EVENT_STEAL_CAR,
EVENT_HIT_AND_RUN,
EVENT_HIT_AND_RUN_COP,
EVENT_SHOOT_PED,
EVENT_SHOOT_COP,
EVENT_EXPLOSION,
EVENT_PED_SET_ON_FIRE,
EVENT_COP_SET_ON_FIRE,
EVENT_CAR_SET_ON_FIRE,
EVENT_ASSAULT_NASTYWEAPON,
EVENT_ASSAULT_NASTYWEAPON_POLICE,
EVENT_ICECREAM,
EVENT_ATM,
EVENT_SHOPSTALL,
EVENT_SHOPWINDOW,
EVENT_LAST_EVENT
};
enum eEventEntity
{
EVENT_ENTITY_NONE,
EVENT_ENTITY_PED,
EVENT_ENTITY_VEHICLE,
EVENT_ENTITY_OBJECT
};
struct CEvent
{
eEventType type;
eEventEntity entityType;
int32 entityRef;
CPed *criminal;
CVector posn;
uint32 timeout;
int32 state;
};
class CEventList
{
static int32 ms_nFirstFreeSlotIndex;
public:
static void Initialise(void);
static void Update(void);
static void RegisterEvent(eEventType type, eEventEntity entityType, CEntity *ent, CPed *criminal, int32 timeout);
static void RegisterEvent(eEventType type, CVector posn, int32 timeout);
static bool GetEvent(eEventType type, int32 *event);
static void ClearEvent(int32 event);
static bool FindClosestEvent(eEventType type, CVector posn, int32 *event);
static void ReportCrimeForEvent(eEventType type, int32, bool);
};

View File

@ -14,6 +14,7 @@ void
CPools::Initialise(void)
{
// TODO: unused right now
assert(0);
ms_pPtrNodePool = new CCPtrNodePool(NUMPTRNODES);
ms_pEntryInfoNodePool = new CEntryInfoNodePool(NUMENTRYINFOS);
ms_pPedPool = new CPedPool(NUMPEDS);
@ -23,3 +24,10 @@ CPools::Initialise(void)
ms_pObjectPool = new CObjectPool(NUMOBJECTS);
ms_pDummyPool = new CDummyPool(NUMDUMMIES);
}
int32 CPools::GetPedRef(CPed *ped) { return ms_pPedPool->GetIndex(ped); }
CPed *CPools::GetPed(int32 handle) { return ms_pPedPool->GetAt(handle); }
int32 CPools::GetVehicleRef(CVehicle *vehicle) { return ms_pVehiclePool->GetIndex(vehicle); }
CVehicle *CPools::GetVehicle(int32 handle) { return ms_pVehiclePool->GetAt(handle); }
int32 CPools::GetObjectRef(CObject *object) { return ms_pObjectPool->GetIndex(object); }
CObject *CPools::GetObject(int32 handle) { return ms_pObjectPool->GetAt(handle); }

View File

@ -40,4 +40,10 @@ public:
static CDummyPool *GetDummyPool(void) { return ms_pDummyPool; }
static void Initialise(void);
static int32 GetPedRef(CPed *ped);
static CPed *GetPed(int32 handle);
static int32 GetVehicleRef(CVehicle *vehicle);
static CVehicle *GetVehicle(int32 handle);
static int32 GetObjectRef(CObject *object);
static CObject *GetObject(int32 handle);
};

View File

@ -1,65 +1,102 @@
#include "common.h"
#include "patcher.h"
#include "Pools.h"
#include "ModelIndices.h"
#include "Timer.h"
#include "World.h"
#include "ZoneCull.h"
#include "Darkel.h"
#include "DMAudio.h"
#include "Wanted.h"
int32 &CWanted::MaximumWantedLevel = *(int32*)0x5F7714;
int32 &CWanted::MaximumWantedLevel = *(int32*)0x5F7714; // 6
int32 &CWanted::nMaximumWantedLevel = *(int32*)0x5F7718; // 6400
bool CWanted::AreSwatRequired()
void
CWanted::Initialise()
{
int i;
m_nChaos = 0;
m_nLastUpdateTime = 0;
m_nLastWantedLevelChange = 0;
m_CurrentCops = 0;
m_MaxCops = 0;
m_MaximumLawEnforcerVehicles = 0;
m_RoadblockDensity = 0;
m_bIgnoredByCops = false;
m_bIgnoredByEveryone = false;
m_bSwatRequired = false;
m_bFbiRequired = false;
m_bArmyRequired = false;
m_fCrimeSensitivity = 1.0f;
m_nWantedLevel = 0;
m_CopsBeatingSuspect = 0;
for(i = 0; i < 10; i++)
m_pCops[i] = nil;
ClearQdCrimes();
}
bool
CWanted::AreSwatRequired()
{
return m_nWantedLevel >= 4;
}
bool CWanted::AreFbiRequired()
bool
CWanted::AreFbiRequired()
{
return m_nWantedLevel >= 5;
}
bool CWanted::AreArmyRequired()
bool
CWanted::AreArmyRequired()
{
return m_nWantedLevel >= 6;
}
int CWanted::NumOfHelisRequired()
int32
CWanted::NumOfHelisRequired()
{
if (m_IsIgnoredByCops)
if (m_bIgnoredByCops)
return 0;
// Return value is number of helicopters, no need to name them.
switch (m_nWantedLevel) {
case WANTEDLEVEL_3:
case WANTEDLEVEL_4:
case 3:
case 4:
return 1;
case WANTEDLEVEL_5:
case WANTEDLEVEL_6:
case 5:
case 6:
return 2;
default:
return 0;
}
}
void CWanted::SetWantedLevel(int32 level)
void
CWanted::SetWantedLevel(int32 level)
{
ClearQdCrimes();
switch (level) {
case NOTWANTED:
case 0:
m_nChaos = 0;
break;
case WANTEDLEVEL_1:
case 1:
m_nChaos = 60;
break;
case WANTEDLEVEL_2:
case 2:
m_nChaos = 220;
break;
case WANTEDLEVEL_3:
case 3:
m_nChaos = 420;
break;
case WANTEDLEVEL_4:
case 4:
m_nChaos = 820;
break;
case WANTEDLEVEL_5:
case 5:
m_nChaos = 1620;
break;
case WANTEDLEVEL_6:
case 6:
m_nChaos = 3220;
break;
default:
@ -70,61 +107,210 @@ void CWanted::SetWantedLevel(int32 level)
UpdateWantedLevel();
}
void CWanted::SetWantedLevelNoDrop(int32 level)
void
CWanted::SetWantedLevelNoDrop(int32 level)
{
if (level > m_nWantedLevel)
SetWantedLevel(level);
}
void CWanted::ClearQdCrimes()
void
CWanted::SetMaximumWantedLevel(int32 level)
{
for (int i = 0; i < 16; i++) {
m_sCrimes[i].m_eCrimeType = CRIME_NONE;
switch(level){
case 0:
nMaximumWantedLevel = 0;
MaximumWantedLevel = 0;
break;
case 1:
nMaximumWantedLevel = 120;
MaximumWantedLevel = 1;
break;
case 2:
nMaximumWantedLevel = 300;
MaximumWantedLevel = 2;
break;
case 3:
nMaximumWantedLevel = 600;
MaximumWantedLevel = 3;
break;
case 4:
nMaximumWantedLevel = 1200;
MaximumWantedLevel = 4;
break;
case 5:
nMaximumWantedLevel = 2400;
MaximumWantedLevel = 5;
break;
case 6:
nMaximumWantedLevel = 4800;
MaximumWantedLevel = 6;
break;
}
}
void CWanted::UpdateWantedLevel()
void
CWanted::RegisterCrime(eCrimeType type, const CVector &coors, uint32 id, bool policeDoesntCare)
{
AddCrimeToQ(type, id, coors, false, policeDoesntCare);
}
void
CWanted::RegisterCrime_Immediately(eCrimeType type, const CVector &coors, uint32 id, bool policeDoesntCare)
{
if(!AddCrimeToQ(type, id, coors, false, policeDoesntCare))
ReportCrimeNow(type, coors, policeDoesntCare);
}
void
CWanted::ClearQdCrimes()
{
for (int i = 0; i < 16; i++)
m_aCrimes[i].m_nType = CRIME_NONE;
}
// returns whether the crime had been reported already
bool
CWanted::AddCrimeToQ(eCrimeType type, int32 id, const CVector &coors, bool reported, bool policeDoesntCare)
{
int i;
for(i = 0; i < 16; i++)
if(m_aCrimes[i].m_nType == type && m_aCrimes[i].m_nId == id){
if(m_aCrimes[i].m_bReported)
return true;
if(reported)
m_aCrimes[i].m_bReported = reported;
return false;
}
for(i = 0; i < 16; i++)
if(m_aCrimes[i].m_nType == CRIME_NONE)
break;
if(i < 16){
m_aCrimes[i].m_nType = type;
m_aCrimes[i].m_nId = id;
m_aCrimes[i].m_vecPosn = coors;
m_aCrimes[i].m_nTime = CTimer::GetTimeInMilliseconds();
m_aCrimes[i].m_bReported = reported;
m_aCrimes[i].m_bPoliceDoesntCare = policeDoesntCare;
}
return false;
}
void
CWanted::ReportCrimeNow(eCrimeType type, const CVector &coors, bool policeDoesntCare)
{
float sensitivity, chaos;
int wantedLevelDrop;
if(CDarkel::FrenzyOnGoing())
sensitivity = m_fCrimeSensitivity*0.3f;
else
sensitivity = m_fCrimeSensitivity;
wantedLevelDrop = min(CCullZones::GetWantedLevelDrop(), 100);
chaos = (1.0f - wantedLevelDrop/100.0f) * sensitivity;
switch(type){
case CRIME_POSSESSION_GUN:
break;
case CRIME_HIT_PED:
m_nChaos += 5.0f*chaos;
break;
case CRIME_HIT_COP:
m_nChaos += 45.0f*chaos;
break;
case CRIME_SHOOT_PED:
m_nChaos += 30.0f*chaos;
break;
case CRIME_SHOOT_COP:
m_nChaos += 80.0f*chaos;
break;
case CRIME_STEAL_CAR:
m_nChaos += 15.0f*chaos;
break;
case CRIME_RUN_REDLIGHT:
m_nChaos += 10.0f*chaos;
break;
case CRIME_RECKLESS_DRIVING:
m_nChaos += 5.0f*chaos;
break;
case CRIME_SPEEDING:
m_nChaos += 5.0f*chaos;
break;
case CRIME_RUNOVER_PED:
m_nChaos += 18.0f*chaos;
break;
case CRIME_RUNOVER_COP:
m_nChaos += 80.0f*chaos;
break;
case CRIME_SHOOT_HELI:
m_nChaos += 400.0f*chaos;
break;
case CRIME_PED_BURNED:
m_nChaos += 20.0f*chaos;
break;
case CRIME_COP_BURNED:
m_nChaos += 80.0f*chaos;
break;
case CRIME_VEHICLE_BURNED:
m_nChaos += 20.0f*chaos;
break;
case CRIME_DESTROYED_CESSNA:
m_nChaos += 500.0f*chaos;
break;
default:
// Error("Undefined crime type, RegisterCrime, Crime.cpp"); // different file for some reason
Error("Undefined crime type, RegisterCrime, Wanted.cpp");
}
DMAudio.ReportCrime(type, coors);
UpdateWantedLevel();
}
void
CWanted::UpdateWantedLevel()
{
int32 CurrWantedLevel = m_nWantedLevel;
if (m_nChaos >= 0 && m_nChaos < 40) {
m_nWantedLevel = NOTWANTED;
m_nWantedLevel = 0;
m_MaximumLawEnforcerVehicles = 0;
m_MaxCops = 0;
m_RoadblockDensity = 0;
}
else if (m_nChaos >= 40 && m_nChaos < 200) {
m_nWantedLevel = WANTEDLEVEL_1;
m_nWantedLevel = 1;
m_MaximumLawEnforcerVehicles = 1;
m_MaxCops = 1;
m_RoadblockDensity = 0;
}
else if (m_nChaos >= 200 && m_nChaos < 400) {
m_nWantedLevel = WANTEDLEVEL_2;
m_nWantedLevel = 2;
m_MaximumLawEnforcerVehicles = 2;
m_MaxCops = 3;
m_RoadblockDensity = 0;
}
else if (m_nChaos >= 400 && m_nChaos < 800) {
m_nWantedLevel = WANTEDLEVEL_3;
m_nWantedLevel = 3;
m_MaximumLawEnforcerVehicles = 2;
m_MaxCops = 4;
m_RoadblockDensity = 4;
}
else if (m_nChaos >= 800 && m_nChaos < 1600) {
m_nWantedLevel = WANTEDLEVEL_4;
m_nWantedLevel = 4;
m_MaximumLawEnforcerVehicles = 2;
m_MaxCops = 6;
m_RoadblockDensity = 8;
}
else if (m_nChaos >= 1600 && m_nChaos < 3200) {
m_nWantedLevel = WANTEDLEVEL_5;
m_nWantedLevel = 5;
m_MaximumLawEnforcerVehicles = 3;
m_MaxCops = 8;
m_RoadblockDensity = 10;
}
else if (m_nChaos >= 3200) {
m_nWantedLevel = WANTEDLEVEL_6;
m_nWantedLevel = 6;
m_MaximumLawEnforcerVehicles = 3;
m_MaxCops = 10;
m_RoadblockDensity = 12;
@ -132,4 +318,58 @@ void CWanted::UpdateWantedLevel()
if (CurrWantedLevel != m_nWantedLevel)
m_nLastWantedLevelChange = CTimer::GetTimeInMilliseconds();
}
}
int32
CWanted::WorkOutPolicePresence(CVector posn, float radius)
{
int i;
CPed *ped;
CVehicle *vehicle;
int numPolice = 0;
i = CPools::GetPedPool()->GetSize();
while(--i >= 0){
ped = CPools::GetPedPool()->GetSlot(i);
if(ped &&
IsPolicePedModel(ped->GetModelIndex()) &&
(posn - ped->GetPosition()).Magnitude() < radius)
numPolice++;
}
i = CPools::GetVehiclePool()->GetSize();
while(--i >= 0){
vehicle = CPools::GetVehiclePool()->GetSlot(i);
if(vehicle &&
vehicle->bIsLawEnforcer &&
IsPoliceVehicleModel(vehicle->GetModelIndex()) &&
vehicle != FindPlayerVehicle() &&
vehicle->m_status != STATUS_ABANDONED && vehicle->m_status != STATUS_WRECKED &&
(posn - vehicle->GetPosition()).Magnitude() < radius)
numPolice++;
}
return numPolice;
}
STARTPATCHES
InjectHook(0x4AD6E0, &CWanted::Initialise, PATCH_JUMP);
// InjectHook(0x4AD790, &CWanted::Reset, PATCH_JUMP);
// InjectHook(0x4AD7B0, &CWanted::Update, PATCH_JUMP);
InjectHook(0x4AD900, &CWanted::UpdateWantedLevel, PATCH_JUMP);
InjectHook(0x4AD9F0, &CWanted::RegisterCrime, PATCH_JUMP);
InjectHook(0x4ADA10, &CWanted::RegisterCrime_Immediately, PATCH_JUMP);
InjectHook(0x4ADA50, &CWanted::SetWantedLevel, PATCH_JUMP);
InjectHook(0x4ADAC0, &CWanted::SetWantedLevelNoDrop, PATCH_JUMP);
InjectHook(0x4ADAE0, &CWanted::SetMaximumWantedLevel, PATCH_JUMP);
InjectHook(0x4ADBA0, &CWanted::AreSwatRequired, PATCH_JUMP);
InjectHook(0x4ADBC0, &CWanted::AreFbiRequired, PATCH_JUMP);
InjectHook(0x4ADBE0, &CWanted::AreArmyRequired, PATCH_JUMP);
InjectHook(0x4ADC00, &CWanted::NumOfHelisRequired, PATCH_JUMP);
// InjectHook(0x4ADC40, &CWanted::ResetPolicePursuit, PATCH_JUMP);
InjectHook(0x4ADD00, &CWanted::WorkOutPolicePresence, PATCH_JUMP);
InjectHook(0x4ADF20, &CWanted::ClearQdCrimes, PATCH_JUMP);
InjectHook(0x4ADFD0, &CWanted::AddCrimeToQ, PATCH_JUMP);
// InjectHook(0x4AE090, &CWanted::UpdateCrimesQ, PATCH_JUMP);
InjectHook(0x4AE110, &CWanted::ReportCrimeNow, PATCH_JUMP);
ENDPATCHES

View File

@ -1,16 +1,38 @@
#pragma once
#include "Entity.h"
#include "math/Vector.h"
#include "CopPed.h"
enum eWantedLevel {
NOTWANTED,
WANTEDLEVEL_1,
WANTEDLEVEL_2,
WANTEDLEVEL_3,
WANTEDLEVEL_4,
WANTEDLEVEL_5,
WANTEDLEVEL_6,
class CEntity;
class CCopPed;
enum eCrimeType
{
CRIME_NONE,
CRIME_POSSESSION_GUN,
CRIME_HIT_PED,
CRIME_HIT_COP,
CRIME_SHOOT_PED,
CRIME_SHOOT_COP,
CRIME_STEAL_CAR,
CRIME_RUN_REDLIGHT,
CRIME_RECKLESS_DRIVING,
CRIME_SPEEDING,
CRIME_RUNOVER_PED,
CRIME_RUNOVER_COP,
CRIME_SHOOT_HELI,
CRIME_PED_BURNED,
CRIME_COP_BURNED,
CRIME_VEHICLE_BURNED,
CRIME_DESTROYED_CESSNA,
};
class CCrimeBeingQd
{
public:
eCrimeType m_nType;
uint32 m_nId;
int32 m_nTime;
CVector m_vecPosn;
bool m_bReported;
bool m_bPoliceDoesntCare;
};
class CWanted
@ -23,28 +45,37 @@ public:
uint8 m_CurrentCops;
uint8 m_MaxCops;
uint8 m_MaximumLawEnforcerVehicles;
int8 field_19;
uint8 m_CopsBeatingSuspect;
int16 m_RoadblockDensity;
uint8 m_IsIgnoredByCops : 1;
uint8 m_IsIgnoredByEveryOne : 1;
uint8 m_IsSwatRequired : 1;
uint8 m_IsFbiRequired : 1;
uint8 m_IdArmyRequired : 1;
int8 field_23;
uint8 m_bIgnoredByCops : 1;
uint8 m_bIgnoredByEveryone : 1;
uint8 m_bSwatRequired : 1;
uint8 m_bFbiRequired : 1;
uint8 m_bArmyRequired : 1;
int32 m_nWantedLevel;
CCrime m_sCrimes[16];
CCrimeBeingQd m_aCrimes[16];
CCopPed *m_pCops[10];
static int32 &MaximumWantedLevel;
static int32 &nMaximumWantedLevel;
public:
void Initialise();
bool AreSwatRequired();
bool AreFbiRequired();
bool AreArmyRequired();
int NumOfHelisRequired();
int32 NumOfHelisRequired();
void SetWantedLevel(int32);
void SetWantedLevelNoDrop(int32 level);
void RegisterCrime(eCrimeType type, const CVector &coors, uint32 id, bool policeDoesntCare);
void RegisterCrime_Immediately(eCrimeType type, const CVector &coors, uint32 id, bool policeDoesntCare);
void ClearQdCrimes();
bool AddCrimeToQ(eCrimeType type, int32 id, const CVector &pos, bool reported, bool policeDoesntCare);
void ReportCrimeNow(eCrimeType type, const CVector &coors, bool policeDoesntCare);
void UpdateWantedLevel();
static int32 WorkOutPolicePresence(CVector posn, float radius);
static void SetMaximumWantedLevel(int32 level);
};
static_assert(sizeof(CWanted) == 0x204, "CWanted: error");

View File

@ -62,6 +62,7 @@ enum Config {
NUMONSCREENTIMERENTRIES = 1,
NUMRADARBLIPS = 32,
NUMPICKUPS = 336,
NUMEVENTS = 64,
};
// We'll use this once we're ready to become independent of the game

View File

@ -465,3 +465,21 @@ IsPickupModel(int16 id)
id == MI_PICKUP_KILLFRENZY ||
id == MI_PICKUP_CAMERA;
}
inline bool
IsPolicePedModel(int16 id)
{
return id == MI_COP ||
id == MI_SWAT ||
id == MI_FBI ||
id == MI_ARMY;
}
inline bool
IsPoliceVehicleModel(int16 id)
{
return id == MI_CHOPPER ||
id == MI_PREDATOR ||
id == MI_POLICE ||
id == MI_ENFORCER;
}

View File

@ -1,27 +1,6 @@
#pragma once
#include "Ped.h"
enum eCrimeType
{
CRIME_NONE,
CRIME_POSSESSION_GUN,
CRIME_HIT_PED,
CRIME_HIT_COP,
CRIME_SHOOT_PED,
CRIME_SHOOT_COP,
CRIME_STEAL_CAR,
CRIME_RUN_REDLIGHT,
CRIME_RECKLESS_DRIVING,
CRIME_SPEEDING,
CRIME_RUNOVER_PED,
CRIME_RUNOVER_COP,
CRIME_SHOOT_HELI,
CRIME_PED_BURNED,
CRIME_COP_BURNED,
CRIME_VEHICLE_BURNED,
CRIME_DESTROYED_CESSNA,
};
enum eCopType
{
COP_STREET = 0,
@ -30,18 +9,6 @@ enum eCopType
COP_ARMY = 3,
};
class CCrime
{
public:
eCrimeType m_eCrimeType;
CEntity *m_pVictim;
int32 m_nCrimeTime;
CVector m_vecCrimePos;
int8 m_bReported;
int8 m_bMultiplier;
int8 pad_20[2];
};
class CCopPed : public CPed
{
public: