summaryrefslogtreecommitdiffstats
path: root/src/core/World.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/World.cpp')
-rw-r--r--src/core/World.cpp163
1 files changed, 149 insertions, 14 deletions
diff --git a/src/core/World.cpp b/src/core/World.cpp
index a31f87a7..829a64d4 100644
--- a/src/core/World.cpp
+++ b/src/core/World.cpp
@@ -11,11 +11,13 @@
#include "Garages.h"
#include "TempColModels.h"
#include "World.h"
+#include "ModelIndices.h"
CPtrList *CWorld::ms_bigBuildingsList = (CPtrList*)0x6FAB60;
CPtrList &CWorld::ms_listMovingEntityPtrs = *(CPtrList*)0x8F433C;
CSector (*CWorld::ms_aSectors)[NUMSECTORS_X] = (CSector (*)[NUMSECTORS_Y])0x665608;
uint16 &CWorld::ms_nCurrentScanCode = *(uint16*)0x95CC64;
+CColPoint &CWorld::ms_testSpherePoint = *(CColPoint*)0x6E64C0;
uint8 &CWorld::PlayerInFocus = *(uint8 *)0x95CD61;
CPlayerInfo *CWorld::Players = (CPlayerInfo *)0x9412F0;
@@ -26,6 +28,8 @@ bool &CWorld::bSecondShift = *(bool*)0x95CD54;
bool &CWorld::bForceProcessControl = *(bool*)0x95CD6C;
bool &CWorld::bProcessCutsceneOnly = *(bool*)0x95CD8B;
+WRAPPER void CWorld::RemoveReferencesToDeletedObject(CEntity*) { EAXJMP(0x4B3BF0); }
+
void
CWorld::Add(CEntity *ent)
{
@@ -603,12 +607,12 @@ CWorld::FindObjectsInRange(CVector &centre, float distance, bool ignoreZ, short
minY = 0;
int maxX = GetSectorIndexX(centre.x + distance);
- if (maxX >= 100)
- maxX = 100;
+ if (maxX >= NUMSECTORS_X)
+ maxX = NUMSECTORS_X;
int maxY = GetSectorIndexY(centre.y + distance);
- if (maxY >= 100)
- maxY = 100;
+ if (maxY >= NUMSECTORS_Y)
+ maxY = NUMSECTORS_Y;
AdvanceCurrentScanCode();
@@ -617,27 +621,156 @@ CWorld::FindObjectsInRange(CVector &centre, float distance, bool ignoreZ, short
for(int curX = minX; curX <= maxX; curX++) {
CSector *sector = GetSector(curX, curY);
if (checkBuildings) {
- CWorld::FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_BUILDINGS], centre, distance, ignoreZ, nextObject, lastObject, objects);
- CWorld::FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], centre, distance, ignoreZ, nextObject, lastObject, objects);
+ FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_BUILDINGS], centre, distance, ignoreZ, nextObject, lastObject, objects);
+ FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], centre, distance, ignoreZ, nextObject, lastObject, objects);
+ }
+ if (checkVehicles) {
+ FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_VEHICLES], centre, distance, ignoreZ, nextObject, lastObject, objects);
+ FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], centre, distance, ignoreZ, nextObject, lastObject, objects);
+ }
+ if (checkPeds) {
+ FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_PEDS], centre, distance, ignoreZ, nextObject, lastObject, objects);
+ FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_PEDS_OVERLAP], centre, distance, ignoreZ, nextObject, lastObject, objects);
+ }
+ if (checkObjects) {
+ FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_OBJECTS], centre, distance, ignoreZ, nextObject, lastObject, objects);
+ FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_OBJECTS_OVERLAP], centre, distance, ignoreZ, nextObject, lastObject, objects);
+ }
+ if (checkDummies) {
+ FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_DUMMIES], centre, distance, ignoreZ, nextObject, lastObject, objects);
+ FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_DUMMIES_OVERLAP], centre, distance, ignoreZ, nextObject, lastObject, objects);
+ }
+ }
+ }
+}
+
+CEntity*
+CWorld::TestSphereAgainstWorld(CVector centre, float distance, CEntity* entityToIgnore, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSomeObjects)
+{
+ CEntity* foundE = nil;
+
+ int minX = GetSectorIndexX(centre.x - distance);
+ if (minX <= 0)
+ minX = 0;
+
+ int minY = GetSectorIndexY(centre.y - distance);
+ if (minY <= 0)
+ minY = 0;
+
+ int maxX = GetSectorIndexX(centre.x + distance);
+ if (maxX >= NUMSECTORS_X)
+ maxX = NUMSECTORS_X;
+
+ int maxY = GetSectorIndexY(centre.y + distance);
+ if (maxY >= NUMSECTORS_Y)
+ maxY = NUMSECTORS_Y;
+
+ AdvanceCurrentScanCode();
+
+ 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, distance, entityToIgnore, false);
+ if (foundE)
+ return foundE;
+
+ foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], centre, distance, entityToIgnore, false);
+ if (foundE)
+ return foundE;
}
if (checkVehicles) {
- CWorld::FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_VEHICLES], centre, distance, ignoreZ, nextObject, lastObject, objects);
- CWorld::FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], centre, distance, ignoreZ, nextObject, lastObject, objects);
+ foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_VEHICLES], centre, distance, entityToIgnore, false);
+ if (foundE)
+ return foundE;
+
+ foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], centre, distance, entityToIgnore, false);
+ if (foundE)
+ return foundE;
}
if (checkPeds) {
- CWorld::FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_PEDS], centre, distance, ignoreZ, nextObject, lastObject, objects);
- CWorld::FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_PEDS_OVERLAP], centre, distance, ignoreZ, nextObject, lastObject, objects);
+ foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_PEDS], centre, distance, entityToIgnore, false);
+ if (foundE)
+ return foundE;
+
+ foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_PEDS_OVERLAP], centre, distance, entityToIgnore, false);
+ if (foundE)
+ return foundE;
}
if (checkObjects) {
- CWorld::FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_OBJECTS], centre, distance, ignoreZ, nextObject, lastObject, objects);
- CWorld::FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_OBJECTS_OVERLAP], centre, distance, ignoreZ, nextObject, lastObject, objects);
+ foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_OBJECTS], centre, distance, entityToIgnore, ignoreSomeObjects);
+ if (foundE)
+ return foundE;
+
+ foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_OBJECTS_OVERLAP], centre, distance, entityToIgnore, ignoreSomeObjects);
+ if (foundE)
+ return foundE;
}
if (checkDummies) {
- CWorld::FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_DUMMIES], centre, distance, ignoreZ, nextObject, lastObject, objects);
- CWorld::FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_DUMMIES_OVERLAP], centre, distance, ignoreZ, nextObject, lastObject, objects);
+ foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_DUMMIES], centre, distance, entityToIgnore, false);
+ if (foundE)
+ return foundE;
+
+ foundE = TestSphereAgainstSectorList(sector->m_lists[ENTITYLIST_DUMMIES_OVERLAP], centre, distance, entityToIgnore, false);
+ if (foundE)
+ return foundE;
}
}
}
+ return foundE;
+}
+
+CEntity*
+CWorld::TestSphereAgainstSectorList(CPtrList &list, CVector spherePos, float radius, CEntity *entityToIgnore, bool ignoreSomeObjects)
+{
+ static CColModel sphereCol;
+
+ 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;
+ sphereCol.spheres = &sphereCol.boundingSphere;
+ sphereCol.numLines = 0;
+ sphereCol.numBoxes = 0;
+ sphereCol.numTriangles = 0;
+ sphereCol.ownsCollisionVolumes = false;
+
+ CMatrix sphereMat;
+ sphereMat.SetTranslate(spherePos);
+
+ for(CPtrNode *node=list.first; node; node = node->next) {
+ CEntity *e = (CEntity*)node->item;
+
+ if (e->m_scanCode != GetCurrentScanCode()) {
+ e->m_scanCode = GetCurrentScanCode();
+
+ if (e != entityToIgnore && e->bUsesCollision && !(ignoreSomeObjects && CameraToIgnoreThisObject(e))) {
+ CVector diff = spherePos - e->GetPosition();
+ float distance = diff.Magnitude();
+
+ if (e->GetBoundRadius() + radius > distance) {
+ CColModel *eCol = CModelInfo::GetModelInfo(e->m_modelIndex)->GetColModel();
+ int collidedSpheres = CCollision::ProcessColModels(sphereMat, sphereCol, e->GetMatrix(),
+ *eCol, &ms_testSpherePoint, nil, nil);
+
+ if (collidedSpheres != 0 ||
+ (e->IsVehicle() && ((CVehicle*)e)->m_vehType == VEHICLE_TYPE_CAR &&
+ e->m_modelIndex != MI_DODO && radius + eCol->boundingBox.max.x > distance)) {
+ return e;
+ }
+ }
+ }
+ }
+ }
+
+ return nil;
}
float
@@ -790,6 +923,8 @@ STARTPATCHES
InjectHook(0x4B2200, CWorld::FindObjectsInRange, PATCH_JUMP);
InjectHook(0x4B2540, CWorld::FindObjectsInRangeSectorList, PATCH_JUMP);
+ InjectHook(0x4B4AC0, CWorld::TestSphereAgainstSectorList, PATCH_JUMP);
+ InjectHook(0x4B4710, CWorld::TestSphereAgainstWorld, PATCH_JUMP);
InjectHook(0x4B3A80, CWorld::FindGroundZForCoord, PATCH_JUMP);
InjectHook(0x4B3AE0, CWorld::FindGroundZFor3DCoord, PATCH_JUMP);
InjectHook(0x4B3B50, CWorld::FindRoofZFor3DCoord, PATCH_JUMP);