summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authoreray orçunus <erayorcunus@gmail.com>2019-06-29 15:55:19 +0200
committereray orçunus <erayorcunus@gmail.com>2019-06-29 15:55:19 +0200
commit0974447f585a457ea7d68187db28bcec5aa269e2 (patch)
tree6f7cf38dc4ea9a17b1bc6125fcc69758cf535e34 /src
parentMerge branch 'master' of git://github.com/GTAmodding/re3 into erorcun (diff)
parentfix (diff)
downloadre3-0974447f585a457ea7d68187db28bcec5aa269e2.tar
re3-0974447f585a457ea7d68187db28bcec5aa269e2.tar.gz
re3-0974447f585a457ea7d68187db28bcec5aa269e2.tar.bz2
re3-0974447f585a457ea7d68187db28bcec5aa269e2.tar.lz
re3-0974447f585a457ea7d68187db28bcec5aa269e2.tar.xz
re3-0974447f585a457ea7d68187db28bcec5aa269e2.tar.zst
re3-0974447f585a457ea7d68187db28bcec5aa269e2.zip
Diffstat (limited to 'src')
-rw-r--r--src/Camera.cpp1
-rw-r--r--src/Collision.cpp303
-rw-r--r--src/Collision.h2
-rw-r--r--src/CullZones.cpp34
-rw-r--r--src/FileLoader.cpp4
-rw-r--r--src/FileMgr.cpp4
-rw-r--r--src/FileMgr.h2
-rw-r--r--src/Game.cpp3
-rw-r--r--src/Game.h15
-rw-r--r--src/Radar.cpp18
-rw-r--r--src/RwMatFX.cpp212
-rw-r--r--src/Streaming.cpp4
-rw-r--r--src/Text.cpp31
-rw-r--r--src/Text.h7
-rw-r--r--src/World.cpp141
-rw-r--r--src/World.h7
-rw-r--r--src/Zones.cpp2
-rw-r--r--src/audio/DMAudio.cpp4
-rw-r--r--src/audio/DMAudio.h2
-rw-r--r--src/config.h2
-rw-r--r--src/control/CarCtrl.cpp1
-rw-r--r--src/control/CarCtrl.h1
-rw-r--r--src/control/Population.cpp2
-rw-r--r--src/control/Population.h1
-rw-r--r--src/control/Replay.cpp12
-rw-r--r--src/control/Replay.h1
-rw-r--r--src/entities/CopPed.h24
-rw-r--r--src/entities/Dummy.cpp52
-rw-r--r--src/entities/Dummy.h7
-rw-r--r--src/entities/Ped.cpp24
-rw-r--r--src/entities/Physical.cpp2
-rw-r--r--src/entities/Physical.h7
-rw-r--r--src/entities/PlayerInfo.h20
-rw-r--r--src/entities/Train.h11
-rw-r--r--src/main.cpp62
-rw-r--r--src/main.h3
-rw-r--r--src/math/Vector.h1
-rw-r--r--src/modelinfo/ModelInfo.cpp18
-rw-r--r--src/modelinfo/ModelInfo.h1
-rw-r--r--src/modelinfo/VehicleModelInfo.cpp2
-rw-r--r--src/re3.cpp2
-rw-r--r--src/skel/win/win.cpp11
42 files changed, 931 insertions, 132 deletions
diff --git a/src/Camera.cpp b/src/Camera.cpp
index 3af5d953..198dda0f 100644
--- a/src/Camera.cpp
+++ b/src/Camera.cpp
@@ -5,6 +5,7 @@
#include "World.h"
#include "Vehicle.h"
#include "Ped.h"
+#include "PlayerPed.h"
#include "Pad.h"
#include "General.h"
#include "CullZones.h"
diff --git a/src/Collision.cpp b/src/Collision.cpp
index 774caf9d..6189a3fc 100644
--- a/src/Collision.cpp
+++ b/src/Collision.cpp
@@ -1,7 +1,21 @@
#include "common.h"
#include "patcher.h"
+#include "main.h"
+#include "Lists.h"
#include "Game.h"
+#include "Zones.h"
#include "General.h"
+#include "CullZones.h"
+#include "World.h"
+#include "Entity.h"
+#include "Train.h"
+#include "Streaming.h"
+#include "Pad.h"
+#include "DMAudio.h"
+#include "Population.h"
+#include "FileLoader.h"
+#include "Replay.h"
+#include "CutsceneMgr.h"
#include "RenderBuffer.h"
#include "SurfaceTable.h"
#include "Collision.h"
@@ -19,8 +33,6 @@ enum Direction
eLevelName &CCollision::ms_collisionInMemory = *(eLevelName*)0x8F6250;
CLinkList<CColModel*> &CCollision::ms_colModelCache = *(CLinkList<CColModel*>*)0x95CB58;
-#if 0
-
void
CCollision::Init(void)
{
@@ -29,71 +41,204 @@ CCollision::Init(void)
}
void
+CCollision::Shutdown(void)
+{
+ ms_colModelCache.Shutdown();
+}
+
+void
CCollision::Update(void)
{
- CVector pos = FindPlayerCoors();
+ CVector playerCoors;
+ playerCoors = FindPlayerCoors();
eLevelName level = CTheZones::m_CurrLevel;
- bool changeLevel = false;
+ bool forceLevelChange = false;
+
+ if(CTimer::GetTimeInMilliseconds() < 2000 || CCutsceneMgr::IsCutsceneProcessing())
+ return;
// hardcode a level if there are no zones
if(level == LEVEL_NONE){
if(CGame::currLevel == LEVEL_INDUSTRIAL &&
- pos.x < 400.0f){
+ playerCoors.x < 400.0f){
level = LEVEL_COMMERCIAL;
- changeLevel = true;
+ forceLevelChange = true;
}else if(CGame::currLevel == LEVEL_SUBURBAN &&
- pos.x > -450.0f && pos.y < -1400.0f){
+ playerCoors.x > -450.0f && playerCoors.y < -1400.0f){
level = LEVEL_COMMERCIAL;
- changeLevel = true;
+ forceLevelChange = true;
}else{
- if(pos.x > 800.0f){
+ if(playerCoors.x > 800.0f){
level = LEVEL_INDUSTRIAL;
- changeLevel = true;
- }else if(pos.x < -800.0f){
+ forceLevelChange = true;
+ }else if(playerCoors.x < -800.0f){
level = LEVEL_SUBURBAN;
- changeLevel = true;
+ forceLevelChange = true;
}
}
}
- if(level != LEVEL_NONE && level != CGame::currLevel){
- debug("changing level %d -> %d\n", CGame::currLevel, level);
+ if(level != LEVEL_NONE && level != CGame::currLevel)
CGame::currLevel = level;
- }
if(ms_collisionInMemory != CGame::currLevel)
- LoadCollisionWhenINeedIt(changeLevel);
+ LoadCollisionWhenINeedIt(forceLevelChange);
CStreaming::HaveAllBigBuildingsLoaded(CGame::currLevel);
}
+eLevelName
+GetCollisionInSectorList(CPtrList &list)
+{
+ CPtrNode *node;
+ CEntity *e;
+ int level;
+
+ for(node = list.first; node; node = node->next){
+ e = (CEntity*)node->item;
+ level = CModelInfo::GetModelInfo(e->GetModelIndex())->GetColModel()->level;
+ if(level != LEVEL_NONE)
+ return (eLevelName)level;
+ }
+ return LEVEL_NONE;
+}
+
+// Get a level this sector is in based on collision models
+eLevelName
+GetCollisionInSector(CSector &sect)
+{
+ int level;
+
+ level = GetCollisionInSectorList(sect.m_lists[ENTITYLIST_BUILDINGS]);
+ if(level == LEVEL_NONE)
+ level = GetCollisionInSectorList(sect.m_lists[ENTITYLIST_BUILDINGS_OVERLAP]);
+ if(level == LEVEL_NONE)
+ level = GetCollisionInSectorList(sect.m_lists[ENTITYLIST_OBJECTS]);
+ if(level == LEVEL_NONE)
+ level = GetCollisionInSectorList(sect.m_lists[ENTITYLIST_OBJECTS_OVERLAP]);
+ if(level == LEVEL_NONE)
+ level = GetCollisionInSectorList(sect.m_lists[ENTITYLIST_DUMMIES]);
+ if(level == LEVEL_NONE)
+ level = GetCollisionInSectorList(sect.m_lists[ENTITYLIST_DUMMIES_OVERLAP]);
+ return (eLevelName)level;
+}
+
void
-CCollision::LoadCollisionWhenINeedIt(bool changeLevel)
+CCollision::LoadCollisionWhenINeedIt(bool forceChange)
{
- eLevelName level;
+ eLevelName level, l;
+ bool multipleLevels;
+ CVector playerCoors;
+ CVehicle *veh;
+ CEntryInfoNode *ei;
+ int sx, sy;
+ int xmin, xmax, ymin, ymax;
+ int x, y;
+
level = LEVEL_NONE;
- if(!changeLevel){
- //assert(0 && "unimplemented");
+
+ playerCoors = FindPlayerCoors();
+ sx = CWorld::GetSectorIndexX(playerCoors.x);
+ sy = CWorld::GetSectorIndexY(playerCoors.y);
+ multipleLevels = false;
+
+ veh = FindPlayerVehicle();
+ if(veh && veh->IsTrain()){
+ if(((CTrain*)veh)->m_doorState != TRAIN_DOOR_STATE2)
+ return ;
+ }else if(playerCoors.z < 4.0f && !CCullZones::DoINeedToLoadCollision())
+ return;
+
+ // Figure out whose level's collisions we're most likely to be interested in
+ if(!forceChange){
+ if(veh && veh->IsBoat()){
+ // on water we expect to be between levels
+ multipleLevels = true;
+ }else{
+ xmin = max(sx - 1, 0);
+ xmax = min(sx + 1, NUMSECTORS_X-1);
+ ymin = max(sy - 1, 0);
+ ymax = min(sy + 1, NUMSECTORS_Y-1);
+
+ for(x = xmin; x <= xmax; x++)
+ for(y = ymin; y <= ymax; y++){
+ l = GetCollisionInSector(*CWorld::GetSector(x, y));
+ if(l != LEVEL_NONE){
+ if(level == LEVEL_NONE)
+ level = l;
+ if(level != l)
+ multipleLevels = true;
+ }
+ }
+ }
+
+ if(multipleLevels && veh && veh->IsBoat())
+ for(ei = veh->m_entryInfoList.first; ei; ei = ei->next){
+ level = GetCollisionInSector(*ei->sector);
+ if(level != LEVEL_NONE)
+ break;
+ }
}
- if(level != CGame::currLevel || changeLevel){
+ if(level == CGame::currLevel || forceChange){
CTimer::Stop();
+ DMAudio.SetEffectsFadeVol(0);
+ CPad::StopPadsShaking();
+ LoadCollisionScreen(CGame::currLevel);
+ DMAudio.Service();
+ CPopulation::DealWithZoneChange(ms_collisionInMemory, CGame::currLevel, false);
CStreaming::RemoveIslandsNotUsed(LEVEL_INDUSTRIAL);
CStreaming::RemoveIslandsNotUsed(LEVEL_COMMERCIAL);
CStreaming::RemoveIslandsNotUsed(LEVEL_SUBURBAN);
CStreaming::RemoveBigBuildings(LEVEL_INDUSTRIAL);
CStreaming::RemoveBigBuildings(LEVEL_COMMERCIAL);
CStreaming::RemoveBigBuildings(LEVEL_SUBURBAN);
+ CModelInfo::RemoveColModelsFromOtherLevels(CGame::currLevel);
+ CStreaming::RemoveUnusedModelsInLoadedList();
+ CGame::TidyUpMemory(true, true);
+ CFileLoader::LoadCollisionFromDatFile(CGame::currLevel);
ms_collisionInMemory = CGame::currLevel;
+ CReplay::EmptyReplayBuffer();
+ if(CGame::currLevel != LEVEL_NONE)
+ LoadSplash(GetLevelSplashScreen(CGame::currLevel));
CStreaming::RemoveUnusedBigBuildings(CGame::currLevel);
CStreaming::RemoveUnusedBuildings(CGame::currLevel);
CStreaming::RequestBigBuildings(CGame::currLevel);
- CStreaming::LoadAllRequestedModels();
+ CStreaming::LoadAllRequestedModels(true);
CStreaming::HaveAllBigBuildingsLoaded(CGame::currLevel);
+ CGame::TidyUpMemory(true, true);
CTimer::Update();
+ DMAudio.SetEffectsFadeVol(127);
}
}
-#endif
+void
+CCollision::SortOutCollisionAfterLoad(void)
+{
+ if(ms_collisionInMemory == CGame::currLevel)
+ return;
-WRAPPER void CCollision::SortOutCollisionAfterLoad(void) { EAXJMP(0x40B900); }
+ CModelInfo::RemoveColModelsFromOtherLevels(CGame::currLevel);
+ if(CGame::currLevel != LEVEL_NONE){
+ CFileLoader::LoadCollisionFromDatFile(CGame::currLevel);
+ if(!CGame::playingIntro)
+ LoadSplash(GetLevelSplashScreen(CGame::currLevel));
+ }
+ ms_collisionInMemory = CGame::currLevel;
+ CGame::TidyUpMemory(true, false);
+}
+
+void
+CCollision::LoadCollisionScreen(eLevelName level)
+{
+ static char *levelNames[4] = {
+ "",
+ "IND_ZON",
+ "COM_ZON",
+ "SUB_ZON"
+ };
+
+ // Why twice?
+ LoadingIslandScreen(levelNames[level]);
+ LoadingIslandScreen(levelNames[level]);
+}
//
// Test
@@ -1585,11 +1730,119 @@ CColModel::GetTrianglePoint(CVector &v, int i) const
v = vertices[i];
}
-WRAPPER CColModel& CColModel::operator=(const CColModel& other) { EAXJMP(0x411710); }
+CColModel&
+CColModel::operator=(const CColModel &other)
+{
+ int i;
+ int numVerts;
+
+ assert(0);
+
+ boundingSphere = other.boundingSphere;
+ boundingBox = other.boundingBox;
+
+ // copy spheres
+ if(other.numSpheres){
+ if(numSpheres != other.numSpheres){
+ numSpheres = other.numSpheres;
+ if(spheres)
+ RwFree(spheres);
+ spheres = (CColSphere*)RwMalloc(numSpheres*sizeof(CColSphere));
+ }
+ for(i = 0; i < numSpheres; i++)
+ spheres[i] = other.spheres[i];
+ }else{
+ numSpheres = 0;
+ if(spheres)
+ RwFree(spheres);
+ spheres = nil;
+ }
+
+ // copy lines
+ if(other.numLines){
+ if(numLines != other.numLines){
+ numLines = other.numLines;
+ if(lines)
+ RwFree(lines);
+ lines = (CColLine*)RwMalloc(numLines*sizeof(CColLine));
+ }
+ for(i = 0; i < numLines; i++)
+ lines[i] = other.lines[i];
+ }else{
+ numLines = 0;
+ if(lines)
+ RwFree(lines);
+ lines = nil;
+ }
+
+ // copy boxes
+ if(other.numBoxes){
+ if(numBoxes != other.numBoxes){
+ numBoxes = other.numBoxes;
+ if(boxes)
+ RwFree(boxes);
+ boxes = (CColBox*)RwMalloc(numBoxes*sizeof(CColBox));
+ }
+ for(i = 0; i < numBoxes; i++)
+ boxes[i] = other.boxes[i];
+ }else{
+ numBoxes = 0;
+ if(boxes)
+ RwFree(boxes);
+ boxes = nil;
+ }
+
+ // copy mesh
+ if(other.numTriangles){
+ // copy vertices
+ numVerts = 0;
+ for(i = 0; i < other.numTriangles; i++){
+ if(other.triangles[i].a > numVerts)
+ other.triangles[i].a = numVerts;
+ if(other.triangles[i].b > numVerts)
+ other.triangles[i].b = numVerts;
+ if(other.triangles[i].c > numVerts)
+ other.triangles[i].c = numVerts;
+ }
+ numVerts++;
+ if(vertices)
+ RwFree(vertices);
+ if(numVerts){
+ vertices = (CVector*)RwMalloc(numVerts*sizeof(CVector));
+ for(i = 0; i < numVerts; i++)
+ vertices[i] = other.vertices[i];
+ }
+
+ // copy triangles
+ if(numTriangles != other.numTriangles){
+ numTriangles = other.numTriangles;
+ if(triangles)
+ RwFree(triangles);
+ triangles = (CColTriangle*)RwMalloc(numTriangles*sizeof(CColTriangle));
+ }
+ for(i = 0; i < numTriangles; i++)
+ triangles[i] = other.triangles[i];
+ }else{
+ numTriangles = 0;
+ if(triangles)
+ RwFree(triangles);
+ triangles = nil;
+ if(vertices)
+ RwFree(vertices);
+ vertices = nil;
+ }
+ return *this;
+}
STARTPATCHES
InjectHook(0x4B9C30, (CMatrix& (*)(const CMatrix &src, CMatrix &dst))Invert, PATCH_JUMP);
+ InjectHook(0x40B380, CCollision::Init, PATCH_JUMP);
+ InjectHook(0x40B3A0, CCollision::Shutdown, PATCH_JUMP);
+ InjectHook(0x40B3B0, CCollision::Update, PATCH_JUMP);
+ InjectHook(0x40B5B0, CCollision::LoadCollisionWhenINeedIt, PATCH_JUMP);
+ InjectHook(0x40B900, CCollision::SortOutCollisionAfterLoad, PATCH_JUMP);
+
InjectHook(0x40BB70, CCollision::TestSphereBox, PATCH_JUMP);
InjectHook(0x40E130, CCollision::TestLineBox, PATCH_JUMP);
InjectHook(0x40E5C0, CCollision::TestVerticalLineBox, PATCH_JUMP);
diff --git a/src/Collision.h b/src/Collision.h
index aa125334..5a9058d3 100644
--- a/src/Collision.h
+++ b/src/Collision.h
@@ -118,9 +118,11 @@ public:
static CLinkList<CColModel*> &ms_colModelCache;
static void Init(void);
+ static void Shutdown(void);
static void Update(void);
static void LoadCollisionWhenINeedIt(bool changeLevel);
static void SortOutCollisionAfterLoad(void);
+ static void LoadCollisionScreen(eLevelName level);
static void DrawColModel(const CMatrix &mat, const CColModel &colModel);
static void DrawColModel_Coloured(const CMatrix &mat, const CColModel &colModel, int32 id);
diff --git a/src/CullZones.cpp b/src/CullZones.cpp
index f89d8256..6155ae57 100644
--- a/src/CullZones.cpp
+++ b/src/CullZones.cpp
@@ -2,6 +2,7 @@
#include "patcher.h"
#include "Building.h"
#include "Treadable.h"
+#include "Train.h"
#include "Pools.h"
#include "Timer.h"
#include "Camera.h"
@@ -71,7 +72,6 @@ void
CCullZones::Update(void)
{
bool invisible;
- CVector v;
if(bCullZonesDisabled)
return;
@@ -95,7 +95,7 @@ CCullZones::Update(void)
case 6:
/* Update player attributes */
- CurrentFlags_Player = FindAttributesForCoors(FindPlayerCoors(v),
+ CurrentFlags_Player = FindAttributesForCoors(FindPlayerCoors(),
&CurrentWantedLevelDrop_Player);
break;
}
@@ -152,7 +152,7 @@ CCullZones::FindZoneWithStairsAttributeForPlayer(void)
int i;
CVector coors;
- FindPlayerCoors(coors);
+ coors = FindPlayerCoors();
for(i = 0; i < NumAttributeZones; i++)
if(aAttributeZones[i].attributes & ATTRZONE_STAIRS &&
coors.x >= aAttributeZones[i].minx && coors.x <= aAttributeZones[i].maxx &&
@@ -162,9 +162,33 @@ CCullZones::FindZoneWithStairsAttributeForPlayer(void)
return nil;
}
-WRAPPER void
+void
CCullZones::MarkSubwayAsInvisible(bool visible)
-{ EAXJMP(0x525AF0);
+{
+ int i, n;
+ CEntity *e;
+ CVehicle *v;
+
+ n = CPools::GetBuildingPool()->GetSize();
+ for(i = 0; i < n; i++){
+ e = CPools::GetBuildingPool()->GetSlot(i);
+ if(e && e->bIsSubway)
+ e->bIsVisible = visible;
+ }
+
+ n = CPools::GetTreadablePool()->GetSize();
+ for(i = 0; i < n; i++){
+ e = CPools::GetTreadablePool()->GetSlot(i);
+ if(e && e->bIsSubway)
+ e->bIsVisible = visible;
+ }
+
+ n = CPools::GetVehiclePool()->GetSize();
+ for(i = 0; i < n; i++){
+ v = CPools::GetVehiclePool()->GetSlot(i);
+ if(v && v->IsTrain() && ((CTrain*)v)->m_trackId != 0)
+ v->bIsVisible = visible;
+ }
}
void
diff --git a/src/FileLoader.cpp b/src/FileLoader.cpp
index dd58614d..8213a5c7 100644
--- a/src/FileLoader.cpp
+++ b/src/FileLoader.cpp
@@ -46,7 +46,7 @@ CFileLoader::LoadLevel(const char *filename)
{
int fd;
RwTexDictionary *savedTxd;
- int savedLevel;
+ eLevelName savedLevel;
bool objectsLoaded;
char *line;
char txdname[64];
@@ -79,7 +79,7 @@ CFileLoader::LoadLevel(const char *filename)
}else if(strncmp(line, "COLFILE", 7) == 0){
int level;
sscanf(line+8, "%d", &level);
- CGame::currLevel = level;
+ CGame::currLevel = (eLevelName)level;
LoadingScreenLoadingFile(line+10);
LoadCollisionFile(line+10);
CGame::currLevel = savedLevel;
diff --git a/src/FileMgr.cpp b/src/FileMgr.cpp
index d4e0b89b..954fcdef 100644
--- a/src/FileMgr.cpp
+++ b/src/FileMgr.cpp
@@ -265,10 +265,10 @@ CFileMgr::Seek(int fd, int offset, int whence)
return !!myfseek(fd, offset, whence);
}
-char*
+bool
CFileMgr::ReadLine(int fd, char *buf, int len)
{
- return myfgets(buf, len, fd);
+ return myfgets(buf, len, fd) != nil;
}
int
diff --git a/src/FileMgr.h b/src/FileMgr.h
index f67056f1..bab86e38 100644
--- a/src/FileMgr.h
+++ b/src/FileMgr.h
@@ -15,7 +15,7 @@ public:
static int Read(int fd, char *buf, int len);
static int Write(int fd, char *buf, int len);
static bool Seek(int fd, int offset, int whence);
- static char *ReadLine(int fd, char *buf, int len);
+ static bool ReadLine(int fd, char *buf, int len);
static int CloseFile(int fd);
static int GetErrorReadWrite(int fd);
};
diff --git a/src/Game.cpp b/src/Game.cpp
index f158e9db..cbd55c48 100644
--- a/src/Game.cpp
+++ b/src/Game.cpp
@@ -2,7 +2,7 @@
#include "patcher.h"
#include "Game.h"
-int &CGame::currLevel = *(int*)0x941514;
+eLevelName &CGame::currLevel = *(eLevelName*)0x941514;
bool &CGame::bDemoMode = *(bool*)0x5F4DD0;
bool &CGame::nastyGame = *(bool*)0x5F4DD4;
bool &CGame::frenchGame = *(bool*)0x95CDCB;
@@ -11,6 +11,7 @@ bool &CGame::noProstitutes = *(bool*)0x95CDCF;
bool &CGame::playingIntro = *(bool*)0x95CDC2;
char *CGame::aDatFile = (char*)0x773A48;
+WRAPPER void CGame::Initialise(const char *datFile) { EAXJMP(0x48BED0); }
WRAPPER void CGame::Process(void) { EAXJMP(0x48C850); }
WRAPPER bool CGame::InitialiseOnceBeforeRW(void) { EAXJMP(0x48BB80); }
WRAPPER bool CGame::InitialiseRenderWare(void) { EAXJMP(0x48BBA0); }
diff --git a/src/Game.h b/src/Game.h
index 6b071125..3bc3e633 100644
--- a/src/Game.h
+++ b/src/Game.h
@@ -11,7 +11,7 @@ enum eLevelName
class CGame
{
public:
- static int &currLevel;
+ static eLevelName &currLevel;
static bool &bDemoMode;
static bool &nastyGame;
static bool &frenchGame;
@@ -20,13 +20,18 @@ public:
static bool &playingIntro;
static char *aDatFile; //[32];
- static void Process(void);
+ static void Initialise(const char *datFile);
static bool InitialiseOnceBeforeRW(void);
static bool InitialiseRenderWare(void);
+ static bool InitialiseOnceAfterRW(void);
+ static void InitialiseWhenRestarting(void);
+ static void ShutDown(void);
static void ShutdownRenderWare(void);
static void FinalShutdown(void);
- static void ShutDown(void);
static void ShutDownForRestart(void);
- static void InitialiseWhenRestarting(void);
- static bool InitialiseOnceAfterRW(void);
+ static void Process(void);
+
+ // NB: these do something on PS2
+ static void TidyUpMemory(bool, bool) {}
+ static void DrasticTidyUpMemory(void) {}
};
diff --git a/src/Radar.cpp b/src/Radar.cpp
index 71f9aacd..839aa3af 100644
--- a/src/Radar.cpp
+++ b/src/Radar.cpp
@@ -279,7 +279,7 @@ void CRadar::DrawBlips()
if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN1)
angle = PI + FindPlayerHeading();
else
- angle = FindPlayerHeading() - (PI + atan2(-TheCamera.GetForward().x, TheCamera.GetForward().y));
+ angle = FindPlayerHeading() - (PI + TheCamera.GetForward().Heading());
DrawRotatingRadarSprite(CentreSprite, out.x, out.y, angle, 255);
@@ -868,8 +868,8 @@ void CRadar::TransformRadarPointToRealWorldSpace(CVector2D &out, const CVector2D
{
float s, c;
- s = -sin(atan2(-TheCamera.GetForward().x, TheCamera.GetForward().y));
- c = cos(atan2(-TheCamera.GetForward().x, TheCamera.GetForward().y));
+ s = -sin(TheCamera.GetForward().Heading());
+ c = cos(TheCamera.GetForward().Heading());
if (TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN1 || TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWNPED) {
s = 0.0f;
@@ -885,8 +885,8 @@ void CRadar::TransformRadarPointToRealWorldSpace(CVector2D &out, const CVector2D
else
forward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetPosition() - TheCamera.Cams[TheCamera.ActiveCam].SourceBeforeLookBehind;
- s = -sin(atan2(-forward.x, forward.y));
- c = cos(atan2(-forward.x, forward.y));
+ s = -sin(forward.Heading());
+ c = cos(forward.Heading());
}
out.x = s * in.y + c * in.x;
@@ -915,8 +915,8 @@ void CRadar::TransformRealWorldPointToRadarSpace(CVector2D &out, const CVector2D
c = 1.0f;
}
else if (TheCamera.GetLookDirection() == LOOKING_FORWARD) {
- s = sin(atan2(-TheCamera.GetForward().x, TheCamera.GetForward().y));
- c = cos(atan2(-TheCamera.GetForward().x, TheCamera.GetForward().y));
+ s = sin(TheCamera.GetForward().Heading());
+ c = cos(TheCamera.GetForward().Heading());
}
else {
CVector forward;
@@ -928,8 +928,8 @@ void CRadar::TransformRealWorldPointToRadarSpace(CVector2D &out, const CVector2D
else
forward = TheCamera.Cams[TheCamera.ActiveCam].CamTargetEntity->GetPosition() - TheCamera.Cams[TheCamera.ActiveCam].SourceBeforeLookBehind;
- s = sin(atan2(-forward.x, forward.y));
- c = cos(atan2(-forward.x, forward.y));
+ s = sin(forward.Heading());
+ c = cos(forward.Heading());
}
float x = (in.x - vec2DRadarOrigin.x) * (1.0f / m_RadarRange);
diff --git a/src/RwMatFX.cpp b/src/RwMatFX.cpp
new file mode 100644
index 00000000..ca47e529
--- /dev/null
+++ b/src/RwMatFX.cpp
@@ -0,0 +1,212 @@
+#define WITHD3D
+#include "common.h"
+#include "patcher.h"
+
+struct MatFXNothing { int pad[5]; int effect; };
+
+struct MatFXBump
+{
+ RwFrame *bumpFrame;
+ RwTexture *bumpedTex;
+ RwTexture *bumpTex;
+ float negBumpCoefficient;
+ int pad;
+ int effect;
+};
+
+struct MatFXEnv
+{
+ RwFrame *envFrame;
+ RwTexture *envTex;
+ float envCoeff;
+ int envFBalpha;
+ int pad;
+ int effect;
+};
+
+struct MatFXDual
+{
+ RwTexture *dualTex;
+ RwInt32 srcBlend;
+ RwInt32 dstBlend;
+};
+
+
+struct MatFX
+{
+ union {
+ MatFXNothing n;
+ MatFXBump b;
+ MatFXEnv e;
+ MatFXDual d;
+ } fx[2];
+ int effects;
+};
+
+int &MatFXMaterialDataOffset = *(int*)0x66188C;
+int &MatFXAtomicDataOffset = *(int*)0x66189C;
+
+#ifdef PS2_MATFX
+
+void
+_rpMatFXD3D8AtomicMatFXDefaultRender(RxD3D8InstanceData *inst, int flags, RwTexture *texture)
+{
+ if(flags & (rpGEOMETRYTEXTURED|rpGEOMETRYTEXTURED2) && texture)
+ RwD3D8SetTexture(texture, 0);
+ else
+ RwD3D8SetTexture(NULL, 0);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)(inst->vertexAlpha || inst->material->color.alpha != 0xFF));
+ RwD3D8SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, inst->vertexAlpha != 0);
+ RwD3D8SetPixelShader(0);
+ RwD3D8SetVertexShader(inst->vertexShader);
+ RwD3D8SetStreamSource(0, inst->vertexBuffer, inst->stride);
+
+ if(inst->indexBuffer){
+ RwD3D8SetIndices(inst->indexBuffer, inst->baseIndex);
+ RwD3D8DrawIndexedPrimitive(inst->primType, 0, inst->numVertices, 0, inst->numIndices);
+ }else
+ RwD3D8DrawPrimitive(inst->primType, inst->baseIndex, inst->numVertices);
+}
+
+// map [-1; -1] -> [0; 1], flip V
+static RwMatrix scalenormal = {
+ { 0.5f, 0.0f, 0.0f }, 0,
+ { 0.0f, -0.5f, 0.0f }, 0,
+ { 0.0f, 0.0f, 1.0f }, 0,
+ { 0.5f, 0.5f, 0.0f }, 0,
+
+};
+
+// flipped U for PS2
+static RwMatrix scalenormal_flipU = {
+ { -0.5f, 0.0f, 0.0f }, 0,
+ { 0.0f, -0.5f, 0.0f }, 0,
+ { 0.0f, 0.0f, 1.0f }, 0,
+ { 0.5f, 0.5f, 0.0f }, 0,
+
+};
+
+void
+ApplyEnvMapTextureMatrix(RwTexture *tex, int n, RwFrame *frame)
+{
+ RwD3D8SetTexture(tex, n);
+ RwD3D8SetTextureStageState(n, D3DRS_ALPHAREF, 2);
+ RwD3D8SetTextureStageState(n, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACENORMAL);
+ if(frame){
+ RwMatrix *envframemat = RwMatrixCreate();
+ RwMatrix *tmpmat = RwMatrixCreate();
+ RwMatrix *envmat = RwMatrixCreate();
+
+ RwMatrixInvert(envframemat, RwFrameGetLTM(frame));
+ // PS2
+ // can this be simplified?
+ *tmpmat = *RwFrameGetLTM(RwCameraGetFrame((RwCamera*)RWSRCGLOBAL(curCamera)));
+ RwV3dNegate(&tmpmat->right, &tmpmat->right);
+ tmpmat->flags = 0;
+ tmpmat->pos.x = 0.0f;
+ tmpmat->pos.y = 0.0f;
+ tmpmat->pos.z = 0.0f;
+ RwMatrixMultiply(envmat, tmpmat, envframemat);
+ *tmpmat = *envmat;
+ // important because envframemat can have a translation that we don't like
+ tmpmat->pos.x = 0.0f;
+ tmpmat->pos.y = 0.0f;
+ tmpmat->pos.z = 0.0f;
+ // for some reason we flip in U as well
+ RwMatrixMultiply(envmat, tmpmat, &scalenormal_flipU);
+
+ RwD3D8SetTransform(D3DTS_TEXTURE0+n, envmat);
+
+ RwMatrixDestroy(envmat);
+ RwMatrixDestroy(tmpmat);
+ RwMatrixDestroy(envframemat);
+ }else
+ RwD3D8SetTransform(D3DTS_TEXTURE0+n, &scalenormal);
+}
+
+void
+_rpMatFXD3D8AtomicMatFXEnvRender_ps2(RxD3D8InstanceData *inst, int flags, int sel, RwTexture *texture, RwTexture *envMap)
+{
+ MatFX *matfx = *RWPLUGINOFFSET(MatFX*, inst->material, MatFXMaterialDataOffset);
+ MatFXEnv *env = &matfx->fx[sel].e;
+
+ uint8 intens = (uint8)(env->envCoeff*255.0f);
+
+ if(intens == 0 || envMap == nil){
+ if(sel == 0)
+ _rpMatFXD3D8AtomicMatFXDefaultRender(inst, flags, texture);
+ return;
+ }
+
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)(inst->vertexAlpha || inst->material->color.alpha != 0xFF));
+ if(flags & (rpGEOMETRYTEXTURED|rpGEOMETRYTEXTURED2) && texture)
+ RwD3D8SetTexture(texture, 0);
+ else
+ RwD3D8SetTexture(nil, 0);
+ RwD3D8SetVertexShader(inst->vertexShader);
+ RwD3D8SetStreamSource(0, inst->vertexBuffer, inst->stride);
+ RwD3D8SetIndices(inst->indexBuffer, inst->baseIndex);
+ if(inst->indexBuffer)
+ RwD3D8DrawIndexedPrimitive(inst->primType, 0, inst->numVertices, 0, inst->numIndices);
+ else
+ RwD3D8DrawPrimitive(inst->primType, inst->baseIndex, inst->numVertices);
+
+ // Effect pass
+
+ ApplyEnvMapTextureMatrix(envMap, 0, env->envFrame);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
+ RwUInt32 src, dst, lighting, zwrite, fog, fogcol;
+ RwRenderStateGet(rwRENDERSTATESRCBLEND, &src);
+ RwRenderStateGet(rwRENDERSTATEDESTBLEND, &dst);
+
+ // This is of course not using framebuffer alpha,
+ // but if the diffuse texture had no alpha, the result should actually be rather the same
+ if(env->envFBalpha)
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
+ else
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
+ RwD3D8GetRenderState(D3DRS_LIGHTING, &lighting);
+ RwD3D8GetRenderState(D3DRS_ZWRITEENABLE, &zwrite);
+ RwD3D8GetRenderState(D3DRS_FOGENABLE, &fog);
+ RwD3D8SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
+ if(fog){
+ RwD3D8GetRenderState(D3DRS_FOGCOLOR, &fogcol);
+ RwD3D8SetRenderState(D3DRS_FOGCOLOR, 0);
+ }
+
+ D3DCOLOR texfactor = D3DCOLOR_RGBA(intens, intens, intens, intens);
+ RwD3D8SetRenderState(D3DRS_TEXTUREFACTOR, texfactor);
+ RwD3D8SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE);
+ RwD3D8SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_CURRENT);
+ RwD3D8SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_TFACTOR);
+ // alpha unused
+ //RwD3D8SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
+ //RwD3D8SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_CURRENT);
+ //RwD3D8SetTextureStageState(1, D3DTSS_ALPHAARG2, D3DTA_TFACTOR);
+
+ if(inst->indexBuffer)
+ RwD3D8DrawIndexedPrimitive(inst->primType, 0, inst->numVertices, 0, inst->numIndices);
+ else
+ RwD3D8DrawPrimitive(inst->primType, inst->baseIndex, inst->numVertices);
+
+ // Reset states
+
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)src);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)dst);
+ RwD3D8SetRenderState(D3DRS_LIGHTING, lighting);
+ RwD3D8SetRenderState(D3DRS_ZWRITEENABLE, zwrite);
+ if(fog)
+ RwD3D8SetRenderState(D3DRS_FOGCOLOR, fogcol);
+ RwD3D8SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
+ RwD3D8SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
+ RwD3D8SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, 0);
+ RwD3D8SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0);
+}
+
+STARTPATCHES
+ InjectHook(0x5CF6C0, _rpMatFXD3D8AtomicMatFXEnvRender_ps2, PATCH_JUMP);
+ENDPATCHES
+
+#endif
diff --git a/src/Streaming.cpp b/src/Streaming.cpp
index f75f358a..08fd80f0 100644
--- a/src/Streaming.cpp
+++ b/src/Streaming.cpp
@@ -250,7 +250,6 @@ void
CStreaming::Update(void)
{
CEntity *train;
- CVector playerPos;
CStreamingInfo *si, *prev;
bool requestedSubway = false;
@@ -280,8 +279,7 @@ CStreaming::Update(void)
ms_numModelsRequested < 5 &&
!CRenderer::m_loadingPriority){
StreamVehiclesAndPeds();
- FindPlayerCoors(playerPos);
- StreamZoneModels(playerPos);
+ StreamZoneModels(FindPlayerCoors());
}
LoadRequestedModels();
diff --git a/src/Text.cpp b/src/Text.cpp
index eeb46253..d7d63467 100644
--- a/src/Text.cpp
+++ b/src/Text.cpp
@@ -15,7 +15,7 @@ CText::CText(void)
keyArray.numEntries = 0;
data.chars = nil;
data.numChars = 0;
- unknown = 101; // What's this? version number?
+ encoding = 101;
memset(WideErrorString, 0, sizeof(WideErrorString));
}
@@ -96,6 +96,25 @@ CText::Get(const char *key)
return keyArray.Search(key);
}
+wchar
+CText::GetUpperCase(wchar c)
+{
+ // TODO: do this depending on encoding
+ if(islower(c))
+ return toupper(c);
+ return c;
+}
+
+void
+CText::UpperCase(wchar *s)
+{
+ while(*s){
+ *s = GetUpperCase(*s);
+ s++;
+ }
+}
+
+
void
CKeyArray::Load(uint32 length, uint8 *data, int *offset)
{
@@ -186,9 +205,15 @@ CData::Unload(void)
}
void
-AsciiToUnicode(const char *cs, uint16 *ws)
+AsciiToUnicode(const char *src, uint16 *dst)
+{
+ while((*dst++ = *src++) != '\0');
+}
+
+void
+TextCopy(wchar *dst, const wchar *src)
{
- while((*ws++ = *cs++) != '\0');
+ while((*dst++ = *src++) != '\0');
}
STARTPATCHES
diff --git a/src/Text.h b/src/Text.h
index 1aaef3b6..2592e6b8 100644
--- a/src/Text.h
+++ b/src/Text.h
@@ -1,6 +1,7 @@
#pragma once
-void AsciiToUnicode(const char *cs, wchar *ws);
+void AsciiToUnicode(const char *src, wchar *dst);
+void TextCopy(wchar *dst, const wchar *src);
struct CKeyEntry
{
@@ -37,13 +38,15 @@ class CText
{
CKeyArray keyArray;
CData data;
- int8 unknown;
+ int8 encoding;
public:
CText(void);
~CText(void);
void Load(void);
void Unload(void);
wchar *Get(const char *key);
+ wchar GetUpperCase(wchar c);
+ void UpperCase(wchar *s);
};
extern CText &TheText;
diff --git a/src/World.cpp b/src/World.cpp
index 0a83c595..538e15c5 100644
--- a/src/World.cpp
+++ b/src/World.cpp
@@ -2,13 +2,16 @@
#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"
-WRAPPER void CWorld::Add(CEntity *entity) { EAXJMP(0x4AE930); }
-
CPtrList *CWorld::ms_bigBuildingsList = (CPtrList*)0x6FAB60;
CPtrList &CWorld::ms_listMovingEntityPtrs = *(CPtrList*)0x8F433C;
CSector (*CWorld::ms_aSectors)[NUMSECTORS_X] = (CSector (*)[NUMSECTORS_Y])0x665608;
@@ -23,6 +26,41 @@ 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)
@@ -571,7 +609,98 @@ CWorld::FindRoofZFor3DCoord(float x, float y, float z, bool *found)
}
}
+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);
@@ -587,11 +716,3 @@ STARTPATCHES
InjectHook(0x4B3AE0, CWorld::FindGroundZFor3DCoord, PATCH_JUMP);
InjectHook(0x4B3B50, CWorld::FindRoofZFor3DCoord, PATCH_JUMP);
ENDPATCHES
-
-WRAPPER CPlayerPed *FindPlayerPed(void) { EAXJMP(0x4A1150); }
-WRAPPER CVector &FindPlayerCoors(CVector &v) { EAXJMP(0x4A1030); }
-WRAPPER CVehicle *FindPlayerVehicle(void) { EAXJMP(0x4A10C0); }
-WRAPPER CVehicle *FindPlayerTrain(void) { EAXJMP(0x4A1120); }
-WRAPPER CVector &FindPlayerSpeed(void) { EAXJMP(0x4A1090); }
-WRAPPER CVector FindPlayerCentreOfWorld_NoSniperShift(void) { EAXJMP(0x4A11C0); }
-WRAPPER float FindPlayerHeading(void) { EAXJMP(0x4A1220); }
diff --git a/src/World.h b/src/World.h
index e3a6a8f2..a2a6e3b2 100644
--- a/src/World.h
+++ b/src/World.h
@@ -68,6 +68,7 @@ public:
static bool &bProcessCutsceneOnly;
static void Add(CEntity *entity);
+ static void Remove(CEntity *ent);
static CSector *GetSector(int x, int y) { return &ms_aSectors[y][x]; }
static CPtrList &GetBigBuildingList(eLevelName i) { return ms_bigBuildingsList[i]; }
@@ -108,9 +109,11 @@ public:
class CPlayerPed;
class CVehicle;
CPlayerPed *FindPlayerPed(void);
-CVector &FindPlayerCoors(CVector &v);
CVehicle *FindPlayerVehicle(void);
CVehicle *FindPlayerTrain(void);
+CEntity *FindPlayerEntity(void);
+CVector FindPlayerCoors(void);
CVector &FindPlayerSpeed(void);
-CVector FindPlayerCentreOfWorld_NoSniperShift(void);
+CVector &FindPlayerCentreOfWorld(int32 player);
+CVector &FindPlayerCentreOfWorld_NoSniperShift(void);
float FindPlayerHeading(void);
diff --git a/src/Zones.cpp b/src/Zones.cpp
index d4ce07f6..4d2d9e5d 100644
--- a/src/Zones.cpp
+++ b/src/Zones.cpp
@@ -114,7 +114,7 @@ void
CTheZones::Update(void)
{
CVector pos;
- FindPlayerCoors(pos);
+ pos = FindPlayerCoors();
m_pPlayersZone = FindSmallestZonePosition(&pos);
m_CurrLevel = GetLevelFromPosition(pos);
}
diff --git a/src/audio/DMAudio.cpp b/src/audio/DMAudio.cpp
index 0bed8d4d..63f23c4a 100644
--- a/src/audio/DMAudio.cpp
+++ b/src/audio/DMAudio.cpp
@@ -25,5 +25,5 @@ WRAPPER uint8 cDMAudio::IsMP3RadioChannelAvailable() { EAXJMP(0x57C9F0); }
WRAPPER void cDMAudio::SetEffectsFadeVol(uint8) { EAXJMP(0x57C8F0); }
WRAPPER void cDMAudio::SetMusicFadeVol(uint8) { EAXJMP(0x57C920); }
WRAPPER int32 cDMAudio::CreateEntity(int, void*) { EAXJMP(0x57C7C0); }
-WRAPPER void cDMAudio::SetEntityStatus(int32, int8) { EAXJMP(0x57C810); }
-WRAPPER void cDMAudio::SetRadioInCar(int32) { EAXJMP(0x57CE60); } \ No newline at end of file
+WRAPPER void cDMAudio::SetEntityStatus(int32 id, uint8 enable) { EAXJMP(0x57C810); }
+WRAPPER void cDMAudio::SetRadioInCar(int32) { EAXJMP(0x57CE60); }
diff --git a/src/audio/DMAudio.h b/src/audio/DMAudio.h
index 6df2ceea..646fa2ff 100644
--- a/src/audio/DMAudio.h
+++ b/src/audio/DMAudio.h
@@ -193,7 +193,7 @@ public:
void SetEffectsFadeVol(uint8);
void SetMusicFadeVol(uint8);
int32 CreateEntity(int, void*);
- void SetEntityStatus(int32, int8);
+ void SetEntityStatus(int32 id, uint8 enable);
void SetRadioInCar(int32);
uint8 IsMP3RadioChannelAvailable();
diff --git a/src/config.h b/src/config.h
index 53a7ad11..61b4f9b6 100644
--- a/src/config.h
+++ b/src/config.h
@@ -77,3 +77,5 @@ enum Config {
#define NO_MOVIES
//#define USE_MY_DOCUMENTS
#define NASTY_GAME
+#define PS2_MATFX
+
diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp
index fe5b6dab..145c643c 100644
--- a/src/control/CarCtrl.cpp
+++ b/src/control/CarCtrl.cpp
@@ -3,6 +3,7 @@
#include "CarCtrl.h"
int &CCarCtrl::NumLawEnforcerCars = *(int*)0x8F1B38;
+bool &CCarCtrl::bCarsGeneratedAroundCamera = *(bool*)0x95CD8A;
WRAPPER void CCarCtrl::SwitchVehicleToRealPhysics(CVehicle*) { EAXJMP(0x41F7F0); }
WRAPPER void CCarCtrl::AddToCarArray(int32 id, int32 vehclass) { EAXJMP(0x4182F0); }
diff --git a/src/control/CarCtrl.h b/src/control/CarCtrl.h
index 27ea6293..3469dcf1 100644
--- a/src/control/CarCtrl.h
+++ b/src/control/CarCtrl.h
@@ -11,4 +11,5 @@ public:
static int32 ChooseCarModel(int32 vehclass);
static int32 &NumLawEnforcerCars;
+ static bool &bCarsGeneratedAroundCamera;
};
diff --git a/src/control/Population.cpp b/src/control/Population.cpp
index fd1a89f5..7b1acaaf 100644
--- a/src/control/Population.cpp
+++ b/src/control/Population.cpp
@@ -1,8 +1,10 @@
#include "common.h"
#include "patcher.h"
+#include "Game.h"
#include "Population.h"
PedGroup *CPopulation::ms_pPedGroups = (PedGroup*)0x6E9248;
bool &CPopulation::ms_bGivePedsWeapons = *(bool*)0x95CCF6;
WRAPPER void CPopulation::UpdatePedCount(uint32, bool) { EAXJMP(0x4F5A60); }
+WRAPPER void CPopulation::DealWithZoneChange(eLevelName oldLevel, eLevelName newLevel, bool) { EAXJMP(0x4F6200); }
diff --git a/src/control/Population.h b/src/control/Population.h
index 76442442..e93e14fc 100644
--- a/src/control/Population.h
+++ b/src/control/Population.h
@@ -14,4 +14,5 @@ public:
static bool &ms_bGivePedsWeapons;
static void UpdatePedCount(uint32, bool);
+ static void DealWithZoneChange(eLevelName oldLevel, eLevelName newLevel, bool);
};
diff --git a/src/control/Replay.cpp b/src/control/Replay.cpp
index 8003b407..055c4ada 100644
--- a/src/control/Replay.cpp
+++ b/src/control/Replay.cpp
@@ -165,6 +165,8 @@ void CReplay::Init(void)
bDoLoadSceneWhenDone = false;
}
+WRAPPER void CReplay::EmptyReplayBuffer(void) { EAXJMP(0x595BD0); }
+
void CReplay::DisableReplays(void)
{
bReplayEnabled = false;
@@ -212,7 +214,7 @@ void CReplay::RecordThisFrame(void)
tGeneralPacket* general = (tGeneralPacket*)&Record.m_pBase[Record.m_nOffset];
general->type = REPLAYPACKET_GENERAL;
general->camera_pos.CopyOnlyMatrix(&TheCamera.GetMatrix());
- FindPlayerCoors(general->player_pos);
+ general->player_pos = FindPlayerCoors();
general->in_rcvehicle = CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle ? true : false;
Record.m_nOffset += sizeof(*general);
tClockPacket* clock = (tClockPacket*)&Record.m_pBase[Record.m_nOffset];
@@ -601,8 +603,8 @@ void CReplay::RestoreStuffFromMem(void)
ped->m_modelIndex = -1;
ped->SetModelIndex(mi);
ped->m_pVehicleAnim = 0;
- ped->uAudioEntityId = DMAudio.CreateEntity(0, ped);
- DMAudio.SetEntityStatus(ped->uAudioEntityId, 1);
+ ped->m_audioEntityId = DMAudio.CreateEntity(0, ped);
+ DMAudio.SetEntityStatus(ped->m_audioEntityId, true);
CPopulation::UpdatePedCount(ped->m_nPedType, false);
if (ped->m_wepModelID >= 0)
ped->AddWeaponModel(ped->m_wepModelID);
@@ -639,8 +641,8 @@ void CReplay::RestoreStuffFromMem(void)
car->SetDoorDamage(16, 4, true); /* DOOR_BACK_LEFT */
car->SetDoorDamage(12, 5, true); /* DOOR_BACK_RIGHT */
}
- vehicle->uAudioEntityId = DMAudio.CreateEntity(0, vehicle);
- DMAudio.SetEntityStatus(vehicle->uAudioEntityId, 1);
+ vehicle->m_audioEntityId = DMAudio.CreateEntity(0, vehicle);
+ DMAudio.SetEntityStatus(vehicle->m_audioEntityId, true);
CCarCtrl::UpdateCarCount(vehicle, false);
if ((mi == MI_AIRTRAIN || mi == MI_DEADDODO) && vehicle->m_rwObject){
CVehicleModelInfo* info = (CVehicleModelInfo*)CModelInfo::GetModelInfo(mi);
diff --git a/src/control/Replay.h b/src/control/Replay.h
index b622788f..c4f3b1a2 100644
--- a/src/control/Replay.h
+++ b/src/control/Replay.h
@@ -244,6 +244,7 @@ private:
public:
static void Init(void);
+ static void EmptyReplayBuffer(void);
static void DisableReplays(void);
static void EnableReplays(void);
static void Update(void);
diff --git a/src/entities/CopPed.h b/src/entities/CopPed.h
index d41c2e9e..23d52ad0 100644
--- a/src/entities/CopPed.h
+++ b/src/entities/CopPed.h
@@ -4,18 +4,18 @@
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_POSSESSION_GUN,
+ CRIME_HIT_PED,
+ CRIME_HIT_COP,
+ CRIME_SHOOT_PED,
+ CRIME_SHOOT_COP,
+ CRIME_STEAL_CAR,
+ CRIME_RUN_REDLIGHT,
+ CRIME_RECKLESS_DRIVING,
+ CRIME_SPEEDING,
+ CRIME_RUNOVER_PED,
+ CRIME_RUNOVER_COP,
+ CRIME_SHOOT_HELI,
CRIME_PED_BURNED,
CRIME_COP_BURNED,
CRIME_VEHICLE_BURNED,
diff --git a/src/entities/Dummy.cpp b/src/entities/Dummy.cpp
index a4880175..68b67b5c 100644
--- a/src/entities/Dummy.cpp
+++ b/src/entities/Dummy.cpp
@@ -1,7 +1,57 @@
#include "common.h"
#include "patcher.h"
-#include "Dummy.h"
#include "Pools.h"
+#include "World.h"
+#include "Dummy.h"
void *CDummy::operator new(size_t sz) { return CPools::GetDummyPool()->New(); }
void CDummy::operator delete(void *p, size_t sz) { CPools::GetDummyPool()->Delete((CDummy*)p); }
+
+void
+CDummy::Add(void)
+{
+ int x, xstart, xmid, xend;
+ int y, ystart, ymid, yend;
+ CSector *s;
+ CPtrList *list;
+
+ CRect bounds = GetBoundRect();
+ xstart = CWorld::GetSectorIndexX(bounds.left);
+ xend = CWorld::GetSectorIndexX(bounds.right);
+ xmid = CWorld::GetSectorIndexX((bounds.left + bounds.right)/2.0f);
+ ystart = CWorld::GetSectorIndexY(bounds.top);
+ yend = CWorld::GetSectorIndexY(bounds.bottom);
+ ymid = CWorld::GetSectorIndexY((bounds.top + bounds.bottom)/2.0f);
+ assert(xstart >= 0);
+ assert(xend < NUMSECTORS_X);
+ assert(ystart >= 0);
+ assert(yend < NUMSECTORS_Y);
+
+ for(y = ystart; y <= yend; y++)
+ for(x = xstart; x <= xend; x++){
+ s = CWorld::GetSector(x, y);
+ if(x == xmid && y == ymid)
+ list = &s->m_lists[ENTITYLIST_OBJECTS];
+ else
+ list = &s->m_lists[ENTITYLIST_DUMMIES_OVERLAP];
+ CPtrNode *node = list->InsertItem(this);
+ assert(node);
+ m_entryInfoList.InsertItem(list, node, s);
+ }
+}
+
+void
+CDummy::Remove(void)
+{
+ CEntryInfoNode *node, *next;
+ for(node = m_entryInfoList.first; node; node = next){
+ next = node->next;
+ node->list->DeleteNode(node->listnode);
+ m_entryInfoList.DeleteNode(node);
+ }
+}
+
+STARTPATCHES
+ InjectHook(0x473860, &CDummy::Add_, PATCH_JUMP);
+ InjectHook(0x473AD0, &CDummy::Remove_, PATCH_JUMP);
+ENDPATCHES
diff --git a/src/entities/Dummy.h b/src/entities/Dummy.h
index 034d4c57..4cfef2e2 100644
--- a/src/entities/Dummy.h
+++ b/src/entities/Dummy.h
@@ -9,9 +9,14 @@ public:
CEntryInfoList m_entryInfoList;
CDummy(void) { m_type = ENTITY_TYPE_DUMMY; }
- // TODO: Add, Remove
+ void Add(void);
+ void Remove(void);
static void *operator new(size_t);
static void operator delete(void*, size_t);
+
+ // to make patching virtual functions possible
+ void Add_(void) { CDummy::Add(); }
+ void Remove_(void) { CDummy::Remove(); }
};
static_assert(sizeof(CDummy) == 0x68, "CDummy: error");
diff --git a/src/entities/Ped.cpp b/src/entities/Ped.cpp
index 74cdab09..7f83ea84 100644
--- a/src/entities/Ped.cpp
+++ b/src/entities/Ped.cpp
@@ -771,9 +771,9 @@ CPed::Attack(void)
}
} else {
if (weaponAnimAssoc->animId == ANIM_WEAPON_BAT_V || weaponAnimAssoc->animId == ANIM_WEAPON_BAT_H) {
- DMAudio.PlayOneShot(uAudioEntityId, SOUND_WEAPON_BAT_ATTACK, 1.0f);
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_BAT_ATTACK, 1.0f);
} else if (weaponAnimAssoc->animId == ANIM_FIGHT_PPUNCH) {
- DMAudio.PlayOneShot(uAudioEntityId, SOUND_WEAPON_PUNCH_ATTACK, 0.0f);
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_PUNCH_ATTACK, 0.0f);
}
weaponAnimAssoc->speed = 0.5f;
@@ -843,13 +843,13 @@ CPed::Attack(void)
if (weaponAnimAssoc->currentTime - weaponAnimAssoc->timeStep <= ourWeapon->m_fAnimLoopEnd) {
switch (ourWeaponType) {
case WEAPONTYPE_UZI:
- DMAudio.PlayOneShot(uAudioEntityId, SOUND_WEAPON_UZI_BULLET_ECHO, 0.0f);
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_UZI_BULLET_ECHO, 0.0f);
break;
case WEAPONTYPE_AK47:
- DMAudio.PlayOneShot(uAudioEntityId, SOUND_WEAPON_AK47_BULLET_ECHO, 0.0f);
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_AK47_BULLET_ECHO, 0.0f);
break;
case WEAPONTYPE_M16:
- DMAudio.PlayOneShot(uAudioEntityId, SOUND_WEAPON_M16_BULLET_ECHO, 0.0f);
+ DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_M16_BULLET_ECHO, 0.0f);
break;
default:
break;
@@ -1281,19 +1281,19 @@ CPed::LineUpPedWithCar(PedLineUpPhase phase)
if (m_vehEnterType == VEHICLE_ENTER_FRONT_RIGHT || m_vehEnterType == VEHICLE_ENTER_REAR_RIGHT) {
if (vehIsUpsideDown) {
- m_fRotationDest = -PI + atan2(-veh->GetForward().x, veh->GetForward().y);
+ m_fRotationDest = -PI + veh->GetForward().Heading();
} else if (veh->bIsBus) {
- m_fRotationDest = 0.5 * PI + atan2(-veh->GetForward().x, veh->GetForward().y);
+ m_fRotationDest = 0.5 * PI + veh->GetForward().Heading();
} else {
- m_fRotationDest = atan2(-veh->GetForward().x, veh->GetForward().y);
+ m_fRotationDest = veh->GetForward().Heading();
}
} else if (m_vehEnterType == VEHICLE_ENTER_FRONT_LEFT || m_vehEnterType == VEHICLE_ENTER_REAR_LEFT) {
if (vehIsUpsideDown) {
- m_fRotationDest = atan2(-veh->GetForward().x, veh->GetForward().y);
+ m_fRotationDest = veh->GetForward().Heading();
} else if (veh->bIsBus) {
- m_fRotationDest = -0.5 * PI + atan2(-veh->GetForward().x, veh->GetForward().y);
+ m_fRotationDest = -0.5 * PI + veh->GetForward().Heading();
} else {
- m_fRotationDest = atan2(-veh->GetForward().x, veh->GetForward().y);
+ m_fRotationDest = veh->GetForward().Heading();
}
}
@@ -1539,7 +1539,7 @@ CPed::PlayFootSteps(void)
stepPart = 2;
if (stepPart != 0) {
- DMAudio.PlayOneShot(uAudioEntityId, stepPart == 1 ? SOUND_STEP_START : SOUND_STEP_END, 1.0f);
+ DMAudio.PlayOneShot(m_audioEntityId, stepPart == 1 ? SOUND_STEP_START : SOUND_STEP_END, 1.0f);
CVector footPos(0.0f, 0.0f, 0.0f);
for (RwFrame *frame = GetNodeFrame(stepPart == 1 ? PED_FOOTL : PED_FOOTR); frame; frame = RwFrameGetParent(frame))
diff --git a/src/entities/Physical.cpp b/src/entities/Physical.cpp
index 3e043a32..64e0fb8b 100644
--- a/src/entities/Physical.cpp
+++ b/src/entities/Physical.cpp
@@ -42,7 +42,7 @@ CPhysical::CPhysical(void)
m_vecDamageNormal = CVector(0.0f, 0.0f, 0.0f);
bUsesCollision = true;
- uAudioEntityId = -5;
+ m_audioEntityId = -5;
unk1 = 100.0f;
m_vecCentreOfMass = CVector(0.0f, 0.0f, 0.0f);
field_EC = 0;
diff --git a/src/entities/Physical.h b/src/entities/Physical.h
index 11d2a1f9..749e2dd8 100644
--- a/src/entities/Physical.h
+++ b/src/entities/Physical.h
@@ -14,7 +14,7 @@ class CPhysical : public CEntity
public:
// The not properly indented fields haven't been checked properly yet
- int uAudioEntityId;
+ int32 m_audioEntityId;
float unk1;
CTreadable *m_carTreadable;
CTreadable *m_pedTreadable;
@@ -58,9 +58,8 @@ public:
uint8 bHitByTrain : 1; // from nick
uint8 m_phy_flagA80 : 1;
- uint8 m_nLastCollType;
- uint8 m_nZoneLevel;
- uint8 pad[3];
+ uint8 m_nLastCollType;
+ uint8 m_nZoneLevel;
CPhysical(void);
~CPhysical(void);
diff --git a/src/entities/PlayerInfo.h b/src/entities/PlayerInfo.h
index abda1b23..79f379d5 100644
--- a/src/entities/PlayerInfo.h
+++ b/src/entities/PlayerInfo.h
@@ -1,6 +1,6 @@
#pragma once
-#include "Automobile.h"
-#include "PlayerPed.h"
+
+#include "Collision.h"
enum eWastedBustedState
{
@@ -10,10 +10,9 @@ enum eWastedBustedState
WBSTATE_FAILED_CRITICAL_MISSION,
};
-struct CCivilianPed
-{
-
-};
+class CVehicle;
+class CPlayerPed;
+class CCivilianPed;
class CPlayerInfo
{
@@ -22,10 +21,7 @@ public:
CVehicle *m_pRemoteVehicle;
CColModel m_ColModel;
CVehicle *m_pVehicleEx;
- char m_aszPlayerName[70];
-private:
- int8 _pad0[2];
-public:
+ char m_aPlayerName[70];
int32 m_nMoney;
int32 m_nVisibleMoney;
int32 m_nCollectedPackages;
@@ -40,7 +36,7 @@ public:
int32 m_nNextSexMoneyUpdateTime;
int32 m_nSexFrequency;
CCivilianPed *m_pHooker;
- int8 m_bWBState; // eWastedBustedState
+ int8 m_WBState; // eWastedBustedState
int8 field_217;
int8 field_218;
int8 field_219;
@@ -71,4 +67,4 @@ public:
RwTexture *m_pSkinTexture;
};
-static_assert(sizeof(CPlayerInfo) == 0x13C, "CPlayerPed: error");
+static_assert(sizeof(CPlayerInfo) == 0x13C, "CPlayerInfo: error");
diff --git a/src/entities/Train.h b/src/entities/Train.h
index e591239b..f3fb9a40 100644
--- a/src/entities/Train.h
+++ b/src/entities/Train.h
@@ -2,10 +2,19 @@
#include "Vehicle.h"
+enum
+{
+ TRAIN_DOOR_STATE2 = 2
+};
+
class CTrain : public CVehicle
{
public:
// 0x288
- uint8 stuff[92];
+ uint8 stuff1[20];
+ uint8 m_trackId;
+ uint8 stuff2[7];
+ int16 m_doorState;
+ uint8 stuff3[62];
};
static_assert(sizeof(CTrain) == 0x2E4, "CTrain: error");
diff --git a/src/main.cpp b/src/main.cpp
index d1ffbe6b..c8af9ae0 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -91,6 +91,13 @@ void PrintGameVersion();
RwRGBA gColourTop;
void
+InitialiseGame(void)
+{
+ LoadingScreen(nil, nil, "loadsc0");
+ CGame::Initialise("DATA\\GTA3.DAT");
+}
+
+void
Idle(void *arg)
{
CTimer::Update();
@@ -591,6 +598,61 @@ ResetLoadingScreenBar(void)
NumberOfChunksLoaded = 0.0f;
}
+void
+LoadingIslandScreen(const char *levelName)
+{
+ CSprite2d *splash;
+ wchar *name;
+ char str[100];
+ wchar wstr[80];
+ CRGBA col;
+
+ splash = LoadSplash(nil);
+ name = TheText.Get(levelName);
+ if(!DoRWStuffStartOfFrame(0, 0, 0, 0, 0, 0, 255))
+ return;
+
+ CSprite2d::SetRecipNearClip();
+ CSprite2d::InitPerFrame();
+ CFont::InitPerFrame();
+ DefinedState();
+ col = CRGBA(255, 255, 255, 255);
+ splash->Draw(CRect(0.0f, 0.0f, SCREENW, SCREENH), col, col, col, col);
+ CFont::SetBackgroundOff();
+ CFont::SetScale(1.5f, 1.5f);
+ CFont::SetPropOn();
+ CFont::SetRightJustifyOn();
+ CFont::SetRightJustifyWrap(150.0f);
+ CFont::SetFontStyle(FONT_HEADING);
+ sprintf(str, "WELCOME TO");
+ AsciiToUnicode(str, wstr);
+ CFont::SetDropColor(CRGBA(0, 0, 0, 255));
+ CFont::SetDropShadowPosition(3);
+ CFont::SetColor(CRGBA(243, 237, 71, 255));
+ CFont::SetScale(SCREEN_STRETCH_X(1.2f), SCREEN_STRETCH_Y(1.2f));
+ CFont::PrintString(SCREENW - 20, SCREEN_STRETCH_FROM_BOTTOM(110.0f), TheText.Get("WELCOME"));
+ TextCopy(wstr, name);
+ TheText.UpperCase(wstr);
+ CFont::SetColor(CRGBA(243, 237, 71, 255));
+ CFont::SetScale(SCREEN_STRETCH_X(1.2f), SCREEN_STRETCH_Y(1.2f));
+ CFont::PrintString(SCREENW-20, SCREEN_STRETCH_FROM_BOTTOM(80.0f), wstr);
+ CFont::DrawFonts();
+ DoRWStuffEndOfFrame();
+}
+
+char*
+GetLevelSplashScreen(int level)
+{
+ static char *splashScreens[4] = {
+ nil,
+ "splash1",
+ "splash2",
+ "splash3",
+ };
+
+ return splashScreens[level];
+}
+
char*
GetRandomSplashScreen(void)
{
diff --git a/src/main.h b/src/main.h
index 45948b34..c7914549 100644
--- a/src/main.h
+++ b/src/main.h
@@ -13,6 +13,9 @@ extern wchar *gUString;
class CSprite2d;
+void InitialiseGame(void);
void LoadingScreen(const char *str1, const char *str2, const char *splashscreen);
+void LoadingIslandScreen(const char *levelName);
CSprite2d *LoadSplash(const char *name);
+char *GetLevelSplashScreen(int level);
char *GetRandomSplashScreen(void);
diff --git a/src/math/Vector.h b/src/math/Vector.h
index 60fcdee5..2c431d0d 100644
--- a/src/math/Vector.h
+++ b/src/math/Vector.h
@@ -22,6 +22,7 @@ public:
return *((RwV3d*)this);
}
#endif
+ float Heading(void) const { return atan2(-x, y); }
float Magnitude(void) const { return sqrt(x*x + y*y + z*z); }
float MagnitudeSqr(void) const { return x*x + y*y + z*z; }
float Magnitude2D(void) const { return sqrt(x*x + y*y); }
diff --git a/src/modelinfo/ModelInfo.cpp b/src/modelinfo/ModelInfo.cpp
index acc40824..454a73f1 100644
--- a/src/modelinfo/ModelInfo.cpp
+++ b/src/modelinfo/ModelInfo.cpp
@@ -175,6 +175,23 @@ CModelInfo::IsBoatModel(int32 id)
((CVehicleModelInfo*)GetModelInfo(id))->m_vehicleType == VEHICLE_TYPE_BOAT;
}
+void
+CModelInfo::RemoveColModelsFromOtherLevels(eLevelName level)
+{
+ int i;
+ CBaseModelInfo *mi;
+ CColModel *colmodel;
+
+ for(i = 0; i < MODELINFOSIZE; i++){
+ mi = GetModelInfo(i);
+ if(mi){
+ colmodel = mi->GetColModel();
+ if(colmodel && colmodel->level != LEVEL_NONE && colmodel->level != level)
+ colmodel->RemoveCollisionVolumes();
+ }
+ }
+}
+
STARTPATCHES
InjectHook(0x50B310, CModelInfo::Initialise, PATCH_JUMP);
InjectHook(0x50B5B0, CModelInfo::ShutDown, PATCH_JUMP);
@@ -184,4 +201,5 @@ STARTPATCHES
InjectHook(0x50BAD0, CModelInfo::AddPedModel, PATCH_JUMP);
InjectHook(0x50BA60, CModelInfo::AddVehicleModel, PATCH_JUMP);
InjectHook(0x50B860, (CBaseModelInfo *(*)(const char*, int*))CModelInfo::GetModelInfo, PATCH_JUMP);
+ InjectHook(0x50BBC0, CModelInfo::RemoveColModelsFromOtherLevels, PATCH_JUMP);
ENDPATCHES
diff --git a/src/modelinfo/ModelInfo.h b/src/modelinfo/ModelInfo.h
index 30be96ca..d20367d1 100644
--- a/src/modelinfo/ModelInfo.h
+++ b/src/modelinfo/ModelInfo.h
@@ -36,4 +36,5 @@ public:
}
static bool IsBoatModel(int32 id);
+ static void RemoveColModelsFromOtherLevels(eLevelName level);
};
diff --git a/src/modelinfo/VehicleModelInfo.cpp b/src/modelinfo/VehicleModelInfo.cpp
index 36a6f301..2f1d2027 100644
--- a/src/modelinfo/VehicleModelInfo.cpp
+++ b/src/modelinfo/VehicleModelInfo.cpp
@@ -1006,7 +1006,9 @@ CVehicleModelInfo::SetEnvironmentMapCB(RpMaterial *material, void *data)
if(RpMaterialGetTexture(material) == 0)
RpMaterialSetTexture(material, gpWhiteTexture);
RpMatFXMaterialSetEffects(material, rpMATFXEFFECTENVMAP);
+#ifndef PS2_MATFX
spec *= 0.5f; // Tone down a bit for PC
+#endif
RpMatFXMaterialSetupEnvMap(material, (RwTexture*)data, pMatFxIdentityFrame, false, spec);
}
return material;
diff --git a/src/re3.cpp b/src/re3.cpp
index ec4f4439..4bdb5469 100644
--- a/src/re3.cpp
+++ b/src/re3.cpp
@@ -344,6 +344,8 @@ patch()
Patch<float>(0x46BC61+6, 1.0f); // car distance
InjectHook(0x59E460, printf, PATCH_JUMP);
+ InjectHook(0x475E00, printf, PATCH_JUMP); // _Error
+
// stolen from silentpatch (sorry)
Patch<WORD>(0x5382BF, 0x0EEB);
diff --git a/src/skel/win/win.cpp b/src/skel/win/win.cpp
index 814cac84..2943475b 100644
--- a/src/skel/win/win.cpp
+++ b/src/skel/win/win.cpp
@@ -114,18 +114,11 @@ DWORD _dwMemAvailVideo;
DWORD &_dwOperatingSystemVersion = *(DWORD*)0x70F290;
RwUInt32 &gGameState = *(RwUInt32*)0x8F5838;
-WRAPPER bool InitialiseGame(void) { EAXJMP(0x48E7E0); }
-
-WRAPPER const char *GetLevelSplashScreen(int32 number) { EAXJMP(0x48D750); }
-//
-
-void LoadingScreen(char const *msg1, char const *msg2, char const *screen);
-CSprite2d *LoadSplash(const char *name);
enum eJoypadState
{
- JOYPAD_UNUSED,
- JOYPAD_ATTACHED,
+ JOYPAD_UNUSED,
+ JOYPAD_ATTACHED,
};
struct tJoy