summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md2
-rw-r--r--src/Clock.h8
-rw-r--r--src/CullZones.cpp24
-rw-r--r--src/Frontend.cpp2
-rw-r--r--src/Pad.cpp8
-rw-r--r--src/Radar.cpp36
-rw-r--r--src/Radar.h2
-rw-r--r--src/Streaming.cpp390
-rw-r--r--src/Streaming.h9
-rw-r--r--src/Wanted.cpp33
-rw-r--r--src/Wanted.h82
-rw-r--r--src/animation/RpAnimBlend.cpp2
-rw-r--r--src/config.h8
-rw-r--r--src/control/PathFind.cpp2
-rw-r--r--src/control/PathFind.h1
-rw-r--r--src/entities/CopPed.h63
-rw-r--r--src/entities/CutsceneObject.cpp2
-rw-r--r--src/entities/Entity.cpp18
-rw-r--r--src/entities/Entity.h16
-rw-r--r--src/entities/Ped.cpp22
-rw-r--r--src/entities/Ped.h4
-rw-r--r--src/main.cpp9
-rw-r--r--src/modelinfo/ModelInfo.cpp7
-rw-r--r--src/modelinfo/ModelInfo.h2
-rw-r--r--src/re3.cpp140
-rw-r--r--src/render/Hud.cpp220
-rw-r--r--src/render/Hud.h16
-rw-r--r--src/render/Renderer.cpp10
28 files changed, 904 insertions, 234 deletions
diff --git a/README.md b/README.md
index d2dcb4ac..90671822 100644
--- a/README.md
+++ b/README.md
@@ -182,5 +182,5 @@ but here are some observations:
Here you can find a list of variables that you might need to set in windows:
```
"GTA_III_RE_DIR" * path to "gta3_re" game folder usually where this plugin run.
-"GTA_III_DIR)" * path to "GTAIII" game folder.
+"GTA_III_DIR" * path to "GTAIII" game folder.
```
diff --git a/src/Clock.h b/src/Clock.h
index 0b6ba304..e11b2293 100644
--- a/src/Clock.h
+++ b/src/Clock.h
@@ -21,7 +21,11 @@ public:
static void StoreClock(void);
static void RestoreClock(void);
- static int8 GetHours(void) { return ms_nGameClockHours; }
- static int8 GetMinutes(void) { return ms_nGameClockMinutes; }
+ static uint8 GetHours(void) { return ms_nGameClockHours; }
+ static uint8 GetMinutes(void) { return ms_nGameClockMinutes; }
static int16 GetSeconds(void) { return ms_nGameClockSeconds; }
+
+
+ static uint8 &GetHoursRef(void) { return ms_nGameClockHours; }
+ static uint8 &GetMinutesRef(void) { return ms_nGameClockMinutes; }
};
diff --git a/src/CullZones.cpp b/src/CullZones.cpp
index 76052351..f89d8256 100644
--- a/src/CullZones.cpp
+++ b/src/CullZones.cpp
@@ -233,10 +233,10 @@ CCullZone::DoStuffLeavingZone_OneBuilding(uint16 i)
int j;
if(i < 6000){
- CPools::GetBuildingPool()->GetSlot(i)->m_bZoneCulled = false;
+ CPools::GetBuildingPool()->GetSlot(i)->bZoneCulled = false;
bb = CCullZones::aPointersToBigBuildingsForBuildings[i];
if(bb != -1)
- CPools::GetBuildingPool()->GetSlot(bb)->m_bZoneCulled = false;
+ CPools::GetBuildingPool()->GetSlot(bb)->bZoneCulled = false;
}else{
i -= 6000;
for(j = 0; j < 3; j++)
@@ -251,11 +251,11 @@ CCullZone::DoStuffLeavingZone_OneTreadableBoth(uint16 i)
int j;
if(i < 6000){
- CPools::GetTreadablePool()->GetSlot(i)->m_bZoneCulled = false;
- CPools::GetTreadablePool()->GetSlot(i)->m_bZoneCulled2 = false;
+ CPools::GetTreadablePool()->GetSlot(i)->bZoneCulled = false;
+ CPools::GetTreadablePool()->GetSlot(i)->bZoneCulled2 = false;
bb = CCullZones::aPointersToBigBuildingsForTreadables[i];
if(bb != -1)
- CPools::GetBuildingPool()->GetSlot(bb)->m_bZoneCulled = false;
+ CPools::GetBuildingPool()->GetSlot(bb)->bZoneCulled = false;
}else{
i -= 6000;
for(j = 0; j < 3; j++)
@@ -283,10 +283,10 @@ CCullZone::DoStuffEnteringZone_OneBuilding(uint16 i)
int j;
if(i < 6000){
- CPools::GetBuildingPool()->GetSlot(i)->m_bZoneCulled = true;
+ CPools::GetBuildingPool()->GetSlot(i)->bZoneCulled = true;
bb = CCullZones::aPointersToBigBuildingsForBuildings[i];
if(bb != -1)
- CPools::GetBuildingPool()->GetSlot(bb)->m_bZoneCulled = true;
+ CPools::GetBuildingPool()->GetSlot(bb)->bZoneCulled = true;
}else{
i -= 6000;
for(j = 0; j < 3; j++)
@@ -301,11 +301,11 @@ CCullZone::DoStuffEnteringZone_OneTreadablePlus10m(uint16 i)
int j;
if(i < 6000){
- CPools::GetTreadablePool()->GetSlot(i)->m_bZoneCulled = true;;
- CPools::GetTreadablePool()->GetSlot(i)->m_bZoneCulled2 = true;;
+ CPools::GetTreadablePool()->GetSlot(i)->bZoneCulled = true;;
+ CPools::GetTreadablePool()->GetSlot(i)->bZoneCulled2 = true;;
bb = CCullZones::aPointersToBigBuildingsForTreadables[i];
if(bb != -1)
- CPools::GetBuildingPool()->GetSlot(bb)->m_bZoneCulled = true;
+ CPools::GetBuildingPool()->GetSlot(bb)->bZoneCulled = true;
}else{
i -= 6000;
for(j = 0; j < 3; j++)
@@ -320,10 +320,10 @@ CCullZone::DoStuffEnteringZone_OneTreadable(uint16 i)
int j;
if(i < 6000){
- CPools::GetTreadablePool()->GetSlot(i)->m_bZoneCulled = true;;
+ CPools::GetTreadablePool()->GetSlot(i)->bZoneCulled = true;;
bb = CCullZones::aPointersToBigBuildingsForTreadables[i];
if(bb != -1)
- CPools::GetBuildingPool()->GetSlot(bb)->m_bZoneCulled = true;
+ CPools::GetBuildingPool()->GetSlot(bb)->bZoneCulled = true;
}else{
i -= 6000;
for(j = 0; j < 3; j++)
diff --git a/src/Frontend.cpp b/src/Frontend.cpp
index de9e8a65..8eff0324 100644
--- a/src/Frontend.cpp
+++ b/src/Frontend.cpp
@@ -906,7 +906,7 @@ void CMenuManager::LoadAllTextures()
CFileMgr::SetDir("");
CTimer::Stop();
- CStreaming::MakeSpaceFor(716800);
+ CStreaming::MakeSpaceFor(700 * 1024);
CStreaming::ImGonnaUseStreamingMemory();
CTxdStore::PushCurrentTxd();
diff --git a/src/Pad.cpp b/src/Pad.cpp
index 61b7ed06..e6f36efd 100644
--- a/src/Pad.cpp
+++ b/src/Pad.cpp
@@ -1677,11 +1677,11 @@ int16 CPad::LookAroundLeftRight(void)
float axis = GetPad(0)->NewState.RightStickX;
if ( fabs(axis) > 85 && !GetLookBehindForPed() )
- return (int16) ( (axis + ( axis > 0 ) ? -85 : 85)
+ return (int16) ( (axis + ( ( axis > 0 ) ? -85 : 85) )
* (127.0f / 32.0f) ); // 3.96875f
else if ( TheCamera.Cams[0].Using3rdPersonMouseCam() && fabs(axis) > 10 )
- return (int16) ( (axis + ( axis > 0 ) ? -10 : 10)
+ return (int16) ( (axis + ( ( axis > 0 ) ? -10 : 10) )
* (127.0f / 64.0f) ); // 1.984375f
return 0;
@@ -1692,11 +1692,11 @@ int16 CPad::LookAroundUpDown(void)
int16 axis = GetPad(0)->NewState.RightStickY;
if ( abs(axis) > 85 && !GetLookBehindForPed() )
- return (int16) ( (axis + ( axis > 0 ) ? -85 : 85)
+ return (int16) ( (axis + ( ( axis > 0 ) ? -85 : 85) )
* (127.0f / 32.0f) ); // 3.96875f
else if ( TheCamera.Cams[0].Using3rdPersonMouseCam() && abs(axis) > 40 )
- return (int16) ( (axis + ( axis > 0 ) ? -40 : 40)
+ return (int16) ( (axis + ( ( axis > 0 ) ? -40 : 40) )
* (127.0f / 64.0f) ); // 1.984375f
return 0;
diff --git a/src/Radar.cpp b/src/Radar.cpp
index 1b6ca527..71f9aacd 100644
--- a/src/Radar.cpp
+++ b/src/Radar.cpp
@@ -645,7 +645,7 @@ int32 CRadar::GetRadarTraceColour(int32 color, bool bright)
}
#endif
-#if 0
+#if 1
WRAPPER void CRadar::Initialise() { EAXJMP(0x4A3EF0); }
#else
void CRadar::Initialise()
@@ -671,8 +671,8 @@ float CRadar::LimitRadarPoint(CVector2D &point)
}
#endif
-#if 0
-WRAPPER void CRadar::LoadAllRadarBlips() { EAXJMP(0x4A6F30); }
+#if 1
+WRAPPER void CRadar::LoadAllRadarBlips(int32) { EAXJMP(0x4A6F30); }
#else
void CRadar::LoadAllRadarBlips(int32)
{
@@ -680,7 +680,7 @@ void CRadar::LoadAllRadarBlips(int32)
}
#endif
-#if 0
+#if 1
WRAPPER void CRadar::LoadTextures() { EAXJMP(0x4A4030); }
#else
void CRadar::LoadTextures()
@@ -689,8 +689,8 @@ void CRadar::LoadTextures()
}
#endif
-#if 0
-WRAPPER void CRadar::RemoveRadarSections() { EAXJMP(0x00); }
+#if 1
+WRAPPER void CRadar::RemoveRadarSections() { EAXJMP(0x4A60E0); }
#else
void CRadar::RemoveRadarSections()
{
@@ -718,8 +718,8 @@ void CRadar::RequestMapSection(int32 x, int32 y)
}
#endif
-#if 0
-WRAPPER void CRadar::SaveAllRadarBlips(int32) { EAXJMP(0x00); }
+#if 1
+WRAPPER void CRadar::SaveAllRadarBlips(int32) { EAXJMP(0x4A6E30); }
#else
void CRadar::SaveAllRadarBlips(int32)
{
@@ -727,8 +727,8 @@ void CRadar::SaveAllRadarBlips(int32)
}
#endif
-#if 0
-WRAPPER void CRadar::SetBlipSprite(int32, int32) { EAXJMP(0x00); }
+#if 1
+WRAPPER void CRadar::SetBlipSprite(int32, int32) { EAXJMP(0x4A5840); }
#else
void CRadar::SetBlipSprite(int32 i, int32 icon)
{
@@ -736,8 +736,8 @@ void CRadar::SetBlipSprite(int32 i, int32 icon)
}
#endif
-#if 0
-WRAPPER void CRadar::SetCoordBlip(int32, CVector, int32) { EAXJMP(0x00); }
+#if 1
+WRAPPER int CRadar::SetCoordBlip(int32, CVector, int32) { EAXJMP(0x4A5590); }
#else
int CRadar::SetCoordBlip(int32 type, CVector pos, int32 flag)
{
@@ -745,8 +745,8 @@ int CRadar::SetCoordBlip(int32 type, CVector pos, int32 flag)
}
#endif
-#if 0
-WRAPPER void CRadar::SetEntityBlip(int32 type, CVector pos, int32 color, int32 flag) { EAXJMP(0x00); }
+#if 1
+WRAPPER int CRadar::SetEntityBlip(int32 type, CVector pos, int32 color, int32 flag) { EAXJMP(0x4A5640); }
#else
int CRadar::SetEntityBlip(int32 type, CVector pos, int32 color, int32 flag)
{
@@ -815,7 +815,7 @@ void CRadar::ShowRadarTrace(float x, float y, uint32 size, uint32 red, uint32 gr
}
#endif
-#if 0
+#if 1
WRAPPER void CRadar::Shutdown() { EAXJMP(0x4A3F60); }
#else
void CRadar::Shutdown()
@@ -824,10 +824,10 @@ void CRadar::Shutdown()
}
#endif
-#if 0
-WRAPPER void CRadar::StreamRadarSections() { EAXJMP(0x4A6B60); }
+#if 1
+WRAPPER void CRadar::StreamRadarSections(const CVector &posn) { EAXJMP(0x4A6B60); }
#else
-void CRadar::StreamRadarSections(CVector posn)
+void CRadar::StreamRadarSections(const CVector &posn)
{
}
diff --git a/src/Radar.h b/src/Radar.h
index 5943498f..e5396a50 100644
--- a/src/Radar.h
+++ b/src/Radar.h
@@ -131,7 +131,7 @@ public:
static void ShowRadarMarker(CVector pos, int16 color, float radius);
static void ShowRadarTrace(float x, float y, uint32 size, uint32 red, uint32 green, uint32 blue, uint32 alpha);
static void Shutdown();
- static void StreamRadarSections(CVector posn);
+ static void StreamRadarSections(const CVector &posn);
static void StreamRadarSections(int32 x, int32 y);
static void TransformRealWorldToTexCoordSpace(CVector2D &out, const CVector2D &in, int32 x, int32 y);
static void TransformRadarPointToRealWorldSpace(CVector2D &out, const CVector2D &in);
diff --git a/src/Streaming.cpp b/src/Streaming.cpp
index 967b3ec8..7d633d90 100644
--- a/src/Streaming.cpp
+++ b/src/Streaming.cpp
@@ -15,6 +15,10 @@
#include "Entity.h"
#include "FileMgr.h"
#include "FileLoader.h"
+#include "Zones.h"
+#include "CullZones.h"
+#include "Radar.h"
+#include "Camera.h"
#include "CdStream.h"
#include "Streaming.h"
@@ -46,7 +50,7 @@ uint16 &CStreaming::ms_loadedGangs = *(uint16*)0x95CC60;
int32 *CStreaming::ms_imageOffsets = (int32*)0x6E60A0;
int32 &CStreaming::ms_lastImageRead = *(int32*)0x880E2C;
int32 &CStreaming::ms_imageSize = *(int32*)0x8F1A34;
-int32 &CStreaming::ms_memoryAvailable = *(int32*)0x880F8C;
+uint32 &CStreaming::ms_memoryAvailable = *(uint32*)0x880F8C;
int32 &desiredNumVehiclesLoaded = *(int32*)0x5EC194;
@@ -61,9 +65,6 @@ int32 &islandLODcomSub = *(int32*)0x6212D0;
int32 &islandLODsubInd = *(int32*)0x6212D4;
int32 &islandLODsubCom = *(int32*)0x6212D8;
-WRAPPER void CStreaming::MakeSpaceFor(int32 size) { EAXJMP(0x409B70); }
-WRAPPER void CStreaming::LoadScene(const CVector &pos) { EAXJMP(0x40A6D0); }
-
bool
CStreamingInfo::GetCdPosnAndSize(uint32 &posn, uint32 &size)
{
@@ -187,6 +188,7 @@ CStreaming::Init(void)
debug("Streaming buffer size is %d sectors", ms_streamingBufferSize);
// PC only, figure out how much memory we got
+#ifdef GTA_PC
#define MB (1024*1024)
extern DWORD &_dwMemAvailPhys;
ms_memoryAvailable = (_dwMemAvailPhys - 10*MB)/2;
@@ -197,6 +199,7 @@ CStreaming::Init(void)
desiredNumVehiclesLoaded = MAXVEHICLESLOADED;
debug("Memory allocated to Streaming is %dMB", ms_memoryAvailable/MB);
#undef MB
+#endif
// find island LODs
@@ -243,14 +246,22 @@ CStreaming::LoadCdDirectory(void)
char dirname[132];
int i;
- // PC specific stuff
+#ifdef GTA_PC
ms_imageOffsets[0] = 0;
- for(i = 1; i < NUMCDIMAGES; i++)
- ms_imageOffsets[i] = -1;
+ ms_imageOffsets[1] = -1;
+ ms_imageOffsets[2] = -1;
+ ms_imageOffsets[3] = -1;
+ ms_imageOffsets[4] = -1;
+ ms_imageOffsets[5] = -1;
+ ms_imageOffsets[6] = -1;
+ ms_imageOffsets[7] = -1;
+ ms_imageOffsets[8] = -1;
+ ms_imageOffsets[9] = -1;
+ ms_imageOffsets[10] = -1;
+ ms_imageOffsets[11] = -1;
ms_imageSize = GetGTA3ImgSize();
-
// PS2 uses CFileMgr::GetCdFile on all IMG files to fill the array
-
+#endif
i = CdStreamGetNumImages();
while(i-- >= 1){
@@ -1687,7 +1698,7 @@ CStreaming::ProcessEntitiesInSectorList(CPtrList &list, float x, float y, float
continue;
e->m_scanCode = CWorld::GetCurrentScanCode();
- if(!e->m_flagC20 && !e->bIsSubway &&
+ if(!e->bStreamingDontDelete && !e->bIsSubway &&
(!e->IsObject() || ((CObject*)e)->ObjectCreatedBy != TEMP_OBJECT)){
CTimeModelInfo *mi = (CTimeModelInfo*)CModelInfo::GetModelInfo(e->GetModelIndex());
if(mi->m_type != MITYPE_TIME || CClock::GetIsTimeInRange(mi->GetTimeOn(), mi->GetTimeOff())){
@@ -1717,7 +1728,7 @@ CStreaming::ProcessEntitiesInSectorList(CPtrList &list)
continue;
e->m_scanCode = CWorld::GetCurrentScanCode();
- if(!e->m_flagC20 && !e->bIsSubway &&
+ if(!e->bStreamingDontDelete && !e->bIsSubway &&
(!e->IsObject() || ((CObject*)e)->ObjectCreatedBy != TEMP_OBJECT)){
CTimeModelInfo *mi = (CTimeModelInfo*)CModelInfo::GetModelInfo(e->GetModelIndex());
if(mi->m_type != MITYPE_TIME || CClock::GetIsTimeInRange(mi->GetTimeOn(), mi->GetTimeOff()))
@@ -1730,7 +1741,126 @@ CStreaming::ProcessEntitiesInSectorList(CPtrList &list)
void
CStreaming::DeleteFarAwayRwObjects(const CVector &pos)
{
- // TODO
+ int posx, posy;
+ int x, y;
+ int r, i;
+ CSector *sect;
+
+ posx = CWorld::GetSectorIndexX(pos.x);
+ posy = CWorld::GetSectorIndexY(pos.y);
+
+ // Move oldSectorX/Y to new sector and delete RW objects in its "wake" for every step:
+ // O is the old sector, <- is the direction in which we move it,
+ // X are the sectors we delete RW objects from (except we go up to 10)
+ // X
+ // X X
+ // X X X
+ // X X X
+ // <- O X X X
+ // X X X
+ // X X X
+ // X X
+ // X
+
+ while(posx != ms_oldSectorX){
+ if(posx < ms_oldSectorX){
+ for(r = 2; r <= 10; r++){
+ x = ms_oldSectorX + r;
+ if(x < 0)
+ continue;
+ if(x >= NUMSECTORS_X)
+ break;
+
+ for(i = -r; i <= r; i++){
+ y = ms_oldSectorY + i;
+ if(y < 0)
+ continue;
+ if(y >= NUMSECTORS_Y)
+ break;
+
+ sect = CWorld::GetSector(x, y);
+ DeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS]);
+ DeleteRwObjectsInOverlapSectorList(sect->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], ms_oldSectorX, ms_oldSectorY);
+ DeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_OBJECTS]);
+ DeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_DUMMIES]);
+ }
+ }
+ ms_oldSectorX--;
+ }else{
+ for(r = 2; r <= 10; r++){
+ x = ms_oldSectorX - r;
+ if(x < 0)
+ break;
+ if(x >= NUMSECTORS_X)
+ continue;
+
+ for(i = -r; i <= r; i++){
+ y = ms_oldSectorY + i;
+ if(y < 0)
+ continue;
+ if(y >= NUMSECTORS_Y)
+ break;
+
+ sect = CWorld::GetSector(x, y);
+ DeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS]);
+ DeleteRwObjectsInOverlapSectorList(sect->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], ms_oldSectorX, ms_oldSectorY);
+ DeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_OBJECTS]);
+ DeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_DUMMIES]);
+ }
+ }
+ ms_oldSectorX++;
+ }
+ }
+
+ while(posy != ms_oldSectorY){
+ if(posy < ms_oldSectorY){
+ for(r = 2; r <= 10; r++){
+ y = ms_oldSectorY + r;
+ if(y < 0)
+ continue;
+ if(y >= NUMSECTORS_Y)
+ break;
+
+ for(i = -r; i <= r; i++){
+ x = ms_oldSectorX + i;
+ if(x < 0)
+ continue;
+ if(x >= NUMSECTORS_X)
+ break;
+
+ sect = CWorld::GetSector(x, y);
+ DeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS]);
+ DeleteRwObjectsInOverlapSectorList(sect->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], ms_oldSectorX, ms_oldSectorY);
+ DeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_OBJECTS]);
+ DeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_DUMMIES]);
+ }
+ }
+ ms_oldSectorY--;
+ }else{
+ for(r = 2; r <= 10; r++){
+ y = ms_oldSectorY - r;
+ if(y < 0)
+ break;
+ if(y >= NUMSECTORS_Y)
+ continue;
+
+ for(i = -r; i <= r; i++){
+ x = ms_oldSectorX + i;
+ if(x < 0)
+ continue;
+ if(x >= NUMSECTORS_X)
+ break;
+
+ sect = CWorld::GetSector(x, y);
+ DeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS]);
+ DeleteRwObjectsInOverlapSectorList(sect->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], ms_oldSectorX, ms_oldSectorY);
+ DeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_OBJECTS]);
+ DeleteRwObjectsInSectorList(sect->m_lists[ENTITYLIST_DUMMIES]);
+ }
+ }
+ ms_oldSectorY++;
+ }
+ }
}
void
@@ -1776,6 +1906,152 @@ CStreaming::DeleteRwObjectsAfterDeath(const CVector &pos)
}
void
+CStreaming::DeleteRwObjectsBehindCamera(int32 mem)
+{
+ int ix, iy;
+ int x, y;
+ int xmin, xmax, ymin, ymax;
+ int inc;
+ CSector *sect;
+
+ if(ms_memoryUsed < mem)
+ return;
+
+ ix = CWorld::GetSectorIndexX(TheCamera.GetPosition().x);
+ iy = CWorld::GetSectorIndexX(TheCamera.GetPosition().y);
+
+ if(fabs(TheCamera.GetForward().x) > fabs(TheCamera.GetForward().y)){
+ // looking west/east
+
+ ymin = max(iy - 10, 0);
+ ymax = min(iy + 10, NUMSECTORS_Y);
+ assert(ymin <= ymax);
+
+ // Delete a block of sectors that we know is behind the camera
+ if(TheCamera.GetForward().x > 0){
+ // looking east
+ xmax = max(ix - 2, 0);
+ xmin = max(ix - 10, 0);
+ inc = 1;
+ }else{
+ // looking west
+ xmax = min(ix + 2, NUMSECTORS_X);
+ xmin = min(ix + 10, NUMSECTORS_X);
+ inc = -1;
+ }
+ for(y = ymin; y <= ymax; y++){
+ for(x = xmin; x != xmax; x += inc){
+ sect = CWorld::GetSector(x, y);
+ if(DeleteRwObjectsBehindCameraInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS], mem) ||
+ DeleteRwObjectsBehindCameraInSectorList(sect->m_lists[ENTITYLIST_DUMMIES], mem) ||
+ DeleteRwObjectsBehindCameraInSectorList(sect->m_lists[ENTITYLIST_OBJECTS], mem))
+ return;
+ }
+ }
+
+ // Now a block that intersects with the camera's frustum
+ if(TheCamera.GetForward().x > 0){
+ // looking east
+ xmax = max(ix + 10, 0);
+ xmin = max(ix - 2, 0);
+ inc = 1;
+ }else{
+ // looking west
+ xmax = min(ix - 10, NUMSECTORS_X);
+ xmin = min(ix + 2, NUMSECTORS_X);
+ inc = -1;
+ }
+ for(y = ymin; y <= ymax; y++){
+ for(x = xmin; x != xmax; x += inc){
+ sect = CWorld::GetSector(x, y);
+ if(DeleteRwObjectsNotInFrustumInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS], mem) ||
+ DeleteRwObjectsNotInFrustumInSectorList(sect->m_lists[ENTITYLIST_DUMMIES], mem) ||
+ DeleteRwObjectsNotInFrustumInSectorList(sect->m_lists[ENTITYLIST_OBJECTS], mem))
+ return;
+ }
+ }
+
+ if(RemoveReferencedTxds(mem))
+ return;
+
+ // As last resort, delete objects from the last step more aggressively
+ for(y = ymin; y <= ymax; y++){
+ for(x = xmax; x != xmin; x -= inc){
+ sect = CWorld::GetSector(x, y);
+ if(DeleteRwObjectsBehindCameraInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS], mem) ||
+ DeleteRwObjectsBehindCameraInSectorList(sect->m_lists[ENTITYLIST_DUMMIES], mem) ||
+ DeleteRwObjectsBehindCameraInSectorList(sect->m_lists[ENTITYLIST_OBJECTS], mem))
+ return;
+ }
+ }
+ }else{
+ // looking north/south
+
+ xmin = max(ix - 10, 0);
+ xmax = min(ix + 10, NUMSECTORS_X);
+ assert(xmin <= xmax);
+
+ // Delete a block of sectors that we know is behind the camera
+ if(TheCamera.GetForward().y > 0){
+ // looking north
+ ymax = max(iy - 2, 0);
+ ymin = max(iy - 10, 0);
+ inc = 1;
+ }else{
+ // looking south
+ ymax = min(iy + 2, NUMSECTORS_Y);
+ ymin = min(iy + 10, NUMSECTORS_Y);
+ inc = -1;
+ }
+ for(x = xmin; x <= xmax; x++){
+ for(y = ymin; y != ymax; y += inc){
+ sect = CWorld::GetSector(x, y);
+ if(DeleteRwObjectsBehindCameraInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS], mem) ||
+ DeleteRwObjectsBehindCameraInSectorList(sect->m_lists[ENTITYLIST_DUMMIES], mem) ||
+ DeleteRwObjectsBehindCameraInSectorList(sect->m_lists[ENTITYLIST_OBJECTS], mem))
+ return;
+ }
+ }
+
+ // Now a block that intersects with the camera's frustum
+ if(TheCamera.GetForward().y > 0){
+ // looking north
+ ymax = max(iy + 10, 0);
+ ymin = max(iy - 2, 0);
+ inc = 1;
+ }else{
+ // looking south
+ ymax = min(iy - 10, NUMSECTORS_Y);
+ ymin = min(iy + 2, NUMSECTORS_Y);
+ inc = -1;
+ }
+ for(x = xmin; x <= xmax; x++){
+ for(y = ymin; y != ymax; y += inc){
+ sect = CWorld::GetSector(x, y);
+ if(DeleteRwObjectsNotInFrustumInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS], mem) ||
+ DeleteRwObjectsNotInFrustumInSectorList(sect->m_lists[ENTITYLIST_DUMMIES], mem) ||
+ DeleteRwObjectsNotInFrustumInSectorList(sect->m_lists[ENTITYLIST_OBJECTS], mem))
+ return;
+ }
+ }
+
+ if(RemoveReferencedTxds(mem))
+ return;
+
+ // As last resort, delete objects from the last step more aggressively
+ for(x = xmin; x <= xmax; x++){
+ for(y = ymax; y != ymin; y -= inc){
+ sect = CWorld::GetSector(x, y);
+ if(DeleteRwObjectsBehindCameraInSectorList(sect->m_lists[ENTITYLIST_BUILDINGS], mem) ||
+ DeleteRwObjectsBehindCameraInSectorList(sect->m_lists[ENTITYLIST_DUMMIES], mem) ||
+ DeleteRwObjectsBehindCameraInSectorList(sect->m_lists[ENTITYLIST_OBJECTS], mem))
+ return;
+ }
+ }
+ }
+}
+
+void
CStreaming::DeleteRwObjectsInSectorList(CPtrList &list)
{
CPtrNode *node;
@@ -1783,7 +2059,7 @@ CStreaming::DeleteRwObjectsInSectorList(CPtrList &list)
for(node = list.first; node; node = node->next){
e = (CEntity*)node->item;
- if(!e->m_flagC20 && !e->bImBeingRendered)
+ if(!e->bStreamingDontDelete && !e->bImBeingRendered)
e->DeleteRwObject();
}
}
@@ -1796,7 +2072,7 @@ CStreaming::DeleteRwObjectsInOverlapSectorList(CPtrList &list, int32 x, int32 y)
for(node = list.first; node; node = node->next){
e = (CEntity*)node->item;
- if(e->m_rwObject && !e->m_flagC20 && !e->bImBeingRendered){
+ if(e->m_rwObject && !e->bStreamingDontDelete && !e->bImBeingRendered){
// Now this is pretty weird...
if(fabs(CWorld::GetSectorIndexX(e->GetPosition().x) - x) >= 2.0f)
// {
@@ -1810,6 +2086,86 @@ CStreaming::DeleteRwObjectsInOverlapSectorList(CPtrList &list, int32 x, int32 y)
}
}
+bool
+CStreaming::DeleteRwObjectsBehindCameraInSectorList(CPtrList &list, int32 mem)
+{
+ CPtrNode *node;
+ CEntity *e;
+
+ for(node = list.first; node; node = node->next){
+ e = (CEntity*)node->item;
+ if(!e->bStreamingDontDelete && !e->bImBeingRendered &&
+ e->m_rwObject && ms_aInfoForModel[e->GetModelIndex()].m_next){
+ e->DeleteRwObject();
+ if(CModelInfo::GetModelInfo(e->GetModelIndex())->m_refCount == 0){
+ RemoveModel(e->GetModelIndex());
+ if(ms_memoryUsed < mem)
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool
+CStreaming::DeleteRwObjectsNotInFrustumInSectorList(CPtrList &list, int32 mem)
+{
+ CPtrNode *node;
+ CEntity *e;
+
+ for(node = list.first; node; node = node->next){
+ e = (CEntity*)node->item;
+ if(!e->bStreamingDontDelete && !e->bImBeingRendered &&
+ e->m_rwObject && !e->IsVisible() && ms_aInfoForModel[e->GetModelIndex()].m_next){
+ e->DeleteRwObject();
+ if(CModelInfo::GetModelInfo(e->GetModelIndex())->m_refCount == 0){
+ RemoveModel(e->GetModelIndex());
+ if(ms_memoryUsed < mem)
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+void
+CStreaming::MakeSpaceFor(int32 size)
+{
+ // BUG: ms_memoryAvailable can be uninitialized
+ // the code still happens to work in that case because ms_memoryAvailable is unsigned
+ // but it's not nice....
+
+ while((uint32)ms_memoryUsed >= ms_memoryAvailable - size)
+ if(!RemoveLeastUsedModel()){
+ DeleteRwObjectsBehindCamera(ms_memoryAvailable - size);
+ return;
+ }
+}
+
+void
+CStreaming::LoadScene(const CVector &pos)
+{
+ CStreamingInfo *si, *prev;
+ eLevelName level;
+
+ level = CTheZones::GetLevelFromPosition(pos);
+ debug("Start load scene\n");
+ for(si = ms_endRequestedList.m_prev; si != &ms_startRequestedList; si = prev){
+ prev = si->m_prev;
+ if((si->m_flags & (STREAMFLAGS_KEEP_IN_MEMORY|STREAMFLAGS_PRIORITY)) == 0)
+ RemoveModel(si - ms_aInfoForModel);
+ }
+ CRenderer::m_loadingPriority = false;
+ CCullZones::ForceCullZoneCoors(pos);
+ DeleteAllRwObjects();
+ AddModelsToRequestList(pos);
+ CRadar::StreamRadarSections(pos);
+ RemoveUnusedBigBuildings(level);
+ RequestBigBuildings(level);
+ LoadAllRequestedModels(false);
+ debug("End load scene\n");
+}
+
STARTPATCHES
InjectHook(0x406430, CStreaming::Init, PATCH_JUMP);
InjectHook(0x406C80, CStreaming::Shutdown, PATCH_JUMP);
@@ -1861,10 +2217,16 @@ STARTPATCHES
InjectHook(0x407C50, (void (*)(CPtrList&,float,float,float,float,float,float))CStreaming::ProcessEntitiesInSectorList, PATCH_JUMP);
InjectHook(0x407DD0, (void (*)(CPtrList&))CStreaming::ProcessEntitiesInSectorList, PATCH_JUMP);
+ InjectHook(0x407070, CStreaming::DeleteFarAwayRwObjects, PATCH_JUMP);
InjectHook(0x407390, CStreaming::DeleteAllRwObjects, PATCH_JUMP);
InjectHook(0x407400, CStreaming::DeleteRwObjectsAfterDeath, PATCH_JUMP);
+ InjectHook(0x408A60, CStreaming::DeleteRwObjectsBehindCamera, PATCH_JUMP);
InjectHook(0x407560, CStreaming::DeleteRwObjectsInSectorList, PATCH_JUMP);
InjectHook(0x4075A0, CStreaming::DeleteRwObjectsInOverlapSectorList, PATCH_JUMP);
+ InjectHook(0x409340, CStreaming::DeleteRwObjectsBehindCameraInSectorList, PATCH_JUMP);
+ InjectHook(0x4093C0, CStreaming::DeleteRwObjectsNotInFrustumInSectorList, PATCH_JUMP);
+ InjectHook(0x409B70, CStreaming::MakeSpaceFor, PATCH_JUMP);
+ InjectHook(0x40A6D0, CStreaming::LoadScene, PATCH_JUMP);
InjectHook(0x4063E0, &CStreamingInfo::GetCdPosnAndSize, PATCH_JUMP);
InjectHook(0x406410, &CStreamingInfo::SetCdPosnAndSize, PATCH_JUMP);
diff --git a/src/Streaming.h b/src/Streaming.h
index a2ff2f5b..4caefb6d 100644
--- a/src/Streaming.h
+++ b/src/Streaming.h
@@ -103,7 +103,7 @@ public:
static int32 *ms_imageOffsets; //[NUMCDIMAGES]
static int32 &ms_lastImageRead;
static int32 &ms_imageSize;
- static int32 &ms_memoryAvailable;
+ static uint32 &ms_memoryAvailable;
static void Init(void);
static void Shutdown(void);
@@ -162,12 +162,17 @@ public:
static void ProcessEntitiesInSectorList(CPtrList &list);
static void DeleteFarAwayRwObjects(const CVector &pos);
static void DeleteAllRwObjects(void);
+ static void DeleteRwObjectsAfterDeath(const CVector &pos);
+ static void DeleteRwObjectsBehindCamera(int32 mem);
static void DeleteRwObjectsInSectorList(CPtrList &list);
static void DeleteRwObjectsInOverlapSectorList(CPtrList &list, int32 x, int32 y);
- static void DeleteRwObjectsAfterDeath(const CVector &pos);
+ static bool DeleteRwObjectsBehindCameraInSectorList(CPtrList &list, int32 mem);
+ static bool DeleteRwObjectsNotInFrustumInSectorList(CPtrList &list, int32 mem);
static void LoadInitialPeds(void);
static void LoadInitialVehicles(void);
static void LoadScene(const CVector &pos);
+
+ static bool IsModelLoaded(int32 id) { return ms_aInfoForModel[id].m_loadState == STREAMSTATE_LOADED; }
};
diff --git a/src/Wanted.cpp b/src/Wanted.cpp
index 36bc4f03..ece68e64 100644
--- a/src/Wanted.cpp
+++ b/src/Wanted.cpp
@@ -1,3 +1,36 @@
#include "common.h"
#include "patcher.h"
#include "Wanted.h"
+
+bool CWanted::AreSwatRequired()
+{
+ return m_nWantedLevel >= 4;
+}
+
+bool CWanted::AreFbiRequired()
+{
+ return m_nWantedLevel >= 5;
+}
+
+bool CWanted::AreArmyRequired()
+{
+ return m_nWantedLevel >= 6;
+}
+
+int CWanted::NumOfHelisRequired()
+{
+ if (m_IsIgnoredByCops)
+ return 0;
+
+ // Return value is number of helicopters, no need to name them.
+ switch (m_nWantedLevel) {
+ case WANTEDLEVEL_3:
+ case WANTEDLEVEL_4:
+ return 1;
+ case WANTEDLEVEL_5:
+ case WANTEDLEVEL_6:
+ return 2;
+ default:
+ return 0;
+ };
+} \ No newline at end of file
diff --git a/src/Wanted.h b/src/Wanted.h
index 60af7d8b..aafa9ac0 100644
--- a/src/Wanted.h
+++ b/src/Wanted.h
@@ -1,70 +1,20 @@
#pragma once
#include "Entity.h"
#include "math/Vector.h"
+#include "CopPed.h"
-enum eCrimeType
-{
- CRIME_NONE,
- CRIME_SHOT_FIRED,
- CRIME_PED_FIGHT,
- CRIME_COP_FIGHT,
- CRIME_DAMAGED_PED,
- CRIME_DAMAGED_COP,
- CRIME_CAR_THEFT,
- CRIME_CRIME7,
- CRIME_COP_EVASIVE_DIVE,
- CRIME_COP_EVASIVE_DIVE2,
- CRIME_PED_RUN_OVER,
- CRIME_COP_RUN_OVER,
- CRIME_DESTROYED_HELI,
- CRIME_PED_BURNED,
- CRIME_COP_BURNED,
- CRIME_VEHICLE_BURNED,
- CRIME_DESTROYED_CESSNA,
+enum eWantedLevel {
+ NOTWANTED,
+ WANTEDLEVEL_1,
+ WANTEDLEVEL_2,
+ WANTEDLEVEL_3,
+ WANTEDLEVEL_4,
+ WANTEDLEVEL_5,
+ WANTEDLEVEL_6,
};
-enum eCopType
+class CWanted
{
- COP_STREET = 0,
- COP_FBI = 1,
- COP_SWAT = 2,
- COP_ARMY = 3,
-};
-
-class CCrime {
-public:
- eCrimeType m_eCrimeType;
- CEntity *m_pVictim;
- int32 m_nCrimeTime;
- CVector m_vecCrimePos;
- int8 m_bReported;
- int8 m_bMultiplier;
- int8 pad_20[2];
-};
-
-class CCopPed {
-public:
- int16 m_wRoadblockNode;
- int8 field_1342;
- int8 field_1343;
- float m_fDistanceToTarget;
- int8 m_bIsInPursuit;
- int8 m_bIsDisabledCop;
- int8 field_1350;
- int8 field_1351;
- int8 m_bZoneDisabledButClose;
- int8 m_bZoneDisabled;
- int8 field_1354;
- int8 field_1355;
- int32 field_1356;
- eCopType m_nCopType;
- int8 field_1364;
- int8 field_1365;
- int8 field_1366;
- int8 field_1367;
-};
-
-class CWanted {
public:
int32 m_nChaos;
int32 m_nLastUpdateTime;
@@ -75,11 +25,21 @@ public:
uint8 m_bMaximumLawEnforcerVehicles;
int8 field_19;
int16 m_wRoadblockDensity;
- uint8 m_bFlags;
+ uint8 m_IsIgnoredByCops : 1;
+ uint8 m_IsIgnoredByEveryOne : 1;
+ uint8 m_IsSwatRequired : 1;
+ uint8 m_IsFbiRequired : 1;
+ uint8 m_IdArmyRequired : 1;
int8 field_23;
int32 m_nWantedLevel;
CCrime m_sCrimes[16];
CCopPed *m_pCops[10];
+
+public:
+ bool AreSwatRequired();
+ bool AreFbiRequired();
+ bool AreArmyRequired();
+ int NumOfHelisRequired();
};
static_assert(sizeof(CWanted) == 0x204, "CWanted: error");
diff --git a/src/animation/RpAnimBlend.cpp b/src/animation/RpAnimBlend.cpp
index 9d5e2162..3d1439c6 100644
--- a/src/animation/RpAnimBlend.cpp
+++ b/src/animation/RpAnimBlend.cpp
@@ -48,7 +48,7 @@ CAnimBlendAssociation*
RpAnimBlendGetNextAssociation(CAnimBlendAssociation *assoc)
{
if(assoc->link.next)
- CAnimBlendAssociation::FromLink(assoc->link.next);
+ return CAnimBlendAssociation::FromLink(assoc->link.next);
return nil;
}
diff --git a/src/config.h b/src/config.h
index 83aa7b8f..53a7ad11 100644
--- a/src/config.h
+++ b/src/config.h
@@ -62,6 +62,12 @@ enum Config {
NUMPICKUPS = 336,
};
+// We don't expect to compile for PS2 or Xbox
+// but it might be interesting for documentation purposes
+#define GTA_PC
+//#define GTA_PS2
+//#define GTA_XBOX
+
#define GTA3_1_1_PATCH
#define USE_PS2_RAND
#define RANDOMSPLASH
@@ -70,4 +76,4 @@ enum Config {
//#define NO_CDCHECK
#define NO_MOVIES
//#define USE_MY_DOCUMENTS
-#define NASTY_GAME \ No newline at end of file
+#define NASTY_GAME
diff --git a/src/control/PathFind.cpp b/src/control/PathFind.cpp
index c3af2e30..f511b5dc 100644
--- a/src/control/PathFind.cpp
+++ b/src/control/PathFind.cpp
@@ -4,6 +4,8 @@
CPathFind &ThePaths = *(CPathFind*)0x8F6754;
+WRAPPER int32 CPathFind::FindNodeClosestToCoors(CVector coors, uint8 type, float distLimit, bool disabled, bool betweenLevels) { EAXJMP(0x42CC30); }
+
int TempListLength;
enum
diff --git a/src/control/PathFind.h b/src/control/PathFind.h
index 83b89953..cc0b0a2f 100644
--- a/src/control/PathFind.h
+++ b/src/control/PathFind.h
@@ -128,6 +128,7 @@ public:
void StoreNodeInfoPed(int16 id, int16 node, int8 type, int8 next, int16 x, int16 y, int16 z, int16 width, bool crossing);
void StoreNodeInfoCar(int16 id, int16 node, int8 type, int8 next, int16 x, int16 y, int16 z, int16 width, int8 numLeft, int8 numRight);
void RegisterMapObject(CTreadable *mapObject);
+ int32 FindNodeClosestToCoors(CVector coors, uint8 type, float distLimit, bool disabled, bool betweenLevels);
bool IsPathObject(int id) { return id < PATHNODESIZE && (InfoForTileCars[id*12].type != 0 || InfoForTilePeds[id*12].type != 0); }
};
diff --git a/src/entities/CopPed.h b/src/entities/CopPed.h
index 2658a386..d41c2e9e 100644
--- a/src/entities/CopPed.h
+++ b/src/entities/CopPed.h
@@ -1,11 +1,68 @@
#pragma once
-
#include "Ped.h"
+enum eCrimeType
+{
+ CRIME_NONE,
+ CRIME_SHOT_FIRED,
+ CRIME_PED_FIGHT,
+ CRIME_COP_FIGHT,
+ CRIME_DAMAGED_PED,
+ CRIME_DAMAGED_COP,
+ CRIME_CAR_THEFT,
+ CRIME_CRIME7,
+ CRIME_COP_EVASIVE_DIVE,
+ CRIME_COP_EVASIVE_DIVE2,
+ CRIME_PED_RUN_OVER,
+ CRIME_COP_RUN_OVER,
+ CRIME_DESTROYED_HELI,
+ CRIME_PED_BURNED,
+ CRIME_COP_BURNED,
+ CRIME_VEHICLE_BURNED,
+ CRIME_DESTROYED_CESSNA,
+};
+
+enum eCopType
+{
+ COP_STREET = 0,
+ COP_FBI = 1,
+ COP_SWAT = 2,
+ COP_ARMY = 3,
+};
+
+class CCrime
+{
+public:
+ eCrimeType m_eCrimeType;
+ CEntity *m_pVictim;
+ int32 m_nCrimeTime;
+ CVector m_vecCrimePos;
+ int8 m_bReported;
+ int8 m_bMultiplier;
+ int8 pad_20[2];
+};
+
class CCopPed : public CPed
{
public:
- // 0x53C
- uint8 stuff[28];
+ int16 m_wRoadblockNode;
+ int8 field_1342;
+ int8 field_1343;
+ float m_fDistanceToTarget;
+ int8 m_bIsInPursuit;
+ int8 m_bIsDisabledCop;
+ int8 field_1350;
+ int8 field_1351;
+ int8 m_bZoneDisabledButClose;
+ int8 m_bZoneDisabled;
+ int8 field_1354;
+ int8 field_1355;
+ int32 field_1356;
+ eCopType m_nCopType;
+ int8 field_1364;
+ int8 field_1365;
+ int8 field_1366;
+ int8 field_1367;
};
+
static_assert(sizeof(CCopPed) == 0x558, "CCopPed: error");
diff --git a/src/entities/CutsceneObject.cpp b/src/entities/CutsceneObject.cpp
index 163d0513..a7bca122 100644
--- a/src/entities/CutsceneObject.cpp
+++ b/src/entities/CutsceneObject.cpp
@@ -15,7 +15,7 @@ CCutsceneObject::CCutsceneObject(void)
{
m_status = STATUS_SIMPLE;
bUsesCollision = false;
- m_flagC20 = true;
+ bStreamingDontDelete = true;
ObjectCreatedBy = CUTSCENE_OBJECT;
m_fMass = 1.0f;
m_fTurnMass = 1.0f;
diff --git a/src/entities/Entity.cpp b/src/entities/Entity.cpp
index 294518c8..e9b35cd5 100644
--- a/src/entities/Entity.cpp
+++ b/src/entities/Entity.cpp
@@ -35,14 +35,14 @@ CEntity::CEntity(void)
bIsBIGBuilding = false;
bRenderDamaged = false;
- m_flagC1 = false;
- m_flagC2 = false;
- m_flagC4 = false;
- m_flagC8 = false;
- m_flagC10 = false;
- m_flagC20 = false;
- m_bZoneCulled = false;
- m_bZoneCulled2 = false;
+ bBulletProof = false;
+ bFireProof = false;
+ bCollisionProof = false;
+ bMeleeProof = false;
+ bOnlyDamagedByPlayer = false;
+ bStreamingDontDelete = false;
+ bZoneCulled = false;
+ bZoneCulled2 = false;
bRemoveFromWorld = false;
bHasHitWall = false;
@@ -305,7 +305,7 @@ CEntity::SetupBigBuilding(void)
mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(m_modelIndex);
bIsBIGBuilding = true;
- m_flagC20 = true;
+ bStreamingDontDelete = true;
bUsesCollision = false;
m_level = CTheZones::GetLevelFromPosition(GetPosition());
if(m_level == LEVEL_NONE){
diff --git a/src/entities/Entity.h b/src/entities/Entity.h
index 8816e206..27dd8c14 100644
--- a/src/entities/Entity.h
+++ b/src/entities/Entity.h
@@ -78,14 +78,14 @@ public:
uint32 bRenderDamaged : 1;
// flagsC
- uint32 m_flagC1 : 1; // bullet proof?
- uint32 m_flagC2 : 1; // fire proof?
- uint32 m_flagC4 : 1; // collision proof?
- uint32 m_flagC8 : 1; // melee proof?
- uint32 m_flagC10 : 1; // bOnlyDamagedByPlayer?
- uint32 m_flagC20 : 1;
- uint32 m_bZoneCulled : 1;
- uint32 m_bZoneCulled2 : 1; // only treadables+10m
+ uint32 bBulletProof : 1;
+ uint32 bFireProof : 1;
+ uint32 bCollisionProof : 1;
+ uint32 bMeleeProof : 1;
+ uint32 bOnlyDamagedByPlayer : 1;
+ uint32 bStreamingDontDelete : 1;
+ uint32 bZoneCulled : 1;
+ uint32 bZoneCulled2 : 1; // only treadables+10m
// flagsD
uint32 bRemoveFromWorld : 1;
diff --git a/src/entities/Ped.cpp b/src/entities/Ped.cpp
index c4109312..0dedacad 100644
--- a/src/entities/Ped.cpp
+++ b/src/entities/Ped.cpp
@@ -249,7 +249,7 @@ CheckForPedsOnGroundToAttack(CPlayerPed *player, CPed **pedOnGround)
foundDead = 1;
if (!deadPed)
deadPed = (CPed*)currentPed;
- } else if (currentPed->IsPedHeadAbovePos(-0.6f)) {
+ } else if (!currentPed->IsPedHeadAbovePos(-0.6f)) {
foundOnTheFloor = 1;
if (!pedOnTheFloor)
pedOnTheFloor = (CPed*)currentPed;
@@ -313,10 +313,9 @@ bool
CPed::CanSetPedState(void)
{
return m_nPedState != PED_DIE && m_nPedState != PED_ARRESTED &&
- m_nPedState != PED_ENTER_CAR && m_nPedState != PED_CARJACK && m_nPedState != PED_DRAG_FROM_CAR && m_nPedState != PED_STEAL_CAR;
+ m_nPedState != PED_ENTER_CAR && m_nPedState != PED_DEAD && m_nPedState != PED_CARJACK && m_nPedState != PED_STEAL_CAR;
}
-
void
CPed::AddWeaponModel(int id)
{
@@ -338,23 +337,23 @@ CPed::AimGun(void)
CVector vector;
if (m_pSeekTarget) {
- if (m_pSeekTarget->m_status == STATUS_PHYSICS) {
- m_pSeekTarget->m_pedIK.GetComponentPosition(&pos, PED_TORSO);
+ if (m_pSeekTarget->IsPed()) {
+ ((CPed*)m_pSeekTarget)->m_pedIK.GetComponentPosition(&pos, PED_TORSO);
vector.x = pos.x;
vector.y = pos.y;
vector.z = pos.z;
} else {
vector = *(m_pSeekTarget->GetPosition());
}
- CPed::Say(SOUND_PED_ATTACK);
+ Say(SOUND_PED_ATTACK);
bCanPointGunAtTarget = m_pedIK.PointGunAtPosition(&vector);
if (m_pLookTarget != m_pSeekTarget) {
- CPed::SetLookFlag(m_pSeekTarget, 1);
+ SetLookFlag(m_pSeekTarget, 1);
}
} else {
- if (CPed::IsPlayer()) {
+ if (IsPlayer()) {
bCanPointGunAtTarget = m_pedIK.PointGunInDirection(m_fLookDirection, ((CPlayerPed*)this)->m_fFPSMoveHeading);
} else {
bCanPointGunAtTarget = m_pedIK.PointGunInDirection(m_fLookDirection, 0.0f);
@@ -459,7 +458,7 @@ CPed::RecurseFrameChildrenVisibilityCB(RwFrame *frame, void *data)
}
void
-CPed::SetLookFlag(CPed *target, bool unknown)
+CPed::SetLookFlag(CEntity *target, bool unknown)
{
if (m_lookTimer < CTimer::GetTimeInMilliseconds()) {
bIsLooking = true;
@@ -621,8 +620,7 @@ CPed::FinishedAttackCB(CAnimBlendAssociation *attackAssoc, void *arg)
if (attackAssoc) {
switch (attackAssoc->animId) {
case ANIM_WEAPON_START_THROW:
- if ((!ped->IsPlayer() || ((CPlayerPed*)ped)->field_1380) && ped->IsPlayer())
- {
+ if ((!ped->IsPlayer() || ((CPlayerPed*)ped)->field_1380) && ped->IsPlayer()) {
attackAssoc->blendDelta = -1000.0f;
newAnim = CAnimManager::AddAnimation((RpClump*)ped->m_rwObject, ASSOCGRP_STD, ANIM_WEAPON_THROWU);
} else {
@@ -1492,7 +1490,7 @@ STARTPATCHES
InjectHook(0x4C6AA0, &CPed::AimGun, PATCH_JUMP);
InjectHook(0x4EB470, &CPed::ApplyHeadShot, PATCH_JUMP);
InjectHook(0x4EAEE0, &CPed::RemoveBodyPart, PATCH_JUMP);
- InjectHook(0x4C6460, (void (CPed::*)(CPed*, bool)) &CPed::SetLookFlag, PATCH_JUMP);
+ InjectHook(0x4C6460, (void (CPed::*)(CEntity*, bool)) &CPed::SetLookFlag, PATCH_JUMP);
InjectHook(0x4C63E0, (void (CPed::*)(float, bool)) &CPed::SetLookFlag, PATCH_JUMP);
InjectHook(0x4D12E0, &CPed::SetLookTimer, PATCH_JUMP);
InjectHook(0x4C5700, &CPed::OurPedCanSeeThisOne, PATCH_JUMP);
diff --git a/src/entities/Ped.h b/src/entities/Ped.h
index 34c7a485..37a1cd3d 100644
--- a/src/entities/Ped.h
+++ b/src/entities/Ped.h
@@ -227,7 +227,7 @@ public:
CVector m_vecOffsetFromPhysSurface;
CEntity *m_pCurSurface;
uint8 stuff3[12];
- CPed *m_pSeekTarget;
+ CEntity *m_pSeekTarget;
CVehicle *m_pMyVehicle;
bool bInVehicle;
uint8 stuff4[23];
@@ -273,7 +273,7 @@ public:
void AimGun(void);
void KillPedWithCar(CVehicle *veh, float impulse);
void Say(uint16 audio);
- void SetLookFlag(CPed *target, bool unknown);
+ void SetLookFlag(CEntity *target, bool unknown);
void SetLookFlag(float direction, bool unknown);
void SetLookTimer(int time);
void SetDie(AnimationId anim, float arg1, float arg2);
diff --git a/src/main.cpp b/src/main.cpp
index 0dadc131..d1ffbe6b 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -84,6 +84,7 @@ void DestroySplashScreen(void);
extern void (*DebugMenuProcess)(void);
extern void (*DebugMenuRender)(void);
void DebugMenuInit(void);
+void DebugMenuPopulate(void);
void PrintGameVersion();
@@ -115,6 +116,13 @@ Idle(void *arg)
if((!FrontEndMenuManager.m_bMenuActive || FrontEndMenuManager.field_452 == 1) &&
TheCamera.GetScreenFadeStatus() != FADE_2){
+#ifdef GTA_PC
+ // This is from SA, but it's nice for windowed mode
+ RwV2d pos;
+ pos.x = SCREENW/2.0f;
+ pos.y = SCREENH/2.0f;
+ RsMouseSetPos(&pos);
+#endif
CRenderer::ConstructRenderList();
CRenderer::PreRender();
@@ -677,6 +685,7 @@ Initialise3D(void *param)
{
//
DebugMenuInit();
+ DebugMenuPopulate();
//
return CGame::InitialiseRenderWare();
diff --git a/src/modelinfo/ModelInfo.cpp b/src/modelinfo/ModelInfo.cpp
index ca36aa61..acc40824 100644
--- a/src/modelinfo/ModelInfo.cpp
+++ b/src/modelinfo/ModelInfo.cpp
@@ -168,6 +168,13 @@ CModelInfo::GetModelInfo(const char *name, int *id)
return nil;
}
+bool
+CModelInfo::IsBoatModel(int32 id)
+{
+ return GetModelInfo(id)->m_type == MITYPE_VEHICLE &&
+ ((CVehicleModelInfo*)GetModelInfo(id))->m_vehicleType == VEHICLE_TYPE_BOAT;
+}
+
STARTPATCHES
InjectHook(0x50B310, CModelInfo::Initialise, PATCH_JUMP);
InjectHook(0x50B5B0, CModelInfo::ShutDown, PATCH_JUMP);
diff --git a/src/modelinfo/ModelInfo.h b/src/modelinfo/ModelInfo.h
index 4ab633bf..30be96ca 100644
--- a/src/modelinfo/ModelInfo.h
+++ b/src/modelinfo/ModelInfo.h
@@ -34,4 +34,6 @@ public:
static CBaseModelInfo *GetModelInfo(int id){
return ms_modelInfoPtrs[id];
}
+
+ static bool IsBoatModel(int32 id);
};
diff --git a/src/re3.cpp b/src/re3.cpp
index 948d9aa0..284b88de 100644
--- a/src/re3.cpp
+++ b/src/re3.cpp
@@ -6,6 +6,14 @@
#include "Renderer.h"
#include "Credits.h"
#include "Camera.h"
+#include "Weather.h"
+#include "Clock.h"
+#include "World.h"
+#include "Vehicle.h"
+#include "Streaming.h"
+#include "PathFind.h"
+#include "Boat.h"
+#include "Automobile.h"
#include "debugmenu_public.h"
void **rwengine = *(void***)0x5A10E1;
@@ -49,12 +57,20 @@ int (*open_script_orig)(const char *path, const char *mode);
int
open_script(const char *path, const char *mode)
{
+ static int scriptToLoad = 1;
+
if(GetAsyncKeyState('G') & 0x8000)
- return open_script_orig("main.scm", mode);
+ scriptToLoad = 0;
+ if(GetAsyncKeyState('R') & 0x8000)
+ scriptToLoad = 1;
if(GetAsyncKeyState('D') & 0x8000)
- return open_script_orig("main_d.scm", mode);
-// if(GetAsyncKeyState('R') & 0x8000)
- return open_script_orig("main_freeroam.scm", mode);
+ scriptToLoad = 2;
+
+ switch(scriptToLoad){
+ case 0: return open_script_orig(path, mode);
+ case 1: return open_script_orig("main_freeroam.scm", mode);
+ case 2: return open_script_orig("main_d.scm", mode);
+ }
return open_script_orig(path, mode);
}
@@ -78,10 +94,126 @@ DebugMenuInit(void)
}
+void WeaponCheat();
+void HealthCheat();
+void TankCheat();
+void BlowUpCarsCheat();
+void ChangePlayerCheat();
+void MayhemCheat();
+void EverybodyAttacksPlayerCheat();
+void WeaponsForAllCheat();
+void FastTimeCheat();
+void SlowTimeCheat();
+void MoneyCheat();
+void ArmourCheat();
+void WantedLevelUpCheat();
+void WantedLevelDownCheat();
+void SunnyWeatherCheat();
+void CloudyWeatherCheat();
+void RainyWeatherCheat();
+void FoggyWeatherCheat();
+void FastWeatherCheat();
+void OnlyRenderWheelsCheat();
+void ChittyChittyBangBangCheat();
+void StrongGripCheat();
+void NastyLimbsCheat();
+
+// needs too much stuff for now
+#if 0
+void
+spawnCar(int id)
+{
+ CVector playerpos;
+ CStreaming::RequestModel(id, 0);
+ CStreaming::LoadAllRequestedModels(false);
+ if(CStreaming::IsModelLoaded(id)){
+ FindPlayerCoors(playerpos);
+ int node = ThePaths.FindNodeClosestToCoors(playerpos, 0, 100.0f, false, false);
+ if(node < 0)
+ return;
+
+ CVehicle *v;
+ if(CModelInfo::IsBoatModel(id)){
+// CBoat* boat = (CBoat*)CVehicle__new(0x484);
+// boat = boat->ctor(id, 1);
+// v = (CVehicle*)(boat);
+ }else{
+// CAutomobile *au = (CAutomobile*)CVehicle__new(0x5A8);
+// au = au->ctor(id, 1);
+// v = (CVehicle*)au;
+ }
+/*
+ // unlock doors
+ FIELD(int, v, 0x224) = 1;
+ // set player owned
+ FIELD(uint8, v, 0x1F7) |= 4;
+
+ DebugMenuEntrySetAddress(carCol1, &FIELD(uchar, v, 0x19C));
+ DebugMenuEntrySetAddress(carCol2, &FIELD(uchar, v, 0x19D));
+ //if(id == MODELID_ESPERANTO)
+ // FIELD(uchar, v, 0x19C) = 54;
+
+ v->matrix.matrix.pos.x = ThePaths.nodes[node].x;
+ v->matrix.matrix.pos.y = ThePaths.nodes[node].y;
+ v->matrix.matrix.pos.z = ThePaths.nodes[node].z + 4.0f;
+ float x = v->matrix.matrix.pos.x;
+ float y = v->matrix.matrix.pos.y;
+ float z = v->matrix.matrix.pos.z;
+ v->matrix.SetRotate(0.0f, 0.0f, 3.49f);
+ v->matrix.matrix.pos.x += x;
+ v->matrix.matrix.pos.y += y;
+ v->matrix.matrix.pos.z += z;
+ v->bfTypeStatus = v->bfTypeStatus & 7 | 0x20;
+ FIELD(int, v, 0x224) = 1;
+*/
+ CWorld::Add(v);
+ }
+}
+#endif
+
void
DebugMenuPopulate(void)
{
if(DebugMenuLoad()){
+ static const char *weathers[] = {
+ "Sunny", "Cloudy", "Rainy", "Foggy"
+ };
+ DebugMenuEntry *e;
+ e = DebugMenuAddVar("Time & Weather", "Current Hour", &CClock::GetHoursRef(), nil, 1, 0, 23, nil);
+ DebugMenuEntrySetWrap(e, true);
+ e = DebugMenuAddVar("Time & Weather", "Current Minute", &CClock::GetMinutesRef(),
+ [](){ CWeather::InterpolationValue = CClock::GetMinutes()/60.0f; }, 1, 0, 59, nil);
+ DebugMenuEntrySetWrap(e, true);
+ e = DebugMenuAddVar("Time & Weather", "Old Weather", (int16*)&CWeather::OldWeatherType, nil, 1, 0, 3, weathers);
+ DebugMenuEntrySetWrap(e, true);
+ e = DebugMenuAddVar("Time & Weather", "New Weather", (int16*)&CWeather::NewWeatherType, nil, 1, 0, 3, weathers);
+ DebugMenuEntrySetWrap(e, true);
+ DebugMenuAddVar("Time & Weather", "Time scale", (float*)0x8F2C20, nil, 0.1f, 0.0f, 10.0f);
+
+ DebugMenuAddCmd("Cheats", "Weapons", WeaponCheat);
+ DebugMenuAddCmd("Cheats", "Money", MoneyCheat);
+ DebugMenuAddCmd("Cheats", "Health", HealthCheat);
+ DebugMenuAddCmd("Cheats", "Wanted level up", WantedLevelUpCheat);
+ DebugMenuAddCmd("Cheats", "Wanted level down", WantedLevelDownCheat);
+ DebugMenuAddCmd("Cheats", "Tank", TankCheat);
+ DebugMenuAddCmd("Cheats", "Blow up cars", BlowUpCarsCheat);
+ DebugMenuAddCmd("Cheats", "Change player", ChangePlayerCheat);
+ DebugMenuAddCmd("Cheats", "Mayhem", MayhemCheat);
+ DebugMenuAddCmd("Cheats", "Everybody attacks player", EverybodyAttacksPlayerCheat);
+ DebugMenuAddCmd("Cheats", "Weapons for all", WeaponsForAllCheat);
+ DebugMenuAddCmd("Cheats", "Fast time", FastTimeCheat);
+ DebugMenuAddCmd("Cheats", "Slow time", SlowTimeCheat);
+ DebugMenuAddCmd("Cheats", "Armour", ArmourCheat);
+ DebugMenuAddCmd("Cheats", "Sunny weather", SunnyWeatherCheat);
+ DebugMenuAddCmd("Cheats", "Cloudy weather", CloudyWeatherCheat);
+ DebugMenuAddCmd("Cheats", "Rainy weather", RainyWeatherCheat);
+ DebugMenuAddCmd("Cheats", "Foggy weather", FoggyWeatherCheat);
+ DebugMenuAddCmd("Cheats", "Fast weather", FastWeatherCheat);
+ DebugMenuAddCmd("Cheats", "Only render wheels", OnlyRenderWheelsCheat);
+ DebugMenuAddCmd("Cheats", "Chitty chitty bang bang", ChittyChittyBangBangCheat);
+ DebugMenuAddCmd("Cheats", "Strong grip", StrongGripCheat);
+ DebugMenuAddCmd("Cheats", "Nasty limbs", NastyLimbsCheat);
+
DebugMenuAddVarBool8("Debug", "Show Ped Road Groups", (int8*)&gbShowPedRoadGroups, nil);
DebugMenuAddVarBool8("Debug", "Show Car Road Groups", (int8*)&gbShowCarRoadGroups, nil);
DebugMenuAddVarBool8("Debug", "Show Collision Polys", (int8*)&gbShowCollisionPolys, nil);
diff --git a/src/render/Hud.cpp b/src/render/Hud.cpp
index 9243bc3a..c3640ebf 100644
--- a/src/render/Hud.cpp
+++ b/src/render/Hud.cpp
@@ -20,12 +20,6 @@
#include "User.h"
#include "World.h"
-WRAPPER void CHud::GetRidOfAllHudMessages(void) { EAXJMP(0x504F90); }
-WRAPPER void CHud::SetHelpMessage(wchar *message, bool quick) { EAXJMP(0x5051E0); }
-WRAPPER void CHud::SetMessage(wchar *message) { EAXJMP(0x50A210); }
-WRAPPER void CHud::SetBigMessage(wchar *message, int16 style) { EAXJMP(0x50A250); }
-WRAPPER void CHud::SetPagerMessage(wchar *message) { EAXJMP(0x50A320); }
-
wchar *CHud::m_HelpMessage = (wchar*)0x86B888;
wchar *CHud::m_LastHelpMessage = (wchar*)0x6E8F28;
int32 &CHud::m_HelpMessageState = *(int32*)0x880E1C;
@@ -53,10 +47,10 @@ wchar *CHud::m_PagerMessage = (wchar*)0x878840;
bool &CHud::m_Wants_To_Draw_Hud = *(bool*)0x95CD89;
bool &CHud::m_Wants_To_Draw_3dMarkers = *(bool*)0x95CD62;
wchar(*CHud::m_BigMessage)[128] = (wchar(*)[128])0x664CE0;
+wchar *CHud::m_LastBigMessage = (wchar*)0x86B288;
float CHud::BigMessageInUse[6];
float CHud::BigMessageAlpha[6];
float CHud::BigMessageX[6];
-
float &CHud::OddJob2OffTimer = *(float*)0x942FA0;
int8 &CHud::CounterOnLastFrame = *(int8*)0x95CD67;
float &CHud::OddJob2XOffset = *(float*)0x8F1B5C;
@@ -125,56 +119,6 @@ char *WeaponFilenames[] = {
RwTexture *&gpSniperSightTex = *(RwTexture**)0x8F5834;
RwTexture *&gpRocketSightTex = *(RwTexture**)0x8E2C20;
-void CHud::Initialise()
-{
- debug("Init CHud");
-
- ReInitialise();
-
- int HudTXD = CTxdStore::AddTxdSlot("hud");
- CTxdStore::LoadTxd(HudTXD, "MODELS/HUD.TXD");
- CTxdStore::AddRef(HudTXD);
- CTxdStore::PopCurrentTxd();
- CTxdStore::SetCurrentTxd(HudTXD);
-
- for (int i = 0; i < ARRAY_SIZE(WeaponFilenames) / 2; i++) {
- Sprites[i].SetTexture(WeaponFilenames[i * 2]);
- }
-
- gpSniperSightTex = RwTextureRead("sitesniper", 0);
- gpRocketSightTex = RwTextureRead("siterocket", 0);
-
- CTxdStore::PopCurrentTxd();
-}
-
-void CHud::Shutdown()
-{
- debug("Shutdown CHud");
-
- for (int i = 0; i < ARRAY_SIZE(WeaponFilenames) / 2; ++i) {
- Sprites[i].Delete();
- }
-
- RwTextureDestroy(gpSniperSightTex);
- gpSniperSightTex = 0;
-
- RwTextureDestroy(gpRocketSightTex);
- gpRocketSightTex = 0;
-
- int HudTXD = CTxdStore::FindTxdSlot("hud");
- CTxdStore::RemoveTxdSlot(HudTXD);
-}
-
-void CHud::SetVehicleName(wchar *name)
-{
- m_VehicleName = name;
-}
-
-void CHud::SetZoneName(wchar *name)
-{
- m_ZoneName = name;
-}
-
#if 0
WRAPPER void CHud::Draw(void) { EAXJMP(0x5052A0); }
#else
@@ -231,7 +175,7 @@ void CHud::Draw()
CRect rect;
float fWidescreenOffset[2] = { 0.0f, 0.0f };
-
+
if (FrontEndMenuManager.m_PrefsUseWideScreen) {
fWidescreenOffset[0] = 0.0f;
fWidescreenOffset[1] = SCREEN_SCALE_Y(18.0f);
@@ -587,7 +531,7 @@ void CHud::Draw()
CFont::SetPropOn();
CFont::SetBackgroundOff();
- if (FrontEndMenuManager.m_PrefsLanguage == 4)
+ if (FrontEndMenuManager.m_PrefsLanguage == LANGUAGE_SPANISH)
CFont::SetScale(SCREEN_SCALE_X(1.2f * 0.8f), SCREEN_SCALE_Y(1.2f));
else
CFont::SetScale(SCREEN_SCALE_X(1.2f), SCREEN_SCALE_Y(1.2f));
@@ -683,7 +627,7 @@ void CHud::Draw()
CFont::SetPropOn();
CFont::SetBackgroundOff();
- if (FrontEndMenuManager.m_PrefsLanguage != 3 && FrontEndMenuManager.m_PrefsLanguage != 4)
+ if (FrontEndMenuManager.m_PrefsLanguage != LANGUAGE_ITALIAN && FrontEndMenuManager.m_PrefsLanguage != LANGUAGE_SPANISH)
CFont::SetScale(SCREEN_SCALE_X(1.2f), SCREEN_SCALE_Y(1.2f));
else
CFont::SetScale(SCREEN_SCALE_X(1.2f * 0.85f), SCREEN_SCALE_Y(1.2f));
@@ -1069,6 +1013,7 @@ void CHud::Draw()
}
#endif
+
#if 0
WRAPPER void CHud::DrawAfterFade(void) { EAXJMP(0x509030); }
#else
@@ -1258,7 +1203,7 @@ void CHud::DrawAfterFade()
CFont::SetJustifyOff();
CFont::SetBackgroundOff();
- if (CGame::frenchGame || FrontEndMenuManager.m_PrefsLanguage == 4)
+ if (CGame::frenchGame || FrontEndMenuManager.m_PrefsLanguage == LANGUAGE_SPANISH)
CFont::SetScale(SCREEN_SCALE_X(0.884f), SCREEN_SCALE_Y(1.36f));
else
CFont::SetScale(SCREEN_SCALE_X(1.04f), SCREEN_SCALE_Y(1.6f));
@@ -1306,6 +1251,37 @@ void CHud::DrawAfterFade()
#endif
#if 0
+WRAPPER void CHud::GetRidOfAllHudMessages(void) { EAXJMP(0x504F90); }
+#else
+void CHud::GetRidOfAllHudMessages()
+{
+ ReInitialise();
+}
+#endif
+
+void CHud::Initialise()
+{
+ debug("Init CHud");
+
+ ReInitialise();
+
+ int HudTXD = CTxdStore::AddTxdSlot("hud");
+ CTxdStore::LoadTxd(HudTXD, "MODELS/HUD.TXD");
+ CTxdStore::AddRef(HudTXD);
+ CTxdStore::PopCurrentTxd();
+ CTxdStore::SetCurrentTxd(HudTXD);
+
+ for (int i = 0; i < ARRAY_SIZE(WeaponFilenames) / 2; i++) {
+ Sprites[i].SetTexture(WeaponFilenames[i * 2]);
+ }
+
+ gpSniperSightTex = RwTextureRead("sitesniper", 0);
+ gpRocketSightTex = RwTextureRead("siterocket", 0);
+
+ CTxdStore::PopCurrentTxd();
+}
+
+#if 0
WRAPPER void CHud::ReInitialise(void) { EAXJMP(0x504CC0); }
#else
void CHud::ReInitialise() {
@@ -1358,8 +1334,124 @@ void CHud::ReInitialise() {
}
#endif
+#if 0
+WRAPPER void CHud::SetBigMessage(wchar *message, int16 style) { EAXJMP(0x50A250); }
+#else
+void CHud::SetBigMessage(wchar *message, int16 style)
+{
+ for (int i = 0; i < 128; i++) {
+ if (!message[i])
+ break;
+
+ if (message[i] != m_LastBigMessage[i]) {
+ OddJob2On = 0;
+ OddJob2OffTimer = 0.0f;
+ }
+
+ m_BigMessage[style][i] = message[i];
+ };
+}
+#endif
+
+#if 0
+WRAPPER void CHud::SetHelpMessage(wchar *message, bool quick) { EAXJMP(0x5051E0); }
+#else
+void CHud::SetHelpMessage(wchar *message, bool quick)
+{
+ if (!CReplay::IsPlayingBack()) {
+ CMessages::WideStringCopy(m_HelpMessage, message, 256);
+ CMessages::InsertPlayerControlKeysInString(m_HelpMessage);
+
+ for (int i = 0; i < 256; i++) {
+ m_LastHelpMessage[i] = message[i];
+ };
+
+ m_HelpMessageState = 0;
+ m_HelpMessageQuick = quick;
+ }
+}
+#endif
+
+#if 0
+WRAPPER void CHud::SetMessage(wchar *message) { EAXJMP(0x50A210); }
+#else
+void CHud::SetMessage(wchar *message)
+{
+ int i = 0;
+ for (i; i < 256; i++) {
+ if (!message[i])
+ break;
+
+ m_Message[i] = message[i];
+ };
+ m_Message[i] = message[i];
+}
+#endif
+
+#if 0
+WRAPPER void CHud::SetPagerMessage(wchar *message) { EAXJMP(0x50A320); }
+#else
+void CHud::SetPagerMessage(wchar *message)
+{
+ int i = 0;
+ for (i; i < 256; i++) {
+ if (!message[i])
+ break;
+
+ m_PagerMessage[i] = message[i];
+ };
+
+ m_PagerMessage[i] = 0;
+}
+#endif
+
+#if 0
+WRAPPER void CHud::SetVehicleName(wchar *name) { EAXJMP(0x505290); }
+#else
+void CHud::SetVehicleName(wchar *name)
+{
+ m_VehicleName = name;
+}
+#endif
+
+#if 0
+WRAPPER void CHud::SetZoneName(wchar *name) { EAXJMP(0x5051D0); }
+#else
+void CHud::SetZoneName(wchar *name)
+{
+ m_ZoneName = name;
+}
+#endif
+
+void CHud::Shutdown()
+{
+ debug("Shutdown CHud");
+
+ for (int i = 0; i < ARRAY_SIZE(WeaponFilenames) / 2; ++i) {
+ Sprites[i].Delete();
+ }
+
+ RwTextureDestroy(gpSniperSightTex);
+ gpSniperSightTex = 0;
+
+ RwTextureDestroy(gpRocketSightTex);
+ gpRocketSightTex = 0;
+
+ int HudTXD = CTxdStore::FindTxdSlot("hud");
+ CTxdStore::RemoveTxdSlot(HudTXD);
+}
+
STARTPATCHES
- InjectHook(0x48BC9A, &CHud::Initialise, PATCH_CALL);
- InjectHook(0x48C4F1, &CHud::ReInitialise, PATCH_CALL);
- InjectHook(0x48BCBC, &CHud::Shutdown, PATCH_CALL);
+ InjectHook(0x5052A0, &CHud::Draw, PATCH_JUMP);
+ InjectHook(0x509030, &CHud::DrawAfterFade, PATCH_JUMP);
+ InjectHook(0x504F90, &CHud::GetRidOfAllHudMessages, PATCH_JUMP);
+ InjectHook(0x5048F0, &CHud::Initialise, PATCH_JUMP);
+ InjectHook(0x504CC0, &CHud::ReInitialise, PATCH_JUMP);
+ InjectHook(0x50A250, &CHud::SetBigMessage, PATCH_JUMP);
+ //InjectHook(0x5051E0, &CHud::SetHelpMessage, PATCH_JUMP);
+ InjectHook(0x50A210, &CHud::SetMessage, PATCH_JUMP);
+ InjectHook(0x50A320, &CHud::SetPagerMessage, PATCH_JUMP);
+ InjectHook(0x505290, &CHud::SetVehicleName, PATCH_JUMP);
+ InjectHook(0x5051D0, &CHud::SetZoneName, PATCH_JUMP);
+ InjectHook(0x504C50, &CHud::Shutdown, PATCH_JUMP);
ENDPATCHES
diff --git a/src/render/Hud.h b/src/render/Hud.h
index 260e5312..c4a768f4 100644
--- a/src/render/Hud.h
+++ b/src/render/Hud.h
@@ -34,7 +34,6 @@ class CHud
{
public:
static CSprite2d *Sprites;
-
static wchar *m_HelpMessage;
static wchar *m_LastHelpMessage;
static int32 &m_HelpMessageState;
@@ -62,6 +61,7 @@ public:
static bool &m_Wants_To_Draw_Hud;
static bool &m_Wants_To_Draw_3dMarkers;
static wchar(*m_BigMessage)[128];
+ static wchar *m_LastBigMessage;
static float BigMessageInUse[6];
static float BigMessageAlpha[6];
static float BigMessageX[6];
@@ -81,16 +81,16 @@ public:
static int16 &PagerOn;
public:
+ static void Draw();
+ static void DrawAfterFade();
+ static void GetRidOfAllHudMessages();
static void Initialise();
- static void Shutdown();
static void ReInitialise();
- static void GetRidOfAllHudMessages();
- static void SetZoneName(wchar *name);
+ static void SetBigMessage(wchar *message, int16 style);
static void SetHelpMessage(wchar *message, bool quick);
- static void SetVehicleName(wchar *name);
- static void Draw();
- static void DrawAfterFade();
static void SetMessage(wchar *message);
- static void SetBigMessage(wchar *message, int16 style);
static void SetPagerMessage(wchar *message);
+ static void SetVehicleName(wchar *name);
+ static void SetZoneName(wchar *name);
+ static void Shutdown();
};
diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp
index 10001100..d8b0bbe6 100644
--- a/src/render/Renderer.cpp
+++ b/src/render/Renderer.cpp
@@ -917,7 +917,7 @@ CRenderer::ScanBigBuildingList(CPtrList &list)
for(node = list.first; node; node = node->next){
ent = (CEntity*)node->item;
- if(!ent->m_bZoneCulled && SetupBigBuildingVisibility(ent) == 1)
+ if(!ent->bZoneCulled && SetupBigBuildingVisibility(ent) == 1)
ms_aVisibleEntityPtrs[ms_nNoOfVisibleEntities++] = ent;
}
}
@@ -1122,7 +1122,7 @@ CRenderer::IsEntityCullZoneVisible(CEntity *ent)
CPed *ped;
CObject *obj;
- if(ent->m_bZoneCulled)
+ if(ent->bZoneCulled)
return false;
switch(ent->m_type){
@@ -1132,12 +1132,12 @@ CRenderer::IsEntityCullZoneVisible(CEntity *ent)
ped = (CPed*)ent;
if(ped->bInVehicle)
return ped->m_pMyVehicle && IsVehicleCullZoneVisible(ped->m_pMyVehicle);
- return !(ped->m_pCurSurface && ped->m_pCurSurface->m_bZoneCulled2);
+ return !(ped->m_pCurSurface && ped->m_pCurSurface->bZoneCulled2);
case ENTITY_TYPE_OBJECT:
obj = (CObject*)ent;
if(!obj->bIsStatic)
return true;
- return !(obj->m_pCurSurface && obj->m_pCurSurface->m_bZoneCulled2);
+ return !(obj->m_pCurSurface && obj->m_pCurSurface->bZoneCulled2);
}
return true;
}
@@ -1151,7 +1151,7 @@ CRenderer::IsVehicleCullZoneVisible(CEntity *ent)
case STATUS_PHYSICS:
case STATUS_ABANDONED:
case STATUS_WRECKED:
- return !(v->m_pCurSurface && v->m_pCurSurface->m_bZoneCulled2);
+ return !(v->m_pCurSurface && v->m_pCurSurface->bZoneCulled2);
return true;
}