re3-wiiu/src/core/World.cpp

2297 lines
85 KiB
C++
Raw Normal View History

#include "common.h"
2019-06-29 11:09:33 +02:00
#include "Camera.h"
#include "CarCtrl.h"
2020-04-17 13:14:59 +02:00
#include "CopPed.h"
2019-09-12 02:43:18 +02:00
#include "CutsceneMgr.h"
2020-04-17 13:14:59 +02:00
#include "DMAudio.h"
#include "Entity.h"
#include "EventList.h"
#include "Explosion.h"
#include "Fire.h"
#include "Garages.h"
#include "Glass.h"
2019-09-12 02:43:18 +02:00
#include "Messages.h"
2020-04-17 13:14:59 +02:00
#include "ModelIndices.h"
#include "Object.h"
#include "ParticleObject.h"
#include "Ped.h"
#include "PlayerPed.h"
2019-09-12 02:43:18 +02:00
#include "Population.h"
2020-04-16 20:46:08 +02:00
#include "ProjectileInfo.h"
2020-04-17 13:14:59 +02:00
#include "Record.h"
#include "References.h"
#include "Replay.h"
#include "RpAnimBlend.h"
2020-04-16 20:46:08 +02:00
#include "Shadows.h"
2020-04-17 13:14:59 +02:00
#include "TempColModels.h"
#include "Vehicle.h"
#include "WaterLevel.h"
#include "World.h"
2020-04-17 15:31:11 +02:00
2020-04-16 20:46:08 +02:00
2020-04-17 02:38:05 +02:00
#define OBJECT_REPOSITION_OFFSET_Z 2.0f
2019-05-15 16:52:37 +02:00
2020-04-15 18:19:45 +02:00
CColPoint gaTempSphereColPoints[MAX_COLLISION_POINTS];
2020-03-26 14:16:06 +01:00
2020-05-24 15:14:27 +02:00
CPtrList CWorld::ms_bigBuildingsList[4];
CPtrList CWorld::ms_listMovingEntityPtrs;
CSector CWorld::ms_aSectors[NUMSECTORS_Y][NUMSECTORS_X];
uint16 CWorld::ms_nCurrentScanCode;
2019-05-15 16:52:37 +02:00
2020-05-24 15:14:27 +02:00
uint8 CWorld::PlayerInFocus;
2020-04-15 18:19:45 +02:00
CPlayerInfo CWorld::Players[NUMPLAYERS];
2020-05-24 15:14:27 +02:00
bool CWorld::bNoMoreCollisionTorque;
CEntity *CWorld::pIgnoreEntity;
bool CWorld::bIncludeDeadPeds;
bool CWorld::bSecondShift;
bool CWorld::bForceProcessControl;
bool CWorld::bProcessCutsceneOnly;
2020-05-24 15:14:27 +02:00
bool CWorld::bDoingCarCollisions;
bool CWorld::bIncludeCarTyres;
CColPoint CWorld::m_aTempColPts[MAX_COLLISION_POINTS];
2019-08-15 16:51:39 +02:00
void
CWorld::Initialise()
{
pIgnoreEntity = nil;
bDoingCarCollisions = false;
bSecondShift = false;
bNoMoreCollisionTorque = false;
bProcessCutsceneOnly = false;
bIncludeDeadPeds = false;
bForceProcessControl = false;
bIncludeCarTyres = false;
}
2019-06-29 11:09:33 +02:00
void
CWorld::Add(CEntity *ent)
{
2020-04-17 13:14:59 +02:00
if(ent->IsVehicle() || ent->IsPed()) DMAudio.SetEntityStatus(((CPhysical *)ent)->m_audioEntityId, true);
2019-06-29 11:09:33 +02:00
if(ent->bIsBIGBuilding)
ms_bigBuildingsList[ent->m_level].InsertItem(ent);
else
ent->Add();
2020-04-17 13:14:59 +02:00
if(ent->IsBuilding() || ent->IsDummy()) return;
2019-06-29 11:09:33 +02:00
2020-05-06 18:17:47 +02:00
if(!ent->IsStatic()) ((CPhysical *)ent)->AddToMovingList();
2019-06-29 11:09:33 +02:00
}
void
CWorld::Remove(CEntity *ent)
{
2020-04-17 13:14:59 +02:00
if(ent->IsVehicle() || ent->IsPed()) DMAudio.SetEntityStatus(((CPhysical *)ent)->m_audioEntityId, false);
2019-06-29 11:09:33 +02:00
if(ent->bIsBIGBuilding)
ms_bigBuildingsList[ent->m_level].RemoveItem(ent);
else
ent->Remove();
2020-04-17 13:14:59 +02:00
if(ent->IsBuilding() || ent->IsDummy()) return;
2019-06-29 11:09:33 +02:00
2020-05-06 18:17:47 +02:00
if(!ent->IsStatic()) ((CPhysical *)ent)->RemoveFromMovingList();
2019-06-29 11:09:33 +02:00
}
2019-05-15 16:52:37 +02:00
void
CWorld::ClearScanCodes(void)
{
CPtrNode *node;
for(int i = 0; i < NUMSECTORS_Y; i++)
2020-04-17 13:14:59 +02:00
for(int j = 0; j < NUMSECTORS_X; j++) {
CSector *s = &ms_aSectors[i][j];
for(node = s->m_lists[ENTITYLIST_BUILDINGS].first; node; node = node->next)
((CEntity *)node->item)->m_scanCode = 0;
for(node = s->m_lists[ENTITYLIST_VEHICLES].first; node; node = node->next)
((CEntity *)node->item)->m_scanCode = 0;
for(node = s->m_lists[ENTITYLIST_PEDS].first; node; node = node->next)
((CEntity *)node->item)->m_scanCode = 0;
for(node = s->m_lists[ENTITYLIST_OBJECTS].first; node; node = node->next)
((CEntity *)node->item)->m_scanCode = 0;
for(node = s->m_lists[ENTITYLIST_DUMMIES].first; node; node = node->next)
((CEntity *)node->item)->m_scanCode = 0;
}
2019-05-15 16:52:37 +02:00
}
2020-04-16 20:46:08 +02:00
void
2020-04-17 13:14:59 +02:00
CWorld::ClearExcitingStuffFromArea(const CVector &pos, float radius, bool bRemoveProjectilesAndTidyUpShadows)
2020-04-16 20:46:08 +02:00
{
2020-04-17 13:14:59 +02:00
CPedPool *pedPool = CPools::GetPedPool();
for(int32 i = 0; i < pedPool->GetSize(); i++) {
CPed *pPed = pedPool->GetSlot(i);
if(pPed && !pPed->IsPlayer() && pPed->CanBeDeleted() &&
2020-05-28 16:21:00 +02:00
CVector2D(pPed->GetPosition() - pos).MagnitudeSqr() < SQR(radius)) {
2020-04-16 20:46:08 +02:00
CPopulation::RemovePed(pPed);
}
}
2020-04-17 13:14:59 +02:00
CVehiclePool *VehiclePool = CPools::GetVehiclePool();
for(int32 i = 0; i < VehiclePool->GetSize(); i++) {
CVehicle *pVehicle = VehiclePool->GetSlot(i);
2020-05-28 16:21:00 +02:00
if(pVehicle && CVector2D(pVehicle->GetPosition() - pos).MagnitudeSqr() < SQR(radius) &&
2020-04-17 13:14:59 +02:00
!pVehicle->bIsLocked && pVehicle->CanBeDeleted()) {
if(pVehicle->pDriver) {
2020-04-16 20:46:08 +02:00
CPopulation::RemovePed(pVehicle->pDriver);
pVehicle->pDriver = nil;
}
2020-04-17 13:14:59 +02:00
for(int32 j = 0; j < pVehicle->m_nNumMaxPassengers; ++j) {
if(pVehicle->pPassengers[j]) {
2020-04-16 20:46:08 +02:00
CPopulation::RemovePed(pVehicle->pPassengers[j]);
pVehicle->pPassengers[j] = nil;
--pVehicle->m_nNumPassengers;
}
}
CCarCtrl::RemoveFromInterestingVehicleList(pVehicle);
CWorld::Remove(pVehicle);
delete pVehicle;
}
}
CObject::DeleteAllTempObjectsInArea(pos, radius);
gFireManager.ExtinguishPoint(pos, radius);
CWorld::ExtinguishAllCarFiresInArea(pos, radius);
CExplosion::RemoveAllExplosionsInArea(pos, radius);
2020-04-17 13:14:59 +02:00
if(bRemoveProjectilesAndTidyUpShadows) {
2020-04-16 20:46:08 +02:00
CProjectileInfo::RemoveAllProjectiles();
CShadows::TidyUpShadows();
}
}
2019-05-28 08:39:36 +02:00
bool
CWorld::CameraToIgnoreThisObject(CEntity *ent)
{
2020-04-17 13:14:59 +02:00
if(CGarages::IsModelIndexADoor(ent->GetModelIndex())) return false;
return ((CObject *)ent)->m_bCameraToAvoidThisObject != 1;
2019-05-28 08:39:36 +02:00
}
bool
2020-04-17 13:14:59 +02:00
CWorld::ProcessLineOfSight(const CVector &point1, const CVector &point2, CColPoint &point, CEntity *&entity,
bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects,
2020-05-24 15:14:27 +02:00
bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects, bool ignoreShootThrough)
2019-05-28 08:39:36 +02:00
{
int x, xstart, xend;
int y, ystart, yend;
int y1, y2;
float dist;
AdvanceCurrentScanCode();
entity = nil;
dist = 1.0f;
xstart = GetSectorIndexX(point1.x);
2020-03-07 20:22:43 +01:00
ystart = GetSectorIndexY(point1.y);
2019-05-28 08:39:36 +02:00
xend = GetSectorIndexX(point2.x);
2020-03-07 20:22:43 +01:00
yend = GetSectorIndexY(point2.y);
2019-05-28 08:39:36 +02:00
2020-04-17 13:14:59 +02:00
#define LOSARGS \
CColLine(point1, point2), point, dist, entity, checkBuildings, checkVehicles, checkPeds, checkObjects, \
2020-05-24 15:14:27 +02:00
checkDummies, ignoreSeeThrough, ignoreSomeObjects, ignoreShootThrough
2019-05-28 08:39:36 +02:00
2020-04-17 13:14:59 +02:00
if(xstart == xend && ystart == yend) {
2019-05-28 08:39:36 +02:00
// Only one sector
return ProcessLineOfSightSector(*GetSector(xstart, ystart), LOSARGS);
2020-04-17 13:14:59 +02:00
} else if(xstart == xend) {
2019-05-28 08:39:36 +02:00
// Only step in y
if(ystart < yend)
2020-04-17 13:14:59 +02:00
for(y = ystart; y <= yend; y++) ProcessLineOfSightSector(*GetSector(xstart, y), LOSARGS);
2019-05-28 08:39:36 +02:00
else
2020-04-17 13:14:59 +02:00
for(y = ystart; y >= yend; y--) ProcessLineOfSightSector(*GetSector(xstart, y), LOSARGS);
2019-05-28 08:39:36 +02:00
return dist < 1.0f;
2020-04-17 13:14:59 +02:00
} else if(ystart == yend) {
2019-05-28 08:39:36 +02:00
// Only step in x
if(xstart < xend)
2020-04-17 13:14:59 +02:00
for(x = xstart; x <= xend; x++) ProcessLineOfSightSector(*GetSector(x, ystart), LOSARGS);
2019-05-28 08:39:36 +02:00
else
2020-04-17 13:14:59 +02:00
for(x = xstart; x >= xend; x--) ProcessLineOfSightSector(*GetSector(x, ystart), LOSARGS);
2019-05-28 08:39:36 +02:00
return dist < 1.0f;
2020-04-17 13:14:59 +02:00
} else {
if(point1.x < point2.x) {
2019-05-28 08:39:36 +02:00
// Step from left to right
float m = (point2.y - point1.y) / (point2.x - point1.x);
y1 = ystart;
2020-04-17 13:14:59 +02:00
y2 = GetSectorIndexY((GetWorldX(xstart + 1) - point1.x) * m + point1.y);
2019-05-28 08:39:36 +02:00
if(y1 < y2)
2020-04-17 13:14:59 +02:00
for(y = y1; y <= y2; y++) ProcessLineOfSightSector(*GetSector(xstart, y), LOSARGS);
2019-05-28 08:39:36 +02:00
else
2020-04-17 13:14:59 +02:00
for(y = y1; y >= y2; y--) ProcessLineOfSightSector(*GetSector(xstart, y), LOSARGS);
2019-05-28 08:39:36 +02:00
2020-04-17 13:14:59 +02:00
for(x = xstart + 1; x < xend; x++) {
2019-05-28 08:39:36 +02:00
y1 = y2;
2020-04-17 13:14:59 +02:00
y2 = GetSectorIndexY((GetWorldX(x + 1) - point1.x) * m + point1.y);
2019-05-28 08:39:36 +02:00
if(y1 < y2)
2020-04-17 13:14:59 +02:00
for(y = y1; y <= y2; y++) ProcessLineOfSightSector(*GetSector(x, y), LOSARGS);
2019-05-28 08:39:36 +02:00
else
2020-04-17 13:14:59 +02:00
for(y = y1; y >= y2; y--) ProcessLineOfSightSector(*GetSector(x, y), LOSARGS);
2019-05-28 08:39:36 +02:00
}
y1 = y2;
y2 = yend;
if(y1 < y2)
2020-04-17 13:14:59 +02:00
for(y = y1; y <= y2; y++) ProcessLineOfSightSector(*GetSector(xend, y), LOSARGS);
2019-05-28 08:39:36 +02:00
else
2020-04-17 13:14:59 +02:00
for(y = y1; y >= y2; y--) ProcessLineOfSightSector(*GetSector(xend, y), LOSARGS);
} else {
2019-05-28 08:39:36 +02:00
// Step from right to left
float m = (point2.y - point1.y) / (point2.x - point1.x);
y1 = ystart;
2020-04-17 13:14:59 +02:00
y2 = GetSectorIndexY((GetWorldX(xstart) - point1.x) * m + point1.y);
2019-05-28 08:39:36 +02:00
if(y1 < y2)
2020-04-17 13:14:59 +02:00
for(y = y1; y <= y2; y++) ProcessLineOfSightSector(*GetSector(xstart, y), LOSARGS);
2019-05-28 08:39:36 +02:00
else
2020-04-17 13:14:59 +02:00
for(y = y1; y >= y2; y--) ProcessLineOfSightSector(*GetSector(xstart, y), LOSARGS);
2019-05-28 08:39:36 +02:00
2020-04-17 13:14:59 +02:00
for(x = xstart - 1; x > xend; x--) {
2019-05-28 08:39:36 +02:00
y1 = y2;
2020-04-17 13:14:59 +02:00
y2 = GetSectorIndexY((GetWorldX(x) - point1.x) * m + point1.y);
2019-05-28 08:39:36 +02:00
if(y1 < y2)
2020-04-17 13:14:59 +02:00
for(y = y1; y <= y2; y++) ProcessLineOfSightSector(*GetSector(x, y), LOSARGS);
2019-05-28 08:39:36 +02:00
else
2020-04-17 13:14:59 +02:00
for(y = y1; y >= y2; y--) ProcessLineOfSightSector(*GetSector(x, y), LOSARGS);
2019-05-28 08:39:36 +02:00
}
y1 = y2;
y2 = yend;
if(y1 < y2)
2020-04-17 13:14:59 +02:00
for(y = y1; y <= y2; y++) ProcessLineOfSightSector(*GetSector(xend, y), LOSARGS);
2019-05-28 08:39:36 +02:00
else
2020-04-17 13:14:59 +02:00
for(y = y1; y >= y2; y--) ProcessLineOfSightSector(*GetSector(xend, y), LOSARGS);
2019-05-28 08:39:36 +02:00
}
return dist < 1.0f;
}
#undef LOSARGS
}
bool
2020-04-17 13:14:59 +02:00
CWorld::ProcessLineOfSightSector(CSector &sector, const CColLine &line, CColPoint &point, float &dist, CEntity *&entity,
bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects,
2020-05-24 15:14:27 +02:00
bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects, bool ignoreShootThrough)
2019-05-28 08:39:36 +02:00
{
float mindist = dist;
bool deadPeds = !!bIncludeDeadPeds;
bIncludeDeadPeds = false;
2020-04-17 13:14:59 +02:00
if(checkBuildings) {
ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_BUILDINGS], line, point, mindist, entity,
2020-05-24 15:14:27 +02:00
ignoreSeeThrough, false, ignoreShootThrough);
2020-04-17 13:14:59 +02:00
ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_BUILDINGS_OVERLAP], line, point, mindist, entity,
2020-05-24 15:14:27 +02:00
ignoreSeeThrough, false, ignoreShootThrough);
2019-05-28 08:39:36 +02:00
}
2020-04-17 13:14:59 +02:00
if(checkVehicles) {
ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_VEHICLES], line, point, mindist, entity,
2020-05-24 15:14:27 +02:00
ignoreSeeThrough, false, ignoreShootThrough);
2020-04-17 13:14:59 +02:00
ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_VEHICLES_OVERLAP], line, point, mindist, entity,
2020-05-24 15:14:27 +02:00
ignoreSeeThrough, false, ignoreShootThrough);
2019-05-28 08:39:36 +02:00
}
2020-04-17 13:14:59 +02:00
if(checkPeds) {
if(deadPeds) bIncludeDeadPeds = true;
ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_PEDS], line, point, mindist, entity,
2020-05-24 15:14:27 +02:00
ignoreSeeThrough, false, ignoreShootThrough);
2020-04-17 13:14:59 +02:00
ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_PEDS_OVERLAP], line, point, mindist, entity,
2020-05-24 15:14:27 +02:00
ignoreSeeThrough, false, ignoreShootThrough);
2019-05-28 08:39:36 +02:00
bIncludeDeadPeds = false;
}
2020-04-17 13:14:59 +02:00
if(checkObjects) {
ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_OBJECTS], line, point, mindist, entity,
2020-05-24 15:14:27 +02:00
ignoreSeeThrough, ignoreSomeObjects, ignoreShootThrough);
2020-04-17 13:14:59 +02:00
ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_OBJECTS_OVERLAP], line, point, mindist, entity,
2020-05-24 15:14:27 +02:00
ignoreSeeThrough, ignoreSomeObjects, ignoreShootThrough);
2019-05-28 08:39:36 +02:00
}
2020-04-17 13:14:59 +02:00
if(checkDummies) {
ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_DUMMIES], line, point, mindist, entity,
2020-05-24 15:14:27 +02:00
ignoreSeeThrough, false, ignoreShootThrough);
2020-04-17 13:14:59 +02:00
ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_DUMMIES_OVERLAP], line, point, mindist, entity,
2020-05-24 15:14:27 +02:00
ignoreSeeThrough, false, ignoreShootThrough);
2019-05-28 08:39:36 +02:00
}
bIncludeDeadPeds = deadPeds;
2020-04-17 13:14:59 +02:00
if(mindist < dist) {
2019-05-28 08:39:36 +02:00
dist = mindist;
return true;
2020-04-17 13:14:59 +02:00
} else
2019-05-28 08:39:36 +02:00
return false;
}
bool
2020-04-17 13:14:59 +02:00
CWorld::ProcessLineOfSightSectorList(CPtrList &list, const CColLine &line, CColPoint &point, float &dist,
2020-05-24 15:14:27 +02:00
CEntity *&entity, bool ignoreSeeThrough, bool ignoreSomeObjects, bool ignoreShootThrough)
2019-05-28 08:39:36 +02:00
{
bool deadPeds = false;
float mindist = dist;
CPtrNode *node;
CEntity *e;
CColModel *colmodel;
2020-04-17 13:14:59 +02:00
if(list.first && bIncludeDeadPeds && ((CEntity *)list.first->item)->IsPed()) deadPeds = true;
2019-05-28 08:39:36 +02:00
2020-04-17 13:14:59 +02:00
for(node = list.first; node; node = node->next) {
e = (CEntity *)node->item;
if(e->m_scanCode != GetCurrentScanCode() && e != pIgnoreEntity && (e->bUsesCollision || deadPeds) &&
!(ignoreSomeObjects && CameraToIgnoreThisObject(e))) {
2019-05-28 08:39:36 +02:00
colmodel = nil;
e->m_scanCode = GetCurrentScanCode();
2020-04-17 13:14:59 +02:00
if(e->IsPed()) {
if(e->bUsesCollision || deadPeds && ((CPed *)e)->m_nPedState == PED_DEAD) {
2020-05-10 13:08:02 +02:00
colmodel = ((CPedModelInfo *)CModelInfo::GetModelInfo(e->GetModelIndex()))->AnimatePedColModelSkinned(e->GetClump());
2020-04-17 13:14:59 +02:00
} else
2019-05-28 08:39:36 +02:00
colmodel = nil;
2020-05-10 13:08:02 +02:00
2020-04-17 13:14:59 +02:00
} else if(e->bUsesCollision)
2019-05-28 08:39:36 +02:00
colmodel = CModelInfo::GetModelInfo(e->GetModelIndex())->GetColModel();
2020-04-17 13:14:59 +02:00
if(colmodel && CCollision::ProcessLineOfSight(line, e->GetMatrix(), *colmodel, point, dist,
2020-05-24 15:14:27 +02:00
ignoreSeeThrough, ignoreShootThrough))
2019-05-28 08:39:36 +02:00
entity = e;
}
}
2020-04-17 13:14:59 +02:00
if(mindist < dist) {
2019-05-28 08:39:36 +02:00
dist = mindist;
return true;
2020-04-17 13:14:59 +02:00
} else
2019-05-28 08:39:36 +02:00
return false;
}
2020-04-17 13:14:59 +02:00
bool
CWorld::ProcessVerticalLine(const CVector &point1, float z2, CColPoint &point, CEntity *&entity, bool checkBuildings,
bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies,
bool ignoreSeeThrough, CStoredCollPoly *poly)
2019-05-28 08:39:36 +02:00
{
AdvanceCurrentScanCode();
CVector point2(point1.x, point1.y, z2);
2020-05-10 11:20:27 +02:00
int secX = GetSectorIndexX(point1.x);
int secY = GetSectorIndexY(point1.y);
secX = clamp(secX, 0, NUMSECTORS_X-1);
secY = clamp(secY, 0, NUMSECTORS_Y-1);
return ProcessVerticalLineSector(*GetSector(secX, secY),
2020-04-17 13:14:59 +02:00
CColLine(point1, point2), point, entity, checkBuildings, checkVehicles,
checkPeds, checkObjects, checkDummies, ignoreSeeThrough, poly);
2019-05-28 08:39:36 +02:00
}
bool
2020-04-17 13:14:59 +02:00
CWorld::ProcessVerticalLineSector(CSector &sector, const CColLine &line, CColPoint &point, CEntity *&entity,
bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects,
bool checkDummies, bool ignoreSeeThrough, CStoredCollPoly *poly)
2019-05-28 08:39:36 +02:00
{
float mindist = 1.0f;
2020-04-17 13:14:59 +02:00
if(checkBuildings) {
ProcessVerticalLineSectorList(sector.m_lists[ENTITYLIST_BUILDINGS], line, point, mindist, entity,
ignoreSeeThrough, poly);
ProcessVerticalLineSectorList(sector.m_lists[ENTITYLIST_BUILDINGS_OVERLAP], line, point, mindist,
entity, ignoreSeeThrough, poly);
2019-05-28 08:39:36 +02:00
}
2020-04-17 13:14:59 +02:00
if(checkVehicles) {
ProcessVerticalLineSectorList(sector.m_lists[ENTITYLIST_VEHICLES], line, point, mindist, entity,
ignoreSeeThrough, poly);
ProcessVerticalLineSectorList(sector.m_lists[ENTITYLIST_VEHICLES_OVERLAP], line, point, mindist, entity,
ignoreSeeThrough, poly);
2019-05-28 08:39:36 +02:00
}
2020-04-17 13:14:59 +02:00
if(checkPeds) {
ProcessVerticalLineSectorList(sector.m_lists[ENTITYLIST_PEDS], line, point, mindist, entity,
ignoreSeeThrough, poly);
ProcessVerticalLineSectorList(sector.m_lists[ENTITYLIST_PEDS_OVERLAP], line, point, mindist, entity,
ignoreSeeThrough, poly);
2019-05-28 08:39:36 +02:00
}
2020-04-17 13:14:59 +02:00
if(checkObjects) {
ProcessVerticalLineSectorList(sector.m_lists[ENTITYLIST_OBJECTS], line, point, mindist, entity,
ignoreSeeThrough, poly);
ProcessVerticalLineSectorList(sector.m_lists[ENTITYLIST_OBJECTS_OVERLAP], line, point, mindist, entity,
ignoreSeeThrough, poly);
2019-05-28 08:39:36 +02:00
}
2020-04-17 13:14:59 +02:00
if(checkDummies) {
ProcessVerticalLineSectorList(sector.m_lists[ENTITYLIST_DUMMIES], line, point, mindist, entity,
ignoreSeeThrough, poly);
ProcessVerticalLineSectorList(sector.m_lists[ENTITYLIST_DUMMIES_OVERLAP], line, point, mindist, entity,
ignoreSeeThrough, poly);
2019-05-28 08:39:36 +02:00
}
return mindist < 1.0f;
}
bool
2020-04-17 13:14:59 +02:00
CWorld::ProcessVerticalLineSectorList(CPtrList &list, const CColLine &line, CColPoint &point, float &dist,
CEntity *&entity, bool ignoreSeeThrough, CStoredCollPoly *poly)
2019-05-28 08:39:36 +02:00
{
float mindist = dist;
CPtrNode *node;
CEntity *e;
CColModel *colmodel;
2020-04-17 13:14:59 +02:00
for(node = list.first; node; node = node->next) {
e = (CEntity *)node->item;
if(e->m_scanCode != GetCurrentScanCode() && e->bUsesCollision) {
2019-05-28 08:39:36 +02:00
e->m_scanCode = GetCurrentScanCode();
colmodel = CModelInfo::GetModelInfo(e->GetModelIndex())->GetColModel();
2020-04-17 13:14:59 +02:00
if(CCollision::ProcessVerticalLine(line, e->GetMatrix(), *colmodel, point, dist,
2020-05-24 15:14:27 +02:00
ignoreSeeThrough, false, poly))
2019-05-28 08:39:36 +02:00
entity = e;
}
}
2020-04-17 13:14:59 +02:00
if(mindist < dist) {
2019-05-28 08:39:36 +02:00
dist = mindist;
return true;
2020-04-17 13:14:59 +02:00
} else
2019-05-28 08:39:36 +02:00
return false;
}
bool
2020-04-17 13:14:59 +02:00
CWorld::GetIsLineOfSightClear(const CVector &point1, const CVector &point2, bool checkBuildings, bool checkVehicles,
bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough,
bool ignoreSomeObjects)
2019-05-28 08:39:36 +02:00
{
int x, xstart, xend;
int y, ystart, yend;
int y1, y2;
AdvanceCurrentScanCode();
xstart = GetSectorIndexX(point1.x);
2020-03-07 20:22:43 +01:00
ystart = GetSectorIndexY(point1.y);
2019-05-28 08:39:36 +02:00
xend = GetSectorIndexX(point2.x);
2020-03-07 20:22:43 +01:00
yend = GetSectorIndexY(point2.y);
2019-05-28 08:39:36 +02:00
2020-04-17 13:14:59 +02:00
#define LOSARGS \
CColLine(point1, point2), checkBuildings, checkVehicles, checkPeds, checkObjects, checkDummies, \
ignoreSeeThrough, ignoreSomeObjects
2019-05-28 08:39:36 +02:00
2020-04-17 13:14:59 +02:00
if(xstart == xend && ystart == yend) {
2019-05-28 08:39:36 +02:00
// Only one sector
return GetIsLineOfSightSectorClear(*GetSector(xstart, ystart), LOSARGS);
2020-04-17 13:14:59 +02:00
} else if(xstart == xend) {
2019-05-28 08:39:36 +02:00
// Only step in y
2020-04-17 13:14:59 +02:00
if(ystart < yend) {
2019-05-28 08:39:36 +02:00
for(y = ystart; y <= yend; y++)
2020-04-17 13:14:59 +02:00
if(!GetIsLineOfSightSectorClear(*GetSector(xstart, y), LOSARGS)) return false;
} else {
2019-05-28 08:39:36 +02:00
for(y = ystart; y >= yend; y--)
2020-04-17 13:14:59 +02:00
if(!GetIsLineOfSightSectorClear(*GetSector(xstart, y), LOSARGS)) return false;
2019-05-28 08:39:36 +02:00
}
2020-04-17 13:14:59 +02:00
} else if(ystart == yend) {
2019-05-28 08:39:36 +02:00
// Only step in x
2020-04-17 13:14:59 +02:00
if(xstart < xend) {
2019-05-28 08:39:36 +02:00
for(x = xstart; x <= xend; x++)
2020-04-17 13:14:59 +02:00
if(!GetIsLineOfSightSectorClear(*GetSector(x, ystart), LOSARGS)) return false;
} else {
2019-05-28 08:39:36 +02:00
for(x = xstart; x >= xend; x--)
2020-04-17 13:14:59 +02:00
if(!GetIsLineOfSightSectorClear(*GetSector(x, ystart), LOSARGS)) return false;
2019-05-28 08:39:36 +02:00
}
2020-04-17 13:14:59 +02:00
} else {
if(point1.x < point2.x) {
2019-05-28 08:39:36 +02:00
// Step from left to right
float m = (point2.y - point1.y) / (point2.x - point1.x);
y1 = ystart;
2020-04-17 13:14:59 +02:00
y2 = GetSectorIndexY((GetWorldX(xstart + 1) - point1.x) * m + point1.y);
if(y1 < y2) {
2019-05-28 08:39:36 +02:00
for(y = y1; y <= y2; y++)
2020-04-17 13:14:59 +02:00
if(!GetIsLineOfSightSectorClear(*GetSector(xstart, y), LOSARGS)) return false;
} else {
2019-05-28 08:39:36 +02:00
for(y = y1; y >= y2; y--)
2020-04-17 13:14:59 +02:00
if(!GetIsLineOfSightSectorClear(*GetSector(xstart, y), LOSARGS)) return false;
2019-05-28 08:39:36 +02:00
}
2020-04-17 13:14:59 +02:00
for(x = xstart + 1; x < xend; x++) {
2019-05-28 08:39:36 +02:00
y1 = y2;
2020-04-17 13:14:59 +02:00
y2 = GetSectorIndexY((GetWorldX(x + 1) - point1.x) * m + point1.y);
if(y1 < y2) {
2019-05-28 08:39:36 +02:00
for(y = y1; y <= y2; y++)
if(!GetIsLineOfSightSectorClear(*GetSector(x, y), LOSARGS))
return false;
2020-04-17 13:14:59 +02:00
} else {
2019-05-28 08:39:36 +02:00
for(y = y1; y >= y2; y--)
if(!GetIsLineOfSightSectorClear(*GetSector(x, y), LOSARGS))
return false;
}
}
y1 = y2;
y2 = yend;
2020-04-17 13:14:59 +02:00
if(y1 < y2) {
2019-05-28 08:39:36 +02:00
for(y = y1; y <= y2; y++)
2020-04-17 13:14:59 +02:00
if(!GetIsLineOfSightSectorClear(*GetSector(xend, y), LOSARGS)) return false;
} else {
2019-05-28 08:39:36 +02:00
for(y = y1; y >= y2; y--)
2020-04-17 13:14:59 +02:00
if(!GetIsLineOfSightSectorClear(*GetSector(xend, y), LOSARGS)) return false;
2019-05-28 08:39:36 +02:00
}
2020-04-17 13:14:59 +02:00
} else {
2019-05-28 08:39:36 +02:00
// Step from right to left
float m = (point2.y - point1.y) / (point2.x - point1.x);
y1 = ystart;
2020-04-17 13:14:59 +02:00
y2 = GetSectorIndexY((GetWorldX(xstart) - point1.x) * m + point1.y);
if(y1 < y2) {
2019-05-28 08:39:36 +02:00
for(y = y1; y <= y2; y++)
2020-04-17 13:14:59 +02:00
if(!GetIsLineOfSightSectorClear(*GetSector(xstart, y), LOSARGS)) return false;
} else {
2019-05-28 08:39:36 +02:00
for(y = y1; y >= y2; y--)
2020-04-17 13:14:59 +02:00
if(!GetIsLineOfSightSectorClear(*GetSector(xstart, y), LOSARGS)) return false;
2019-05-28 08:39:36 +02:00
}
2020-04-17 13:14:59 +02:00
for(x = xstart - 1; x > xend; x--) {
2019-05-28 08:39:36 +02:00
y1 = y2;
2020-04-17 13:14:59 +02:00
y2 = GetSectorIndexY((GetWorldX(x) - point1.x) * m + point1.y);
if(y1 < y2) {
2019-05-28 08:39:36 +02:00
for(y = y1; y <= y2; y++)
if(!GetIsLineOfSightSectorClear(*GetSector(x, y), LOSARGS))
return false;
2020-04-17 13:14:59 +02:00
} else {
2019-05-28 08:39:36 +02:00
for(y = y1; y >= y2; y--)
if(!GetIsLineOfSightSectorClear(*GetSector(x, y), LOSARGS))
return false;
}
}
y1 = y2;
y2 = yend;
2020-04-17 13:14:59 +02:00
if(y1 < y2) {
2019-05-28 08:39:36 +02:00
for(y = y1; y <= y2; y++)
2020-04-17 13:14:59 +02:00
if(!GetIsLineOfSightSectorClear(*GetSector(xend, y), LOSARGS)) return false;
} else {
2019-05-28 08:39:36 +02:00
for(y = y1; y >= y2; y--)
2020-04-17 13:14:59 +02:00
if(!GetIsLineOfSightSectorClear(*GetSector(xend, y), LOSARGS)) return false;
2019-05-28 08:39:36 +02:00
}
}
}
return true;
#undef LOSARGS
}
bool
2020-04-17 13:14:59 +02:00
CWorld::GetIsLineOfSightSectorClear(CSector &sector, const CColLine &line, bool checkBuildings, bool checkVehicles,
bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough,
bool ignoreSomeObjects)
2019-05-28 08:39:36 +02:00
{
2020-04-17 13:14:59 +02:00
if(checkBuildings) {
2019-05-28 08:39:36 +02:00
if(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_BUILDINGS], line, ignoreSeeThrough))
return false;
2020-04-17 13:14:59 +02:00
if(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_BUILDINGS_OVERLAP], line,
ignoreSeeThrough))
2019-05-28 08:39:36 +02:00
return false;
}
2020-04-17 13:14:59 +02:00
if(checkVehicles) {
2019-05-28 08:39:36 +02:00
if(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_VEHICLES], line, ignoreSeeThrough))
return false;
2020-04-17 13:14:59 +02:00
if(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_VEHICLES_OVERLAP], line,
ignoreSeeThrough))
2019-05-28 08:39:36 +02:00
return false;
}
2020-04-17 13:14:59 +02:00
if(checkPeds) {
2019-05-28 08:39:36 +02:00
if(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_PEDS], line, ignoreSeeThrough))
return false;
if(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_PEDS_OVERLAP], line, ignoreSeeThrough))
return false;
}
2020-04-17 13:14:59 +02:00
if(checkObjects) {
if(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_OBJECTS], line, ignoreSeeThrough,
ignoreSomeObjects))
2019-05-28 08:39:36 +02:00
return false;
2020-04-17 13:14:59 +02:00
if(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_OBJECTS_OVERLAP], line, ignoreSeeThrough,
ignoreSomeObjects))
2019-05-28 08:39:36 +02:00
return false;
}
2020-04-17 13:14:59 +02:00
if(checkDummies) {
2019-05-28 08:39:36 +02:00
if(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_DUMMIES], line, ignoreSeeThrough))
return false;
if(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_DUMMIES_OVERLAP], line, ignoreSeeThrough))
return false;
}
return true;
}
bool
2020-04-17 13:14:59 +02:00
CWorld::GetIsLineOfSightSectorListClear(CPtrList &list, const CColLine &line, bool ignoreSeeThrough,
bool ignoreSomeObjects)
2019-05-28 08:39:36 +02:00
{
CPtrNode *node;
CEntity *e;
CColModel *colmodel;
2020-04-17 13:14:59 +02:00
for(node = list.first; node; node = node->next) {
e = (CEntity *)node->item;
if(e->m_scanCode != GetCurrentScanCode() && e->bUsesCollision) {
2019-05-28 08:39:36 +02:00
e->m_scanCode = GetCurrentScanCode();
2020-04-17 13:14:59 +02:00
if(e != pIgnoreEntity && !(ignoreSomeObjects && CameraToIgnoreThisObject(e))) {
2019-05-28 08:39:36 +02:00
colmodel = CModelInfo::GetModelInfo(e->GetModelIndex())->GetColModel();
2020-05-24 15:14:27 +02:00
if(CCollision::TestLineOfSight(line, e->GetMatrix(), *colmodel, ignoreSeeThrough, false))
2019-05-28 08:39:36 +02:00
return false;
}
}
}
return true;
}
void
2020-06-14 23:15:56 +02:00
CWorld::FindObjectsInRangeSectorList(CPtrList &list, Const CVector &centre, float radius, bool ignoreZ, int16 *numObjects,
int16 lastObject, CEntity **objects)
{
2020-03-26 14:16:06 +01:00
float radiusSqr = radius * radius;
float objDistSqr;
2020-04-17 13:14:59 +02:00
for(CPtrNode *node = list.first; node; node = node->next) {
CEntity *object = (CEntity *)node->item;
if(object->m_scanCode != GetCurrentScanCode()) {
2019-09-12 14:35:05 +02:00
object->m_scanCode = GetCurrentScanCode();
CVector diff = centre - object->GetPosition();
2020-04-17 13:14:59 +02:00
if(ignoreZ)
objDistSqr = diff.MagnitudeSqr2D();
else
objDistSqr = diff.MagnitudeSqr();
2020-06-14 23:15:56 +02:00
if(objDistSqr < radiusSqr && *numObjects < lastObject) {
if(objects) { objects[*numObjects] = object; }
(*numObjects)++;
}
}
}
}
void
2020-06-14 23:15:56 +02:00
CWorld::FindObjectsInRange(Const CVector &centre, float radius, bool ignoreZ, int16 *numObjects, int16 lastObject,
2020-04-17 13:14:59 +02:00
CEntity **objects, bool checkBuildings, bool checkVehicles, bool checkPeds,
bool checkObjects, bool checkDummies)
{
2020-03-26 14:16:06 +01:00
int minX = GetSectorIndexX(centre.x - radius);
2020-04-17 13:14:59 +02:00
if(minX <= 0) minX = 0;
2020-03-26 14:16:06 +01:00
int minY = GetSectorIndexY(centre.y - radius);
2020-04-17 13:14:59 +02:00
if(minY <= 0) minY = 0;
2020-03-26 14:16:06 +01:00
int maxX = GetSectorIndexX(centre.x + radius);
2020-03-07 20:22:43 +01:00
#ifdef FIX_BUGS
2020-04-17 13:14:59 +02:00
if(maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X - 1;
2020-03-07 20:22:43 +01:00
#else
2020-04-17 13:14:59 +02:00
if(maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X;
2020-03-07 20:22:43 +01:00
#endif
2020-03-26 14:16:06 +01:00
int maxY = GetSectorIndexY(centre.y + radius);
2020-03-07 20:22:43 +01:00
#ifdef FIX_BUGS
2020-04-17 13:14:59 +02:00
if(maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y - 1;
2020-03-07 20:22:43 +01:00
#else
2020-04-17 13:14:59 +02:00
if(maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y;
2020-03-07 20:22:43 +01:00
#endif
2020-04-17 13:14:59 +02:00
AdvanceCurrentScanCode();
2020-06-14 23:15:56 +02:00
*numObjects = 0;
for(int curY = minY; curY <= maxY; curY++) {
for(int curX = minX; curX <= maxX; curX++) {
CSector *sector = GetSector(curX, curY);
2020-04-17 13:14:59 +02:00
if(checkBuildings) {
FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_BUILDINGS], centre, radius,
2020-06-14 23:15:56 +02:00
ignoreZ, numObjects, lastObject, objects);
2020-04-17 13:14:59 +02:00
FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], centre,
2020-06-14 23:15:56 +02:00
radius, ignoreZ, numObjects, lastObject, objects);
}
2020-04-17 13:14:59 +02:00
if(checkVehicles) {
FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_VEHICLES], centre, radius,
2020-06-14 23:15:56 +02:00
ignoreZ, numObjects, lastObject, objects);
2020-04-17 13:14:59 +02:00
FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], centre,
2020-06-14 23:15:56 +02:00
radius, ignoreZ, numObjects, lastObject, objects);
}
2020-04-17 13:14:59 +02:00
if(checkPeds) {
FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_PEDS], centre, radius, ignoreZ,
2020-06-14 23:15:56 +02:00
numObjects, lastObject, objects);
2020-04-17 13:14:59 +02:00
FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_PEDS_OVERLAP], centre, radius,
2020-06-14 23:15:56 +02:00
ignoreZ, numObjects, lastObject, objects);
}
2020-04-17 13:14:59 +02:00
if(checkObjects) {
FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_OBJECTS], centre, radius,
2020-06-14 23:15:56 +02:00
ignoreZ, numObjects, lastObject, objects);
2020-04-17 13:14:59 +02:00
FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_OBJECTS_OVERLAP], centre,
2020-06-14 23:15:56 +02:00
radius, ignoreZ, numObjects, lastObject, objects);
}
2020-04-17 13:14:59 +02:00
if(checkDummies) {
FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_DUMMIES], centre, radius,
2020-06-14 23:15:56 +02:00
ignoreZ, numObjects, lastObject, objects);
2020-04-17 13:14:59 +02:00
FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_DUMMIES_OVERLAP], centre,
2020-06-14 23:15:56 +02:00
radius, ignoreZ, numObjects, lastObject, objects);
}
}
}
}
2020-04-17 13:14:59 +02:00
void
CWorld::FindObjectsOfTypeInRangeSectorList(uint32 modelId, CPtrList &list, const CVector &position, float radius,
bool bCheck2DOnly, int16 *nEntitiesFound, int16 maxEntitiesToFind,
CEntity **aEntities)
2020-04-16 20:46:08 +02:00
{
2020-04-17 13:14:59 +02:00
for(CPtrNode *pNode = list.first; pNode; pNode = pNode->next) {
CEntity *pEntity = (CEntity *)pNode->item;
if(pEntity->m_scanCode != GetCurrentScanCode()) {
2020-04-17 13:13:55 +02:00
pEntity->m_scanCode = GetCurrentScanCode();
2020-05-05 13:48:35 +02:00
if (modelId == pEntity->GetModelIndex()) {
float fMagnitude = 0.0f;
if(bCheck2DOnly)
fMagnitude = (position - pEntity->GetPosition()).MagnitudeSqr2D();
else
fMagnitude = (position - pEntity->GetPosition()).MagnitudeSqr();
if(fMagnitude < radius * radius && *nEntitiesFound < maxEntitiesToFind) {
if(aEntities) aEntities[*nEntitiesFound] = pEntity;
++*nEntitiesFound;
}
2020-04-16 20:46:08 +02:00
}
}
}
}
2020-04-17 13:14:59 +02:00
void
CWorld::FindObjectsOfTypeInRange(uint32 modelId, const CVector &position, float radius, bool bCheck2DOnly,
int16 *nEntitiesFound, int16 maxEntitiesToFind, CEntity **aEntities, bool bBuildings,
bool bVehicles, bool bPeds, bool bObjects, bool bDummies)
2020-04-16 20:46:08 +02:00
{
CWorld::AdvanceCurrentScanCode();
*nEntitiesFound = 0;
const CVector2D vecSectorStartPos(position.x - radius, position.y - radius);
const CVector2D vecSectorEndPos(position.x + radius, position.y + radius);
2020-04-19 18:34:08 +02:00
const int32 nStartX = Max(CWorld::GetSectorIndexX(vecSectorStartPos.x), 0);
const int32 nStartY = Max(CWorld::GetSectorIndexY(vecSectorStartPos.y), 0);
const int32 nEndX = Min(CWorld::GetSectorIndexX(vecSectorEndPos.x), NUMSECTORS_X - 1);
const int32 nEndY = Min(CWorld::GetSectorIndexY(vecSectorEndPos.y), NUMSECTORS_Y - 1);
2020-04-17 13:14:59 +02:00
for(int32 y = nStartY; y <= nEndY; y++) {
for(int32 x = nStartX; x <= nEndX; x++) {
CSector *pSector = CWorld::GetSector(x, y);
if(bBuildings) {
CWorld::FindObjectsOfTypeInRangeSectorList(
modelId, pSector->m_lists[ENTITYLIST_BUILDINGS], position, radius, bCheck2DOnly,
nEntitiesFound, maxEntitiesToFind, aEntities);
CWorld::FindObjectsOfTypeInRangeSectorList(
modelId, pSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], position, radius,
bCheck2DOnly, nEntitiesFound, maxEntitiesToFind, aEntities);
}
if(bVehicles) {
CWorld::FindObjectsOfTypeInRangeSectorList(
modelId, pSector->m_lists[ENTITYLIST_VEHICLES], position, radius, bCheck2DOnly,
nEntitiesFound, maxEntitiesToFind, aEntities);
CWorld::FindObjectsOfTypeInRangeSectorList(
modelId, pSector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], position, radius,
bCheck2DOnly, nEntitiesFound, maxEntitiesToFind, aEntities);
}
if(bPeds) {
CWorld::FindObjectsOfTypeInRangeSectorList(
modelId, pSector->m_lists[ENTITYLIST_PEDS], position, radius, bCheck2DOnly,
nEntitiesFound, maxEntitiesToFind, aEntities);
CWorld::FindObjectsOfTypeInRangeSectorList(
modelId, pSector->m_lists[ENTITYLIST_PEDS_OVERLAP], position, radius, bCheck2DOnly,
nEntitiesFound, maxEntitiesToFind, aEntities);
}
if(bObjects) {
CWorld::FindObjectsOfTypeInRangeSectorList(
modelId, pSector->m_lists[ENTITYLIST_OBJECTS], position, radius, bCheck2DOnly,
nEntitiesFound, maxEntitiesToFind, aEntities);
CWorld::FindObjectsOfTypeInRangeSectorList(
modelId, pSector->m_lists[ENTITYLIST_OBJECTS_OVERLAP], position, radius,
bCheck2DOnly, nEntitiesFound, maxEntitiesToFind, aEntities);
}
if(bDummies) {
CWorld::FindObjectsOfTypeInRangeSectorList(
modelId, pSector->m_lists[ENTITYLIST_DUMMIES], position, radius, bCheck2DOnly,
nEntitiesFound, maxEntitiesToFind, aEntities);
CWorld::FindObjectsOfTypeInRangeSectorList(
modelId, pSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP], position, radius,
bCheck2DOnly, nEntitiesFound, maxEntitiesToFind, aEntities);
}
}
}
}
CEntity *
CWorld::TestSphereAgainstWorld(CVector centre, float radius, CEntity *entityToIgnore, bool checkBuildings,
bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies,
bool ignoreSomeObjects)
2019-07-15 14:11:40 +02:00
{
2020-04-17 13:14:59 +02:00
CEntity *foundE = nil;
2019-07-15 14:11:40 +02:00
2020-03-26 14:16:06 +01:00
int minX = GetSectorIndexX(centre.x - radius);
2020-04-17 13:14:59 +02:00
if(minX <= 0) minX = 0;
2019-07-15 14:11:40 +02:00
2020-03-26 14:16:06 +01:00
int minY = GetSectorIndexY(centre.y - radius);
2020-04-17 13:14:59 +02:00
if(minY <= 0) minY = 0;
2019-07-15 14:11:40 +02:00
2020-03-26 14:16:06 +01:00
int maxX = GetSectorIndexX(centre.x + radius);
2020-03-07 20:22:43 +01:00
#ifdef FIX_BUGS
2020-04-17 13:14:59 +02:00
if(maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X - 1;
2020-03-07 20:22:43 +01:00
#else
2020-04-17 13:14:59 +02:00
if(maxX >= NUMSECTORS_X) maxX = NUMSECTORS_X;
2020-03-07 20:22:43 +01:00
#endif
2019-07-15 14:11:40 +02:00
2020-03-26 14:16:06 +01:00
int maxY = GetSectorIndexY(centre.y + radius);
2020-03-07 20:22:43 +01:00
#ifdef FIX_BUGS
2020-04-17 13:14:59 +02:00
if(maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y - 1;
2020-03-07 20:22:43 +01:00
#else
2020-04-17 13:14:59 +02:00
if(maxY >= NUMSECTORS_Y) maxY = NUMSECTORS_Y;
2020-03-07 20:22:43 +01:00
#endif
2019-07-15 14:11:40 +02:00
AdvanceCurrentScanCode();
2020-04-17 13:14:59 +02:00
for(int curY = minY; curY <= maxY; curY++) {
for(int curX = minX; curX <= maxX; curX++) {
CSector *sector = GetSector(curX, curY);
if(checkBuildings) {
foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_BUILDINGS], centre,
radius, entityToIgnore, false);
if(foundE) return foundE;
2019-07-15 14:11:40 +02:00
2020-04-17 13:14:59 +02:00
foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP],
centre, radius, entityToIgnore, false);
if(foundE) return foundE;
2019-07-15 14:11:40 +02:00
}
2020-04-17 13:14:59 +02:00
if(checkVehicles) {
foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_VEHICLES], centre,
radius, entityToIgnore, false);
if(foundE) return foundE;
2019-07-15 14:11:40 +02:00
2020-04-17 13:14:59 +02:00
foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_VEHICLES_OVERLAP],
centre, radius, entityToIgnore, false);
if(foundE) return foundE;
2019-07-15 14:11:40 +02:00
}
2020-04-17 13:14:59 +02:00
if(checkPeds) {
foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_PEDS], centre, radius,
entityToIgnore, false);
if(foundE) return foundE;
2019-07-15 14:11:40 +02:00
2020-04-17 13:14:59 +02:00
foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_PEDS_OVERLAP], centre,
radius, entityToIgnore, false);
if(foundE) return foundE;
2019-07-15 14:11:40 +02:00
}
2020-04-17 13:14:59 +02:00
if(checkObjects) {
foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_OBJECTS], centre,
radius, entityToIgnore, ignoreSomeObjects);
if(foundE) return foundE;
2019-07-15 14:11:40 +02:00
2020-04-17 13:14:59 +02:00
foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_OBJECTS_OVERLAP],
centre, radius, entityToIgnore, ignoreSomeObjects);
if(foundE) return foundE;
2019-07-15 14:11:40 +02:00
}
2020-04-17 13:14:59 +02:00
if(checkDummies) {
foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_DUMMIES], centre,
radius, entityToIgnore, false);
if(foundE) return foundE;
2019-07-15 14:11:40 +02:00
2020-04-17 13:14:59 +02:00
foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_DUMMIES_OVERLAP],
centre, radius, entityToIgnore, false);
if(foundE) return foundE;
2019-07-15 14:11:40 +02:00
}
}
}
return foundE;
}
2020-04-17 13:14:59 +02:00
CEntity *
CWorld::TestSphereAgainstSectorList(CPtrList &list, CVector spherePos, float radius, CEntity *entityToIgnore,
bool ignoreSomeObjects)
2019-07-15 14:11:40 +02:00
{
static CColModel sphereCol;
2020-05-06 17:56:38 +02:00
CColSphere sphere;
2019-07-15 14:11:40 +02:00
sphereCol.boundingSphere.center.x = 0.0f;
sphereCol.boundingSphere.center.y = 0.0f;
sphereCol.boundingSphere.center.z = 0.0f;
sphereCol.boundingSphere.radius = radius;
sphereCol.boundingBox.min.x = -radius;
sphereCol.boundingBox.min.y = -radius;
sphereCol.boundingBox.min.z = -radius;
sphereCol.boundingBox.max.x = radius;
sphereCol.boundingBox.max.y = radius;
sphereCol.boundingBox.max.z = radius;
sphereCol.numSpheres = 1;
2020-05-06 17:56:38 +02:00
sphere.Set(radius, CVector(0.0f, 0.0f, 0.0f));
sphereCol.spheres = &sphere;
2019-07-15 14:11:40 +02:00
sphereCol.numLines = 0;
sphereCol.numBoxes = 0;
sphereCol.numTriangles = 0;
sphereCol.ownsCollisionVolumes = false;
CMatrix sphereMat;
sphereMat.SetTranslate(spherePos);
2020-04-17 13:14:59 +02:00
for(CPtrNode *node = list.first; node; node = node->next) {
CEntity *e = (CEntity *)node->item;
2019-07-15 14:11:40 +02:00
2020-04-17 13:14:59 +02:00
if(e->m_scanCode != GetCurrentScanCode()) {
2019-07-15 14:11:40 +02:00
e->m_scanCode = GetCurrentScanCode();
2020-04-17 13:14:59 +02:00
if(e != entityToIgnore && e->bUsesCollision &&
!(ignoreSomeObjects && CameraToIgnoreThisObject(e))) {
CVector diff = spherePos - e->GetBoundCentre();
2019-07-15 14:11:40 +02:00
float distance = diff.Magnitude();
2020-04-17 13:14:59 +02:00
if(e->GetBoundRadius() + radius > distance) {
2020-05-05 13:48:35 +02:00
CColModel *eCol = CModelInfo::GetModelInfo(e->GetModelIndex())->GetColModel();
2020-04-17 13:14:59 +02:00
int collidedSpheres =
CCollision::ProcessColModels(sphereMat, sphereCol, e->GetMatrix(), *eCol,
gaTempSphereColPoints, nil, nil);
if(collidedSpheres != 0 ||
2020-05-05 13:48:35 +02:00
(e->IsVehicle() && ((CVehicle *)e)->m_vehType == VEHICLE_TYPE_CAR && e->GetModelIndex() != MI_DODO &&
2020-04-17 13:14:59 +02:00
radius + eCol->boundingBox.max.x > distance)) {
2019-07-15 14:11:40 +02:00
return e;
}
}
}
}
}
return nil;
}
2019-05-28 08:39:36 +02:00
float
CWorld::FindGroundZForCoord(float x, float y)
{
CColPoint point;
CEntity *ent;
2020-04-17 13:14:59 +02:00
if(ProcessVerticalLine(CVector(x, y, 1000.0f), -1000.0f, point, ent, true, false, false, false, true, false,
nil))
2019-05-28 08:39:36 +02:00
return point.point.z;
else
return 20.0f;
}
float
CWorld::FindGroundZFor3DCoord(float x, float y, float z, bool *found)
{
CColPoint point;
CEntity *ent;
2020-04-17 13:14:59 +02:00
if(ProcessVerticalLine(CVector(x, y, z), -1000.0f, point, ent, true, false, false, false, false, false, nil)) {
if(found) *found = true;
2019-05-28 08:39:36 +02:00
return point.point.z;
2020-04-17 13:14:59 +02:00
} else {
if(found) *found = false;
2019-05-28 08:39:36 +02:00
return 0.0f;
}
}
float
CWorld::FindRoofZFor3DCoord(float x, float y, float z, bool *found)
{
CColPoint point;
CEntity *ent;
2020-04-17 13:14:59 +02:00
if(ProcessVerticalLine(CVector(x, y, z), 1000.0f, point, ent, true, false, false, false, true, false, nil)) {
if(found) *found = true;
2019-05-28 08:39:36 +02:00
return point.point.z;
2020-04-17 13:14:59 +02:00
} else {
2019-05-28 08:39:36 +02:00
if(found == nil)
2020-04-17 13:14:59 +02:00
printf("THERE IS NO MAP BELOW THE FOLLOWING COORS:%f %f %f. (FindGroundZFor3DCoord)\n", x, y,
z);
if(found) *found = false;
2019-05-28 08:39:36 +02:00
return 20.0f;
}
}
2020-04-17 13:14:59 +02:00
void
CWorld::RemoveReferencesToDeletedObject(CEntity *pDeletedObject)
{
2020-04-16 20:46:08 +02:00
int32 i = CPools::GetPedPool()->GetSize();
2020-04-17 13:14:59 +02:00
while(--i >= 0) {
CPed *pPed = CPools::GetPedPool()->GetSlot(i);
if(pPed && pPed != pDeletedObject) {
2020-04-16 20:46:08 +02:00
pPed->RemoveRefsToEntity(pDeletedObject);
2020-04-17 13:14:59 +02:00
if(pPed->m_pCurrentPhysSurface == pDeletedObject) pPed->m_pCurrentPhysSurface = nil;
2020-04-16 20:46:08 +02:00
}
}
i = CPools::GetVehiclePool()->GetSize();
2020-04-17 13:14:59 +02:00
while(--i >= 0) {
CVehicle *pVehicle = CPools::GetVehiclePool()->GetSlot(i);
if(pVehicle && pVehicle != pDeletedObject) {
2020-04-16 20:46:08 +02:00
pVehicle->RemoveRefsToEntity(pDeletedObject);
pVehicle->RemoveRefsToVehicle(pDeletedObject);
}
}
i = CPools::GetObjectPool()->GetSize();
2020-04-17 13:14:59 +02:00
while(--i >= 0) {
CObject *pObject = CPools::GetObjectPool()->GetSlot(i);
if(pObject && pObject != pDeletedObject) { pObject->RemoveRefsToEntity(pDeletedObject); }
2020-04-16 20:46:08 +02:00
}
}
2020-04-17 13:14:59 +02:00
void
CWorld::FindObjectsKindaColliding(const CVector &position, float radius, bool bCheck2DOnly, int16 *nCollidingEntities,
int16 maxEntitiesToFind, CEntity **aEntities, bool bBuildings, bool bVehicles,
bool bPeds, bool bObjects, bool bDummies)
{
2020-04-16 20:46:08 +02:00
CWorld::AdvanceCurrentScanCode();
*nCollidingEntities = 0;
const CVector2D vecSectorStartPos(position.x - radius, position.y - radius);
const CVector2D vecSectorEndPos(position.x + radius, position.y + radius);
2020-04-19 18:34:08 +02:00
const int32 nStartX = Max(CWorld::GetSectorIndexX(vecSectorStartPos.x), 0);
const int32 nStartY = Max(CWorld::GetSectorIndexY(vecSectorStartPos.y), 0);
const int32 nEndX = Min(CWorld::GetSectorIndexX(vecSectorEndPos.x), NUMSECTORS_X - 1);
const int32 nEndY = Min(CWorld::GetSectorIndexY(vecSectorEndPos.y), NUMSECTORS_Y - 1);
2020-04-17 13:14:59 +02:00
for(int32 y = nStartY; y <= nEndY; y++) {
for(int32 x = nStartX; x <= nEndX; x++) {
CSector *pSector = CWorld::GetSector(x, y);
if(bBuildings) {
CWorld::FindObjectsKindaCollidingSectorList(
pSector->m_lists[ENTITYLIST_BUILDINGS], position, radius, bCheck2DOnly,
nCollidingEntities, maxEntitiesToFind, aEntities);
CWorld::FindObjectsKindaCollidingSectorList(
pSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], position, radius, bCheck2DOnly,
nCollidingEntities, maxEntitiesToFind, aEntities);
}
if(bVehicles) {
CWorld::FindObjectsKindaCollidingSectorList(
pSector->m_lists[ENTITYLIST_VEHICLES], position, radius, bCheck2DOnly,
nCollidingEntities, maxEntitiesToFind, aEntities);
CWorld::FindObjectsKindaCollidingSectorList(
pSector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], position, radius, bCheck2DOnly,
nCollidingEntities, maxEntitiesToFind, aEntities);
}
if(bPeds) {
CWorld::FindObjectsKindaCollidingSectorList(pSector->m_lists[ENTITYLIST_PEDS], position,
radius, bCheck2DOnly, nCollidingEntities,
maxEntitiesToFind, aEntities);
CWorld::FindObjectsKindaCollidingSectorList(
pSector->m_lists[ENTITYLIST_PEDS_OVERLAP], position, radius, bCheck2DOnly,
nCollidingEntities, maxEntitiesToFind, aEntities);
}
if(bObjects) {
CWorld::FindObjectsKindaCollidingSectorList(
pSector->m_lists[ENTITYLIST_OBJECTS], position, radius, bCheck2DOnly,
nCollidingEntities, maxEntitiesToFind, aEntities);
CWorld::FindObjectsKindaCollidingSectorList(
pSector->m_lists[ENTITYLIST_OBJECTS_OVERLAP], position, radius, bCheck2DOnly,
nCollidingEntities, maxEntitiesToFind, aEntities);
}
if(bDummies) {
CWorld::FindObjectsKindaCollidingSectorList(
pSector->m_lists[ENTITYLIST_DUMMIES], position, radius, bCheck2DOnly,
nCollidingEntities, maxEntitiesToFind, aEntities);
CWorld::FindObjectsKindaCollidingSectorList(
pSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP], position, radius, bCheck2DOnly,
nCollidingEntities, maxEntitiesToFind, aEntities);
2020-04-16 20:46:08 +02:00
}
}
}
}
2020-04-17 13:14:59 +02:00
void
CWorld::FindObjectsKindaCollidingSectorList(CPtrList &list, const CVector &position, float radius, bool bCheck2DOnly,
int16 *nCollidingEntities, int16 maxEntitiesToFind, CEntity **aEntities)
2020-04-16 20:46:08 +02:00
{
2020-04-17 13:14:59 +02:00
for(CPtrNode *pNode = list.first; pNode; pNode = pNode->next) {
CEntity *pEntity = (CEntity *)pNode->item;
if(pEntity->m_scanCode != GetCurrentScanCode()) {
2020-04-17 13:13:55 +02:00
pEntity->m_scanCode = GetCurrentScanCode();
2020-04-16 20:46:08 +02:00
float fMagnitude = 0.0f;
2020-04-17 13:14:59 +02:00
if(bCheck2DOnly)
2020-04-17 02:38:05 +02:00
fMagnitude = (position - pEntity->GetPosition()).Magnitude2D();
2020-04-16 20:46:08 +02:00
else
2020-04-17 02:38:05 +02:00
fMagnitude = (position - pEntity->GetPosition()).Magnitude();
2020-04-17 13:14:59 +02:00
if(pEntity->GetBoundRadius() + radius > fMagnitude && *nCollidingEntities < maxEntitiesToFind) {
if(aEntities) aEntities[*nCollidingEntities] = pEntity;
2020-04-16 20:46:08 +02:00
++*nCollidingEntities;
}
}
}
}
void
2020-04-17 13:14:59 +02:00
CWorld::FindObjectsIntersectingCube(const CVector &vecStartPos, const CVector &vecEndPos, int16 *nIntersecting,
int16 maxEntitiesToFind, CEntity **aEntities, bool bBuildings, bool bVehicles,
bool bPeds, bool bObjects, bool bDummies)
{
2020-04-16 20:46:08 +02:00
CWorld::AdvanceCurrentScanCode();
*nIntersecting = 0;
2020-04-19 18:34:08 +02:00
const int32 nStartX = Max(CWorld::GetSectorIndexX(vecStartPos.x), 0);
const int32 nStartY = Max(CWorld::GetSectorIndexY(vecStartPos.y), 0);
const int32 nEndX = Min(CWorld::GetSectorIndexX(vecEndPos.x), NUMSECTORS_X - 1);
const int32 nEndY = Min(CWorld::GetSectorIndexY(vecEndPos.y), NUMSECTORS_Y - 1);
2020-04-17 13:14:59 +02:00
for(int32 y = nStartY; y <= nEndY; y++) {
for(int32 x = nStartX; x <= nEndX; x++) {
CSector *pSector = CWorld::GetSector(x, y);
if(bBuildings) {
CWorld::FindObjectsIntersectingCubeSectorList(pSector->m_lists[ENTITYLIST_BUILDINGS],
vecStartPos, vecEndPos, nIntersecting,
maxEntitiesToFind, aEntities);
CWorld::FindObjectsIntersectingCubeSectorList(
pSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], vecStartPos, vecEndPos,
nIntersecting, maxEntitiesToFind, aEntities);
}
if(bVehicles) {
CWorld::FindObjectsIntersectingCubeSectorList(pSector->m_lists[ENTITYLIST_VEHICLES],
vecStartPos, vecEndPos, nIntersecting,
maxEntitiesToFind, aEntities);
CWorld::FindObjectsIntersectingCubeSectorList(
pSector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], vecStartPos, vecEndPos,
nIntersecting, maxEntitiesToFind, aEntities);
}
if(bPeds) {
CWorld::FindObjectsIntersectingCubeSectorList(pSector->m_lists[ENTITYLIST_PEDS],
vecStartPos, vecEndPos, nIntersecting,
maxEntitiesToFind, aEntities);
CWorld::FindObjectsIntersectingCubeSectorList(pSector->m_lists[ENTITYLIST_PEDS_OVERLAP],
vecStartPos, vecEndPos, nIntersecting,
maxEntitiesToFind, aEntities);
}
if(bObjects) {
CWorld::FindObjectsIntersectingCubeSectorList(pSector->m_lists[ENTITYLIST_OBJECTS],
vecStartPos, vecEndPos, nIntersecting,
maxEntitiesToFind, aEntities);
CWorld::FindObjectsIntersectingCubeSectorList(
pSector->m_lists[ENTITYLIST_OBJECTS_OVERLAP], vecStartPos, vecEndPos, nIntersecting,
maxEntitiesToFind, aEntities);
}
if(bDummies) {
CWorld::FindObjectsIntersectingCubeSectorList(pSector->m_lists[ENTITYLIST_DUMMIES],
vecStartPos, vecEndPos, nIntersecting,
maxEntitiesToFind, aEntities);
CWorld::FindObjectsIntersectingCubeSectorList(
pSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP], vecStartPos, vecEndPos, nIntersecting,
maxEntitiesToFind, aEntities);
2020-04-16 20:46:08 +02:00
}
}
}
}
2020-04-17 13:14:59 +02:00
void
CWorld::FindObjectsIntersectingCubeSectorList(CPtrList &list, const CVector &vecStartPos, const CVector &vecEndPos,
int16 *nIntersecting, int16 maxEntitiesToFind, CEntity **aEntities)
2020-04-16 20:46:08 +02:00
{
2020-04-17 13:14:59 +02:00
for(CPtrNode *pNode = list.first; pNode; pNode = pNode->next) {
CEntity *pEntity = (CEntity *)pNode->item;
if(pEntity->m_scanCode != GetCurrentScanCode()) {
pEntity->m_scanCode = GetCurrentScanCode();
float fRadius = pEntity->GetBoundRadius();
const CVector &entityPos = pEntity->GetPosition();
if(fRadius + entityPos.x >= vecStartPos.x && entityPos.x - fRadius <= vecEndPos.x &&
fRadius + entityPos.y >= vecStartPos.y && entityPos.y - fRadius <= vecEndPos.y &&
fRadius + entityPos.z >= vecStartPos.z && entityPos.z - fRadius <= vecEndPos.z &&
*nIntersecting < maxEntitiesToFind) {
if(aEntities) aEntities[*nIntersecting] = pEntity;
++*nIntersecting;
2020-04-16 20:46:08 +02:00
}
2020-04-17 13:14:59 +02:00
}
2020-04-16 20:46:08 +02:00
}
}
2020-04-17 13:14:59 +02:00
void
2020-05-06 17:56:38 +02:00
CWorld::FindObjectsIntersectingAngledCollisionBox(const CBox &boundingBox, const CMatrix &matrix,
2020-04-17 13:14:59 +02:00
const CVector &position, float fStartX, float fStartY, float fEndX,
float fEndY, int16 *nEntitiesFound, int16 maxEntitiesToFind,
CEntity **aEntities, bool bBuildings, bool bVehicles, bool bPeds,
bool bObjects, bool bDummies)
2020-04-16 20:46:08 +02:00
{
CWorld::AdvanceCurrentScanCode();
*nEntitiesFound = 0;
2020-04-19 18:34:08 +02:00
const int32 nStartX = Max(CWorld::GetSectorIndexX(fStartX), 0);
const int32 nStartY = Max(CWorld::GetSectorIndexY(fStartY), 0);
const int32 nEndX = Min(CWorld::GetSectorIndexX(fEndX), NUMSECTORS_X - 1);
const int32 nEndY = Min(CWorld::GetSectorIndexY(fEndY), NUMSECTORS_Y - 1);
2020-04-17 13:14:59 +02:00
for(int32 y = nStartY; y <= nEndY; y++) {
for(int32 x = nStartX; x <= nEndX; x++) {
CSector *pSector = CWorld::GetSector(x, y);
if(bBuildings) {
CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList(
pSector->m_lists[ENTITYLIST_BUILDINGS], boundingBox, matrix, position,
nEntitiesFound, maxEntitiesToFind, aEntities);
CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList(
pSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], boundingBox, matrix, position,
nEntitiesFound, maxEntitiesToFind, aEntities);
}
if(bVehicles) {
CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList(
pSector->m_lists[ENTITYLIST_VEHICLES], boundingBox, matrix, position,
nEntitiesFound, maxEntitiesToFind, aEntities);
CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList(
pSector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], boundingBox, matrix, position,
nEntitiesFound, maxEntitiesToFind, aEntities);
}
if(bPeds) {
CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList(
pSector->m_lists[ENTITYLIST_PEDS], boundingBox, matrix, position, nEntitiesFound,
maxEntitiesToFind, aEntities);
CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList(
pSector->m_lists[ENTITYLIST_PEDS_OVERLAP], boundingBox, matrix, position,
nEntitiesFound, maxEntitiesToFind, aEntities);
}
if(bObjects) {
CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList(
pSector->m_lists[ENTITYLIST_OBJECTS], boundingBox, matrix, position, nEntitiesFound,
maxEntitiesToFind, aEntities);
CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList(
pSector->m_lists[ENTITYLIST_OBJECTS_OVERLAP], boundingBox, matrix, position,
nEntitiesFound, maxEntitiesToFind, aEntities);
}
if(bDummies) {
CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList(
pSector->m_lists[ENTITYLIST_DUMMIES], boundingBox, matrix, position, nEntitiesFound,
maxEntitiesToFind, aEntities);
CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList(
pSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP], boundingBox, matrix, position,
nEntitiesFound, maxEntitiesToFind, aEntities);
2020-04-16 20:46:08 +02:00
}
}
}
}
2020-04-17 13:14:59 +02:00
void
2020-05-06 17:56:38 +02:00
CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList(CPtrList &list, const CBox &boundingBox,
2020-04-17 13:14:59 +02:00
const CMatrix &matrix, const CVector &position,
int16 *nEntitiesFound, int16 maxEntitiesToFind,
CEntity **aEntities)
2020-04-16 20:46:08 +02:00
{
2020-04-17 13:14:59 +02:00
for(CPtrNode *pNode = list.first; pNode; pNode = pNode->next) {
CEntity *pEntity = (CEntity *)pNode->item;
if(pEntity->m_scanCode != GetCurrentScanCode()) {
2020-04-17 13:13:55 +02:00
pEntity->m_scanCode = GetCurrentScanCode();
2020-04-16 20:46:08 +02:00
CColSphere sphere;
2020-04-17 02:38:05 +02:00
CVector vecDistance = pEntity->GetPosition() - position;
2020-04-16 20:46:08 +02:00
sphere.radius = pEntity->GetBoundRadius();
sphere.center = Multiply3x3(vecDistance, matrix);
2020-04-17 13:14:59 +02:00
if(CCollision::TestSphereBox(sphere, boundingBox) && *nEntitiesFound < maxEntitiesToFind) {
if(aEntities) aEntities[*nEntitiesFound] = pEntity;
2020-04-16 20:46:08 +02:00
++*nEntitiesFound;
}
}
}
}
void
2020-04-17 13:14:59 +02:00
CWorld::FindMissionEntitiesIntersectingCube(const CVector &vecStartPos, const CVector &vecEndPos, int16 *nIntersecting,
int16 maxEntitiesToFind, CEntity **aEntities, bool bVehicles, bool bPeds,
bool bObjects)
2020-04-16 20:46:08 +02:00
{
CWorld::AdvanceCurrentScanCode();
*nIntersecting = 0;
2020-04-19 18:34:08 +02:00
const int32 nStartX = Max(CWorld::GetSectorIndexX(vecStartPos.x), 0);
const int32 nStartY = Max(CWorld::GetSectorIndexY(vecStartPos.y), 0);
const int32 nEndX = Min(CWorld::GetSectorIndexX(vecEndPos.x), NUMSECTORS_X - 1);
const int32 nEndY = Min(CWorld::GetSectorIndexY(vecEndPos.y), NUMSECTORS_Y - 1);
2020-04-17 13:14:59 +02:00
for(int32 y = nStartY; y <= nEndY; y++) {
for(int32 x = nStartX; x <= nEndX; x++) {
CSector *pSector = CWorld::GetSector(x, y);
if(bVehicles) {
CWorld::FindMissionEntitiesIntersectingCubeSectorList(
pSector->m_lists[ENTITYLIST_VEHICLES], vecStartPos, vecEndPos, nIntersecting,
maxEntitiesToFind, aEntities, true, false);
CWorld::FindMissionEntitiesIntersectingCubeSectorList(
pSector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], vecStartPos, vecEndPos,
nIntersecting, maxEntitiesToFind, aEntities, true, false);
2020-04-16 20:46:08 +02:00
}
2020-04-17 13:14:59 +02:00
if(bPeds) {
CWorld::FindMissionEntitiesIntersectingCubeSectorList(
pSector->m_lists[ENTITYLIST_PEDS], vecStartPos, vecEndPos, nIntersecting,
maxEntitiesToFind, aEntities, false, true);
CWorld::FindMissionEntitiesIntersectingCubeSectorList(
pSector->m_lists[ENTITYLIST_PEDS_OVERLAP], vecStartPos, vecEndPos, nIntersecting,
maxEntitiesToFind, aEntities, false, true);
2020-04-16 20:46:08 +02:00
}
2020-04-17 13:14:59 +02:00
if(bObjects) {
CWorld::FindMissionEntitiesIntersectingCubeSectorList(
pSector->m_lists[ENTITYLIST_OBJECTS], vecStartPos, vecEndPos, nIntersecting,
maxEntitiesToFind, aEntities, false, false);
CWorld::FindMissionEntitiesIntersectingCubeSectorList(
pSector->m_lists[ENTITYLIST_OBJECTS_OVERLAP], vecStartPos, vecEndPos, nIntersecting,
maxEntitiesToFind, aEntities, false, false);
2020-04-16 20:46:08 +02:00
}
}
}
}
void
2020-04-17 13:14:59 +02:00
CWorld::FindMissionEntitiesIntersectingCubeSectorList(CPtrList &list, const CVector &vecStartPos,
const CVector &vecEndPos, int16 *nIntersecting,
int16 maxEntitiesToFind, CEntity **aEntities, bool bIsVehicleList,
bool bIsPedList)
2020-04-16 20:46:08 +02:00
{
2020-04-17 13:14:59 +02:00
for(CPtrNode *pNode = list.first; pNode; pNode = pNode->next) {
CEntity *pEntity = (CEntity *)pNode->item;
if(pEntity->m_scanCode != GetCurrentScanCode()) {
2020-04-17 13:13:55 +02:00
pEntity->m_scanCode = GetCurrentScanCode();
2020-04-16 20:46:08 +02:00
bool bIsMissionEntity = false;
2020-04-17 13:14:59 +02:00
if(bIsVehicleList)
bIsMissionEntity = ((CVehicle *)pEntity)->VehicleCreatedBy == MISSION_VEHICLE;
else if(bIsPedList)
bIsMissionEntity = ((CPed *)pEntity)->CharCreatedBy == MISSION_CHAR;
2020-04-16 20:46:08 +02:00
else
2020-04-17 13:14:59 +02:00
bIsMissionEntity = ((CObject *)pEntity)->ObjectCreatedBy == MISSION_OBJECT;
2020-04-16 20:46:08 +02:00
float fRadius = pEntity->GetBoundRadius();
2020-04-17 13:14:59 +02:00
const CVector &entityPos = pEntity->GetPosition();
if(bIsMissionEntity && fRadius + entityPos.x >= vecStartPos.x &&
entityPos.x - fRadius <= vecEndPos.x && fRadius + entityPos.y >= vecStartPos.y &&
entityPos.y - fRadius <= vecEndPos.y && fRadius + entityPos.z >= vecStartPos.z &&
entityPos.z - fRadius <= vecEndPos.z && *nIntersecting < maxEntitiesToFind) {
if(aEntities) aEntities[*nIntersecting] = pEntity;
2020-04-16 20:46:08 +02:00
++*nIntersecting;
}
}
}
}
2020-04-17 13:14:59 +02:00
CPlayerPed *
2019-06-29 11:09:33 +02:00
FindPlayerPed(void)
{
return CWorld::Players[CWorld::PlayerInFocus].m_pPed;
}
2020-04-17 13:14:59 +02:00
CVehicle *
2019-06-29 11:09:33 +02:00
FindPlayerVehicle(void)
{
2019-12-02 21:02:32 +01:00
CPlayerPed *ped = FindPlayerPed();
2020-04-17 13:14:59 +02:00
if(ped && ped->InVehicle()) return ped->m_pMyVehicle;
2020-02-06 18:35:24 +01:00
return nil;
2019-06-29 11:09:33 +02:00
}
2020-04-17 13:14:59 +02:00
CVehicle *
2019-06-29 11:09:33 +02:00
FindPlayerTrain(void)
{
if(FindPlayerVehicle() && FindPlayerVehicle()->IsTrain())
return FindPlayerVehicle();
else
return nil;
}
2020-04-17 13:14:59 +02:00
CEntity *
2019-06-29 11:09:33 +02:00
FindPlayerEntity(void)
{
2019-12-02 21:02:32 +01:00
CPlayerPed *ped = FindPlayerPed();
if(ped->InVehicle())
2019-06-29 11:09:33 +02:00
return ped->m_pMyVehicle;
else
return ped;
}
CVector
FindPlayerCoors(void)
{
2020-04-18 22:50:37 +02:00
#ifdef FIX_BUGS
if (CReplay::IsPlayingBack())
return TheCamera.GetPosition();
#endif
2019-12-02 21:02:32 +01:00
CPlayerPed *ped = FindPlayerPed();
if(ped->InVehicle())
2019-06-29 11:09:33 +02:00
return ped->m_pMyVehicle->GetPosition();
else
return ped->GetPosition();
}
2020-04-17 13:14:59 +02:00
CVector &
2019-06-29 11:09:33 +02:00
FindPlayerSpeed(void)
{
2020-04-18 22:50:37 +02:00
#ifdef FIX_BUGS
static CVector vecTmpVector(0.0f, 0.0f, 0.0f);
if (CReplay::IsPlayingBack())
return vecTmpVector;
#endif
2019-12-02 21:02:32 +01:00
CPlayerPed *ped = FindPlayerPed();
if(ped->InVehicle())
2019-06-29 11:09:33 +02:00
return ped->m_pMyVehicle->m_vecMoveSpeed;
else
return ped->m_vecMoveSpeed;
}
2020-05-05 03:45:18 +02:00
const CVector &
2019-06-29 11:09:33 +02:00
FindPlayerCentreOfWorld(int32 player)
{
2020-04-18 22:50:37 +02:00
#ifdef FIX_BUGS
if(CReplay::IsPlayingBack()) return TheCamera.GetPosition();
#endif
2020-04-17 13:14:59 +02:00
if(CCarCtrl::bCarsGeneratedAroundCamera) return TheCamera.GetPosition();
if(CWorld::Players[player].m_pRemoteVehicle) return CWorld::Players[player].m_pRemoteVehicle->GetPosition();
if(FindPlayerVehicle()) return FindPlayerVehicle()->GetPosition();
2019-06-29 11:09:33 +02:00
return CWorld::Players[player].m_pPed->GetPosition();
}
2020-05-05 03:45:18 +02:00
const CVector &
2019-06-29 11:09:33 +02:00
FindPlayerCentreOfWorld_NoSniperShift(void)
{
2020-04-18 22:50:37 +02:00
#ifdef FIX_BUGS
if (CReplay::IsPlayingBack()) return TheCamera.GetPosition();
#endif
2020-04-17 13:14:59 +02:00
if(CCarCtrl::bCarsGeneratedAroundCamera) return TheCamera.GetPosition();
2019-06-29 11:09:33 +02:00
if(CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle)
return CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle->GetPosition();
2020-04-17 13:14:59 +02:00
if(FindPlayerVehicle()) return FindPlayerVehicle()->GetPosition();
2019-12-02 21:02:32 +01:00
return FindPlayerPed()->GetPosition();
2019-06-29 11:09:33 +02:00
}
float
FindPlayerHeading(void)
{
if(CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle)
return CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle->GetForward().Heading();
2020-04-17 13:14:59 +02:00
if(FindPlayerVehicle()) return FindPlayerVehicle()->GetForward().Heading();
2019-12-02 21:02:32 +01:00
return FindPlayerPed()->GetForward().Heading();
2019-06-29 11:09:33 +02:00
}
2020-04-17 13:14:59 +02:00
void
CWorld::ClearCarsFromArea(float x1, float y1, float z1, float x2, float y2, float z2)
2020-04-16 20:46:08 +02:00
{
CVehiclePool *pVehiclePool = CPools::GetVehiclePool();
2020-04-17 13:14:59 +02:00
for(int32 i = 0; i < pVehiclePool->GetSize(); i++) {
CVehicle *pVehicle = CPools::GetVehiclePool()->GetSlot(i);
if(pVehicle) {
const CVector &position = pVehicle->GetPosition();
if(position.x >= x1 && position.x <= x2 && position.y >= y1 && position.y <= y2 &&
position.z >= z1 && position.z <= z2 && !pVehicle->bIsLocked && pVehicle->CanBeDeleted()) {
if(pVehicle->pDriver) {
2020-04-16 20:46:08 +02:00
CPopulation::RemovePed(pVehicle->pDriver);
pVehicle->pDriver = nil;
}
2020-04-17 13:14:59 +02:00
for(int32 j = 0; j < pVehicle->m_nNumMaxPassengers; ++j) {
if(pVehicle->pPassengers[j]) {
2020-04-16 20:46:08 +02:00
CPopulation::RemovePed(pVehicle->pPassengers[j]);
pVehicle->pPassengers[j] = nil;
--pVehicle->m_nNumPassengers;
}
}
CCarCtrl::RemoveFromInterestingVehicleList(pVehicle);
CWorld::Remove(pVehicle);
delete pVehicle;
}
}
}
}
2020-04-17 13:14:59 +02:00
void
2020-04-16 20:46:08 +02:00
CWorld::ClearPedsFromArea(float x1, float y1, float z1, float x2, float y2, float z2)
{
2020-04-17 13:14:59 +02:00
CPedPool *pPedPool = CPools::GetPedPool();
for(int32 i = 0; i < pPedPool->GetSize(); i++) {
CPed *pPed = CPools::GetPedPool()->GetSlot(i);
if(pPed) {
const CVector &position = pPed->GetPosition();
if(!pPed->IsPlayer() && pPed->CanBeDeleted() && position.x >= x1 && position.x <= x2 &&
position.y >= y1 && position.y <= y2 && position.z >= z1 && position.z <= z2) {
2020-04-16 20:46:08 +02:00
CPopulation::RemovePed(pPed);
}
}
}
}
2020-04-17 13:14:59 +02:00
void
2020-04-16 20:46:08 +02:00
CWorld::CallOffChaseForArea(float x1, float y1, float x2, float y2)
{
CWorld::AdvanceCurrentScanCode();
float fStartX = x1 - 10.0f;
float fStartY = y1 - 10.0f;
float fEndX = x2 + 10.0f;
float fEndY = y2 + 10.0f;
2020-04-19 18:34:08 +02:00
const int32 nStartX = Max(CWorld::GetSectorIndexX(fStartX), 0);
const int32 nStartY = Max(CWorld::GetSectorIndexY(fStartY), 0);
const int32 nEndX = Min(CWorld::GetSectorIndexX(fEndX), NUMSECTORS_X - 1);
const int32 nEndY = Min(CWorld::GetSectorIndexY(fEndY), NUMSECTORS_Y - 1);
2020-04-17 13:14:59 +02:00
for(int32 y = nStartY; y <= nEndY; y++) {
for(int32 x = nStartX; x <= nEndX; x++) {
CSector *pSector = CWorld::GetSector(x, y);
CWorld::CallOffChaseForAreaSectorListVehicles(pSector->m_lists[ENTITYLIST_VEHICLES], x1, y1, x2,
y2, fStartX, fStartY, fEndX, fEndY);
CWorld::CallOffChaseForAreaSectorListVehicles(pSector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], x1,
y1, x2, y2, fStartX, fStartY, fEndX, fEndY);
2020-04-16 20:46:08 +02:00
CWorld::CallOffChaseForAreaSectorListPeds(pSector->m_lists[ENTITYLIST_PEDS], x1, y1, x2, y2);
2020-04-17 13:14:59 +02:00
CWorld::CallOffChaseForAreaSectorListPeds(pSector->m_lists[ENTITYLIST_PEDS_OVERLAP], x1, y1, x2,
y2);
2020-04-16 20:46:08 +02:00
}
}
}
2020-04-17 13:14:59 +02:00
void
CWorld::CallOffChaseForAreaSectorListVehicles(CPtrList &list, float x1, float y1, float x2, float y2, float fStartX,
float fStartY, float fEndX, float fEndY)
2020-04-16 20:46:08 +02:00
{
2020-04-17 13:14:59 +02:00
for(CPtrNode *pNode = list.first; pNode; pNode = pNode->next) {
CVehicle *pVehicle = (CVehicle *)pNode->item;
if(pVehicle->m_scanCode != GetCurrentScanCode()) {
2020-04-17 13:13:55 +02:00
pVehicle->m_scanCode = GetCurrentScanCode();
2020-04-17 13:14:59 +02:00
const CVector &vehiclePos = pVehicle->GetPosition();
2020-04-16 20:46:08 +02:00
eCarMission carMission = pVehicle->AutoPilot.m_nCarMission;
2020-04-17 13:14:59 +02:00
if(pVehicle != FindPlayerVehicle() && vehiclePos.x > fStartX && vehiclePos.x < fEndX &&
vehiclePos.y > fStartY && vehiclePos.y < fEndY && pVehicle->bIsLawEnforcer &&
(carMission == MISSION_RAMPLAYER_FARAWAY || carMission == MISSION_RAMPLAYER_CLOSE ||
carMission == MISSION_BLOCKPLAYER_FARAWAY || carMission == MISSION_BLOCKPLAYER_CLOSE)) {
2020-04-17 13:13:55 +02:00
pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 2000;
2020-04-17 13:14:59 +02:00
CColModel *pColModel = pVehicle->GetColModel();
2020-04-17 13:13:55 +02:00
bool bInsideSphere = false;
2020-04-17 13:14:59 +02:00
for(int32 i = 0; i < pColModel->numSpheres; i++) {
2020-04-17 13:13:55 +02:00
CVector pos = pVehicle->m_matrix * pColModel->spheres[i].center;
float fRadius = pColModel->spheres[i].radius;
2020-04-17 13:14:59 +02:00
if(pos.x + fRadius > x1 && pos.x - fRadius < x2 && pos.y + fRadius > y1 &&
pos.y - fRadius < y2)
2020-04-17 13:13:55 +02:00
bInsideSphere = true;
// Maybe break the loop when bInsideSphere is set to true?
}
2020-04-17 13:14:59 +02:00
if(bInsideSphere) {
if(pVehicle->GetPosition().x <= (x1 + x2) * 0.5f)
2020-04-19 18:34:08 +02:00
pVehicle->m_vecMoveSpeed.x = Min(pVehicle->m_vecMoveSpeed.x, 0.0f);
2020-04-17 13:13:55 +02:00
else
2020-04-19 18:34:08 +02:00
pVehicle->m_vecMoveSpeed.x = Max(pVehicle->m_vecMoveSpeed.x, 0.0f);
2020-04-17 13:14:59 +02:00
if(pVehicle->GetPosition().y <= (y1 + y2) * 0.5f)
2020-04-19 18:34:08 +02:00
pVehicle->m_vecMoveSpeed.y = Min(pVehicle->m_vecMoveSpeed.y, 0.0f);
2020-04-17 13:13:55 +02:00
else
2020-04-19 18:34:08 +02:00
pVehicle->m_vecMoveSpeed.y = Max(pVehicle->m_vecMoveSpeed.y, 0.0f);
2020-04-16 20:46:08 +02:00
}
}
2020-04-17 13:13:55 +02:00
}
2020-04-16 20:46:08 +02:00
}
}
2020-04-17 13:14:59 +02:00
void
CWorld::CallOffChaseForAreaSectorListPeds(CPtrList &list, float x1, float y1, float x2, float y2)
2020-04-16 20:46:08 +02:00
{
2020-04-17 13:14:59 +02:00
for(CPtrNode *pNode = list.first; pNode; pNode = pNode->next) {
CPed *pPed = (CPed *)pNode->item;
const CVector &pedPos = pPed->GetPosition();
if(pPed->m_scanCode != GetCurrentScanCode()) {
2020-04-17 13:13:55 +02:00
pPed->m_scanCode = GetCurrentScanCode();
2020-04-17 13:14:59 +02:00
if(pPed != FindPlayerPed() && pPed->m_leader != FindPlayerPed() && pedPos.x > x1 &&
pedPos.x < x2 && pedPos.y > y1 && pedPos.y < y2 &&
(pPed->m_pedInObjective == FindPlayerPed() ||
pPed->m_carInObjective && pPed->m_carInObjective == FindPlayerVehicle()) &&
pPed->m_nPedState != PED_DEAD && pPed->m_nPedState != PED_DIE &&
(pPed->m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT ||
pPed->m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER ||
pPed->m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS)) {
if(pPed->IsPedInControl()) {
if(pPed->m_nPedType == PEDTYPE_COP)
((CCopPed *)pPed)->ClearPursuit();
2020-04-16 20:46:08 +02:00
else
pPed->SetIdle();
pPed->SetObjective(OBJECTIVE_NONE);
2020-04-17 13:14:59 +02:00
} else {
2020-04-16 20:46:08 +02:00
pPed->m_prevObjective = OBJECTIVE_NONE;
pPed->m_nLastPedState = PED_IDLE;
}
}
}
}
}
2019-09-12 02:43:18 +02:00
void
2020-04-17 13:14:59 +02:00
CWorld::RemoveEntityInsteadOfProcessingIt(CEntity *ent)
2019-09-12 02:43:18 +02:00
{
2020-04-17 13:14:59 +02:00
if(ent->IsPed()) {
if(FindPlayerPed() == ent)
2019-09-12 14:35:05 +02:00
Remove(ent);
2019-09-12 02:43:18 +02:00
else
2020-04-17 13:14:59 +02:00
CPopulation::RemovePed((CPed *)ent);
2019-09-12 02:43:18 +02:00
} else {
2019-09-12 14:35:05 +02:00
Remove(ent);
2019-09-12 02:43:18 +02:00
delete ent;
}
}
void
CWorld::RemoveFallenPeds(void)
{
int poolSize = CPools::GetPedPool()->GetSize();
2020-04-17 13:14:59 +02:00
for(int poolIndex = poolSize - 1; poolIndex >= 0; poolIndex--) {
2019-09-12 02:43:18 +02:00
CPed *ped = CPools::GetPedPool()->GetSlot(poolIndex);
2020-04-17 13:14:59 +02:00
if(ped) {
if(ped->GetPosition().z < MAP_Z_LOW_LIMIT) {
if(ped->CharCreatedBy != RANDOM_CHAR || ped->IsPlayer()) {
int closestNode = ThePaths.FindNodeClosestToCoors(ped->GetPosition(), PATH_PED,
999999.9f, false, false);
CVector newPos = ThePaths.m_pathNodes[closestNode].GetPosition();
2019-09-12 02:43:18 +02:00
newPos.z += 2.0f;
ped->Teleport(newPos);
ped->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
} else {
CPopulation::RemovePed(ped);
}
}
}
}
}
void
CWorld::RemoveFallenCars(void)
{
int poolSize = CPools::GetVehiclePool()->GetSize();
2020-04-17 13:14:59 +02:00
for(int poolIndex = poolSize - 1; poolIndex >= 0; poolIndex--) {
CVehicle *veh = CPools::GetVehiclePool()->GetSlot(poolIndex);
if(veh) {
if(veh->GetPosition().z < MAP_Z_LOW_LIMIT) {
if(veh->VehicleCreatedBy == MISSION_VEHICLE || veh == FindPlayerVehicle() ||
(veh->pDriver && veh->pDriver->IsPlayer())) {
int closestNode = ThePaths.FindNodeClosestToCoors(veh->GetPosition(), PATH_CAR,
999999.9f, false, false);
CVector newPos = ThePaths.m_pathNodes[closestNode].GetPosition();
2019-09-12 02:43:18 +02:00
newPos.z += 3.0f;
veh->Teleport(newPos);
veh->m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
2020-04-17 13:14:59 +02:00
} else if(veh->VehicleCreatedBy == RANDOM_VEHICLE ||
veh->VehicleCreatedBy == PARKED_VEHICLE) {
2019-09-12 14:35:05 +02:00
Remove(veh);
2019-09-12 02:43:18 +02:00
delete veh;
}
}
}
}
}
2019-10-21 23:39:59 +02:00
void
CWorld::StopAllLawEnforcersInTheirTracks(void)
{
int poolSize = CPools::GetVehiclePool()->GetSize();
2020-04-17 13:14:59 +02:00
for(int poolIndex = poolSize - 1; poolIndex >= 0; poolIndex--) {
CVehicle *veh = CPools::GetVehiclePool()->GetSlot(poolIndex);
if(veh) {
if(veh->bIsLawEnforcer) veh->SetMoveSpeed(0.0f, 0.0f, 0.0f);
2019-10-21 23:39:59 +02:00
}
}
}
2019-12-02 21:02:32 +01:00
void
CWorld::SetAllCarsCanBeDamaged(bool toggle)
{
int poolSize = CPools::GetVehiclePool()->GetSize();
2020-04-17 13:14:59 +02:00
for(int poolIndex = 0; poolIndex < poolSize; poolIndex++) {
2019-12-02 21:02:32 +01:00
CVehicle *veh = CPools::GetVehiclePool()->GetSlot(poolIndex);
2020-04-17 13:14:59 +02:00
if(veh) veh->bCanBeDamaged = toggle;
2019-12-02 21:02:32 +01:00
}
}
void
CWorld::ExtinguishAllCarFiresInArea(CVector point, float range)
{
int poolSize = CPools::GetVehiclePool()->GetSize();
2020-04-17 13:14:59 +02:00
for(int poolIndex = 0; poolIndex < poolSize; poolIndex++) {
CVehicle *veh = CPools::GetVehiclePool()->GetSlot(poolIndex);
if(veh) {
if((point - veh->GetPosition()).MagnitudeSqr() < sq(range)) veh->ExtinguishCarFire();
2019-12-02 21:02:32 +01:00
}
}
}
2020-04-17 13:14:59 +02:00
void
CWorld::AddParticles(void)
2020-04-16 20:46:08 +02:00
{
2020-04-17 13:14:59 +02:00
for(int32 y = 0; y < NUMSECTORS_Y; y++) {
for(int32 x = 0; x < NUMSECTORS_X; x++) {
CSector *pSector = GetSector(x, y);
2020-04-17 02:38:05 +02:00
CEntity::AddSteamsFromGround(pSector->m_lists[ENTITYLIST_BUILDINGS]);
CEntity::AddSteamsFromGround(pSector->m_lists[ENTITYLIST_DUMMIES]);
2020-04-16 20:46:08 +02:00
}
}
}
2020-04-17 13:14:59 +02:00
void
2020-04-16 20:46:08 +02:00
CWorld::ShutDown(void)
{
2020-04-17 13:14:59 +02:00
for(int i = 0; i < NUMSECTORS_X * NUMSECTORS_Y; i++) {
2020-04-17 13:13:55 +02:00
CSector *pSector = GetSector(i % NUMSECTORS_X, i / NUMSECTORS_Y);
2020-04-17 13:14:59 +02:00
for(CPtrNode *pNode = pSector->m_lists[ENTITYLIST_BUILDINGS].first; pNode; pNode = pNode->next) {
CEntity *pEntity = (CEntity *)pNode->item;
2020-04-17 13:13:55 +02:00
CWorld::Remove(pEntity);
delete pEntity;
2020-04-16 20:46:08 +02:00
}
2020-04-17 13:14:59 +02:00
for(CPtrNode *pNode = pSector->m_lists[ENTITYLIST_VEHICLES].first; pNode; pNode = pNode->next) {
CEntity *pEntity = (CEntity *)pNode->item;
2020-04-17 13:13:55 +02:00
CWorld::Remove(pEntity);
delete pEntity;
}
2020-04-17 13:14:59 +02:00
for(CPtrNode *pNode = pSector->m_lists[ENTITYLIST_PEDS].first; pNode; pNode = pNode->next) {
CEntity *pEntity = (CEntity *)pNode->item;
2020-04-17 13:13:55 +02:00
CWorld::Remove(pEntity);
delete pEntity;
}
2020-04-17 13:14:59 +02:00
for(CPtrNode *pNode = pSector->m_lists[ENTITYLIST_OBJECTS].first; pNode; pNode = pNode->next) {
CEntity *pEntity = (CEntity *)pNode->item;
2020-04-17 13:13:55 +02:00
CWorld::Remove(pEntity);
delete pEntity;
}
2020-04-17 13:14:59 +02:00
for(CPtrNode *pNode = pSector->m_lists[ENTITYLIST_DUMMIES].first; pNode; pNode = pNode->next) {
CEntity *pEntity = (CEntity *)pNode->item;
2020-04-17 13:13:55 +02:00
CWorld::Remove(pEntity);
delete pEntity;
}
pSector->m_lists[ENTITYLIST_BUILDINGS].Flush();
pSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP].Flush();
pSector->m_lists[ENTITYLIST_DUMMIES].Flush();
pSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP].Flush();
2020-04-16 20:46:08 +02:00
}
2020-04-17 13:14:59 +02:00
for(int32 i = 0; i < 4; i++) {
for(CPtrNode *pNode = GetBigBuildingList((eLevelName)i).first; pNode; pNode = pNode->next) {
CEntity *pEntity = (CEntity *)pNode->item;
2020-04-17 13:13:55 +02:00
// Maybe remove from world here?
delete pEntity;
2020-04-16 20:46:08 +02:00
}
GetBigBuildingList((eLevelName)i).Flush();
}
2020-04-17 13:14:59 +02:00
for(int i = 0; i < NUMSECTORS_X * NUMSECTORS_Y; i++) {
2020-04-17 13:13:55 +02:00
CSector *pSector = GetSector(i % NUMSECTORS_X, i / NUMSECTORS_Y);
2020-04-17 13:14:59 +02:00
if(pSector->m_lists[ENTITYLIST_BUILDINGS].first) {
2020-04-17 13:13:55 +02:00
sprintf(gString, "Building list %d,%d not empty\n", i % NUMSECTORS_X, i / NUMSECTORS_Y);
pSector->m_lists[ENTITYLIST_BUILDINGS].Flush();
}
2020-04-17 13:14:59 +02:00
if(pSector->m_lists[ENTITYLIST_DUMMIES].first) {
2020-04-17 13:13:55 +02:00
sprintf(gString, "Dummy list %d,%d not empty\n", i % NUMSECTORS_X, i / NUMSECTORS_Y);
pSector->m_lists[ENTITYLIST_DUMMIES].Flush();
}
2020-04-17 13:14:59 +02:00
if(pSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP].first) {
2020-04-17 13:13:55 +02:00
sprintf(gString, "Building overlap list %d,%d not empty\n", i % NUMSECTORS_X, i / NUMSECTORS_Y);
pSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP].Flush();
}
2020-04-17 13:14:59 +02:00
if(pSector->m_lists[ENTITYLIST_VEHICLES_OVERLAP].first) {
2020-04-17 13:13:55 +02:00
sprintf(gString, "Vehicle overlap list %d,%d not empty\n", i % NUMSECTORS_X, i / NUMSECTORS_Y);
pSector->m_lists[ENTITYLIST_VEHICLES_OVERLAP].Flush();
}
2020-04-17 13:14:59 +02:00
if(pSector->m_lists[ENTITYLIST_PEDS_OVERLAP].first) {
2020-04-17 13:13:55 +02:00
sprintf(gString, "Ped overlap list %d,%d not empty\n", i % NUMSECTORS_X, i / NUMSECTORS_Y);
pSector->m_lists[ENTITYLIST_PEDS_OVERLAP].Flush();
}
2020-04-17 13:14:59 +02:00
if(pSector->m_lists[ENTITYLIST_OBJECTS_OVERLAP].first) {
2020-04-17 13:13:55 +02:00
sprintf(gString, "Object overlap list %d,%d not empty\n", i % NUMSECTORS_X, i / NUMSECTORS_Y);
pSector->m_lists[ENTITYLIST_OBJECTS_OVERLAP].Flush();
}
2020-04-17 13:14:59 +02:00
if(pSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP].first) {
2020-04-17 13:13:55 +02:00
sprintf(gString, "Dummy overlap list %d,%d not empty\n", i % NUMSECTORS_X, i / NUMSECTORS_Y);
pSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP].Flush();
2020-04-16 20:46:08 +02:00
}
}
ms_listMovingEntityPtrs.Flush();
}
2020-04-17 13:14:59 +02:00
void
CWorld::ClearForRestart(void)
2020-04-16 20:46:08 +02:00
{
2020-04-17 13:14:59 +02:00
if(CCutsceneMgr::HasLoaded()) CCutsceneMgr::DeleteCutsceneData();
2020-04-16 20:46:08 +02:00
CProjectileInfo::RemoveAllProjectiles();
CObject::DeleteAllTempObjects();
CObject::DeleteAllMissionObjects();
CPopulation::ConvertAllObjectsToDummyObjects();
2020-04-17 13:14:59 +02:00
for(int i = 0; i < NUMSECTORS_X * NUMSECTORS_Y; i++) {
CSector *pSector = GetSector(i % NUMSECTORS_X, i / NUMSECTORS_Y);
for(CPtrNode *pNode = pSector->m_lists[ENTITYLIST_PEDS].first; pNode; pNode = pNode->next) {
CEntity *pEntity = (CEntity *)pNode->item;
2020-04-17 13:13:55 +02:00
CWorld::Remove(pEntity);
delete pEntity;
}
2020-07-13 16:43:09 +02:00
for(CPtrNode *pNode = GetBigBuildingList(LEVEL_GENERIC).first; pNode; pNode = pNode->next) {
2020-04-17 13:14:59 +02:00
CVehicle *pVehicle = (CVehicle *)pNode->item;
if(pVehicle && pVehicle->IsVehicle() && pVehicle->IsPlane()) {
2020-04-17 13:13:55 +02:00
CWorld::Remove(pVehicle);
delete pVehicle;
2020-04-16 20:46:08 +02:00
}
}
2020-04-17 13:14:59 +02:00
for(CPtrNode *pNode = pSector->m_lists[ENTITYLIST_VEHICLES].first; pNode; pNode = pNode->next) {
CEntity *pEntity = (CEntity *)pNode->item;
2020-04-17 13:13:55 +02:00
CWorld::Remove(pEntity);
delete pEntity;
}
2020-04-16 20:46:08 +02:00
}
CPools::CheckPoolsEmpty();
}
2020-04-17 13:14:59 +02:00
void
CWorld::RepositionCertainDynamicObjects()
{
2020-04-16 20:46:08 +02:00
int32 i = CPools::GetDummyPool()->GetSize();
2020-04-17 13:14:59 +02:00
while(--i >= 0) {
CDummy *dummy = CPools::GetDummyPool()->GetSlot(i);
if(dummy) { RepositionOneObject(dummy); }
2020-04-16 20:46:08 +02:00
}
}
void
2020-04-17 13:14:59 +02:00
CWorld::RepositionOneObject(CEntity *pEntity)
2020-04-16 20:46:08 +02:00
{
2020-05-05 13:48:35 +02:00
int16 modelId = pEntity->GetModelIndex();
2020-05-19 20:56:42 +02:00
if (modelId == MI_PARKINGMETER || modelId == MI_PHONEBOOTH1 || modelId == MI_WASTEBIN ||
modelId == MI_BIN || modelId == MI_POSTBOX1 || modelId == MI_NEWSSTAND || modelId == MI_TRAFFICCONE ||
modelId == MI_DUMP1 || modelId == MI_ROADWORKBARRIER1 || modelId == MI_BUSSIGN1 || modelId == MI_NOPARKINGSIGN1 ||
modelId == MI_PHONESIGN || modelId == MI_FIRE_HYDRANT || modelId == MI_BOLLARDLIGHT ||
modelId == MI_PARKTABLE || modelId == MI_PARKINGMETER2 || modelId == MI_TELPOLE02 ||
2020-05-20 19:10:05 +02:00
modelId == MI_PARKBENCH || modelId == MI_BARRIER1 || IsTreeModel(modelId) ||
IsLightThatNeedsRepositioning(modelId)
2020-05-19 20:56:42 +02:00
) {
2020-05-05 03:45:18 +02:00
CVector &position = pEntity->GetMatrix().GetPosition();
2020-05-19 20:56:42 +02:00
CColModel *pColModel = pEntity->GetColModel();
float fBoundingBoxMinZ = pColModel->boundingBox.min.z;
float fHeight = pColModel->boundingBox.max.z - pColModel->boundingBox.min.z;
if(fHeight < OBJECT_REPOSITION_OFFSET_Z) fHeight = OBJECT_REPOSITION_OFFSET_Z;
2020-04-17 13:14:59 +02:00
position.z = CWorld::FindGroundZFor3DCoord(position.x, position.y,
2020-05-19 20:56:42 +02:00
position.z + fHeight, nil) -
2020-04-17 13:14:59 +02:00
fBoundingBoxMinZ;
2020-04-16 20:46:08 +02:00
pEntity->m_matrix.UpdateRW();
pEntity->UpdateRwFrame();
2020-04-17 13:14:59 +02:00
} else if(modelId == MI_BUOY) {
2020-04-16 20:46:08 +02:00
float fWaterLevel = 0.0f;
2020-04-17 00:54:22 +02:00
bool bFound = true;
2020-04-17 13:14:59 +02:00
const CVector &position = pEntity->GetPosition();
float fGroundZ = CWorld::FindGroundZFor3DCoord(position.x, position.y,
position.z + OBJECT_REPOSITION_OFFSET_Z, &bFound);
if(CWaterLevel::GetWaterLevelNoWaves(position.x, position.y, position.z + OBJECT_REPOSITION_OFFSET_Z,
&fWaterLevel)) {
if(!bFound || fWaterLevel > fGroundZ) {
CColModel *pColModel = pEntity->GetColModel();
2020-04-16 20:46:08 +02:00
float fHeight = pColModel->boundingBox.max.z - pColModel->boundingBox.min.z;
2020-05-05 03:45:18 +02:00
pEntity->GetMatrix().GetPosition().z = 0.2f * fHeight + fWaterLevel - 0.5f * fHeight;
2020-04-16 20:46:08 +02:00
}
}
}
}
2020-03-29 17:26:23 +02:00
void
CWorld::SetCarsOnFire(float x, float y, float z, float radius, CEntity *reason)
{
int poolSize = CPools::GetVehiclePool()->GetSize();
2020-04-17 13:14:59 +02:00
for(int poolIndex = poolSize - 1; poolIndex >= 0; poolIndex--) {
2020-03-29 17:26:23 +02:00
CVehicle *veh = CPools::GetVehiclePool()->GetSlot(poolIndex);
if(veh && veh->GetStatus() != STATUS_WRECKED && !veh->m_pCarFire && !veh->bFireProof) {
2020-04-17 13:14:59 +02:00
if(Abs(veh->GetPosition().z - z) < 5.0f && Abs(veh->GetPosition().x - x) < radius &&
Abs(veh->GetPosition().y - y) < radius)
gFireManager.StartFire(veh, reason, 0.8f, true);
2020-03-29 17:26:23 +02:00
}
}
}
2020-04-17 13:14:59 +02:00
void
CWorld::SetPedsOnFire(float x, float y, float z, float radius, CEntity *reason)
2020-04-16 20:46:08 +02:00
{
int32 poolSize = CPools::GetPedPool()->GetSize();
2020-04-17 13:14:59 +02:00
for(int32 i = poolSize - 1; i >= 0; i--) {
CPed *pPed = CPools::GetPedPool()->GetSlot(i);
if(pPed && pPed->m_nPedState != PED_DEAD && !pPed->bInVehicle && !pPed->m_pFire && !pPed->bFireProof) {
if(Abs(pPed->GetPosition().z - z) < 5.0f && Abs(pPed->GetPosition().x - x) < radius &&
Abs(pPed->GetPosition().y - y) < radius)
2020-04-16 20:46:08 +02:00
gFireManager.StartFire(pPed, reason, 0.8f, true);
}
}
}
2020-04-17 13:14:59 +02:00
void
CWorld::RemoveStaticObjects()
2020-04-16 20:46:08 +02:00
{
2020-04-17 13:13:55 +02:00
for(int i = 0; i < NUMSECTORS_X * NUMSECTORS_Y; i++) {
CSector *pSector = GetSector(i % NUMSECTORS_X, i / NUMSECTORS_Y);
2020-04-17 13:14:59 +02:00
for(CPtrNode *pNode = pSector->m_lists[ENTITYLIST_BUILDINGS].first; pNode; pNode = pNode->next) {
CEntity *pEntity = (CEntity *)pNode->item;
2020-04-17 13:13:55 +02:00
CWorld::Remove(pEntity);
delete pEntity;
}
2020-04-17 13:14:59 +02:00
for(CPtrNode *pNode = pSector->m_lists[ENTITYLIST_OBJECTS].first; pNode; pNode = pNode->next) {
CEntity *pEntity = (CEntity *)pNode->item;
2020-04-17 13:13:55 +02:00
CWorld::Remove(pEntity);
delete pEntity;
}
2020-04-17 13:14:59 +02:00
for(CPtrNode *pNode = pSector->m_lists[ENTITYLIST_DUMMIES].first; pNode; pNode = pNode->next) {
CEntity *pEntity = (CEntity *)pNode->item;
2020-04-17 13:13:55 +02:00
CWorld::Remove(pEntity);
delete pEntity;
2020-04-16 20:46:08 +02:00
}
2020-04-17 13:13:55 +02:00
pSector->m_lists[ENTITYLIST_BUILDINGS].Flush();
pSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP].Flush();
pSector->m_lists[ENTITYLIST_DUMMIES].Flush();
pSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP].Flush();
2020-04-16 20:46:08 +02:00
}
}
2019-09-12 02:43:18 +02:00
void
CWorld::Process(void)
{
2020-04-17 13:14:59 +02:00
if(!(CTimer::GetFrameCounter() & 63)) CReferences::PruneAllReferencesInWorld();
2019-09-12 02:43:18 +02:00
2020-04-17 13:14:59 +02:00
if(bProcessCutsceneOnly) {
for(int i = 0; i < NUMCUTSCENEOBJECTS; i++) {
2019-09-12 02:43:18 +02:00
CCutsceneObject *csObj = CCutsceneMgr::GetCutsceneObject(i);
2020-04-17 13:14:59 +02:00
if(csObj && csObj->m_entryInfoList.first) {
if(csObj->m_rwObject && RwObjectGetType(csObj->m_rwObject) == rpCLUMP &&
RpAnimBlendClumpGetFirstAssociation(csObj->GetClump())) {
2020-05-10 23:47:53 +02:00
// TODO(MIAMI): doRender argument
2020-04-17 13:14:59 +02:00
RpAnimBlendClumpUpdateAnimations(csObj->GetClump(),
0.02f * (csObj->IsObject()
2020-04-17 13:14:59 +02:00
? CTimer::GetTimeStepNonClipped()
: CTimer::GetTimeStep()));
2019-09-12 02:43:18 +02:00
}
csObj->ProcessControl();
csObj->ProcessCollision();
csObj->GetMatrix().UpdateRW();
csObj->UpdateRwFrame();
}
}
CRecordDataForChase::ProcessControlCars();
CRecordDataForChase::SaveOrRetrieveCarPositions();
} else {
2020-04-17 13:14:59 +02:00
for(CPtrNode *node = ms_listMovingEntityPtrs.first; node; node = node->next) {
CEntity *movingEnt = (CEntity *)node->item;
#ifdef SQUEEZE_PERFORMANCE
if (movingEnt->bRemoveFromWorld) {
RemoveEntityInsteadOfProcessingIt(movingEnt);
} else
#endif
2020-04-17 13:14:59 +02:00
if(movingEnt->m_rwObject && RwObjectGetType(movingEnt->m_rwObject) == rpCLUMP &&
RpAnimBlendClumpGetFirstAssociation(movingEnt->GetClump())) {
2020-05-10 23:47:53 +02:00
// TODO(MIAMI): doRender argument
2020-04-17 13:14:59 +02:00
RpAnimBlendClumpUpdateAnimations(movingEnt->GetClump(),
0.02f * (movingEnt->IsObject()
2020-04-17 13:14:59 +02:00
? CTimer::GetTimeStepNonClipped()
: CTimer::GetTimeStep()));
}
}
for(CPtrNode *node = ms_listMovingEntityPtrs.first; node; node = node->next) {
CPhysical *movingEnt = (CPhysical *)node->item;
if(movingEnt->bRemoveFromWorld) {
2019-09-12 02:43:18 +02:00
RemoveEntityInsteadOfProcessingIt(movingEnt);
} else {
movingEnt->ProcessControl();
2020-05-06 18:17:47 +02:00
if(movingEnt->IsStatic()) { movingEnt->RemoveFromMovingList(); }
2019-09-12 02:43:18 +02:00
}
}
2019-09-12 14:35:05 +02:00
bForceProcessControl = true;
2020-04-17 13:14:59 +02:00
for(CPtrNode *node = ms_listMovingEntityPtrs.first; node; node = node->next) {
CPhysical *movingEnt = (CPhysical *)node->item;
if(movingEnt->bWasPostponed) {
if(movingEnt->bRemoveFromWorld) {
2019-09-12 02:43:18 +02:00
RemoveEntityInsteadOfProcessingIt(movingEnt);
} else {
movingEnt->ProcessControl();
2020-05-06 18:17:47 +02:00
if(movingEnt->IsStatic()) { movingEnt->RemoveFromMovingList(); }
2019-09-12 02:43:18 +02:00
}
}
}
2019-09-12 14:35:05 +02:00
bForceProcessControl = false;
2020-04-17 13:14:59 +02:00
if(CReplay::IsPlayingBack()) {
for(CPtrNode *node = ms_listMovingEntityPtrs.first; node; node = node->next) {
CEntity *movingEnt = (CEntity *)node->item;
2019-09-12 02:43:18 +02:00
movingEnt->bIsInSafePosition = true;
movingEnt->GetMatrix().UpdateRW();
movingEnt->UpdateRwFrame();
}
} else {
2019-09-12 14:35:05 +02:00
bNoMoreCollisionTorque = false;
2020-04-17 13:14:59 +02:00
for(CPtrNode *node = ms_listMovingEntityPtrs.first; node; node = node->next) {
CEntity *movingEnt = (CEntity *)node->item;
if(!movingEnt->bIsInSafePosition) {
2019-09-12 02:43:18 +02:00
movingEnt->ProcessCollision();
movingEnt->GetMatrix().UpdateRW();
movingEnt->UpdateRwFrame();
}
}
2019-09-12 14:35:05 +02:00
bNoMoreCollisionTorque = true;
2020-04-17 13:14:59 +02:00
for(int i = 0; i < 4; i++) {
for(CPtrNode *node = ms_listMovingEntityPtrs.first; node; node = node->next) {
CEntity *movingEnt = (CEntity *)node->item;
if(!movingEnt->bIsInSafePosition) {
2019-09-12 02:43:18 +02:00
movingEnt->ProcessCollision();
movingEnt->GetMatrix().UpdateRW();
movingEnt->UpdateRwFrame();
}
}
}
2020-04-17 13:14:59 +02:00
for(CPtrNode *node = ms_listMovingEntityPtrs.first; node; node = node->next) {
CEntity *movingEnt = (CEntity *)node->item;
if(!movingEnt->bIsInSafePosition) {
2019-09-12 02:43:18 +02:00
movingEnt->bIsStuck = true;
movingEnt->ProcessCollision();
movingEnt->GetMatrix().UpdateRW();
movingEnt->UpdateRwFrame();
2020-04-17 13:14:59 +02:00
if(!movingEnt->bIsInSafePosition) { movingEnt->bIsStuck = true; }
2019-09-12 02:43:18 +02:00
}
}
2019-09-12 14:35:05 +02:00
bSecondShift = false;
2020-04-17 13:14:59 +02:00
for(CPtrNode *node = ms_listMovingEntityPtrs.first; node; node = node->next) {
CEntity *movingEnt = (CEntity *)node->item;
if(!movingEnt->bIsInSafePosition) {
2019-09-12 02:43:18 +02:00
movingEnt->ProcessShift();
movingEnt->GetMatrix().UpdateRW();
movingEnt->UpdateRwFrame();
2020-04-17 13:14:59 +02:00
if(!movingEnt->bIsInSafePosition) { movingEnt->bIsStuck = true; }
2019-09-12 02:43:18 +02:00
}
}
2019-09-12 14:35:05 +02:00
bSecondShift = true;
2020-04-17 13:14:59 +02:00
for(CPtrNode *node = ms_listMovingEntityPtrs.first; node; node = node->next) {
CPhysical *movingEnt = (CPhysical *)node->item;
if(!movingEnt->bIsInSafePosition) {
2019-09-12 02:43:18 +02:00
movingEnt->ProcessShift();
movingEnt->GetMatrix().UpdateRW();
movingEnt->UpdateRwFrame();
2020-04-17 13:14:59 +02:00
if(!movingEnt->bIsInSafePosition) {
2019-09-12 02:43:18 +02:00
movingEnt->bIsStuck = true;
if(movingEnt->GetStatus() == STATUS_PLAYER) {
2020-05-05 13:48:35 +02:00
printf("STUCK: Final Step: Player Entity %d Is Stuck\n", movingEnt->GetModelIndex());
2019-09-12 18:13:32 +02:00
movingEnt->m_vecMoveSpeed *= 0.3f;
2019-09-12 02:43:18 +02:00
movingEnt->ApplyMoveSpeed();
movingEnt->ApplyTurnSpeed();
}
}
}
}
}
2020-04-17 13:14:59 +02:00
for(CPtrNode *node = ms_listMovingEntityPtrs.first; node; node = node->next) {
CPed *movingPed = (CPed *)node->item;
if(movingPed->IsPed()) {
if(movingPed->bInVehicle && movingPed->m_nPedState != PED_EXIT_TRAIN ||
movingPed->EnteringCar()) {
2019-09-12 02:43:18 +02:00
CVehicle *movingCar = movingPed->m_pMyVehicle;
2020-04-17 13:14:59 +02:00
if(movingCar) {
2020-05-15 16:30:25 +02:00
#ifdef GTA_TRAIN
2020-04-17 13:14:59 +02:00
if(movingCar->IsTrain()) {
2019-09-12 02:43:18 +02:00
movingPed->SetPedPositionInTrain();
2020-05-15 16:30:25 +02:00
} else
#endif
{
2020-04-17 13:14:59 +02:00
switch(movingPed->m_nPedState) {
case PED_ENTER_CAR:
case PED_CARJACK: movingPed->EnterCar(); break;
case PED_DRAG_FROM_CAR: movingPed->BeingDraggedFromCar(); break;
case PED_EXIT_CAR: movingPed->ExitCar(); break;
case PED_ARRESTED:
if(movingPed->m_nLastPedState == PED_DRAG_FROM_CAR) {
2019-09-12 02:43:18 +02:00
movingPed->BeingDraggedFromCar();
break;
2020-04-17 13:14:59 +02:00
}
// fall through
default: movingPed->SetPedPositionInCar(); break;
2019-09-12 02:43:18 +02:00
}
}
movingPed->GetMatrix().UpdateRW();
movingPed->UpdateRwFrame();
} else {
movingPed->bInVehicle = false;
movingPed->QuitEnteringCar();
}
} else if (movingPed->m_attachedTo) {
movingPed->PositionAttachedPed();
movingPed->GetMatrix().UpdateRW();
movingPed->UpdateRwFrame();
2019-09-12 02:43:18 +02:00
}
}
}
CMessages::Process();
Players[PlayerInFocus].Process();
CRecordDataForChase::SaveOrRetrieveCarPositions();
2020-04-17 13:14:59 +02:00
if((CTimer::GetFrameCounter() & 7) == 1) {
2019-09-12 14:35:05 +02:00
RemoveFallenPeds();
2020-04-17 13:14:59 +02:00
} else if((CTimer::GetFrameCounter() & 7) == 5) {
2019-09-12 14:35:05 +02:00
RemoveFallenCars();
2019-09-12 02:43:18 +02:00
}
}
}
2020-04-17 13:14:59 +02:00
void
CWorld::TriggerExplosion(const CVector &position, float fRadius, float fPower, CEntity *pCreator,
bool bProcessVehicleBombTimer)
2020-04-16 20:46:08 +02:00
{
CVector2D vecStartPos(position.x - fRadius, position.y - fRadius);
CVector2D vecEndPos(position.x + fRadius, position.y + fRadius);
2020-04-19 18:34:08 +02:00
const int32 nStartX = Max(CWorld::GetSectorIndexX(vecStartPos.x), 0);
const int32 nStartY = Max(CWorld::GetSectorIndexY(vecStartPos.y), 0);
const int32 nEndX = Min(CWorld::GetSectorIndexX(vecEndPos.x), NUMSECTORS_X - 1);
const int32 nEndY = Min(CWorld::GetSectorIndexY(vecEndPos.y), NUMSECTORS_Y - 1);
2020-04-17 13:14:59 +02:00
for(int32 y = nStartY; y <= nEndY; y++) {
for(int32 x = nStartX; x <= nEndX; x++) {
CSector *pSector = CWorld::GetSector(x, y);
CWorld::TriggerExplosionSectorList(pSector->m_lists[ENTITYLIST_VEHICLES], position, fRadius,
fPower, pCreator, bProcessVehicleBombTimer);
CWorld::TriggerExplosionSectorList(pSector->m_lists[ENTITYLIST_PEDS], position, fRadius, fPower,
pCreator, bProcessVehicleBombTimer);
CWorld::TriggerExplosionSectorList(pSector->m_lists[ENTITYLIST_OBJECTS], position, fRadius,
fPower, pCreator, bProcessVehicleBombTimer);
2020-04-16 20:46:08 +02:00
}
}
}
2020-04-17 00:20:34 +02:00
void
2020-04-17 13:14:59 +02:00
CWorld::TriggerExplosionSectorList(CPtrList &list, const CVector &position, float fRadius, float fPower,
CEntity *pCreator, bool bProcessVehicleBombTimer)
{
for(CPtrNode *pNode = list.first; pNode; pNode = pNode->next) {
CPhysical *pEntity = (CPhysical *)pNode->item;
CVector vecDistance = pEntity->GetPosition() - position;
float fMagnitude = vecDistance.Magnitude();
if(fRadius > fMagnitude) {
CWeapon::BlowUpExplosiveThings(pEntity);
CPed *pPed = (CPed *)pEntity;
CObject *pObject = (CObject *)pEntity;
CVehicle *pVehicle = (CVehicle *)pEntity;
if(!pEntity->bExplosionProof && (!pEntity->IsPed() || !pPed->bInVehicle)) {
2020-05-06 18:17:47 +02:00
if(pEntity->IsStatic()) {
2020-04-17 13:14:59 +02:00
if(pEntity->IsObject()) {
2020-05-05 13:48:35 +02:00
if (fPower > pObject->m_fUprootLimit || IsFence(pObject->GetModelIndex())) {
if (IsGlass(pObject->GetModelIndex())) {
2020-04-17 00:20:34 +02:00
CGlass::WindowRespondsToExplosion(pObject, position);
} else {
pObject->bIsStatic = false;
pObject->AddToMovingList();
2020-05-05 13:48:35 +02:00
int16 modelId = pEntity->GetModelIndex();
2020-04-17 13:14:59 +02:00
if(modelId != MI_FIRE_HYDRANT ||
pObject->bHasBeenDamaged) {
if(pEntity->IsObject() &&
modelId != MI_EXPLODINGBARREL &&
modelId != MI_PETROLPUMP)
2020-04-17 00:20:34 +02:00
pObject->bHasBeenDamaged = true;
} else {
2020-04-17 02:38:05 +02:00
CVector pos = pEntity->GetPosition();
2020-04-17 00:20:34 +02:00
pos.z -= 0.5f;
2020-04-17 13:14:59 +02:00
CParticleObject::AddObject(POBJECT_FIRE_HYDRANT,
pos, true);
2020-04-17 00:20:34 +02:00
pObject->bHasBeenDamaged = true;
}
}
}
2020-05-06 18:17:47 +02:00
if(pEntity->IsStatic()) {
2020-04-17 13:14:59 +02:00
float fDamageMultiplier =
(fRadius - fMagnitude) * 2.0f / fRadius;
2020-04-19 18:34:08 +02:00
float fDamage = 300.0f * Min(fDamageMultiplier, 1.0f);
2020-04-17 00:20:34 +02:00
pObject->ObjectDamage(fDamage);
}
} else {
pEntity->bIsStatic = false;
pEntity->AddToMovingList();
}
}
2020-05-06 18:17:47 +02:00
if(!pEntity->IsStatic()) {
2020-04-19 18:34:08 +02:00
float fDamageMultiplier = Min((fRadius - fMagnitude) * 2.0f / fRadius, 1.0f);
2020-04-17 13:14:59 +02:00
CVector vecForceDir =
vecDistance * (fPower * pEntity->m_fMass * 0.00071429f * fDamageMultiplier /
2020-04-19 18:34:08 +02:00
Max(fMagnitude, 0.01f));
vecForceDir.z = Max(vecForceDir.z, 0.0f);
if(pEntity == FindPlayerPed()) vecForceDir.z = Min(vecForceDir.z, 1.0f);
2020-04-17 00:20:34 +02:00
pEntity->ApplyMoveForce(vecForceDir);
2020-04-17 13:14:59 +02:00
if(!pEntity->bPedPhysics) {
2020-04-17 00:20:34 +02:00
float fBoundRadius = pEntity->GetBoundRadius();
2020-04-17 02:38:05 +02:00
float fDistanceZ = position.z - pEntity->GetPosition().z;
2020-04-17 00:20:34 +02:00
float fPointZ = fBoundRadius;
2020-04-19 18:34:08 +02:00
if(Max(fDistanceZ, -fBoundRadius) < fBoundRadius) {
2020-04-17 13:14:59 +02:00
if(fDistanceZ <= -fBoundRadius)
2020-04-17 00:20:34 +02:00
fPointZ = -fBoundRadius;
else
fPointZ = fDistanceZ;
}
2020-04-17 13:14:59 +02:00
pEntity->ApplyTurnForce(vecForceDir.x, vecForceDir.y, vecForceDir.z,
0.0f, 0.0f, fPointZ);
2020-04-17 00:20:34 +02:00
}
switch(pEntity->GetType()) {
2020-04-17 00:20:34 +02:00
case ENTITY_TYPE_VEHICLE:
if(pEntity->GetStatus() == STATUS_SIMPLE) {
pEntity->SetStatus(STATUS_PHYSICS);
2020-04-17 00:20:34 +02:00
CCarCtrl::SwitchVehicleToRealPhysics(pVehicle);
}
2020-04-17 13:14:59 +02:00
pVehicle->InflictDamage(pCreator, WEAPONTYPE_EXPLOSION,
1100.0f * fDamageMultiplier);
if(bProcessVehicleBombTimer) {
if(pVehicle->m_nBombTimer) pVehicle->m_nBombTimer /= 10;
2020-04-17 00:20:34 +02:00
}
break;
case ENTITY_TYPE_PED: {
int8 direction = pPed->GetLocalDirection(-vecForceDir);
pPed->bIsStanding = false;
pPed->ApplyMoveForce(0.0, 0.0, 2.0f);
float fDamage = 250.0f * fDamageMultiplier;
2020-04-17 13:14:59 +02:00
pPed->InflictDamage(pCreator, WEAPONTYPE_EXPLOSION, fDamage,
PEDPIECE_TORSO, direction);
if(pPed->m_nPedState != PED_DIE)
pPed->SetFall(2000,
(AnimationId)(direction + ANIM_KO_SKID_FRONT), 0);
if(pCreator && pCreator->IsPed()) {
2020-04-17 00:20:34 +02:00
eEventType eventType = EVENT_SHOOT_PED;
2020-04-17 13:14:59 +02:00
if(pPed->m_nPedType == PEDTYPE_COP) eventType = EVENT_SHOOT_COP;
CEventList::RegisterEvent(eventType, EVENT_ENTITY_PED, pEntity,
(CPed *)pCreator, 10000);
2020-04-17 00:20:34 +02:00
pPed->RegisterThreatWithGangPeds(pCreator);
}
break;
}
case ENTITY_TYPE_OBJECT:
pObject->ObjectDamage(300.0f * fDamageMultiplier);
break;
2020-05-12 01:24:57 +02:00
default: break;
2020-04-17 00:20:34 +02:00
}
}
}
}
}
}
2020-04-17 13:14:59 +02:00
void
CWorld::UseDetonator(CEntity *pEntity)
2020-04-17 00:20:34 +02:00
{
int32 i = CPools::GetVehiclePool()->GetSize();
2020-04-17 13:14:59 +02:00
while(--i >= 0) {
CAutomobile *pVehicle = (CAutomobile *)CPools::GetVehiclePool()->GetSlot(i);
if(pVehicle && !pVehicle->m_vehType && pVehicle->m_bombType == CARBOMB_REMOTE &&
pVehicle->m_pBombRigger == pEntity) {
2020-04-17 00:20:34 +02:00
pVehicle->m_bombType = CARBOMB_NONE;
pVehicle->m_nBombTimer = 500;
pVehicle->m_pBlowUpEntity = pVehicle->m_pBombRigger;
2020-04-17 13:14:59 +02:00
if(pVehicle->m_pBlowUpEntity)
2020-04-17 00:20:34 +02:00
pVehicle->m_pBlowUpEntity->RegisterReference(&pVehicle->m_pBlowUpEntity);
}
}
2020-05-15 16:30:25 +02:00
CProjectileInfo::RemoveDetonatorProjectiles();
2020-04-17 00:20:34 +02:00
}
2020-05-16 00:49:30 +02:00
bool
CWorld::IsWanderPathClear(CVector const& point1, CVector const& point2, float distance, int maxSteps)
{
if (Abs(point1.z - point2.z) > distance)
return false;
if (!GetIsLineOfSightClear(point1, point2, true, false, false, false, false, false, false))
return false;
CVector vecBetween = point2 - point1;
uint32 nSteps = Max(vecBetween.Magnitude(), maxSteps);
if (nSteps == 0)
return true;
vecBetween.Normalise();
uint32 step = 1;
for (step = 1; step < nSteps; step++) {
CVector posThisStep = point1 + vecBetween * step;
float level;
if (!CWaterLevel::GetWaterLevel(posThisStep, &level, false))
continue;
posThisStep.z = level;
AdvanceCurrentScanCode();
CVector vecCheckedPos(posThisStep.x, posThisStep.y, Max(point1.z, point2.z));
CColPoint colpoint;
CEntity* entity;
if (!ProcessVerticalLineSector(*GetSector(GetSectorIndexX(posThisStep.x), GetSectorIndexY(posThisStep.y)),
CColLine(posThisStep, vecCheckedPos), colpoint, entity, true, false, false, false, false, false, nil))
return false;
}
CVector posThisStep = point1;
AdvanceCurrentScanCode();
CVector vecCheckedPos(posThisStep.x, posThisStep.y, point1.z - 5.0f);
CColPoint colpoint;
CEntity* entity;
if (!ProcessVerticalLineSector(*GetSector(GetSectorIndexX(posThisStep.x), GetSectorIndexY(posThisStep.y)),
CColLine(posThisStep, vecCheckedPos), colpoint, entity, true, false, false, false, false, false, nil))
return false;
float heightNextStep = colpoint.point.z + 0.5f;
for (step = 1; step < nSteps; step++) {
CVector posThisStep = point1 + vecBetween * step;
posThisStep.z = heightNextStep;
AdvanceCurrentScanCode();
CVector vecCheckedPos(posThisStep.x, posThisStep.y, heightNextStep - 2.0f);
if (!ProcessVerticalLineSector(*GetSector(GetSectorIndexX(posThisStep.x), GetSectorIndexY(posThisStep.y)),
CColLine(posThisStep, vecCheckedPos), colpoint, entity, true, false, false, false, false, false, nil))
return false;
if (Abs(colpoint.point.z - heightNextStep) > 1.0f)
return false;
heightNextStep = colpoint.point.z + 0.5f;
}
return true;
}