diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/animation/CutsceneMgr.h | 1 | ||||
-rw-r--r-- | src/control/Replay.cpp | 2 | ||||
-rw-r--r-- | src/core/World.cpp | 982 | ||||
-rw-r--r-- | src/core/World.h | 36 | ||||
-rw-r--r-- | src/entities/Entity.cpp | 12 | ||||
-rw-r--r-- | src/entities/Entity.h | 3 | ||||
-rw-r--r-- | src/modelinfo/ModelIndices.h | 7 | ||||
-rw-r--r-- | src/objects/Object.cpp | 4 | ||||
-rw-r--r-- | src/objects/Object.h | 2 |
9 files changed, 1010 insertions, 39 deletions
diff --git a/src/animation/CutsceneMgr.h b/src/animation/CutsceneMgr.h index b025816b..bfdcdb57 100644 --- a/src/animation/CutsceneMgr.h +++ b/src/animation/CutsceneMgr.h @@ -28,6 +28,7 @@ public: static void StartCutsceneProcessing() { ms_cutsceneProcessing = true; } static bool IsRunning(void) { return ms_running; } + static bool HasLoaded(void) { return ms_loaded; } static bool IsCutsceneProcessing(void) { return ms_cutsceneProcessing; } static bool UseLodMultiplier(void) { return ms_useLodMultiplier; } static CCutsceneObject* GetCutsceneObject(int id) { return ms_pCutsceneObjects[id]; } diff --git a/src/control/Replay.cpp b/src/control/Replay.cpp index 9e0bed66..c4a1e686 100644 --- a/src/control/Replay.cpp +++ b/src/control/Replay.cpp @@ -1087,7 +1087,7 @@ void CReplay::TriggerPlayback(uint8 cam_mode, float cam_x, float cam_y, float ca Playback.m_bSlot = first; Playback.m_nOffset = 0; Playback.m_pBase = Buffers[first]; - CObject::DeleteAllTempObjectInArea(CVector(0.0f, 0.0f, 0.0f), 1000000.0f); + CObject::DeleteAllTempObjectsInArea(CVector(0.0f, 0.0f, 0.0f), 1000000.0f); StoreStuffInMem(); EmptyPedsAndVehiclePools(); SlowMotion = 1; diff --git a/src/core/World.cpp b/src/core/World.cpp index 313b958a..02c0e2f6 100644 --- a/src/core/World.cpp +++ b/src/core/World.cpp @@ -20,6 +20,17 @@ #include "Replay.h" #include "Population.h" #include "Fire.h" +#include "ProjectileInfo.h" +#include "WaterLevel.h" +#include "CopPed.h" +#include "Object.h" +#include "Shadows.h" +#include "Explosion.h" +#include "Glass.h" +#include "ParticleObject.h" +#include "EventList.h" + +#define OBJECT_REPOSITION_OFFSET_Z 2.0f CColPoint gaTempSphereColPoints[MAX_COLLISION_POINTS]; @@ -40,26 +51,6 @@ bool &CWorld::bProcessCutsceneOnly = *(bool*)0x95CD8B; bool &CWorld::bDoingCarCollisions = *(bool*)0x95CD8C; bool &CWorld::bIncludeCarTyres = *(bool*)0x95CDAA; -WRAPPER void CWorld::ClearForRestart(void) { EAXJMP(0x4AE850); } -WRAPPER void CWorld::AddParticles(void) { EAXJMP(0x4B4010); } -WRAPPER void CWorld::ShutDown(void) { EAXJMP(0x4AE450); } -WRAPPER void CWorld::RepositionCertainDynamicObjects() { EAXJMP(0x4B42B0); } -WRAPPER void CWorld::RemoveStaticObjects() { EAXJMP(0x4B4D50); } -WRAPPER void CWorld::RemoveReferencesToDeletedObject(CEntity*) { EAXJMP(0x4B3BF0); } -WRAPPER void CWorld::FindObjectsKindaColliding(const CVector &, float, bool, int16*, int16, CEntity **, bool, bool, bool, bool, bool){ EAXJMP(0x4B2A30); } -WRAPPER void CWorld::ClearExcitingStuffFromArea(const CVector &pos, float radius, uint8) { EAXJMP(0x4B4E70) }; -WRAPPER void CWorld::FindObjectsIntersectingCube(const CVector &, const CVector &, int16*, int16, CEntity **, bool, bool, bool, bool, bool) { EAXJMP(0x4B2E70); } -WRAPPER void CWorld::FindObjectsIntersectingAngledCollisionBox(const CColBox &, const CMatrix &, const CVector &, float, float, float, float, int16*, int16, CEntity **, bool, bool, bool, bool, bool) { EAXJMP(0x4B3280); } -WRAPPER void CWorld::FindObjectsOfTypeInRange(uint32, CVector&, float, bool, short*, short, CEntity**, bool, bool, bool, bool, bool) { EAXJMP(0x4B2600); } -WRAPPER void CWorld::FindObjectsOfTypeInRangeSectorList(uint32, CPtrList&, CVector&, float, bool, short*, short, CEntity**) { EAXJMP(0x4B2960); } -WRAPPER void CWorld::FindMissionEntitiesIntersectingCube(const CVector&, const CVector&, int16*, int16, CEntity**, bool, bool, bool) { EAXJMP(0x4B3680); } -WRAPPER void CWorld::ClearCarsFromArea(float, float, float, float, float, float) { EAXJMP(0x4B50E0); } -WRAPPER void CWorld::ClearPedsFromArea(float, float, float, float, float, float) { EAXJMP(0x4B52B0); } -WRAPPER void CWorld::CallOffChaseForArea(float, float, float, float) { EAXJMP(0x4B5530); } -WRAPPER void CWorld::TriggerExplosion(const CVector& a1, float a2, float a3, CEntity *a4, bool a5) { EAXJMP(0x4B1140); } -WRAPPER void CWorld::SetPedsOnFire(float, float, float, float, CEntity*) { EAXJMP(0x4B3D30); } -WRAPPER void CWorld::UseDetonator(CEntity *) { EAXJMP(0x4B4650); } - void CWorld::Initialise() { @@ -129,6 +120,48 @@ CWorld::ClearScanCodes(void) } } +void +CWorld::ClearExcitingStuffFromArea(const CVector& pos, float radius, bool bRemoveProjectilesAndTidyUpShadows) +{ + CPedPool* pedPool = CPools::GetPedPool(); + for (int32 i = 0; i < pedPool->GetSize(); i++) { + CPed* pPed = pedPool->GetSlot(i); + if (pPed && !pPed->IsPlayer() && pPed->CanBeDeleted() && + CVector2D(pPed->GetPosition() - pos).MagnitudeSqr() < radius) { + CPopulation::RemovePed(pPed); + } + } + CVehiclePool* VehiclePool = CPools::GetVehiclePool(); + for (int32 i = 0; i < VehiclePool->GetSize(); i++) { + CVehicle* pVehicle = VehiclePool->GetSlot(i); + if (pVehicle && CVector2D(pVehicle->GetPosition() - pos).MagnitudeSqr() < radius && + !pVehicle->bIsLocked && pVehicle->CanBeDeleted()) { + if (pVehicle->pDriver) { + CPopulation::RemovePed(pVehicle->pDriver); + pVehicle->pDriver = nil; + } + for (int32 j = 0; j < pVehicle->m_nNumMaxPassengers; ++j) { + if (pVehicle->pPassengers[j]) { + 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); + if (bRemoveProjectilesAndTidyUpShadows) { + CProjectileInfo::RemoveAllProjectiles(); + CShadows::TidyUpShadows(); + } +} + bool CWorld::CameraToIgnoreThisObject(CEntity *ent) { @@ -695,6 +728,67 @@ CWorld::FindObjectsInRange(CVector ¢re, float radius, bool ignoreZ, short *n } } +void +CWorld::FindObjectsOfTypeInRangeSectorList(uint32 modelId, CPtrList& list, const CVector& position, float radius, bool bCheck2DOnly, int16* nEntitiesFound, int16 maxEntitiesToFind, CEntity** aEntities) +{ + CPtrNode* pNode = list.first; + while (pNode) { + CEntity* pEntity = (CEntity*)pNode->item; + if (pEntity->m_scanCode != ms_nCurrentScanCode) { + pEntity->m_scanCode = ms_nCurrentScanCode; + 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; + } + } + pNode = pNode->next; + } +} + +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) +{ + CWorld::AdvanceCurrentScanCode(); + *nEntitiesFound = 0; + const CVector2D vecSectorStartPos(position.x - radius, position.y - radius); + const CVector2D vecSectorEndPos(position.x + radius, position.y + radius); + 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); + 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) { @@ -873,6 +967,273 @@ CWorld::FindRoofZFor3DCoord(float x, float y, float z, bool *found) } } +void +CWorld::RemoveReferencesToDeletedObject(CEntity* pDeletedObject) +{ + int32 i = CPools::GetPedPool()->GetSize(); + while (--i >= 0) { + CPed* pPed = CPools::GetPedPool()->GetSlot(i); + if (pPed && pPed != pDeletedObject) { + pPed->RemoveRefsToEntity(pDeletedObject); + if (pPed->m_pCurrentPhysSurface == pDeletedObject) + pPed->m_pCurrentPhysSurface = nil; + } + } + i = CPools::GetVehiclePool()->GetSize(); + while (--i >= 0) { + CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i); + if (pVehicle && pVehicle != pDeletedObject) { + pVehicle->RemoveRefsToEntity(pDeletedObject); + pVehicle->RemoveRefsToVehicle(pDeletedObject); + } + } + i = CPools::GetObjectPool()->GetSize(); + while (--i >= 0) { + CObject* pObject = CPools::GetObjectPool()->GetSlot(i); + if (pObject && pObject != pDeletedObject) { + pObject->RemoveRefsToEntity(pDeletedObject); + } + } +} + +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) +{ + CWorld::AdvanceCurrentScanCode(); + *nCollidingEntities = 0; + const CVector2D vecSectorStartPos(position.x - radius, position.y - radius); + const CVector2D vecSectorEndPos(position.x + radius, position.y + radius); + 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); + 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); + } + } + } +} + +void +CWorld::FindObjectsKindaCollidingSectorList(CPtrList& list, const CVector& position, float radius, bool bCheck2DOnly, int16* nCollidingEntities, int16 maxEntitiesToFind, CEntity** aEntities) +{ + CPtrNode* pNode = list.first; + while (pNode) { + CEntity* pEntity = (CEntity*)pNode->item; + if (pEntity->m_scanCode != ms_nCurrentScanCode) { + pEntity->m_scanCode = ms_nCurrentScanCode; + float fMagnitude = 0.0f; + if (bCheck2DOnly) + fMagnitude = (position - pEntity->GetPosition()).Magnitude2D(); + else + fMagnitude = (position - pEntity->GetPosition()).Magnitude(); + if (pEntity->GetBoundRadius() + radius > fMagnitude && *nCollidingEntities < maxEntitiesToFind) { + if (aEntities) + aEntities[*nCollidingEntities] = pEntity; + ++*nCollidingEntities; + } + } + pNode = pNode->next; + } +} + +void +CWorld::FindObjectsIntersectingCube(const CVector& vecStartPos, const CVector& vecEndPos, int16* nIntersecting, int16 maxEntitiesToFind, CEntity** aEntities, bool bBuildings, bool bVehicles, bool bPeds, bool bObjects, bool bDummies) +{ + CWorld::AdvanceCurrentScanCode(); + *nIntersecting = 0; + 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); + 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); + } + } + } + +} + +void +CWorld::FindObjectsIntersectingCubeSectorList(CPtrList& list, const CVector& vecStartPos, const CVector& vecEndPos, int16* nIntersecting, int16 maxEntitiesToFind, CEntity** aEntities) +{ + CPtrNode* pNode = list.first; + while (pNode) { + CEntity* pEntity = (CEntity*)pNode->item; + if (pEntity->m_scanCode != CWorld::ms_nCurrentScanCode) { + pEntity->m_scanCode = CWorld::ms_nCurrentScanCode; + 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; + } + } + pNode = pNode->next; + } +} + +void +CWorld::FindObjectsIntersectingAngledCollisionBox(const CColBox& boundingBox, const CMatrix& matrix, 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) +{ + CWorld::AdvanceCurrentScanCode(); + *nEntitiesFound = 0; + 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); + 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); + } + } + } +} + +void +CWorld::FindObjectsIntersectingAngledCollisionBoxSectorList(CPtrList& list, const CColBox& boundingBox, const CMatrix& matrix, const CVector& position, int16* nEntitiesFound, int16 maxEntitiesToFind, CEntity** aEntities) +{ + CPtrNode* pNode = list.first; + while (pNode) { + CEntity* pEntity = (CEntity*)pNode->item; + if (pEntity->m_scanCode != CWorld::ms_nCurrentScanCode) { + pEntity->m_scanCode = CWorld::ms_nCurrentScanCode; + CColSphere sphere; + CVector vecDistance = pEntity->GetPosition() - position; + sphere.radius = pEntity->GetBoundRadius(); + sphere.center = Multiply3x3(vecDistance, matrix); + if (CCollision::TestSphereBox(sphere, boundingBox) && *nEntitiesFound < maxEntitiesToFind) { + if (aEntities) + aEntities[*nEntitiesFound] = pEntity; + ++*nEntitiesFound; + } + } + pNode = pNode->next; + } +} + +void +CWorld::FindMissionEntitiesIntersectingCube(const CVector& vecStartPos, const CVector& vecEndPos, int16* nIntersecting, int16 maxEntitiesToFind, CEntity** aEntities, bool bVehicles, bool bPeds, bool bObjects) +{ + CWorld::AdvanceCurrentScanCode(); + *nIntersecting = 0; + 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); + 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); + } + 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); + } + 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); + } + } + } +} + +void +CWorld::FindMissionEntitiesIntersectingCubeSectorList(CPtrList& list, const CVector& vecStartPos, const CVector& vecEndPos, int16* nIntersecting, int16 maxEntitiesToFind, CEntity** aEntities, bool bIsVehicleList, bool bIsPedList) +{ + CPtrNode* pNode = list.first; + while (pNode) { + CEntity* pEntity = (CEntity*)pNode->item; + if (pEntity->m_scanCode != CWorld::ms_nCurrentScanCode) { + pEntity->m_scanCode = CWorld::ms_nCurrentScanCode; + bool bIsMissionEntity = false; + if (bIsVehicleList) + bIsMissionEntity = ((CVehicle*)pEntity)->VehicleCreatedBy == MISSION_VEHICLE; + else if (bIsPedList) + bIsMissionEntity = ((CPed*)pEntity)->CharCreatedBy == MISSION_CHAR; + else + bIsMissionEntity = ((CObject*)pEntity)->ObjectCreatedBy == MISSION_OBJECT; + float fRadius = pEntity->GetBoundRadius(); + 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; + ++*nIntersecting; + } + } + pNode = pNode->next; + } +} + CPlayerPed* FindPlayerPed(void) { @@ -961,6 +1322,155 @@ FindPlayerHeading(void) return FindPlayerPed()->GetForward().Heading(); } + +void CWorld::ClearCarsFromArea(float x1, float y1, float z1, float x2, float y2, float z2) +{ + CVehiclePool *pVehiclePool = CPools::GetVehiclePool(); + 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) { + CPopulation::RemovePed(pVehicle->pDriver); + pVehicle->pDriver = nil; + } + for (int32 j = 0; j < pVehicle->m_nNumMaxPassengers; ++j) { + if (pVehicle->pPassengers[j]) { + CPopulation::RemovePed(pVehicle->pPassengers[j]); + pVehicle->pPassengers[j] = nil; + --pVehicle->m_nNumPassengers; + } + } + CCarCtrl::RemoveFromInterestingVehicleList(pVehicle); + CWorld::Remove(pVehicle); + delete pVehicle; + } + } + } +} + +void +CWorld::ClearPedsFromArea(float x1, float y1, float z1, float x2, float y2, float z2) +{ + 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) { + CPopulation::RemovePed(pPed); + } + } + } +} + +void +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; + 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); + 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); + CWorld::CallOffChaseForAreaSectorListPeds(pSector->m_lists[ENTITYLIST_PEDS], x1, y1, x2, y2); + CWorld::CallOffChaseForAreaSectorListPeds(pSector->m_lists[ENTITYLIST_PEDS_OVERLAP], x1, y1, x2, y2); + } + } +} + +void +CWorld::CallOffChaseForAreaSectorListVehicles(CPtrList& list, float x1, float y1, float x2, float y2, float fStartX, float fStartY, float fEndX, float fEndY) +{ + CPtrNode* pNode = list.first; + while (pNode) { + CVehicle *pVehicle = (CVehicle*)pNode->item; + if (pVehicle->m_scanCode != CWorld::ms_nCurrentScanCode) { + pVehicle->m_scanCode = CWorld::ms_nCurrentScanCode; + const CVector& vehiclePos = pVehicle->GetPosition(); + eCarMission carMission = pVehicle->AutoPilot.m_nCarMission; + 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) + ) { + pVehicle->AutoPilot.m_nTimeTempAction = CTimer::GetTimeInMilliseconds() + 2000; + CColModel* pColModel = pVehicle->GetColModel(); + bool bInsideSphere = false; + for (int32 i = 0; i < pColModel->numSpheres; i++) { + CVector pos = pVehicle->m_matrix * pColModel->spheres[i].center; + float fRadius = pColModel->spheres[i].radius; + if (pos.x + fRadius > x1 && pos.x - fRadius < x2 && pos.y + fRadius > y1 && pos.y - fRadius < y2) + bInsideSphere = true; + // Maybe break the loop when bInsideSphere is set to true? + } + if (bInsideSphere) { + if (pVehicle->GetPosition().x <= (x1 + x2) * 0.5f) + pVehicle->m_vecMoveSpeed.x = min(pVehicle->m_vecMoveSpeed.x, 0.0f); + else + pVehicle->m_vecMoveSpeed.x = max(pVehicle->m_vecMoveSpeed.x, 0.0f); + if (pVehicle->GetPosition().y <= (y1 + y2) * 0.5f) + pVehicle->m_vecMoveSpeed.y = min(pVehicle->m_vecMoveSpeed.y, 0.0f); + else + pVehicle->m_vecMoveSpeed.y = max(pVehicle->m_vecMoveSpeed.y, 0.0f); + } + } + } + pNode = pNode->next; + } +} + +void +CWorld::CallOffChaseForAreaSectorListPeds(CPtrList& list, float x1, float y1, float x2, float y2) +{ + CPtrNode* pNode = list.first; + while (pNode) { + CPed* pPed = (CPed*)pNode->item; + const CVector& pedPos = pPed->GetPosition(); + if (pPed->m_scanCode != CWorld::ms_nCurrentScanCode) + { + pPed->m_scanCode = CWorld::ms_nCurrentScanCode; + 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(); + else + pPed->SetIdle(); + pPed->SetObjective(OBJECTIVE_NONE); + } + else { + pPed->m_prevObjective = OBJECTIVE_NONE; + pPed->m_nLastPedState = PED_IDLE; + } + } + } + } +} + void CWorld::RemoveEntityInsteadOfProcessingIt(CEntity* ent) { @@ -1057,6 +1567,243 @@ CWorld::ExtinguishAllCarFiresInArea(CVector point, float range) } } +void +CWorld::AddParticles(void) +{ + for (int32 y = 0; y < NUMSECTORS_Y; y++) { + for (int32 x = 0; x < NUMSECTORS_X; x++) { + CSector* pSector = GetSector(x, y); + CEntity::AddSteamsFromGround(pSector->m_lists[ENTITYLIST_BUILDINGS]); + CEntity::AddSteamsFromGround(pSector->m_lists[ENTITYLIST_DUMMIES]); + } + } +} + +void +CWorld::ShutDown(void) +{ + for (int32 y = 0; y < NUMSECTORS_Y; y++) { + for (int32 x = 0; x < NUMSECTORS_X; x++) { + CSector *pSector = GetSector(x, y); + CPtrNode *pNode = pSector->m_lists[ENTITYLIST_BUILDINGS].first; + while (pNode) { + CEntity* pEntity = (CEntity*)pNode->item; + if (pEntity) { + CWorld::Remove(pEntity); + delete pEntity; + } + pNode = pNode->next; + } + pNode = pSector->m_lists[ENTITYLIST_VEHICLES].first; + while (pNode) { + CEntity* pEntity = (CEntity*)pNode->item; + if (pEntity) { + CWorld::Remove(pEntity); + delete pEntity; + } + pNode = pNode->next; + } + pNode = pSector->m_lists[ENTITYLIST_PEDS].first; + while (pNode) { + CEntity *pEntity = (CEntity*)pNode->item; + if (pEntity) { + CWorld::Remove(pEntity); + delete pEntity; + } + pNode = pNode->next; + } + pNode = pSector->m_lists[ENTITYLIST_OBJECTS].first; + while (pNode) { + CEntity *pEntity = (CEntity*)pNode->item; + if (pEntity) { + CWorld::Remove(pEntity); + delete pEntity; + } + pNode = pNode->next; + } + pNode = pSector->m_lists[ENTITYLIST_DUMMIES].first; + while (pNode) { + CEntity *pEntity = (CEntity*)pNode->item; + if (pEntity) { + CWorld::Remove(pEntity); + delete pEntity; + } + pNode = pNode->next; + } + 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(); + } + } + for (int32 i = 0; i < 4; i ++) { + CPtrNode *pNode = GetBigBuildingList((eLevelName)i).first; + while (pNode) { + CEntity *pEntity = (CEntity*)pNode->item; + if (pEntity) { + // Maybe remove from world here? + delete pEntity; + } + pNode = pNode->next; + } + GetBigBuildingList((eLevelName)i).Flush(); + } + for (int32 y = 0; y < NUMSECTORS_Y; y++) { + for (int32 x = 0; x < NUMSECTORS_X; x++) { + CSector *pSector = GetSector(x, y); + if (pSector->m_lists[ENTITYLIST_BUILDINGS].first) { + sprintf(gString, "Building list %d,%d not empty\n", x, y); + pSector->m_lists[ENTITYLIST_BUILDINGS].Flush(); + } + if (pSector->m_lists[ENTITYLIST_DUMMIES].first) { + sprintf(gString, "Dummy list %d,%d not empty\n", x, y); + pSector->m_lists[ENTITYLIST_DUMMIES].Flush(); + } + if (pSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP].first) { + sprintf(gString, "Building overlap list %d,%d not empty\n", x, y); + pSector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP].Flush(); + } + if (pSector->m_lists[ENTITYLIST_VEHICLES_OVERLAP].first) { + sprintf(gString, "Vehicle overlap list %d,%d not empty\n", x, y); + pSector->m_lists[ENTITYLIST_VEHICLES_OVERLAP].Flush(); + } + if (pSector->m_lists[ENTITYLIST_PEDS_OVERLAP].first) { + sprintf(gString, "Ped overlap list %d,%d not empty\n", x, y); + pSector->m_lists[ENTITYLIST_PEDS_OVERLAP].Flush(); + } + if (pSector->m_lists[ENTITYLIST_OBJECTS_OVERLAP].first) { + sprintf(gString, "Object overlap list %d,%d not empty\n", x, y); + pSector->m_lists[ENTITYLIST_OBJECTS_OVERLAP].Flush(); + } + if (pSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP].first) { + sprintf(gString, "Dummy overlap list %d,%d not empty\n", x, y); + pSector->m_lists[ENTITYLIST_DUMMIES_OVERLAP].Flush(); + } + } + } + ms_listMovingEntityPtrs.Flush(); +} + +void +CWorld::ClearForRestart(void) +{ + if (CCutsceneMgr::HasLoaded()) + CCutsceneMgr::DeleteCutsceneData(); + CProjectileInfo::RemoveAllProjectiles(); + CObject::DeleteAllTempObjects(); + CObject::DeleteAllMissionObjects(); + CPopulation::ConvertAllObjectsToDummyObjects(); + for (int32 y = 0; y < NUMSECTORS_Y; y++) { + for (int32 x = 0; x < NUMSECTORS_X; x++) { + CSector *pSector = GetSector(x, y); + CPtrNode *pNode = pSector->m_lists[ENTITYLIST_PEDS].first; + while (pNode) { + CEntity *pEntity = (CEntity*)pNode->item; + if (pEntity) { + CWorld::Remove(pEntity); + delete pEntity; + } + pNode = pNode->next; + } + pNode = GetBigBuildingList(LEVEL_NONE).first; + while (pNode) { + CVehicle *pVehicle = (CVehicle*)pNode->item; + if (pVehicle && pVehicle->IsVehicle() && pVehicle->IsPlane()) { + CWorld::Remove(pVehicle); + delete pVehicle; + } + pNode = pNode->next; + } + pNode = pSector->m_lists[ENTITYLIST_VEHICLES].first; + while (pNode) { + CEntity* pEntity = (CEntity*)pNode->item; + if (pEntity) { + CWorld::Remove(pEntity); + delete pEntity; + } + pNode = pNode->next; + } + } + } + CPools::CheckPoolsEmpty(); +} + +void +CWorld::RepositionCertainDynamicObjects() +{ + int32 i = CPools::GetDummyPool()->GetSize(); + while (--i >= 0) { + CDummy* dummy = CPools::GetDummyPool()->GetSlot(i); + if (dummy) { + RepositionOneObject(dummy); + } + } +} + +void +CWorld::RepositionOneObject(CEntity* pEntity) +{ + int16 modelId = pEntity->m_modelIndex; + if (modelId == MI_SINGLESTREETLIGHTS1 + || modelId == MI_SINGLESTREETLIGHTS2 + || modelId == MI_SINGLESTREETLIGHTS3 + || modelId == MI_DOUBLESTREETLIGHTS + || modelId == MI_TREE1 + || modelId == MI_TREE2 + || modelId == MI_TREE3 + || modelId == MI_TREE4 + || modelId == MI_TREE5 + || modelId == MI_TREE6 + || modelId == MI_TREE7 + || modelId == MI_TREE8 + || modelId == MI_TREE9 + || modelId == MI_TREE10 + || modelId == MI_TREE11 + || modelId == MI_TREE12 + || modelId == MI_TREE13 + || modelId == MI_TREE14 + || modelId == MI_TRAFFICLIGHTS + || 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_TAXISIGN + || modelId == MI_FISHSTALL01 + || modelId == MI_FISHSTALL02 + || modelId == MI_FISHSTALL03 + || modelId == MI_FISHSTALL04 + || modelId == MI_BAGELSTAND2 + || modelId == MI_FIRE_HYDRANT + || modelId == MI_BOLLARDLIGHT + || modelId == MI_PARKTABLE) { + CVector& position = pEntity->GetPosition(); + float fBoundingBoxMinZ = pEntity->GetColModel()->boundingBox.min.z; + position.z = CWorld::FindGroundZFor3DCoord(position.x, position.y, position.z + OBJECT_REPOSITION_OFFSET_Z, nil) - fBoundingBoxMinZ; + pEntity->m_matrix.UpdateRW(); + pEntity->UpdateRwFrame(); + } else if (modelId == MI_BUOY) { + float fWaterLevel = 0.0f; + bool bFound = true; + 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(); + float fHeight = pColModel->boundingBox.max.z - pColModel->boundingBox.min.z; + pEntity->GetPosition().z = 0.2f * fHeight + fWaterLevel - 0.5f * fHeight; + } + } + } +} + void CWorld::SetCarsOnFire(float x, float y, float z, float radius, CEntity *reason) { @@ -1070,6 +1817,60 @@ CWorld::SetCarsOnFire(float x, float y, float z, float radius, CEntity *reason) } } +void +CWorld::SetPedsOnFire(float x, float y, float z, float radius, CEntity* reason) +{ + int32 poolSize = CPools::GetPedPool()->GetSize(); + 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) + gFireManager.StartFire(pPed, reason, 0.8f, true); + } + } +} + +void +CWorld::RemoveStaticObjects() +{ + for (int32 y = 0; y < NUMSECTORS_Y; y++) { + for (int32 x = 0; x < NUMSECTORS_X; x++) { + CSector* pSector = GetSector(x, y); + CPtrNode* pNode = pSector->m_lists[ENTITYLIST_BUILDINGS].first; + while (pNode) { + CEntity* pEntity = (CEntity*)pNode->item; + if (pEntity) { + CWorld::Remove(pEntity); + delete pEntity; + } + pNode = pNode->next; + } + pNode = pSector->m_lists[ENTITYLIST_OBJECTS].first; + while (pNode) { + CEntity* pEntity = (CEntity*)pNode->item; + if (pEntity) { + CWorld::Remove(pEntity); + delete pEntity; + } + pNode = pNode->next; + } + pNode = pSector->m_lists[ENTITYLIST_DUMMIES].first; + while (pNode) { + CEntity* pEntity = (CEntity*)pNode->item; + if (pEntity) { + CWorld::Remove(pEntity); + delete pEntity; + } + pNode = pNode->next; + } + 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(); + } + } +} + void CWorld::Process(void) { @@ -1248,6 +2049,147 @@ CWorld::Process(void) } } +void +CWorld::TriggerExplosion(const CVector& position, float fRadius, float fPower, CEntity* pCreator, bool bProcessVehicleBombTimer) +{ + CVector2D vecStartPos(position.x - fRadius, position.y - fRadius); + CVector2D vecEndPos(position.x + fRadius, position.y + fRadius); + 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); + 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); + } + } + +} + +void +CWorld::TriggerExplosionSectorList(CPtrList& list, const CVector& position, float fRadius, float fPower, CEntity* pCreator, bool bProcessVehicleBombTimer) +{ + CPtrNode* pNode = list.first; + while (pNode) { + 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)) { + if (pEntity->bIsStatic) { + if (pEntity->IsObject()) { + if (fPower > pObject->m_fUprootLimit || IsFence(pObject->m_modelIndex)) { + if (IsGlass(pObject->m_modelIndex)) { + CGlass::WindowRespondsToExplosion(pObject, position); + } else { + pObject->bIsStatic = false; + pObject->AddToMovingList(); + int16 modelId = pEntity->m_modelIndex; + if (modelId != MI_FIRE_HYDRANT || pObject->bHasBeenDamaged) { + if (pEntity->IsObject() && modelId != MI_EXPLODINGBARREL && modelId != MI_PETROLPUMP) + pObject->bHasBeenDamaged = true; + } else { + CVector pos = pEntity->GetPosition(); + pos.z -= 0.5f; + CParticleObject::AddObject(POBJECT_FIRE_HYDRANT, pos, true); + pObject->bHasBeenDamaged = true; + } + } + } + if (pEntity->bIsStatic) { + float fDamageMultiplier = (fRadius - fMagnitude) * 2.0f / fRadius; + float fDamage = 300.0f * min(fDamageMultiplier, 1.0f); + pObject->ObjectDamage(fDamage); + } + } else { + pEntity->bIsStatic = false; + pEntity->AddToMovingList(); + } + } + if (!pEntity->bIsStatic) { + float fDamageMultiplier = min((fRadius - fMagnitude) * 2.0f / fRadius, 1.0f); + CVector vecForceDir = vecDistance * (fPower * pEntity->m_fMass * 0.00071429f * fDamageMultiplier / max(fMagnitude, 0.01f)); + vecForceDir.z = max(vecForceDir.z, 0.0f); + if (pEntity == FindPlayerPed()) + vecForceDir.z = min(vecForceDir.z, 1.0f); + pEntity->ApplyMoveForce(vecForceDir); + if (!pEntity->bPedPhysics) { + float fBoundRadius = pEntity->GetBoundRadius(); + float fDistanceZ = position.z - pEntity->GetPosition().z; + float fPointZ = fBoundRadius; + if (max(fDistanceZ, -fBoundRadius) < fBoundRadius) + { + if (fDistanceZ <= -fBoundRadius) + fPointZ = -fBoundRadius; + else + fPointZ = fDistanceZ; + } + pEntity->ApplyTurnForce(vecForceDir.x, vecForceDir.y, vecForceDir.z, 0.0f, 0.0f, fPointZ); + } + switch (pEntity->m_type) + { + case ENTITY_TYPE_VEHICLE: + if (pEntity->m_status == STATUS_SIMPLE) { + pEntity->m_status = STATUS_PHYSICS; + CCarCtrl::SwitchVehicleToRealPhysics(pVehicle); + } + pVehicle->InflictDamage(pCreator, WEAPONTYPE_EXPLOSION, 1100.0f * fDamageMultiplier); + if (bProcessVehicleBombTimer) { + if (pVehicle->m_nBombTimer) + pVehicle->m_nBombTimer /= 10; + } + 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; + 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()) { + eEventType eventType = EVENT_SHOOT_PED; + if (pPed->m_nPedType == PEDTYPE_COP) + eventType = EVENT_SHOOT_COP; + CEventList::RegisterEvent(eventType, EVENT_ENTITY_PED, pEntity, (CPed*)pCreator, 10000); + pPed->RegisterThreatWithGangPeds(pCreator); + } + break; + } + case ENTITY_TYPE_OBJECT: + pObject->ObjectDamage(300.0f * fDamageMultiplier); + break; + } + } + } + } + pNode = pNode->next; + } +} + +void +CWorld::UseDetonator(CEntity* pEntity) +{ + int32 i = CPools::GetVehiclePool()->GetSize(); + while (--i >= 0) { + CAutomobile* pVehicle = (CAutomobile*)CPools::GetVehiclePool()->GetSlot(i); + if (pVehicle && !pVehicle->m_vehType && pVehicle->m_bombType == CARBOMB_REMOTE && pVehicle->m_pBombRigger == pEntity) { + pVehicle->m_bombType = CARBOMB_NONE; + pVehicle->m_nBombTimer = 500; + pVehicle->m_pBlowUpEntity = pVehicle->m_pBombRigger; + if (pVehicle->m_pBlowUpEntity) + pVehicle->m_pBlowUpEntity->RegisterReference(&pVehicle->m_pBlowUpEntity); + } + } +} + STARTPATCHES InjectHook(0x4AE930, CWorld::Add, PATCH_JUMP); InjectHook(0x4AE9D0, CWorld::Remove, PATCH_JUMP); diff --git a/src/core/World.h b/src/core/World.h index d3f1e2d5..a1e2acfd 100644 --- a/src/core/World.h +++ b/src/core/World.h @@ -85,7 +85,7 @@ public: } } static void ClearScanCodes(void); - static void ClearExcitingStuffFromArea(const CVector &pos, float radius, uint8); + static void ClearExcitingStuffFromArea(const CVector &pos, float radius, bool bRemoveProjectilesAndTidyUpShadows); static bool CameraToIgnoreThisObject(CEntity *ent); @@ -103,19 +103,26 @@ public: static CEntity *TestSphereAgainstSectorList(CPtrList&, CVector, float, CEntity*, bool); static void FindObjectsInRangeSectorList(CPtrList&, CVector&, float, bool, short*, short, CEntity**); static void FindObjectsInRange(CVector&, float, bool, short*, short, CEntity**, bool, bool, bool, bool, bool); - static void FindObjectsOfTypeInRangeSectorList(uint32, CPtrList&, CVector&, float, bool, short*, short, CEntity**); - static void FindObjectsOfTypeInRange(uint32, CVector&, float, bool, short*, short, CEntity**, bool, bool, bool, bool, bool); + static void FindObjectsOfTypeInRangeSectorList(uint32 modelId, CPtrList& list, const CVector& position, float radius, bool bCheck2DOnly, int16* nEntitiesFound, int16 maxEntitiesToFind, CEntity** aEntities); + static void 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); static float FindGroundZForCoord(float x, float y); static float FindGroundZFor3DCoord(float x, float y, float z, bool *found); static float FindRoofZFor3DCoord(float x, float y, float z, bool *found); static void RemoveReferencesToDeletedObject(CEntity*); - static void FindObjectsKindaColliding(const CVector &, float, bool, int16*, int16, CEntity **, bool, bool, bool, bool, bool); - static void FindObjectsIntersectingCube(const CVector &, const CVector &, int16*, int16, CEntity **, bool, bool, bool, bool, bool); + static void FindObjectsKindaColliding(const CVector& position, float radius, bool bCheck2DOnly, int16* nCollidingEntities, int16 maxEntitiesToFind, CEntity** aEntities, bool bBuildings, bool bVehicles, bool bPeds, bool bObjects, bool bDummies); + static void FindObjectsKindaCollidingSectorList(CPtrList& list, const CVector& position, float radius, bool bCheck2DOnly, int16* nCollidingEntities, int16 maxEntitiesToFind, CEntity** aEntities); + static void FindObjectsIntersectingCube(const CVector& vecStartPos, const CVector& vecEndPos, int16* nIntersecting, int16 maxEntitiesToFind, CEntity** aEntities, bool bBuildings, bool bVehicles, bool bPeds, bool bObjects, bool bDummies); + static void FindObjectsIntersectingCubeSectorList(CPtrList& list, const CVector& vecStartPos, const CVector& vecEndPos, int16* nIntersecting, int16 maxEntitiesToFind, CEntity** aEntities); static void FindObjectsIntersectingAngledCollisionBox(const CColBox &, const CMatrix &, const CVector &, float, float, float, float, int16*, int16, CEntity **, bool, bool, bool, bool, bool); - static void FindMissionEntitiesIntersectingCube(const CVector&, const CVector&, int16*, int16, CEntity**, bool, bool, bool); - static void ClearCarsFromArea(float, float, float, float, float, float); - static void ClearPedsFromArea(float, float, float, float, float, float); - static void CallOffChaseForArea(float, float, float, float); + static void FindObjectsIntersectingAngledCollisionBoxSectorList(CPtrList& list, const CColBox& boundingBox, const CMatrix& matrix, const CVector& position, int16* nEntitiesFound, int16 maxEntitiesToFind, CEntity** aEntities); + static void FindMissionEntitiesIntersectingCube(const CVector& vecStartPos, const CVector& vecEndPos, int16* nIntersecting, int16 maxEntitiesToFind, CEntity** aEntities, bool bVehicles, bool bPeds, bool bObjects); + static void FindMissionEntitiesIntersectingCubeSectorList(CPtrList& list, const CVector& vecStartPos, const CVector& vecEndPos, int16* nIntersecting, int16 maxEntitiesToFind, CEntity** aEntities, bool bIsVehicleList, bool bIsPedList); + + static void ClearCarsFromArea(float x1, float y1, float z1, float x2, float y2, float z2); + static void ClearPedsFromArea(float x1, float y1, float z1, float x2, float y2, float z2); + static void CallOffChaseForArea(float x1, float y1, float x2, float y2); + static void CallOffChaseForAreaSectorListVehicles(CPtrList& list, float x1, float y1, float x2, float y2, float fStartX, float fStartY, float fEndX, float fEndY); + static void CallOffChaseForAreaSectorListPeds(CPtrList& list, float x1, float y1, float x2, float y2); static float GetSectorX(float f) { return ((f - WORLD_MIN_X)/SECTOR_SIZE_X); } static float GetSectorY(float f) { return ((f - WORLD_MIN_Y)/SECTOR_SIZE_Y); } @@ -131,19 +138,20 @@ public: static void StopAllLawEnforcersInTheirTracks(); static void SetAllCarsCanBeDamaged(bool); static void ExtinguishAllCarFiresInArea(CVector, float); - static void SetCarsOnFire(float, float, float, float, CEntity*); - static void SetPedsOnFire(float, float, float, float, CEntity*); + static void SetCarsOnFire(float x, float y, float z, float radius, CEntity* reason); + static void SetPedsOnFire(float x, float y, float z, float radius, CEntity* reason); static void Initialise(); static void AddParticles(); static void ShutDown(); static void ClearForRestart(void); static void RepositionCertainDynamicObjects(); + static void RepositionOneObject(CEntity* pEntity); static void RemoveStaticObjects(); static void Process(); - static void TriggerExplosion(const CVector &, float, float, CEntity*, bool); - - static void UseDetonator(CEntity *); + static void TriggerExplosion(const CVector& position, float fRadius, float fPower, CEntity* pCreator, bool bProcessVehicleBombTimer); + static void TriggerExplosionSectorList(CPtrList& list, const CVector& position, float fRadius, float fPower, CEntity* pCreator, bool bProcessVehicleBombTimer); + static void UseDetonator(CEntity *pEntity); }; extern CColPoint gaTempSphereColPoints[MAX_COLLISION_POINTS]; diff --git a/src/entities/Entity.cpp b/src/entities/Entity.cpp index 25e5db48..0efee4e7 100644 --- a/src/entities/Entity.cpp +++ b/src/entities/Entity.cpp @@ -865,6 +865,16 @@ CEntity::ModifyMatrixForBannerInWind(void) UpdateRwFrame(); } +void +CEntity::AddSteamsFromGround(CPtrList& list) +{ + CPtrNode *pNode = list.first; + while (pNode) { + ((CEntity*)pNode->item)->AddSteamsFromGround(nil); + pNode = pNode->next; + } +} + #include <new> class CEntity_ : public CEntity @@ -912,7 +922,7 @@ STARTPATCHES InjectHook(0x473F60, &CEntity::DetachFromRwObject, PATCH_JUMP); InjectHook(0x475A20, &CEntity::PreRenderForGlassWindow, PATCH_JUMP); - InjectHook(0x50CE40, &CEntity::AddSteamsFromGround, PATCH_JUMP); + InjectHook(0x50CE40, (void (CEntity::*)(CVector*))& CEntity::AddSteamsFromGround, PATCH_JUMP); InjectHook(0x475670, &CEntity::ModifyMatrixForTreeInWind, PATCH_JUMP); InjectHook(0x475830, &CEntity::ModifyMatrixForBannerInWind, PATCH_JUMP); InjectHook(0x4FA530, &CEntity::ProcessLightsForEntity, PATCH_JUMP); diff --git a/src/entities/Entity.h b/src/entities/Entity.h index ca501ba4..dadeee54 100644 --- a/src/entities/Entity.h +++ b/src/entities/Entity.h @@ -4,6 +4,7 @@ #include "Placeable.h" struct CReference; +class CPtrList; enum eEntityType { @@ -152,5 +153,7 @@ public: void ModifyMatrixForTreeInWind(void); void ModifyMatrixForBannerInWind(void); void ProcessLightsForEntity(void); + + static void AddSteamsFromGround(CPtrList& list); }; static_assert(sizeof(CEntity) == 0x64, "CEntity: error"); diff --git a/src/modelinfo/ModelIndices.h b/src/modelinfo/ModelIndices.h index 309fa1bb..cc8399e7 100644 --- a/src/modelinfo/ModelIndices.h +++ b/src/modelinfo/ModelIndices.h @@ -496,4 +496,11 @@ IsExplosiveThingModel(int16 id) { return id == MI_EXPLODINGBARREL || id == MI_PETROLPUMP; +} + +inline bool +IsFence(int16 id) +{ + return id == MI_FENCE || + id == MI_FENCE2; }
\ No newline at end of file diff --git a/src/objects/Object.cpp b/src/objects/Object.cpp index 867624c7..88773b83 100644 --- a/src/objects/Object.cpp +++ b/src/objects/Object.cpp @@ -383,7 +383,7 @@ CObject::DeleteAllTempObjects() } void -CObject::DeleteAllTempObjectInArea(CVector point, float fRadius) +CObject::DeleteAllTempObjectsInArea(CVector point, float fRadius) { CObjectPool *objectPool = CPools::GetObjectPool(); for (int32 i = 0; i < objectPool->GetSize(); i++) { @@ -426,5 +426,5 @@ STARTPATCHES InjectHook(0x4BB010, &CObject::CanBeDeleted, PATCH_JUMP); InjectHook(0x4BBE60, &CObject::DeleteAllMissionObjects, PATCH_JUMP); InjectHook(0x4BBDF0, &CObject::DeleteAllTempObjects, PATCH_JUMP); - InjectHook(0x4BBED0, &CObject::DeleteAllTempObjectInArea, PATCH_JUMP); + InjectHook(0x4BBED0, &CObject::DeleteAllTempObjectsInArea, PATCH_JUMP); ENDPATCHES diff --git a/src/objects/Object.h b/src/objects/Object.h index 6d04c78a..80c742a0 100644 --- a/src/objects/Object.h +++ b/src/objects/Object.h @@ -99,6 +99,6 @@ public: static void DeleteAllMissionObjects(); static void DeleteAllTempObjects(); - static void DeleteAllTempObjectInArea(CVector point, float fRadius); + static void DeleteAllTempObjectsInArea(CVector point, float fRadius); }; static_assert(sizeof(CObject) == 0x198, "CObject: error"); |