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.cpp718
1 files changed, 718 insertions, 0 deletions
diff --git a/src/core/World.cpp b/src/core/World.cpp
new file mode 100644
index 00000000..538e15c5
--- /dev/null
+++ b/src/core/World.cpp
@@ -0,0 +1,718 @@
+#include "common.h"
+#include "patcher.h"
+#include "Entity.h"
+#include "Ped.h"
+#include "PlayerPed.h"
+#include "Vehicle.h"
+#include "Object.h"
+#include "Camera.h"
+#include "DMAudio.h"
+#include "CarCtrl.h"
+#include "Garages.h"
+#include "TempColModels.h"
+#include "World.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;
+
+uint8 &CWorld::PlayerInFocus = *(uint8 *)0x95CD61;
+CPlayerInfo *CWorld::Players = (CPlayerInfo *)0x9412F0;
+bool &CWorld::bNoMoreCollisionTorque = *(bool*)0x95CDCC;
+CEntity *&CWorld::pIgnoreEntity = *(CEntity**)0x8F6494;
+bool &CWorld::bIncludeDeadPeds = *(bool*)0x95CD8F;
+bool &CWorld::bSecondShift = *(bool*)0x95CD54;
+bool &CWorld::bForceProcessControl = *(bool*)0x95CD6C;
+bool &CWorld::bProcessCutsceneOnly = *(bool*)0x95CD8B;
+
+void
+CWorld::Add(CEntity *ent)
+{
+ if(ent->IsVehicle() || ent->IsPed())
+ DMAudio.SetEntityStatus(((CPhysical*)ent)->m_audioEntityId, true);
+
+ if(ent->bIsBIGBuilding)
+ ms_bigBuildingsList[ent->m_level].InsertItem(ent);
+ else
+ ent->Add();
+
+ if(ent->IsBuilding() || ent->IsDummy())
+ return;
+
+ if(!ent->bIsStatic)
+ ((CPhysical*)ent)->AddToMovingList();
+}
+
+void
+CWorld::Remove(CEntity *ent)
+{
+ if(ent->IsVehicle() || ent->IsPed())
+ DMAudio.SetEntityStatus(((CPhysical*)ent)->m_audioEntityId, false);
+
+ if(ent->bIsBIGBuilding)
+ ms_bigBuildingsList[ent->m_level].RemoveItem(ent);
+ else
+ ent->Remove();
+
+ if(ent->IsBuilding() || ent->IsDummy())
+ return;
+
+ if(!ent->bIsStatic)
+ ((CPhysical*)ent)->RemoveFromMovingList();
+}
+
+void
+CWorld::ClearScanCodes(void)
+{
+ CPtrNode *node;
+ for(int i = 0; i < NUMSECTORS_Y; i++)
+ 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;
+ }
+}
+
+bool
+CWorld::CameraToIgnoreThisObject(CEntity *ent)
+{
+ if(CGarages::IsModelIndexADoor(ent->GetModelIndex()))
+ return false;
+ return ((CObject*)ent)->m_bCameraToAvoidThisObject != 1;
+}
+
+bool
+CWorld::ProcessLineOfSight(const CVector &point1, const CVector &point2, CColPoint &point, CEntity *&entity, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects)
+{
+ int x, xstart, xend;
+ int y, ystart, yend;
+ int y1, y2;
+ float dist;
+
+ AdvanceCurrentScanCode();
+
+ entity = nil;
+ dist = 1.0f;
+
+ xstart = GetSectorIndexX(point1.x);
+ ystart = GetSectorIndexX(point1.y);
+ xend = GetSectorIndexX(point2.x);
+ yend = GetSectorIndexX(point2.y);
+
+#define LOSARGS CColLine(point1, point2), point, dist, entity, checkBuildings, checkVehicles, checkPeds, checkObjects, checkDummies, ignoreSeeThrough, ignoreSomeObjects
+
+ if(xstart == xend && ystart == yend){
+ // Only one sector
+ return ProcessLineOfSightSector(*GetSector(xstart, ystart), LOSARGS);
+ }else if(xstart == xend){
+ // Only step in y
+ if(ystart < yend)
+ for(y = ystart; y <= yend; y++)
+ ProcessLineOfSightSector(*GetSector(xstart, y), LOSARGS);
+ else
+ for(y = ystart; y >= yend; y--)
+ ProcessLineOfSightSector(*GetSector(xstart, y), LOSARGS);
+ return dist < 1.0f;
+ }else if(ystart == yend){
+ // Only step in x
+ if(xstart < xend)
+ for(x = xstart; x <= xend; x++)
+ ProcessLineOfSightSector(*GetSector(x, ystart), LOSARGS);
+ else
+ for(x = xstart; x >= xend; x--)
+ ProcessLineOfSightSector(*GetSector(x, ystart), LOSARGS);
+ return dist < 1.0f;
+ }else{
+ if(point1.x < point2.x){
+ // Step from left to right
+ float m = (point2.y - point1.y) / (point2.x - point1.x);
+
+ y1 = ystart;
+ y2 = GetSectorIndexY((GetWorldX(xstart+1) - point1.x)*m + point1.y);
+ if(y1 < y2)
+ for(y = y1; y <= y2; y++)
+ ProcessLineOfSightSector(*GetSector(xstart, y), LOSARGS);
+ else
+ for(y = y1; y >= y2; y--)
+ ProcessLineOfSightSector(*GetSector(xstart, y), LOSARGS);
+
+ for(x = xstart+1; x < xend; x++){
+ y1 = y2;
+ y2 = GetSectorIndexY((GetWorldX(x+1) - point1.x)*m + point1.y);
+ if(y1 < y2)
+ for(y = y1; y <= y2; y++)
+ ProcessLineOfSightSector(*GetSector(x, y), LOSARGS);
+ else
+ for(y = y1; y >= y2; y--)
+ ProcessLineOfSightSector(*GetSector(x, y), LOSARGS);
+ }
+
+ y1 = y2;
+ y2 = yend;
+ if(y1 < y2)
+ for(y = y1; y <= y2; y++)
+ ProcessLineOfSightSector(*GetSector(xend, y), LOSARGS);
+ else
+ for(y = y1; y >= y2; y--)
+ ProcessLineOfSightSector(*GetSector(xend, y), LOSARGS);
+ }else{
+ // Step from right to left
+ float m = (point2.y - point1.y) / (point2.x - point1.x);
+
+ y1 = ystart;
+ y2 = GetSectorIndexY((GetWorldX(xstart) - point1.x)*m + point1.y);
+ if(y1 < y2)
+ for(y = y1; y <= y2; y++)
+ ProcessLineOfSightSector(*GetSector(xstart, y), LOSARGS);
+ else
+ for(y = y1; y >= y2; y--)
+ ProcessLineOfSightSector(*GetSector(xstart, y), LOSARGS);
+
+ for(x = xstart-1; x > xend; x--){
+ y1 = y2;
+ y2 = GetSectorIndexY((GetWorldX(x) - point1.x)*m + point1.y);
+ if(y1 < y2)
+ for(y = y1; y <= y2; y++)
+ ProcessLineOfSightSector(*GetSector(x, y), LOSARGS);
+ else
+ for(y = y1; y >= y2; y--)
+ ProcessLineOfSightSector(*GetSector(x, y), LOSARGS);
+ }
+
+ y1 = y2;
+ y2 = yend;
+ if(y1 < y2)
+ for(y = y1; y <= y2; y++)
+ ProcessLineOfSightSector(*GetSector(xend, y), LOSARGS);
+ else
+ for(y = y1; y >= y2; y--)
+ ProcessLineOfSightSector(*GetSector(xend, y), LOSARGS);
+ }
+ return dist < 1.0f;
+ }
+
+#undef LOSARGS
+}
+
+bool
+CWorld::ProcessLineOfSightSector(CSector &sector, const CColLine &line, CColPoint &point, float &dist, CEntity *&entity, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects)
+{
+ float mindist = dist;
+ bool deadPeds = !!bIncludeDeadPeds;
+ bIncludeDeadPeds = false;
+
+ if(checkBuildings){
+ ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_BUILDINGS], line, point, mindist, entity, ignoreSeeThrough);
+ ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_BUILDINGS_OVERLAP], line, point, mindist, entity, ignoreSeeThrough);
+ }
+
+ if(checkVehicles){
+ ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_VEHICLES], line, point, mindist, entity, ignoreSeeThrough);
+ ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_VEHICLES_OVERLAP], line, point, mindist, entity, ignoreSeeThrough);
+ }
+
+ if(checkPeds){
+ if(deadPeds)
+ bIncludeDeadPeds = true;
+ ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_PEDS], line, point, mindist, entity, ignoreSeeThrough);
+ ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_PEDS_OVERLAP], line, point, mindist, entity, ignoreSeeThrough);
+ bIncludeDeadPeds = false;
+ }
+
+ if(checkObjects){
+ ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_OBJECTS], line, point, mindist, entity, ignoreSeeThrough, ignoreSomeObjects);
+ ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_OBJECTS_OVERLAP], line, point, mindist, entity, ignoreSeeThrough, ignoreSomeObjects);
+ }
+
+ if(checkDummies){
+ ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_DUMMIES], line, point, mindist, entity, ignoreSeeThrough);
+ ProcessLineOfSightSectorList(sector.m_lists[ENTITYLIST_DUMMIES_OVERLAP], line, point, mindist, entity, ignoreSeeThrough);
+ }
+
+ bIncludeDeadPeds = deadPeds;
+
+ if(mindist < dist){
+ dist = mindist;
+ return true;
+ }else
+ return false;
+}
+
+bool
+CWorld::ProcessLineOfSightSectorList(CPtrList &list, const CColLine &line, CColPoint &point, float &dist, CEntity *&entity, bool ignoreSeeThrough, bool ignoreSomeObjects)
+{
+ bool deadPeds = false;
+ float mindist = dist;
+ CPtrNode *node;
+ CEntity *e;
+ CColModel *colmodel;
+
+ if(list.first && bIncludeDeadPeds && ((CEntity*)list.first->item)->IsPed())
+ deadPeds = true;
+
+ 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))){
+ colmodel = nil;
+ e->m_scanCode = GetCurrentScanCode();
+
+ if(e->IsPed()){
+ if(e->bUsesCollision ||
+ deadPeds && ((CPed*)e)->m_nPedState == PED_DEAD){
+ if(((CPed*)e)->UseGroundColModel())
+ colmodel = &CTempColModels::ms_colModelPedGroundHit;
+ else
+ colmodel = ((CPedModelInfo*)CModelInfo::GetModelInfo(e->GetModelIndex()))->GetHitColModel();
+ }else
+ colmodel = nil;
+ }else if(e->bUsesCollision)
+ colmodel = CModelInfo::GetModelInfo(e->GetModelIndex())->GetColModel();
+
+ if(colmodel &&
+ CCollision::ProcessLineOfSight(line, e->GetMatrix(), *colmodel, point, dist, ignoreSeeThrough))
+ entity = e;
+ }
+ }
+
+ if(mindist < dist){
+ dist = mindist;
+ return true;
+ }else
+ return false;
+}
+
+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)
+{
+ AdvanceCurrentScanCode();
+ CVector point2(point1.x, point1.y, z2);
+ return CWorld::ProcessVerticalLineSector(*GetSector(GetSectorIndexX(point1.x), GetSectorIndexX(point1.y)),
+ CColLine(point1, point2), point, entity,
+ checkBuildings, checkVehicles, checkPeds, checkObjects, checkDummies, ignoreSeeThrough, poly);
+}
+
+bool
+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)
+{
+ float mindist = 1.0f;
+
+ 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);
+ }
+
+ 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);
+ }
+
+ 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);
+ }
+
+ 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);
+ }
+
+ 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);
+ }
+
+ return mindist < 1.0f;
+}
+
+bool
+CWorld::ProcessVerticalLineSectorList(CPtrList &list, const CColLine &line, CColPoint &point, float &dist, CEntity *&entity, bool ignoreSeeThrough, CStoredCollPoly *poly)
+{
+ float mindist = dist;
+ CPtrNode *node;
+ CEntity *e;
+ CColModel *colmodel;
+
+ for(node = list.first; node; node = node->next){
+ e = (CEntity*)node->item;
+ if(e->m_scanCode != GetCurrentScanCode() &&
+ e->bUsesCollision){
+ e->m_scanCode = GetCurrentScanCode();
+
+ colmodel = CModelInfo::GetModelInfo(e->GetModelIndex())->GetColModel();
+ if(CCollision::ProcessVerticalLine(line, e->GetMatrix(), *colmodel, point, dist, ignoreSeeThrough, poly))
+ entity = e;
+ }
+ }
+
+ if(mindist < dist){
+ dist = mindist;
+ return true;
+ }else
+ return false;
+}
+
+bool
+CWorld::GetIsLineOfSightClear(const CVector &point1, const CVector &point2, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects)
+{
+ int x, xstart, xend;
+ int y, ystart, yend;
+ int y1, y2;
+
+ AdvanceCurrentScanCode();
+
+ xstart = GetSectorIndexX(point1.x);
+ ystart = GetSectorIndexX(point1.y);
+ xend = GetSectorIndexX(point2.x);
+ yend = GetSectorIndexX(point2.y);
+
+#define LOSARGS CColLine(point1, point2), checkBuildings, checkVehicles, checkPeds, checkObjects, checkDummies, ignoreSeeThrough, ignoreSomeObjects
+
+ if(xstart == xend && ystart == yend){
+ // Only one sector
+ return GetIsLineOfSightSectorClear(*GetSector(xstart, ystart), LOSARGS);
+ }else if(xstart == xend){
+ // Only step in y
+ if(ystart < yend){
+ for(y = ystart; y <= yend; y++)
+ if(!GetIsLineOfSightSectorClear(*GetSector(xstart, y), LOSARGS))
+ return false;
+ }else{
+ for(y = ystart; y >= yend; y--)
+ if(!GetIsLineOfSightSectorClear(*GetSector(xstart, y), LOSARGS))
+ return false;
+ }
+ }else if(ystart == yend){
+ // Only step in x
+ if(xstart < xend){
+ for(x = xstart; x <= xend; x++)
+ if(!GetIsLineOfSightSectorClear(*GetSector(x, ystart), LOSARGS))
+ return false;
+ }else{
+ for(x = xstart; x >= xend; x--)
+ if(!GetIsLineOfSightSectorClear(*GetSector(x, ystart), LOSARGS))
+ return false;
+ }
+ }else{
+ if(point1.x < point2.x){
+ // Step from left to right
+ float m = (point2.y - point1.y) / (point2.x - point1.x);
+
+ y1 = ystart;
+ y2 = GetSectorIndexY((GetWorldX(xstart+1) - point1.x)*m + point1.y);
+ if(y1 < y2){
+ for(y = y1; y <= y2; y++)
+ if(!GetIsLineOfSightSectorClear(*GetSector(xstart, y), LOSARGS))
+ return false;
+ }else{
+ for(y = y1; y >= y2; y--)
+ if(!GetIsLineOfSightSectorClear(*GetSector(xstart, y), LOSARGS))
+ return false;
+ }
+
+ for(x = xstart+1; x < xend; x++){
+ y1 = y2;
+ y2 = GetSectorIndexY((GetWorldX(x+1) - point1.x)*m + point1.y);
+ if(y1 < y2){
+ for(y = y1; y <= y2; y++)
+ if(!GetIsLineOfSightSectorClear(*GetSector(x, y), LOSARGS))
+ return false;
+ }else{
+ for(y = y1; y >= y2; y--)
+ if(!GetIsLineOfSightSectorClear(*GetSector(x, y), LOSARGS))
+ return false;
+ }
+ }
+
+ y1 = y2;
+ y2 = yend;
+ if(y1 < y2){
+ for(y = y1; y <= y2; y++)
+ if(!GetIsLineOfSightSectorClear(*GetSector(xend, y), LOSARGS))
+ return false;
+ }else{
+ for(y = y1; y >= y2; y--)
+ if(!GetIsLineOfSightSectorClear(*GetSector(xend, y), LOSARGS))
+ return false;
+ }
+ }else{
+ // Step from right to left
+ float m = (point2.y - point1.y) / (point2.x - point1.x);
+
+ y1 = ystart;
+ y2 = GetSectorIndexY((GetWorldX(xstart) - point1.x)*m + point1.y);
+ if(y1 < y2){
+ for(y = y1; y <= y2; y++)
+ if(!GetIsLineOfSightSectorClear(*GetSector(xstart, y), LOSARGS))
+ return false;
+ }else{
+ for(y = y1; y >= y2; y--)
+ if(!GetIsLineOfSightSectorClear(*GetSector(xstart, y), LOSARGS))
+ return false;
+ }
+
+ for(x = xstart-1; x > xend; x--){
+ y1 = y2;
+ y2 = GetSectorIndexY((GetWorldX(x) - point1.x)*m + point1.y);
+ if(y1 < y2){
+ for(y = y1; y <= y2; y++)
+ if(!GetIsLineOfSightSectorClear(*GetSector(x, y), LOSARGS))
+ return false;
+ }else{
+ for(y = y1; y >= y2; y--)
+ if(!GetIsLineOfSightSectorClear(*GetSector(x, y), LOSARGS))
+ return false;
+ }
+ }
+
+ y1 = y2;
+ y2 = yend;
+ if(y1 < y2){
+ for(y = y1; y <= y2; y++)
+ if(!GetIsLineOfSightSectorClear(*GetSector(xend, y), LOSARGS))
+ return false;
+ }else{
+ for(y = y1; y >= y2; y--)
+ if(!GetIsLineOfSightSectorClear(*GetSector(xend, y), LOSARGS))
+ return false;
+ }
+ }
+ }
+
+ return true;
+
+#undef LOSARGS
+}
+
+bool
+CWorld::GetIsLineOfSightSectorClear(CSector &sector, const CColLine &line, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects)
+{
+ if(checkBuildings){
+ if(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_BUILDINGS], line, ignoreSeeThrough))
+ return false;
+ if(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_BUILDINGS_OVERLAP], line, ignoreSeeThrough))
+ return false;
+ }
+
+ if(checkVehicles){
+ if(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_VEHICLES], line, ignoreSeeThrough))
+ return false;
+ if(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_VEHICLES_OVERLAP], line, ignoreSeeThrough))
+ return false;
+ }
+
+ if(checkPeds){
+ if(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_PEDS], line, ignoreSeeThrough))
+ return false;
+ if(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_PEDS_OVERLAP], line, ignoreSeeThrough))
+ return false;
+ }
+
+ if(checkObjects){
+ if(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_OBJECTS], line, ignoreSeeThrough, ignoreSomeObjects))
+ return false;
+ if(!GetIsLineOfSightSectorListClear(sector.m_lists[ENTITYLIST_OBJECTS_OVERLAP], line, ignoreSeeThrough, ignoreSomeObjects))
+ return false;
+ }
+
+ if(checkDummies){
+ 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
+CWorld::GetIsLineOfSightSectorListClear(CPtrList &list, const CColLine &line, bool ignoreSeeThrough, bool ignoreSomeObjects)
+{
+ CPtrNode *node;
+ CEntity *e;
+ CColModel *colmodel;
+
+ for(node = list.first; node; node = node->next){
+ e = (CEntity*)node->item;
+ if(e->m_scanCode != GetCurrentScanCode() &&
+ e->bUsesCollision){
+
+ e->m_scanCode = GetCurrentScanCode();
+
+ if(e != pIgnoreEntity &&
+ !(ignoreSomeObjects && CameraToIgnoreThisObject(e))){
+
+ colmodel = CModelInfo::GetModelInfo(e->GetModelIndex())->GetColModel();
+
+ if(CCollision::TestLineOfSight(line, e->GetMatrix(), *colmodel, ignoreSeeThrough))
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+float
+CWorld::FindGroundZForCoord(float x, float y)
+{
+ CColPoint point;
+ CEntity *ent;
+ if(ProcessVerticalLine(CVector(x, y, 1000.0f), -1000.0f, point, ent, true, false, false, false, true, false, nil))
+ return point.point.z;
+ else
+ return 20.0f;
+}
+
+float
+CWorld::FindGroundZFor3DCoord(float x, float y, float z, bool *found)
+{
+ CColPoint point;
+ CEntity *ent;
+ if(ProcessVerticalLine(CVector(x, y, z), -1000.0f, point, ent, true, false, false, false, false, false, nil)){
+ if(found)
+ *found = true;
+ return point.point.z;
+ }else{
+ if(found)
+ *found = false;
+ return 0.0f;
+ }
+}
+
+float
+CWorld::FindRoofZFor3DCoord(float x, float y, float z, bool *found)
+{
+ CColPoint point;
+ CEntity *ent;
+ if(ProcessVerticalLine(CVector(x, y, z), 1000.0f, point, ent, true, false, false, false, true, false, nil)){
+ if(found)
+ *found = true;
+ return point.point.z;
+ }else{
+ if(found == nil)
+ printf("THERE IS NO MAP BELOW THE FOLLOWING COORS:%f %f %f. (FindGroundZFor3DCoord)\n", x, y, z);
+ if(found)
+ *found = false;
+ return 20.0f;
+ }
+}
+
+CPlayerPed*
+FindPlayerPed(void)
+{
+ return CWorld::Players[CWorld::PlayerInFocus].m_pPed;
+}
+
+CVehicle*
+FindPlayerVehicle(void)
+{
+ CPlayerPed *ped = CWorld::Players[CWorld::PlayerInFocus].m_pPed;
+ if(ped->bInVehicle && ped->m_pMyVehicle)
+ return ped->m_pMyVehicle;
+ else
+ return nil;
+}
+
+CVehicle*
+FindPlayerTrain(void)
+{
+ if(FindPlayerVehicle() && FindPlayerVehicle()->IsTrain())
+ return FindPlayerVehicle();
+ else
+ return nil;
+}
+
+CEntity*
+FindPlayerEntity(void)
+{
+ CPlayerPed *ped = CWorld::Players[CWorld::PlayerInFocus].m_pPed;
+ if(ped->bInVehicle && ped->m_pMyVehicle)
+ return ped->m_pMyVehicle;
+ else
+ return ped;
+}
+
+CVector
+FindPlayerCoors(void)
+{
+ CPlayerPed *ped = CWorld::Players[CWorld::PlayerInFocus].m_pPed;
+ if(ped->bInVehicle && ped->m_pMyVehicle)
+ return ped->m_pMyVehicle->GetPosition();
+ else
+ return ped->GetPosition();
+}
+
+CVector&
+FindPlayerSpeed(void)
+{
+ CPlayerPed *ped = CWorld::Players[CWorld::PlayerInFocus].m_pPed;
+ if(ped->bInVehicle && ped->m_pMyVehicle)
+ return ped->m_pMyVehicle->m_vecMoveSpeed;
+ else
+ return ped->m_vecMoveSpeed;
+}
+
+CVector&
+FindPlayerCentreOfWorld(int32 player)
+{
+ if(CCarCtrl::bCarsGeneratedAroundCamera)
+ return TheCamera.GetPosition();
+ if(CWorld::Players[player].m_pRemoteVehicle)
+ return CWorld::Players[player].m_pRemoteVehicle->GetPosition();
+ if(FindPlayerVehicle())
+ return FindPlayerVehicle()->GetPosition();
+ return CWorld::Players[player].m_pPed->GetPosition();
+}
+
+CVector&
+FindPlayerCentreOfWorld_NoSniperShift(void)
+{
+ if(CCarCtrl::bCarsGeneratedAroundCamera)
+ return TheCamera.GetPosition();
+ if(CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle)
+ return CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle->GetPosition();
+ if(FindPlayerVehicle())
+ return FindPlayerVehicle()->GetPosition();
+ return CWorld::Players[CWorld::PlayerInFocus].m_pPed->GetPosition();
+}
+
+float
+FindPlayerHeading(void)
+{
+ if(CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle)
+ return CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle->GetForward().Heading();
+ if(FindPlayerVehicle())
+ return FindPlayerVehicle()->GetForward().Heading();
+ return CWorld::Players[CWorld::PlayerInFocus].m_pPed->GetForward().Heading();
+}
+
+STARTPATCHES
+ InjectHook(0x4AE930, CWorld::Add, PATCH_JUMP);
+ InjectHook(0x4AE9D0, CWorld::Remove, PATCH_JUMP);
+ InjectHook(0x4B1F60, CWorld::ClearScanCodes, PATCH_JUMP);
+ InjectHook(0x4AF970, CWorld::ProcessLineOfSight, PATCH_JUMP);
+ InjectHook(0x4B0A80, CWorld::ProcessLineOfSightSector, PATCH_JUMP);
+ InjectHook(0x4B0C70, CWorld::ProcessLineOfSightSectorList, PATCH_JUMP);
+ InjectHook(0x4B0DE0, CWorld::ProcessVerticalLine, PATCH_JUMP);
+ InjectHook(0x4B0EF0, CWorld::ProcessVerticalLineSector, PATCH_JUMP);
+ InjectHook(0x4B1090, CWorld::ProcessVerticalLineSectorList, PATCH_JUMP);
+ InjectHook(0x4AEAA0, CWorld::GetIsLineOfSightClear, PATCH_JUMP);
+ InjectHook(0x4B2000, CWorld::GetIsLineOfSightSectorClear, PATCH_JUMP);
+ InjectHook(0x4B2160, CWorld::GetIsLineOfSightSectorListClear, PATCH_JUMP);
+
+ InjectHook(0x4B3A80, CWorld::FindGroundZForCoord, PATCH_JUMP);
+ InjectHook(0x4B3AE0, CWorld::FindGroundZFor3DCoord, PATCH_JUMP);
+ InjectHook(0x4B3B50, CWorld::FindRoofZFor3DCoord, PATCH_JUMP);
+ENDPATCHES