summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--premake5.lua2
-rw-r--r--src/audio/AudioManager.cpp11
-rw-r--r--src/audio/sampman.cpp3
-rw-r--r--src/control/AccidentManager.cpp2
-rw-r--r--src/control/AccidentManager.h1
-rw-r--r--src/control/Bridge.cpp3
-rw-r--r--src/control/CarAI.cpp2
-rw-r--r--src/control/CarCtrl.cpp6
-rw-r--r--src/control/Cranes.cpp4
-rw-r--r--src/control/Cranes.h2
-rw-r--r--src/control/GameLogic.cpp2
-rw-r--r--src/control/Gangs.cpp70
-rw-r--r--src/control/Garages.cpp5
-rw-r--r--src/control/Garages.h2
-rw-r--r--src/control/Phones.cpp6
-rw-r--r--src/control/Phones.h1
-rw-r--r--src/control/Pickups.cpp7
-rw-r--r--src/control/Pickups.h1
-rw-r--r--src/control/Population.cpp59
-rw-r--r--src/control/Population.h22
-rw-r--r--src/control/Record.cpp3
-rw-r--r--src/control/Record.h3
-rw-r--r--src/control/Replay.cpp20
-rw-r--r--src/control/RoadBlocks.cpp2
-rw-r--r--src/control/RoadBlocks.h2
-rw-r--r--src/control/SceneEdit.cpp5
-rw-r--r--src/control/SceneEdit.h7
-rw-r--r--src/control/Script.cpp12
-rw-r--r--src/control/TrafficLights.cpp1
-rw-r--r--src/control/TrafficLights.h1
-rw-r--r--src/core/ControllerConfig.cpp1
-rw-r--r--src/core/ControllerConfig.h62
-rw-r--r--src/core/CutsceneMgr.cpp3
-rw-r--r--src/core/CutsceneMgr.h2
-rw-r--r--src/core/FileLoader.cpp2
-rw-r--r--src/core/FileLoader.h2
-rw-r--r--src/core/Fire.cpp1
-rw-r--r--src/core/Fire.h1
-rw-r--r--src/core/Game.cpp165
-rw-r--r--src/core/Game.h1
-rw-r--r--src/core/Messages.cpp26
-rw-r--r--src/core/Messages.h56
-rw-r--r--src/core/Pools.cpp80
-rw-r--r--src/core/Pools.h4
-rw-r--r--src/core/Streaming.cpp30
-rw-r--r--src/core/User.cpp5
-rw-r--r--src/core/User.h10
-rw-r--r--src/core/Wanted.h2
-rw-r--r--src/core/World.cpp2
-rw-r--r--src/core/World.h2
-rw-r--r--src/core/ZoneCull.cpp12
-rw-r--r--src/core/templates.h17
-rw-r--r--src/peds/PlayerPed.cpp2
-rw-r--r--src/render/Glass.cpp1
-rw-r--r--src/render/Glass.h1
-rw-r--r--src/render/Hud.cpp2
-rw-r--r--src/render/Rubbish.cpp1
-rw-r--r--src/render/Rubbish.h1
-rw-r--r--src/render/Skidmarks.cpp1
-rw-r--r--src/render/Skidmarks.h1
-rw-r--r--src/render/SpecialFX.cpp1
-rw-r--r--src/render/SpecialFX.h1
-rw-r--r--src/render/WaterCannon.cpp1
-rw-r--r--src/render/WaterCannon.h1
-rw-r--r--src/render/Weather.cpp1
-rw-r--r--src/render/Weather.h1
-rw-r--r--src/text/Messages.cpp835
-rw-r--r--src/text/Messages.h69
-rw-r--r--src/text/Pager.cpp193
-rw-r--r--src/text/Pager.h28
-rw-r--r--src/text/Text.cpp (renamed from src/core/Text.cpp)85
-rw-r--r--src/text/Text.h (renamed from src/core/Text.h)7
-rw-r--r--src/weapons/ProjectileInfo.cpp7
-rw-r--r--src/weapons/ProjectileInfo.h9
-rw-r--r--src/weapons/Weapon.cpp1
-rw-r--r--src/weapons/Weapon.h1
76 files changed, 1765 insertions, 239 deletions
diff --git a/premake5.lua b/premake5.lua
index 8b2373a1..b06749c5 100644
--- a/premake5.lua
+++ b/premake5.lua
@@ -15,6 +15,7 @@ workspace "re3"
files { "src/render/*.*" }
files { "src/skel/*.*" }
files { "src/skel/win/*.*" }
+ files { "src/text/*.*" }
files { "src/vehicles/*.*" }
files { "src/weapons/*.*" }
files { "eax/*.*" }
@@ -32,6 +33,7 @@ workspace "re3"
includedirs { "src/render" }
includedirs { "src/skel/" }
includedirs { "src/skel/win" }
+ includedirs { "src/text" }
includedirs { "src/vehicles" }
includedirs { "src/weapons" }
includedirs { "eax" }
diff --git a/src/audio/AudioManager.cpp b/src/audio/AudioManager.cpp
index d32d4207..b82c650c 100644
--- a/src/audio/AudioManager.cpp
+++ b/src/audio/AudioManager.cpp
@@ -7376,12 +7376,12 @@ bool
cAudioManager::ProcessTrainNoise(cVehicleParams *params)
{
CTrain *train;
- int32 emittingVol;
+ uint8 emittingVol;
float speedMultipler;
if(params->m_fDistance >= 90000.f) return 0;
- if(params->m_fVelocityChange <= 0.0f) {
+ if(params->m_fVelocityChange > 0.0f) {
CalculateDistance((bool *)params, params->m_fDistance);
train = (CTrain *)params->m_pVehicle;
speedMultipler = min(1.0f, train->m_fSpeed * 250.f / 51.f);
@@ -7427,11 +7427,8 @@ cAudioManager::ProcessTrainNoise(cVehicleParams *params)
100 * m_sQueueSample.m_nEntityIndex % 987;
m_sQueueSample.m_nLoopCount = 0;
m_sQueueSample.m_bEmittingVolume = emittingVol;
- m_sQueueSample.m_nLoopStart =
- SampleManager.GetSampleLoopStartOffset(
- m_sQueueSample.m_nSampleIndex);
- m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(
- m_sQueueSample.m_nSampleIndex);
+ m_sQueueSample.m_nLoopStart = SampleManager.GetSampleLoopStartOffset(m_sQueueSample.m_nSampleIndex);
+ m_sQueueSample.m_nLoopEnd = SampleManager.GetSampleLoopEndOffset(m_sQueueSample.m_nSampleIndex);
m_sQueueSample.field_48 = 6.0f;
m_sQueueSample.m_fSoundIntensity = 70.0f;
m_sQueueSample.field_56 = 0;
diff --git a/src/audio/sampman.cpp b/src/audio/sampman.cpp
index de222493..9bb2687d 100644
--- a/src/audio/sampman.cpp
+++ b/src/audio/sampman.cpp
@@ -1280,9 +1280,8 @@ cSampleManager::Terminate(void)
bool
cSampleManager::CheckForAnAudioFileOnCD(void)
{
- char filepath[MAX_PATH];
-
#if !defined(GTA3_STEAM_PATCH) && !defined(NO_CDCHECK)
+ char filepath[MAX_PATH];
#if defined(GTA3_1_1_PATCH)
if (_bUseHDDAudio)
diff --git a/src/control/AccidentManager.cpp b/src/control/AccidentManager.cpp
index e2b1f6d0..46d254fc 100644
--- a/src/control/AccidentManager.cpp
+++ b/src/control/AccidentManager.cpp
@@ -6,6 +6,8 @@
CAccidentManager& gAccidentManager = *(CAccidentManager*)0x87FD10;
+WRAPPER void CAccidentManager::Update(void) { EAXJMP(0x456710); }
+
uint16 CAccidentManager::CountActiveAccidents()
{
uint16 accidents = 0;
diff --git a/src/control/AccidentManager.h b/src/control/AccidentManager.h
index 999abddc..6d7f25c8 100644
--- a/src/control/AccidentManager.h
+++ b/src/control/AccidentManager.h
@@ -22,6 +22,7 @@ class CAccidentManager
public:
uint16 CountActiveAccidents();
CAccident* FindNearestAccident(CVector, float*);
+ void Update(void);
};
extern CAccidentManager& gAccidentManager; \ No newline at end of file
diff --git a/src/control/Bridge.cpp b/src/control/Bridge.cpp
index 81f43f32..dacb7aab 100644
--- a/src/control/Bridge.cpp
+++ b/src/control/Bridge.cpp
@@ -123,8 +123,7 @@ void CBridge::FindBridgeEntities()
pLiftRoad = nil;
pLiftPart = nil;
- for (int i = 1; i < CPools::GetBuildingPool()->GetSize(); ++i)
- {
+ for (int i = CPools::GetBuildingPool()->GetSize()-1; i >= 0; i--) {
CBuilding* entry = CPools::GetBuildingPool()->GetSlot(i);
if (entry)
{
diff --git a/src/control/CarAI.cpp b/src/control/CarAI.cpp
index bb0c1ec3..b4dd8777 100644
--- a/src/control/CarAI.cpp
+++ b/src/control/CarAI.cpp
@@ -588,7 +588,7 @@ void CCarAI::MakeWayForCarWithSiren(CVehicle *pVehicle)
CVector2D forward = pVehicle->GetMoveSpeed() / flatSpeed;
float projection = flatSpeed * 45 + 20;
int i = CPools::GetVehiclePool()->GetSize();
- while (i--) {
+ while (--i >= 0) {
CVehicle* vehicle = CPools::GetVehiclePool()->GetSlot(i);
if (!vehicle)
continue;
diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp
index fd6d8057..cf77b5a4 100644
--- a/src/control/CarCtrl.cpp
+++ b/src/control/CarCtrl.cpp
@@ -648,8 +648,7 @@ CCarCtrl::AddToCarArray(int32 id, int32 vehclass)
void
CCarCtrl::RemoveDistantCars()
{
- uint32 i = CPools::GetVehiclePool()->GetSize();
- while (--i){
+ for (int i = CPools::GetVehiclePool()->GetSize()-1; i >= 0; i--) {
CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);
if (!pVehicle)
continue;
@@ -733,8 +732,7 @@ int32
CCarCtrl::CountCarsOfType(int32 mi)
{
int32 total = 0;
- uint32 i = CPools::GetVehiclePool()->GetSize();
- while (i--){
+ for (int i = CPools::GetVehiclePool()->GetSize()-1; i >= 0; i--) {
CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);
if (!pVehicle)
continue;
diff --git a/src/control/Cranes.cpp b/src/control/Cranes.cpp
index ebdbf957..291e147f 100644
--- a/src/control/Cranes.cpp
+++ b/src/control/Cranes.cpp
@@ -5,4 +5,6 @@
WRAPPER bool CCranes::IsThisCarBeingTargettedByAnyCrane(CVehicle*) { EAXJMP(0x5451E0); }
WRAPPER bool CCranes::IsThisCarBeingCarriedByAnyCrane(CVehicle*) { EAXJMP(0x545190); }
WRAPPER void CCranes::ActivateCrane(float, float, float, float, float, float, float, float, bool, bool, float, float) { EAXJMP(0x543650); }
-WRAPPER void CCranes::DeActivateCrane(float, float) { EAXJMP(0x543890); } \ No newline at end of file
+WRAPPER void CCranes::DeActivateCrane(float, float) { EAXJMP(0x543890); }
+WRAPPER void CCranes::InitCranes(void) { EAXJMP(0x543360); }
+WRAPPER void CCranes::UpdateCranes(void) { EAXJMP(0x5439E0); } \ No newline at end of file
diff --git a/src/control/Cranes.h b/src/control/Cranes.h
index be586398..956e2e84 100644
--- a/src/control/Cranes.h
+++ b/src/control/Cranes.h
@@ -10,4 +10,6 @@ public:
static bool IsThisCarBeingCarriedByAnyCrane(CVehicle*);
static void ActivateCrane(float, float, float, float, float, float, float, float, bool, bool, float, float);
static void DeActivateCrane(float, float);
+ static void InitCranes(void);
+ static void UpdateCranes(void);
};
diff --git a/src/control/GameLogic.cpp b/src/control/GameLogic.cpp
index 16727960..ed101cad 100644
--- a/src/control/GameLogic.cpp
+++ b/src/control/GameLogic.cpp
@@ -67,7 +67,7 @@ CGameLogic::Update()
CVector vecRestartPos;
float fRestartFloat;
- if (CCutsceneMgr::ms_cutsceneProcessing) return;
+ if (CCutsceneMgr::IsCutsceneProcessing()) return;
CPlayerInfo &pPlayerInfo = CWorld::Players[CWorld::PlayerInFocus];
switch (pPlayerInfo.m_WBState) {
diff --git a/src/control/Gangs.cpp b/src/control/Gangs.cpp
index 9ff40ef3..f6f9261e 100644
--- a/src/control/Gangs.cpp
+++ b/src/control/Gangs.cpp
@@ -3,7 +3,7 @@
#include "ModelIndices.h"
#include "Gangs.h"
-CGangInfo(&CGangs::Gang)[NUM_GANGS] = *(CGangInfo(*)[9])*(uintptr*)0x6EDF78;
+CGangInfo(&CGangs::Gang)[NUM_GANGS] = *(CGangInfo(*)[NUM_GANGS])*(uintptr*)0x6EDF78;
CGangInfo::CGangInfo() :
m_nVehicleMI(MI_BUS),
@@ -47,53 +47,37 @@ int8 CGangs::GetGangPedModelOverride(int16 gang)
return GetGangInfo(gang)->m_nPedModelOverride;
}
-void CGangs::SaveAllGangData(uint8 *buffer, uint32 *size)
+void CGangs::SaveAllGangData(uint8 *buf, uint32 *size)
{
- buffer[0] = 'G';
- buffer[1] = 'N';
- buffer[2] = 'G';
- buffer[3] = '\0';
- *size = 8 + NUM_GANGS * 16;
- *(uint32*)(buffer + 4) = *size - 8;
- buffer += 8;
- for (int i = 0; i < NUM_GANGS; i++) {
- *(uint32*)(buffer) = GetGangInfo(i)->m_nVehicleMI;
- *(int8*)(buffer + 4) = GetGangInfo(i)->m_nPedModelOverride;
- *(int8*)(buffer + 5) = GetGangInfo(i)->field_5;
- *(int16*)(buffer + 6) = GetGangInfo(i)->field_6;
- *(eWeaponType*)(buffer + 8) = GetGangInfo(i)->m_Weapon1;
- *(eWeaponType*)(buffer + 12) = GetGangInfo(i)->m_Weapon2;
- buffer += 16;
- }
+INITSAVEBUF
+
+ *size = SAVE_HEADER_SIZE + sizeof(Gang);
+ WriteSaveHeader(buf, 'G','N','G','\0', *size - SAVE_HEADER_SIZE);
+ for (int i = 0; i < NUM_GANGS; i++)
+ WriteSaveBuf(buf, Gang[i]);
+
+VALIDATESAVEBUF(*size);
}
-void CGangs::LoadAllGangData(uint8 *buffer, uint32 size)
+void CGangs::LoadAllGangData(uint8 *buf, uint32 size)
{
- Initialize();
- assert(size == 8 + NUM_GANGS * 16);
- assert(buffer[0] == 'G');
- assert(buffer[1] == 'N');
- assert(buffer[2] == 'G');
- assert(buffer[3] == '\0');
- assert(*(uint32*)(buffer + 4) == size - 8);
- buffer += 8;
- for (int i = 0; i < NUM_GANGS; i++){
- GetGangInfo(i)->m_nVehicleMI = *(uint32*)(buffer);
- GetGangInfo(i)->m_nPedModelOverride = *(int8*)(buffer + 4);
- GetGangInfo(i)->field_5 = *(int8*)(buffer + 5);
- GetGangInfo(i)->field_6 = *(int16*)(buffer + 6);
- GetGangInfo(i)->m_Weapon1 = *(eWeaponType*)(buffer + 8);
- GetGangInfo(i)->m_Weapon2 = *(eWeaponType*)(buffer + 12);
- buffer += 16;
- }
+ Initialize();
+
+INITSAVEBUF
+
+ WriteSaveHeader(buf, 'G','N','G','\0', size - SAVE_HEADER_SIZE);
+ for (int i = 0; i < NUM_GANGS; i++)
+ Gang[i] = ReadSaveBuf<CGangInfo>(buf);
+
+VALIDATESAVEBUF(size);
}
STARTPATCHES
-InjectHook(0x4C3FB0, CGangs::Initialize, PATCH_JUMP);
-InjectHook(0x4C4010, CGangs::SetGangVehicleModel, PATCH_JUMP);
-InjectHook(0x4C4030, CGangs::SetGangWeapons, PATCH_JUMP);
-InjectHook(0x4C4050, CGangs::SetGangPedModelOverride, PATCH_JUMP);
-InjectHook(0x4C4070, CGangs::GetGangPedModelOverride, PATCH_JUMP);
-InjectHook(0x4C4080, CGangs::SaveAllGangData, PATCH_JUMP);
-InjectHook(0x4C4100, CGangs::LoadAllGangData, PATCH_JUMP);
+ InjectHook(0x4C3FB0, CGangs::Initialize, PATCH_JUMP);
+ InjectHook(0x4C4010, CGangs::SetGangVehicleModel, PATCH_JUMP);
+ InjectHook(0x4C4030, CGangs::SetGangWeapons, PATCH_JUMP);
+ InjectHook(0x4C4050, CGangs::SetGangPedModelOverride, PATCH_JUMP);
+ InjectHook(0x4C4070, CGangs::GetGangPedModelOverride, PATCH_JUMP);
+ InjectHook(0x4C4080, CGangs::SaveAllGangData, PATCH_JUMP);
+ InjectHook(0x4C4100, CGangs::LoadAllGangData, PATCH_JUMP);
ENDPATCHES
diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp
index 5f55ae66..b5ad37f4 100644
--- a/src/control/Garages.cpp
+++ b/src/control/Garages.cpp
@@ -25,6 +25,9 @@ bool &CGarages::PlayerInGarage = *(bool *)0x95CD83;
int32 &CGarages::PoliceCarsCollected = *(int32 *)0x941444;
uint32 &CGarages::GarageToBeTidied = *(uint32 *)0x623570;
+WRAPPER void CGarages::Init(void) { EAXJMP(0x421C60); }
+WRAPPER void CGarages::Update(void) { EAXJMP(0x421E40); }
+
bool
CGarages::IsModelIndexADoor(uint32 id)
{
@@ -116,4 +119,4 @@ void CGarages::PrintMessages()
}
}
}
-#endif
+#endif \ No newline at end of file
diff --git a/src/control/Garages.h b/src/control/Garages.h
index bcd966e8..41c6b5ad 100644
--- a/src/control/Garages.h
+++ b/src/control/Garages.h
@@ -28,4 +28,6 @@ public:
static bool IsPointWithinHideOutGarage(CVector&);
static bool IsPointWithinAnyGarage(CVector&);
static void PlayerArrestedOrDied();
+ static void Init(void);
+ static void Update(void);
};
diff --git a/src/control/Phones.cpp b/src/control/Phones.cpp
index f8005899..ef978868 100644
--- a/src/control/Phones.cpp
+++ b/src/control/Phones.cpp
@@ -15,6 +15,8 @@ CPhone *&CPhoneInfo::pickedUpPhone = *(CPhone**)0x6283B0;
bool &CPhoneInfo::isPhoneBeingPickedUp = *(bool*)0x6283B4;
CPed *&CPhoneInfo::pedWhoPickingUpPhone = *(CPed**)0x6283B8;
+WRAPPER void CPhoneInfo::Update(void) { EAXJMP(0x42F7A0); }
+
int
CPhoneInfo::FindNearestFreePhone(CVector *pos)
{
@@ -151,8 +153,8 @@ CPhoneInfo::Initialise(void)
pickedUpPhone = nil;
m_nMax = 0;
m_nNum = 0;
- for (int v5 = pool->GetSize() - 1; v5 >= 0; v5--) {
- CBuilding *building = pool->GetSlot(v5);
+ for (int i = pool->GetSize() - 1; i >= 0; i--) {
+ CBuilding *building = pool->GetSlot(i);
if (building) {
if (building->m_modelIndex == MI_PHONEBOOTH1) {
CPhone *maxPhone = &m_aPhones[m_nMax];
diff --git a/src/control/Phones.h b/src/control/Phones.h
index 6842eef4..99ec520c 100644
--- a/src/control/Phones.h
+++ b/src/control/Phones.h
@@ -56,6 +56,7 @@ public:
int GrabPhone(float, float);
void Initialise(void);
void Shutdown(void);
+ void Update(void);
};
extern CPhoneInfo &gPhoneInfo;
diff --git a/src/control/Pickups.cpp b/src/control/Pickups.cpp
index 3ba01e46..91fd889c 100644
--- a/src/control/Pickups.cpp
+++ b/src/control/Pickups.cpp
@@ -47,6 +47,7 @@ uint8 aWeaponBlues[] = { 0, 0, 255, 0, 255, 255, 0, 128, 255, 0, 255, 0, 128, 25
float aWeaponScale[] = { 1.0f, 2.0f, 1.5f, 1.0f, 1.0f, 1.5f, 1.0f, 2.0f, 1.0f, 2.0f, 2.5f, 1.0f, 1.0f, 1.0f, 1.0f };
WRAPPER void CPacManPickups::Render(void) { EAXJMP(0x432F60); }
+WRAPPER void CPacManPickups::Update(void) { EAXJMP(0x432800); }
void
@@ -296,7 +297,7 @@ CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId)
m_pObject->UpdateRwFrame();
bool touched = false;
- for (int32 i = CPools::GetVehiclePool()->GetSize(); i > 0; i--) { // TODO: check if i > 0 is not a R* mistake
+ for (int32 i = CPools::GetVehiclePool()->GetSize()-1; i >= 0; i--) {
CVehicle *vehicle = CPools::GetVehiclePool()->GetSlot(i);
if (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 1.5f)) {
touched = true;
@@ -323,7 +324,7 @@ CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId)
if (CTimer::GetTimeInMilliseconds() > m_nTimer)
explode = true;
else {// added else here since vehicle lookup is useless
- for (int32 i = CPools::GetVehiclePool()->GetSize(); i > 0; i--) { // TODO: check if i > 0 is not a R* mistake
+ for (int32 i = CPools::GetVehiclePool()->GetSize()-1; i >= 0; i--) {
CVehicle *vehicle = CPools::GetVehiclePool()->GetSlot(i);
if (vehicle != nil && vehicle->IsSphereTouchingVehicle(m_pObject->GetPosition().x, m_pObject->GetPosition().y, m_pObject->GetPosition().z, 1.5f)) {
explode = true;
@@ -986,7 +987,7 @@ VALIDATESAVEBUF(size)
void
CPickups::Save(uint8 *buf, uint32 *size)
{
- *size = sizeof(CPickup) * NUMPICKUPS + sizeof(uint16) + sizeof(uint16) + sizeof(uint32) * NUMCOLLECTEDPICKUPS;
+ *size = sizeof(aPickUps) + sizeof(uint16) + sizeof(uint16) + sizeof(aPickUpsCollected);
INITSAVEBUF
diff --git a/src/control/Pickups.h b/src/control/Pickups.h
index cbf3f245..5f9814c3 100644
--- a/src/control/Pickups.h
+++ b/src/control/Pickups.h
@@ -106,4 +106,5 @@ class CPacManPickups
{
public:
static void Render(void);
+ static void Update(void);
};
diff --git a/src/control/Population.cpp b/src/control/Population.cpp
index 3e7ab427..a98721ac 100644
--- a/src/control/Population.cpp
+++ b/src/control/Population.cpp
@@ -11,15 +11,74 @@ int32 &CPopulation::m_AllRandomPedsThisType = *(int32*)0x5FA570;
float &CPopulation::PedDensityMultiplier = *(float*)0x5FA56C;
uint32 &CPopulation::ms_nTotalMissionPeds = *(uint32*)0x8F5F70;
int32 &CPopulation::MaxNumberOfPedsInUse = *(int32*)0x5FA574;
+uint32& CPopulation::ms_nNumCivMale = *(uint32*)0x8F2548;
+uint32& CPopulation::ms_nNumCivFemale = *(uint32*)0x8F5F44;
+uint32& CPopulation::ms_nNumCop = *(uint32*)0x885AFC;
+bool& CPopulation::bZoneChangeHasHappened = *(bool*)0x95CD79;
+uint32& CPopulation::ms_nNumEmergency = *(uint32*)0x94071C;
+uint32& CPopulation::m_CountDownToPedsAtStart = *(uint32*)0x95CD4F;
+uint32& CPopulation::ms_nNumGang1 = *(uint32*)0x8F1B1C;
+uint32& CPopulation::ms_nNumGang2 = *(uint32*)0x8F1B14;
+uint32& CPopulation::ms_nTotalPeds = *(uint32*)0x95CB50;
+uint32& CPopulation::ms_nNumGang3 = *(uint32*)0x8F2548;
+uint32& CPopulation::ms_nTotalGangPeds = *(uint32*)0x885AF0;
+uint32& CPopulation::ms_nNumGang4 = *(uint32*)0x8F1B2C;
+uint32& CPopulation::ms_nTotalCivPeds = *(uint32*)0x8F2C3C;
+uint32& CPopulation::ms_nNumGang5 = *(uint32*)0x8F1B30;
+uint32& CPopulation::ms_nNumDummy = *(uint32*)0x8F1A98;
+uint32& CPopulation::ms_nNumGang6 = *(uint32*)0x8F1B20;
+uint32& CPopulation::ms_nNumGang9 = *(uint32*)0x8F1B10;
+uint32& CPopulation::ms_nNumGang7 = *(uint32*)0x8F1B28;
+uint32& CPopulation::ms_nNumGang8 = *(uint32*)0x8F1B0C;
+WRAPPER void CPopulation::Update(void) { EAXJMP(0x4F39A0); }
+WRAPPER void CPopulation::LoadPedGroups() { EAXJMP(0x4F3870); }
WRAPPER void CPopulation::UpdatePedCount(uint32, bool) { EAXJMP(0x4F5A60); }
WRAPPER void CPopulation::DealWithZoneChange(eLevelName oldLevel, eLevelName newLevel, bool) { EAXJMP(0x4F6200); }
WRAPPER CPed *CPopulation::AddPedInCar(CVehicle *vehicle) { EAXJMP(0x4F5800); }
WRAPPER bool CPopulation::IsPointInSafeZone(CVector *coors) { EAXJMP(0x4F60C0); }
void
+CPopulation::Initialise()
+{
+ debug("Initialising CPopulation...\n");
+
+ ms_nNumCivMale = 0;
+ m_AllRandomPedsThisType = -1;
+ ms_nNumCivFemale = 0;
+ PedDensityMultiplier = 1.0;
+ ms_nNumCop = 0;
+ bZoneChangeHasHappened = 0;
+ ms_nNumEmergency = 0;
+ m_CountDownToPedsAtStart = 2;
+ ms_nNumGang1 = 0;
+ ms_nTotalMissionPeds = 0;
+ ms_nNumGang2 = 0;
+ ms_nTotalPeds = 0;
+ ms_nNumGang3 = 0;
+ ms_nTotalGangPeds = 0;
+ ms_nNumGang4 = 0;
+ ms_nTotalCivPeds = 0;
+ ms_nNumGang5 = 0;
+ ms_nNumDummy = 0;
+ ms_nNumGang6 = 0;
+ ms_nNumGang9 = 0;
+ ms_nNumGang7 = 0;
+ ms_nNumGang8 = 0;
+
+ LoadPedGroups();
+ DealWithZoneChange(LEVEL_COMMERCIAL, LEVEL_INDUSTRIAL, true);
+
+ debug("CPopulation ready\n");
+}
+
+void
CPopulation::RemovePed(CEntity* ent)
{
CWorld::Remove(ent);
delete ent;
}
+
+STARTPATCHES
+InjectHook(0x4F3770, CPopulation::Initialise, PATCH_JUMP);
+ENDPATCHES \ No newline at end of file
diff --git a/src/control/Population.h b/src/control/Population.h
index 7757a7a6..006e6104 100644
--- a/src/control/Population.h
+++ b/src/control/Population.h
@@ -19,7 +19,29 @@ public:
static float &PedDensityMultiplier;
static uint32 &ms_nTotalMissionPeds;
static int32 &MaxNumberOfPedsInUse;
+ static uint32& ms_nNumCivMale;
+ static uint32 &ms_nNumCivFemale;
+ static uint32 &ms_nNumCop;
+ static bool &bZoneChangeHasHappened;
+ static uint32 &ms_nNumEmergency;
+ static uint32& m_CountDownToPedsAtStart;
+ static uint32& ms_nNumGang1;
+ static uint32& ms_nNumGang2;
+ static uint32& ms_nTotalPeds;
+ static uint32& ms_nNumGang3;
+ static uint32& ms_nTotalGangPeds;
+ static uint32& ms_nNumGang4;
+ static uint32& ms_nTotalCivPeds;
+ static uint32& ms_nNumGang5;
+ static uint32& ms_nNumDummy;
+ static uint32& ms_nNumGang6;
+ static uint32& ms_nNumGang9;
+ static uint32& ms_nNumGang7;
+ static uint32& ms_nNumGang8;
+ static void Initialise();
+ static void Update(void);
+ static void LoadPedGroups();
static void UpdatePedCount(uint32, bool);
static void DealWithZoneChange(eLevelName oldLevel, eLevelName newLevel, bool);
static CPed *AddPedInCar(CVehicle *vehicle);
diff --git a/src/control/Record.cpp b/src/control/Record.cpp
index cff4a19b..802ca516 100644
--- a/src/control/Record.cpp
+++ b/src/control/Record.cpp
@@ -6,5 +6,8 @@ uint16 &CRecordDataForGame::RecordingState = *(uint16*)0x95CC24;
uint8 &CRecordDataForChase::Status = *(uint8*)0x95CDCE;
+WRAPPER void CRecordDataForGame::SaveOrRetrieveDataForThisFrame(void) { EAXJMP(0x4341F0); }
+
+WRAPPER void CRecordDataForChase::SaveOrRetrieveDataForThisFrame(void) { EAXJMP(0x4347F0); }
WRAPPER void CRecordDataForChase::ProcessControlCars(void) { EAXJMP(0x435540); }
WRAPPER void CRecordDataForChase::SaveOrRetrieveCarPositions(void) { EAXJMP(0x434B20); } \ No newline at end of file
diff --git a/src/control/Record.h b/src/control/Record.h
index 08e9f7c8..9f396c96 100644
--- a/src/control/Record.h
+++ b/src/control/Record.h
@@ -11,6 +11,7 @@ class CRecordDataForChase
public:
static uint8 &Status;
+ static void SaveOrRetrieveDataForThisFrame(void);
static void ProcessControlCars(void);
static void SaveOrRetrieveCarPositions(void);
};
@@ -20,4 +21,6 @@ class CRecordDataForGame
{
public:
static uint16 &RecordingState;
+
+ static void SaveOrRetrieveDataForThisFrame(void);
};
diff --git a/src/control/Replay.cpp b/src/control/Replay.cpp
index 65ee2840..473b13d3 100644
--- a/src/control/Replay.cpp
+++ b/src/control/Replay.cpp
@@ -1156,7 +1156,7 @@ void CReplay::RestoreStuffFromMem(void)
FindPlayerPed()->m_pWanted = new CWanted(PlayerWanted); /* Nice memory leak */
CWorld::Players[0] = PlayerInfo;
int i = CPools::GetPedPool()->GetSize();
- while (i--){
+ while (--i >= 0) {
CPed* ped = CPools::GetPedPool()->GetSlot(i);
if (!ped)
continue;
@@ -1174,7 +1174,7 @@ void CReplay::RestoreStuffFromMem(void)
ped->AddWeaponModel(ped->m_wepModelID);
}
i = CPools::GetVehiclePool()->GetSize();
- while (i--){
+ while (--i >= 0) {
CVehicle* vehicle = CPools::GetVehiclePool()->GetSlot(i);
if (!vehicle)
continue;
@@ -1233,7 +1233,7 @@ void CReplay::RestoreStuffFromMem(void)
}
PrintElementsInPtrList();
i = CPools::GetObjectPool()->GetSize();
- while (i--){
+ while (--i >= 0) {
CObject* object = CPools::GetObjectPool()->GetSlot(i);
if (!object)
continue;
@@ -1248,7 +1248,7 @@ void CReplay::RestoreStuffFromMem(void)
object->GetMatrix().AttachRW(RwFrameGetMatrix(RpAtomicGetFrame(object->m_rwObject)), false);
}
i = CPools::GetDummyPool()->GetSize();
- while (i--){
+ while (--i >= 0) {
CDummy* dummy = CPools::GetDummyPool()->GetSlot(i);
if (!dummy)
continue;
@@ -1294,7 +1294,7 @@ WRAPPER void CReplay::EmptyPedsAndVehiclePools(void) { EAXJMP(0x5970E0); }
void CReplay::EmptyPedsAndVehiclePools(void)
{
int i = CPools::GetVehiclePool()->GetSize();
- while (i--) {
+ while (--i >= 0) {
CVehicle* v = CPools::GetVehiclePool()->GetSlot(i);
if (!v)
continue;
@@ -1302,7 +1302,7 @@ void CReplay::EmptyPedsAndVehiclePools(void)
delete v;
}
i = CPools::GetPedPool()->GetSize();
- while (i--) {
+ while (--i >= 0) {
CPed* p = CPools::GetPedPool()->GetSlot(i);
if (!p)
continue;
@@ -1319,7 +1319,7 @@ void CReplay::EmptyAllPools(void)
{
EmptyPedsAndVehiclePools();
int i = CPools::GetObjectPool()->GetSize();
- while (i--) {
+ while (--i >= 0) {
CObject* o = CPools::GetObjectPool()->GetSlot(i);
if (!o)
continue;
@@ -1327,7 +1327,7 @@ void CReplay::EmptyAllPools(void)
delete o;
}
i = CPools::GetDummyPool()->GetSize();
- while (i--) {
+ while (--i >= 0) {
CDummy* d = CPools::GetDummyPool()->GetSlot(i);
if (!d)
continue;
@@ -1343,14 +1343,14 @@ WRAPPER void CReplay::MarkEverythingAsNew(void) { EAXJMP(0x597280); }
void CReplay::MarkEverythingAsNew(void)
{
int i = CPools::GetVehiclePool()->GetSize();
- while (i--) {
+ while (--i >= 0) {
CVehicle* v = CPools::GetVehiclePool()->GetSlot(i);
if (!v)
continue;
v->bHasAlreadyBeenRecorded = false;
}
i = CPools::GetPedPool()->GetSize();
- while (i--) {
+ while (--i >= 0) {
CPed* p = CPools::GetPedPool()->GetSlot(i);
if (!p)
continue;
diff --git a/src/control/RoadBlocks.cpp b/src/control/RoadBlocks.cpp
index 3683ff28..ed092391 100644
--- a/src/control/RoadBlocks.cpp
+++ b/src/control/RoadBlocks.cpp
@@ -2,4 +2,6 @@
#include "patcher.h"
#include "RoadBlocks.h"
+WRAPPER void CRoadBlocks::Init(void) { EAXJMP(0x436F50); }
WRAPPER void CRoadBlocks::GenerateRoadBlockCopsForCar(CVehicle*, int32, int16) { EAXJMP(0x4376A0); }
+WRAPPER void CRoadBlocks::GenerateRoadBlocks(void) { EAXJMP(0x436FA0); } \ No newline at end of file
diff --git a/src/control/RoadBlocks.h b/src/control/RoadBlocks.h
index 0d965e48..b1bb3589 100644
--- a/src/control/RoadBlocks.h
+++ b/src/control/RoadBlocks.h
@@ -6,5 +6,7 @@ class CVehicle;
class CRoadBlocks
{
public:
+ static void Init(void);
static void GenerateRoadBlockCopsForCar(CVehicle*, int32, int16);
+ static void GenerateRoadBlocks(void);
};
diff --git a/src/control/SceneEdit.cpp b/src/control/SceneEdit.cpp
new file mode 100644
index 00000000..287b3c98
--- /dev/null
+++ b/src/control/SceneEdit.cpp
@@ -0,0 +1,5 @@
+#include "common.h"
+#include "patcher.h"
+#include "SceneEdit.h"
+
+WRAPPER void CSceneEdit::Update(void) { EAXJMP(0x585570); }
diff --git a/src/control/SceneEdit.h b/src/control/SceneEdit.h
new file mode 100644
index 00000000..f44b0011
--- /dev/null
+++ b/src/control/SceneEdit.h
@@ -0,0 +1,7 @@
+#pragma once
+
+class CSceneEdit
+{
+public:
+ static void Update(void);
+};
diff --git a/src/control/Script.cpp b/src/control/Script.cpp
index 777acb12..ced06f1e 100644
--- a/src/control/Script.cpp
+++ b/src/control/Script.cpp
@@ -662,12 +662,12 @@ void CRunningScript::Process()
if (!CPad::GetPad(0)->GetCrossJustDown())
return;
m_nWakeTime = 0;
- for (int i = 0; i < 6; i++){ /* TODO: add constant for number of messages */
- if (CMessages::BIGMessages[i].m_Current.m_pText)
- CMessages::BIGMessages[i].m_Current.m_nStartTime = 0;
- if (CMessages::BriefMessages[0].m_pText)
- CMessages::BriefMessages[0].m_nStartTime = 0;
+ for (int i = 0; i < NUMBIGMESSAGES; i++){
+ if (CMessages::BIGMessages[i].m_Stack[0].m_pText != nil)
+ CMessages::BIGMessages[i].m_Stack[0].m_nStartTime = 0;
}
+ if (CMessages::BriefMessages[0].m_pText != nil)
+ CMessages::BriefMessages[0].m_nStartTime = 0;
}
int8 CRunningScript::ProcessOneCommand()
@@ -2183,7 +2183,7 @@ int8 CRunningScript::ProcessCommandsFrom100To199(int32 command)
wchar* key = TheText.Get((char*)&CTheScripts::ScriptSpace[m_nIp]);
m_nIp += 8;
CollectParameters(&m_nIp, 2);
- CMessages::AddMessage(key, ScriptParams[0], ScriptParams[1]);
+ CMessages::AddMessageSoon(key, ScriptParams[0], ScriptParams[1]);
return 0;
}
case COMMAND_CLEAR_PRINTS:
diff --git a/src/control/TrafficLights.cpp b/src/control/TrafficLights.cpp
index 61c941b8..2cd09a03 100644
--- a/src/control/TrafficLights.cpp
+++ b/src/control/TrafficLights.cpp
@@ -5,6 +5,7 @@
#include "Vehicle.h"
WRAPPER void CTrafficLights::DisplayActualLight(CEntity *ent) { EAXJMP(0x455800); }
+WRAPPER void CTrafficLights::ScanForLightsOnMap(void) { EAXJMP(0x454F40); }
WRAPPER bool CTrafficLights::ShouldCarStopForLight(CVehicle*, bool) { EAXJMP(0x455350); }
WRAPPER bool CTrafficLights::ShouldCarStopForBridge(CVehicle*) { EAXJMP(0x456460); }
diff --git a/src/control/TrafficLights.h b/src/control/TrafficLights.h
index f0d0248d..06505ed6 100644
--- a/src/control/TrafficLights.h
+++ b/src/control/TrafficLights.h
@@ -13,6 +13,7 @@ class CTrafficLights
{
public:
static void DisplayActualLight(CEntity *ent);
+ static void ScanForLightsOnMap(void);
static uint8 LightForPeds(void);
static bool ShouldCarStopForLight(CVehicle*, bool);
static bool ShouldCarStopForBridge(CVehicle*);
diff --git a/src/core/ControllerConfig.cpp b/src/core/ControllerConfig.cpp
index e3a586b2..6eef4d3d 100644
--- a/src/core/ControllerConfig.cpp
+++ b/src/core/ControllerConfig.cpp
@@ -22,6 +22,7 @@ WRAPPER void CControllerConfigManager::ClearSimButtonPressCheckers() { EAXJMP(0x
WRAPPER void CControllerConfigManager::AffectPadFromKeyBoard() { EAXJMP(0x58D0C0); }
WRAPPER void CControllerConfigManager::AffectPadFromMouse() { EAXJMP(0x58D1A0); }
WRAPPER void CControllerConfigManager::ClearSettingsAssociatedWithAction(int, int) { EAXJMP(0x58EB40); }
+WRAPPER void CControllerConfigManager::GetWideStringOfCommandKeys(uint16, wchar*, uint16) { EAXJMP(0x58F460); }
void CControllerConfigManager::LoadSettings(int32 file)
{
diff --git a/src/core/ControllerConfig.h b/src/core/ControllerConfig.h
index b064a381..ab17577b 100644
--- a/src/core/ControllerConfig.h
+++ b/src/core/ControllerConfig.h
@@ -9,10 +9,64 @@ enum eControllerType
OPTIONAL_EXTRA,
MOUSE,
JOYSTICK,
+ TOTAL_CONTROLLER_TYPES
+};
+
+enum e_ControllerAction
+{
+ PED_FIREWEAPON = 0,
+ PED_CYCLE_WEAPON_RIGHT,
+ PED_CYCLE_WEAPON_LEFT,
+ GO_FORWARD,
+ GO_BACK,
+ GO_LEFT,
+ GO_RIGHT,
+ PED_SNIPER_ZOOM_IN,
+ PED_SNIPER_ZOOM_OUT,
+ VEHICLE_ENTER_EXIT,
+ CAMERA_CHANGE_VIEW_ALL_SITUATIONS,
+ PED_JUMPING,
+ PED_SPRINT,
+ PED_LOOKBEHIND,
+ //PED_DUCK, // VC
+ //PED_ANSWER_PHONE, // VC
+ VEHICLE_ACCELERATE,
+ VEHICLE_BRAKE,
+ VEHICLE_CHANGE_RADIO_STATION,
+ VEHICLE_HORN,
+ TOGGLE_SUBMISSIONS,
+ VEHICLE_HANDBRAKE,
+ PED_1RST_PERSON_LOOK_LEFT,
+ PED_1RST_PERSON_LOOK_RIGHT,
+ VEHICLE_LOOKLEFT,
+ VEHICLE_LOOKRIGHT,
+ VEHICLE_LOOKBEHIND,
+ VEHICLE_TURRETLEFT,
+ VEHICLE_TURRETRIGHT,
+ VEHICLE_TURRETUP,
+ VEHICLE_TURRETDOWN,
+ PED_CYCLE_TARGET_LEFT,
+ PED_CYCLE_TARGET_RIGHT,
+ PED_CENTER_CAMERA_BEHIND_PLAYER,
+ PED_LOCK_TARGET,
+ NETWORK_TALK,
+ PED_1RST_PERSON_LOOK_UP,
+ PED_1RST_PERSON_LOOK_DOWN,
+
+ CONTROLLERACTION_36, // unk, unused?
+
+ TOGGLE_DPAD,
+ SWITCH_DEBUG_CAM_ON,
+ TAKE_SCREEN_SHOT,
+ SHOW_MOUSE_POINTER_TOGGLE,
+
+ TOTAL_CONTROL_ACTIONS
};
class CMouseControllerState;
+#define ACTIONNAME_LENGTH 40
+
class CControllerConfigManager
{
public:
@@ -23,16 +77,13 @@ public:
};
bool firstCapture;
- char _pad0[3];
DIJOYSTATE2 m_OldState;
DIJOYSTATE2 m_NewState;
- wchar m_aActionNames[41][40];
+ wchar m_aActionNames[TOTAL_CONTROL_ACTIONS][ACTIONNAME_LENGTH];
bool m_aButtonStates[17];
- char _pad1[3];
- tControllerConfigBind m_aSettings[41][4];
+ tControllerConfigBind m_aSettings[TOTAL_CONTROL_ACTIONS][TOTAL_CONTROLLER_TYPES];
uint8 m_aSimCheckers[4][4];
bool m_bMouseAssociated;
- char _pad2[3];
void UpdateJoyButtonState(int padnumber);
void UpdateJoyInConfigMenus_ButtonDown(int button, int padnumber);
@@ -52,6 +103,7 @@ public:
void AffectPadFromMouse();
void ClearSettingsAssociatedWithAction(int, int);
+ void GetWideStringOfCommandKeys(uint16, wchar*, uint16);
};
VALIDATE_SIZE(CControllerConfigManager, 0x143C);
diff --git a/src/core/CutsceneMgr.cpp b/src/core/CutsceneMgr.cpp
index b446cd5d..95abfcc9 100644
--- a/src/core/CutsceneMgr.cpp
+++ b/src/core/CutsceneMgr.cpp
@@ -107,8 +107,7 @@ const struct {
int
FindCutsceneAudioTrackId(const char *szCutsceneName)
{
- for (int i = 0; musicNameIdAssoc[i].szTrackName; i++)
- {
+ for (int i = 0; musicNameIdAssoc[i].szTrackName; i++) {
if (!strcmpi(musicNameIdAssoc[i].szTrackName, szCutsceneName))
return musicNameIdAssoc[i].iTrackId;
}
diff --git a/src/core/CutsceneMgr.h b/src/core/CutsceneMgr.h
index 7215a123..8c4a918b 100644
--- a/src/core/CutsceneMgr.h
+++ b/src/core/CutsceneMgr.h
@@ -21,10 +21,10 @@ class CCutsceneMgr
static CAnimBlendAssocGroup &ms_cutsceneAssociations;
static CVector &ms_cutsceneOffset;
static float &ms_cutsceneTimer;
+ static bool &ms_cutsceneProcessing;
public:
static CDirectory *&ms_pCutsceneDir;
static uint32 &ms_cutsceneLoadStatus;
- static bool &ms_cutsceneProcessing;
static bool IsRunning(void) { return ms_running; }
static bool IsCutsceneProcessing(void) { return ms_cutsceneProcessing; }
diff --git a/src/core/FileLoader.cpp b/src/core/FileLoader.cpp
index e9c06201..6f3b0971 100644
--- a/src/core/FileLoader.cpp
+++ b/src/core/FileLoader.cpp
@@ -25,6 +25,8 @@
#include "CdStream.h"
#include "FileLoader.h"
+WRAPPER void CFileLoader::ReloadPaths(const char *filename) { EAXJMP(0x476DB0); }
+
char CFileLoader::ms_line[256];
const char*
diff --git a/src/core/FileLoader.h b/src/core/FileLoader.h
index ea7f47d9..7ef96da3 100644
--- a/src/core/FileLoader.h
+++ b/src/core/FileLoader.h
@@ -39,4 +39,6 @@ public:
static void LoadPickup(const char *line);
static void LoadMapZones(const char *filename);
+
+ static void ReloadPaths(const char *filename);
};
diff --git a/src/core/Fire.cpp b/src/core/Fire.cpp
index 2181f91c..0317ccbe 100644
--- a/src/core/Fire.cpp
+++ b/src/core/Fire.cpp
@@ -32,4 +32,5 @@ CFire* CFireManager::FindNearestFire(CVector vecPos, float* pDistance)
}
WRAPPER void CFireManager::StartFire(CEntity *entityOnFire, CEntity *culprit, float, uint32) { EAXJMP(0x479590); }
+WRAPPER void CFireManager::Update(void) { EAXJMP(0x479310); }
WRAPPER CFire *CFireManager::FindFurthestFire_NeverMindFireMen(CVector coors, float, float) { EAXJMP(0x479430); }
diff --git a/src/core/Fire.h b/src/core/Fire.h
index 5080fd89..c752b2a6 100644
--- a/src/core/Fire.h
+++ b/src/core/Fire.h
@@ -31,6 +31,7 @@ class CFireManager
CFire m_aFires[NUM_FIRES];
public:
void StartFire(CEntity *entityOnFire, CEntity *culprit, float, uint32);
+ void Update(void);
CFire *FindFurthestFire_NeverMindFireMen(CVector coors, float, float);
CFire *FindNearestFire(CVector, float*);
uint32 GetTotalActiveFires() const { return m_nTotalFires; }
diff --git a/src/core/Game.cpp b/src/core/Game.cpp
index b488a217..00d50fa8 100644
--- a/src/core/Game.cpp
+++ b/src/core/Game.cpp
@@ -2,8 +2,60 @@
#include "patcher.h"
#include "Game.h"
#include "main.h"
+#include "AccidentManager.h"
+#include "Antennas.h"
+#include "Bridge.h"
+#include "Camera.h"
+#include "CarCtrl.h"
+#include "CarGen.h"
#include "CdStream.h"
+#include "Clock.h"
+#include "Clouds.h"
+#include "Collision.h"
+#include "Coronas.h"
+#include "Cranes.h"
+#include "CutsceneMgr.h"
+#include "Darkel.h"
+#include "EventList.h"
+#include "FileLoader.h"
#include "FileMgr.h"
+#include "Fire.h"
+#include "Fluff.h"
+#include "Font.h"
+#include "Frontend.h"
+#include "GameLogic.h"
+#include "Garages.h"
+#include "Glass.h"
+#include "Heli.h"
+#include "Pad.h"
+#include "Particle.h"
+#include "Phones.h"
+#include "Pickups.h"
+#include "Plane.h"
+#include "Population.h"
+#include "Record.h"
+#include "Renderer.h"
+#include "Replay.h"
+#include "RoadBlocks.h"
+#include "Rubbish.h"
+#include "SceneEdit.h"
+#include "Script.h"
+#include "Shadows.h"
+#include "Skidmarks.h"
+#include "SpecialFX.h"
+#include "Sprite2d.h"
+#include "Streaming.h"
+#include "TimeCycle.h"
+#include "TrafficLights.h"
+#include "Train.h"
+#include "TxdStore.h"
+#include "User.h"
+#include "WaterCannon.h"
+#include "Weapon.h"
+#include "Weather.h"
+#include "World.h"
+#include "ZoneCull.h"
+#include "Zones.h"
eLevelName &CGame::currLevel = *(eLevelName*)0x941514;
bool &CGame::bDemoMode = *(bool*)0x5F4DD0;
@@ -25,14 +77,125 @@ CGame::InitialiseOnceBeforeRW(void)
}
WRAPPER void CGame::Initialise(const char *datFile) { EAXJMP(0x48BED0); }
+#if 0
WRAPPER void CGame::Process(void) { EAXJMP(0x48C850); }
+#else
+void CGame::Process(void)
+{
+ CPad::UpdatePads();
+ TheCamera.SetMotionBlurAlpha(0);
+ if (TheCamera.m_BlurType == MBLUR_NONE || TheCamera.m_BlurType == MBLUR_SNIPER || TheCamera.m_BlurType == MBLUR_NORMAL)
+ TheCamera.SetMotionBlur(0, 0, 0, 0, MBLUR_NONE);
+ CCutsceneMgr::Update();
+ if (!CCutsceneMgr::IsCutsceneProcessing() && !CTimer::GetIsCodePaused())
+ FrontEndMenuManager.Process();
+ CStreaming::Update();
+ if (!CTimer::GetIsPaused())
+ {
+ CTheZones::Update();
+ CSprite2d::SetRecipNearClip();
+ CSprite2d::InitPerFrame();
+ CFont::InitPerFrame();
+ CRecordDataForGame::SaveOrRetrieveDataForThisFrame();
+ CRecordDataForChase::SaveOrRetrieveDataForThisFrame();
+ CPad::DoCheats();
+ CClock::Update();
+ CWeather::Update();
+ CTheScripts::Process();
+ CCollision::Update();
+ CTrain::UpdateTrains();
+ CPlane::UpdatePlanes();
+ CHeli::UpdateHelis();
+ CDarkel::Update();
+ CSkidmarks::Update();
+ CAntennas::Update();
+ CGlass::Update();
+ CSceneEdit::Update();
+ CEventList::Update();
+ CParticle::Update();
+ gFireManager.Update();
+ CPopulation::Update();
+ CWeapon::UpdateWeapons();
+ if (!CCutsceneMgr::IsRunning())
+ CTheCarGenerators::Process();
+ if (!CReplay::IsPlayingBack())
+ CCranes::UpdateCranes();
+ CClouds::Update();
+ CMovingThings::Update();
+ CWaterCannons::Update();
+ CUserDisplay::Process();
+ CReplay::Update();
+ CWorld::Process();
+ gAccidentManager.Update();
+ CPacManPickups::Update();
+ CPickups::Update();
+ CGarages::Update();
+ CRubbish::Update();
+ CSpecialFX::Update();
+ CTimeCycle::Update();
+ if (CReplay::ShouldStandardCameraBeProcessed())
+ TheCamera.Process();
+ CCullZones::Update();
+ if (!CReplay::IsPlayingBack())
+ CGameLogic::Update();
+ CBridge::Update();
+ CCoronas::DoSunAndMoon();
+ CCoronas::Update();
+ CShadows::UpdateStaticShadows();
+ CShadows::UpdatePermanentShadows();
+ gPhoneInfo.Update();
+ if (!CReplay::IsPlayingBack())
+ {
+ CCarCtrl::GenerateRandomCars();
+ CRoadBlocks::GenerateRoadBlocks();
+ CCarCtrl::RemoveDistantCars();
+ }
+ }
+}
+#endif
+void CGame::ReloadIPLs(void)
+{
+ CTimer::Stop();
+ CWorld::RemoveStaticObjects();
+ ThePaths.Init();
+ CCullZones::Init();
+ CFileLoader::ReloadPaths("GTA3.IDE");
+ CFileLoader::LoadScene("INDUST.IPL");
+ CFileLoader::LoadScene("COMMER.IPL");
+ CFileLoader::LoadScene("SUBURBAN.IPL");
+ CFileLoader::LoadScene("CULL.IPL");
+ ThePaths.PreparePathData();
+ CTrafficLights::ScanForLightsOnMap();
+ CRoadBlocks::Init();
+ CCranes::InitCranes();
+ CGarages::Init();
+ CWorld::RepositionCertainDynamicObjects();
+ CCullZones::ResolveVisibilities();
+ CRenderer::SortBIGBuildings();
+ CTimer::Update();
+}
+#if 0
+WRAPPER void CGame::FinalShutdown(void) { EAXJMP(0x48BEC0); }
+#else
+void
+CGame::FinalShutdown(void)
+{
+ CTxdStore::Shutdown();
+ CPedStats::Shutdown();
+ CdStreamShutdown();
+}
+#endif
WRAPPER bool CGame::InitialiseRenderWare(void) { EAXJMP(0x48BBA0); }
WRAPPER void CGame::ShutdownRenderWare(void) { EAXJMP(0x48BCB0); }
-WRAPPER void CGame::FinalShutdown(void) { EAXJMP(0x48BEC0); }
WRAPPER void CGame::ShutDown(void) { EAXJMP(0x48C3A0); }
WRAPPER void CGame::ShutDownForRestart(void) { EAXJMP(0x48C6B0); }
WRAPPER void CGame::InitialiseWhenRestarting(void) { EAXJMP(0x48C740); }
WRAPPER bool CGame::InitialiseOnceAfterRW(void) { EAXJMP(0x48BD50); }
+
+STARTPATCHES
+ InjectHook(0x48C850, CGame::Process, PATCH_JUMP);
+ InjectHook(0x48BEC0, CGame::FinalShutdown, PATCH_JUMP);
+ENDPATCHES
diff --git a/src/core/Game.h b/src/core/Game.h
index 3bc3e633..dca38bdb 100644
--- a/src/core/Game.h
+++ b/src/core/Game.h
@@ -30,6 +30,7 @@ public:
static void FinalShutdown(void);
static void ShutDownForRestart(void);
static void Process(void);
+ static void ReloadIPLs(void);
// NB: these do something on PS2
static void TidyUpMemory(bool, bool) {}
diff --git a/src/core/Messages.cpp b/src/core/Messages.cpp
deleted file mode 100644
index 9b5342ac..00000000
--- a/src/core/Messages.cpp
+++ /dev/null
@@ -1,26 +0,0 @@
-#include "common.h"
-#include "patcher.h"
-#include "Messages.h"
-
-WRAPPER void CMessages::Display(void) { EAXJMP(0x529800); }
-WRAPPER void CMessages::ClearAllMessagesDisplayedByGame(void) { EAXJMP(0x52B670); }
-WRAPPER int CMessages::WideStringCopy(wchar* dst, wchar* src, unsigned short size) { EAXJMP(0x5294B0); }
-WRAPPER char CMessages::WideStringCompare(wchar* str1, wchar* str2, unsigned short size) { EAXJMP(0x529510); }
-WRAPPER void CMessages::InsertNumberInString(wchar* src, int n1, int n2, int n3, int n4, int n5, int n6, wchar* dst) { EAXJMP(0x52A1A0); }
-WRAPPER void CMessages::InsertPlayerControlKeysInString(wchar* src) { EAXJMP(0x52A490); }
-WRAPPER int CMessages::GetWideStringLength(wchar* src) { EAXJMP(0x529490); }
-WRAPPER void CMessages::AddBigMessage(wchar* key, uint32 time, uint16 pos) { EAXJMP(0x529EB0); }
-WRAPPER void CMessages::AddBigMessageWithNumber(wchar* key, uint32 time, uint16 pos, int n1, int n2, int n3, int n4, int n5, int n6) { EAXJMP(0x52AD10); }
-WRAPPER void CMessages::AddBigMessageWithNumberQ(wchar* key, uint32 time, uint16 pos, int n1, int n2, int n3, int n4, int n5, int n6) { EAXJMP(0x52AE00); }
-WRAPPER void CMessages::AddMessage(wchar* key, uint32 time, uint16 pos) { EAXJMP(0x529900); }
-WRAPPER void CMessages::AddMessageJumpQ(wchar* key, uint32 time, uint16 pos) { EAXJMP(0x529A10); }
-WRAPPER void CMessages::AddMessageSoon(wchar* key, uint32 time, uint16 pos) { EAXJMP(0x529AF0); }
-WRAPPER void CMessages::AddMessageWithNumber(wchar* key, uint32 time, uint16 pos, int n1, int n2, int n3, int n4, int n5, int n6) { EAXJMP(0x52A850); }
-WRAPPER void CMessages::AddMessageJumpQWithNumber(wchar* key, uint32 time, uint16 pos, int n1, int n2, int n3, int n4, int n5, int n6) { EAXJMP(0x52A9A0); }
-WRAPPER void CMessages::AddMessageSoonWithNumber(wchar* key, uint32 time, uint16 pos, int n1, int n2, int n3, int n4, int n5, int n6) { EAXJMP(0x52AAC0); }
-WRAPPER void CMessages::ClearMessages() { EAXJMP(0x529CE0); }
-WRAPPER void CMessages::Init() { EAXJMP(0x529310); }
-WRAPPER void CMessages::Process() { EAXJMP(0x529580); }
-tPreviousBrief *CMessages::PreviousBriefs = (tPreviousBrief *)0x713C08;
-tMessage *CMessages::BriefMessages = (tMessage *)0x8786E0;
-tBigMessage *CMessages::BIGMessages = (tBigMessage *)0x773628;
diff --git a/src/core/Messages.h b/src/core/Messages.h
deleted file mode 100644
index 7caf5786..00000000
--- a/src/core/Messages.h
+++ /dev/null
@@ -1,56 +0,0 @@
-#pragma once
-
-struct tMessage
-{
- wchar *m_pText;
- uint16 m_nFlag;
-private:
- int8 _pad6[2];
-public:
- uint32 m_nTime;
- uint32 m_nStartTime;
- int32 m_nNumber[6];
- wchar *m_pString;
-};
-
-struct tBigMessage
-{
- tMessage m_Current;
- tMessage m_Stack[3];
-};
-
-struct tPreviousBrief
-{
- wchar *m_pText;
- int32 m_nNumber[6];
- wchar *m_pString;
-};
-
-class CMessages
-{
-public:
- static tPreviousBrief *PreviousBriefs;
- static tMessage *BriefMessages;
- static tBigMessage *BIGMessages;
-
-public:
- static void Display(void);
- static void ClearAllMessagesDisplayedByGame(void);
- static int WideStringCopy(wchar* dst, wchar* src, unsigned short size);
- static char WideStringCompare(wchar* str1, wchar* str2, unsigned short size);
- static void InsertNumberInString(wchar* src, int n1, int n2, int n3, int n4, int n5, int n6, wchar* dst);
- static void InsertPlayerControlKeysInString(wchar* src);
- static int GetWideStringLength(wchar *src);
- static void AddBigMessage(wchar* key, uint32 time, uint16 pos);
- static void AddBigMessageWithNumber(wchar* key, uint32 time, uint16 pos, int n1, int n2, int n3, int n4, int n5, int n6);
- static void AddBigMessageWithNumberQ(wchar* key, uint32 time, uint16 pos, int n1, int n2, int n3, int n4, int n5, int n6);
- static void AddMessage(wchar* key, uint32 time, uint16 pos);
- static void AddMessageJumpQ(wchar* key, uint32 time, uint16 pos);
- static void AddMessageSoon(wchar* key, uint32 time, uint16 pos);
- static void AddMessageWithNumber(wchar* key, uint32 time, uint16 pos, int n1, int n2, int n3, int n4, int n5, int n6);
- static void AddMessageJumpQWithNumber(wchar* key, uint32 time, uint16 pos, int n1, int n2, int n3, int n4, int n5, int n6);
- static void AddMessageSoonWithNumber(wchar* key, uint32 time, uint16 pos, int n1, int n2, int n3, int n4, int n5, int n6);
- static void ClearMessages();
- static void Init();
- static void Process();
-};
diff --git a/src/core/Pools.cpp b/src/core/Pools.cpp
index 847fa753..8e66b049 100644
--- a/src/core/Pools.cpp
+++ b/src/core/Pools.cpp
@@ -1,6 +1,8 @@
#include "common.h"
#include "patcher.h"
#include "Pools.h"
+#include "World.h"
+#include "ProjectileInfo.h"
CCPtrNodePool *&CPools::ms_pPtrNodePool = *(CCPtrNodePool**)0x943044;
CEntryInfoNodePool *&CPools::ms_pEntryInfoNodePool = *(CEntryInfoNodePool**)0x941448;
@@ -12,15 +14,9 @@ CObjectPool *&CPools::ms_pObjectPool = *(CObjectPool**)0x880E28;
CDummyPool *&CPools::ms_pDummyPool = *(CDummyPool**)0x8F2C18;
CAudioScriptObjectPool *&CPools::ms_pAudioScriptObjectPool = *(CAudioScriptObjectPool**)0x8F1B6C;
-WRAPPER void CPools::Initialise(void) { EAXJMP(0x4A1770); }
-WRAPPER void CPools::MakeSureSlotInObjectPoolIsEmpty(int32 handle) { EAXJMP(0x4A2DB0); }
-
-#if 0
void
CPools::Initialise(void)
{
- // TODO: unused right now
- assert(0);
ms_pPtrNodePool = new CCPtrNodePool(NUMPTRNODES);
ms_pEntryInfoNodePool = new CEntryInfoNodePool(NUMENTRYINFOS);
ms_pPedPool = new CPedPool(NUMPEDS);
@@ -31,7 +27,33 @@ CPools::Initialise(void)
ms_pDummyPool = new CDummyPool(NUMDUMMIES);
ms_pAudioScriptObjectPool = new CAudioScriptObjectPool(NUMAUDIOSCRIPTOBJECTS);
}
-#endif
+
+void
+CPools::ShutDown(void)
+{
+ debug("PtrNodes left %d\n", ms_pPtrNodePool->GetNoOfUsedSpaces());
+ debug("EntryInfoNodes left %d\n", ms_pEntryInfoNodePool->GetNoOfUsedSpaces());
+ debug("Peds left %d\n", ms_pPedPool->GetNoOfUsedSpaces());
+ debug("Vehicles left %d\n", ms_pVehiclePool->GetNoOfUsedSpaces());
+ debug("Buildings left %d\n", ms_pBuildingPool->GetNoOfUsedSpaces());
+ debug("Treadables left %d\n", ms_pTreadablePool->GetNoOfUsedSpaces());
+ debug("Objects left %d\n", ms_pObjectPool->GetNoOfUsedSpaces());
+ debug("Dummys left %d\n", ms_pDummyPool->GetNoOfUsedSpaces());
+ debug("AudioScriptObjects left %d\n", ms_pAudioScriptObjectPool->GetNoOfUsedSpaces());
+ printf("Shutdown pool started\n");
+
+ delete ms_pPtrNodePool;
+ delete ms_pEntryInfoNodePool;
+ delete ms_pPedPool;
+ delete ms_pVehiclePool;
+ delete ms_pBuildingPool;
+ delete ms_pTreadablePool;
+ delete ms_pObjectPool;
+ delete ms_pDummyPool;
+ delete ms_pAudioScriptObjectPool;
+
+ printf("Shutdown pool done\n");
+}
int32 CPools::GetPedRef(CPed *ped) { return ms_pPedPool->GetIndex(ped); }
CPed *CPools::GetPed(int32 handle) { return ms_pPedPool->GetAt(handle); }
@@ -39,3 +61,47 @@ int32 CPools::GetVehicleRef(CVehicle *vehicle) { return ms_pVehiclePool->GetInde
CVehicle *CPools::GetVehicle(int32 handle) { return ms_pVehiclePool->GetAt(handle); }
int32 CPools::GetObjectRef(CObject *object) { return ms_pObjectPool->GetIndex(object); }
CObject *CPools::GetObject(int32 handle) { return ms_pObjectPool->GetAt(handle); }
+
+void
+CPools::CheckPoolsEmpty()
+{
+ assert(ms_pPedPool->GetNoOfUsedSpaces() == 0);
+ assert(ms_pVehiclePool->GetNoOfUsedSpaces() == 0);
+ printf("pools have beem cleared \n");
+}
+
+
+void
+CPools::MakeSureSlotInObjectPoolIsEmpty(int32 slot)
+{
+ if (ms_pObjectPool->IsFreeSlot(slot)) return;
+
+ CObject *object = ms_pObjectPool->GetSlot(slot);
+ if (object->ObjectCreatedBy == TEMP_OBJECT) {
+ CWorld::Remove(object);
+ delete object;
+ } else if (!CProjectileInfo::RemoveIfThisIsAProjectile(object)) {
+ // relocate to another slot??
+ CObject *newObject = new CObject();
+ CWorld::Remove(object);
+ memcpy(newObject, object, ms_pObjectPool->GetMaxEntrySize());
+ CWorld::Add(newObject);
+ object->m_rwObject = nil;
+ delete object;
+ newObject->m_pFirstReference = nil;
+ }
+}
+
+
+STARTPATCHES
+ InjectHook(0x4A1770, CPools::Initialise, PATCH_JUMP);
+ InjectHook(0x4A1880, CPools::ShutDown, PATCH_JUMP);
+ InjectHook(0x4A1A50, CPools::CheckPoolsEmpty, PATCH_JUMP);
+ InjectHook(0x4A1A80, CPools::GetPedRef, PATCH_JUMP);
+ InjectHook(0x4A1AA0, CPools::GetPed, PATCH_JUMP);
+ InjectHook(0x4A1AC0, CPools::GetVehicleRef, PATCH_JUMP);
+ InjectHook(0x4A1AE0, CPools::GetVehicle, PATCH_JUMP);
+ InjectHook(0x4A1B00, CPools::GetObjectRef, PATCH_JUMP);
+ InjectHook(0x4A1B20, CPools::GetObject, PATCH_JUMP);
+ InjectHook(0x4A2DB0, CPools::MakeSureSlotInObjectPoolIsEmpty, PATCH_JUMP);
+ENDPATCHES
diff --git a/src/core/Pools.h b/src/core/Pools.h
index 4e6bd547..770a1de1 100644
--- a/src/core/Pools.h
+++ b/src/core/Pools.h
@@ -43,11 +43,13 @@ public:
static CAudioScriptObjectPool *GetAudioScriptObjectPool(void) { return ms_pAudioScriptObjectPool; }
static void Initialise(void);
+ static void ShutDown(void);
static int32 GetPedRef(CPed *ped);
static CPed *GetPed(int32 handle);
static int32 GetVehicleRef(CVehicle *vehicle);
static CVehicle *GetVehicle(int32 handle);
static int32 GetObjectRef(CObject *object);
static CObject *GetObject(int32 handle);
- static void MakeSureSlotInObjectPoolIsEmpty(int32 handle);
+ static void CheckPoolsEmpty();
+ static void MakeSureSlotInObjectPoolIsEmpty(int32 slot);
};
diff --git a/src/core/Streaming.cpp b/src/core/Streaming.cpp
index d9dc8628..69e14869 100644
--- a/src/core/Streaming.cpp
+++ b/src/core/Streaming.cpp
@@ -226,7 +226,7 @@ CStreaming::Init(void)
CModelInfo::GetModelInfo("IslandLODsubIND", &islandLODsubInd);
CModelInfo::GetModelInfo("IslandLODsubCOM", &islandLODsubCom);
- for(i = 0; i < CPools::GetBuildingPool()->GetSize(); i++){
+ for(i = CPools::GetBuildingPool()->GetSize()-1; i >= 0; i--){
CBuilding *building = CPools::GetBuildingPool()->GetSlot(i);
if(building == nil)
continue;
@@ -682,8 +682,8 @@ CStreaming::RequestBigBuildings(eLevelName level)
int i, n;
CBuilding *b;
- n = CPools::GetBuildingPool()->GetSize();
- for(i = 0; i < n; i++){
+ n = CPools::GetBuildingPool()->GetSize()-1;
+ for(i = n; i >= 0; i--){
b = CPools::GetBuildingPool()->GetSlot(i);
if(b && b->bIsBIGBuilding && b->m_level == level)
RequestModel(b->GetModelIndex(), STREAMFLAGS_DONT_REMOVE|STREAMFLAGS_PRIORITY);
@@ -837,8 +837,8 @@ CStreaming::RemoveBuildings(eLevelName level)
CEntity *e;
CBaseModelInfo *mi;
- n = CPools::GetBuildingPool()->GetSize();
- for(i = 0; i < n; i++){
+ n = CPools::GetBuildingPool()->GetSize()-1;
+ for(i = n; i >= 0; i--){
e = CPools::GetBuildingPool()->GetSlot(i);
if(e && e->m_level == level){
mi = CModelInfo::GetModelInfo(e->GetModelIndex());
@@ -850,8 +850,8 @@ CStreaming::RemoveBuildings(eLevelName level)
}
}
- n = CPools::GetTreadablePool()->GetSize();
- for(i = 0; i < n; i++){
+ n = CPools::GetTreadablePool()->GetSize()-1;
+ for(i = n; i >= 0; i--){
e = CPools::GetTreadablePool()->GetSlot(i);
if(e && e->m_level == level){
mi = CModelInfo::GetModelInfo(e->GetModelIndex());
@@ -863,8 +863,8 @@ CStreaming::RemoveBuildings(eLevelName level)
}
}
- n = CPools::GetObjectPool()->GetSize();
- for(i = 0; i < n; i++){
+ n = CPools::GetObjectPool()->GetSize()-1;
+ for(i = n; i >= 0; i--){
e = CPools::GetObjectPool()->GetSlot(i);
if(e && e->m_level == level){
mi = CModelInfo::GetModelInfo(e->GetModelIndex());
@@ -876,8 +876,8 @@ CStreaming::RemoveBuildings(eLevelName level)
}
}
- n = CPools::GetDummyPool()->GetSize();
- for(i = 0; i < n; i++){
+ n = CPools::GetDummyPool()->GetSize()-1;
+ for(i = n; i >= 0; i--){
e = CPools::GetDummyPool()->GetSlot(i);
if(e && e->m_level == level){
mi = CModelInfo::GetModelInfo(e->GetModelIndex());
@@ -951,8 +951,8 @@ CStreaming::RemoveBigBuildings(eLevelName level)
CEntity *e;
CBaseModelInfo *mi;
- n = CPools::GetBuildingPool()->GetSize();
- for(i = 0; i < n; i++){
+ n = CPools::GetBuildingPool()->GetSize()-1;
+ for(i = n; i >= 0; i--){
e = CPools::GetBuildingPool()->GetSlot(i);
if(e && e->bIsBIGBuilding && e->m_level == level){
mi = CModelInfo::GetModelInfo(e->GetModelIndex());
@@ -1172,8 +1172,8 @@ CStreaming::HaveAllBigBuildingsLoaded(eLevelName level)
return;
}
- n = CPools::GetBuildingPool()->GetSize();
- for(i = 0; i < n; i++){
+ n = CPools::GetBuildingPool()->GetSize()-1;
+ for(i = n; i >= 0; i--){
e = CPools::GetBuildingPool()->GetSlot(i);
if(e && e->bIsBIGBuilding && e->m_level == level &&
ms_aInfoForModel[e->GetModelIndex()].m_loadState != STREAMSTATE_LOADED)
diff --git a/src/core/User.cpp b/src/core/User.cpp
index f40a06db..600fa443 100644
--- a/src/core/User.cpp
+++ b/src/core/User.cpp
@@ -13,7 +13,7 @@ COnscreenTimer& CUserDisplay::OnscnTimer = *(COnscreenTimer*)0x862238;
CPager& CUserDisplay::Pager = *(CPager*)0x8F2744;
CCurrentVehicle& CUserDisplay::CurrentVehicle = *(CCurrentVehicle*)0x8F5FE8;
-WRAPPER void CPager::AddMessage(wchar*, uint16, uint16, uint16) { EAXJMP(0x52B940); }
+WRAPPER void CUserDisplay::Process(void) { EAXJMP(0x4AD690); }
void COnscreenTimer::Init() {
m_bDisabled = false;
@@ -125,8 +125,7 @@ void COnscreenTimerEntry::Process() {
*timerPtr = (uint32)newTime;
uint32 oldTimeSeconds = oldTime / 1000;
if(oldTimeSeconds <= 11 && newTime / 1000 != oldTimeSeconds) {
- // TODO: use an enum here
- DMAudio.PlayFrontEndSound(0x93, newTime / 1000);
+ DMAudio.PlayFrontEndSound(SOUND_CLOCK_TICK, newTime / 1000);
}
}
}
diff --git a/src/core/User.h b/src/core/User.h
index cac2a318..90b2da55 100644
--- a/src/core/User.h
+++ b/src/core/User.h
@@ -1,5 +1,7 @@
#pragma once
+#include "Pager.h"
+
class COnscreenTimerEntry
{
public:
@@ -50,12 +52,6 @@ class CCurrentVehicle
{
};
-class CPager
-{
-public:
- void AddMessage(wchar*, uint16, uint16, uint16);
-};
-
class CUserDisplay
{
public:
@@ -63,4 +59,6 @@ public:
static COnscreenTimer &OnscnTimer;
static CPager &Pager;
static CCurrentVehicle &CurrentVehicle;
+
+ static void Process(void);
};
diff --git a/src/core/Wanted.h b/src/core/Wanted.h
index 1303365d..15bff1a5 100644
--- a/src/core/Wanted.h
+++ b/src/core/Wanted.h
@@ -43,7 +43,7 @@ class CWanted
public:
int32 m_nChaos;
int32 m_nLastUpdateTime;
- int32 m_nLastWantedLevelChange;
+ uint32 m_nLastWantedLevelChange;
float m_fCrimeSensitivity;
uint8 m_CurrentCops;
uint8 m_MaxCops;
diff --git a/src/core/World.cpp b/src/core/World.cpp
index 3a8367f1..5dea09bd 100644
--- a/src/core/World.cpp
+++ b/src/core/World.cpp
@@ -39,6 +39,8 @@ bool &CWorld::bDoingCarCollisions = *(bool*)0x95CD8C;
bool &CWorld::bIncludeCarTyres = *(bool*)0x95CDAA;
WRAPPER void CWorld::ShutDown(void) { EAXJMP(0x4AE450); }
+WRAPPER void CWorld::RepositionCertainDynamicObjects() { EAXJMP(0x4B42B0); }
+WRAPPER void CWorld::RemoveStaticObjects() { EAXJMP(0x4B4D50); }
WRAPPER void CWorld::RemoveReferencesToDeletedObject(CEntity*) { EAXJMP(0x4B3BF0); }
WRAPPER void CWorld::FindObjectsKindaColliding(const CVector &, float, bool, int16*, int16, CEntity **, bool, bool, bool, bool, bool){ EAXJMP(0x4B2A30); }
WRAPPER void CWorld::ClearExcitingStuffFromArea(const CVector &pos, float radius, uint8) { EAXJMP(0x4B4E70) };
diff --git a/src/core/World.h b/src/core/World.h
index f420207c..a1aa0376 100644
--- a/src/core/World.h
+++ b/src/core/World.h
@@ -122,6 +122,8 @@ public:
static void Initialise();
static void ShutDown();
+ static void RepositionCertainDynamicObjects();
+ static void RemoveStaticObjects();
static void Process();
};
diff --git a/src/core/ZoneCull.cpp b/src/core/ZoneCull.cpp
index dc162147..6d33a1cf 100644
--- a/src/core/ZoneCull.cpp
+++ b/src/core/ZoneCull.cpp
@@ -169,22 +169,22 @@ CCullZones::MarkSubwayAsInvisible(bool visible)
CEntity *e;
CVehicle *v;
- n = CPools::GetBuildingPool()->GetSize();
- for(i = 0; i < n; i++){
+ n = CPools::GetBuildingPool()->GetSize()-1;
+ for(i = n; i >= 0; i--){
e = CPools::GetBuildingPool()->GetSlot(i);
if(e && e->bIsSubway)
e->bIsVisible = visible;
}
- n = CPools::GetTreadablePool()->GetSize();
- for(i = 0; i < n; i++){
+ n = CPools::GetTreadablePool()->GetSize()-1;
+ for(i = n; i >= 0; i--){
e = CPools::GetTreadablePool()->GetSlot(i);
if(e && e->bIsSubway)
e->bIsVisible = visible;
}
- n = CPools::GetVehiclePool()->GetSize();
- for(i = 0; i < n; i++){
+ n = CPools::GetVehiclePool()->GetSize()-1;
+ for(i = n; i >= 0; i--){
v = CPools::GetVehiclePool()->GetSlot(i);
if(v && v->IsTrain() && ((CTrain*)v)->m_nTrackId != TRACK_ELTRAIN)
v->bIsVisible = visible;
diff --git a/src/core/templates.h b/src/core/templates.h
index ef2db33a..f785d647 100644
--- a/src/core/templates.h
+++ b/src/core/templates.h
@@ -44,7 +44,20 @@ public:
m_flags[i].free = 1;
}
}
- int GetSize(void) { return m_size; }
+ ~CPool() {
+ Flush();
+ }
+ void Flush() {
+ if (m_size > 0) {
+ free(m_entries);
+ free(m_flags);
+ m_entries = nil;
+ m_flags = nil;
+ m_size = 0;
+ m_allocPtr = 0;
+ }
+ }
+ int GetSize(void) const { return m_size; }
T *New(void){
bool wrapped = false;
do
@@ -101,12 +114,14 @@ public:
n++;
return n;
}
+ bool IsFreeSlot(int i) { return !!m_flags[i].free; }
void ClearStorage(uint8 *&flags, U *&entries){
free(flags);
free(entries);
flags = nil;
entries = nil;
}
+ uint32 GetMaxEntrySize() const { return sizeof(U); }
void CopyBack(uint8 *&flags, U *&entries){
memcpy(m_flags, flags, sizeof(uint8)*m_size);
memcpy(m_entries, entries, sizeof(U)*m_size);
diff --git a/src/peds/PlayerPed.cpp b/src/peds/PlayerPed.cpp
index 55906c38..69cc316a 100644
--- a/src/peds/PlayerPed.cpp
+++ b/src/peds/PlayerPed.cpp
@@ -100,7 +100,7 @@ CPlayerPed::ClearAdrenaline(void)
{
if (m_bAdrenalineActive && m_nAdrenalineTime != 0) {
m_nAdrenalineTime = 0;
- CTimer::SetTimeStep(1.0f);
+ CTimer::SetTimeScale(1.0f);
}
}
diff --git a/src/render/Glass.cpp b/src/render/Glass.cpp
index 9a233584..5d7dcc86 100644
--- a/src/render/Glass.cpp
+++ b/src/render/Glass.cpp
@@ -17,3 +17,4 @@ CGlass::WindowRespondsToSoftCollision(CEntity *ent, float amount)
}
WRAPPER void CGlass::Render(void) { EAXJMP(0x502350); }
+WRAPPER void CGlass::Update(void) { EAXJMP(0x502050); }
diff --git a/src/render/Glass.h b/src/render/Glass.h
index 60592c39..b29cf173 100644
--- a/src/render/Glass.h
+++ b/src/render/Glass.h
@@ -9,4 +9,5 @@ public:
static void WindowRespondsToCollision(CEntity *ent, float amount, CVector speed, CVector point, bool foo);
static void WindowRespondsToSoftCollision(CEntity *ent, float amount);
static void Render(void);
+ static void Update(void);
};
diff --git a/src/render/Hud.cpp b/src/render/Hud.cpp
index d74816bf..a9215cb7 100644
--- a/src/render/Hud.cpp
+++ b/src/render/Hud.cpp
@@ -755,7 +755,7 @@ void CHud::Draw()
PagerXOffset -= fStep * CTimer::GetTimeStep();
}
if (!PagerSoundPlayed) {
- DMAudio.PlayFrontEndSound(96, 0);
+ DMAudio.PlayFrontEndSound(SOUND_PAGER, 0);
PagerSoundPlayed = 1;
}
}
diff --git a/src/render/Rubbish.cpp b/src/render/Rubbish.cpp
index c925df1c..05d6b544 100644
--- a/src/render/Rubbish.cpp
+++ b/src/render/Rubbish.cpp
@@ -4,3 +4,4 @@
WRAPPER void CRubbish::Render(void) { EAXJMP(0x512190); }
WRAPPER void CRubbish::StirUp(CVehicle *veh) { EAXJMP(0x512690); }
+WRAPPER void CRubbish::Update(void) { EAXJMP(0x511B90); }
diff --git a/src/render/Rubbish.h b/src/render/Rubbish.h
index 9f946dc2..0bc7c397 100644
--- a/src/render/Rubbish.h
+++ b/src/render/Rubbish.h
@@ -7,4 +7,5 @@ class CRubbish
public:
static void Render(void);
static void StirUp(CVehicle *veh); // CAutomobile on PS2
+ static void Update(void);
};
diff --git a/src/render/Skidmarks.cpp b/src/render/Skidmarks.cpp
index bbadd54c..7489f7cd 100644
--- a/src/render/Skidmarks.cpp
+++ b/src/render/Skidmarks.cpp
@@ -3,6 +3,7 @@
#include "Skidmarks.h"
WRAPPER void CSkidmarks::Clear(void) { EAXJMP(0x518130); }
+WRAPPER void CSkidmarks::Update() { EAXJMP(0x518200); }
WRAPPER void CSkidmarks::Render(void) { EAXJMP(0x5182E0); }
WRAPPER void CSkidmarks::RegisterOne(uint32 id, CVector pos, float fwdx, float fwdY, bool *isMuddy, bool *isBloddy) { EAXJMP(0x5185C0); }
diff --git a/src/render/Skidmarks.h b/src/render/Skidmarks.h
index 280150a7..e5372136 100644
--- a/src/render/Skidmarks.h
+++ b/src/render/Skidmarks.h
@@ -4,6 +4,7 @@ class CSkidmarks
{
public:
static void Clear(void);
+ static void Update(void);
static void Render(void);
static void RegisterOne(uint32 id, CVector pos, float fwdx, float fwdY, bool *isMuddy, bool *isBloddy);
};
diff --git a/src/render/SpecialFX.cpp b/src/render/SpecialFX.cpp
index 09881831..f1fd3f09 100644
--- a/src/render/SpecialFX.cpp
+++ b/src/render/SpecialFX.cpp
@@ -13,6 +13,7 @@
#include "World.h"
WRAPPER void CSpecialFX::Render(void) { EAXJMP(0x518DC0); }
+WRAPPER void CSpecialFX::Update(void) { EAXJMP(0x518D40); }
WRAPPER void CMotionBlurStreaks::RegisterStreak(int32 id, uint8 r, uint8 g, uint8 b, CVector p1, CVector p2) { EAXJMP(0x519460); }
diff --git a/src/render/SpecialFX.h b/src/render/SpecialFX.h
index c3966f33..a747d1c9 100644
--- a/src/render/SpecialFX.h
+++ b/src/render/SpecialFX.h
@@ -4,6 +4,7 @@ class CSpecialFX
{
public:
static void Render(void);
+ static void Update(void);
};
class CMotionBlurStreaks
diff --git a/src/render/WaterCannon.cpp b/src/render/WaterCannon.cpp
index 9398c847..7f44116b 100644
--- a/src/render/WaterCannon.cpp
+++ b/src/render/WaterCannon.cpp
@@ -2,5 +2,6 @@
#include "patcher.h"
#include "WaterCannon.h"
+WRAPPER void CWaterCannons::Update(void) { EAXJMP(0x522510); }
WRAPPER void CWaterCannons::UpdateOne(uint32 id, CVector *pos, CVector *dir) { EAXJMP(0x522470); }
WRAPPER void CWaterCannons::Render(void) { EAXJMP(0x522550); }
diff --git a/src/render/WaterCannon.h b/src/render/WaterCannon.h
index 55949803..de9d0344 100644
--- a/src/render/WaterCannon.h
+++ b/src/render/WaterCannon.h
@@ -3,6 +3,7 @@
class CWaterCannons
{
public:
+ static void Update(void);
static void UpdateOne(uint32 id, CVector *pos, CVector *dir);
static void Render(void);
};
diff --git a/src/render/Weather.cpp b/src/render/Weather.cpp
index 452eca92..db1bc80b 100644
--- a/src/render/Weather.cpp
+++ b/src/render/Weather.cpp
@@ -28,6 +28,7 @@ bool &CWeather::bScriptsForceRain = *(bool*)0x95CD7D;
bool &CWeather::Stored_StateStored = *(bool*)0x95CDC1;
WRAPPER void CWeather::RenderRainStreaks(void) { EAXJMP(0x524550); }
+WRAPPER void CWeather::Update(void) { EAXJMP(0x522C10); }
void CWeather::ReleaseWeather()
{
diff --git a/src/render/Weather.h b/src/render/Weather.h
index bbf8498e..41cc5c0e 100644
--- a/src/render/Weather.h
+++ b/src/render/Weather.h
@@ -34,6 +34,7 @@ public:
static bool &Stored_StateStored;
static void RenderRainStreaks(void);
+ static void Update(void);
static void ReleaseWeather();
static void ForceWeather(int16);
diff --git a/src/text/Messages.cpp b/src/text/Messages.cpp
new file mode 100644
index 00000000..c5259910
--- /dev/null
+++ b/src/text/Messages.cpp
@@ -0,0 +1,835 @@
+#define DIRECTINPUT_VERSION 0x0800
+#include "dinput.h"
+
+#include "common.h"
+#include "patcher.h"
+#include "Messages.h"
+#include "RwHelper.h"
+#include "Hud.h"
+#include "User.h"
+#include "Timer.h"
+#include "Text.h"
+
+#include "ControllerConfig.h"
+
+tMessage(&CMessages::BriefMessages)[NUMBRIEFMESSAGES] = *(tMessage(*)[NUMBRIEFMESSAGES])*(uintptr*)0x8786E0;
+tPreviousBrief(&CMessages::PreviousBriefs)[NUMPREVIOUSBRIEFS] = *(tPreviousBrief(*)[NUMPREVIOUSBRIEFS])*(uintptr*)0x713C08;
+tBigMessage(&CMessages::BIGMessages)[NUMBIGMESSAGES] = *(tBigMessage(*)[NUMBIGMESSAGES])*(uintptr*)0x773628;
+char CMessages::PreviousMissionTitle[16]; // unused
+
+void
+CMessages::Init()
+{
+ ClearMessages();
+
+ for (int32 i = 0; i < NUMPREVIOUSBRIEFS; i++) {
+ PreviousBriefs[i].m_pText = nil;
+ PreviousBriefs[i].m_pString = nil;
+ }
+}
+
+uint16
+CMessages::GetWideStringLength(wchar *src)
+{
+ uint16 length = 0;
+ while (*(src++)) length++;
+ return length;
+}
+
+void
+CMessages::WideStringCopy(wchar *dst, wchar *src, uint16 size)
+{
+ int32 i = 0;
+ if (src) {
+ while (i < size - 1) {
+ if (!src[i]) break;
+ dst[i] = src[i];
+ i++;
+ }
+ } else {
+ while (i < size - 1)
+ dst[i++] = '\0';
+ }
+ dst[i] = '\0';
+}
+
+bool
+CMessages::WideStringCompare(wchar *str1, wchar *str2, uint16 size)
+{
+ uint16 len1 = GetWideStringLength(str1);
+ uint16 len2 = GetWideStringLength(str2);
+ if (len1 != len2 && (len1 < size || len2 < size))
+ return false;
+
+ for (int32 i = 0; i < size; i++) {
+ if (!str1[i])
+ break;
+
+ if (str1[i] != str2[i])
+ return false;
+ }
+ return true;
+}
+
+void
+CMessages::Process()
+{
+ for (int32 style = 0; style < 6; style++) {
+ if (BIGMessages[style].m_Stack[0].m_pText != nil && CTimer::GetTimeInMilliseconds() > BIGMessages[style].m_Stack[0].m_nTime + BIGMessages[style].m_Stack[0].m_nStartTime) {
+ BIGMessages[style].m_Stack[0].m_pText = nil;
+
+ int32 i = 0;
+ while (i < 3) {
+ if (BIGMessages[style].m_Stack[i + 1].m_pText == nil) break;
+ BIGMessages[style].m_Stack[i] = BIGMessages[style].m_Stack[i + 1];
+ i++;
+ }
+
+ BIGMessages[style].m_Stack[i].m_pText = nil;
+ BIGMessages[style].m_Stack[0].m_nStartTime = CTimer::GetTimeInMilliseconds();
+ }
+ }
+
+ if (BriefMessages[0].m_pText != nil && CTimer::GetTimeInMilliseconds() > BriefMessages[0].m_nTime + BriefMessages[0].m_nStartTime) {
+ BriefMessages[0].m_pText = nil;
+ int32 i = 0;
+ while (i < NUMBRIEFMESSAGES-1) {
+ if (BriefMessages[i + 1].m_pText == nil)
+ break;
+
+ BriefMessages[i] = BriefMessages[i + 1];
+ i++;
+ }
+ CMessages::BriefMessages[i].m_pText = nil;
+ CMessages::BriefMessages[0].m_nStartTime = CTimer::GetTimeInMilliseconds();
+ if (BriefMessages[0].m_pText != nil)
+ AddToPreviousBriefArray(
+ BriefMessages[0].m_pText,
+ BriefMessages[0].m_nNumber[0],
+ BriefMessages[0].m_nNumber[1],
+ BriefMessages[0].m_nNumber[2],
+ BriefMessages[0].m_nNumber[3],
+ BriefMessages[0].m_nNumber[4],
+ BriefMessages[0].m_nNumber[5],
+ BriefMessages[0].m_pString);
+ }
+}
+
+void
+CMessages::Display()
+{
+ wchar outstr[260];
+
+ DefinedState();
+
+ for (int32 i = 0; i < NUMBIGMESSAGES; i++) {
+ InsertNumberInString(
+ BIGMessages[i].m_Stack[0].m_pText,
+ BIGMessages[i].m_Stack[0].m_nNumber[0],
+ BIGMessages[i].m_Stack[0].m_nNumber[1],
+ BIGMessages[i].m_Stack[0].m_nNumber[2],
+ BIGMessages[i].m_Stack[0].m_nNumber[3],
+ BIGMessages[i].m_Stack[0].m_nNumber[4],
+ BIGMessages[i].m_Stack[0].m_nNumber[5],
+ outstr);
+ InsertStringInString(outstr, BIGMessages[i].m_Stack[0].m_pString);
+ InsertPlayerControlKeysInString(outstr);
+ CHud::SetBigMessage(outstr, i);
+ }
+
+ InsertNumberInString(
+ BriefMessages[0].m_pText,
+ BriefMessages[0].m_nNumber[0],
+ BriefMessages[0].m_nNumber[1],
+ BriefMessages[0].m_nNumber[2],
+ BriefMessages[0].m_nNumber[3],
+ BriefMessages[0].m_nNumber[4],
+ BriefMessages[0].m_nNumber[5],
+ outstr);
+ InsertStringInString(outstr, BriefMessages[0].m_pString);
+ InsertPlayerControlKeysInString(outstr);
+ CHud::SetMessage(outstr);
+}
+
+void
+CMessages::AddMessage(wchar *msg, uint32 time, uint16 flag)
+{
+ wchar outstr[514]; // unused
+ WideStringCopy(outstr, msg, 256);
+ InsertPlayerControlKeysInString(outstr);
+ GetWideStringLength(outstr);
+
+ int32 i = 0;
+ while (i < NUMBRIEFMESSAGES && BriefMessages[i].m_pText != nil)
+ i++;
+ if (i >= NUMBRIEFMESSAGES) return;
+
+ BriefMessages[i].m_pText = msg;
+ BriefMessages[i].m_nFlag = flag;
+ BriefMessages[i].m_nTime = time;
+ BriefMessages[i].m_nStartTime = CTimer::GetTimeInMilliseconds();
+ BriefMessages[i].m_nNumber[0] = -1;
+ BriefMessages[i].m_nNumber[1] = -1;
+ BriefMessages[i].m_nNumber[2] = -1;
+ BriefMessages[i].m_nNumber[3] = -1;
+ BriefMessages[i].m_nNumber[4] = -1;
+ BriefMessages[i].m_nNumber[5] = -1;
+ BriefMessages[i].m_pString = nil;
+ if (i == 0)
+ AddToPreviousBriefArray(
+ BriefMessages[0].m_pText,
+ BriefMessages[0].m_nNumber[0],
+ BriefMessages[0].m_nNumber[1],
+ BriefMessages[0].m_nNumber[2],
+ BriefMessages[0].m_nNumber[3],
+ BriefMessages[0].m_nNumber[4],
+ BriefMessages[0].m_nNumber[5],
+ BriefMessages[0].m_pString);
+}
+
+void
+CMessages::AddMessageJumpQ(wchar *msg, uint32 time, uint16 flag)
+{
+ wchar outstr[514]; // unused
+ WideStringCopy(outstr, msg, 256);
+ InsertPlayerControlKeysInString(outstr);
+ GetWideStringLength(outstr);
+
+ BriefMessages[0].m_pText = msg;
+ BriefMessages[0].m_nFlag = flag;
+ BriefMessages[0].m_nTime = time;
+ BriefMessages[0].m_nStartTime = CTimer::GetTimeInMilliseconds();
+ BriefMessages[0].m_nNumber[0] = -1;
+ BriefMessages[0].m_nNumber[1] = -1;
+ BriefMessages[0].m_nNumber[2] = -1;
+ BriefMessages[0].m_nNumber[3] = -1;
+ BriefMessages[0].m_nNumber[4] = -1;
+ BriefMessages[0].m_nNumber[5] = -1;
+ BriefMessages[0].m_pString = nil;
+ AddToPreviousBriefArray(msg, -1, -1, -1, -1, -1, -1, 0);
+}
+
+void
+CMessages::AddMessageSoon(wchar *msg, uint32 time, uint16 flag)
+{
+ wchar outstr[520]; // unused
+ WideStringCopy(outstr, msg, 256);
+ InsertPlayerControlKeysInString(outstr);
+ GetWideStringLength(outstr);
+
+ if (BriefMessages[0].m_pText != nil) {
+ for (int i = NUMBRIEFMESSAGES-1; i > 1; i--)
+ BriefMessages[i] = BriefMessages[i-1];
+
+ BriefMessages[1].m_pText = msg;
+ BriefMessages[1].m_nFlag = flag;
+ BriefMessages[1].m_nTime = time;
+ BriefMessages[1].m_nStartTime = CTimer::GetTimeInMilliseconds();
+ BriefMessages[1].m_nNumber[0] = -1;
+ BriefMessages[1].m_nNumber[1] = -1;
+ BriefMessages[1].m_nNumber[2] = -1;
+ BriefMessages[1].m_nNumber[3] = -1;
+ BriefMessages[1].m_nNumber[4] = -1;
+ BriefMessages[1].m_nNumber[5] = -1;
+ BriefMessages[1].m_pString = nil;
+ }else{
+ BriefMessages[0].m_pText = msg;
+ BriefMessages[0].m_nFlag = flag;
+ BriefMessages[0].m_nTime = time;
+ BriefMessages[0].m_nStartTime = CTimer::GetTimeInMilliseconds();
+ BriefMessages[0].m_nNumber[0] = -1;
+ BriefMessages[0].m_nNumber[1] = -1;
+ BriefMessages[0].m_nNumber[2] = -1;
+ BriefMessages[0].m_nNumber[3] = -1;
+ BriefMessages[0].m_nNumber[4] = -1;
+ BriefMessages[0].m_nNumber[5] = -1;
+ BriefMessages[0].m_pString = nil;
+ AddToPreviousBriefArray(msg, -1, -1, -1, -1, -1, -1, nil);
+ }
+}
+
+void
+CMessages::ClearMessages()
+{
+ for (int32 i = 0; i < NUMBIGMESSAGES; i++) {
+ for (int32 j = 0; j < 4; j++) {
+ BIGMessages[i].m_Stack[j].m_pText = nil;
+ BIGMessages[i].m_Stack[j].m_pString = nil;
+ }
+ }
+ ClearSmallMessagesOnly();
+}
+
+void
+CMessages::ClearSmallMessagesOnly()
+{
+ for (int32 i = 0; i < NUMBRIEFMESSAGES; i++) {
+ BriefMessages[i].m_pText = nil;
+ BriefMessages[i].m_pString = nil;
+ }
+}
+
+void
+CMessages::AddBigMessage(wchar *msg, uint32 time, uint16 style)
+{
+ wchar outstr[514]; // unused
+ WideStringCopy(outstr, msg, 256);
+ InsertPlayerControlKeysInString(outstr);
+ GetWideStringLength(outstr);
+
+ BIGMessages[style].m_Stack[0].m_pText = msg;
+ BIGMessages[style].m_Stack[0].m_nFlag = 0;
+ BIGMessages[style].m_Stack[0].m_nTime = time;
+ BIGMessages[style].m_Stack[0].m_nStartTime = CTimer::GetTimeInMilliseconds();
+ BIGMessages[style].m_Stack[0].m_nNumber[0] = -1;
+ BIGMessages[style].m_Stack[0].m_nNumber[1] = -1;
+ BIGMessages[style].m_Stack[0].m_nNumber[2] = -1;
+ BIGMessages[style].m_Stack[0].m_nNumber[3] = -1;
+ BIGMessages[style].m_Stack[0].m_nNumber[4] = -1;
+ BIGMessages[style].m_Stack[0].m_nNumber[5] = -1;
+ BIGMessages[style].m_Stack[0].m_pString = nil;
+}
+void
+CMessages::AddBigMessageQ(wchar *msg, uint32 time, uint16 style)
+{
+ wchar outstr[518]; // unused
+ WideStringCopy(outstr, msg, 256);
+ InsertPlayerControlKeysInString(outstr);
+ GetWideStringLength(outstr);
+
+ int32 i = 0;
+ while (i < 4 && BIGMessages[style].m_Stack[i].m_pText != nil)
+ i++;
+
+ if (i >= 4) return;
+
+ BIGMessages[style].m_Stack[i].m_pText = msg;
+ BIGMessages[style].m_Stack[i].m_nFlag = 0;
+ BIGMessages[style].m_Stack[i].m_nTime = time;
+ BIGMessages[style].m_Stack[i].m_nStartTime = CTimer::GetTimeInMilliseconds();
+ BIGMessages[style].m_Stack[i].m_nNumber[0] = -1;
+ BIGMessages[style].m_Stack[i].m_nNumber[1] = -1;
+ BIGMessages[style].m_Stack[i].m_nNumber[2] = -1;
+ BIGMessages[style].m_Stack[i].m_nNumber[3] = -1;
+ BIGMessages[style].m_Stack[i].m_nNumber[4] = -1;
+ BIGMessages[style].m_Stack[i].m_nNumber[5] = -1;
+ BIGMessages[style].m_Stack[i].m_pString = nil;
+}
+
+void
+CMessages::AddToPreviousBriefArray(wchar *text, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6, wchar *string)
+{
+ int32 i = 0;
+ while (i < NUMPREVIOUSBRIEFS) {
+ if (PreviousBriefs[i].m_pText == nil)
+ break;
+ if (PreviousBriefs[i].m_nNumber[0] == n1
+ && PreviousBriefs[i].m_nNumber[1] == n2
+ && PreviousBriefs[i].m_nNumber[2] == n3
+ && PreviousBriefs[i].m_nNumber[3] == n4
+ && PreviousBriefs[i].m_nNumber[4] == n5
+ && PreviousBriefs[i].m_nNumber[5] == n6
+ && PreviousBriefs[i].m_pText == text
+ && PreviousBriefs[i].m_pString == string)
+ return;
+
+ i++;
+ }
+
+ if (i != 0) {
+ if (i == NUMPREVIOUSBRIEFS) i -= 2;
+ else i--;
+
+ while (i >= 0) {
+ PreviousBriefs[i + 1] = PreviousBriefs[i];
+ i--;
+ }
+ }
+ PreviousBriefs[0].m_pText = text;
+ PreviousBriefs[0].m_nNumber[0] = n1;
+ PreviousBriefs[0].m_nNumber[1] = n2;
+ PreviousBriefs[0].m_nNumber[2] = n3;
+ PreviousBriefs[0].m_nNumber[3] = n4;
+ PreviousBriefs[0].m_nNumber[4] = n5;
+ PreviousBriefs[0].m_nNumber[5] = n6;
+ PreviousBriefs[0].m_pString = string;
+}
+
+void
+CMessages::InsertNumberInString(wchar *str, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6, wchar *outstr)
+{
+ char numStr[12];
+ wchar wNumStr[18];
+
+ if (str == nil) {
+ *outstr = '\0';
+ return;
+ }
+
+ int32 size = GetWideStringLength(str);
+
+ int32 i = 0;
+
+ for (int32 c = 0; c < size;) {
+ if (str[c] == '~' && str[c + 1] == '1' && str[c + 2] == '~') {
+ switch (i) {
+ case 0: sprintf(numStr, "%d", n1); break;
+ case 1: sprintf(numStr, "%d", n2); break;
+ case 2: sprintf(numStr, "%d", n3); break;
+ case 3: sprintf(numStr, "%d", n4); break;
+ case 4: sprintf(numStr, "%d", n5); break;
+ case 5: sprintf(numStr, "%d", n6); break;
+ }
+ i++;
+ AsciiToUnicode(numStr, wNumStr);
+
+ int j = 0;
+ while (wNumStr[j] != '\0')
+ *(outstr++) = wNumStr[j++];
+
+ c += 3;
+ } else {
+ *(outstr++) = str[c++];
+ }
+ }
+ *outstr = '\0';
+}
+
+void
+CMessages::InsertStringInString(wchar *str1, wchar *str2)
+{
+ wchar tempstr[264];
+
+ if (!str1 || !str2) return;
+
+ int32 str1_size = GetWideStringLength(str1);
+ int32 str2_size = GetWideStringLength(str2);
+ int32 total_size = str1_size + str2_size;
+
+ wchar *_str1 = str1;
+ uint16 i;
+ for (i = 0; i < total_size; ) {
+ if (*_str1 == '~' && *(_str1 + 1) == 'a' && *(_str1 + 2) == '~') {
+ _str1 += 3;
+ for (int j = 0; j < str2_size; j++) {
+ tempstr[i++] = str2[j];
+ }
+ } else {
+ tempstr[i++] = *(_str1++);
+ }
+ }
+ tempstr[i] = '\0';
+
+ for (i = 0; i < total_size; i++)
+ str1[i] = tempstr[i];
+
+ while (i < 256)
+ str1[i++] = '\0';
+}
+
+void
+CMessages::InsertPlayerControlKeysInString(wchar *str)
+{
+ uint16 i;
+ wchar outstr[256];
+ wchar keybuf[264];
+
+ if (!str) return;
+ uint16 strSize = GetWideStringLength(str);
+ memset(keybuf, 0, 256*sizeof(wchar));
+
+ wchar *_outstr = outstr;
+ for (i = 0; i < strSize;) {
+ if (str[i] == '~' && str[i + 1] == 'k' && str[i + 2] == '~') {
+ i += 4;
+ for (int32 cont = 0; cont < TOTAL_CONTROL_ACTIONS; cont++) {
+ uint16 contSize = GetWideStringLength(ControlsManager.m_aActionNames[cont]);
+ if (contSize != 0) {
+ if (WideStringCompare(&str[i], ControlsManager.m_aActionNames[cont], contSize)) {
+ ControlsManager.GetWideStringOfCommandKeys(cont, keybuf, 256);
+ uint16 keybuf_size = GetWideStringLength(keybuf);
+ for (uint16 j = 0; j < keybuf_size; j++) {
+ *(_outstr++) = keybuf[j];
+ keybuf[j] = '\0';
+ }
+ i += contSize + 1;
+ }
+ }
+ }
+ } else {
+ *(_outstr++) = str[i++];
+ }
+ }
+ *_outstr = '\0';
+
+ for (i = 0; i < GetWideStringLength(outstr); i++)
+ str[i] = outstr[i];
+
+ while (i < 256)
+ str[i++] = '\0';
+}
+
+void
+CMessages::AddMessageWithNumber(wchar *str, uint32 time, uint16 flag, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6)
+{
+ wchar outstr[520]; // unused
+ InsertNumberInString(str, n1, n2, n3, n4, n5, n6, outstr);
+ InsertPlayerControlKeysInString(outstr);
+ GetWideStringLength(outstr);
+
+ uint16 i = 0;
+ while (i < NUMBRIEFMESSAGES && BriefMessages[i].m_pText)
+ i++;
+
+ if (i >= NUMBRIEFMESSAGES) return;
+
+ BriefMessages[i].m_pText = str;
+ BriefMessages[i].m_nFlag = flag;
+ BriefMessages[i].m_nTime = time;
+ BriefMessages[i].m_nStartTime = CTimer::GetTimeInMilliseconds();
+ BriefMessages[i].m_nNumber[0] = n1;
+ BriefMessages[i].m_nNumber[1] = n2;
+ BriefMessages[i].m_nNumber[2] = n3;
+ BriefMessages[i].m_nNumber[3] = n4;
+ BriefMessages[i].m_nNumber[4] = n5;
+ BriefMessages[i].m_nNumber[5] = n6;
+ BriefMessages[i].m_pString = nil;
+ if (i == 0)
+ AddToPreviousBriefArray(
+ BriefMessages[0].m_pText,
+ BriefMessages[0].m_nNumber[0],
+ BriefMessages[0].m_nNumber[1],
+ BriefMessages[0].m_nNumber[2],
+ BriefMessages[0].m_nNumber[3],
+ BriefMessages[0].m_nNumber[4],
+ BriefMessages[0].m_nNumber[5],
+ BriefMessages[0].m_pString);
+}
+
+void
+CMessages::AddMessageJumpQWithNumber(wchar *str, uint32 time, uint16 flag, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6)
+{
+ wchar outstr[520]; // unused
+ InsertNumberInString(str, n1, n2, n3, n4, n5, n6, outstr);
+ InsertPlayerControlKeysInString(outstr);
+ GetWideStringLength(outstr);
+
+ BriefMessages[0].m_pText = str;
+ BriefMessages[0].m_nFlag = flag;
+ BriefMessages[0].m_nTime = time;
+ BriefMessages[0].m_nStartTime = CTimer::GetTimeInMilliseconds();
+ BriefMessages[0].m_nNumber[0] = n1;
+ BriefMessages[0].m_nNumber[1] = n2;
+ BriefMessages[0].m_nNumber[2] = n3;
+ BriefMessages[0].m_nNumber[3] = n4;
+ BriefMessages[0].m_nNumber[4] = n5;
+ BriefMessages[0].m_nNumber[5] = n6;
+ BriefMessages[0].m_pString = nil;
+ AddToPreviousBriefArray(str, n1, n2, n3, n4, n5, n6, nil);
+}
+
+void
+CMessages::AddMessageSoonWithNumber(wchar *str, uint32 time, uint16 flag, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6)
+{
+ wchar outstr[520]; // unused
+ InsertNumberInString(str, n1, n2, n3, n4, n5, n6, outstr);
+ InsertPlayerControlKeysInString(outstr);
+ GetWideStringLength(outstr);
+
+ if (BriefMessages[0].m_pText != nil) {
+ for (int32 i = NUMBRIEFMESSAGES-1; i > 1; i--)
+ BriefMessages[i] = BriefMessages[i-1];
+
+ BriefMessages[1].m_pText = str;
+ BriefMessages[1].m_nFlag = flag;
+ BriefMessages[1].m_nTime = time;
+ BriefMessages[1].m_nStartTime = CTimer::GetTimeInMilliseconds();
+ BriefMessages[1].m_nNumber[0] = n1;
+ BriefMessages[1].m_nNumber[1] = n2;
+ BriefMessages[1].m_nNumber[2] = n3;
+ BriefMessages[1].m_nNumber[3] = n4;
+ BriefMessages[1].m_nNumber[4] = n5;
+ BriefMessages[1].m_nNumber[5] = n6;
+ BriefMessages[1].m_pString = nil;
+ } else {
+ BriefMessages[0].m_pText = str;
+ BriefMessages[0].m_nFlag = flag;
+ BriefMessages[0].m_nTime = time;
+ BriefMessages[0].m_nStartTime = CTimer::GetTimeInMilliseconds();
+ BriefMessages[0].m_nNumber[0] = n1;
+ BriefMessages[0].m_nNumber[1] = n2;
+ BriefMessages[0].m_nNumber[2] = n3;
+ BriefMessages[0].m_nNumber[3] = n4;
+ BriefMessages[0].m_nNumber[4] = n5;
+ BriefMessages[0].m_nNumber[5] = n6;
+ BriefMessages[0].m_pString = nil;
+ AddToPreviousBriefArray(str, n1, n2, n3, n4, n5, n6, nil);
+ }
+}
+
+void
+CMessages::AddBigMessageWithNumber(wchar *str, uint32 time, uint16 style, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6)
+{
+ wchar outstr[520]; // unused
+ InsertNumberInString(str, n1, n2, n3, n4, n5, n6, outstr);
+ InsertPlayerControlKeysInString(outstr);
+ GetWideStringLength(outstr);
+
+ BIGMessages[style].m_Stack[0].m_pText = str;
+ BIGMessages[style].m_Stack[0].m_nFlag = 0;
+ BIGMessages[style].m_Stack[0].m_nTime = time;
+ BIGMessages[style].m_Stack[0].m_nStartTime = CTimer::GetTimeInMilliseconds();
+ BIGMessages[style].m_Stack[0].m_nNumber[0] = n1;
+ BIGMessages[style].m_Stack[0].m_nNumber[1] = n2;
+ BIGMessages[style].m_Stack[0].m_nNumber[2] = n3;
+ BIGMessages[style].m_Stack[0].m_nNumber[3] = n4;
+ BIGMessages[style].m_Stack[0].m_nNumber[4] = n5;
+ BIGMessages[style].m_Stack[0].m_nNumber[5] = n6;
+ BIGMessages[style].m_Stack[0].m_pString = nil;
+}
+
+void
+CMessages::AddBigMessageWithNumberQ(wchar *str, uint32 time, uint16 style, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6)
+{
+ wchar outstr[520]; // unused
+ InsertNumberInString(str, n1, n2, n3, n4, n5, n6, outstr);
+ InsertPlayerControlKeysInString(outstr);
+ GetWideStringLength(outstr);
+
+ int32 i = 0;
+
+ while (i < 4 && BIGMessages[style].m_Stack[i].m_pText != nil)
+ i++;
+
+ if (i >= 4) return;
+
+ BIGMessages[style].m_Stack[i].m_pText = str;
+ BIGMessages[style].m_Stack[i].m_nFlag = 0;
+ BIGMessages[style].m_Stack[i].m_nTime = time;
+ BIGMessages[style].m_Stack[i].m_nStartTime = CTimer::GetTimeInMilliseconds();
+ BIGMessages[style].m_Stack[i].m_nNumber[0] = n1;
+ BIGMessages[style].m_Stack[i].m_nNumber[1] = n2;
+ BIGMessages[style].m_Stack[i].m_nNumber[2] = n3;
+ BIGMessages[style].m_Stack[i].m_nNumber[3] = n4;
+ BIGMessages[style].m_Stack[i].m_nNumber[4] = n5;
+ BIGMessages[style].m_Stack[i].m_nNumber[5] = n6;
+ BIGMessages[style].m_Stack[i].m_pString = nil;
+}
+
+void
+CMessages::AddMessageWithString(wchar *text, uint32 time, uint16 flag, wchar *str)
+{
+ wchar outstr[516]; // unused
+ WideStringCopy(outstr, text, 256);
+ InsertStringInString(outstr, str);
+ InsertPlayerControlKeysInString(outstr);
+ GetWideStringLength(outstr);
+
+ int32 i = 0;
+ while (i < NUMBRIEFMESSAGES && BriefMessages[i].m_pText != nil)
+ i++;
+
+ if (i >= NUMBRIEFMESSAGES) return;
+
+ BriefMessages[i].m_pText = text;
+ BriefMessages[i].m_nFlag = flag;
+ BriefMessages[i].m_nTime = time;
+ BriefMessages[i].m_nStartTime = CTimer::GetTimeInMilliseconds();
+ BriefMessages[i].m_nNumber[0] = -1;
+ BriefMessages[i].m_nNumber[1] = -1;
+ BriefMessages[i].m_nNumber[2] = -1;
+ BriefMessages[i].m_nNumber[3] = -1;
+ BriefMessages[i].m_nNumber[4] = -1;
+ BriefMessages[i].m_nNumber[5] = -1;
+ BriefMessages[i].m_pString = str;
+ if (i == 0)
+ AddToPreviousBriefArray(
+ BriefMessages[0].m_pText,
+ BriefMessages[0].m_nNumber[0],
+ BriefMessages[0].m_nNumber[1],
+ BriefMessages[0].m_nNumber[2],
+ BriefMessages[0].m_nNumber[3],
+ BriefMessages[0].m_nNumber[4],
+ BriefMessages[0].m_nNumber[5],
+ BriefMessages[0].m_pString);
+}
+
+void
+CMessages::AddMessageJumpQWithString(wchar *text, uint32 time, uint16 flag, wchar *str)
+{
+ wchar outstr[516]; // unused
+ WideStringCopy(outstr, text, 256);
+ InsertStringInString(outstr, str);
+ InsertPlayerControlKeysInString(outstr);
+ GetWideStringLength(outstr);
+
+ BriefMessages[0].m_pText = text;
+ BriefMessages[0].m_nFlag = flag;
+ BriefMessages[0].m_nTime = time;
+ BriefMessages[0].m_nStartTime = CTimer::GetTimeInMilliseconds();
+ BriefMessages[0].m_nNumber[0] = -1;
+ BriefMessages[0].m_nNumber[1] = -1;
+ BriefMessages[0].m_nNumber[2] = -1;
+ BriefMessages[0].m_nNumber[3] = -1;
+ BriefMessages[0].m_nNumber[4] = -1;
+ BriefMessages[0].m_nNumber[5] = -1;
+ BriefMessages[0].m_pString = str;
+ AddToPreviousBriefArray(text, -1, -1, -1, -1, -1, -1, str);
+}
+
+inline bool
+FastWideStringComparison(wchar *str1, wchar *str2)
+{
+ while (*str1 == *str2) {
+ ++str1;
+ ++str2;
+ if (!*str1 && !*str2) return true;
+ }
+ return false;
+}
+
+void
+CMessages::ClearThisPrint(wchar *str)
+{
+ bool equal;
+
+ do {
+ equal = false;
+ uint16 i = 0;
+ while (i < NUMBRIEFMESSAGES) {
+ if (BriefMessages[i].m_pText == nil)
+ break;
+
+ equal = FastWideStringComparison(str, BriefMessages[i].m_pText);
+
+ if (equal) break;
+ i++;
+ }
+
+ if (equal) {
+ if (i != 0) {
+ BriefMessages[i].m_pText = nil;
+ while (i < NUMBRIEFMESSAGES-1) {
+ if (BriefMessages[i + 1].m_pText == nil)
+ break;
+
+ BriefMessages[i] = BriefMessages[i + 1];
+ i++;
+ }
+ BriefMessages[i].m_pText = nil;
+ } else {
+ BriefMessages[0].m_pText = nil;
+ while (i < NUMBRIEFMESSAGES-1) {
+ if (BriefMessages[i + 1].m_pText == nil)
+ break;
+ BriefMessages[i] = BriefMessages[i + 1];
+ i++;
+ }
+ BriefMessages[i].m_pText = nil;
+ BriefMessages[0].m_nStartTime = CTimer::GetTimeInMilliseconds();
+ if (BriefMessages[0].m_pText == nil)
+ AddToPreviousBriefArray(
+ BriefMessages[0].m_pText,
+ BriefMessages[0].m_nNumber[0],
+ BriefMessages[0].m_nNumber[1],
+ BriefMessages[0].m_nNumber[2],
+ BriefMessages[0].m_nNumber[3],
+ BriefMessages[0].m_nNumber[4],
+ BriefMessages[0].m_nNumber[5],
+ BriefMessages[0].m_pString);
+ }
+ }
+ } while (equal);
+}
+
+void
+CMessages::ClearThisBigPrint(wchar *str)
+{
+ bool equal;
+
+ do {
+ uint16 i = 0;
+ equal = false;
+ uint16 style = 0;
+ while (style < NUMBIGMESSAGES)
+ {
+ if (i >= 4)
+ break;
+
+ if (CMessages::BIGMessages[style].m_Stack[i].m_pText == nil || equal)
+ break;
+
+ equal = FastWideStringComparison(str, BIGMessages[style].m_Stack[i].m_pText);
+
+ if (!equal && ++i == 4) {
+ i = 0;
+ style++;
+ }
+ }
+ if (equal) {
+ if (i != 0) {
+ BIGMessages[style].m_Stack[i].m_pText = nil;
+ while (i < 3) {
+ if (BIGMessages[style].m_Stack[i + 1].m_pText == nil)
+ break;
+ BIGMessages[style].m_Stack[i] = BIGMessages[style].m_Stack[i + 1];
+ i++;
+ }
+ BIGMessages[style].m_Stack[i].m_pText = nil;
+ } else {
+ BIGMessages[style].m_Stack[0].m_pText = 0;
+ i = 0;
+ while (i < 3) {
+ if (BIGMessages[style].m_Stack[i + 1].m_pText == nil)
+ break;
+ BIGMessages[style].m_Stack[i] = BIGMessages[style].m_Stack[i + 1];
+ i++;
+ }
+ BIGMessages[style].m_Stack[i].m_pText = nil;
+ BIGMessages[style].m_Stack[0].m_nStartTime = CTimer::GetTimeInMilliseconds();
+ }
+ }
+ } while (equal);
+}
+
+void
+CMessages::ClearAllMessagesDisplayedByGame()
+{
+ ClearMessages();
+ for (int32 i = 0; i < NUMPREVIOUSBRIEFS; i++) {
+ PreviousBriefs[i].m_pText = nil;
+ PreviousBriefs[i].m_pString = nil;
+ }
+ CHud::GetRidOfAllHudMessages();
+ CUserDisplay::Pager.ClearMessages();
+}
+
+STARTPATCHES
+ InjectHook(0x529310, CMessages::Init, PATCH_JUMP);
+ InjectHook(0x529490, CMessages::GetWideStringLength, PATCH_JUMP);
+ InjectHook(0x5294B0, CMessages::WideStringCopy, PATCH_JUMP);
+ InjectHook(0x529510, CMessages::WideStringCompare, PATCH_JUMP);
+ InjectHook(0x529580, CMessages::Process, PATCH_JUMP);
+ InjectHook(0x529800, CMessages::Display, PATCH_JUMP);
+ InjectHook(0x529900, CMessages::AddMessage, PATCH_JUMP);
+ InjectHook(0x529A10, CMessages::AddMessageJumpQ, PATCH_JUMP);
+ InjectHook(0x529AF0, CMessages::AddMessageSoon, PATCH_JUMP);
+ InjectHook(0x529CE0, CMessages::ClearMessages, PATCH_JUMP);
+ InjectHook(0x529E00, CMessages::ClearSmallMessagesOnly, PATCH_JUMP);
+ InjectHook(0x529EB0, CMessages::AddBigMessage, PATCH_JUMP);
+ InjectHook(0x529F60, CMessages::AddBigMessageQ, PATCH_JUMP);
+ InjectHook(0x52A040, CMessages::AddToPreviousBriefArray, PATCH_JUMP);
+ InjectHook(0x52A1A0, CMessages::InsertNumberInString, PATCH_JUMP);
+ InjectHook(0x52A300, CMessages::InsertStringInString, PATCH_JUMP);
+ InjectHook(0x52A490, CMessages::InsertPlayerControlKeysInString, PATCH_JUMP);
+ InjectHook(0x52A850, CMessages::AddMessageWithNumber, PATCH_JUMP);
+ InjectHook(0x52A9A0, CMessages::AddMessageJumpQWithNumber, PATCH_JUMP);
+ InjectHook(0x52AAC0, CMessages::AddMessageSoonWithNumber, PATCH_JUMP);
+ InjectHook(0x52AD10, CMessages::AddBigMessageWithNumber, PATCH_JUMP);
+ InjectHook(0x52AE00, CMessages::AddBigMessageWithNumberQ, PATCH_JUMP);
+ InjectHook(0x52AF30, CMessages::AddMessageWithString, PATCH_JUMP);
+ InjectHook(0x52B050, CMessages::AddMessageJumpQWithString, PATCH_JUMP);
+ InjectHook(0x52B140, CMessages::ClearThisPrint, PATCH_JUMP);
+ InjectHook(0x52B3C0, CMessages::ClearThisBigPrint, PATCH_JUMP);
+ InjectHook(0x52B670, CMessages::ClearAllMessagesDisplayedByGame, PATCH_JUMP);
+ENDPATCHES \ No newline at end of file
diff --git a/src/text/Messages.h b/src/text/Messages.h
new file mode 100644
index 00000000..8044c626
--- /dev/null
+++ b/src/text/Messages.h
@@ -0,0 +1,69 @@
+#pragma once
+
+struct tMessage
+{
+ wchar *m_pText;
+ uint16 m_nFlag;
+ uint32 m_nTime;
+ uint32 m_nStartTime;
+ int32 m_nNumber[6];
+ wchar *m_pString;
+};
+
+struct tBigMessage
+{
+ tMessage m_Stack[4];
+};
+
+struct tPreviousBrief
+{
+ wchar *m_pText;
+ int32 m_nNumber[6];
+ wchar *m_pString;
+};
+
+#define NUMBRIEFMESSAGES 8
+#define NUMBIGMESSAGES 6
+#define NUMPREVIOUSBRIEFS 5
+
+class CMessages
+{
+public:
+ static tMessage(&BriefMessages)[NUMBRIEFMESSAGES];
+ static tBigMessage(&BIGMessages)[NUMBIGMESSAGES];
+ static tPreviousBrief(&PreviousBriefs)[NUMPREVIOUSBRIEFS];
+ static char PreviousMissionTitle[16]; // unused
+public:
+ static void Init(void);
+ static uint16 GetWideStringLength(wchar *src);
+ static void WideStringCopy(wchar *dst, wchar *src, uint16 size);
+ static bool WideStringCompare(wchar *str1, wchar *str2, uint16 size);
+ static void Process(void);
+ static void Display(void);
+ static void AddMessage(wchar *key, uint32 time, uint16 pos);
+ static void AddMessageJumpQ(wchar *key, uint32 time, uint16 pos);
+ static void AddMessageSoon(wchar *key, uint32 time, uint16 pos);
+ static void ClearMessages(void);
+ static void ClearSmallMessagesOnly(void);
+ static void AddBigMessage(wchar *key, uint32 time, uint16 pos);
+ static void AddBigMessageQ(wchar *key, uint32 time, uint16 pos);
+ static void AddToPreviousBriefArray(wchar *text, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6, wchar *string);
+ static void InsertNumberInString(wchar *src, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6, wchar *dst);
+ static void InsertStringInString(wchar *str1, wchar *str2);
+ static void InsertPlayerControlKeysInString(wchar *src);
+ static void AddMessageWithNumber(wchar *key, uint32 time, uint16 pos, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6);
+ static void AddMessageJumpQWithNumber(wchar *key, uint32 time, uint16 pos, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6);
+ static void AddMessageSoonWithNumber(wchar *key, uint32 time, uint16 pos, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6);
+ static void AddBigMessageWithNumber(wchar *key, uint32 time, uint16 pos, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6);
+ static void AddBigMessageWithNumberQ(wchar *key, uint32 time, uint16 pos, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6);
+ static void AddMessageWithString(wchar *text, uint32 time, uint16 flag, wchar *str);
+ static void AddMessageJumpQWithString(wchar *text, uint32 time, uint16 flag, wchar *str);
+ static void ClearThisPrint(wchar *str);
+ static void ClearThisBigPrint(wchar *str);
+ static void ClearAllMessagesDisplayedByGame(void);
+
+ // unused or cut
+ //static void AddMessageSoonWithString(wchar*, uint32, uint16, wchar*);
+ //static void CutString(int16, char*, char**);
+ //static void PrintString(char*, int16, int16, int16);
+};
diff --git a/src/text/Pager.cpp b/src/text/Pager.cpp
new file mode 100644
index 00000000..a9813b18
--- /dev/null
+++ b/src/text/Pager.cpp
@@ -0,0 +1,193 @@
+#include "common.h"
+#include "patcher.h"
+#include "Pager.h"
+#include "Timer.h"
+#include "Messages.h"
+#include "Hud.h"
+#include "Camera.h"
+
+void
+CPager::Init()
+{
+ ClearMessages();
+ m_nNumDisplayLetters = 8;
+}
+
+void
+CPager::Process()
+{
+ if (m_messages[0].m_pText != nil && m_messages[0].m_nCurrentPosition >= (int32)m_messages[0].m_nStringLength) {
+ m_messages[0].m_pText = nil;
+ uint16 i = 0;
+ while (i < NUMPAGERMESSAGES-1) {
+ if (m_messages[i + 1].m_pText == nil) break;
+ m_messages[i] = m_messages[i + 1];
+ }
+ m_messages[i].m_pText = nil;
+ if (m_messages[0].m_pText != nil)
+ CMessages::AddToPreviousBriefArray(
+ m_messages[0].m_pText,
+ m_messages[0].m_nNumber[0],
+ m_messages[0].m_nNumber[1],
+ m_messages[0].m_nNumber[2],
+ m_messages[0].m_nNumber[3],
+ m_messages[0].m_nNumber[4],
+ m_messages[0].m_nNumber[5],
+ 0);
+ }
+ Display();
+ if (m_messages[0].m_pText != nil) {
+ if (TheCamera.m_WideScreenOn || !CHud::m_Wants_To_Draw_Hud || CHud::m_BigMessage[0][0] || CHud::m_BigMessage[2][0]) {
+ RestartCurrentMessage();
+ } else {
+ if (CTimer::GetTimeInMilliseconds() > m_messages[0].m_nTimeToChangePosition) {
+ m_messages[0].m_nCurrentPosition++;
+ m_messages[0].m_nTimeToChangePosition = CTimer::GetTimeInMilliseconds() + m_messages[0].m_nSpeedMs;
+ }
+ }
+ }
+}
+
+void
+CPager::Display()
+{
+ wchar outstr1[256];
+ wchar outstr2[260];
+
+ wchar *pText = m_messages[0].m_pText;
+ uint16 i = 0;
+ if (pText != nil) {
+ CMessages::InsertNumberInString(
+ pText,
+ m_messages[0].m_nNumber[0],
+ m_messages[0].m_nNumber[1],
+ m_messages[0].m_nNumber[2],
+ m_messages[0].m_nNumber[3],
+ m_messages[0].m_nNumber[4],
+ m_messages[0].m_nNumber[5],
+ outstr1);
+ for (; i < m_nNumDisplayLetters; i++) {
+ int pos = m_messages[0].m_nCurrentPosition + i;
+ if (pos >= 0) {
+ if (!outstr1[pos]) break;
+
+ outstr2[i] = outstr1[pos];
+ } else {
+ outstr2[i] = ' ';
+ }
+ }
+ }
+ outstr2[i] = '\0';
+ CHud::SetPagerMessage(outstr2);
+}
+
+void
+CPager::AddMessage(wchar *str, uint16 speed, uint16 priority, uint16 a5)
+{
+ uint16 size = CMessages::GetWideStringLength(str);
+ for (int32 i = 0; i < NUMPAGERMESSAGES; i++) {
+ if (m_messages[i].m_pText) {
+ if (m_messages[i].m_nPriority >= priority)
+ continue;
+
+ for (int j = NUMPAGERMESSAGES-1; j > i; j--)
+ m_messages[j] = m_messages[j-1];
+
+ }
+ m_messages[i].m_pText = str;
+ m_messages[i].m_nSpeedMs = speed;
+ m_messages[i].m_nPriority = priority;
+ m_messages[i].field_10 = a5;
+ m_messages[i].m_nCurrentPosition = -(m_nNumDisplayLetters + 10);
+ m_messages[i].m_nTimeToChangePosition = CTimer::GetTimeInMilliseconds() + speed;
+ m_messages[i].m_nStringLength = size;
+ m_messages[i].m_nNumber[0] = -1;
+ m_messages[i].m_nNumber[1] = -1;
+ m_messages[i].m_nNumber[2] = -1;
+ m_messages[i].m_nNumber[3] = -1;
+ m_messages[i].m_nNumber[4] = -1;
+ m_messages[i].m_nNumber[5] = -1;
+
+ if (i == 0)
+ CMessages::AddToPreviousBriefArray(
+ m_messages[0].m_pText,
+ m_messages[0].m_nNumber[0],
+ m_messages[0].m_nNumber[1],
+ m_messages[0].m_nNumber[2],
+ m_messages[0].m_nNumber[3],
+ m_messages[0].m_nNumber[4],
+ m_messages[0].m_nNumber[5],
+ nil);
+ return;
+ }
+}
+
+void
+CPager::AddMessageWithNumber(wchar *str, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6, uint16 speed, uint16 priority, uint16 a11)
+{
+ wchar nstr[520];
+
+ CMessages::InsertNumberInString(str, n1, n2, n3, n4, n5, n6, nstr);
+ uint16 size = CMessages::GetWideStringLength(nstr);
+ for (int32 i = 0; i < NUMPAGERMESSAGES; i++) {
+ if (m_messages[i].m_pText) {
+ if (m_messages[i].m_nPriority >= priority)
+ continue;
+
+ for (int j = NUMPAGERMESSAGES-1; j > i; j--)
+ m_messages[j] = m_messages[j - 1];
+
+ }
+ m_messages[i].m_pText = str;
+ m_messages[i].m_nSpeedMs = speed;
+ m_messages[i].m_nPriority = priority;
+ m_messages[i].field_10 = a11;
+ m_messages[i].m_nCurrentPosition = -(m_nNumDisplayLetters + 10);
+ m_messages[i].m_nTimeToChangePosition = CTimer::GetTimeInMilliseconds() + speed;
+ m_messages[i].m_nStringLength = size;
+ m_messages[i].m_nNumber[0] = n1;
+ m_messages[i].m_nNumber[1] = n2;
+ m_messages[i].m_nNumber[2] = n3;
+ m_messages[i].m_nNumber[3] = n4;
+ m_messages[i].m_nNumber[4] = n5;
+ m_messages[i].m_nNumber[5] = n6;
+
+ if (i == 0)
+ CMessages::AddToPreviousBriefArray(
+ m_messages[0].m_pText,
+ m_messages[0].m_nNumber[0],
+ m_messages[0].m_nNumber[1],
+ m_messages[0].m_nNumber[2],
+ m_messages[0].m_nNumber[3],
+ m_messages[0].m_nNumber[4],
+ m_messages[0].m_nNumber[5],
+ nil);
+ return;
+ }
+}
+
+void
+CPager::ClearMessages()
+{
+ for (int32 i = 0; i < NUMPAGERMESSAGES; i++)
+ m_messages[i].m_pText = nil;
+}
+
+void
+CPager::RestartCurrentMessage()
+{
+ if (m_messages[0].m_pText != nil) {
+ m_messages[0].m_nCurrentPosition = -(m_nNumDisplayLetters + 10);
+ m_messages[0].m_nTimeToChangePosition = CTimer::GetTimeInMilliseconds() + m_messages[0].m_nSpeedMs;
+ }
+}
+
+STARTPATCHES
+ InjectHook(0x52B6F0, &CPager::Init, PATCH_JUMP);
+ InjectHook(0x52B740, &CPager::Process, PATCH_JUMP);
+ InjectHook(0x52B890, &CPager::Display, PATCH_JUMP);
+ InjectHook(0x52B940, &CPager::AddMessage, PATCH_JUMP);
+ InjectHook(0x52BB50, &CPager::AddMessageWithNumber, PATCH_JUMP);
+ InjectHook(0x52BE50, &CPager::RestartCurrentMessage, PATCH_JUMP);
+ InjectHook(0x52BE00, &CPager::ClearMessages, PATCH_JUMP);
+ENDPATCHES \ No newline at end of file
diff --git a/src/text/Pager.h b/src/text/Pager.h
new file mode 100644
index 00000000..727eeb24
--- /dev/null
+++ b/src/text/Pager.h
@@ -0,0 +1,28 @@
+#pragma once
+
+struct PagerMessage {
+ wchar *m_pText;
+ uint16 m_nSpeedMs;
+ int16 m_nCurrentPosition;
+ uint16 m_nStringLength;
+ uint16 m_nPriority;
+ uint32 m_nTimeToChangePosition;
+ int16 field_10;
+ int32 m_nNumber[6];
+};
+
+#define NUMPAGERMESSAGES 8
+
+class CPager
+{
+ int16 m_nNumDisplayLetters;
+ PagerMessage m_messages[NUMPAGERMESSAGES];
+public:
+ void Init();
+ void Process();
+ void Display();
+ void AddMessage(wchar*, uint16, uint16, uint16);
+ void AddMessageWithNumber(wchar *str, int32 n1, int32 n2, int32 n3, int32 n4, int32 n5, int32 n6, uint16 speed, uint16 priority, uint16 a11);
+ void ClearMessages();
+ void RestartCurrentMessage();
+}; \ No newline at end of file
diff --git a/src/core/Text.cpp b/src/text/Text.cpp
index dfa9815c..40717ed5 100644
--- a/src/core/Text.cpp
+++ b/src/text/Text.cpp
@@ -11,20 +11,10 @@ CText &TheText = *(CText*)0x941520;
CText::CText(void)
{
- keyArray.entries = nil;
- keyArray.numEntries = 0;
- data.chars = nil;
- data.numChars = 0;
- encoding = 101;
+ encoding = 'e';
memset(WideErrorString, 0, sizeof(WideErrorString));
}
-CText::~CText(void)
-{
- data.Unload();
- keyArray.Unload();
-}
-
void
CText::Load(void)
{
@@ -96,12 +86,64 @@ CText::Get(const char *key)
return keyArray.Search(key);
}
+wchar UpperCaseTable[128] = {
+ 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138,
+ 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
+ 150, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137,
+ 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148,
+ 149, 173, 173, 175, 176, 177, 178, 179, 180, 181, 182,
+ 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193,
+ 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204,
+ 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215,
+ 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226,
+ 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237,
+ 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248,
+ 249, 250, 251, 252, 253, 254, 255
+};
+
+wchar FrenchUpperCaseTable[128] = {
+ 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138,
+ 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
+ 150, 65, 65, 65, 65, 132, 133, 69, 69, 69, 69, 73, 73,
+ 73, 73, 79, 79, 79, 79, 85, 85, 85, 85, 173, 173, 175,
+ 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186,
+ 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197,
+ 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208,
+ 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219,
+ 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230,
+ 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241,
+ 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252,
+ 253, 254, 255
+};
+
wchar
CText::GetUpperCase(wchar c)
-{
- // TODO: do this depending on encoding
- if(islower(c))
- return toupper(c);
+{
+ switch (encoding)
+ {
+ case 'e':
+ if (c >= 'a' && c <= 'z')
+ return c - 32;
+ break;
+ case 'f':
+ if (c >= 'a' && c <= 'z')
+ return c - 32;
+
+ if (c >= 128 && c <= 255)
+ return FrenchUpperCaseTable[c-128];
+ break;
+ case 'g':
+ case 'i':
+ case 's':
+ if (c >= 'a' && c <= 'z')
+ return c - 32;
+
+ if (c >= 128 && c <= 255)
+ return UpperCaseTable[c-128];
+ break;
+ default:
+ break;
+ }
return c;
}
@@ -205,7 +247,7 @@ CData::Unload(void)
}
void
-AsciiToUnicode(const char *src, uint16 *dst)
+AsciiToUnicode(const char *src, wchar *dst)
{
while((*dst++ = *src++) != '\0');
}
@@ -215,8 +257,8 @@ UnicodeToAscii(wchar *src)
{
static char aStr[256];
int len;
- for(len = 0; src && *src != 0 && len < 256-1; len++, src++)
- if(*src < 256)
+ for(len = 0; *src != '\0' && len < 256-1; len++, src++)
+ if(*src < 128)
aStr[len] = *src;
else
aStr[len] = '#';
@@ -227,10 +269,9 @@ UnicodeToAscii(wchar *src)
char*
UnicodeToAsciiForSaveLoad(wchar *src)
{
- // exact same code as above
static char aStr[256];
int len;
- for(len = 0; src && *src != 0 && len < 256-1; len++, src++)
+ for(len = 0; *src != '\0' && len < 256-1; len++, src++)
if(*src < 256)
aStr[len] = *src;
else
@@ -249,7 +290,7 @@ int
UnicodeStrlen(const wchar *str)
{
int len;
- for(len = 0; *str != 0; len++, str++);
+ for(len = 0; *str != '\0'; len++, str++);
return len;
}
@@ -264,6 +305,8 @@ STARTPATCHES
InjectHook(0x52C3C0, &CText::Load, PATCH_JUMP);
InjectHook(0x52C580, &CText::Unload, PATCH_JUMP);
InjectHook(0x52C5A0, &CText::Get, PATCH_JUMP);
+ InjectHook(0x52C220, &CText::GetUpperCase, PATCH_JUMP);
+ InjectHook(0x52C2C0, &CText::UpperCase, PATCH_JUMP);
InjectHook(0x52BE70, &CKeyArray::Load, PATCH_JUMP);
InjectHook(0x52BF60, &CKeyArray::Unload, PATCH_JUMP);
diff --git a/src/core/Text.h b/src/text/Text.h
index f554628c..6f39ba49 100644
--- a/src/core/Text.h
+++ b/src/text/Text.h
@@ -21,6 +21,8 @@ public:
CKeyEntry *entries;
int numEntries;
+ CKeyArray(void) : entries(nil), numEntries(0) {}
+ ~CKeyArray(void) { Unload(); }
void Load(uint32 length, uint8 *data, int *offset);
void Unload(void);
void Update(wchar *chars);
@@ -34,6 +36,8 @@ public:
wchar *chars;
int numChars;
+ CData(void) : chars(nil), numChars(0) {}
+ ~CData(void) { Unload(); }
void Load(uint32 length, uint8 *data, int *offset);
void Unload(void);
};
@@ -42,10 +46,9 @@ class CText
{
CKeyArray keyArray;
CData data;
- int8 encoding;
+ char encoding;
public:
CText(void);
- ~CText(void);
void Load(void);
void Unload(void);
wchar *Get(const char *key);
diff --git a/src/weapons/ProjectileInfo.cpp b/src/weapons/ProjectileInfo.cpp
new file mode 100644
index 00000000..50d75516
--- /dev/null
+++ b/src/weapons/ProjectileInfo.cpp
@@ -0,0 +1,7 @@
+#include "common.h"
+#include "patcher.h"
+#include "ProjectileInfo.h"
+#include "Projectile.h"
+
+
+WRAPPER bool CProjectileInfo::RemoveIfThisIsAProjectile(CObject *pObject) { EAXJMP(0x55BBD0); } \ No newline at end of file
diff --git a/src/weapons/ProjectileInfo.h b/src/weapons/ProjectileInfo.h
new file mode 100644
index 00000000..f4753b28
--- /dev/null
+++ b/src/weapons/ProjectileInfo.h
@@ -0,0 +1,9 @@
+#pragma once
+
+class CObject;
+
+class CProjectileInfo
+{
+public:
+ static bool RemoveIfThisIsAProjectile(CObject *pObject);
+}; \ No newline at end of file
diff --git a/src/weapons/Weapon.cpp b/src/weapons/Weapon.cpp
index 3f511358..860e3ab2 100644
--- a/src/weapons/Weapon.cpp
+++ b/src/weapons/Weapon.cpp
@@ -6,6 +6,7 @@
#include "Ped.h"
#include "World.h"
+WRAPPER void CWeapon::UpdateWeapons(void) { EAXJMP(0x55C310); }
WRAPPER bool CWeapon::Fire(CEntity*, CVector*) { EAXJMP(0x55C380); }
WRAPPER void CWeapon::FireFromCar(CAutomobile *car, bool left) { EAXJMP(0x55C940); }
WRAPPER void CWeapon::AddGunshell(CEntity*, CVector const&, CVector2D const&, float) { EAXJMP(0x55F770); }
diff --git a/src/weapons/Weapon.h b/src/weapons/Weapon.h
index 2f277c62..1663ee0d 100644
--- a/src/weapons/Weapon.h
+++ b/src/weapons/Weapon.h
@@ -73,5 +73,6 @@ public:
static void DoTankDoomAiming(CEntity *playerVehicle, CEntity *playerPed, CVector *start, CVector *end);
bool HitsGround(CEntity* holder, CVector* firePos, CEntity* aimingTo);
static void InitialiseWeapons(void);
+ static void UpdateWeapons(void);
};
static_assert(sizeof(CWeapon) == 0x18, "CWeapon: error");