summaryrefslogtreecommitdiffstats
path: root/src/peds/Population.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/peds/Population.cpp')
-rw-r--r--src/peds/Population.cpp195
1 files changed, 174 insertions, 21 deletions
diff --git a/src/peds/Population.cpp b/src/peds/Population.cpp
index bcbe7794..496ece34 100644
--- a/src/peds/Population.cpp
+++ b/src/peds/Population.cpp
@@ -18,11 +18,13 @@
#include "PedPlacement.h"
#include "DummyObject.h"
#include "Script.h"
+#include "Shadows.h"
-#define CREATION_DIST_MULT_TO_DIST 40.0f
-#define CREATION_RANGE 10.0f // Being added over the CREATION_DIST_MULT_TO_DIST.
-#define OFFSCREEN_CREATION_MULT 0.5f
-// Also there are some hardcoded values in GeneratePedsAtStartOfGame.
+#define MIN_CREATION_DIST 40.0f // not for start of the game (look at the GeneratePedsAtStartOfGame)
+#define CREATION_RANGE 10.0f // added over the MIN_CREATION_DIST.
+#define OFFSCREEN_CREATION_MULT 0.5f
+#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.
// 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::RegenerationForward = *(CVector*)0x8F1AD4;
-WRAPPER void CPopulation::ManagePopulation(void) { EAXJMP(0x4F3B90); }
-WRAPPER bool CPopulation::TestSafeForRealObject(CDummyObject*) { EAXJMP(0x4F4700); }
-
void
CPopulation::Initialise()
{
@@ -416,10 +415,10 @@ CPopulation::Update()
+ ms_nTotalGangPeds + ms_nNumCivFemale + ms_nNumCivMale;
if (!CCutsceneMgr::IsRunning()) {
float pcdm = PedCreationDistMultiplier();
- AddToPopulation(pcdm * (CREATION_DIST_MULT_TO_DIST * TheCamera.GenerationDistMultiplier),
- pcdm * ((CREATION_DIST_MULT_TO_DIST + CREATION_RANGE) * TheCamera.GenerationDistMultiplier),
- pcdm * (CREATION_DIST_MULT_TO_DIST + CREATION_RANGE) * OFFSCREEN_CREATION_MULT - CREATION_RANGE,
- pcdm * (CREATION_DIST_MULT_TO_DIST + CREATION_RANGE) * OFFSCREEN_CREATION_MULT);
+ AddToPopulation(pcdm * (MIN_CREATION_DIST * TheCamera.GenerationDistMultiplier),
+ pcdm * ((MIN_CREATION_DIST + CREATION_RANGE) * TheCamera.GenerationDistMultiplier),
+ pcdm * (MIN_CREATION_DIST + CREATION_RANGE) * OFFSCREEN_CREATION_MULT - CREATION_RANGE,
+ pcdm * (MIN_CREATION_DIST + CREATION_RANGE) * OFFSCREEN_CREATION_MULT);
}
}
}
@@ -437,8 +436,8 @@ CPopulation::GeneratePedsAtStartOfGame()
+ ms_nTotalGangPeds + ms_nNumCivFemale + ms_nNumCivMale;
// Min dist is 10.0f only for start of the game (naturally)
- AddToPopulation(10.0f, PedCreationDistMultiplier() * (CREATION_DIST_MULT_TO_DIST + CREATION_RANGE),
- 10.0f, PedCreationDistMultiplier() * (CREATION_DIST_MULT_TO_DIST + CREATION_RANGE));
+ AddToPopulation(10.0f, PedCreationDistMultiplier() * (MIN_CREATION_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::NumMissionCars + CCarCtrl::NumLawEnforcerCars + CCarCtrl::NumRandomCars >= CCarCtrl::MaxNumberOfCarsInUse)) {
addCop = true;
- minDist = PedCreationDistMultiplier() * CREATION_DIST_MULT_TO_DIST;
- maxDist = PedCreationDistMultiplier() * (CREATION_DIST_MULT_TO_DIST + CREATION_RANGE);
+ minDist = PedCreationDistMultiplier() * MIN_CREATION_DIST;
+ maxDist = PedCreationDistMultiplier() * (MIN_CREATION_DIST + CREATION_RANGE);
}
}
// Yeah, float
- float maxPossiblePedsForArea = (zoneInfo.pedDensity + zoneInfo.carDensity) * playerInfo->m_fRoadDensity * PedDensityMultiplier * CIniFile::PedNumberMultiplier;
- maxPossiblePedsForArea = min(maxPossiblePedsForArea, MaxNumberOfPedsInUse);
+ float maxPossiblePedsForArea = 10.0f * (zoneInfo.pedDensity + zoneInfo.carDensity) * playerInfo->m_fRoadDensity * PedDensityMultiplier * CIniFile::PedNumberMultiplier;
+ // maxPossiblePedsForArea = min(maxPossiblePedsForArea, MaxNumberOfPedsInUse);
if (ms_nTotalPeds < maxPossiblePedsForArea || addCop) {
int decisionThreshold = CGeneral::GetRandomNumberInRange(0, 1000);
@@ -689,7 +688,7 @@ CPopulation::AddToPopulation(float minDist, float maxDist, float minDistOffScree
bool farEnoughToAdd = true;
CMatrix mat(TheCamera.GetCameraMatrix());
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;
}
if (!farEnoughToAdd)
@@ -927,7 +926,6 @@ CPopulation::ConvertAllObjectsToDummyObjects()
for (int poolIndex = poolSize - 1; poolIndex >= 0; poolIndex--) {
CObject *obj = CPools::GetObjectPool()->GetSlot(poolIndex);
-
if (obj) {
if (obj->CanBeDeleted())
ConvertToDummyObject(obj);
@@ -970,8 +968,6 @@ void
CPopulation::ConvertToDummyObject(CObject *obj)
{
CDummyObject *dummy = new CDummyObject(obj);
- if (!dummy)
- return;
dummy->GetMatrix() = obj->m_objectMatrix;
dummy->GetMatrix().UpdateRW();
@@ -1005,6 +1001,163 @@ CPopulation::TestRoomForDummyObject(CObject *obj)
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
InjectHook(0x4F3770, &CPopulation::Initialise, PATCH_JUMP);
InjectHook(0x4F5780, &CPopulation::ChooseGangOccupation, PATCH_JUMP);