#include "common.h"
#include "patcher.h"
#include "Pools.h"
#include "ModelIndices.h"
#include "World.h"
#include "Wanted.h"
#include "EventList.h"
#include "Messages.h"
#include "Text.h"
#include "main.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 != type)
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;
}
#ifdef VC_PED_PORTS
if (crime == CRIME_HIT_PED && ((CPed*)crimeId)->IsPointerValid() &&
FindPlayerPed()->m_pWanted->m_nWantedLevel == 0 && ((CPed*)crimeId)->bBeingChasedByPolice) {
if(!((CPed*)crimeId)->DyingOrDead()) {
sprintf(gString, "$50 Good Citizen Bonus!");
AsciiToUnicode(gString, gUString);
CMessages::AddBigMessage(gUString, 5000, 0);
CWorld::Players[CWorld::PlayerInFocus].m_nMoney += 50;
}
} else
#endif
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