summaryrefslogtreecommitdiffstats
path: root/src/peds
diff options
context:
space:
mode:
Diffstat (limited to 'src/peds')
-rw-r--r--src/peds/CivilianPed.cpp4
-rw-r--r--src/peds/Gangs.cpp2
-rw-r--r--src/peds/Ped.cpp2
-rw-r--r--src/peds/Ped.h2
-rw-r--r--src/peds/PedChat.cpp7
-rw-r--r--src/peds/PedType.cpp2
-rw-r--r--src/peds/Population.cpp1024
-rw-r--r--src/peds/Population.h40
8 files changed, 868 insertions, 215 deletions
diff --git a/src/peds/CivilianPed.cpp b/src/peds/CivilianPed.cpp
index 2be45ba9..1950c4b3 100644
--- a/src/peds/CivilianPed.cpp
+++ b/src/peds/CivilianPed.cpp
@@ -117,7 +117,7 @@ CCivilianPed::CivilianAI(void)
} else {
SetMoveState(PEDMOVE_WALK);
}
- } else if (threatPed->IsPlayer() && IsGangMember() && b158_80) {
+ } else if (threatPed->IsPlayer() && IsGangMember() && bCanAttackPlayerWithCops) {
SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, m_threatEntity);
} else if (threatPed->IsPlayer() && FindPlayerPed()->m_pWanted->m_CurrentCops != 0) {
@@ -203,7 +203,7 @@ CCivilianPed::CivilianAI(void)
CPed *threatPed = (CPed*)m_threatEntity;
if (m_pedStats->m_fear <= 100 - threatPed->m_pedStats->m_temper && threatPed->m_nPedType != PEDTYPE_COP) {
if (threatPed->GetWeapon()->IsTypeMelee() || !GetWeapon()->IsTypeMelee()) {
- if (threatPed->IsPlayer() && IsGangMember() && b158_80) {
+ if (threatPed->IsPlayer() && IsGangMember() && bCanAttackPlayerWithCops) {
SetObjective(OBJECTIVE_KILL_CHAR_ON_FOOT, m_threatEntity);
} else if (threatPed->IsPlayer() && FindPlayerPed()->m_pWanted->m_CurrentCops != 0) {
diff --git a/src/peds/Gangs.cpp b/src/peds/Gangs.cpp
index 2d6d1137..38e37430 100644
--- a/src/peds/Gangs.cpp
+++ b/src/peds/Gangs.cpp
@@ -6,6 +6,8 @@
#include "Streaming.h"
#include "Weapon.h"
+// --MIAMI: file done
+
CGangInfo CGangs::Gang[NUM_GANGS];
bool CGangs::GangAttackWithCops[NUM_GANGS];
diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp
index a7c82f0a..f6d54268 100644
--- a/src/peds/Ped.cpp
+++ b/src/peds/Ped.cpp
@@ -459,7 +459,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
bCollectBusFare = false;
bBoughtIceCream = false;
bDonePositionOutOfCollision = false;
- b158_80 = false;
+ bCanAttackPlayerWithCops = false;
if (CGeneral::GetRandomNumber() & 3)
bHasACamera = false;
diff --git a/src/peds/Ped.h b/src/peds/Ped.h
index 03dcebff..3ee38df3 100644
--- a/src/peds/Ped.h
+++ b/src/peds/Ped.h
@@ -491,7 +491,7 @@ public:
uint32 bCollectBusFare : 1;
uint32 bBoughtIceCream : 1;
uint32 bDonePositionOutOfCollision : 1;
- uint32 b158_80 : 1;
+ uint32 bCanAttackPlayerWithCops : 1;
// our own flags
uint32 m_ped_flagI80 : 1; // KANGAROO_CHEAT define makes use of this as cheat toggle
diff --git a/src/peds/PedChat.cpp b/src/peds/PedChat.cpp
index 73a8e59c..b7732274 100644
--- a/src/peds/PedChat.cpp
+++ b/src/peds/PedChat.cpp
@@ -4,7 +4,8 @@
#include "General.h"
#include "Ped.h"
-// --MIAMI: Done
+// --MIAMI: file done
+
// Corresponds to ped sounds (from SOUND_PED_DEATH to SOUND_PED_TAXI_CALL)
PedAudioData CommentWaitTime[56] = {
{ 500, 800, 500, 2 },
@@ -65,14 +66,12 @@ PedAudioData CommentWaitTime[56] = {
{ 0, 0, 0, 0 }
};
-// --MIAMI: Done
bool
CPed::ServiceTalkingWhenDead(void)
{
return m_queuedSound == SOUND_PED_DEATH;
}
-// --MIAMI: Done
void
CPed::ServiceTalking(void)
{
@@ -102,7 +101,6 @@ CPed::ServiceTalking(void)
}
}
-// --MIAMI: Done
void
CPed::Say(uint16 audio)
{
@@ -157,7 +155,6 @@ CPed::Say(uint16 audio)
}
}
-// --MIAMI: Done
void
CPed::Say(uint16 audio, int32 time)
{
diff --git a/src/peds/PedType.cpp b/src/peds/PedType.cpp
index 397cd71d..8a631e7a 100644
--- a/src/peds/PedType.cpp
+++ b/src/peds/PedType.cpp
@@ -3,6 +3,8 @@
#include "FileMgr.h"
#include "PedType.h"
+// --MIAMI: file done
+
CPedType *CPedType::ms_apPedType[NUM_PEDTYPES];
void
diff --git a/src/peds/Population.cpp b/src/peds/Population.cpp
index 35a09a4f..94533f4a 100644
--- a/src/peds/Population.cpp
+++ b/src/peds/Population.cpp
@@ -23,6 +23,13 @@
#include "Script.h"
#include "Shadows.h"
#include "SurfaceTable.h"
+#include "Weather.h"
+#include "Darkel.h"
+#include "Streaming.h"
+#include "Clock.h"
+#include "WaterLevel.h"
+
+// --MIAMI: File done
#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.
@@ -30,37 +37,13 @@
#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
-// Transition areas between zones
-const RegenerationPoint aSafeZones[] = {
-// TODO(MIAMI): this is totally bogus
- { LEVEL_BEACH, LEVEL_MAINLAND, 400.0f, 814.0f, -954.0f, -903.0f, 30.0f, 100.0f,
- CVector(790.0f, -917.0f, 39.0f), CVector(775.0f, -921.0f, 39.0f), CVector(424.0f, -942.0f, 38.0f), CVector(439.0f, -938.0f, 38.0f) },
-#ifndef MIAMI
- { LEVEL_INDUSTRIAL, LEVEL_COMMERCIAL, 400.0f, 814.0f, -954.0f, -903.0f, 30.0f, 100.0f,
- CVector(790.0f, -917.0f, 39.0f), CVector(775.0f, -921.0f, 39.0f), CVector(424.0f, -942.0f, 38.0f), CVector(439.0f, -938.0f, 38.0f) },
- { LEVEL_INDUSTRIAL, LEVEL_COMMERCIAL, 555.0f, 711.0f, 118.0f, 186.0f, -30.0f, -10.0f,
- CVector(698.0f, 182.0f, -20.0f), CVector(681.0f, 178.0f, -20.0f), CVector(586.0f, 144.0f, -20.0f), CVector(577.0f, 135.0f, -20.0f) },
- { LEVEL_INDUSTRIAL, LEVEL_COMMERCIAL, 626.0f, 744.0f, -124.0f, -87.0f, -20.0f, -6.0f,
- CVector(736.0f, -117.0f, -13.0f), CVector(730.0f, -115.0f, -13.0f), CVector(635.0f, -93.0f, -12.5f), CVector(650.0f, -89.0f, -12.5f) },
- { LEVEL_INDUSTRIAL, LEVEL_COMMERCIAL, 645.0f, 734.0f, -780.0f, -750.0f, -25.0f, -6.0f,
- CVector(729.0f, -764.0f, -18.0f), CVector(720.0f, -769.0f, -17.0f), CVector(652.0f, -774.0f, -10.5f), CVector(659.0f, -770.0f, -10.5f) },
- { LEVEL_COMMERCIAL, LEVEL_SUBURBAN, -532.0f, -136.0f, -668.0f, -599.0f, 34.0f, 60.0f,
- CVector(-172.0f, -619.0f, 44.0f), CVector(-183.0f, -623.0f, 44.0f), CVector(-511.0f, -645.0f, 41.0f), CVector(-493.0f, -639.0f, 41.5f) },
- { LEVEL_COMMERCIAL, LEVEL_SUBURBAN, -325.0f, -175.0f, 27.0f, 75.0f, -30.0f, -10.0f,
- CVector(-185.0f, 40.8f, -20.5f), CVector(-202.0f, 37.0f, -20.5f), CVector(-315.0f, 65.5f, -20.5f), CVector(-306.0f, 62.4f, -20.5f) },
- { LEVEL_COMMERCIAL, LEVEL_SUBURBAN, -410.0f, -310.0f, -1055.0f, -1030.0f, -20.0f, -6.0f,
- CVector(-321.0f, -1043.0f, -13.2f), CVector(-328.0f, -1045.0f, -13.2f), CVector(-398.0f, -1044.0f, -13.5f), CVector(-390.0f, -1040.5f, -13.5f) },
- { LEVEL_COMMERCIAL, LEVEL_SUBURBAN, -425.0f, -280.0f, -471.0f, -447.0f, -20.0f, -5.0f,
- CVector(-292.0f, -457.0f, -11.6f), CVector(-310.0f, -461.0f, -11.6f), CVector(-413.0f, -461.0f, -11.5f), CVector(-399.0f, -457.0f, -11.3f) }
-#endif
-};
-
PedGroup CPopulation::ms_pPedGroups[NUMPEDGROUPS];
bool CPopulation::ms_bGivePedsWeapons;
int32 CPopulation::m_AllRandomPedsThisType = -1;
float CPopulation::PedDensityMultiplier = 1.0f;
uint32 CPopulation::ms_nTotalMissionPeds;
int32 CPopulation::MaxNumberOfPedsInUse = 25;
+int32 CPopulation::MaxNumberOfPedsInUseInterior = 40;
uint32 CPopulation::ms_nNumCivMale;
uint32 CPopulation::ms_nNumCivFemale;
uint32 CPopulation::ms_nNumCop;
@@ -80,13 +63,14 @@ uint32 CPopulation::ms_nNumGang6;
uint32 CPopulation::ms_nNumGang9;
uint32 CPopulation::ms_nNumGang7;
uint32 CPopulation::ms_nNumGang8;
-CVector CPopulation::RegenerationPoint_a;
-CVector CPopulation::RegenerationPoint_b;
-CVector CPopulation::RegenerationForward;
uint32 CPopulation::ms_nTotalCarPassengerPeds;
uint32 CPopulation::NumMiamiViceCops;
+uint32 gLastSelectedCivilianIndex;
+CEntity *gSunbatheObstacles[2];
+CEntity *gCoupleObstacles[3];
+
void
CPopulation::Initialise()
{
@@ -108,16 +92,16 @@ CPopulation::Initialise()
ms_nNumDummy = 0;
ms_nTotalCarPassengerPeds = 0;
+ ms_nTotalCivPeds = 0;
+ ms_nTotalGangPeds = 0;
+ ms_nTotalPeds = 0;
+ ms_nTotalMissionPeds = 0;
+ m_CountDownToPedsAtStart = 2;
+ bZoneChangeHasHappened = false; // III leftover
m_AllRandomPedsThisType = -1;
PedDensityMultiplier = 1.0f;
- bZoneChangeHasHappened = false;
- m_CountDownToPedsAtStart = 2;
- ms_nTotalMissionPeds = 0;
- ms_nTotalPeds = 0;
- ms_nTotalGangPeds = 0;
- ms_nTotalCivPeds = 0;
LoadPedGroups();
@@ -134,7 +118,45 @@ CPopulation::RemovePed(CPed *ent)
int32
CPopulation::ChooseCivilianOccupation(int32 group)
{
- return ms_pPedGroups[group].models[CGeneral::GetRandomNumberInRange(0, NUMMODELSPERPEDGROUP)];
+ if (CWeather::Rain > 0.1f) {
+ int32 lastModel;
+ for (int i = 0; i < 8; i++) {
+ gLastSelectedCivilianIndex = CGeneral::GetRandomNumberInRange(0, NUMMODELSPERPEDGROUP);
+ lastModel = ms_pPedGroups[group].models[gLastSelectedCivilianIndex];
+
+ if (!CPopulation::IsSunbather(lastModel))
+ break;
+ }
+ return lastModel;
+
+ } else {
+ gLastSelectedCivilianIndex = CGeneral::GetRandomNumberInRange(0, NUMMODELSPERPEDGROUP);
+ return ms_pPedGroups[group].models[gLastSelectedCivilianIndex];
+ }
+}
+
+int32
+CPopulation::ChooseNextCivilianOccupation(int32 group)
+{
+ if (CWeather::Rain > 0.1f) {
+ int32 lastModel;
+ for (int i = 0; i < NUMMODELSPERPEDGROUP; i++) {
+ ++gLastSelectedCivilianIndex;
+ if (gLastSelectedCivilianIndex >= NUMMODELSPERPEDGROUP)
+ gLastSelectedCivilianIndex = 0;
+ lastModel = ms_pPedGroups[group].models[gLastSelectedCivilianIndex];
+
+ if (!CPopulation::IsSunbather(ms_pPedGroups[group].models[gLastSelectedCivilianIndex]))
+ break;
+ }
+ return lastModel;
+
+ } else {
+ ++gLastSelectedCivilianIndex;
+ if (gLastSelectedCivilianIndex >= NUMMODELSPERPEDGROUP)
+ gLastSelectedCivilianIndex = 0;
+ return ms_pPedGroups[group].models[gLastSelectedCivilianIndex];
+ }
}
// returns eCopType
@@ -332,54 +354,17 @@ CPopulation::ChooseGangOccupation(int gangId)
return CGangs::ChooseGangPedModel(gangId);
}
-//--MIAMI: done
void
CPopulation::DealWithZoneChange(eLevelName oldLevel, eLevelName newLevel, bool forceIndustrialZone)
{
}
void
-CPopulation::FindCollisionZoneForCoors(CVector *coors, int *safeZoneOut, eLevelName *levelOut)
-{
- *safeZoneOut = -1;
- for (int i = 0; i < ARRAY_SIZE(aSafeZones); i++) {
- if (coors->x > aSafeZones[i].x1 && coors->x < aSafeZones[i].x2) {
- if (coors->y > aSafeZones[i].y1 && coors->y < aSafeZones[i].y2) {
- if (coors->z > aSafeZones[i].z1 && coors->z < aSafeZones[i].z2)
- *safeZoneOut = i;
- }
- }
- }
- // Then it's transition area
- if (*safeZoneOut >= 0)
- *levelOut = LEVEL_GENERIC;
- else
- *levelOut = CTheZones::GetLevelFromPosition(coors);
-}
-
-void
-CPopulation::FindClosestZoneForCoors(CVector *coors, int *safeZoneOut, eLevelName level1, eLevelName level2)
-{
- float minDist = 10000000.0f;
- int closestSafeZone = -1;
- for (int i = 0; i < ARRAY_SIZE(aSafeZones); i++) {
- if ((level1 == aSafeZones[i].srcLevel || level1 == aSafeZones[i].destLevel) && (level2 == aSafeZones[i].srcLevel || level2 == aSafeZones[i].destLevel)) {
- CVector2D safeZoneDistVec(coors->x - (aSafeZones[i].x1 + aSafeZones[i].x2) * 0.5f, coors->y - (aSafeZones[i].y1 + aSafeZones[i].y2) * 0.5f);
- float safeZoneDist = safeZoneDistVec.Magnitude();
- if (safeZoneDist < minDist) {
- minDist = safeZoneDist;
- closestSafeZone = i;
- }
- }
- }
- *safeZoneOut = closestSafeZone;
-}
-
-void
CPopulation::Update(bool addPeds)
{
if (!CReplay::IsPlayingBack()) {
ManagePopulation();
+ RemovePedsIfThePoolGetsFull();
MoveCarsAndPedsOutOfAbandonedZones();
if (m_CountDownToPedsAtStart != 0) {
if (--m_CountDownToPedsAtStart == 0)
@@ -406,7 +391,7 @@ CPopulation::Update(bool addPeds)
void
CPopulation::GeneratePedsAtStartOfGame()
{
- for (int i = 0; i < 50; i++) {
+ for (int i = 0; i < 100; i++) {
ms_nTotalCivPeds = ms_nNumCivFemale + ms_nNumCivMale;
ms_nTotalGangPeds = ms_nNumGang9 + ms_nNumGang8 + ms_nNumGang7
+ ms_nNumGang6 + ms_nNumGang5 + ms_nNumGang4
@@ -421,20 +406,6 @@ CPopulation::GeneratePedsAtStartOfGame()
}
}
-bool
-CPopulation::IsPointInSafeZone(CVector *coors)
-{
- for (int i = 0; i < ARRAY_SIZE(aSafeZones); i++) {
- if (coors->x > aSafeZones[i].x1 && coors->x < aSafeZones[i].x2) {
- if (coors->y > aSafeZones[i].y1 && coors->y < aSafeZones[i].y2) {
- if (coors->z > aSafeZones[i].z1 && coors->z < aSafeZones[i].z2)
- return true;
- }
- }
- }
- return false;
-}
-
// More speed = wider area to spawn peds
float
CPopulation::PedCreationDistMultiplier()
@@ -556,8 +527,10 @@ CPopulation::AddToPopulation(float minDist, float maxDist, float minDistOffScree
int pedAmount;
CZoneInfo zoneInfo;
+ int32 man = -1, woman = -1;
CPed *gangLeader = nil;
bool addCop = false;
+ bool isSecurityGuard = false;
bool forceAddingCop = false;
CPlayerInfo *playerInfo = &CWorld::Players[CWorld::PlayerInFocus];
CVector playerCentreOfWorld = FindPlayerCentreOfWorld(CWorld::PlayerInFocus);
@@ -580,9 +553,25 @@ CPopulation::AddToPopulation(float minDist, float maxDist, float minDistOffScree
maxDist = PedCreationDistMultiplier() * (MIN_CREATION_DIST + CREATION_RANGE);
}
}
+ float missionAndWeatherMult = -0.8f * Sqrt(CWeather::Rain) + 1.0f;
+
+ // Taxi side mission
+ if (CTheScripts::IsPlayerOnAMission()) {
+ CPed *player = FindPlayerPed();
+ if (player && player->InVehicle()) {
+ int32 model = player->m_pMyVehicle->GetModelIndex();
+ if (model == MI_TAXI || model == MI_CABBIE || model == MI_ZEBRA || model == MI_KAUFMAN)
+ missionAndWeatherMult = 1.0f;
+ }
+ }
+ if (CDarkel::FrenzyOnGoing())
+ missionAndWeatherMult = 1.0f;
+ int selectedMaxPeds = CGame::IsInInterior() ? CPopulation::MaxNumberOfPedsInUseInterior : CPopulation::MaxNumberOfPedsInUse;
+
// Yeah, float
- float maxPossiblePedsForArea = (zoneInfo.pedDensity + zoneInfo.carDensity) * playerInfo->m_fRoadDensity * PedDensityMultiplier * CIniFile::PedNumberMultiplier;
- maxPossiblePedsForArea = Min(maxPossiblePedsForArea, MaxNumberOfPedsInUse);
+ float maxPossiblePedsForArea = (zoneInfo.pedDensity + zoneInfo.carDensity) * playerInfo->m_fRoadDensity * PedDensityMultiplier
+ * (CDarkel::FrenzyOnGoing() ? 1.f : CIniFile::PedNumberMultiplier) * missionAndWeatherMult;
+ maxPossiblePedsForArea = Min(maxPossiblePedsForArea, selectedMaxPeds);
if (ms_nTotalPeds < maxPossiblePedsForArea || addCop) {
int decisionThreshold = CGeneral::GetRandomNumberInRange(0, 1000);
@@ -590,39 +579,48 @@ CPopulation::AddToPopulation(float minDist, float maxDist, float minDistOffScree
pedTypeToAdd = PEDTYPE_COP;
modelToAdd = ChoosePolicePedOccupation();
} else {
- for (int i = 0; i < NUM_GANGS; i++) {
+ int i = 0;
+ for (i = 0; i < NUM_GANGS; i++) {
if (decisionThreshold < zoneInfo.gangPedThreshold[i]) {
- pedTypeToAdd = PEDTYPE_GANG1 + i;
break;
}
+ }
- if (i == NUM_GANGS - 1) {
+ if (i == NUM_GANGS) {
+ if (CGeneral::GetRandomNumberInRange(0.0f, 1.0f) <= 0.95f) {
modelToAdd = ChooseCivilianOccupation(zoneInfo.pedGroup);
+
if (modelToAdd == -1)
return;
pedTypeToAdd = ((CPedModelInfo*)CModelInfo::GetModelInfo(modelToAdd))->m_pedType;
+
+ } else {
+ ChooseCivilianCoupleOccupations(zoneInfo.pedGroup, man, woman);
+ if (man == -1 || woman == -1)
+ return;
+ pedTypeToAdd = ((CPedModelInfo*)CModelInfo::GetModelInfo(woman))->m_pedType;
}
+ } else {
+ pedTypeToAdd = PEDTYPE_GANG1 + i;
+ if (IsSecurityGuard((ePedType)pedTypeToAdd)) {
+ isSecurityGuard = true;
+ modelToAdd = ChooseGangOccupation(pedTypeToAdd - PEDTYPE_GANG1);
+
+ if (modelToAdd == -1)
+ return;
+ pedTypeToAdd = ((CPedModelInfo*)CModelInfo::GetModelInfo(modelToAdd))->m_pedType;
+
+ }
}
}
if (!addCop && m_AllRandomPedsThisType > PEDTYPE_PLAYER1)
pedTypeToAdd = m_AllRandomPedsThisType;
- if (pedTypeToAdd >= PEDTYPE_GANG1 && pedTypeToAdd <= PEDTYPE_GANG9) {
- int randVal = CGeneral::GetRandomNumber() % 100;
- if (randVal < 50)
- return;
-
- if (randVal < 57) {
- pedAmount = 1;
- } else if (randVal >= 74) {
- if (randVal >= 85)
- pedAmount = 4;
- else
- pedAmount = 3;
- } else {
- pedAmount = 2;
- }
+ if (pedTypeToAdd >= PEDTYPE_GANG1 && pedTypeToAdd <= PEDTYPE_GANG9 && !isSecurityGuard) {
+ minDist += 30.0f;
+ maxDist += 30.0f;
+ pedAmount = ComputeRandomisedGangSize();
} else
pedAmount = 1;
@@ -635,35 +633,59 @@ CPopulation::AddToPopulation(float minDist, float maxDist, float minDistOffScree
if (!foundCoors)
return;
+ uint8 nodeSpawnRate = Min(ThePaths.m_pathNodes[node1].spawnRate, ThePaths.m_pathNodes[node2].spawnRate);
+ int randomRate = CGeneral::GetRandomNumber() & 0xF;
+ if (randomRate > nodeSpawnRate)
+ return;
+
+ CPathFind::TakeWidthIntoAccountForCoors(&ThePaths.m_pathNodes[node1], &ThePaths.m_pathNodes[node2], CGeneral::GetRandomNumber(), &generatedCoors.x, &generatedCoors.y);
+ if (CGame::currArea == AREA_MALL && (pedTypeToAdd == PEDTYPE_CIVMALE || pedTypeToAdd == PEDTYPE_CIVFEMALE || pedTypeToAdd == PEDTYPE_CRIMINAL) &&
+ CGeneral::GetRandomNumberInRange(0.f, 1.f) > 0.5f) {
+
+ PlaceMallPedsAsStationaryGroup(generatedCoors, zoneInfo.pedGroup);
+ return;
+ }
+
+ if (pedTypeToAdd >= PEDTYPE_GANG1 && pedTypeToAdd <= PEDTYPE_GANG9 && !isSecurityGuard) {
+ PlaceGangMembers((ePedType)pedTypeToAdd, pedAmount, generatedCoors);
+ return;
+ }
+
+ if (man > -1 && woman > -1) {
+ PlaceCouple(PEDTYPE_CIVMALE, man, PEDTYPE_CIVFEMALE, woman, generatedCoors);
+ return;
+ }
+
for (int i = 0; i < pedAmount; ++i) {
- if (pedTypeToAdd >= PEDTYPE_GANG1 && pedTypeToAdd <= PEDTYPE_GANG9)
- modelToAdd = ChooseGangOccupation(pedTypeToAdd - PEDTYPE_GANG1);
if (pedTypeToAdd == PEDTYPE_COP) {
// Unused code, ChoosePolicePedOccupation returns COP_STREET. Spawning FBI/SWAT/Army done in somewhere else.
if (modelToAdd == COP_STREET) {
- if (!CModelInfo::GetModelInfo(MI_COP)->GetRwObject())
+ if (!CStreaming::HasModelLoaded(MI_COP))
return;
} else if (modelToAdd == COP_FBI) {
- if (!CModelInfo::GetModelInfo(MI_FBI)->GetRwObject())
+ if (!CStreaming::HasModelLoaded(MI_COP) || !CStreaming::HasModelLoaded(CWeaponInfo::GetWeaponInfo(WEAPONTYPE_MP5)->m_nModelId))
return;
} else if (modelToAdd == COP_SWAT) {
- if (!CModelInfo::GetModelInfo(MI_SWAT)->GetRwObject())
+ if (!CStreaming::HasModelLoaded(MI_SWAT) || !CStreaming::HasModelLoaded(CWeaponInfo::GetWeaponInfo(WEAPONTYPE_UZI)->m_nModelId))
return;
- } else if (modelToAdd == COP_ARMY && !CModelInfo::GetModelInfo(MI_ARMY)->GetRwObject()) {
- return;
+ } else if (modelToAdd == COP_ARMY) {
+ if (!CStreaming::HasModelLoaded(MI_ARMY) ||
+ !CStreaming::HasModelLoaded(CWeaponInfo::GetWeaponInfo(WEAPONTYPE_MP5)->m_nModelId) || !CStreaming::HasModelLoaded(CWeaponInfo::GetWeaponInfo(WEAPONTYPE_GRENADE)->m_nModelId))
+ return;
}
- } else if (!CModelInfo::GetModelInfo(modelToAdd)->GetRwObject()) {
+ } else if (!CStreaming::HasModelLoaded(modelToAdd)) {
return;
}
generatedCoors.z += 0.7f;
// What? How can this not be met?
if (i < pedAmount) {
- //rand()
+ // rand()
+ // III leftover, unused
if (gangLeader) {
// Align gang members in formation. (btw i can't be 0 in here)
float offsetMin = i * 0.75f;
@@ -690,32 +712,81 @@ CPopulation::AddToPopulation(float minDist, float maxDist, float minDistOffScree
generatedCoors.z = Max(generatedCoors.z, groundZ);
}
- bool farEnoughToAdd = true;
- CMatrix mat(TheCamera.GetCameraMatrix());
- if (TheCamera.IsSphereVisible(generatedCoors, 2.0f, &mat)) {
+ bool surfaceAndDistIsOk = true;
+ if (TheCamera.IsSphereVisible(generatedCoors, 2.0f)) {
if (PedCreationDistMultiplier() * MIN_CREATION_DIST > (generatedCoors - playerCentreOfWorld).Magnitude2D())
- farEnoughToAdd = false;
+ surfaceAndDistIsOk = false;
+ }
+
+ // Place skaters if only they're on tarmac.
+ if (((CPedModelInfo*)CModelInfo::GetModelInfo(modelToAdd))->m_pedStatType == PEDSTAT_SKATER) {
+ CEntity* foundEnt = nil;
+ CColPoint foundCol;
+ CWorld::ProcessVerticalLine(generatedCoors + CVector(0.f, 0.f, 2.f), generatedCoors.z - 2.0f, foundCol, foundEnt, true, false, false, false, false, false, nil);
+ if (foundEnt) {
+ if (foundCol.surfaceB == SURFACE_TARMAC || foundCol.surfaceB == SURFACE_PAVEMENT)
+ surfaceAndDistIsOk = true;
+ else
+ surfaceAndDistIsOk = false;
+
+ } else {
+ surfaceAndDistIsOk = false;
+ }
}
- if (!farEnoughToAdd)
+ if (!surfaceAndDistIsOk)
break;
CPed *newPed = AddPed((ePedType)pedTypeToAdd, modelToAdd, generatedCoors);
if (forceAddingCop && newPed->m_nPedType == PEDTYPE_COP)
((CCopPed*)newPed)->m_bThrowsSpikeTrap = true;
- newPed->SetWanderPath(CGeneral::GetRandomNumberInRange(0, 8));
-
+ bool gonnaSunbathe = false;
+ if (CPopulation::IsSunbather(modelToAdd)) {
+ CEntity* foundEnt = nil;
+ CColPoint foundCol;
+ CWorld::ProcessVerticalLine(generatedCoors + CVector(0.f, 0.f, 2.f), generatedCoors.z - 2.0f, foundCol, foundEnt, true, false, false, false, false, false, nil);
+ if (foundEnt) {
+ if ((foundCol.surfaceB == SURFACE_CONCRETE_BEACH || foundCol.surfaceB == SURFACE_SAND)
+ && CClock::GetHours() >= 10 && CClock::GetHours() <= 18 && 0.0f == CWeather::Rain) {
+ gonnaSunbathe = true;
+ if (CPedPlacement::IsPositionClearForPed(generatedCoors, 3.0f, ARRAY_SIZE(gSunbatheObstacles), gSunbatheObstacles)) {
+ for (int j = 0; j < ARRAY_SIZE(gSunbatheObstacles); j++) {
+ if (gSunbatheObstacles[j] && gSunbatheObstacles[j] != newPed)
+ gonnaSunbathe = false;
+ }
+ }
+ }
+ }
+ }
+ if (gonnaSunbathe) {
+ float heading = CGeneral::GetRandomNumberInRange(0.f, 1.f) * TWOPI;
+ newPed->m_fRotationDest = heading;
+ newPed->m_fRotationCur = heading;
+ // unused
+ // v61 = CGeneral::GetRandomTrueFalse();
+ newPed->SetWaitState(WAITSTATE_SUN_BATHE_IDLE, nil);
+ CVector toyPos(newPed->GetPosition());
+ float waterLevel;
+ if (CWaterLevel::GetGroundLevel(toyPos, &waterLevel, nil, 30.0f)) {
+ toyPos.z = 0.004f + waterLevel;
+ CEntity *toy = CWaterLevel::CreateBeachToy(toyPos, BEACHTOY_11);
+ if (toy)
+ toy->SetHeading(heading);
+
+ if (!(CGeneral::GetRandomNumber() & 3)) {
+ CWaterLevel::CreateBeachToy(toyPos + CVector(CGeneral::GetRandomNumberInRange(-2.f, 2.f), CGeneral::GetRandomNumberInRange(-2.f, 2.f), 0.f), BEACHTOY_6);
+ }
+ }
+ } else {
+ newPed->SetWanderPath(CGeneral::GetRandomNumberInRange(0, 8));
+ }
+
if (i != 0) {
// Gang member
newPed->SetLeader(gangLeader);
-#ifndef FIX_BUGS
- // seems to be a miami leftover (this code is not on PS2) but gang peds end up just being frozen
- newPed->m_nPedState = PED_UNKNOWN;
- gangLeader->m_nPedState = PED_UNKNOWN;
- newPed->m_fRotationCur = CGeneral::GetRadianAngleBetweenPoints(
- gangLeader->GetPosition().x, gangLeader->GetPosition().y,
- newPed->GetPosition().x, newPed->GetPosition().y);
- newPed->m_fRotationDest = newPed->m_fRotationCur;
-#endif
+
+ newPed->SetPedState(PED_UNKNOWN);
+ gangLeader->SetPedState(PED_UNKNOWN);
+
} else {
gangLeader = newPed;
}
@@ -730,7 +801,6 @@ CPopulation::AddToPopulation(float minDist, float maxDist, float minDistOffScree
}
}
-// TODO(Miami)
CPed*
CPopulation::AddPedInCar(CVehicle* car, bool isDriver)
{
@@ -779,11 +849,15 @@ CPopulation::AddPedInCar(CVehicle* car, bool isDriver)
preferredModel = MI_TAXI_D;
break;
}
- } else if (car->GetModelIndex() == MI_VICECHEE && car->bIsLawEnforcer) {
- preferredModel = COP_MIAMIVICE;
- pedType = PEDTYPE_COP;
- miamiViceIndex = (isDriver ? 2 * CCarCtrl::MiamiViceCycle : 2 * CCarCtrl::MiamiViceCycle + 1);
- break;
+ // fall through if not
+ } else if (car->GetModelIndex() == MI_VICECHEE) {
+ if (car->bIsLawEnforcer) {
+ preferredModel = COP_MIAMIVICE;
+ pedType = PEDTYPE_COP;
+ miamiViceIndex = (isDriver ? 2 * CCarCtrl::MiamiViceCycle : 2 * CCarCtrl::MiamiViceCycle + 1);
+ break;
+ }
+ // fall through if not
}
int gangOfPed = 0;
@@ -796,20 +870,20 @@ CPopulation::AddPedInCar(CVehicle* car, bool isDriver)
pedType = gangOfPed + PEDTYPE_GANG1;
preferredModel = ChooseGangOccupation(gangOfPed);
} else if (gangOfPed == NUM_GANGS) {
- CVehicleModelInfo *carModelInfo = ((CVehicleModelInfo *)CModelInfo::GetModelInfo(car->GetModelIndex()));
+ CVehicleModelInfo *carModel = ((CVehicleModelInfo *)CModelInfo::GetModelInfo(car->GetModelIndex()));
+ preferredModel = ChooseCivilianOccupation(zoneInfo.pedGroup);
int i = 15;
for(; i >= 0; i--) {
- // Should return random model each time
- preferredModel = ChooseCivilianOccupation(zoneInfo.pedGroup);
- if (preferredModel == -1)
- preferredModel = defaultModel;
+ CPedModelInfo* pedModel = (CPedModelInfo*)CModelInfo::GetModelInfo(preferredModel);
- if (((CPedModelInfo*)CModelInfo::GetModelInfo(preferredModel))->GetRwObject()) {
+ if (pedModel->GetRwObject()) {
if (!car->IsPassenger(preferredModel) && !car->IsDriver(preferredModel)) {
- if (((CPedModelInfo*)CModelInfo::GetModelInfo(preferredModel))->m_carsCanDrive & (1 << carModelInfo->m_vehicleClass))
+ if (((CPedModelInfo*)CModelInfo::GetModelInfo(preferredModel))->m_carsCanDrive & (1 << carModel->m_vehicleClass))
break;
}
}
+
+ preferredModel = ChooseNextCivilianOccupation(zoneInfo.pedGroup);
}
if (i == -1)
preferredModel = defaultModel;
@@ -900,7 +974,7 @@ bool
CPopulation::TestRoomForDummyObject(CObject *obj)
{
int16 collidingObjs;
- CWorld::FindObjectsKindaColliding(obj->m_objectMatrix.GetPosition(), CModelInfo::GetModelInfo(obj->GetModelIndex())->GetColModel()->boundingSphere.radius,
+ CWorld::FindObjectsKindaColliding(obj->m_objectMatrix.GetPosition(), obj->GetBoundRadius(),
false, &collidingObjs, 2, nil, false, true, true, false, false);
return collidingObjs == 0;
@@ -975,17 +1049,20 @@ CPopulation::ManagePopulation(void)
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) {
+ float objPlayerDist = (obj->GetPosition() - playerPos).Magnitude();
+ if (obj->ObjectCreatedBy == TEMP_OBJECT) {
+ if (obj->GetModelIndex() != MI_ROADWORKBARRIER1 && obj->GetModelIndex() != MI_BEACHBALL) {
+ if (objPlayerDist > 51.0f || objPlayerDist > 25.0f && !obj->GetIsOnScreen() || CTimer::GetTimeInMilliseconds() > obj->m_nEndOfLifeTime) {
+ CWorld::Remove(obj);
+ delete obj;
+ }
+ } else if (objPlayerDist > 120.0f) {
CWorld::Remove(obj);
delete obj;
}
- } else {
- if (obj->ObjectCreatedBy == TEMP_OBJECT) {
- CWorld::Remove(obj);
- delete obj;
- } else if (obj->ObjectCreatedBy != CUTSCENE_OBJECT && TestRoomForDummyObject(obj)) {
+
+ } else if (objPlayerDist > 80.0f && (obj->m_objectMatrix.GetPosition() - playerPos).Magnitude() > 80.0f) {
+ if (obj->ObjectCreatedBy != CUTSCENE_OBJECT && TestRoomForDummyObject(obj)) {
ConvertToDummyObject(obj);
}
}
@@ -996,7 +1073,7 @@ CPopulation::ManagePopulation(void)
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 && (dummy->m_area == CGame::currArea || dummy->m_area == AREA_EVERYWHERE)) {
if ((dummy->GetPosition() - playerPos).Magnitude() < 80.0f)
ConvertToRealObject((CDummyObject*)dummy);
}
@@ -1011,7 +1088,8 @@ CPopulation::ManagePopulation(void)
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)
+ uint32 timeSinceDeath = CTimer::GetTimeInMilliseconds() - ped->m_bloodyFootprintCountOrDeathTime;
+ if (ped->m_nPedState == PED_DEAD && (timeSinceDeath > 30000 || CDarkel::FrenzyOnGoing() && timeSinceDeath > 15000))
ped->bFadeOut = true;
if (ped->bFadeOut && CVisibilityPlugins::GetClumpAlpha(ped->GetClump()) == 0) {
@@ -1020,22 +1098,33 @@ CPopulation::ManagePopulation(void)
}
float dist = (ped->GetPosition() - playerPos).Magnitude2D();
+ bool pedIsFarAway = false;
- if (ped->IsGangMember() || (ped->bDeadPedInFrontOfCar && ped->m_vehicleInAccident))
+ if (ped->IsGangMember())
dist -= 30.0f;
+ else if (ped->bDeadPedInFrontOfCar && ped->m_vehicleInAccident)
+ dist = 0.0f;
- 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))
+ if (PedCreationDistMultiplier() * (PED_REMOVE_DIST_SPECIAL * TheCamera.GenerationDistMultiplier) < dist ||
+ (!ped->bCullExtraFarAway && PedCreationDistMultiplier() * PED_REMOVE_DIST * TheCamera.GenerationDistMultiplier < dist)) {
pedIsFarAway = true;
+ } else if (PedCreationDistMultiplier() * (MIN_CREATION_DIST + CREATION_RANGE) * OFFSCREEN_CREATION_MULT < dist) {
+ if (CTimer::GetTimeInMilliseconds() > ped->m_nExtendedRangeTimer && !ped->GetIsOnScreen()) {
+ if (TheCamera.Cams[TheCamera.ActiveCam].Mode != CCam::MODE_SNIPER
+ && TheCamera.Cams[TheCamera.ActiveCam].Mode != CCam::MODE_SNIPER_RUNABOUT
+ && TheCamera.Cams[TheCamera.ActiveCam].Mode != CCam::MODE_CAMERA
+ && !TheCamera.Cams[TheCamera.ActiveCam].LookingLeft
+ && !TheCamera.Cams[TheCamera.ActiveCam].LookingRight
+ && !TheCamera.Cams[TheCamera.ActiveCam].LookingBehind) {
+ pedIsFarAway = true;
+ }
+ }
+
+ } else {
+ ped->m_nExtendedRangeTimer = ped->m_nPedType == PEDTYPE_COP ? CTimer::GetTimeInMilliseconds() + 10000 : CTimer::GetTimeInMilliseconds() + 4000;
+ }
+
if (!pedIsFarAway)
continue;
@@ -1074,24 +1163,18 @@ CPopulation::ManagePopulation(void)
CPed*
CPopulation::AddDeadPedInFrontOfCar(const CVector& pos, CVehicle* pCulprit)
{
- if (TheCamera.IsSphereVisible(pos, 2.0f)) {
- float fDistanceToPlayer = (pos - FindPlayerPed()->GetPosition()).Magnitude2D();
- float fDistanceMultiplier;
- if (FindPlayerVehicle())
- fDistanceMultiplier = clamp(FindPlayerVehicle()->GetMoveSpeed().Magnitude2D() - 0.1f + 1.0f, 1.0f, 1.5f);
- else
- fDistanceMultiplier = 1.0f;
- if (40.0f * fDistanceMultiplier > fDistanceToPlayer)
+ if (TheCamera.IsSphereVisible(pos, 2.0f) && MIN_CREATION_DIST * PedCreationDistMultiplier() > (pos - FindPlayerPed()->GetPosition()).Magnitude2D()) {
return nil;
}
+
bool found;
float z = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z, &found) + 1.0f;
if (!found)
return nil;
z = Max(z, pos.z);
- if (!CModelInfo::GetModelInfo(MI_MALE01)->GetRwObject()) // strange way to check it
+ if (!CModelInfo::GetModelInfo(MI_MALE01)->GetRwObject())
return nil;
- CPed* pPed = CPopulation::AddPed(PEDTYPE_CIVMALE, MI_MALE01, pos); // TODO(MIAMI): 4th parameter
+ CPed* pPed = CPopulation::AddPed(PEDTYPE_CIVMALE, MI_MALE01, pos);
pPed->SetDie();
pPed->m_nPedMoney = 0;
pPed->bDeadPedInFrontOfCar = true;
@@ -1101,16 +1184,14 @@ CPopulation::AddDeadPedInFrontOfCar(const CVector& pos, CVehicle* pCulprit)
if (!CPedPlacement::IsPositionClearForPed(pos, 2.0f, 3, pEntities)) {
for (int i = 0; i < 3; i++) {
if (pEntities[i] && pEntities[i] != pCulprit && pEntities[i] != pPed) {
- CWorld::Remove(pPed);
- delete pPed;
+ RemovePed(pPed);
return nil;
}
}
}
CColPoint colpts[MAX_COLLISION_POINTS];
if (CCollision::ProcessColModels(pCulprit->GetMatrix(), *pCulprit->GetColModel(), pPed->GetMatrix(), *pPed->GetColModel(), colpts, nil, nil)) {
- CWorld::Remove(pPed);
- delete pPed;
+ RemovePed(pPed);
return nil;
}
CVisibilityPlugins::SetClumpAlpha(pPed->GetClump(), 0);
@@ -1133,4 +1214,583 @@ bool
CPopulation::CanJeerAtStripper(int32 model)
{
return model == MI_WMOBE || model == MI_WMYBE || model == MI_WMOST || model == MI_BMYBB;
+}
+
+void
+CPopulation::RemovePedsIfThePoolGetsFull(void)
+{
+ if ((CTimer::GetFrameCounter() & 7) == 5) {
+ if (CPools::GetPedPool()->GetNoOfFreeSpaces() < 8) {
+ CPed *closestPed = nil;
+ float closestDist = 10000000.0;
+ int poolSize = CPools::GetPedPool()->GetSize();
+ for (int i = poolSize - 1; i >= 0; i--) {
+ CPed* ped = CPools::GetPedPool()->GetSlot(i);
+ if (ped && ped->CanBeDeleted()) {
+ float dist = (TheCamera.GetPosition() - ped->GetPosition()).Magnitude();
+ if (dist < closestDist) {
+ closestDist = dist;
+ closestPed = ped;
+ }
+ }
+ }
+ if (closestPed) {
+ RemovePed(closestPed);
+ }
+ }
+ }
+}
+
+bool
+CPopulation::IsMale(int32 model)
+{
+ switch (model) {
+ case MI_HMYST:
+ case MI_HMOST:
+ case MI_HMYRI:
+ case MI_HMORI:
+ case MI_HMYBE:
+ case MI_HMOBE:
+ case MI_HMOTR:
+ case MI_HMYAP:
+ case MI_HMOCA:
+ case MI_BMODK:
+ case MI_BMYKR:
+ case MI_BMYST:
+ case MI_BMOST:
+ case MI_BMYRI:
+ case MI_BMYBE:
+ case MI_BMOBE:
+ case MI_BMYBU:
+ case MI_BMOTR:
+ case MI_BMYPI:
+ case MI_BMYBB:
+ case MI_WMYCR:
+ case MI_WMYST:
+ case MI_WMOST:
+ case MI_WMYRI:
+ case MI_WMORI:
+ case MI_WMYBE:
+ case MI_WMOBE:
+ case MI_WMYCW:
+ case MI_WMYGO:
+ case MI_WMOGO:
+ case MI_WMYLG:
+ case MI_WMYBU:
+ case MI_WMOBU:
+ case MI_WMOTR:
+ case MI_WMYPI:
+ case MI_WMOCA:
+ case MI_WMYJG:
+ case MI_WMYSK:
+
+ // BUG? Why no JMOTO?
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool
+CPopulation::IsFemale(int32 model)
+{
+ switch (model) {
+ case MI_HFYST:
+ case MI_HFOST:
+ case MI_HFYRI:
+ case MI_HFORI:
+ case MI_HFYBE:
+ case MI_HFOBE:
+ case MI_HFYBU:
+ case MI_HFYMD:
+ case MI_HFYCG:
+ case MI_HFYPR:
+ case MI_HFOTR:
+ case MI_BFYST:
+ case MI_BFOST:
+ case MI_BFYRI:
+ case MI_BFORI:
+ case MI_BFYBE:
+ case MI_BFOBE:
+ case MI_BFYPR:
+ case MI_BFOTR:
+ case MI_WFYST:
+ case MI_WFOST:
+ case MI_WFYRI:
+ case MI_WFORI:
+ case MI_WFYBE:
+ case MI_WFOBE:
+ case MI_WFOGO:
+ case MI_WFYLG:
+ case MI_WFYBU:
+ case MI_WFYPR:
+ case MI_WFOTR:
+ case MI_WFYJG:
+ case MI_WFYSK:
+ case MI_WFYSH:
+ case MI_WFOSH:
+ case MI_JFOTO:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool
+CPopulation::IsSunbather(int32 model)
+{
+ switch (model) {
+ case MI_HFYBE:
+ case MI_HFOBE:
+ case MI_HMYBE:
+ case MI_HMOBE:
+ case MI_BFYBE:
+ case MI_BMYBE:
+ case MI_BFOBE:
+ case MI_BMOBE:
+ case MI_WFYBE:
+ case MI_WMYBE:
+ case MI_WFOBE:
+ case MI_WMOBE:
+ return true;
+ default:
+ return false;
+ }
+}
+
+int32
+CPopulation::ComputeRandomisedGangSize(void)
+{
+ return CGeneral::GetRandomNumberInRange(3, 6);
+}
+
+bool
+CPopulation::CanSolicitPlayerInCar(int32 model)
+{
+ return model == MI_HFYPR || model == MI_BFYPR || model == MI_WFYPR;
+}
+
+bool
+CPopulation::CanSolicitPlayerOnFoot(int32 model)
+{
+ return model == MI_HFYMD || model == MI_HFYCG || model == MI_BFOTR || model == MI_BMOTR || model == MI_WFOTR || model == MI_WMOTR;
+}
+
+bool
+CPopulation::IsSecurityGuard(ePedType pedType)
+{
+ return pedType == PEDTYPE_GANG5;
+}
+
+void
+CPopulation::ChooseCivilianCoupleOccupations(int32 group, int32& man, int32& woman)
+{
+ man = -1;
+ woman = -1;
+
+ for (int i = 0; i < 8; i++) {
+ if (man > -1)
+ break;
+
+ int32 model = ms_pPedGroups[group].models[CGeneral::GetRandomNumberInRange(0, NUMMODELSPERPEDGROUP)];
+ if (man == -1 && IsMale(model) && ((CPedModelInfo*)CModelInfo::GetModelInfo(model))->m_pedType == PEDTYPE_CIVMALE) {
+ man = model;
+ }
+ }
+
+ if (man != -1) {
+ int32 model;
+ for (int i = 0; i < NUMMODELSPERPEDGROUP; i++) {
+ model = ms_pPedGroups[group].models[i];
+ if (IsFemale(model)) {
+ CPedModelInfo* womanModelInfo = (CPedModelInfo*)CModelInfo::GetModelInfo(model);
+ if (womanModelInfo->m_pedType == PEDTYPE_CIVFEMALE) {
+ CPedModelInfo* manModelInfo = (CPedModelInfo*)CModelInfo::GetModelInfo(man);
+
+ // If both are skater or not, finalize the decision
+ if (manModelInfo && womanModelInfo) {
+ if (manModelInfo->m_animGroup == womanModelInfo->m_animGroup) {
+ if (manModelInfo->m_pedStatType != PEDSTAT_SKATER && womanModelInfo->m_pedStatType != PEDSTAT_SKATER)
+ break;
+
+ if (manModelInfo->m_pedStatType == PEDSTAT_SKATER && womanModelInfo->m_pedStatType == PEDSTAT_SKATER)
+ break;
+ }
+ }
+ }
+ }
+ }
+ woman = model;
+ }
+}
+
+void
+CPopulation::PlaceGangMembers(ePedType pedType, int pedAmount, CVector const& coors)
+{
+ if (CGeneral::GetRandomNumberInRange(0.f, 1.f) < 0.333f) {
+ PlaceGangMembersInFormation(pedType, pedAmount, coors);
+ } else {
+ PlaceGangMembersInCircle(pedType, pedAmount, coors);
+ }
+}
+
+void
+CPopulation::PlaceGangMembersInFormation(ePedType pedType, int pedAmount, CVector const& coors)
+{
+ CPed *createdPeds[5];
+
+ if (!TheCamera.IsSphereVisible(coors, 3.0f) || MIN_CREATION_DIST * PedCreationDistMultiplier() <= (coors - FindPlayerPed()->GetPosition()).Magnitude2D()) {
+ if (CPedPlacement::IsPositionClearForPed(coors, 3.0f, -1, 0)) {
+ bool leaderFoundGround;
+ float leaderGroundZ = CWorld::FindGroundZFor3DCoord(coors.x, coors.y, coors.z, &leaderFoundGround) + 1.0f;
+ if (leaderFoundGround) {
+ float finalZ = coors.z > leaderGroundZ ? coors.z : leaderGroundZ;
+ int leaderModel = ChooseGangOccupation(pedType - PEDTYPE_GANG1);
+ if (((CPedModelInfo*)CModelInfo::GetModelInfo(leaderModel))->GetRwObject()) {
+ CPed *leader = AddPed(pedType, leaderModel, CVector(coors.x, coors.y, finalZ));
+ if (leader) {
+ leader->SetObjective(OBJECTIVE_NONE);
+ leader->SetWanderPath(CGeneral::GetRandomNumberInRange(0, 8));
+ leader->bIsLeader = true;
+ if (CGangs::GetWillAttackPlayerWithCops(pedType))
+ leader->bCanAttackPlayerWithCops = true;
+
+ int pedIdx = 1;
+ createdPeds[0] = leader;
+ for (int i = 1; i < pedAmount; ++i) {
+ int memberModel = ChooseGangOccupation(pedType - PEDTYPE_GANG1);
+ if (!((CPedModelInfo*)CModelInfo::GetModelInfo(memberModel))->GetRwObject())
+ continue;
+
+ CPed* memberPed = AddPed(pedType, memberModel, CVector(coors.x, coors.y, finalZ));
+ if (!memberPed)
+ continue;
+
+ memberPed->SetObjective(OBJECTIVE_FOLLOW_CHAR_IN_FORMATION, leader);
+ memberPed->SetFormation((eFormation)i);
+ CVector formationPos = memberPed->GetFormationPosition();
+ CVector finalFormationPos = formationPos;
+ bool formationFoundGround;
+ float formationGroundZ = CWorld::FindGroundZFor3DCoord(formationPos.x, formationPos.y, 1.0f + formationPos.z, &formationFoundGround) + 1.0f;
+
+ finalFormationPos.z = Max(finalFormationPos.z, formationGroundZ);
+ if (formationFoundGround) {
+ if (Abs(finalFormationPos.z - leader->GetPosition().z) <= 1.0f) {
+ if (CWorld::GetIsLineOfSightClear(finalFormationPos, leader->GetPosition(), true, false, false, false, false, false, false)) {
+ memberPed->SetPosition(finalFormationPos);
+ createdPeds[pedIdx++] = memberPed;
+ if (CGangs::GetWillAttackPlayerWithCops(pedType))
+ leader->bCanAttackPlayerWithCops = true;
+
+ CVisibilityPlugins::SetClumpAlpha(memberPed->GetClump(), 0);
+ continue;
+ }
+ }
+ }
+ RemovePed(memberPed);
+ }
+ if (pedIdx >= 3) {
+ for (int j = 1; j < pedIdx; ++j)
+ createdPeds[j]->SetLeader(createdPeds[0]);
+
+ } else {
+ for (int k = 0; k < pedIdx; ++k) {
+ RemovePed(createdPeds[k]);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+void
+CPopulation::PlaceGangMembersInCircle(ePedType pedType, int pedAmount, CVector const& coors)
+{
+ CPed *createdPeds[5];
+
+ if (pedAmount < 2)
+ return;
+
+ float circleSector = TWOPI / pedAmount;
+
+ float circleR = Sqrt(0.5f / (1.0f - Cos(circleSector)));
+
+ if (!TheCamera.IsSphereVisible(coors, circleR) ||
+ MIN_CREATION_DIST * PedCreationDistMultiplier() <= (coors - FindPlayerPed()->GetPosition()).Magnitude2D()) {
+
+ if (CPedPlacement::IsPositionClearForPed(coors, circleR, -1, 0)) {
+ int pedIdx = 0;
+ CVector leaderPos;
+
+ for (int i = 0; i < pedAmount; i++) {
+ float angleMult = i + CGeneral::GetRandomNumberInRange(-0.2f, 0.2f);
+ float randomR = circleR + CGeneral::GetRandomNumberInRange(-0.2f, 0.2f) * circleR;
+ float xOffset = randomR * Cos(angleMult * circleSector);
+ float yOffset = randomR * Sin(angleMult * circleSector);
+ bool foundGround;
+ float groundZ = CWorld::FindGroundZFor3DCoord(xOffset + coors.x, yOffset + coors.y, coors.z + 1.0, &foundGround) + 1.0f;
+ if (foundGround) {
+ CVector finalPos(coors.x + xOffset, coors.y + yOffset, coors.z > groundZ ? coors.z : groundZ);
+
+ if (i == 0)
+ leaderPos = finalPos;
+
+ int gangModel = ChooseGangOccupation(pedType - PEDTYPE_GANG1);
+ if (((CPedModelInfo*)CModelInfo::GetModelInfo(gangModel))->GetRwObject()) {
+ CEntity* obstacles[6] = { nil, nil, nil, nil, nil, nil };
+ CPedPlacement::IsPositionClearForPed(finalPos, CModelInfo::GetModelInfo(gangModel)->GetColModel()->boundingSphere.radius, ARRAY_SIZE(obstacles), obstacles);
+ bool foundObstacle = false;
+ for (int m = 0; m < ARRAY_SIZE(obstacles); m++) {
+ CEntity* obstacle = obstacles[m];
+ if (obstacle) {
+ int n = 0;
+ bool obstacleIsHarmless = false;
+ for (int n = 0; n < pedIdx; n++) {
+ if (obstacle == createdPeds[n])
+ obstacleIsHarmless = true;
+ }
+ if (!obstacleIsHarmless) {
+ foundObstacle = true;
+ break;
+ }
+ }
+ }
+ bool memberCanSeeLeader = i == 0 ? true : CWorld::GetIsLineOfSightClear(finalPos, leaderPos, true, false, false, false, false, false, false);
+
+ bool notTooCloseToLeader = i == 0 ? true : !(Abs(finalPos.z - leaderPos.z) < 1.0f);
+
+ if (!foundObstacle && memberCanSeeLeader && notTooCloseToLeader) {
+ CPed* newPed = AddPed(pedType, gangModel, finalPos);
+ if (newPed) {
+ createdPeds[pedIdx++] = newPed;
+ float angle = CGeneral::GetRadianAngleBetweenPoints(
+ coors.x, coors.y,
+ finalPos.x, finalPos.y);
+ newPed->m_fRotationDest = angle;
+ newPed->m_fRotationCur = angle;
+ if (CGangs::GetWillAttackPlayerWithCops(pedType))
+ newPed->bCanAttackPlayerWithCops = true;
+
+ CVisibilityPlugins::SetClumpAlpha(newPed->GetClump(), 0);
+ }
+ // No.
+#ifndef FIX_BUGS
+ else
+ CWorld::Remove(nil);
+#endif
+ }
+ }
+ }
+ }
+ if (pedIdx >= 3) {
+ for (int j = 0; j < pedIdx / 2; ++j) {
+ createdPeds[j]->SetChat(createdPeds[pedIdx - 1 - j], 100000);
+ createdPeds[pedIdx - 1 - j]->SetChat(createdPeds[j], 100000);
+ }
+
+ // Make that extra guy in the middle stand there(PED_UNKNOWN locks him) and do nothing :lmao:
+ if (pedIdx % 2 != 0) {
+ CPed *tmim = createdPeds[(pedIdx - 1) / 2];
+ float angle = CGeneral::GetRadianAngleBetweenPoints(
+ tmim->GetPosition().x, tmim->GetPosition().y,
+ createdPeds[0]->GetPosition().x, createdPeds[0]->GetPosition().y);
+ tmim->SetHeading(angle);
+ tmim->SetPedState(PED_UNKNOWN);
+ }
+ createdPeds[0]->bIsLeader = true;
+
+ for (int l = 1; l < pedIdx; ++l)
+ createdPeds[l]->SetLeader(createdPeds[0]);
+
+ } else {
+ for (int k = 0; k < pedIdx; ++k) {
+ RemovePed(createdPeds[k]);
+ }
+ }
+ }
+ }
+}
+
+void
+CPopulation::PlaceCouple(ePedType manType, int32 manModel, ePedType womanType, int32 womanModel, CVector coors)
+{
+ // Homosexuality filter!!!! Homophobic R* >>>:(
+ if (manType != PEDTYPE_CIVMALE || womanType != PEDTYPE_CIVFEMALE)
+ return;
+
+ if (!TheCamera.IsSphereVisible(coors, 1.5f) || MIN_CREATION_DIST * PedCreationDistMultiplier() <= (coors - FindPlayerPed()->GetPosition()).Magnitude2D()) {
+ if (CPedPlacement::IsPositionClearForPed(coors, CModelInfo::GetModelInfo(manModel)->GetColModel()->boundingSphere.radius, -1, 0)) {
+ bool manFoundGround;
+ float manGroundZ = CWorld::FindGroundZFor3DCoord(coors.x, coors.y, coors.z, &manFoundGround) + 1.0f;
+ if (manFoundGround) {
+ CVector correctedManPos = coors;
+ correctedManPos.z = Max(coors.z, manGroundZ);
+ if (((CPedModelInfo*)CModelInfo::GetModelInfo(manModel))->GetRwObject()) {
+ CPed *man = AddPed(PEDTYPE_CIVMALE, manModel, correctedManPos);
+ if (man) {
+ man->SetObjective(OBJECTIVE_NONE);
+ man->SetWanderPath(CGeneral::GetRandomNumberInRange(0, 8));
+ man->bIsLeader = true;
+ CVisibilityPlugins::SetClumpAlpha(man->GetClump(), 0);
+
+ if (((CPedModelInfo*)CModelInfo::GetModelInfo(womanModel))->GetRwObject()) {
+ CPed* woman = AddPed(PEDTYPE_CIVFEMALE, womanModel, correctedManPos); // will set the correct position later
+ if (woman) {
+ woman->SetObjective(OBJECTIVE_FOLLOW_CHAR_IN_FORMATION, man);
+ woman->SetFormation(FORMATION_RIGHT);
+
+ CVector formationPos = woman->GetFormationPosition();
+ CVector womanPos = formationPos;
+ bool womanFoundGround;
+ float formationGroundZ = CWorld::FindGroundZFor3DCoord(formationPos.x, formationPos.y, 1.0f + formationPos.z, &womanFoundGround) + 1.0f;
+
+ if (womanFoundGround) {
+ CVector correctedWomanPos = womanPos;
+ correctedWomanPos.z = Max(womanPos.z, formationGroundZ);
+ woman->SetPosition(correctedWomanPos);
+
+ // What's the point of this??
+ CEntity* obstacles[3];
+ memcpy(obstacles, gCoupleObstacles, sizeof(gCoupleObstacles));
+
+ CPedPlacement::IsPositionClearForPed(womanPos, CModelInfo::GetModelInfo(womanModel)->GetColModel()->boundingSphere.radius, ARRAY_SIZE(obstacles), obstacles);
+ for (int i = 0; i < ARRAY_SIZE(obstacles); i++) {
+ CEntity *obstacle = obstacles[i];
+ if (obstacle) {
+
+ // We found a real obstacle, so let's break and we can delete them...
+ if (obstacle != man && obstacle != woman)
+ break;
+ }
+ if (i == ARRAY_SIZE(obstacles) - 1) {
+ CVisibilityPlugins::SetClumpAlpha(woman->GetClump(), 0);
+ return;
+ }
+ }
+ }
+ RemovePed(woman);
+ RemovePed(man);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+// Mostly copy paste of PlaceGangMembersInFormation.
+void
+CPopulation::PlaceMallPedsAsStationaryGroup(CVector const& coors, int32 group)
+{
+#ifdef FIX_BUGS
+ CPed *createdPeds[6];
+#else
+ CPed *createdPeds[5];
+#endif
+
+ if (CGame::currArea != AREA_MALL)
+ return;
+
+ int pedAmount = CGeneral::GetRandomNumberInRange(0, 4) + 3;
+
+ float circleSector = TWOPI / pedAmount;
+
+ float circleR = Sqrt(0.5f / (1.0f - Cos(circleSector)));
+
+ if (!TheCamera.IsSphereVisible(coors, circleR) ||
+ MIN_CREATION_DIST * PedCreationDistMultiplier() <= (coors - FindPlayerPed()->GetPosition()).Magnitude2D()) {
+
+ if (CPedPlacement::IsPositionClearForPed(coors, circleR, -1, 0)) {
+ int pedIdx = 0;
+ CVector leaderPos;
+
+ for (int i = 0; i < pedAmount; i++) {
+ float angleMult = i + CGeneral::GetRandomNumberInRange(-0.2f, 0.2f);
+ float randomR = circleR + CGeneral::GetRandomNumberInRange(-0.2f, 0.2f) * circleR;
+ float xOffset = randomR * Cos(angleMult * circleSector);
+ float yOffset = randomR * Sin(angleMult * circleSector);
+ bool foundGround;
+ float groundZ = CWorld::FindGroundZFor3DCoord(xOffset + coors.x, yOffset + coors.y, coors.z + 1.0, &foundGround) + 1.0f;
+ if (foundGround) {
+ CVector finalPos(coors.x + xOffset, coors.y + yOffset, coors.z > groundZ ? coors.z : groundZ);
+
+ if (i == 0)
+ leaderPos = finalPos;
+
+ int pedModel = ChooseCivilianOccupation(group);
+ CPedModelInfo *pedModelInfo = (CPedModelInfo*)CModelInfo::GetModelInfo(pedModel);
+ if (pedModelInfo->GetRwObject()) {
+ CEntity* obstacles[6] = { nil, nil, nil, nil, nil, nil };
+ CPedPlacement::IsPositionClearForPed(finalPos, CModelInfo::GetModelInfo(pedModel)->GetColModel()->boundingSphere.radius, ARRAY_SIZE(obstacles), obstacles);
+ bool foundObstacle = false;
+ for (int m = 0; m < ARRAY_SIZE(obstacles); m++) {
+ CEntity* obstacle = obstacles[m];
+ if (obstacle) {
+ int n = 0;
+ bool obstacleIsHarmless = false;
+ for (int n = 0; n < pedIdx; n++) {
+ if (obstacle == createdPeds[n])
+ obstacleIsHarmless = true;
+ }
+ if (!obstacleIsHarmless) {
+ foundObstacle = true;
+ break;
+ }
+ }
+ }
+ bool memberCanSeeLeader = i == 0 ? true : CWorld::GetIsLineOfSightClear(finalPos, leaderPos, true, false, false, false, false, false, false);
+
+ bool notTooCloseToLeader = i == 0 ? true : !(Abs(finalPos.z - leaderPos.z) < 1.0f);
+
+ if (!foundObstacle && memberCanSeeLeader && notTooCloseToLeader) {
+ CPed *newPed = AddPed(pedModelInfo->m_pedType, pedModel, finalPos);
+ if (newPed) {
+ createdPeds[pedIdx++] = newPed;
+ float angle = CGeneral::GetRadianAngleBetweenPoints(
+ coors.x, coors.y,
+ finalPos.x, finalPos.y);
+ newPed->m_fRotationDest = angle;
+ newPed->m_fRotationCur = angle;
+ newPed->m_fearFlags = 0;
+ CVisibilityPlugins::SetClumpAlpha(newPed->GetClump(), 0);
+ }
+ // No.
+#ifndef FIX_BUGS
+ else
+ CWorld::Remove(nil);
+#endif
+ }
+ }
+ }
+ }
+ if (pedIdx >= 3) {
+ for (int j = 0; j < pedIdx / 2; ++j) {
+ createdPeds[j]->SetChat(createdPeds[pedIdx - 1 - j], 100000);
+ createdPeds[pedIdx - 1 - j]->SetChat(createdPeds[j], 100000);
+ }
+
+ // Make that extra guy in the middle stand there(PED_UNKNOWN locks him) and do nothing :lmao:
+ if (pedIdx % 2 != 0) {
+ CPed *tmim = createdPeds[(pedIdx - 1) / 2];
+ float angle = CGeneral::GetRadianAngleBetweenPoints(
+ tmim->GetPosition().x, tmim->GetPosition().y,
+ createdPeds[0]->GetPosition().x, createdPeds[0]->GetPosition().y);
+ tmim->SetHeading(angle);
+ tmim->SetPedState(PED_UNKNOWN);
+ }
+ createdPeds[0]->bIsLeader = true;
+
+ for (int l = 1; l < pedIdx; ++l)
+ createdPeds[l]->SetLeader(createdPeds[0]);
+
+ } else {
+ for (int k = 0; k < pedIdx; ++k) {
+ RemovePed(createdPeds[k]);
+ }
+ }
+ }
+ }
} \ No newline at end of file
diff --git a/src/peds/Population.h b/src/peds/Population.h
index 4ea45e7e..8c58f1b6 100644
--- a/src/peds/Population.h
+++ b/src/peds/Population.h
@@ -13,23 +13,6 @@ struct PedGroup
int32 models[NUMMODELSPERPEDGROUP];
};
-// Don't know the original name
-struct RegenerationPoint
-{
- eLevelName srcLevel; // this and below one may need to be exchanged
- eLevelName destLevel;
- float x1;
- float x2;
- float y1;
- float y2;
- float z1;
- float z2;
- CVector destPosA;
- CVector destPosB;
- CVector srcPosA;
- CVector srcPosB;
-};
-
class CPopulation
{
public:
@@ -39,6 +22,7 @@ public:
static float PedDensityMultiplier;
static uint32 ms_nTotalMissionPeds;
static int32 MaxNumberOfPedsInUse;
+ static int32 MaxNumberOfPedsInUseInterior;
static uint32 ms_nNumCivMale;
static uint32 ms_nNumCivFemale;
static uint32 ms_nNumCop;
@@ -58,9 +42,6 @@ public:
static uint32 ms_nNumGang9;
static uint32 ms_nNumGang7;
static uint32 ms_nNumGang8;
- static CVector RegenerationPoint_a;
- static CVector RegenerationPoint_b;
- static CVector RegenerationForward;
static uint32 ms_nTotalCarPassengerPeds;
static uint32 NumMiamiViceCops;
@@ -71,13 +52,12 @@ public:
static void UpdatePedCount(ePedType, bool);
static void DealWithZoneChange(eLevelName oldLevel, eLevelName newLevel, bool);
static CPed *AddPedInCar(CVehicle *car, bool isDriver);
- static bool IsPointInSafeZone(CVector *coors);
static void RemovePed(CPed *ent);
static int32 ChooseCivilianOccupation(int32);
+ static int32 ChooseNextCivilianOccupation(int32);
+ static void ChooseCivilianCoupleOccupations(int32, int32&, int32&);
static int32 ChoosePolicePedOccupation();
static int32 ChooseGangOccupation(int);
- static void FindCollisionZoneForCoors(CVector*, int*, eLevelName*);
- static void FindClosestZoneForCoors(CVector*, int*, eLevelName, eLevelName);
static void GeneratePedsAtStartOfGame();
static float PedCreationDistMultiplier();
static CPed *AddPed(ePedType pedType, uint32 mi, CVector const &coors, int32 modifier = 0);
@@ -91,6 +71,18 @@ public:
static bool TestSafeForRealObject(CDummyObject*);
static bool IsSkateable(CVector const&);
static bool CanJeerAtStripper(int32 model);
-
+ static void RemovePedsIfThePoolGetsFull(void);
+ static bool IsMale(int32);
+ static bool IsFemale(int32);
+ static bool IsSunbather(int32);
+ static int32 ComputeRandomisedGangSize(void);
+ static bool CanSolicitPlayerInCar(int32);
+ static bool CanSolicitPlayerOnFoot(int32);
+ static bool IsSecurityGuard(ePedType);
+ static void PlaceGangMembers(ePedType, int32, CVector const&);
+ static void PlaceGangMembersInFormation(ePedType, int32, CVector const&);
+ static void PlaceGangMembersInCircle(ePedType, int32, CVector const&);
+ static void PlaceCouple(ePedType, int32, ePedType, int32, CVector);
+ static void PlaceMallPedsAsStationaryGroup(CVector const&, int32);
static CPed* AddDeadPedInFrontOfCar(const CVector& pos, CVehicle* pCulprit);
};