Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Nikolay Korolev 2020-03-15 18:47:36 +03:00
commit 1971b3db62
20 changed files with 588 additions and 151 deletions

View File

@ -63,7 +63,6 @@ CMotionBlurStreaks
CObject CObject
CPacManPickups CPacManPickups
CPedPath CPedPath
CPopulation
CRadar CRadar
CRecordDataForChase CRecordDataForChase
CRoadBlocks CRoadBlocks

View File

@ -249,7 +249,7 @@ CGameLogic::RestorePlayerStuffDuringResurrection(CPlayerPed *pPlayerPed, CVector
pPlayerPed->m_fHealth = 100.0f; pPlayerPed->m_fHealth = 100.0f;
pPlayerPed->m_fArmour = 0.0f; pPlayerPed->m_fArmour = 0.0f;
pPlayerPed->bIsVisible = true; pPlayerPed->bIsVisible = true;
pPlayerPed->m_bloodyFootprintCount = 0; pPlayerPed->m_bloodyFootprintCountOrDeathTime = 0;
pPlayerPed->bDoBloodyFootprints = false; pPlayerPed->bDoBloodyFootprints = false;
pPlayerPed->ClearAdrenaline(); pPlayerPed->ClearAdrenaline();
pPlayerPed->m_fCurrentStamina = pPlayerPed->m_fMaxStamina; pPlayerPed->m_fCurrentStamina = pPlayerPed->m_fMaxStamina;

View File

@ -153,7 +153,7 @@ void
CPlayerInfo::CancelPlayerEnteringCars(CVehicle *car) CPlayerInfo::CancelPlayerEnteringCars(CVehicle *car)
{ {
if (!car || car == m_pPed->m_pMyVehicle) { if (!car || car == m_pPed->m_pMyVehicle) {
if (m_pPed->m_nPedState == PED_CARJACK || m_pPed->m_nPedState == PED_ENTER_CAR) if (m_pPed->EnteringCar())
m_pPed->QuitEnteringCar(); m_pPed->QuitEnteringCar();
} }
if (m_pPed->m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER || m_pPed->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER) if (m_pPed->m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER || m_pPed->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER)

View File

@ -1287,7 +1287,7 @@ CStreaming::StreamVehiclesAndPeds(void)
if(timeBeforeNextLoad >= 0) if(timeBeforeNextLoad >= 0)
timeBeforeNextLoad--; timeBeforeNextLoad--;
else if(ms_numVehiclesLoaded <= desiredNumVehiclesLoaded){ else if(ms_numVehiclesLoaded <= desiredNumVehiclesLoaded){
for(i = 0; i <= 10; i++){ for(i = 1; i <= 10; i++){
model = CCarCtrl::ChooseCarModel(modelQualityClass); model = CCarCtrl::ChooseCarModel(modelQualityClass);
modelQualityClass++; modelQualityClass++;
if(modelQualityClass >= NUM_VEHICLE_CLASSES) if(modelQualityClass >= NUM_VEHICLE_CLASSES)
@ -1893,9 +1893,9 @@ CStreaming::AddModelsToRequestList(const CVector &pos)
CWorld::AdvanceCurrentScanCode(); CWorld::AdvanceCurrentScanCode();
for(iy = iymin; iy < iymax; iy++){ for(iy = iymin; iy <= iymax; iy++){
dy = iy - CWorld::GetSectorIndexY(pos.y); dy = iy - CWorld::GetSectorIndexY(pos.y);
for(ix = ixmin; ix < ixmax; ix++){ for(ix = ixmin; ix <= ixmax; ix++){
if(CRenderer::m_loadingPriority && ms_numModelsRequested > 5) if(CRenderer::m_loadingPriority && ms_numModelsRequested > 5)
return; return;
@ -2124,7 +2124,7 @@ CStreaming::DeleteRwObjectsAfterDeath(const CVector &pos)
CSector *sect; CSector *sect;
ix = CWorld::GetSectorIndexX(pos.x); ix = CWorld::GetSectorIndexX(pos.x);
iy = CWorld::GetSectorIndexX(pos.y); iy = CWorld::GetSectorIndexY(pos.y);
for(x = 0; x < NUMSECTORS_X; x++) for(x = 0; x < NUMSECTORS_X; x++)
for(y = 0; y < NUMSECTORS_Y; y++) for(y = 0; y < NUMSECTORS_Y; y++)
@ -2153,13 +2153,13 @@ CStreaming::DeleteRwObjectsBehindCamera(int32 mem)
return; return;
ix = CWorld::GetSectorIndexX(TheCamera.GetPosition().x); ix = CWorld::GetSectorIndexX(TheCamera.GetPosition().x);
iy = CWorld::GetSectorIndexX(TheCamera.GetPosition().y); iy = CWorld::GetSectorIndexY(TheCamera.GetPosition().y);
if(Abs(TheCamera.GetForward().x) > Abs(TheCamera.GetForward().y)){ if(Abs(TheCamera.GetForward().x) > Abs(TheCamera.GetForward().y)){
// looking west/east // looking west/east
ymin = max(iy - 10, 0); ymin = max(iy - 10, 0);
ymax = min(iy + 10, NUMSECTORS_Y); ymax = min(iy + 10, NUMSECTORS_Y - 1);
assert(ymin <= ymax); assert(ymin <= ymax);
// Delete a block of sectors that we know is behind the camera // Delete a block of sectors that we know is behind the camera
@ -2170,8 +2170,8 @@ CStreaming::DeleteRwObjectsBehindCamera(int32 mem)
inc = 1; inc = 1;
}else{ }else{
// looking west // looking west
xmax = min(ix + 2, NUMSECTORS_X); xmax = min(ix + 2, NUMSECTORS_X - 1);
xmin = min(ix + 10, NUMSECTORS_X); xmin = min(ix + 10, NUMSECTORS_X - 1);
inc = -1; inc = -1;
} }
for(y = ymin; y <= ymax; y++){ for(y = ymin; y <= ymax; y++){
@ -2192,8 +2192,8 @@ CStreaming::DeleteRwObjectsBehindCamera(int32 mem)
inc = 1; inc = 1;
}else{ }else{
// looking west // looking west
xmax = min(ix - 10, NUMSECTORS_X); xmax = min(ix - 10, NUMSECTORS_X - 1);
xmin = min(ix + 2, NUMSECTORS_X); xmin = min(ix + 2, NUMSECTORS_X - 1);
inc = -1; inc = -1;
} }
for(y = ymin; y <= ymax; y++){ for(y = ymin; y <= ymax; y++){
@ -2223,7 +2223,7 @@ CStreaming::DeleteRwObjectsBehindCamera(int32 mem)
// looking north/south // looking north/south
xmin = max(ix - 10, 0); xmin = max(ix - 10, 0);
xmax = min(ix + 10, NUMSECTORS_X); xmax = min(ix + 10, NUMSECTORS_X - 1);
assert(xmin <= xmax); assert(xmin <= xmax);
// Delete a block of sectors that we know is behind the camera // Delete a block of sectors that we know is behind the camera
@ -2234,8 +2234,8 @@ CStreaming::DeleteRwObjectsBehindCamera(int32 mem)
inc = 1; inc = 1;
}else{ }else{
// looking south // looking south
ymax = min(iy + 2, NUMSECTORS_Y); ymax = min(iy + 2, NUMSECTORS_Y - 1);
ymin = min(iy + 10, NUMSECTORS_Y); ymin = min(iy + 10, NUMSECTORS_Y - 1);
inc = -1; inc = -1;
} }
for(x = xmin; x <= xmax; x++){ for(x = xmin; x <= xmax; x++){
@ -2256,8 +2256,8 @@ CStreaming::DeleteRwObjectsBehindCamera(int32 mem)
inc = 1; inc = 1;
}else{ }else{
// looking south // looking south
ymax = min(iy - 10, NUMSECTORS_Y); ymax = min(iy - 10, NUMSECTORS_Y - 1);
ymin = min(iy + 2, NUMSECTORS_Y); ymin = min(iy + 2, NUMSECTORS_Y - 1);
inc = -1; inc = -1;
} }
for(x = xmin; x <= xmax; x++){ for(x = xmin; x <= xmax; x++){

View File

@ -143,9 +143,9 @@ CWorld::ProcessLineOfSight(const CVector &point1, const CVector &point2, CColPoi
dist = 1.0f; dist = 1.0f;
xstart = GetSectorIndexX(point1.x); xstart = GetSectorIndexX(point1.x);
ystart = GetSectorIndexX(point1.y); ystart = GetSectorIndexY(point1.y);
xend = GetSectorIndexX(point2.x); xend = GetSectorIndexX(point2.x);
yend = GetSectorIndexX(point2.y); yend = GetSectorIndexY(point2.y);
#define LOSARGS CColLine(point1, point2), point, dist, entity, checkBuildings, checkVehicles, checkPeds, checkObjects, checkDummies, ignoreSeeThrough, ignoreSomeObjects #define LOSARGS CColLine(point1, point2), point, dist, entity, checkBuildings, checkVehicles, checkPeds, checkObjects, checkDummies, ignoreSeeThrough, ignoreSomeObjects
@ -416,9 +416,9 @@ CWorld::GetIsLineOfSightClear(const CVector &point1, const CVector &point2, bool
AdvanceCurrentScanCode(); AdvanceCurrentScanCode();
xstart = GetSectorIndexX(point1.x); xstart = GetSectorIndexX(point1.x);
ystart = GetSectorIndexX(point1.y); ystart = GetSectorIndexY(point1.y);
xend = GetSectorIndexX(point2.x); xend = GetSectorIndexX(point2.x);
yend = GetSectorIndexX(point2.y); yend = GetSectorIndexY(point2.y);
#define LOSARGS CColLine(point1, point2), checkBuildings, checkVehicles, checkPeds, checkObjects, checkDummies, ignoreSeeThrough, ignoreSomeObjects #define LOSARGS CColLine(point1, point2), checkBuildings, checkVehicles, checkPeds, checkObjects, checkDummies, ignoreSeeThrough, ignoreSomeObjects
@ -638,20 +638,24 @@ void
CWorld::FindObjectsInRange(CVector &centre, float distance, bool ignoreZ, short *nextObject, short lastObject, CEntity **objects, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies) CWorld::FindObjectsInRange(CVector &centre, float distance, bool ignoreZ, short *nextObject, short lastObject, CEntity **objects, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies)
{ {
int minX = GetSectorIndexX(centre.x - distance); int minX = GetSectorIndexX(centre.x - distance);
if (minX <= 0) if (minX <= 0) minX = 0;
minX = 0;
int minY = GetSectorIndexY(centre.y - distance); int minY = GetSectorIndexY(centre.y - distance);
if (minY <= 0) if (minY <= 0) minY = 0;
minY = 0;
int maxX = GetSectorIndexX(centre.x + distance); int maxX = GetSectorIndexX(centre.x + distance);
if (maxX >= NUMSECTORS_X) #ifdef FIX_BUGS
maxX = NUMSECTORS_X; if (maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X - 1;
#else
if (maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X;
#endif
int maxY = GetSectorIndexY(centre.y + distance); int maxY = GetSectorIndexY(centre.y + distance);
if (maxY >= NUMSECTORS_Y) #ifdef FIX_BUGS
maxY = NUMSECTORS_Y; if (maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y - 1;
#else
if (maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y;
#endif
AdvanceCurrentScanCode(); AdvanceCurrentScanCode();
@ -689,20 +693,24 @@ CWorld::TestSphereAgainstWorld(CVector centre, float distance, CEntity *entityTo
CEntity* foundE = nil; CEntity* foundE = nil;
int minX = GetSectorIndexX(centre.x - distance); int minX = GetSectorIndexX(centre.x - distance);
if (minX <= 0) if (minX <= 0) minX = 0;
minX = 0;
int minY = GetSectorIndexY(centre.y - distance); int minY = GetSectorIndexY(centre.y - distance);
if (minY <= 0) if (minY <= 0) minY = 0;
minY = 0;
int maxX = GetSectorIndexX(centre.x + distance); int maxX = GetSectorIndexX(centre.x + distance);
if (maxX >= NUMSECTORS_X) #ifdef FIX_BUGS
maxX = NUMSECTORS_X; if (maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X - 1;
#else
if (maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X;
#endif
int maxY = GetSectorIndexY(centre.y + distance); int maxY = GetSectorIndexY(centre.y + distance);
if (maxY >= NUMSECTORS_Y) #ifdef FIX_BUGS
maxY = NUMSECTORS_Y; if (maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y - 1;
#else
if (maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y;
#endif
AdvanceCurrentScanCode(); AdvanceCurrentScanCode();
@ -1171,8 +1179,7 @@ CWorld::Process(void)
for (CPtrNode* node = ms_listMovingEntityPtrs.first; node; node = node->next) { for (CPtrNode* node = ms_listMovingEntityPtrs.first; node; node = node->next) {
CPed* movingPed = (CPed*)node->item; CPed* movingPed = (CPed*)node->item;
if (movingPed->IsPed()) { if (movingPed->IsPed()) {
if (movingPed->bInVehicle && movingPed->m_nPedState != PED_EXIT_TRAIN if (movingPed->bInVehicle && movingPed->m_nPedState != PED_EXIT_TRAIN || movingPed->EnteringCar()) {
|| movingPed->m_nPedState == PED_ENTER_CAR || movingPed->m_nPedState == PED_CARJACK) {
CVehicle *movingCar = movingPed->m_pMyVehicle; CVehicle *movingCar = movingPed->m_pMyVehicle;
if (movingCar) { if (movingCar) {
if (movingCar->IsTrain()) { if (movingCar->IsTrain()) {

View File

@ -16,8 +16,12 @@ class CDummyObject_ : public CDummyObject
{ {
public: public:
void dtor(void) { CDummyObject::~CDummyObject(); } void dtor(void) { CDummyObject::~CDummyObject(); }
CDummyObject *ctor(void) { return ::new (this) CDummyObject(); }
CDummyObject *ctor(CObject *obj) { return ::new (this) CDummyObject(obj); }
}; };
STARTPATCHES STARTPATCHES
InjectHook(0x4BAAF0, (CDummyObject* (CDummyObject::*)(void)) &CDummyObject_::ctor, PATCH_JUMP);
InjectHook(0x4BAB10, (CDummyObject* (CDummyObject::*)(CObject*)) &CDummyObject_::ctor, PATCH_JUMP);
InjectHook(0x4BAB70, &CDummyObject_::dtor, PATCH_JUMP); InjectHook(0x4BAB70, &CDummyObject_::dtor, PATCH_JUMP);
ENDPATCHES ENDPATCHES

View File

@ -52,7 +52,7 @@ public:
int8 field_17D; int8 field_17D;
int8 field_17E; int8 field_17E;
int8 field_17F; int8 field_17F;
int32 m_nEndOfLifeTime; uint32 m_nEndOfLifeTime;
int16 m_nRefModelIndex; int16 m_nRefModelIndex;
int8 field_186; int8 field_186;
int8 field_187; int8 field_187;

View File

@ -1,10 +1,14 @@
#include "common.h" #include "common.h"
#include "patcher.h" #include "patcher.h"
#include "World.h"
#include "PlayerPed.h"
#include "CopPed.h" #include "CopPed.h"
#include "ModelIndices.h" #include "ModelIndices.h"
#include "Vehicle.h"
#include "RpAnimBlend.h"
#include "General.h"
WRAPPER void CCopPed::ProcessControl() { EAXJMP(0x4C1400); } WRAPPER void CCopPed::ProcessControl() { EAXJMP(0x4C1400); }
WRAPPER void CCopPed::SetArrestPlayer(CPed*) { EAXJMP(0x4C2B00); }
CCopPed::CCopPed(eCopType copType) : CPed(PEDTYPE_COP) CCopPed::CCopPed(eCopType copType) : CPed(PEDTYPE_COP)
{ {
@ -66,7 +70,210 @@ CCopPed::~CCopPed()
ClearPursuit(); 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 class CCopPed_ : public CCopPed
{ {
@ -78,4 +285,9 @@ public:
STARTPATCHES STARTPATCHES
InjectHook(0x4C11B0, &CCopPed_::ctor, PATCH_JUMP); InjectHook(0x4C11B0, &CCopPed_::ctor, PATCH_JUMP);
InjectHook(0x4C13E0, &CCopPed_::dtor, 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 ENDPATCHES

View File

@ -37,6 +37,9 @@ public:
void ClearPursuit(void); void ClearPursuit(void);
void ProcessControl(void); void ProcessControl(void);
void SetArrestPlayer(CPed*); void SetArrestPlayer(CPed*);
void SetPursuit(bool);
void ArrestPlayer(void);
void ScanForCrimes(void);
}; };
static_assert(sizeof(CCopPed) == 0x558, "CCopPed: error"); static_assert(sizeof(CCopPed) == 0x558, "CCopPed: error");

View File

@ -303,7 +303,7 @@ CEmergencyPed::MedicAI(void)
if (!m_pRevivedPed || m_pRevivedPed->m_fHealth > 0.0f || m_pRevivedPed->bFadeOut) { if (!m_pRevivedPed || m_pRevivedPed->m_fHealth > 0.0f || m_pRevivedPed->bFadeOut) {
m_nEmergencyPedState = EMERGENCY_PED_DETERMINE_NEXT_STATE; m_nEmergencyPedState = EMERGENCY_PED_DETERMINE_NEXT_STATE;
} else { } else {
m_pRevivedPed->m_bloodyFootprintCount = CTimer::GetTimeInMilliseconds(); m_pRevivedPed->m_bloodyFootprintCountOrDeathTime = CTimer::GetTimeInMilliseconds();
SetMoveState(PEDMOVE_STILL); SetMoveState(PEDMOVE_STILL);
m_nPedState = PED_CPR; m_nPedState = PED_CPR;
m_nLastPedState = PED_CPR; m_nLastPedState = PED_CPR;

View File

@ -49,19 +49,56 @@
#include "ParticleObject.h" #include "ParticleObject.h"
#include "Floater.h" #include "Floater.h"
#define FEET_OFFSET 1.04f #define CAN_SEE_ENTITY_ANGLE_THRESHOLD DEGTORAD(60.0f)
CPed *gapTempPedList[50]; CPed *gapTempPedList[50];
uint16 gnNumTempPedList; uint16 gnNumTempPedList;
bool &CPed::bNastyLimbsCheat = *(bool*)0x95CD44;
bool &CPed::bPedCheat2 = *(bool*)0x95CD5A;
bool &CPed::bPedCheat3 = *(bool*)0x95CD59;
CColPoint &aTempPedColPts = *(CColPoint*)0x62DB14; CColPoint &aTempPedColPts = *(CColPoint*)0x62DB14;
// TODO: CommentWaitTime should be hardcoded into exe, and it isn't reversed yet. // Corresponds to ped sounds (from SOUND_PED_DEATH to SOUND_PED_TAXI_CALL)
CPedAudioData (&CPed::CommentWaitTime)[38] = *(CPedAudioData(*)[38]) * (uintptr*)0x5F94C4; 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},
};
// *(CPedAudioData(*)[39]) * (uintptr*)0x5F94C4;
uint16 nPlayerInComboMove; uint16 nPlayerInComboMove;
@ -106,6 +143,9 @@ CVector vecPedQuickDraggedOutCarAnimOffset;
CVector vecPedDraggedOutCarAnimOffset; CVector vecPedDraggedOutCarAnimOffset;
CVector vecPedTrainDoorAnimOffset; CVector vecPedTrainDoorAnimOffset;
bool &CPed::bNastyLimbsCheat = *(bool*)0x95CD44;
bool &CPed::bPedCheat2 = *(bool*)0x95CD5A;
bool &CPed::bPedCheat3 = *(bool*)0x95CD59;
CVector2D CPed::ms_vec2DFleePosition; CVector2D CPed::ms_vec2DFleePosition;
void *CPed::operator new(size_t sz) { return CPools::GetPedPool()->New(); } void *CPed::operator new(size_t sz) { return CPools::GetPedPool()->New(); }
@ -351,7 +391,7 @@ CPed::~CPed(void)
m_pMyVehicle->m_nGettingOutFlags &= ~door_flag; m_pMyVehicle->m_nGettingOutFlags &= ~door_flag;
bInVehicle = false; bInVehicle = false;
m_pMyVehicle = nil; m_pMyVehicle = nil;
} else if (m_nPedState == PED_ENTER_CAR || m_nPedState == PED_CARJACK){ } else if (EnteringCar()) {
QuitEnteringCar(); QuitEnteringCar();
} }
if (m_pFire) if (m_pFire)
@ -745,8 +785,7 @@ CPed::UseGroundColModel(void)
bool bool
CPed::CanSetPedState(void) CPed::CanSetPedState(void)
{ {
return m_nPedState != PED_DIE && m_nPedState != PED_ARRESTED && return !DyingOrDead() && m_nPedState != PED_ARRESTED && !EnteringCar() && m_nPedState != PED_STEAL_CAR;
m_nPedState != PED_ENTER_CAR && m_nPedState != PED_DEAD && m_nPedState != PED_CARJACK && m_nPedState != PED_STEAL_CAR;
} }
bool bool
@ -1912,7 +1951,7 @@ CPed::LineUpPedWithCar(PedLineUpPhase phase)
// Smoothly change ped position // Smoothly change ped position
neededPos.z = (neededPos.z - currentZ) / (m_pVehicleAnim->GetTimeLeft() / adjustedTimeStep) + currentZ; neededPos.z = (neededPos.z - currentZ) / (m_pVehicleAnim->GetTimeLeft() / adjustedTimeStep) + currentZ;
} else if (m_nPedState == PED_ENTER_CAR || m_nPedState == PED_CARJACK) { } else if (EnteringCar()) {
neededPos.z = max(currentZ, autoZPos.z); neededPos.z = max(currentZ, autoZPos.z);
} }
#ifdef VC_PED_PORTS #ifdef VC_PED_PORTS
@ -1999,10 +2038,10 @@ void
CPed::PlayFootSteps(void) CPed::PlayFootSteps(void)
{ {
if (bDoBloodyFootprints) { if (bDoBloodyFootprints) {
if (m_bloodyFootprintCount > 0 && m_bloodyFootprintCount < 300) { if (m_bloodyFootprintCountOrDeathTime > 0 && m_bloodyFootprintCountOrDeathTime < 300) {
m_bloodyFootprintCount--; m_bloodyFootprintCountOrDeathTime--;
if (m_bloodyFootprintCount == 0) if (m_bloodyFootprintCountOrDeathTime == 0)
bDoBloodyFootprints = false; bDoBloodyFootprints = false;
} }
} }
@ -2055,11 +2094,11 @@ CPed::PlayFootSteps(void)
right.x, right.y, right.x, right.y,
255, 255, 0, 0, 4.0f, 3000.0f, 1.0f); 255, 255, 0, 0, 4.0f, 3000.0f, 1.0f);
if (m_bloodyFootprintCount <= 20) { if (m_bloodyFootprintCountOrDeathTime <= 20) {
m_bloodyFootprintCount = 0; m_bloodyFootprintCountOrDeathTime = 0;
bDoBloodyFootprints = false; bDoBloodyFootprints = false;
} else { } else {
m_bloodyFootprintCount -= 20; m_bloodyFootprintCountOrDeathTime -= 20;
} }
} }
if (CWeather::Rain <= 0.1f || CCullZones::CamNoRain() || CCullZones::PlayerNoRain()) { if (CWeather::Rain <= 0.1f || CCullZones::CamNoRain() || CCullZones::PlayerNoRain()) {
@ -2482,7 +2521,7 @@ CPed::CanPedReturnToState(void)
} }
bool bool
CPed::CanSeeEntity(CEntity *entity, float threshold) CPed::CanSeeEntity(CEntity *entity, float threshold = CAN_SEE_ENTITY_ANGLE_THRESHOLD)
{ {
float neededAngle = CGeneral::GetRadianAngleBetweenPoints( float neededAngle = CGeneral::GetRadianAngleBetweenPoints(
entity->GetPosition().x, entity->GetPosition().x,
@ -3353,7 +3392,7 @@ CPed::CheckForPointBlankPeds(CPed *pedToVerify)
if (nearPedState == PED_FALL || nearPedState == PED_GETUP || nearPedState == PED_DIE || nearPedState == PED_DEAD || nearPedState == PED_DIVE_AWAY) if (nearPedState == PED_FALL || nearPedState == PED_GETUP || nearPedState == PED_DIE || nearPedState == PED_DEAD || nearPedState == PED_DIVE_AWAY)
return NO_POINT_BLANK_PED; return NO_POINT_BLANK_PED;
if (neededTurn < DEGTORAD(60.0f)) { if (neededTurn < CAN_SEE_ENTITY_ANGLE_THRESHOLD) {
if (pedToVerify == nearPed) if (pedToVerify == nearPed)
return POINT_BLANK_FOR_WANTED_PED; return POINT_BLANK_FOR_WANTED_PED;
else else
@ -3415,6 +3454,13 @@ CPed::ClearAttack(void)
if (m_nPedState != PED_ATTACK || bIsDucking || m_nWaitState == WAITSTATE_PLAYANIM_DUCK) if (m_nPedState != PED_ATTACK || bIsDucking || m_nWaitState == WAITSTATE_PLAYANIM_DUCK)
return; return;
#ifdef VC_PED_PORTS
// VC uses CCamera::Using1stPersonWeaponMode
if (FindPlayerPed() == this && (TheCamera.PlayerWeaponMode.Mode == CCam::MODE_SNIPER ||
TheCamera.PlayerWeaponMode.Mode == CCam::MODE_M16_1STPERSON || TheCamera.PlayerWeaponMode.Mode == CCam::MODE_ROCKETLAUNCHER)) {
SetPointGunAt(nil);
} else
#endif
if (bIsPointingGunAt) { if (bIsPointingGunAt) {
if (m_pLookTarget) if (m_pLookTarget)
SetPointGunAt(m_pLookTarget); SetPointGunAt(m_pLookTarget);
@ -3504,7 +3550,7 @@ CPed::SetDie(AnimationId animId, float delta, float speed)
} else if (bInVehicle) { } else if (bInVehicle) {
if (m_pVehicleAnim) if (m_pVehicleAnim)
m_pVehicleAnim->blendDelta = -1000.0f; m_pVehicleAnim->blendDelta = -1000.0f;
} else if (m_nPedState == PED_ENTER_CAR || m_nPedState == PED_CARJACK) { } else if (EnteringCar()) {
QuitEnteringCar(); QuitEnteringCar();
} }
@ -3529,8 +3575,7 @@ CPed::SetDie(AnimationId animId, float delta, float speed)
if (!bInVehicle) if (!bInVehicle)
StopNonPartialAnims(); StopNonPartialAnims();
// BUG: This is not timer. m_bloodyFootprintCountOrDeathTime = CTimer::GetTimeInMilliseconds();
m_bloodyFootprintCount = CTimer::GetTimeInMilliseconds();
} }
bool bool
@ -5924,8 +5969,7 @@ CPed::SetDead(void)
CreateDeadPedMoney(); CreateDeadPedMoney();
} }
// BUG: Is this count or timer?! m_bloodyFootprintCountOrDeathTime = CTimer::GetTimeInMilliseconds();
m_bloodyFootprintCount = CTimer::GetTimeInMilliseconds();
m_deadBleeding = false; m_deadBleeding = false;
bDoBloodyFootprints = false; bDoBloodyFootprints = false;
bVehExitWillBeInstant = false; bVehExitWillBeInstant = false;
@ -6066,7 +6110,7 @@ CPed::DuckAndCover(void)
CVector pos = GetPosition(); CVector pos = GetPosition();
int16 lastVehicle; int16 lastVehicle;
CEntity *vehicles[8]; CEntity *vehicles[8];
CWorld::FindObjectsInRange(pos, 15.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false); CWorld::FindObjectsInRange(pos, CHECK_NEARBY_THINGS_MAX_DIST, true, &lastVehicle, 6, vehicles, false, true, false, false, false);
for (int i = 0; i < lastVehicle; i++) { for (int i = 0; i < lastVehicle; i++) {
CVehicle *veh = (CVehicle*) vehicles[i]; CVehicle *veh = (CVehicle*) vehicles[i];
@ -6971,11 +7015,11 @@ CPed::FinishLaunchCB(CAnimBlendAssociation *animAssoc, void *arg)
0.14f * ped->GetRight().y, 0.14f * ped->GetRight().y,
255, 255, 0, 0, 4.0f, 3000, 1.0f); 255, 255, 0, 0, 4.0f, 3000, 1.0f);
if (ped->m_bloodyFootprintCount <= 40) { if (ped->m_bloodyFootprintCountOrDeathTime <= 40) {
ped->m_bloodyFootprintCount = 0; ped->m_bloodyFootprintCountOrDeathTime = 0;
ped->bDoBloodyFootprints = false; ped->bDoBloodyFootprints = false;
} else { } else {
ped->m_bloodyFootprintCount -= 40; ped->m_bloodyFootprintCountOrDeathTime -= 40;
} }
} }
} }
@ -8674,18 +8718,29 @@ CPed::LookForInterestingNodes(void)
bool found = false; bool found = false;
uint8 randVal = CGeneral::GetRandomNumber() % 256; uint8 randVal = CGeneral::GetRandomNumber() % 256;
int minX = CWorld::GetSectorIndexX(GetPosition().x - 15.0f); int minX = CWorld::GetSectorIndexX(GetPosition().x - CHECK_NEARBY_THINGS_MAX_DIST);
if (minX < 0) minX = 0; if (minX < 0) minX = 0;
int minY = CWorld::GetSectorIndexY(GetPosition().y - 15.0f); int minY = CWorld::GetSectorIndexY(GetPosition().y - CHECK_NEARBY_THINGS_MAX_DIST);
if (minY < 0) minY = 0; if (minY < 0) minY = 0;
int maxX = CWorld::GetSectorIndexX(GetPosition().x + 15.0f); int maxX = CWorld::GetSectorIndexX(GetPosition().x + CHECK_NEARBY_THINGS_MAX_DIST);
if (maxX > NUMSECTORS_X) maxX = NUMSECTORS_X; #ifdef FIX_BUGS
int maxY = CWorld::GetSectorIndexY(GetPosition().y + 15.0f); if (maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X - 1;
if (maxY > NUMSECTORS_Y) maxY = NUMSECTORS_Y; #else
if (maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X;
#endif
int maxY = CWorld::GetSectorIndexY(GetPosition().y + CHECK_NEARBY_THINGS_MAX_DIST);
#ifdef FIX_BUGS
if (maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y - 1;
#else
if (maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y;
#endif
for (int curY = minY; curY <= maxY && !found; curY++) { for (int curY = minY; curY <= maxY && !found; curY++) {
for (int curX = minX; curX <= maxX && !found; curX++) { for (int curX = minX; curX <= maxX && !found; curX++) {
for (ptrNode = CWorld::GetSector(curX, curY)->m_lists[ENTITYLIST_VEHICLES].first; ptrNode && !found; ptrNode = ptrNode->next) { CSector *sector = CWorld::GetSector(curX, curY);
for (ptrNode = sector->m_lists[ENTITYLIST_VEHICLES].first; ptrNode && !found; ptrNode = ptrNode->next) {
CVehicle *veh = (CVehicle*)ptrNode->item; CVehicle *veh = (CVehicle*)ptrNode->item;
model = veh->GetModelInfo(); model = veh->GetModelInfo();
if (model->m_num2dEffects != 0) { if (model->m_num2dEffects != 0) {
@ -8703,7 +8758,7 @@ CPed::LookForInterestingNodes(void)
} }
} }
} }
for (ptrNode = CWorld::GetSector(curX, curY)->m_lists[ENTITYLIST_OBJECTS].first; ptrNode && !found; ptrNode = ptrNode->next) { for (ptrNode = sector->m_lists[ENTITYLIST_OBJECTS].first; ptrNode && !found; ptrNode = ptrNode->next) {
CObject *obj = (CObject*)ptrNode->item; CObject *obj = (CObject*)ptrNode->item;
model = CModelInfo::GetModelInfo(obj->m_modelIndex); model = CModelInfo::GetModelInfo(obj->m_modelIndex);
if (model->m_num2dEffects != 0) { if (model->m_num2dEffects != 0) {
@ -8721,7 +8776,7 @@ CPed::LookForInterestingNodes(void)
} }
} }
} }
for (ptrNode = CWorld::GetSector(curX, curY)->m_lists[ENTITYLIST_BUILDINGS].first; ptrNode && !found; ptrNode = ptrNode->next) { for (ptrNode = sector->m_lists[ENTITYLIST_BUILDINGS].first; ptrNode && !found; ptrNode = ptrNode->next) {
CBuilding *building = (CBuilding*)ptrNode->item; CBuilding *building = (CBuilding*)ptrNode->item;
model = CModelInfo::GetModelInfo(building->m_modelIndex); model = CModelInfo::GetModelInfo(building->m_modelIndex);
if (model->m_num2dEffects != 0) { if (model->m_num2dEffects != 0) {
@ -8739,7 +8794,7 @@ CPed::LookForInterestingNodes(void)
} }
} }
} }
for (ptrNode = CWorld::GetSector(curX, curY)->m_lists[ENTITYLIST_BUILDINGS_OVERLAP].first; ptrNode && !found; ptrNode = ptrNode->next) { for (ptrNode = sector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP].first; ptrNode && !found; ptrNode = ptrNode->next) {
CBuilding *building = (CBuilding*)ptrNode->item; CBuilding *building = (CBuilding*)ptrNode->item;
model = CModelInfo::GetModelInfo(building->m_modelIndex); model = CModelInfo::GetModelInfo(building->m_modelIndex);
if (model->m_num2dEffects != 0) { if (model->m_num2dEffects != 0) {
@ -8847,11 +8902,8 @@ CPed::LookForSexyPeds(void)
return; return;
for (int i = 0; i < m_numNearPeds; i++) { for (int i = 0; i < m_numNearPeds; i++) {
if (CanSeeEntity(m_nearPeds[i])) {
if (CanSeeEntity(m_nearPeds[i], DEGTORAD(60.0f))) {
if ((GetPosition() - m_nearPeds[i]->GetPosition()).Magnitude() < 10.0f) { if ((GetPosition() - m_nearPeds[i]->GetPosition()).Magnitude() < 10.0f) {
CPed *nearPed = m_nearPeds[i]; CPed *nearPed = m_nearPeds[i];
if ((nearPed->m_pedStats->m_sexiness > m_pedStats->m_sexiness) if ((nearPed->m_pedStats->m_sexiness > m_pedStats->m_sexiness)
&& nearPed->m_nPedType == PEDTYPE_CIVFEMALE) { && nearPed->m_nPedType == PEDTYPE_CIVFEMALE) {
@ -9097,7 +9149,7 @@ CPed::PedAnimAlignCB(CAnimBlendAssociation *animAssoc, void *arg)
if (!ped->IsNotInWreckedVehicle()) if (!ped->IsNotInWreckedVehicle())
return; return;
if (ped->m_nPedState != PED_ENTER_CAR && ped->m_nPedState != PED_CARJACK) { if (!ped->EnteringCar()) {
ped->QuitEnteringCar(); ped->QuitEnteringCar();
return; return;
} }
@ -9237,7 +9289,7 @@ CPed::ProcessControl(void)
#else #else
if (CGame::nastyGame && !bIsInWater) { if (CGame::nastyGame && !bIsInWater) {
#endif #endif
uint32 remainingBloodyFpTime = CTimer::GetTimeInMilliseconds() - m_bloodyFootprintCount; uint32 remainingBloodyFpTime = CTimer::GetTimeInMilliseconds() - m_bloodyFootprintCountOrDeathTime;
float timeDependentDist; float timeDependentDist;
if (remainingBloodyFpTime >= 2000) { if (remainingBloodyFpTime >= 2000) {
if (remainingBloodyFpTime <= 7000) if (remainingBloodyFpTime <= 7000)
@ -9253,7 +9305,7 @@ CPed::ProcessControl(void)
if (!nearPed->DyingOrDead()) { if (!nearPed->DyingOrDead()) {
CVector dist = nearPed->GetPosition() - GetPosition(); CVector dist = nearPed->GetPosition() - GetPosition();
if (dist.MagnitudeSqr() < sq(timeDependentDist)) { if (dist.MagnitudeSqr() < sq(timeDependentDist)) {
nearPed->m_bloodyFootprintCount = 200; nearPed->m_bloodyFootprintCountOrDeathTime = 200;
nearPed->bDoBloodyFootprints = true; nearPed->bDoBloodyFootprints = true;
if (nearPed->IsPlayer()) { if (nearPed->IsPlayer()) {
if (!nearPed->bIsLooking && nearPed->m_nPedState != PED_ATTACK) { if (!nearPed->bIsLooking && nearPed->m_nPedState != PED_ATTACK) {
@ -10313,7 +10365,7 @@ CPed::ProcessControl(void)
CPed::Chat(); CPed::Chat();
break; break;
case PED_AIM_GUN: case PED_AIM_GUN:
if (m_pPointGunAt && m_pPointGunAt->IsPed() && ((CPed*)m_pPointGunAt)->CanSeeEntity(this, DEGTORAD(120.0f))) { if (m_pPointGunAt && m_pPointGunAt->IsPed() && ((CPed*)m_pPointGunAt)->CanSeeEntity(this, CAN_SEE_ENTITY_ANGLE_THRESHOLD * 2)) {
((CPed*)m_pPointGunAt)->ReactToPointGun(this); ((CPed*)m_pPointGunAt)->ReactToPointGun(this);
} }
PointGunAt(); PointGunAt();
@ -10588,7 +10640,7 @@ CPed::PedAnimDoorCloseCB(CAnimBlendAssociation *animAssoc, void *arg)
if (!ped->IsNotInWreckedVehicle() || ped->DyingOrDead()) if (!ped->IsNotInWreckedVehicle() || ped->DyingOrDead())
return; return;
if (ped->m_nPedState == PED_CARJACK || ped->m_nPedState == PED_ENTER_CAR) { if (ped->EnteringCar()) {
bool isLow = veh->bLowVehicle; bool isLow = veh->bLowVehicle;
if (!veh->bIsBus) if (!veh->bIsBus)
@ -10681,7 +10733,7 @@ CPed::PedAnimDoorOpenCB(CAnimBlendAssociation* animAssoc, void* arg)
if (!ped->IsNotInWreckedVehicle()) if (!ped->IsNotInWreckedVehicle())
return; return;
if (ped->m_nPedState != PED_CARJACK && ped->m_nPedState != PED_ENTER_CAR) { if (!ped->EnteringCar()) {
ped->QuitEnteringCar(); ped->QuitEnteringCar();
return; return;
} }
@ -10926,7 +10978,7 @@ CPed::PedAnimGetInCB(CAnimBlendAssociation *animAssoc, void *arg)
if (!ped->IsNotInWreckedVehicle() || ped->DyingOrDead()) if (!ped->IsNotInWreckedVehicle() || ped->DyingOrDead())
return; return;
if (ped->m_nPedState != PED_CARJACK && ped->m_nPedState != PED_ENTER_CAR) { if (!ped->EnteringCar()) {
ped->QuitEnteringCar(); ped->QuitEnteringCar();
return; return;
} }
@ -11018,7 +11070,10 @@ CPed::PedAnimGetInCB(CAnimBlendAssociation *animAssoc, void *arg)
if ((ped->m_nPedType != PEDTYPE_EMERGENCY || veh->pDriver->m_nPedType != PEDTYPE_EMERGENCY) if ((ped->m_nPedType != PEDTYPE_EMERGENCY || veh->pDriver->m_nPedType != PEDTYPE_EMERGENCY)
&& (ped->m_nPedType != PEDTYPE_COP || veh->pDriver->m_nPedType != PEDTYPE_COP)) { && (ped->m_nPedType != PEDTYPE_COP || veh->pDriver->m_nPedType != PEDTYPE_COP)) {
veh->pDriver->SetObjective(OBJECTIVE_LEAVE_VEHICLE, veh); veh->pDriver->SetObjective(OBJECTIVE_LEAVE_VEHICLE, veh);
veh->pDriver->Say(SOUND_PICKUP_WEAPON_BOUGHT); veh->pDriver->Say(SOUND_PED_CAR_JACKED);
#ifdef VC_PED_PORTS
veh->pDriver->SetRadioStation();
#endif
} else { } else {
ped->m_objective = OBJECTIVE_ENTER_CAR_AS_PASSENGER; ped->m_objective = OBJECTIVE_ENTER_CAR_AS_PASSENGER;
} }
@ -11063,7 +11118,7 @@ CPed::PedAnimPullPedOutCB(CAnimBlendAssociation* animAssoc, void* arg)
if (animAssoc) if (animAssoc)
animAssoc->blendDelta = -1000.0f; animAssoc->blendDelta = -1000.0f;
if (ped->m_nPedState == PED_CARJACK || ped->m_nPedState == PED_ENTER_CAR) { if (ped->EnteringCar()) {
if (!ped->IsNotInWreckedVehicle()) if (!ped->IsNotInWreckedVehicle())
return; return;
@ -12809,10 +12864,10 @@ CPed::ProcessObjective(void)
if (distWithTargetSc > wepRange if (distWithTargetSc > wepRange
|| m_pedInObjective->m_getUpTimer > CTimer::GetTimeInMilliseconds() || m_pedInObjective->m_getUpTimer > CTimer::GetTimeInMilliseconds()
|| m_pedInObjective->m_nPedState == PED_ARRESTED || m_pedInObjective->m_nPedState == PED_ARRESTED
|| (m_pedInObjective->m_nPedState == PED_ENTER_CAR || m_pedInObjective->m_nPedState == PED_CARJACK) && distWithTargetSc < 3.0f || m_pedInObjective->EnteringCar() && distWithTargetSc < 3.0f
|| distWithTargetSc > m_distanceToCountSeekDone && !CanSeeEntity(m_pedInObjective, DEGTORAD(60.0f))) { || distWithTargetSc > m_distanceToCountSeekDone && !CanSeeEntity(m_pedInObjective)) {
if (m_pedInObjective->m_nPedState == PED_ENTER_CAR || m_pedInObjective->m_nPedState == PED_CARJACK) if (m_pedInObjective->EnteringCar())
wepRangeAdjusted = 2.0f; wepRangeAdjusted = 2.0f;
if (bUsePedNodeSeek) { if (bUsePedNodeSeek) {
@ -13110,7 +13165,7 @@ CPed::ProcessObjective(void)
break; break;
} }
if (m_objectiveTimer && m_objectiveTimer < CTimer::GetTimeInMilliseconds()) { if (m_objectiveTimer && m_objectiveTimer < CTimer::GetTimeInMilliseconds()) {
if (m_nPedState != PED_CARJACK && m_nPedState != PED_ENTER_CAR) { if (!EnteringCar()) {
bool foundSeat = false; bool foundSeat = false;
if (m_carInObjective->pPassengers[0] || m_carInObjective->m_nGettingInFlags & CAR_DOOR_FLAG_RF) { if (m_carInObjective->pPassengers[0] || m_carInObjective->m_nGettingInFlags & CAR_DOOR_FLAG_RF) {
if (m_carInObjective->pPassengers[1] || m_carInObjective->m_nGettingInFlags & CAR_DOOR_FLAG_LR) { if (m_carInObjective->pPassengers[1] || m_carInObjective->m_nGettingInFlags & CAR_DOOR_FLAG_LR) {
@ -13452,7 +13507,7 @@ CPed::ProcessObjective(void)
SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, m_carInObjective); SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, m_carInObjective);
} else { } else {
CVehicle* trainToEnter = nil; CVehicle* trainToEnter = nil;
float closestCarDist = 15.0f; float closestCarDist = CHECK_NEARBY_THINGS_MAX_DIST;
CVector pos = GetPosition(); CVector pos = GetPosition();
int16 lastVehicle; int16 lastVehicle;
CEntity* vehicles[8]; CEntity* vehicles[8];
@ -13500,7 +13555,7 @@ CPed::ProcessObjective(void)
int16 lastVehicle; int16 lastVehicle;
CEntity *vehicles[8]; CEntity *vehicles[8];
CWorld::FindObjectsInRange(pos, 15.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false); CWorld::FindObjectsInRange(pos, CHECK_NEARBY_THINGS_MAX_DIST, true, &lastVehicle, 6, vehicles, false, true, false, false, false);
for(int i = 0; i < lastVehicle; i++) { for(int i = 0; i < lastVehicle; i++) {
CVehicle *nearVeh = (CVehicle*)vehicles[i]; CVehicle *nearVeh = (CVehicle*)vehicles[i];
if (nearVeh->VehicleCreatedBy != MISSION_VEHICLE) { if (nearVeh->VehicleCreatedBy != MISSION_VEHICLE) {
@ -15497,7 +15552,7 @@ CPed::ScanForInterestingStuff(void)
} }
} }
if (m_nPedState == PEDTYPE_CIVFEMALE) { if (m_nPedState == PED_WANDER_PATH) {
#ifndef VC_PED_PORTS #ifndef VC_PED_PORTS
if (CTimer::GetTimeInMilliseconds() > m_standardTimer) { if (CTimer::GetTimeInMilliseconds() > m_standardTimer) {
@ -15509,7 +15564,7 @@ CPed::ScanForInterestingStuff(void)
else { else {
if ((GetPosition() - m_nearPeds[i]->GetPosition()).Magnitude() >= 1.8f) { if ((GetPosition() - m_nearPeds[i]->GetPosition()).Magnitude() >= 1.8f) {
m_standardTimer = CTimer::GetTimeInMilliseconds() + 30000; m_standardTimer = CTimer::GetTimeInMilliseconds() + 30000;
} else if (CanSeeEntity(m_nearPeds[i], DEGTORAD(60.0f))) { } else if (CanSeeEntity(m_nearPeds[i])) {
int time = CGeneral::GetRandomNumber() % 4000 + 10000; int time = CGeneral::GetRandomNumber() % 4000 + 10000;
SetChat(m_nearPeds[i], time); SetChat(m_nearPeds[i], time);
m_nearPeds[i]->SetChat(this, time); m_nearPeds[i]->SetChat(this, time);
@ -15525,10 +15580,10 @@ CPed::ScanForInterestingStuff(void)
} else { } else {
if (CTimer::GetTimeInMilliseconds() > m_standardTimer) { if (CTimer::GetTimeInMilliseconds() > m_standardTimer) {
for (int i = 0; i < m_numNearPeds; i ++) { for (int i = 0; i < m_numNearPeds; i ++) {
if (m_nearPeds[i]->m_nPedState == PED_WANDER_PATH) { if (m_nearPeds[i] && m_nearPeds[i]->m_nPedState == PED_WANDER_PATH) {
if ((GetPosition() - m_nearPeds[i]->GetPosition()).Magnitude() < 1.8f if ((GetPosition() - m_nearPeds[i]->GetPosition()).Magnitude() < 1.8f
&& CanSeeEntity(m_nearPeds[i], DEGTORAD(60.0f) && CanSeeEntity(m_nearPeds[i])
&& m_nearPeds[i]->CanSeeEntity(this, DEGTORAD(60.0f))) && m_nearPeds[i]->CanSeeEntity(this)
&& WillChat(m_nearPeds[i])) { && WillChat(m_nearPeds[i])) {
int time = CGeneral::GetRandomNumber() % 4000 + 10000; int time = CGeneral::GetRandomNumber() % 4000 + 10000;
@ -15550,7 +15605,7 @@ CPed::ScanForInterestingStuff(void)
CVector pos = GetPosition(); CVector pos = GetPosition();
int16 lastVehicle; int16 lastVehicle;
CEntity* vehicles[8]; CEntity* vehicles[8];
CWorld::FindObjectsInRange(pos, 15.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false); CWorld::FindObjectsInRange(pos, CHECK_NEARBY_THINGS_MAX_DIST, true, &lastVehicle, 6, vehicles, false, true, false, false, false);
for (int i = 0; i < lastVehicle; i++) { for (int i = 0; i < lastVehicle; i++) {
CVehicle* veh = (CVehicle*)vehicles[i]; CVehicle* veh = (CVehicle*)vehicles[i];
@ -15570,7 +15625,7 @@ CPed::ScanForInterestingStuff(void)
CVector pos = GetPosition(); CVector pos = GetPosition();
int16 lastVehicle; int16 lastVehicle;
CEntity* vehicles[8]; CEntity* vehicles[8];
CWorld::FindObjectsInRange(pos, 15.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false); CWorld::FindObjectsInRange(pos, CHECK_NEARBY_THINGS_MAX_DIST, true, &lastVehicle, 6, vehicles, false, true, false, false, false);
for (int i = 0; i < lastVehicle; i++) { for (int i = 0; i < lastVehicle; i++) {
CVehicle* veh = (CVehicle*)vehicles[i]; CVehicle* veh = (CVehicle*)vehicles[i];

View File

@ -13,11 +13,14 @@
#include "DMAudio.h" #include "DMAudio.h"
#include "EventList.h" #include "EventList.h"
#define FEET_OFFSET 1.04f
#define CHECK_NEARBY_THINGS_MAX_DIST 15.0f
struct CPathNode; struct CPathNode;
class CAccident; class CAccident;
class CObject; class CObject;
struct CPedAudioData struct PedAudioData
{ {
int m_nFixedDelayTime; int m_nFixedDelayTime;
int m_nOverrideFixedDelayTime; int m_nOverrideFixedDelayTime;
@ -81,7 +84,7 @@ struct FightMove
}; };
static_assert(sizeof(FightMove) == 0x18, "FightMove: error"); static_assert(sizeof(FightMove) == 0x18, "FightMove: error");
// TO-DO: This is eFightState on mobile. // TODO: This is eFightState on mobile.
enum PedFightMoves enum PedFightMoves
{ {
FIGHTMOVE_NULL, FIGHTMOVE_NULL,
@ -359,7 +362,7 @@ public:
uint8 bStartWanderPathOnFoot : 1; // exits the car if he's in it, reset after path found uint8 bStartWanderPathOnFoot : 1; // exits the car if he's in it, reset after path found
uint8 bOnBoat : 1; // not just driver, may be just standing uint8 bOnBoat : 1; // not just driver, may be just standing
uint8 bBusJacked : 1; uint8 bBusJacked : 1;
uint8 bGonnaKillTheCarJacker : 1; // only set when car is jacked from right door uint8 bGonnaKillTheCarJacker : 1; // only set when car is jacked from right door and when arrested by police
uint8 bFadeOut : 1; uint8 bFadeOut : 1;
uint8 bKnockedUpIntoAir : 1; // has ped been knocked up into the air by a car collision uint8 bKnockedUpIntoAir : 1; // has ped been knocked up into the air by a car collision
@ -496,7 +499,7 @@ public:
uint32 m_objectiveTimer; uint32 m_objectiveTimer;
uint32 m_duckTimer; uint32 m_duckTimer;
uint32 m_duckAndCoverTimer; uint32 m_duckAndCoverTimer;
int32 m_bloodyFootprintCount; uint32 m_bloodyFootprintCountOrDeathTime; // Death time when bDoBloodyFootprints is false. Weird decision
uint8 m_panicCounter; uint8 m_panicCounter;
bool m_deadBleeding; bool m_deadBleeding;
int8 m_bodyPartBleeding; // PedNode, but -1 if there isn't int8 m_bodyPartBleeding; // PedNode, but -1 if there isn't
@ -791,10 +794,13 @@ public:
CWeapon &GetWeapon(uint8 weaponType) { return m_weapons[weaponType]; } CWeapon &GetWeapon(uint8 weaponType) { return m_weapons[weaponType]; }
CWeapon *GetWeapon(void) { return &m_weapons[m_currentWeapon]; } CWeapon *GetWeapon(void) { return &m_weapons[m_currentWeapon]; }
RwFrame *GetNodeFrame(int nodeId) { return m_pFrames[nodeId]->frame; } RwFrame *GetNodeFrame(int nodeId) { return m_pFrames[nodeId]->frame; }
PedState GetPedState(void) { return m_nPedState; } PedState GetPedState(void) { return m_nPedState; }
void SetPedState(PedState state) { m_nPedState = state; } void SetPedState(PedState state) { m_nPedState = state; }
bool DyingOrDead(void) { return m_nPedState == PED_DIE || m_nPedState == PED_DEAD; } bool DyingOrDead(void) { return m_nPedState == PED_DIE || m_nPedState == PED_DEAD; }
bool InVehicle(void) { return bInVehicle && m_pMyVehicle; } // True when ped is sitting/standing in vehicle, not in enter/exit state. bool InVehicle(void) { return bInVehicle && m_pMyVehicle; } // True when ped is sitting/standing in vehicle, not in enter/exit state.
bool EnteringCar(void) { return m_nPedState == PED_ENTER_CAR || m_nPedState == PED_CARJACK; }
void ReplaceWeaponWhenExitingVehicle(void); void ReplaceWeaponWhenExitingVehicle(void);
void RemoveWeaponWhenEnteringVehicle(void); void RemoveWeaponWhenEnteringVehicle(void);
bool IsNotInWreckedVehicle(); bool IsNotInWreckedVehicle();
@ -827,7 +833,6 @@ public:
static bool &bPedCheat2; static bool &bPedCheat2;
static bool &bPedCheat3; static bool &bPedCheat3;
static CVector2D ms_vec2DFleePosition; static CVector2D ms_vec2DFleePosition;
static CPedAudioData (&CommentWaitTime)[38];
#ifdef TOGGLEABLE_BETA_FEATURES #ifdef TOGGLEABLE_BETA_FEATURES
static bool bPopHeadsOnHeadshot; static bool bPopHeadsOnHeadshot;

View File

@ -32,7 +32,7 @@ CPedPlacement::FindZCoorForPed(CVector* pos)
zForPed = max(foundColZ, foundColZ2); zForPed = max(foundColZ, foundColZ2);
if (zForPed > -99.0f) if (zForPed > -99.0f)
pos->z = 1.04f + zForPed; pos->z = FEET_OFFSET + zForPed;
} }
CEntity* CEntity*

View File

@ -1,7 +1,6 @@
#pragma once #pragma once
class CVector; #include "Ped.h"
class CEntity;
class CPedPlacement { class CPedPlacement {
public: public:

View File

@ -735,7 +735,7 @@ CPlayerPed::KeepAreaAroundPlayerClear(void)
if (nearPed->m_objective == OBJECTIVE_NONE) { if (nearPed->m_objective == OBJECTIVE_NONE) {
nearPed->SetFindPathAndFlee(this, 5000, true); nearPed->SetFindPathAndFlee(this, 5000, true);
} else { } else {
if (nearPed->m_nPedState == PED_ENTER_CAR || nearPed->m_nPedState == PED_CARJACK) if (nearPed->EnteringCar())
nearPed->QuitEnteringCar(); nearPed->QuitEnteringCar();
nearPed->ClearObjective(); nearPed->ClearObjective();
@ -750,7 +750,7 @@ CPlayerPed::KeepAreaAroundPlayerClear(void)
CVector pos = GetPosition(); CVector pos = GetPosition();
int16 lastVehicle; int16 lastVehicle;
CEntity *vehicles[8]; CEntity *vehicles[8];
CWorld::FindObjectsInRange(pos, 15.0f, true, &lastVehicle, 6, vehicles, false, true, false, false, false); CWorld::FindObjectsInRange(pos, CHECK_NEARBY_THINGS_MAX_DIST, true, &lastVehicle, 6, vehicles, false, true, false, false, false);
for (int i = 0; i < lastVehicle; i++) { for (int i = 0; i < lastVehicle; i++) {
CVehicle *veh = (CVehicle*)vehicles[i]; CVehicle *veh = (CVehicle*)vehicles[i];
@ -1181,7 +1181,7 @@ CPlayerPed::ProcessControl(void)
} }
if (m_nPedState == PED_DIE) { if (m_nPedState == PED_DIE) {
ClearWeaponTarget(); ClearWeaponTarget();
if (CTimer::GetTimeInMilliseconds() > (uint32)m_bloodyFootprintCount + 4000) if (CTimer::GetTimeInMilliseconds() > m_bloodyFootprintCountOrDeathTime + 4000)
SetDead(); SetDead();
return; return;
} }

View File

@ -18,11 +18,13 @@
#include "PedPlacement.h" #include "PedPlacement.h"
#include "DummyObject.h" #include "DummyObject.h"
#include "Script.h" #include "Script.h"
#include "Shadows.h"
#define CREATION_DIST_MULT_TO_DIST 40.0f #define MIN_CREATION_DIST 40.0f // not for start of the game (look at the GeneratePedsAtStartOfGame)
#define CREATION_RANGE 10.0f // Being added over the CREATION_DIST_MULT_TO_DIST. #define CREATION_RANGE 10.0f // added over the MIN_CREATION_DIST.
#define OFFSCREEN_CREATION_MULT 0.5f #define OFFSCREEN_CREATION_MULT 0.5f
// Also there are some hardcoded values in GeneratePedsAtStartOfGame. #define PED_REMOVE_DIST (MIN_CREATION_DIST + CREATION_RANGE + 1.0f)
#define PED_REMOVE_DIST_SPECIAL (MIN_CREATION_DIST + CREATION_RANGE + 15.0f) // for peds with bCullExtraFarAway flag
// TO-DO: These are hard-coded, reverse them. // TO-DO: These are hard-coded, reverse them.
// More clearly they're transition areas between zones. // More clearly they're transition areas between zones.
@ -57,9 +59,6 @@ CVector &CPopulation::RegenerationPoint_a = *(CVector*)0x8E2AA4;
CVector &CPopulation::RegenerationPoint_b = *(CVector*)0x8E2A98; CVector &CPopulation::RegenerationPoint_b = *(CVector*)0x8E2A98;
CVector &CPopulation::RegenerationForward = *(CVector*)0x8F1AD4; CVector &CPopulation::RegenerationForward = *(CVector*)0x8F1AD4;
WRAPPER void CPopulation::ManagePopulation(void) { EAXJMP(0x4F3B90); }
WRAPPER bool CPopulation::TestSafeForRealObject(CDummyObject*) { EAXJMP(0x4F4700); }
void void
CPopulation::Initialise() CPopulation::Initialise()
{ {
@ -416,10 +415,10 @@ CPopulation::Update()
+ ms_nTotalGangPeds + ms_nNumCivFemale + ms_nNumCivMale; + ms_nTotalGangPeds + ms_nNumCivFemale + ms_nNumCivMale;
if (!CCutsceneMgr::IsRunning()) { if (!CCutsceneMgr::IsRunning()) {
float pcdm = PedCreationDistMultiplier(); float pcdm = PedCreationDistMultiplier();
AddToPopulation(pcdm * (CREATION_DIST_MULT_TO_DIST * TheCamera.GenerationDistMultiplier), AddToPopulation(pcdm * (MIN_CREATION_DIST * TheCamera.GenerationDistMultiplier),
pcdm * ((CREATION_DIST_MULT_TO_DIST + CREATION_RANGE) * TheCamera.GenerationDistMultiplier), pcdm * ((MIN_CREATION_DIST + CREATION_RANGE) * TheCamera.GenerationDistMultiplier),
pcdm * (CREATION_DIST_MULT_TO_DIST + CREATION_RANGE) * OFFSCREEN_CREATION_MULT - CREATION_RANGE, pcdm * (MIN_CREATION_DIST + CREATION_RANGE) * OFFSCREEN_CREATION_MULT - CREATION_RANGE,
pcdm * (CREATION_DIST_MULT_TO_DIST + CREATION_RANGE) * OFFSCREEN_CREATION_MULT); pcdm * (MIN_CREATION_DIST + CREATION_RANGE) * OFFSCREEN_CREATION_MULT);
} }
} }
} }
@ -437,8 +436,8 @@ CPopulation::GeneratePedsAtStartOfGame()
+ ms_nTotalGangPeds + ms_nNumCivFemale + ms_nNumCivMale; + ms_nTotalGangPeds + ms_nNumCivFemale + ms_nNumCivMale;
// Min dist is 10.0f only for start of the game (naturally) // Min dist is 10.0f only for start of the game (naturally)
AddToPopulation(10.0f, PedCreationDistMultiplier() * (CREATION_DIST_MULT_TO_DIST + CREATION_RANGE), AddToPopulation(10.0f, PedCreationDistMultiplier() * (MIN_CREATION_DIST + CREATION_RANGE),
10.0f, PedCreationDistMultiplier() * (CREATION_DIST_MULT_TO_DIST + CREATION_RANGE)); 10.0f, PedCreationDistMultiplier() * (MIN_CREATION_DIST + CREATION_RANGE));
} }
} }
@ -570,13 +569,13 @@ CPopulation::AddToPopulation(float minDist, float maxDist, float minDistOffScree
|| CCarCtrl::NumFiretrucksOnDuty + CCarCtrl::NumAmbulancesOnDuty + CCarCtrl::NumParkedCars || CCarCtrl::NumFiretrucksOnDuty + CCarCtrl::NumAmbulancesOnDuty + CCarCtrl::NumParkedCars
+ CCarCtrl::NumMissionCars + CCarCtrl::NumLawEnforcerCars + CCarCtrl::NumRandomCars >= CCarCtrl::MaxNumberOfCarsInUse)) { + CCarCtrl::NumMissionCars + CCarCtrl::NumLawEnforcerCars + CCarCtrl::NumRandomCars >= CCarCtrl::MaxNumberOfCarsInUse)) {
addCop = true; addCop = true;
minDist = PedCreationDistMultiplier() * CREATION_DIST_MULT_TO_DIST; minDist = PedCreationDistMultiplier() * MIN_CREATION_DIST;
maxDist = PedCreationDistMultiplier() * (CREATION_DIST_MULT_TO_DIST + CREATION_RANGE); maxDist = PedCreationDistMultiplier() * (MIN_CREATION_DIST + CREATION_RANGE);
} }
} }
// Yeah, float // Yeah, float
float maxPossiblePedsForArea = (zoneInfo.pedDensity + zoneInfo.carDensity) * playerInfo->m_fRoadDensity * PedDensityMultiplier * CIniFile::PedNumberMultiplier; float maxPossiblePedsForArea = 10.0f * (zoneInfo.pedDensity + zoneInfo.carDensity) * playerInfo->m_fRoadDensity * PedDensityMultiplier * CIniFile::PedNumberMultiplier;
maxPossiblePedsForArea = min(maxPossiblePedsForArea, MaxNumberOfPedsInUse); // maxPossiblePedsForArea = min(maxPossiblePedsForArea, MaxNumberOfPedsInUse);
if (ms_nTotalPeds < maxPossiblePedsForArea || addCop) { if (ms_nTotalPeds < maxPossiblePedsForArea || addCop) {
int decisionThreshold = CGeneral::GetRandomNumberInRange(0, 1000); int decisionThreshold = CGeneral::GetRandomNumberInRange(0, 1000);
@ -689,7 +688,7 @@ CPopulation::AddToPopulation(float minDist, float maxDist, float minDistOffScree
bool farEnoughToAdd = true; bool farEnoughToAdd = true;
CMatrix mat(TheCamera.GetCameraMatrix()); CMatrix mat(TheCamera.GetCameraMatrix());
if (TheCamera.IsSphereVisible(generatedCoors, 2.0f, &mat)) { if (TheCamera.IsSphereVisible(generatedCoors, 2.0f, &mat)) {
if (PedCreationDistMultiplier() * CREATION_DIST_MULT_TO_DIST > (generatedCoors - playerCentreOfWorld).Magnitude2D()) if (PedCreationDistMultiplier() * MIN_CREATION_DIST > (generatedCoors - playerCentreOfWorld).Magnitude2D())
farEnoughToAdd = false; farEnoughToAdd = false;
} }
if (!farEnoughToAdd) if (!farEnoughToAdd)
@ -927,7 +926,6 @@ CPopulation::ConvertAllObjectsToDummyObjects()
for (int poolIndex = poolSize - 1; poolIndex >= 0; poolIndex--) { for (int poolIndex = poolSize - 1; poolIndex >= 0; poolIndex--) {
CObject *obj = CPools::GetObjectPool()->GetSlot(poolIndex); CObject *obj = CPools::GetObjectPool()->GetSlot(poolIndex);
if (obj) { if (obj) {
if (obj->CanBeDeleted()) if (obj->CanBeDeleted())
ConvertToDummyObject(obj); ConvertToDummyObject(obj);
@ -970,8 +968,6 @@ void
CPopulation::ConvertToDummyObject(CObject *obj) CPopulation::ConvertToDummyObject(CObject *obj)
{ {
CDummyObject *dummy = new CDummyObject(obj); CDummyObject *dummy = new CDummyObject(obj);
if (!dummy)
return;
dummy->GetMatrix() = obj->m_objectMatrix; dummy->GetMatrix() = obj->m_objectMatrix;
dummy->GetMatrix().UpdateRW(); dummy->GetMatrix().UpdateRW();
@ -1005,6 +1001,163 @@ CPopulation::TestRoomForDummyObject(CObject *obj)
return collidingObjs == 0; return collidingObjs == 0;
} }
bool
CPopulation::TestSafeForRealObject(CDummyObject *dummy)
{
CPtrNode *ptrNode;
CColModel *dummyCol = dummy->GetColModel();
float colRadius = dummy->GetBoundRadius();
CVector colCentre = dummy->GetBoundCentre();
int minX = CWorld::GetSectorIndexX(dummy->GetPosition().x - colRadius);
if (minX < 0) minX = 0;
int minY = CWorld::GetSectorIndexY(dummy->GetPosition().y - colRadius);
if (minY < 0) minY = 0;
int maxX = CWorld::GetSectorIndexX(dummy->GetPosition().x + colRadius);
#ifdef FIX_BUGS
if (maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X - 1;
#else
if (maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X;
#endif
int maxY = CWorld::GetSectorIndexY(dummy->GetPosition().y + colRadius);
#ifdef FIX_BUGS
if (maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y - 1;
#else
if (maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y;
#endif
static CColPoint aTempColPoints;
for (int curY = minY; curY <= maxY; curY++) {
for (int curX = minX; curX <= maxX; curX++) {
CSector *sector = CWorld::GetSector(curX, curY);
for (ptrNode = sector->m_lists[ENTITYLIST_VEHICLES].first; ptrNode; ptrNode = ptrNode->next) {
CVehicle *veh = (CVehicle*)ptrNode->item;
if (veh->m_scanCode != CWorld::GetCurrentScanCode()) {
if (veh->GetIsTouching(colCentre, colRadius)) {
veh->m_scanCode = CWorld::GetCurrentScanCode();
if (CCollision::ProcessColModels(dummy->GetMatrix(), *dummyCol, veh->GetMatrix(), *veh->GetColModel(), &aTempColPoints, nil, nil) > 0)
return false;
}
}
}
for (ptrNode = sector->m_lists[ENTITYLIST_VEHICLES_OVERLAP].first; ptrNode; ptrNode = ptrNode->next) {
CVehicle *veh = (CVehicle*)ptrNode->item;
if (veh->m_scanCode != CWorld::GetCurrentScanCode()) {
if (veh->GetIsTouching(colCentre, colRadius)) {
veh->m_scanCode = CWorld::GetCurrentScanCode();
if (CCollision::ProcessColModels(dummy->GetMatrix(), *dummyCol, veh->GetMatrix(), *veh->GetColModel(), &aTempColPoints, nil, nil) > 0)
return false;
}
}
}
}
}
return true;
}
void
CPopulation::ManagePopulation(void)
{
int frameMod32 = CTimer::GetFrameCounter() & 31;
CVector playerPos = FindPlayerCentreOfWorld(CWorld::PlayerInFocus);
// Why this code is here?! Delete temporary objects when they got too far, and convert others to "dummy" objects. (like lamp posts)
int objectPoolSize = CPools::GetObjectPool()->GetSize();
for (int i = objectPoolSize * frameMod32 / 32; i < objectPoolSize * (frameMod32 + 1) / 32; i++) {
CObject *obj = CPools::GetObjectPool()->GetSlot(i);
if (obj && obj->CanBeDeleted()) {
if ((obj->GetPosition() - playerPos).Magnitude() <= 80.0f ||
(obj->m_objectMatrix.GetPosition() - playerPos).Magnitude() <= 80.0f) {
if (obj->ObjectCreatedBy == TEMP_OBJECT && CTimer::GetTimeInMilliseconds() > obj->m_nEndOfLifeTime) {
CWorld::Remove(obj);
delete obj;
}
} else {
if (obj->ObjectCreatedBy == TEMP_OBJECT) {
CWorld::Remove(obj);
delete obj;
} else if (obj->ObjectCreatedBy != CUTSCENE_OBJECT && TestRoomForDummyObject(obj)) {
ConvertToDummyObject(obj);
}
}
}
}
// Convert them back to real objects. Dummy objects don't have collisions, so they need to be converted.
int dummyPoolSize = CPools::GetDummyPool()->GetSize();
for (int i = dummyPoolSize * frameMod32 / 32; i < dummyPoolSize * (frameMod32 + 1) / 32; i++) {
CDummy *dummy = CPools::GetDummyPool()->GetSlot(i);
if (dummy) {
if ((dummy->GetPosition() - playerPos).Magnitude() < 80.0f)
ConvertToRealObject((CDummyObject*)dummy);
}
}
int pedPoolSize = CPools::GetPedPool()->GetSize();
for (int poolIndex = pedPoolSize-1; poolIndex >= 0; poolIndex--) {
CPed *ped = CPools::GetPedPool()->GetSlot(poolIndex);
if (ped && !ped->IsPlayer() && ped->CanBeDeleted() && !ped->bInVehicle) {
if (ped->m_nPedState == PED_DEAD && CTimer::GetTimeInMilliseconds() - ped->m_bloodyFootprintCountOrDeathTime > 60000)
ped->bFadeOut = true;
if (ped->bFadeOut && CVisibilityPlugins::GetClumpAlpha(ped->GetClump()) == 0) {
RemovePed(ped);
continue;
}
float dist = (ped->GetPosition() - playerPos).Magnitude2D();
bool pedIsFarAway = false;
if (PedCreationDistMultiplier() * (PED_REMOVE_DIST_SPECIAL * TheCamera.GenerationDistMultiplier) < dist
|| (!ped->bCullExtraFarAway && PedCreationDistMultiplier() * PED_REMOVE_DIST * TheCamera.GenerationDistMultiplier < dist)
|| (PedCreationDistMultiplier() * (MIN_CREATION_DIST + CREATION_RANGE) * OFFSCREEN_CREATION_MULT < dist
&& !ped->GetIsOnScreen()
&& TheCamera.Cams[TheCamera.ActiveCam].Mode != CCam::MODE_SNIPER
&& TheCamera.Cams[TheCamera.ActiveCam].Mode != CCam::MODE_SNIPER_RUNABOUT
&& !TheCamera.Cams[TheCamera.ActiveCam].LookingLeft
&& !TheCamera.Cams[TheCamera.ActiveCam].LookingRight
&& !TheCamera.Cams[TheCamera.ActiveCam].LookingBehind))
pedIsFarAway = true;
if (!pedIsFarAway)
continue;
if (ped->m_nPedState == PED_DEAD && !ped->bFadeOut) {
CVector pedPos = ped->GetPosition();
float randAngle = (uint8) CGeneral::GetRandomNumber() * (3.14f / 128.0f); // Not PI, 3.14
switch (CGeneral::GetRandomNumber() % 3) {
case 0:
CShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpOutline1Tex, &pedPos,
0.9f * Cos(randAngle), 0.9f * Sin(randAngle), 0.9f * Sin(randAngle), -0.9f * Cos(randAngle),
255, 255, 255, 255, 4.0f, 40000, 1.0f);
break;
case 1:
CShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpOutline2Tex, &pedPos,
0.9f * Cos(randAngle), 0.9f * Sin(randAngle), 0.9f * Sin(randAngle), -0.9f * Cos(randAngle),
255, 255, 255, 255, 4.0f, 40000, 1.0f);
break;
case 2:
CShadows::AddPermanentShadow(SHADOWTYPE_DARK, gpOutline3Tex, &pedPos,
0.9f * Cos(randAngle), 0.9f * Sin(randAngle), 0.9f * Sin(randAngle), -0.9f * Cos(randAngle),
255, 255, 255, 255, 4.0f, 40000, 1.0f);
break;
default:
break;
}
}
if (ped->GetIsOnScreen())
ped->bFadeOut = true;
else
RemovePed(ped);
}
}
}
STARTPATCHES STARTPATCHES
InjectHook(0x4F3770, &CPopulation::Initialise, PATCH_JUMP); InjectHook(0x4F3770, &CPopulation::Initialise, PATCH_JUMP);
InjectHook(0x4F5780, &CPopulation::ChooseGangOccupation, PATCH_JUMP); InjectHook(0x4F5780, &CPopulation::ChooseGangOccupation, PATCH_JUMP);

View File

@ -130,12 +130,9 @@ void CHud::Draw()
Draw Crosshairs Draw Crosshairs
*/ */
if (TheCamera.Cams->Using3rdPersonMouseCam() && (!CPad::GetPad(0)->GetLookBehindForPed() || TheCamera.m_bPlayerIsInGarage) || Mode == CCam::MODE_1STPERSON_RUNABOUT) { if (TheCamera.Cams->Using3rdPersonMouseCam() && (!CPad::GetPad(0)->GetLookBehindForPed() || TheCamera.m_bPlayerIsInGarage) || Mode == CCam::MODE_1STPERSON_RUNABOUT) {
if (FindPlayerPed()) { if (FindPlayerPed() && !FindPlayerPed()->EnteringCar()) {
int32 State = FindPlayerPed()->m_nPedState; if ((WeaponType >= WEAPONTYPE_COLT45 && WeaponType <= WEAPONTYPE_M16) || WeaponType == WEAPONTYPE_FLAMETHROWER)
if (State != PED_ENTER_CAR && State != PED_CARJACK) { Mode_RunAround = 1;
if ((WeaponType >= WEAPONTYPE_COLT45 && WeaponType <= WEAPONTYPE_M16) || WeaponType == WEAPONTYPE_FLAMETHROWER)
Mode_RunAround = 1;
}
} }
} }

View File

@ -179,3 +179,6 @@ extern RwTexture *&gpBloodPoolTex;
extern RwTexture *&gpShadowExplosionTex; extern RwTexture *&gpShadowExplosionTex;
extern RwTexture *&gpShadowHeadLightsTex; extern RwTexture *&gpShadowHeadLightsTex;
extern RwTexture *&gpGoalTex; extern RwTexture *&gpGoalTex;
extern RwTexture *&gpOutline1Tex;
extern RwTexture *&gpOutline2Tex;
extern RwTexture *&gpOutline3Tex;

View File

@ -3002,9 +3002,9 @@ CAutomobile::RcbanditCheckHitWheels(void)
if(xmin < 0) xmin = 0; if(xmin < 0) xmin = 0;
xmax = CWorld::GetSectorIndexX(GetPosition().x + 2.0f); xmax = CWorld::GetSectorIndexX(GetPosition().x + 2.0f);
if(xmax > NUMSECTORS_X-1) xmax = NUMSECTORS_X-1; if(xmax > NUMSECTORS_X-1) xmax = NUMSECTORS_X-1;
ymin = CWorld::GetSectorIndexX(GetPosition().y - 2.0f); ymin = CWorld::GetSectorIndexY(GetPosition().y - 2.0f);
if(ymin < 0) ymin = 0; if(ymin < 0) ymin = 0;
ymax = CWorld::GetSectorIndexX(GetPosition().y + 2.0f); ymax = CWorld::GetSectorIndexY(GetPosition().y + 2.0f);
if(ymax > NUMSECTORS_Y-1) ymax = NUMSECTORS_X-1; if(ymax > NUMSECTORS_Y-1) ymax = NUMSECTORS_X-1;
CWorld::AdvanceCurrentScanCode(); CWorld::AdvanceCurrentScanCode();

View File

@ -261,9 +261,9 @@ CTrain::ProcessControl(void)
if(xmin < 0) xmin = 0; if(xmin < 0) xmin = 0;
xmax = CWorld::GetSectorIndexX(front.x + 3.0f); xmax = CWorld::GetSectorIndexX(front.x + 3.0f);
if(xmax > NUMSECTORS_X-1) xmax = NUMSECTORS_X-1; if(xmax > NUMSECTORS_X-1) xmax = NUMSECTORS_X-1;
ymin = CWorld::GetSectorIndexX(front.y - 3.0f); ymin = CWorld::GetSectorIndexY(front.y - 3.0f);
if(ymin < 0) ymin = 0; if(ymin < 0) ymin = 0;
ymax = CWorld::GetSectorIndexX(front.y + 3.0f); ymax = CWorld::GetSectorIndexY(front.y + 3.0f);
if(ymax > NUMSECTORS_Y-1) ymax = NUMSECTORS_X-1; if(ymax > NUMSECTORS_Y-1) ymax = NUMSECTORS_X-1;
CWorld::AdvanceCurrentScanCode(); CWorld::AdvanceCurrentScanCode();