summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/control/Garages.cpp2
-rw-r--r--src/control/Pickups.cpp1
-rw-r--r--src/control/Record.cpp13
-rw-r--r--src/control/RoadBlocks.cpp200
-rw-r--r--src/control/RoadBlocks.h2
-rw-r--r--src/core/Frontend.cpp51
-rw-r--r--src/core/Frontend.h48
-rw-r--r--src/core/Pools.cpp345
-rw-r--r--src/core/Profile.cpp71
-rw-r--r--src/core/Profile.h28
-rw-r--r--src/core/Timer.h3
-rw-r--r--src/entities/Entity.h1
-rw-r--r--src/modelinfo/BaseModelInfo.h4
-rw-r--r--src/peds/Gangs.cpp (renamed from src/control/Gangs.cpp)2
-rw-r--r--src/peds/Gangs.h (renamed from src/control/Gangs.h)0
-rw-r--r--src/peds/Population.cpp81
-rw-r--r--src/peds/Population.h54
-rw-r--r--src/rw/RwHelper.cpp53
-rw-r--r--src/rw/RwHelper.h1
-rw-r--r--src/save/GenericGameStorage.cpp184
-rw-r--r--src/vehicles/CarGen.cpp (renamed from src/control/CarGen.cpp)86
-rw-r--r--src/vehicles/CarGen.h (renamed from src/control/CarGen.h)12
-rw-r--r--src/vehicles/Cranes.cpp (renamed from src/control/Cranes.cpp)94
-rw-r--r--src/vehicles/Cranes.h (renamed from src/control/Cranes.h)9
-rw-r--r--src/vehicles/Vehicle.h3
25 files changed, 1023 insertions, 325 deletions
diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp
index 84d49bee..d971d453 100644
--- a/src/control/Garages.cpp
+++ b/src/control/Garages.cpp
@@ -2108,7 +2108,7 @@ void CGarages::CloseHideOutGaragesBeforeSave()
aGarages[i].m_eGarageType != GARAGE_HIDEOUT_THREE)
continue;
if (aGarages[i].m_eGarageState != GS_FULLYCLOSED &&
- aGarages[i].m_eGarageType != GARAGE_HIDEOUT_ONE || !aGarages[i].IsAnyCarBlockingDoor()) {
+ (aGarages[i].m_eGarageType != GARAGE_HIDEOUT_ONE || !aGarages[i].IsAnyCarBlockingDoor())) {
aGarages[i].m_eGarageState = GS_FULLYCLOSED;
switch (aGarages[i].m_eGarageType) {
case GARAGE_HIDEOUT_ONE:
diff --git a/src/control/Pickups.cpp b/src/control/Pickups.cpp
index 80e89ee8..eb561670 100644
--- a/src/control/Pickups.cpp
+++ b/src/control/Pickups.cpp
@@ -1016,6 +1016,7 @@ CPacManPickup::Update()
FindPlayerPed()->m_pWanted->m_nChaos += 10;
FindPlayerPed()->m_pWanted->UpdateWantedLevel();
DMAudio.PlayFrontEndSound(SOUND_PICKUP_PACMAN_PACKAGE, 0);
+ break;
}
case PACMAN_RACE:
CPacManPickups::PillsEatenInRace++;
diff --git a/src/control/Record.cpp b/src/control/Record.cpp
index aead1720..ca4128e3 100644
--- a/src/control/Record.cpp
+++ b/src/control/Record.cpp
@@ -21,8 +21,7 @@ tGameBuffer& CRecordDataForGame::pDataBufferForFrame = *(tGameBuffer*)0x72CED0;
void CRecordDataForGame::Init(void)
{
RecordingState = STATE_NONE;
- if (pDataBuffer)
- delete[] pDataBuffer;
+ delete[] pDataBuffer;
pDataBufferPointer = nil;
pDataBuffer = nil;
#ifndef GTA_PS2 // this stuff is not present on PS2
@@ -42,7 +41,7 @@ void CRecordDataForGame::Init(void)
if (RecordingState == STATE_PLAYBACK) {
pDataBufferPointer = new uint8[MEMORY_FOR_GAME_RECORD];
pDataBuffer = pDataBufferPointer;
- pDataBuffer[CFileMgr::Read(FId, (char*)pDataBufferPointer, MEMORY_FOR_GAME_RECORD) + 8] = -1;
+ pDataBuffer[CFileMgr::Read(FId, (char*)pDataBufferPointer, MEMORY_FOR_GAME_RECORD) + 8] = (uint8)-1;
CFileMgr::CloseFile(FId);
}
#else
@@ -71,7 +70,7 @@ void CRecordDataForGame::SaveOrRetrieveDataForThisFrame(void)
break;
}
case STATE_PLAYBACK:
- if (pDataBufferPointer[8] == -1)
+ if (pDataBufferPointer[8] == (uint8)-1)
CPad::GetPad(0)->NewState.Clear();
else {
tGameBuffer* pData = (tGameBuffer*)pDataBufferPointer;
@@ -92,7 +91,7 @@ void CRecordDataForGame::SaveOrRetrieveDataForThisFrame(void)
#define PROCESS_BUTTON_STATE_STORE(buf, os, ns, field, id) \
do { \
- if (os->field != os->field){ \
+ if (os->field != ns->field){ \
*buf++ = id; \
*buf++ = ns->field; \
} \
@@ -102,7 +101,7 @@ uint8* CRecordDataForGame::PackCurrentPadValues(uint8* buf, CControllerState* os
{
PROCESS_BUTTON_STATE_STORE(buf, os, ns, LeftStickX, 0);
PROCESS_BUTTON_STATE_STORE(buf, os, ns, LeftStickY, 1);
- PROCESS_BUTTON_STATE_STORE(buf, os, ns, LeftShoulder1, 2);
+ PROCESS_BUTTON_STATE_STORE(buf, os, ns, RightStickX, 2);
PROCESS_BUTTON_STATE_STORE(buf, os, ns, RightStickY, 3);
PROCESS_BUTTON_STATE_STORE(buf, os, ns, LeftShoulder1, 4);
PROCESS_BUTTON_STATE_STORE(buf, os, ns, LeftShoulder2, 5);
@@ -132,7 +131,7 @@ uint8* CRecordDataForGame::UnPackCurrentPadValues(uint8* buf, uint8 total, CCont
switch (*buf++) {
PROCESS_BUTTON_STATE_RESTORE(buf, state, LeftStickX, 0);
PROCESS_BUTTON_STATE_RESTORE(buf, state, LeftStickY, 1);
- PROCESS_BUTTON_STATE_RESTORE(buf, state, LeftShoulder1, 2);
+ PROCESS_BUTTON_STATE_RESTORE(buf, state, RightStickX, 2);
PROCESS_BUTTON_STATE_RESTORE(buf, state, RightStickY, 3);
PROCESS_BUTTON_STATE_RESTORE(buf, state, LeftShoulder1, 4);
PROCESS_BUTTON_STATE_RESTORE(buf, state, LeftShoulder2, 5);
diff --git a/src/control/RoadBlocks.cpp b/src/control/RoadBlocks.cpp
index e39fe481..9548bc0a 100644
--- a/src/control/RoadBlocks.cpp
+++ b/src/control/RoadBlocks.cpp
@@ -2,36 +2,202 @@
#include "patcher.h"
#include "RoadBlocks.h"
#include "PathFind.h"
+#include "ModelIndices.h"
+#include "Streaming.h"
+#include "World.h"
+#include "PedPlacement.h"
+#include "Automobile.h"
+#include "CopPed.h"
+#include "VisibilityPlugins.h"
+#include "PlayerPed.h"
+#include "Wanted.h"
+#include "Camera.h"
+#include "CarCtrl.h"
+#include "General.h"
int16 &CRoadBlocks::NumRoadBlocks = *(int16*)0x95CC34;
int16 (&CRoadBlocks::RoadBlockObjects)[NUMROADBLOCKS] = *(int16(*)[NUMROADBLOCKS]) * (uintptr*)0x72B3A8;
bool (&CRoadBlocks::InOrOut)[NUMROADBLOCKS] = *(bool(*)[NUMROADBLOCKS]) * (uintptr*)0x733810;
-WRAPPER void CRoadBlocks::GenerateRoadBlockCopsForCar(CVehicle*, int32, int16) { EAXJMP(0x4376A0); }
-WRAPPER void CRoadBlocks::GenerateRoadBlocks(void) { EAXJMP(0x436FA0); }
-
void
CRoadBlocks::Init(void)
{
- NumRoadBlocks = 0;
- for (int objId = 0; objId < ThePaths.m_numMapObjects; objId++) {
- if (ThePaths.m_objectFlags[objId] & UseInRoadBlock) {
- if (NumRoadBlocks < 600) {
- InOrOut[NumRoadBlocks] = true;
- RoadBlockObjects[NumRoadBlocks] = objId;
- NumRoadBlocks++;
- } else {
+ NumRoadBlocks = 0;
+ for (int objId = 0; objId < ThePaths.m_numMapObjects; objId++) {
+ if (ThePaths.m_objectFlags[objId] & UseInRoadBlock) {
+ if (NumRoadBlocks < NUMROADBLOCKS) {
+ InOrOut[NumRoadBlocks] = true;
+ RoadBlockObjects[NumRoadBlocks] = objId;
+ NumRoadBlocks++;
+ } else {
#ifndef MASTER
- printf("Not enough room for the potential roadblocks\n");
+ printf("Not enough room for the potential roadblocks\n");
#endif
- // FIX: Don't iterate loop after NUMROADBLOCKS
- return;
- }
- }
- }
+ // FIX: Don't iterate loop after NUMROADBLOCKS
+ return;
+ }
+ }
+ }
+
+}
+
+void
+CRoadBlocks::GenerateRoadBlockCopsForCar(CVehicle* pVehicle, int32 roadBlockType, int16 roadBlockNode)
+{
+ static const CVector vecRoadBlockOffets[6] = { {-1.5, 1.8f, 0.0f}, {-1.5f, -1.8f, 0.0f}, {1.5f, 1.8f, 0.0f},
+ {1.5f, -1.8f, 0.0f}, {-1.5f, 0.0f, 0.0f}, {1.5, 0.0, 0.0} };
+ CEntity* pEntityToAttack = (CEntity*)FindPlayerVehicle();
+ if (!pEntityToAttack)
+ pEntityToAttack = (CEntity*)FindPlayerPed();
+ CColModel* pPoliceColModel = CModelInfo::GetModelInfo(MI_POLICE)->GetColModel();
+ float fRadius = pVehicle->GetBoundRadius() / pPoliceColModel->boundingSphere.radius;
+ for (int32 i = 0; i < 2; i++) {
+ const int32 roadBlockIndex = i + 2 * roadBlockType;
+ CVector posForZ = pVehicle->m_matrix * (fRadius * vecRoadBlockOffets[roadBlockIndex]);
+ int32 modelInfoId = MI_COP;
+ eCopType copType = COP_STREET;
+ switch (pVehicle->GetModelIndex())
+ {
+ case MI_FBICAR:
+ modelInfoId = MI_FBI;
+ copType = COP_FBI;
+ break;
+ case MI_ENFORCER:
+ modelInfoId = MI_SWAT;
+ copType = COP_SWAT;
+ break;
+ case MI_BARRACKS:
+ modelInfoId = MI_ARMY;
+ copType = COP_ARMY;
+ break;
+ }
+ if (!CStreaming::HasModelLoaded(modelInfoId))
+ copType = COP_STREET;
+ CCopPed* pCopPed = new CCopPed(copType);
+ if (copType == COP_STREET)
+ pCopPed->SetCurrentWeapon(WEAPONTYPE_COLT45);
+ CPedPlacement::FindZCoorForPed(&posForZ);
+ pCopPed->m_matrix.GetPosition() = posForZ;
+ CVector vecSavedPos = pCopPed->m_matrix.GetPosition();
+ pCopPed->m_matrix.SetRotate(0.0f, 0.0f, -HALFPI);
+ pCopPed->m_matrix.GetPosition() += vecSavedPos;
+ pCopPed->m_bIsDisabledCop = true;
+ pCopPed->SetIdle();
+ pCopPed->bKindaStayInSamePlace = true;
+ pCopPed->bNotAllowedToDuck = false;
+ pCopPed->m_wRoadblockNode = roadBlockNode;
+ pCopPed->bCrouchWhenShooting = roadBlockType != 2;
+ if (pEntityToAttack) {
+ pCopPed->m_pPointGunAt = pEntityToAttack;
+ pEntityToAttack->RegisterReference(&pCopPed->m_pPointGunAt);
+ pCopPed->SetAttack(pEntityToAttack);
+ }
+ pCopPed->m_pMyVehicle = pVehicle;
+ pVehicle->RegisterReference((CEntity**)&pCopPed->m_pMyVehicle);
+ pCopPed->bCullExtraFarAway = true;
+ CVisibilityPlugins::SetClumpAlpha(pCopPed->GetClump(), 0);
+ CWorld::Add(pCopPed);
+ }
+}
+void
+CRoadBlocks::GenerateRoadBlocks(void)
+{
+ CMatrix offsetMatrix;
+ uint32 frame = CTimer::GetFrameCounter() & 0xF;
+ int16 nRoadblockNode = (int16)(NUMROADBLOCKS * frame) / 16;
+ const int16 maxRoadBlocks = (int16)(NUMROADBLOCKS * (frame + 1)) / 16;
+ int16 numRoadBlocks = CRoadBlocks::NumRoadBlocks;
+ if (CRoadBlocks::NumRoadBlocks >= maxRoadBlocks)
+ numRoadBlocks = maxRoadBlocks;
+ for (; nRoadblockNode < numRoadBlocks; nRoadblockNode++) {
+ CTreadable *mapObject = ThePaths.m_mapObjects[CRoadBlocks::RoadBlockObjects[nRoadblockNode]];
+ CVector2D vecDistance = FindPlayerCoors() - mapObject->GetPosition();
+ if (vecDistance.x > -80.0f && vecDistance.x < 80.0f &&
+ vecDistance.y > -80.0f && vecDistance.y < 80.0f &&
+ vecDistance.Magnitude() < 80.0f) {
+ if (!CRoadBlocks::InOrOut[nRoadblockNode]) {
+ CRoadBlocks::InOrOut[nRoadblockNode] = true;
+ if (FindPlayerVehicle() && (CGeneral::GetRandomNumber() & 0x7F) < FindPlayerPed()->m_pWanted->m_RoadblockDensity) {
+ CWanted *pPlayerWanted = FindPlayerPed()->m_pWanted;
+ float fMapObjectRadius = 2.0f * mapObject->GetColModel()->boundingBox.max.x;
+ int32 vehicleId = MI_POLICE;
+ if (pPlayerWanted->AreArmyRequired())
+ vehicleId = MI_BARRACKS;
+ else if (pPlayerWanted->AreFbiRequired())
+ vehicleId = MI_FBICAR;
+ else if (pPlayerWanted->AreSwatRequired())
+ vehicleId = MI_ENFORCER;
+ if (!CStreaming::HasModelLoaded(vehicleId))
+ vehicleId = MI_POLICE;
+ CColModel *pVehicleColModel = CModelInfo::GetModelInfo(vehicleId)->GetColModel();
+ float fModelRadius = 2.0f * pVehicleColModel->boundingSphere.radius + 0.25f;
+ int16 radius = (int16)(fMapObjectRadius / fModelRadius);
+ if (radius > 0 && radius < 6) {
+ CVector2D vecDistanceToCamera = TheCamera.GetPosition() - mapObject->m_matrix.GetPosition();
+ float fDotProduct = DotProduct2D(vecDistanceToCamera, mapObject->m_matrix.GetUp());
+ float fOffset = 0.5f * fModelRadius * (float)(radius - 1);
+ for (int16 i = 0; i < radius; i++) {
+ uint8 nRoadblockType = fDotProduct < 0.0f;
+ if (CGeneral::GetRandomNumber() & 1) {
+ offsetMatrix.SetRotateZ(((CGeneral::GetRandomNumber() & 0xFF) - 128.0f) * 0.003f + HALFPI);
+ }
+ else {
+ nRoadblockType = !nRoadblockType;
+ offsetMatrix.SetRotateZ(((CGeneral::GetRandomNumber() & 0xFF) - 128.0f) * 0.003f - HALFPI);
+ }
+ if (ThePaths.m_objectFlags[CRoadBlocks::RoadBlockObjects[nRoadblockNode]] & ObjectEastWest)
+ offsetMatrix.GetPosition() = CVector(0.0f, -fOffset, 0.6f);
+ else
+ offsetMatrix.GetPosition() = CVector(-fOffset, 0.0f, 0.6f);
+ CMatrix vehicleMatrix = mapObject->m_matrix * offsetMatrix;
+ float fModelRadius = CModelInfo::GetModelInfo(vehicleId)->GetColModel()->boundingSphere.radius - 0.25f;
+ int16 colliding = 0;
+ CWorld::FindObjectsKindaColliding(vehicleMatrix.GetPosition(), fModelRadius, 0, &colliding, 2, nil, false, true, true, false, false);
+ if (!colliding) {
+ CAutomobile *pVehicle = new CAutomobile(vehicleId, RANDOM_VEHICLE);
+ pVehicle->m_status = STATUS_ABANDONED;
+ // pVehicle->GetHeightAboveRoad(); // called but return value is ignored?
+ vehicleMatrix.GetPosition().z += fModelRadius - 0.6f;
+ pVehicle->m_matrix = vehicleMatrix;
+ pVehicle->PlaceOnRoadProperly();
+ pVehicle->bIsStatic = false;
+ pVehicle->m_matrix.UpdateRW();
+ pVehicle->m_nDoorLock = CARLOCK_UNLOCKED;
+ CCarCtrl::JoinCarWithRoadSystem(pVehicle);
+ pVehicle->bIsLocked = false;
+ pVehicle->AutoPilot.m_nCarMission = MISSION_NONE;
+ pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
+ pVehicle->AutoPilot.m_nCurrentLane = 0;
+ pVehicle->AutoPilot.m_nNextLane = 0;
+ pVehicle->AutoPilot.m_fMaxTrafficSpeed = 0.0f;
+ pVehicle->AutoPilot.m_nCruiseSpeed = 0.0f;
+ pVehicle->bExtendedRange = true;
+ if (pVehicle->UsesSiren(pVehicle->GetModelIndex()) && CGeneral::GetRandomNumber() & 1)
+ pVehicle->m_bSirenOrAlarm = true;
+ if (pVehicle->m_matrix.GetForward().z > 0.94f) {
+ CVisibilityPlugins::SetClumpAlpha(pVehicle->GetClump(), 0);
+ CWorld::Add(pVehicle);
+ pVehicle->bCreateRoadBlockPeds = true;
+ pVehicle->m_nRoadblockType = nRoadblockType;
+ pVehicle->m_nRoadblockNode = nRoadblockNode;
+ }
+ else {
+ delete pVehicle;
+ }
+ }
+ }
+ }
+ }
+ }
+ } else {
+ CRoadBlocks::InOrOut[nRoadblockNode] = false;
+ }
+ }
}
STARTPATCHES
InjectHook(0x436F50, &CRoadBlocks::Init, PATCH_JUMP);
+ InjectHook(0x4376A0, &CRoadBlocks::GenerateRoadBlockCopsForCar, PATCH_JUMP);
+ InjectHook(0x436FA0, &CRoadBlocks::GenerateRoadBlocks, PATCH_JUMP);
ENDPATCHES \ No newline at end of file
diff --git a/src/control/RoadBlocks.h b/src/control/RoadBlocks.h
index 3f5868e7..16e3a362 100644
--- a/src/control/RoadBlocks.h
+++ b/src/control/RoadBlocks.h
@@ -11,6 +11,6 @@ public:
static bool (&InOrOut)[NUMROADBLOCKS];
static void Init(void);
- static void GenerateRoadBlockCopsForCar(CVehicle*, int32, int16);
+ static void GenerateRoadBlockCopsForCar(CVehicle* pVehicle, int32 roadBlockType, int16 roadBlockNode);
static void GenerateRoadBlocks(void);
};
diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp
index 643c450f..48683abc 100644
--- a/src/core/Frontend.cpp
+++ b/src/core/Frontend.cpp
@@ -82,34 +82,34 @@ int curBottomBarOption = -1;
int hoveredBottomBarOption = -1;
#endif
-int32 &CMenuManager::OS_Language = *(int32*)0x5F2F78; // 9
-int8 &CMenuManager::m_PrefsUseVibration = *(int8*)0x95CD92;
-int8 &CMenuManager::m_DisplayControllerOnFoot = *(int8*)0x95CD8D;
-int8 &CMenuManager::m_PrefsVsync = *(int8*)0x5F2E58; // 1
-int8 &CMenuManager::m_PrefsVsyncDisp = *(int8*)0x5F2E5C; // 1
-int8 &CMenuManager::m_PrefsFrameLimiter = *(int8*)0x5F2E60; // 1
-int8 &CMenuManager::m_PrefsShowSubtitles = *(int8*)0x5F2E54; // 1
-int8 &CMenuManager::m_PrefsSpeakers = *(int8*)0x95CD7E;
-int32 &CMenuManager::m_ControlMethod = *(int32*)0x8F5F7C;
-int8 &CMenuManager::m_PrefsDMA = *(int8*)0x5F2F74; // 1
-int32 &CMenuManager::m_PrefsLanguage = *(int32*)0x941238;
+int32 CMenuManager::OS_Language = LANG_ENGLISH; // *(int32*)0x5F2F78;
+int8 CMenuManager::m_PrefsUseVibration; // = *(int8*)0x95CD92;
+int8 CMenuManager::m_DisplayControllerOnFoot; // = *(int8*)0x95CD8D;
+int8 CMenuManager::m_PrefsVsync = 1; // *(int8*)0x5F2E58;
+int8 CMenuManager::m_PrefsVsyncDisp = 1; // *(int8*)0x5F2E5C;
+int8 CMenuManager::m_PrefsFrameLimiter = 1; // *(int8*)0x5F2E60;
+int8 CMenuManager::m_PrefsShowSubtitles = 1; // *(int8*)0x5F2E54;
+int8 CMenuManager::m_PrefsSpeakers; // = *(int8*)0x95CD7E;
+int32 CMenuManager::m_ControlMethod; // = *(int32*)0x8F5F7C;
+int8 CMenuManager::m_PrefsDMA = 1; // *(int8*)0x5F2F74;
+int32 CMenuManager::m_PrefsLanguage; // = *(int32*)0x941238;
uint8 CMenuManager::m_PrefsStereoMono; // *(bool*)0x95CDB5; // unused except restore settings
-bool &CMenuManager::m_PrefsAllowNastyGame = *(bool*)0x5F2E64; // true
-bool &CMenuManager::m_bStartUpFrontEndRequested = *(bool*)0x95CCF4;
-bool &CMenuManager::m_bShutDownFrontEndRequested = *(bool*)0x95CD6A;
+bool CMenuManager::m_PrefsAllowNastyGame = true; // *(bool*)0x5F2E64;
+bool CMenuManager::m_bStartUpFrontEndRequested; // = *(bool*)0x95CCF4;
+bool CMenuManager::m_bShutDownFrontEndRequested; // = *(bool*)0x95CD6A;
-int8 &CMenuManager::m_PrefsUseWideScreen = *(int8*)0x95CD23;
-int8 &CMenuManager::m_PrefsRadioStation = *(int8*)0x95CDA4;
-int32 &CMenuManager::m_PrefsBrightness = *(int32*)0x5F2E50; // 256
-float &CMenuManager::m_PrefsLOD = *(float*)0x8F42C4;
-int8 &CMenuManager::m_bFrontEnd_ReloadObrTxtGxt = *(int8*)0x628CFC;
-int32 &CMenuManager::m_PrefsMusicVolume = *(int32*)0x5F2E4C; // 102
-int32 &CMenuManager::m_PrefsSfxVolume = *(int32*)0x5F2E48; // 102
+int8 CMenuManager::m_PrefsUseWideScreen; // = *(int8*)0x95CD23;
+int8 CMenuManager::m_PrefsRadioStation; // = *(int8*)0x95CDA4;
+int32 CMenuManager::m_PrefsBrightness = 256; // = *(int32*)0x5F2E50;
+float CMenuManager::m_PrefsLOD; // = *(float*)0x8F42C4;
+int8 CMenuManager::m_bFrontEnd_ReloadObrTxtGxt; // = *(int8*)0x628CFC;
+int32 CMenuManager::m_PrefsMusicVolume = 102; // = *(int32*)0x5F2E4C;
+int32 CMenuManager::m_PrefsSfxVolume = 102; // = *(int32*)0x5F2E48;
-char *CMenuManager::m_PrefsSkinFile = (char*)0x5F2E74; //[256] "$$\"\""
+char CMenuManager::m_PrefsSkinFile[256] = "$$\"\""; // = (char*)0x5F2E74;
-int32 &CMenuManager::m_KeyPressedCode = *(int32*)0x5F2E70; // -1
+int32 CMenuManager::m_KeyPressedCode = -1; // = *(int32*)0x5F2E70;
// Originally that was PS2 option color, they forget it here and used in PrintBriefs once(but didn't use the output anyway)
#ifdef PS2_LIKE_MENU
@@ -1655,7 +1655,6 @@ CMenuManager::DrawControllerBound(int32 yStart, int32 xStart, int32 unused, int8
}
}
-// TODO: Complete aScreens and test that
void
CMenuManager::DrawControllerScreenExtraText(int yStart, int xStart, int lineHeight)
{
@@ -2463,7 +2462,7 @@ CMenuManager::DrawPlayerSetupScreen()
m_pSelectedSkin->skinNameDisplayed[oldLength - 4] = '\0';
m_pSelectedSkin->skinNameOriginal[oldLength - 4] = '\0';
- // Truncate to 40 bytes-39 chars, idk why. This is done in sepearate function in game.
+ // Fill to 40 bytes-39 chars, idk why. This is done in sepearate function in game.
strncpy(nameTemp, m_pSelectedSkin->skinNameDisplayed, 39); // game doesn't do that, but in our day strncpy to same string is forbidden
strncpy(m_pSelectedSkin->skinNameDisplayed, nameTemp, 39);
if (oldLength - 4 > 39)
@@ -4875,7 +4874,7 @@ float CMenuManager::StretchY(float y)
void
CMenuManager::SwitchMenuOnAndOff()
{
- bool menuWasActive = !!m_bMenuActive;
+ bool menuWasActive = GetIsMenuActive();
// Reminder: You need REGISTER_START_BUTTON defined to make it work.
if (CPad::GetPad(0)->GetStartJustDown()
diff --git a/src/core/Frontend.h b/src/core/Frontend.h
index 81765af9..9064cf4e 100644
--- a/src/core/Frontend.h
+++ b/src/core/Frontend.h
@@ -530,30 +530,30 @@ public:
bool GetIsMenuActive() {return !!m_bMenuActive;}
public:
- static int32 &OS_Language;
- static int8 &m_PrefsUseVibration;
- static int8 &m_DisplayControllerOnFoot;
- static int8 &m_PrefsUseWideScreen;
- static int8 &m_PrefsRadioStation;
- static int8 &m_PrefsVsync;
- static int8 &m_PrefsVsyncDisp;
- static int8 &m_PrefsFrameLimiter;
- static int8 &m_PrefsShowSubtitles;
- static int8 &m_PrefsSpeakers;
- static int32 &m_ControlMethod;
- static int8 &m_PrefsDMA;
- static int32 &m_PrefsLanguage;
- static int32 &m_PrefsBrightness;
- static float &m_PrefsLOD;
- static int8 &m_bFrontEnd_ReloadObrTxtGxt;
- static int32 &m_PrefsMusicVolume;
- static int32 &m_PrefsSfxVolume;
- static char *m_PrefsSkinFile;
- static int32 &m_KeyPressedCode;
-
- static bool &m_bStartUpFrontEndRequested;
- static bool &m_bShutDownFrontEndRequested;
- static bool &m_PrefsAllowNastyGame;
+ static int32 OS_Language;
+ static int8 m_PrefsUseVibration;
+ static int8 m_DisplayControllerOnFoot;
+ static int8 m_PrefsUseWideScreen;
+ static int8 m_PrefsRadioStation;
+ static int8 m_PrefsVsync;
+ static int8 m_PrefsVsyncDisp;
+ static int8 m_PrefsFrameLimiter;
+ static int8 m_PrefsShowSubtitles;
+ static int8 m_PrefsSpeakers;
+ static int32 m_ControlMethod;
+ static int8 m_PrefsDMA;
+ static int32 m_PrefsLanguage;
+ static int32 m_PrefsBrightness;
+ static float m_PrefsLOD;
+ static int8 m_bFrontEnd_ReloadObrTxtGxt;
+ static int32 m_PrefsMusicVolume;
+ static int32 m_PrefsSfxVolume;
+ static char m_PrefsSkinFile[256];
+ static int32 m_KeyPressedCode;
+
+ static bool m_bStartUpFrontEndRequested;
+ static bool m_bShutDownFrontEndRequested;
+ static bool m_PrefsAllowNastyGame;
static uint8 m_PrefsStereoMono;
static int32 m_SelectedMap;
diff --git a/src/core/Pools.cpp b/src/core/Pools.cpp
index 75536b88..6add9e0c 100644
--- a/src/core/Pools.cpp
+++ b/src/core/Pools.cpp
@@ -1,8 +1,14 @@
#include "common.h"
#include "patcher.h"
#include "Pools.h"
-#include "World.h"
+
+#include "Boat.h"
+#include "CarCtrl.h"
+#include "Population.h"
#include "ProjectileInfo.h"
+#include "Streaming.h"
+#include "Wanted.h"
+#include "World.h"
CCPtrNodePool *&CPools::ms_pPtrNodePool = *(CCPtrNodePool**)0x943044;
CEntryInfoNodePool *&CPools::ms_pEntryInfoNodePool = *(CEntryInfoNodePool**)0x941448;
@@ -14,13 +20,6 @@ CObjectPool *&CPools::ms_pObjectPool = *(CObjectPool**)0x880E28;
CDummyPool *&CPools::ms_pDummyPool = *(CDummyPool**)0x8F2C18;
CAudioScriptObjectPool *&CPools::ms_pAudioScriptObjectPool = *(CAudioScriptObjectPool**)0x8F1B6C;
-WRAPPER void CPools::LoadObjectPool(uint8* buf, uint32 size) { EAXJMP(0x4a2550); }
-WRAPPER void CPools::LoadPedPool(uint8* buf, uint32 size) { EAXJMP(0x4a2b50); }
-WRAPPER void CPools::LoadVehiclePool(uint8* buf, uint32 size) { EAXJMP(0x4a1b40); }
-WRAPPER void CPools::SaveObjectPool(uint8* buf, uint32 *size) { EAXJMP(0x4a22d0); }
-WRAPPER void CPools::SavePedPool(uint8* buf, uint32 *size) { EAXJMP(0x4a29b0); }
-WRAPPER void CPools::SaveVehiclePool(uint8* buf, uint32 *size) { EAXJMP(0x4a2080); }
-
void
CPools::Initialise(void)
{
@@ -99,6 +98,333 @@ CPools::MakeSureSlotInObjectPoolIsEmpty(int32 slot)
}
}
+void CPools::LoadVehiclePool(uint8* buf, uint32 size)
+{
+INITSAVEBUF
+ int nNumCars = ReadSaveBuf<int>(buf);
+ int nNumBoats = ReadSaveBuf<int>(buf);
+ for (int i = 0; i < nNumCars + nNumBoats; i++) {
+ uint32 type = ReadSaveBuf<uint32>(buf);
+ int16 model = ReadSaveBuf<int16>(buf);
+ CStreaming::RequestModel(model, STREAMFLAGS_DEPENDENCY);
+ CStreaming::LoadAllRequestedModels(false);
+ int32 slot = ReadSaveBuf<int32>(buf);
+ CVehicle* pVehicle;
+ char* vbuf = new char[max(sizeof(CAutomobile), sizeof(CBoat))];
+ if (type == VEHICLE_TYPE_BOAT) {
+ memcpy(vbuf, buf, sizeof(CBoat));
+ SkipSaveBuf(buf, sizeof(CBoat));
+ CBoat* pBoat = new(slot) CBoat(model, RANDOM_VEHICLE);
+ pVehicle = pBoat;
+ --CCarCtrl::NumRandomCars; // why?
+ }
+ else if (type == VEHICLE_TYPE_CAR) {
+ memcpy(vbuf, buf, sizeof(CAutomobile));
+ SkipSaveBuf(buf, sizeof(CAutomobile));
+ CStreaming::RequestModel(model, 0); // is it needed?
+ CStreaming::LoadAllRequestedModels(false);
+ CAutomobile* pAutomobile = new(slot) CAutomobile(model, RANDOM_VEHICLE);
+ pVehicle = pAutomobile;
+ CCarCtrl::NumRandomCars--; // why?
+ pAutomobile->Damage = ((CAutomobile*)vbuf)->Damage;
+ pAutomobile->SetupDamageAfterLoad();
+ }
+ else
+ assert(0);
+ CVehicle* pBufferVehicle = (CVehicle*)vbuf;
+ pVehicle->GetMatrix() = pBufferVehicle->GetMatrix();
+ pVehicle->VehicleCreatedBy = pBufferVehicle->VehicleCreatedBy;
+ pVehicle->m_currentColour1 = pBufferVehicle->m_currentColour1;
+ pVehicle->m_currentColour2 = pBufferVehicle->m_currentColour2;
+ pVehicle->m_nAlarmState = pBufferVehicle->m_nAlarmState;
+ pVehicle->m_nNumMaxPassengers = pBufferVehicle->m_nNumMaxPassengers;
+ pVehicle->field_1D0[0] = pBufferVehicle->field_1D0[0];
+ pVehicle->field_1D0[1] = pBufferVehicle->field_1D0[1];
+ pVehicle->field_1D0[2] = pBufferVehicle->field_1D0[2];
+ pVehicle->field_1D0[3] = pBufferVehicle->field_1D0[3];
+ pVehicle->m_fSteerAngle = pBufferVehicle->m_fSteerAngle;
+ pVehicle->m_fGasPedal = pBufferVehicle->m_fGasPedal;
+ pVehicle->m_fBrakePedal = pBufferVehicle->m_fBrakePedal;
+ pVehicle->bIsLawEnforcer = pBufferVehicle->bIsLawEnforcer;
+ pVehicle->bIsLocked = pBufferVehicle->bIsLocked;
+ pVehicle->bEngineOn = pBufferVehicle->bEngineOn;
+ pVehicle->bIsHandbrakeOn = pBufferVehicle->bIsHandbrakeOn;
+ pVehicle->bLightsOn = pBufferVehicle->bLightsOn;
+ pVehicle->bFreebies = pBufferVehicle->bFreebies;
+ pVehicle->m_fHealth = pBufferVehicle->m_fHealth;
+ pVehicle->m_nCurrentGear = pBufferVehicle->m_nCurrentGear;
+ pVehicle->m_fChangeGearTime = pBufferVehicle->m_fChangeGearTime;
+ pVehicle->m_nTimeOfDeath = pBufferVehicle->m_nTimeOfDeath;
+#ifdef FIX_BUGS //must be copypaste
+ pVehicle->m_nBombTimer = pBufferVehicle->m_nBombTimer;
+#else
+ pVehicle->m_nTimeOfDeath = pBufferVehicle->m_nTimeOfDeath;
+#endif
+ pVehicle->m_nDoorLock = pBufferVehicle->m_nDoorLock;
+ pVehicle->m_status = pBufferVehicle->m_status;
+ pVehicle->m_type = pBufferVehicle->m_type;
+ (pVehicle->GetAddressOfEntityProperties())[0] = (pBufferVehicle->GetAddressOfEntityProperties())[0];
+ (pVehicle->GetAddressOfEntityProperties())[1] = (pBufferVehicle->GetAddressOfEntityProperties())[1];
+ pVehicle->AutoPilot = pBufferVehicle->AutoPilot;
+ CWorld::Add(pVehicle);
+ delete[] vbuf;
+ }
+VALIDATESAVEBUF(size)
+}
+
+void CPools::SaveVehiclePool(uint8* buf, uint32* size)
+{
+INITSAVEBUF
+ int nNumCars = 0;
+ int nNumBoats = 0;
+ int nPoolSize = GetVehiclePool()->GetSize();
+ for (int i = 0; i < nPoolSize; i++) {
+ CVehicle* pVehicle = GetVehiclePool()->GetSlot(i);
+ if (!pVehicle)
+ continue;
+ bool bHasPassenger = false;
+ for (int j = 0; j < ARRAY_SIZE(pVehicle->pPassengers); j++) {
+ if (pVehicle->pPassengers[i])
+ bHasPassenger = true;
+ }
+ if (!pVehicle->pDriver && !bHasPassenger) {
+ if (pVehicle->IsCar() && pVehicle->VehicleCreatedBy == MISSION_VEHICLE)
+ ++nNumCars;
+ if (pVehicle->IsBoat() && pVehicle->VehicleCreatedBy == MISSION_VEHICLE)
+ ++nNumBoats;
+ }
+ }
+ *size = nNumCars * (sizeof(uint32) + sizeof(int16) + sizeof(int32) + sizeof(CAutomobile)) + sizeof(int) +
+ nNumBoats * (sizeof(uint32) + sizeof(int16) + sizeof(int32) + sizeof(CBoat)) + sizeof(int);
+ WriteSaveBuf(buf, nNumCars);
+ WriteSaveBuf(buf, nNumBoats);
+ for (int i = 0; i < nPoolSize; i++) {
+ CVehicle* pVehicle = GetVehiclePool()->GetSlot(i);
+ if (!pVehicle)
+ continue;
+ bool bHasPassenger = false;
+ for (int j = 0; j < ARRAY_SIZE(pVehicle->pPassengers); j++) {
+ if (pVehicle->pPassengers[j])
+ bHasPassenger = true;
+ }
+ if (!pVehicle->pDriver && !bHasPassenger) {
+ if (pVehicle->IsCar() && pVehicle->VehicleCreatedBy == MISSION_VEHICLE) {
+ WriteSaveBuf(buf, (uint32)pVehicle->m_vehType);
+ WriteSaveBuf(buf, pVehicle->m_modelIndex);
+ WriteSaveBuf(buf, GetVehicleRef(pVehicle));
+ memcpy(buf, pVehicle, sizeof(CAutomobile));
+ SkipSaveBuf(buf, sizeof(CAutomobile));
+ }
+ if (pVehicle->IsBoat() && pVehicle->VehicleCreatedBy == MISSION_VEHICLE) {
+ WriteSaveBuf(buf, (uint32)pVehicle->m_vehType);
+ WriteSaveBuf(buf, pVehicle->m_modelIndex);
+ WriteSaveBuf(buf, GetVehicleRef(pVehicle));
+ memcpy(buf, pVehicle, sizeof(CBoat));
+ SkipSaveBuf(buf, sizeof(CBoat));
+ }
+ }
+ }
+VALIDATESAVEBUF(*size)
+}
+
+void CPools::SaveObjectPool(uint8* buf, uint32* size)
+{
+INITSAVEBUF
+ CProjectileInfo::RemoveAllProjectiles();
+ CObject::DeleteAllTempObjects();
+ int nObjects = 0;
+ int nPoolSize = GetObjectPool()->GetSize();
+ for (int i = 0; i < nPoolSize; i++) {
+ CObject* pObject = GetObjectPool()->GetSlot(i);
+ if (!pObject)
+ continue;
+ if (pObject->ObjectCreatedBy == MISSION_OBJECT)
+ ++nObjects;
+ }
+ *size = nObjects * (sizeof(int16) + sizeof(int) + sizeof(CCompressedMatrixNotAligned) + sizeof(uint32) +
+ sizeof(float) + sizeof(CCompressedMatrixNotAligned) + sizeof(uint32) + sizeof(int8) + 7 * sizeof(bool) + sizeof(float) +
+ sizeof(int8) + sizeof(int8) + sizeof(uint32) + 2 * sizeof(uint32)) + sizeof(int);
+ WriteSaveBuf(buf, nObjects);
+ for (int i = 0; i < nPoolSize; i++) {
+ CObject* pObject = GetObjectPool()->GetSlot(i);
+ if (!pObject)
+ continue;
+ if (pObject->ObjectCreatedBy == MISSION_OBJECT) {
+ bool bIsPickup = pObject->bIsPickup;
+ bool bFlag2 = pObject->m_obj_flag2;
+ bool bOutOfStock = pObject->bOutOfStock;
+ bool bGlassCracked = pObject->bGlassCracked;
+ bool bGlassBroken = pObject->bGlassBroken;
+ bool bHasBeenDamaged = pObject->bHasBeenDamaged;
+ bool bUseVehicleColours = pObject->bUseVehicleColours;
+ CCompressedMatrixNotAligned tmp;
+ WriteSaveBuf(buf, pObject->m_modelIndex);
+ WriteSaveBuf(buf, GetObjectRef(pObject));
+ tmp.CompressFromFullMatrix(pObject->GetMatrix());
+ WriteSaveBuf(buf, tmp);
+ WriteSaveBuf(buf, (uint32)0); // game writes ununitialized data here
+ WriteSaveBuf(buf, pObject->m_fUprootLimit);
+ tmp.CompressFromFullMatrix(pObject->m_objectMatrix);
+ WriteSaveBuf(buf, tmp);
+ WriteSaveBuf(buf, (uint32)0); // same
+ WriteSaveBuf(buf, pObject->ObjectCreatedBy);
+ WriteSaveBuf(buf, bIsPickup);
+ WriteSaveBuf(buf, bFlag2);
+ WriteSaveBuf(buf, bOutOfStock);
+ WriteSaveBuf(buf, bGlassCracked);
+ WriteSaveBuf(buf, bGlassBroken);
+ WriteSaveBuf(buf, bHasBeenDamaged);
+ WriteSaveBuf(buf, bUseVehicleColours);
+ WriteSaveBuf(buf, pObject->m_fCollisionDamageMultiplier);
+ WriteSaveBuf(buf, pObject->m_nCollisionDamageEffect);
+ WriteSaveBuf(buf, pObject->m_nSpecialCollisionResponseCases);
+ WriteSaveBuf(buf, pObject->m_nEndOfLifeTime);
+ WriteSaveBuf(buf, (pObject->GetAddressOfEntityProperties())[0]);
+ WriteSaveBuf(buf, (pObject->GetAddressOfEntityProperties())[1]);
+ }
+ }
+VALIDATESAVEBUF(*size)
+}
+
+void CPools::LoadObjectPool(uint8* buf, uint32 size)
+{
+INITSAVEBUF
+ int nObjects = ReadSaveBuf<int>(buf);
+ for (int i = 0; i < nObjects; i++) {
+ int16 mi = ReadSaveBuf<int16>(buf);
+ int ref = ReadSaveBuf<int>(buf);
+ char* obuf = new char[sizeof(CObject)];
+ CObject* pBufferObject = (CObject*)obuf;
+ CCompressedMatrixNotAligned tmp;
+ tmp = ReadSaveBuf<CCompressedMatrixNotAligned>(buf);
+ tmp.DecompressIntoFullMatrix(pBufferObject->GetMatrix());
+ ReadSaveBuf<uint32>(buf);
+ pBufferObject->m_fUprootLimit = ReadSaveBuf<float>(buf);
+ tmp = ReadSaveBuf<CCompressedMatrixNotAligned>(buf);
+ tmp.DecompressIntoFullMatrix(pBufferObject->m_objectMatrix);
+ ReadSaveBuf<uint32>(buf);
+ pBufferObject->ObjectCreatedBy = ReadSaveBuf<int8>(buf);
+ pBufferObject->bIsPickup = ReadSaveBuf<bool>(buf);
+ pBufferObject->m_flagE2 = ReadSaveBuf<bool>(buf);
+ pBufferObject->bOutOfStock = ReadSaveBuf<bool>(buf);
+ pBufferObject->bGlassCracked = ReadSaveBuf<bool>(buf);
+ pBufferObject->bGlassBroken = ReadSaveBuf<bool>(buf);
+ pBufferObject->bHasBeenDamaged = ReadSaveBuf<bool>(buf);
+ pBufferObject->bUseVehicleColours = ReadSaveBuf<bool>(buf);
+ pBufferObject->m_fCollisionDamageMultiplier = ReadSaveBuf<float>(buf);
+ pBufferObject->m_nCollisionDamageEffect = ReadSaveBuf<uint8>(buf);
+ pBufferObject->m_nSpecialCollisionResponseCases = ReadSaveBuf<uint8>(buf);
+ pBufferObject->m_nEndOfLifeTime = ReadSaveBuf<uint32>(buf);
+ (pBufferObject->GetAddressOfEntityProperties())[0] = ReadSaveBuf<uint32>(buf);
+ (pBufferObject->GetAddressOfEntityProperties())[1] = ReadSaveBuf<uint32>(buf);
+ if (GetObjectPool()->GetSlot(ref >> 8))
+ CPopulation::ConvertToDummyObject(GetObjectPool()->GetSlot(ref >> 8));
+ CObject* pObject = new(ref) CObject(mi, false);
+ pObject->GetMatrix() = pBufferObject->GetMatrix();
+ pObject->m_fUprootLimit = pBufferObject->m_fUprootLimit;
+ pObject->m_objectMatrix = pBufferObject->m_objectMatrix;
+ pObject->ObjectCreatedBy = pBufferObject->ObjectCreatedBy;
+ pObject->bIsPickup = pBufferObject->bIsPickup;
+ pObject->m_flagE2 = pBufferObject->m_flagE2;
+ pObject->bOutOfStock = pBufferObject->bOutOfStock;
+ pObject->bGlassCracked = pBufferObject->bGlassCracked;
+ pObject->bGlassBroken = pBufferObject->bGlassBroken;
+ pObject->bHasBeenDamaged = pBufferObject->bHasBeenDamaged;
+ pObject->bUseVehicleColours = pBufferObject->bUseVehicleColours;
+ pObject->m_fCollisionDamageMultiplier = pBufferObject->m_fCollisionDamageMultiplier;
+ pObject->m_nCollisionDamageEffect = pBufferObject->m_nCollisionDamageEffect;
+ pObject->m_nSpecialCollisionResponseCases = pBufferObject->m_nSpecialCollisionResponseCases;
+ pObject->m_nEndOfLifeTime = pBufferObject->m_nEndOfLifeTime;
+ (pObject->GetAddressOfEntityProperties())[0] = (pBufferObject->GetAddressOfEntityProperties())[0];
+ (pObject->GetAddressOfEntityProperties())[1] = (pBufferObject->GetAddressOfEntityProperties())[1];
+ pObject->bHasCollided = false;
+ CWorld::Add(pObject);
+ delete[] obuf;
+ }
+VALIDATESAVEBUF(size)
+}
+
+void CPools::SavePedPool(uint8* buf, uint32* size)
+{
+INITSAVEBUF
+ int nNumPeds = 0;
+ int nPoolSize = GetPedPool()->GetSize();
+ for (int i = 0; i < nPoolSize; i++) {
+ CPed* pPed = GetPedPool()->GetSlot(i);
+ if (!pPed)
+ continue;
+ if (!pPed->bInVehicle && pPed->m_nPedType == PEDTYPE_PLAYER1)
+ nNumPeds++;
+ }
+ *size = sizeof(int) + nNumPeds * (sizeof(uint32) + sizeof(int16) + sizeof(int) + sizeof(CPlayerPed) +
+ sizeof(CWanted::MaximumWantedLevel) + sizeof(CWanted::nMaximumWantedLevel) + MAX_MODEL_NAME);
+ WriteSaveBuf(buf, nNumPeds);
+ for (int i = 0; i < nPoolSize; i++) {
+ CPed* pPed = GetPedPool()->GetSlot(i);
+ if (!pPed)
+ continue;
+ if (!pPed->bInVehicle && pPed->m_nPedType == PEDTYPE_PLAYER1) {
+ WriteSaveBuf(buf, pPed->m_nPedType);
+ WriteSaveBuf(buf, pPed->m_modelIndex);
+ WriteSaveBuf(buf, GetPedRef(pPed));
+ memcpy(buf, pPed, sizeof(CPlayerPed));
+ SkipSaveBuf(buf, sizeof(CPlayerPed));
+ WriteSaveBuf(buf, CWanted::MaximumWantedLevel);
+ WriteSaveBuf(buf, CWanted::nMaximumWantedLevel);
+ memcpy(buf, CModelInfo::GetModelInfo(pPed->GetModelIndex())->GetName(), MAX_MODEL_NAME);
+ SkipSaveBuf(buf, MAX_MODEL_NAME);
+ }
+ }
+VALIDATESAVEBUF(*size);
+}
+
+void CPools::LoadPedPool(uint8* buf, uint32 size)
+{
+INITSAVEBUF
+ int nPeds = ReadSaveBuf<int>(buf);
+ for (int i = 0; i < nPeds; i++) {
+ uint32 pedtype = ReadSaveBuf<uint32>(buf);
+ int16 model = ReadSaveBuf<int16>(buf);
+ int ref = ReadSaveBuf<int>(buf);
+ char* pbuf = new char[sizeof(CPlayerPed)];
+ CPlayerPed* pBufferPlayer = (CPlayerPed*)pbuf;
+ CPed* pPed;
+ char name[MAX_MODEL_NAME];
+ // the code implies that there was idea to load non-player ped
+ if (pedtype == PEDTYPE_PLAYER1) { // always true
+ memcpy(pbuf, buf, sizeof(CPlayerPed));
+ SkipSaveBuf(buf, sizeof(CPlayerPed));
+ CWanted::MaximumWantedLevel = ReadSaveBuf<int32>(buf);
+ CWanted::nMaximumWantedLevel = ReadSaveBuf<int32>(buf);
+ memcpy(name, buf, MAX_MODEL_NAME);
+ SkipSaveBuf(buf, MAX_MODEL_NAME);
+ }
+ CStreaming::RequestSpecialModel(model, name, STREAMFLAGS_DONT_REMOVE);
+ CStreaming::LoadAllRequestedModels(false);
+ if (pedtype == PEDTYPE_PLAYER1) {
+ CPlayerPed* pPlayerPed = new(ref) CPlayerPed();
+ for (int i = 0; i < ARRAY_SIZE(pPlayerPed->m_nTargettableObjects); i++)
+ pPlayerPed->m_nTargettableObjects[i] = pBufferPlayer->m_nTargettableObjects[i];
+ pPlayerPed->m_fMaxStamina = pBufferPlayer->m_fMaxStamina;
+ pPed = pPlayerPed;
+ }
+ pPed->GetPosition() = pBufferPlayer->GetPosition();
+ pPed->m_fHealth = pBufferPlayer->m_fHealth;
+ pPed->m_fArmour = pBufferPlayer->m_fArmour;
+ pPed->CharCreatedBy = pBufferPlayer->CharCreatedBy;
+ pPed->m_currentWeapon = 0;
+ pPed->m_maxWeaponTypeAllowed = pBufferPlayer->m_maxWeaponTypeAllowed;
+ for (int i = 0; i < WEAPONTYPE_TOTAL_INVENTORY_WEAPONS; i++)
+ pPed->m_weapons[i] = pBufferPlayer->m_weapons[i];
+ if (pedtype == PEDTYPE_PLAYER1) {
+ pPed->m_wepAccuracy = 100;
+ CWorld::Players[0].m_pPed = (CPlayerPed*)pPed;
+ }
+ CWorld::Add(pPed);
+ delete[] pbuf;
+ }
+VALIDATESAVEBUF(size)
+}
STARTPATCHES
InjectHook(0x4A1770, CPools::Initialise, PATCH_JUMP);
@@ -111,4 +437,7 @@ STARTPATCHES
InjectHook(0x4A1B00, CPools::GetObjectRef, PATCH_JUMP);
InjectHook(0x4A1B20, CPools::GetObject, PATCH_JUMP);
InjectHook(0x4A2DB0, CPools::MakeSureSlotInObjectPoolIsEmpty, PATCH_JUMP);
+ InjectHook(0x4A1B40, CPools::LoadVehiclePool, PATCH_JUMP);
+ InjectHook(0x4A2550, CPools::LoadObjectPool, PATCH_JUMP);
+ InjectHook(0x4A2B50, CPools::LoadPedPool, PATCH_JUMP);
ENDPATCHES
diff --git a/src/core/Profile.cpp b/src/core/Profile.cpp
new file mode 100644
index 00000000..56584d12
--- /dev/null
+++ b/src/core/Profile.cpp
@@ -0,0 +1,71 @@
+#include "common.h"
+#include "Profile.h"
+
+#ifndef MASTER
+float CProfile::ms_afStartTime[NUM_PROFILES];
+float CProfile::ms_afCumulativeTime[NUM_PROFILES];
+float CProfile::ms_afEndTime[NUM_PROFILES];
+float CProfile::ms_afMaxEndTime[NUM_PROFILES];
+float CProfile::ms_afMaxCumulativeTime[NUM_PROFILES];
+char *CProfile::ms_pProfileString[NUM_PROFILES];
+RwRGBA CProfile::ms_aBarColours[NUM_PROFILES];
+
+void CProfile::Initialise()
+{
+ ms_afMaxEndTime[PROFILE_FRAME_RATE] = 0.0f;
+ ms_afMaxEndTime[PROFILE_PHYSICS] = 0.0f;
+ ms_afMaxEndTime[PROFILE_COLLISION] = 0.0f;
+ ms_afMaxEndTime[PROFILE_PED_AI] = 0.0f;
+ ms_afMaxEndTime[PROFILE_PROCESSING_TIME] = 0.0f;
+ ms_afMaxEndTime[PROFILE_RENDERING_TIME] = 0.0f;
+ ms_afMaxEndTime[PROFILE_TOTAL] = 0.0f;
+
+ ms_pProfileString[PROFILE_FRAME_RATE] = "Frame rate";
+ ms_pProfileString[PROFILE_PHYSICS] = "Physics";
+ ms_pProfileString[PROFILE_COLLISION] = "Collision";
+ ms_pProfileString[PROFILE_PED_AI] = "Ped AI";
+ ms_pProfileString[PROFILE_PROCESSING_TIME] = "Processing time";
+ ms_pProfileString[PROFILE_RENDERING_TIME] = "Rendering time";
+ ms_pProfileString[PROFILE_TOTAL] = "Total";
+
+ ms_afMaxCumulativeTime[PROFILE_FRAME_RATE] = 0.0f;
+ ms_afMaxCumulativeTime[PROFILE_PHYSICS] = 0.0f;
+ ms_afMaxCumulativeTime[PROFILE_COLLISION] = 0.0f;
+ ms_afMaxCumulativeTime[PROFILE_PED_AI] = 0.0f;
+ ms_afMaxCumulativeTime[PROFILE_PROCESSING_TIME] = 0.0f;
+ ms_afMaxCumulativeTime[PROFILE_RENDERING_TIME] = 0.0f;
+ ms_afMaxCumulativeTime[PROFILE_TOTAL] = 0.0f;
+
+ ms_aBarColours[PROFILE_PHYSICS] = { 0, 127, 255, 255 };
+ ms_aBarColours[PROFILE_COLLISION] = { 0, 255, 255, 255 };
+ ms_aBarColours[PROFILE_PED_AI] = { 255, 0, 0, 255 };
+ ms_aBarColours[PROFILE_PROCESSING_TIME] = { 0, 255, 0, 255 };
+ ms_aBarColours[PROFILE_RENDERING_TIME] = { 0, 0, 255, 255 };
+ ms_aBarColours[PROFILE_TOTAL] = { 255, 255, 255, 255 };
+}
+
+void CProfile::SuspendProfile(eProfile profile)
+{
+ ms_afEndTime[profile] = -ms_afStartTime[profile];
+ ms_afCumulativeTime[profile] -= ms_afStartTime[profile];
+}
+
+void CProfile::ShowResults()
+{
+ ms_afMaxEndTime[PROFILE_FRAME_RATE] = max(ms_afMaxEndTime[PROFILE_FRAME_RATE], ms_afEndTime[PROFILE_FRAME_RATE]);
+ ms_afMaxEndTime[PROFILE_PHYSICS] = max(ms_afMaxEndTime[PROFILE_PHYSICS], ms_afEndTime[PROFILE_PHYSICS]);
+ ms_afMaxEndTime[PROFILE_COLLISION] = max(ms_afMaxEndTime[PROFILE_COLLISION], ms_afEndTime[PROFILE_COLLISION]);
+ ms_afMaxEndTime[PROFILE_PED_AI] = max(ms_afMaxEndTime[PROFILE_PED_AI], ms_afEndTime[PROFILE_PED_AI]);
+ ms_afMaxEndTime[PROFILE_PROCESSING_TIME] = max(ms_afMaxEndTime[PROFILE_PROCESSING_TIME], ms_afEndTime[PROFILE_PROCESSING_TIME]);
+ ms_afMaxEndTime[PROFILE_RENDERING_TIME] = max(ms_afMaxEndTime[PROFILE_RENDERING_TIME], ms_afEndTime[PROFILE_RENDERING_TIME]);
+ ms_afMaxEndTime[PROFILE_TOTAL] = max(ms_afMaxEndTime[PROFILE_TOTAL], ms_afEndTime[PROFILE_TOTAL]);
+
+ ms_afMaxCumulativeTime[PROFILE_FRAME_RATE] = max(ms_afMaxCumulativeTime[PROFILE_FRAME_RATE], ms_afCumulativeTime[PROFILE_FRAME_RATE]);
+ ms_afMaxCumulativeTime[PROFILE_PHYSICS] = max(ms_afMaxCumulativeTime[PROFILE_PHYSICS], ms_afCumulativeTime[PROFILE_PHYSICS]);
+ ms_afMaxCumulativeTime[PROFILE_COLLISION] = max(ms_afMaxCumulativeTime[PROFILE_COLLISION], ms_afCumulativeTime[PROFILE_COLLISION]);
+ ms_afMaxCumulativeTime[PROFILE_PED_AI] = max(ms_afMaxCumulativeTime[PROFILE_PED_AI], ms_afCumulativeTime[PROFILE_PED_AI]);
+ ms_afMaxCumulativeTime[PROFILE_PROCESSING_TIME] = max(ms_afMaxCumulativeTime[PROFILE_PROCESSING_TIME], ms_afCumulativeTime[PROFILE_PROCESSING_TIME]);
+ ms_afMaxCumulativeTime[PROFILE_RENDERING_TIME] = max(ms_afMaxCumulativeTime[PROFILE_RENDERING_TIME], ms_afCumulativeTime[PROFILE_RENDERING_TIME]);
+ ms_afMaxCumulativeTime[PROFILE_TOTAL] = max(ms_afMaxCumulativeTime[PROFILE_TOTAL], ms_afCumulativeTime[PROFILE_TOTAL]);
+}
+#endif \ No newline at end of file
diff --git a/src/core/Profile.h b/src/core/Profile.h
new file mode 100644
index 00000000..d2e8054b
--- /dev/null
+++ b/src/core/Profile.h
@@ -0,0 +1,28 @@
+#pragma once
+
+enum eProfile
+{
+ PROFILE_FRAME_RATE,
+ PROFILE_PHYSICS,
+ PROFILE_COLLISION,
+ PROFILE_PED_AI,
+ PROFILE_PROCESSING_TIME,
+ PROFILE_RENDERING_TIME,
+ PROFILE_TOTAL,
+ NUM_PROFILES,
+};
+
+class CProfile
+{
+ static float ms_afStartTime[NUM_PROFILES];
+ static float ms_afCumulativeTime[NUM_PROFILES];
+ static float ms_afEndTime[NUM_PROFILES];
+ static float ms_afMaxEndTime[NUM_PROFILES];
+ static float ms_afMaxCumulativeTime[NUM_PROFILES];
+ static char *ms_pProfileString[NUM_PROFILES];
+ static RwRGBA ms_aBarColours[NUM_PROFILES];
+public:
+ static void Initialise();
+ static void SuspendProfile(eProfile profile);
+ static void ShowResults();
+}; \ No newline at end of file
diff --git a/src/core/Timer.h b/src/core/Timer.h
index b119bfb2..a4d674da 100644
--- a/src/core/Timer.h
+++ b/src/core/Timer.h
@@ -53,6 +53,9 @@ public:
static void Stop(void);
static void StartUserPause(void);
static void EndUserPause(void);
+
+ friend bool GenericLoad(void);
+ friend bool GenericSave(int file);
};
#ifdef FIX_BUGS
diff --git a/src/entities/Entity.h b/src/entities/Entity.h
index 17a219c3..ca501ba4 100644
--- a/src/entities/Entity.h
+++ b/src/entities/Entity.h
@@ -90,6 +90,7 @@ public:
CReference *m_pFirstReference;
CColModel *GetColModel(void) { return CModelInfo::GetModelInfo(m_modelIndex)->GetColModel(); }
+ uint32* GetAddressOfEntityProperties() { /* AWFUL */ return (uint32*)((char*)&m_rwObject + sizeof(m_rwObject)); }
CEntity(void);
~CEntity(void);
diff --git a/src/modelinfo/BaseModelInfo.h b/src/modelinfo/BaseModelInfo.h
index a9bafb64..0c4bf934 100644
--- a/src/modelinfo/BaseModelInfo.h
+++ b/src/modelinfo/BaseModelInfo.h
@@ -2,6 +2,8 @@
#include "Collision.h"
+#define MAX_MODEL_NAME (24)
+
enum ModeInfoType : uint8
{
MITYPE_NA = 0,
@@ -21,7 +23,7 @@ class CBaseModelInfo
{
protected:
// TODO?: make more things protected
- char m_name[24];
+ char m_name[MAX_MODEL_NAME];
CColModel *m_colModel;
C2dEffect *m_twodEffects;
int16 m_objectId;
diff --git a/src/control/Gangs.cpp b/src/peds/Gangs.cpp
index 57d9c67e..c67fe599 100644
--- a/src/control/Gangs.cpp
+++ b/src/peds/Gangs.cpp
@@ -4,7 +4,6 @@
#include "Gangs.h"
#include "Weapon.h"
-//CGangInfo(&CGangs::Gang)[NUM_GANGS] = *(CGangInfo(*)[NUM_GANGS])*(uintptr*)0x6EDF78;
CGangInfo CGangs::Gang[NUM_GANGS];
CGangInfo::CGangInfo() :
@@ -70,7 +69,6 @@ void CGangs::LoadAllGangData(uint8 *buf, uint32 size)
Initialise();
INITSAVEBUF
- // original: SkipSaveBuf(buf, SAVE_HEADER_SIZE);
CheckSaveHeader(buf, 'G','N','G','\0', size - SAVE_HEADER_SIZE);
for (int i = 0; i < NUM_GANGS; i++)
diff --git a/src/control/Gangs.h b/src/peds/Gangs.h
index dd7a7f93..dd7a7f93 100644
--- a/src/control/Gangs.h
+++ b/src/peds/Gangs.h
diff --git a/src/peds/Population.cpp b/src/peds/Population.cpp
index dfa61584..6959487f 100644
--- a/src/peds/Population.cpp
+++ b/src/peds/Population.cpp
@@ -29,39 +29,54 @@
#define PED_REMOVE_DIST (MIN_CREATION_DIST + CREATION_RANGE + 1.0f)
#define PED_REMOVE_DIST_SPECIAL (MIN_CREATION_DIST + CREATION_RANGE + 15.0f) // for peds with bCullExtraFarAway flag
-// TO-DO: These are hard-coded, reverse them.
-// More clearly they're transition areas between zones.
-RegenerationPoint (&aSafeZones)[8] = *(RegenerationPoint(*)[8]) * (uintptr*)0x5FA578;
-
-//PedGroup (&CPopulation::ms_pPedGroups)[NUMPEDGROUPS] = *(PedGroup(*)[NUMPEDGROUPS]) * (uintptr*)0x6E9248;
-PedGroup CPopulation::ms_pPedGroups[NUMPEDGROUPS];
-bool &CPopulation::ms_bGivePedsWeapons = *(bool*)0x95CCF6;
-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;
-int8& CPopulation::m_CountDownToPedsAtStart = *(int8*)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;
-CVector &CPopulation::RegenerationPoint_a = *(CVector*)0x8E2AA4;
-CVector &CPopulation::RegenerationPoint_b = *(CVector*)0x8E2A98;
-CVector &CPopulation::RegenerationForward = *(CVector*)0x8F1AD4;
+// Transition areas between zones
+const RegenerationPoint aSafeZones[] = {
+ { LEVEL_INDUSTRIAL, LEVEL_COMMERCIAL, 400.0f, 814.0f, -954.0f, -903.0f, 30.0f, 100.0f,
+ CVector(790.0f, -917.0f, 39.0f), CVector(775.0f, -921.0f, 39.0f), CVector(424.0f, -942.0f, 38.0f), CVector(439.0f, -938.0f, 38.0f) },
+ { LEVEL_INDUSTRIAL, LEVEL_COMMERCIAL, 555.0f, 711.0f, 118.0f, 186.0f, -30.0f, -10.0f,
+ CVector(698.0f, 182.0f, -20.0f), CVector(681.0f, 178.0f, -20.0f), CVector(586.0f, 144.0f, -20.0f), CVector(577.0f, 135.0f, -20.0f) },
+ { LEVEL_INDUSTRIAL, LEVEL_COMMERCIAL, 26.0f, 44.0f, 124.0f, 87.0f, 20.0f, 6.0f,
+ CVector(736.0f, -117.0f, -13.0f), CVector(730.0f, -115.0f, -13.0f), CVector(635.0f, -93.0f, -12.5f), CVector(650.0f, -89.0f, -12.5f) },
+ { LEVEL_INDUSTRIAL, LEVEL_COMMERCIAL, 45.0f, 34.0f, 780.0f, 750.0f, 25.0f, 6.0f,
+ CVector(729.0f, -764.0f, -18.0f), CVector(720.0f, -769.0f, -17.0f), CVector(652.0f, -774.0f, -10.5f), CVector(659.0f, -770.0f, -10.5f) },
+ { LEVEL_COMMERCIAL, LEVEL_SUBURBAN, 532.0f, 136.0f, 668.0f, 599.0f, 4.0f, 0.0f,
+ CVector(-172.0f, -619.0f, 44.0f), CVector(-183.0f, -623.0f, 44.0f), CVector(-511.0f, -645.0f, 41.0f), CVector(-493.0f, -639.0f, 41.5f) },
+ { LEVEL_COMMERCIAL, LEVEL_SUBURBAN, 325.0f, 175.0f, 7.0f, 5.0f, 30.0f, 10.0f,
+ CVector(-185.0f, 40.8f, -20.5f), CVector(-202.0f, 37.0f, -20.5f), CVector(-315.0f, 65.5f, -20.5f), CVector(-306.0f, 62.4f, -20.5f) },
+ { LEVEL_COMMERCIAL, LEVEL_SUBURBAN, 410.0f, 310.0f, 1055.0f, 1030.0f, 20.0f, 6.0f,
+ CVector(-321.0f, -1043.0f, -13.2f), CVector(-328.0f, -1045.0f, -13.2f), CVector(-398.0f, -1044.0f, -13.5f), CVector(-390.0f, -1040.5f, -13.5f) },
+ { LEVEL_COMMERCIAL, LEVEL_SUBURBAN, 425.0f, 280.0f, 471.0f, 447.0f, 20.0f, 5.0f,
+ CVector(-292.0f, -457.0f, -11.6f), CVector(-310.0f, -461.0f, -11.6f), CVector(-413.0f, -461.0f, -11.5f), CVector(-399.0f, -457.0f, -11.3f) }
+}; // *(RegenerationPoint(*)[8]) * (uintptr*)0x5FA578;
+
+PedGroup CPopulation::ms_pPedGroups[NUMPEDGROUPS]; // = *(PedGroup(*)[NUMPEDGROUPS]) * (uintptr*)0x6E9248;
+bool CPopulation::ms_bGivePedsWeapons; // = *(bool*)0x95CCF6;
+int32 CPopulation::m_AllRandomPedsThisType = -1; // = *(int32*)0x5FA570;
+float CPopulation::PedDensityMultiplier = 1.0f; // = *(float*)0x5FA56C;
+uint32 CPopulation::ms_nTotalMissionPeds; // = *(uint32*)0x8F5F70;
+int32 CPopulation::MaxNumberOfPedsInUse = 25; // *(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;
+int8 CPopulation::m_CountDownToPedsAtStart; // = *(int8*)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;
+CVector CPopulation::RegenerationPoint_a; // = *(CVector*)0x8E2AA4;
+CVector CPopulation::RegenerationPoint_b; // = *(CVector*)0x8E2A98;
+CVector CPopulation::RegenerationForward; // = *(CVector*)0x8F1AD4;
void
CPopulation::Initialise()
diff --git a/src/peds/Population.h b/src/peds/Population.h
index f9e6c3b7..aa8129c0 100644
--- a/src/peds/Population.h
+++ b/src/peds/Population.h
@@ -34,33 +34,33 @@ class CPopulation
{
public:
static PedGroup ms_pPedGroups[NUMPEDGROUPS];
- static bool &ms_bGivePedsWeapons;
- static int32 &m_AllRandomPedsThisType;
- 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 int8& 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 CVector& RegenerationPoint_a;
- static CVector& RegenerationPoint_b;
- static CVector& RegenerationForward;
+ static bool ms_bGivePedsWeapons;
+ static int32 m_AllRandomPedsThisType;
+ 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 int8 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 CVector RegenerationPoint_a;
+ static CVector RegenerationPoint_b;
+ static CVector RegenerationForward;
static void Initialise();
static void Update(void);
diff --git a/src/rw/RwHelper.cpp b/src/rw/RwHelper.cpp
index 44866f4f..44ca3a0a 100644
--- a/src/rw/RwHelper.cpp
+++ b/src/rw/RwHelper.cpp
@@ -3,6 +3,44 @@
#include "patcher.h"
#include "Timecycle.h"
#include "skeleton.h"
+#if defined(RWLIBS) && !defined(FINAL)
+#include "rtcharse.h"
+#pragma comment( lib, "rtcharse.lib" )
+
+RtCharset *debugCharset;
+#endif
+
+void CreateDebugFont()
+{
+#if defined(RWLIBS) && !defined(FINAL)
+ RwRGBA color = { 255, 255, 128, 255 };
+ RwRGBA colorbg = { 0, 0, 0, 0 };
+ RtCharsetOpen();
+ debugCharset = RtCharsetCreate(&color, &colorbg);
+#endif
+}
+
+void DestroyDebugFont()
+{
+#if defined(RWLIBS) && !defined(FINAL)
+ RtCharsetDestroy(debugCharset);
+ RtCharsetClose();
+#endif
+}
+
+void ObrsPrintfString(const char *str, short x, short y)
+{
+#if defined(RWLIBS) && !defined(FINAL)
+ RtCharsetPrintBuffered(debugCharset, str, x, y, true);
+#endif
+}
+
+void FlushObrsPrintfs()
+{
+#if defined(RWLIBS) && !defined(FINAL)
+ RtCharsetBufferFlush();
+#endif
+}
void *
RwMallocAlign(RwUInt32 size, RwUInt32 align)
@@ -347,21 +385,6 @@ CameraCreate(RwInt32 width, RwInt32 height, RwBool zBuffer)
return (nil);
}
-void CreateDebugFont()
-{
- ;
-}
-
-void DestroyDebugFont()
-{
- ;
-}
-
-void FlushObrsPrintfs()
-{
- ;
-}
-
WRAPPER void _TexturePoolsInitialise() { EAXJMP(0x598B10); }
WRAPPER void _TexturePoolsShutdown() { EAXJMP(0x598B30); }
diff --git a/src/rw/RwHelper.h b/src/rw/RwHelper.h
index a9f0bdf4..5b47cb6f 100644
--- a/src/rw/RwHelper.h
+++ b/src/rw/RwHelper.h
@@ -5,6 +5,7 @@ void RwFreeAlign(void *mem);
void CreateDebugFont();
void DestroyDebugFont();
+void ObrsPrintfString(const char *str, short x, short y);
void FlushObrsPrintfs();
void DefinedState(void);
RwFrame *GetFirstChild(RwFrame *frame);
diff --git a/src/save/GenericGameStorage.cpp b/src/save/GenericGameStorage.cpp
index 2545b9ab..0ec0b117 100644
--- a/src/save/GenericGameStorage.cpp
+++ b/src/save/GenericGameStorage.cpp
@@ -9,17 +9,20 @@
#include "Clock.h"
#include "Date.h"
#include "FileMgr.h"
+#include "Frontend.h"
#include "GameLogic.h"
#include "Gangs.h"
#include "Garages.h"
#include "GenericGameStorage.h"
#include "Pad.h"
+#include "Particle.h"
#include "ParticleObject.h"
#include "PathFind.h"
#include "PCSave.h"
#include "Phones.h"
#include "Pickups.h"
#include "PlayerPed.h"
+#include "ProjectileInfo.h"
#include "Pools.h"
#include "Radar.h"
#include "Restart.h"
@@ -48,7 +51,6 @@ char SaveFileNameJustSaved[260];
int (&Slots)[SLOT_COUNT+1] = *(int(*)[SLOT_COUNT+1])*(uintptr*)0x72803C;
CDate &CompileDateAndTime = *(CDate*)0x72BCB8;
-
bool &b_FoundRecentSavedGameWantToLoad = *(bool*)0x95CDA8;
bool &JustLoadedDontFadeInYet = *(bool*)0x95CDB4;
bool &StillToFadeOut = *(bool*)0x95CD99;
@@ -58,10 +60,26 @@ uint32 &TimeToStayFadedBeforeFadeOut = *(uint32*)0x611564;
#define ReadDataFromBufferPointer(buf, to) memcpy(&to, buf, sizeof(to)); buf += align4bytes(sizeof(to));
#define WriteDataToBufferPointer(buf, from) memcpy(buf, &from, sizeof(from)); buf += align4bytes(sizeof(from));
-WRAPPER bool GenericLoad() { EAXJMP(0x590A00); }
+#define LoadSaveDataBlock()\
+do {\
+ if (!ReadDataFromFile(file, (uint8 *) &size, 4))\
+ return false;\
+ size = align4bytes(size);\
+ if (!ReadDataFromFile(file, work_buff, size))\
+ return false;\
+ buf = work_buff;\
+} while (0)
+#define ReadDataFromBlock(msg,load_func)\
+do {\
+ debug(msg);\
+ ReadDataFromBufferPointer(buf, size);\
+ load_func(buf, size);\
+ size = align4bytes(size);\
+ buf += size;\
+} while (0)
-#define WRITE_BLOCK(save_func)\
+#define WriteSaveDataBlock(save_func)\
do {\
buf = work_buff;\
reserved = 0;\
@@ -117,11 +135,11 @@ GenericSave(int file)
WriteDataToBufferPointer(buf, CClock::ms_nGameClockMinutes);
currPad = CPad::GetPad(0);
WriteDataToBufferPointer(buf, currPad->Mode);
- WriteDataToBufferPointer(buf, CTimer::GetTimeInMilliseconds());
- WriteDataToBufferPointer(buf, CTimer::GetTimeScale());
- WriteDataToBufferPointer(buf, CTimer::GetTimeStep());
- WriteDataToBufferPointer(buf, CTimer::GetTimeStepNonClipped());
- WriteDataToBufferPointer(buf, CTimer::GetFrameCounter());
+ WriteDataToBufferPointer(buf, CTimer::m_snTimeInMilliseconds);
+ WriteDataToBufferPointer(buf, CTimer::ms_fTimeScale);
+ WriteDataToBufferPointer(buf, CTimer::ms_fTimeStep);
+ WriteDataToBufferPointer(buf, CTimer::ms_fTimeStepNonClipped);
+ WriteDataToBufferPointer(buf, CTimer::m_FrameCounter);
WriteDataToBufferPointer(buf, CTimeStep::ms_fTimeStep);
WriteDataToBufferPointer(buf, CTimeStep::ms_fFramesPerUpdate);
WriteDataToBufferPointer(buf, CTimeStep::ms_fTimeScale);
@@ -138,7 +156,6 @@ GenericSave(int file)
WriteDataToBufferPointer(buf, CWeather::WeatherTypeInList);
WriteDataToBufferPointer(buf, TheCamera.CarZoomIndicator);
WriteDataToBufferPointer(buf, TheCamera.PedZoomIndicator);
-
assert(buf - work_buff == SIZE_OF_SIMPLEVARS);
// Save scripts, block is nested within the same block as simple vars for some reason
@@ -153,25 +170,25 @@ GenericSave(int file)
totalSize = buf - work_buff;
// Save the rest
- WRITE_BLOCK(CPools::SavePedPool);
- WRITE_BLOCK(CGarages::Save);
- WRITE_BLOCK(CPools::SaveVehiclePool);
- WRITE_BLOCK(CPools::SaveObjectPool);
- WRITE_BLOCK(ThePaths.Save);
- WRITE_BLOCK(CCranes::Save);
- WRITE_BLOCK(CPickups::Save);
- WRITE_BLOCK(gPhoneInfo.Save);
- WRITE_BLOCK(CRestart::SaveAllRestartPoints);
- WRITE_BLOCK(CRadar::SaveAllRadarBlips);
- WRITE_BLOCK(CTheZones::SaveAllZones);
- WRITE_BLOCK(CGangs::SaveAllGangData);
- WRITE_BLOCK(CTheCarGenerators::SaveAllCarGenerators);
- WRITE_BLOCK(CParticleObject::SaveParticle);
- WRITE_BLOCK(cAudioScriptObject::SaveAllAudioScriptObjects);
- WRITE_BLOCK(CWorld::Players[CWorld::PlayerInFocus].SavePlayerInfo);
- WRITE_BLOCK(CStats::SaveStats);
- WRITE_BLOCK(CStreaming::MemoryCardSave);
- WRITE_BLOCK(CPedType::Save);
+ WriteSaveDataBlock(CPools::SavePedPool);
+ WriteSaveDataBlock(CGarages::Save);
+ WriteSaveDataBlock(CPools::SaveVehiclePool);
+ WriteSaveDataBlock(CPools::SaveObjectPool);
+ WriteSaveDataBlock(ThePaths.Save);
+ WriteSaveDataBlock(CCranes::Save);
+ WriteSaveDataBlock(CPickups::Save);
+ WriteSaveDataBlock(gPhoneInfo.Save);
+ WriteSaveDataBlock(CRestart::SaveAllRestartPoints);
+ WriteSaveDataBlock(CRadar::SaveAllRadarBlips);
+ WriteSaveDataBlock(CTheZones::SaveAllZones);
+ WriteSaveDataBlock(CGangs::SaveAllGangData);
+ WriteSaveDataBlock(CTheCarGenerators::SaveAllCarGenerators);
+ WriteSaveDataBlock(CParticleObject::SaveParticle);
+ WriteSaveDataBlock(cAudioScriptObject::SaveAllAudioScriptObjects);
+ WriteSaveDataBlock(CWorld::Players[CWorld::PlayerInFocus].SavePlayerInfo);
+ WriteSaveDataBlock(CStats::SaveStats);
+ WriteSaveDataBlock(CStreaming::MemoryCardSave);
+ WriteSaveDataBlock(CPedType::Save);
// Write padding
for (int i = 0; i < 4; i++) {
@@ -199,6 +216,115 @@ GenericSave(int file)
}
bool
+GenericLoad()
+{
+ uint8 *buf;
+ int32 file;
+ uint32 size;
+
+ int32 saveSize;
+ CPad *currPad;
+
+ // Load SimpleVars and Scripts
+ CheckSum = 0;
+ CDate(CompileDateAndTime);
+ CPad::ResetCheats();
+ if (!ReadInSizeofSaveFileBuffer(file, size))
+ return false;
+ size = align4bytes(size);
+ ReadDataFromFile(file, work_buff, size);
+ buf = (work_buff + 0x40);
+ ReadDataFromBufferPointer(buf, saveSize);
+ ReadDataFromBufferPointer(buf, CGame::currLevel);
+ ReadDataFromBufferPointer(buf, TheCamera.GetPosition().x);
+ ReadDataFromBufferPointer(buf, TheCamera.GetPosition().y);
+ ReadDataFromBufferPointer(buf, TheCamera.GetPosition().z);
+ ReadDataFromBufferPointer(buf, CClock::ms_nMillisecondsPerGameMinute);
+ ReadDataFromBufferPointer(buf, CClock::ms_nLastClockTick);
+ ReadDataFromBufferPointer(buf, CClock::ms_nGameClockHours);
+ ReadDataFromBufferPointer(buf, CClock::ms_nGameClockMinutes);
+ currPad = CPad::GetPad(0);
+ ReadDataFromBufferPointer(buf, currPad->Mode);
+ ReadDataFromBufferPointer(buf, CTimer::m_snTimeInMilliseconds);
+ ReadDataFromBufferPointer(buf, CTimer::ms_fTimeScale);
+ ReadDataFromBufferPointer(buf, CTimer::ms_fTimeStep);
+ ReadDataFromBufferPointer(buf, CTimer::ms_fTimeStepNonClipped);
+ ReadDataFromBufferPointer(buf, CTimer::m_FrameCounter);
+ ReadDataFromBufferPointer(buf, CTimeStep::ms_fTimeStep);
+ ReadDataFromBufferPointer(buf, CTimeStep::ms_fFramesPerUpdate);
+ ReadDataFromBufferPointer(buf, CTimeStep::ms_fTimeScale);
+ ReadDataFromBufferPointer(buf, CWeather::OldWeatherType);
+ ReadDataFromBufferPointer(buf, CWeather::NewWeatherType);
+ ReadDataFromBufferPointer(buf, CWeather::ForcedWeatherType);
+ ReadDataFromBufferPointer(buf, CWeather::InterpolationValue);
+ ReadDataFromBufferPointer(buf, CompileDateAndTime.m_nSecond);
+ ReadDataFromBufferPointer(buf, CompileDateAndTime.m_nMinute);
+ ReadDataFromBufferPointer(buf, CompileDateAndTime.m_nHour);
+ ReadDataFromBufferPointer(buf, CompileDateAndTime.m_nDay);
+ ReadDataFromBufferPointer(buf, CompileDateAndTime.m_nMonth);
+ ReadDataFromBufferPointer(buf, CompileDateAndTime.m_nYear);
+ ReadDataFromBufferPointer(buf, CWeather::WeatherTypeInList);
+ ReadDataFromBufferPointer(buf, TheCamera.CarZoomIndicator);
+ ReadDataFromBufferPointer(buf, TheCamera.PedZoomIndicator);
+ assert(buf - work_buff == SIZE_OF_SIMPLEVARS);
+ ReadDataFromBlock("Loading Scripts \n", CTheScripts::LoadAllScripts);
+
+ // Load the rest
+ LoadSaveDataBlock();
+ ReadDataFromBlock("Loading PedPool \n", CPools::LoadPedPool);
+ LoadSaveDataBlock();
+ ReadDataFromBlock("Loading Garages \n", CGarages::Load);
+ LoadSaveDataBlock();
+ ReadDataFromBlock("Loading Vehicles \n", CPools::LoadVehiclePool);
+ LoadSaveDataBlock();
+ CProjectileInfo::RemoveAllProjectiles();
+ CObject::DeleteAllTempObjects();
+ ReadDataFromBlock("Loading Objects \n", CPools::LoadObjectPool);
+ LoadSaveDataBlock();
+ ReadDataFromBlock("Loading Paths \n", ThePaths.Load);
+ LoadSaveDataBlock();
+ ReadDataFromBlock("Loading Cranes \n", CCranes::Load);
+ LoadSaveDataBlock();
+ ReadDataFromBlock("Loading Pickups \n", CPickups::Load);
+ LoadSaveDataBlock();
+ ReadDataFromBlock("Loading Phoneinfo \n", gPhoneInfo.Load);
+ LoadSaveDataBlock();
+ ReadDataFromBlock("Loading Restart \n", CRestart::LoadAllRestartPoints);
+ LoadSaveDataBlock();
+ ReadDataFromBlock("Loading Radar Blips \n", CRadar::LoadAllRadarBlips);
+ LoadSaveDataBlock();
+ ReadDataFromBlock("Loading Zones \n", CTheZones::LoadAllZones);
+ LoadSaveDataBlock();
+ ReadDataFromBlock("Loading Gang Data \n", CGangs::LoadAllGangData);
+ LoadSaveDataBlock();
+ ReadDataFromBlock("Loading Car Generators \n", CTheCarGenerators::LoadAllCarGenerators);
+ CParticle::ReloadConfig();
+ LoadSaveDataBlock();
+ ReadDataFromBlock("Loading Particles \n", CParticleObject::LoadParticle);
+ LoadSaveDataBlock();
+ ReadDataFromBlock("Loading AudioScript Objects \n", cAudioScriptObject::LoadAllAudioScriptObjects);
+ LoadSaveDataBlock();
+ ReadDataFromBlock("Loading Player Info \n", CWorld::Players[CWorld::PlayerInFocus].LoadPlayerInfo);
+ LoadSaveDataBlock();
+ ReadDataFromBlock("Loading Stats \n", CStats::LoadStats);
+ LoadSaveDataBlock();
+ ReadDataFromBlock("Loading Streaming Stuff \n", CStreaming::MemoryCardLoad);
+ LoadSaveDataBlock();
+ ReadDataFromBlock("Loading PedType Stuff \n", CPedType::Load);
+
+ DMAudio.SetMusicMasterVolume(CMenuManager::m_PrefsMusicVolume);
+ DMAudio.SetEffectsMasterVolume(CMenuManager::m_PrefsSfxVolume);
+ if (!CloseFile(file)) {
+ PcSaveHelper.nErrorCode = SAVESTATUS_ERR_LOAD_CLOSE;
+ return false;
+ }
+
+ DoGameSpecificStuffAfterSucessLoad();
+ debug("Game successfully loaded \n");
+ return true;
+}
+
+bool
ReadInSizeofSaveFileBuffer(int32 &file, uint32 &size)
{
file = CFileMgr::OpenFile(LoadFileName, "rb");
@@ -411,7 +537,7 @@ align4bytes(int32 size)
STARTPATCHES
InjectHook(0x58F8D0, GenericSave, PATCH_JUMP);
- //InjectHook(0x590A00, GenericLoad, PATCH_JUMP);
+ InjectHook(0x590A00, GenericLoad, PATCH_JUMP);
InjectHook(0x591910, ReadInSizeofSaveFileBuffer, PATCH_JUMP);
InjectHook(0x591990, ReadDataFromFile, PATCH_JUMP);
InjectHook(0x591A00, CloseFile, PATCH_JUMP);
diff --git a/src/control/CarGen.cpp b/src/vehicles/CarGen.cpp
index 721ac35a..43f77fb7 100644
--- a/src/control/CarGen.cpp
+++ b/src/vehicles/CarGen.cpp
@@ -14,11 +14,11 @@
#include "Vehicle.h"
#include "World.h"
-uint8 &CTheCarGenerators::ProcessCounter = *(uint8*)0x95CDAF;
-uint32 &CTheCarGenerators::NumOfCarGenerators = *(uint32*)0x8E2C1C;
-CCarGenerator (&CTheCarGenerators::CarGeneratorArray)[NUM_CARGENS] = *(CCarGenerator(*)[NUM_CARGENS])*(uintptr*)0x87CB18;
-uint8 &CTheCarGenerators::GenerateEvenIfPlayerIsCloseCounter = *(uint8*)0x95CDC6;
-uint32 &CTheCarGenerators::CurrentActiveCount = *(uint32*)0x8F2C5C;
+uint8 CTheCarGenerators::ProcessCounter;
+uint32 CTheCarGenerators::NumOfCarGenerators;
+CCarGenerator CTheCarGenerators::CarGeneratorArray[NUM_CARGENS];
+uint8 CTheCarGenerators::GenerateEvenIfPlayerIsCloseCounter;
+uint32 CTheCarGenerators::CurrentActiveCount;
void CCarGenerator::SwitchOff()
{
@@ -187,59 +187,6 @@ bool CCarGenerator::CheckIfWithinRangeOfAnyPlayer()
return DotProduct2D(direction, FindPlayerSpeed()) <= 0;
}
-void CCarGenerator::Save(uint8 *&buffer)
-{
- WriteSaveBuf(buffer, m_nModelIndex);
- WriteSaveBuf(buffer, m_vecPos);
- WriteSaveBuf(buffer, m_fAngle);
- WriteSaveBuf(buffer, m_nColor1);
- WriteSaveBuf(buffer, m_nColor2);
- WriteSaveBuf(buffer, m_bForceSpawn);
- WriteSaveBuf(buffer, m_nAlarm);
- WriteSaveBuf(buffer, m_nDoorlock);
- WriteSaveBuf(buffer, (uint8)0);
- WriteSaveBuf(buffer, m_nMinDelay);
- WriteSaveBuf(buffer, m_nMaxDelay);
- WriteSaveBuf(buffer, m_nTimer);
- WriteSaveBuf(buffer, m_nVehicleHandle);
- WriteSaveBuf(buffer, m_nUsesRemaining);
- WriteSaveBuf(buffer, m_bIsBlocking);
- WriteSaveBuf(buffer, (uint8)0);
- WriteSaveBuf(buffer, m_vecInf);
- WriteSaveBuf(buffer, m_vecSup);
- WriteSaveBuf(buffer, m_fSize);
-
- // or
- //WriteSaveBuf(buffer, *this);
-
-}
-
-void CCarGenerator::Load(uint8 *&buffer)
-{
- m_nModelIndex = ReadSaveBuf<uint32>(buffer);
- m_vecPos = ReadSaveBuf<CVector>(buffer);
- m_fAngle = ReadSaveBuf<float>(buffer);
- m_nColor1 = ReadSaveBuf<int16>(buffer);
- m_nColor2 = ReadSaveBuf<int16>(buffer);
- m_bForceSpawn = ReadSaveBuf<uint8>(buffer);
- m_nAlarm = ReadSaveBuf<uint8>(buffer);
- m_nDoorlock = ReadSaveBuf<uint8>(buffer);
- ReadSaveBuf<uint8>(buffer);
- m_nMinDelay = ReadSaveBuf<uint16>(buffer);
- m_nMaxDelay = ReadSaveBuf<uint16>(buffer);
- m_nTimer = ReadSaveBuf<uint32>(buffer);
- m_nVehicleHandle = ReadSaveBuf<int32>(buffer);
- m_nUsesRemaining = ReadSaveBuf<uint16>(buffer);
- m_bIsBlocking = ReadSaveBuf<bool>(buffer);
- ReadSaveBuf<uint8>(buffer);
- m_vecInf = ReadSaveBuf<CVector>(buffer);
- m_vecSup = ReadSaveBuf<CVector>(buffer);
- m_fSize = ReadSaveBuf<float>(buffer);
-
- // or
- //*this = ReadSaveBuf<CCarGenerator>(buffer);
-}
-
void CTheCarGenerators::Process()
{
if (FindPlayerTrain() || CCutsceneMgr::IsCutsceneProcessing())
@@ -268,39 +215,38 @@ void CTheCarGenerators::Init()
void CTheCarGenerators::SaveAllCarGenerators(uint8 *buffer, uint32 *size)
{
- *size = 20 + sizeof(CarGeneratorArray) + SAVE_HEADER_SIZE;
+ const uint32 nGeneralDataSize = sizeof(NumOfCarGenerators) + sizeof(CurrentActiveCount) + sizeof(ProcessCounter) + sizeof(GenerateEvenIfPlayerIsCloseCounter) + sizeof(int16);
+ *size = sizeof(int) + nGeneralDataSize + sizeof(CarGeneratorArray) + SAVE_HEADER_SIZE;
INITSAVEBUF
WriteSaveHeader(buffer, 'C','G','N','\0', *size - SAVE_HEADER_SIZE);
- WriteSaveBuf(buffer, 12); /* what is this? */
+ WriteSaveBuf(buffer, nGeneralDataSize);
WriteSaveBuf(buffer, NumOfCarGenerators);
WriteSaveBuf(buffer, CurrentActiveCount);
WriteSaveBuf(buffer, ProcessCounter);
WriteSaveBuf(buffer, GenerateEvenIfPlayerIsCloseCounter);
- WriteSaveBuf(buffer, (int16)0);
+ WriteSaveBuf(buffer, (int16)0); // alignment
WriteSaveBuf(buffer, sizeof(CarGeneratorArray));
- for (int i = 0; i < NUM_CARGENS; i++){
- CarGeneratorArray[i].Save(buffer);
- }
+ for (int i = 0; i < NUM_CARGENS; i++)
+ WriteSaveBuf(buffer, CarGeneratorArray[i]);
VALIDATESAVEBUF(*size)
}
void CTheCarGenerators::LoadAllCarGenerators(uint8* buffer, uint32 size)
{
+ const int32 nGeneralDataSize = sizeof(NumOfCarGenerators) + sizeof(CurrentActiveCount) + sizeof(ProcessCounter) + sizeof(GenerateEvenIfPlayerIsCloseCounter) + sizeof(int16);
Init();
INITSAVEBUF
- assert(size == 20 + sizeof(CarGeneratorArray) + SAVE_HEADER_SIZE);
CheckSaveHeader(buffer, 'C','G','N','\0', size - SAVE_HEADER_SIZE);
- ReadSaveBuf<uint32>(buffer);
+ assert(ReadSaveBuf<uint32>(buffer) == nGeneralDataSize);
NumOfCarGenerators = ReadSaveBuf<uint32>(buffer);
CurrentActiveCount = ReadSaveBuf<uint32>(buffer);
ProcessCounter = ReadSaveBuf<uint8>(buffer);
GenerateEvenIfPlayerIsCloseCounter = ReadSaveBuf<uint8>(buffer);
- ReadSaveBuf<int16>(buffer);
+ ReadSaveBuf<int16>(buffer); // alignment
assert(ReadSaveBuf<uint32>(buffer) == sizeof(CarGeneratorArray));
- for (int i = 0; i < NUM_CARGENS; i++) {
- CarGeneratorArray[i].Load(buffer);
- }
+ for (int i = 0; i < NUM_CARGENS; i++)
+ CarGeneratorArray[i] = ReadSaveBuf<CCarGenerator>(buffer);
VALIDATESAVEBUF(size)
}
diff --git a/src/control/CarGen.h b/src/vehicles/CarGen.h
index 75acdd56..9d645318 100644
--- a/src/control/CarGen.h
+++ b/src/vehicles/CarGen.h
@@ -34,19 +34,17 @@ public:
void Setup(float x, float y, float z, float angle, int32 mi, int16 color1, int16 color2, uint8 force, uint8 alarm, uint8 lock, uint16 min_delay, uint16 max_delay);
bool CheckForBlockage();
bool CheckIfWithinRangeOfAnyPlayer();
- void Save(uint8*&);
- void Load(uint8*&);
void SetUsesRemaining(uint16 uses) { m_nUsesRemaining = uses; }
};
class CTheCarGenerators
{
public:
- static uint8 &ProcessCounter;
- static uint32 &NumOfCarGenerators;
- static CCarGenerator (&CarGeneratorArray)[NUM_CARGENS];
- static uint8 &GenerateEvenIfPlayerIsCloseCounter;
- static uint32 &CurrentActiveCount;
+ static uint8 ProcessCounter;
+ static uint32 NumOfCarGenerators;
+ static CCarGenerator CarGeneratorArray[NUM_CARGENS];
+ static uint8 GenerateEvenIfPlayerIsCloseCounter;
+ static uint32 CurrentActiveCount;
static void Process();
static int32 CreateCarGenerator(float x, float y, float z, float angle, int32 mi, int16 color1, int16 color2, uint8 force, uint8 alarm, uint8 lock, uint16 min_delay, uint16 max_delay);
diff --git a/src/control/Cranes.cpp b/src/vehicles/Cranes.cpp
index 33385dae..dbc3c340 100644
--- a/src/control/Cranes.cpp
+++ b/src/vehicles/Cranes.cpp
@@ -38,9 +38,9 @@
uint32 TimerForCamInterpolation;
-uint32& CCranes::CarsCollectedMilitaryCrane = *(uint32*)0x8F6248;
-int32& CCranes::NumCranes = *(int32*)0x8E28AC;
-CCrane(&CCranes::aCranes)[NUM_CRANES] = *(CCrane(*)[NUM_CRANES])*(uintptr*)0x6FA4E0;
+uint32 CCranes::CarsCollectedMilitaryCrane;
+int32 CCranes::NumCranes;
+CCrane CCranes::aCranes[NUM_CRANES];
void CCranes::InitCranes(void)
{
@@ -466,13 +466,13 @@ bool CCrane::DoesCranePickUpThisCarType(uint32 mi)
bool CCranes::DoesMilitaryCraneHaveThisOneAlready(uint32 mi)
{
switch (mi) {
- case MI_FIRETRUCK: return (CCranes::CarsCollectedMilitaryCrane & 1);
- case MI_AMBULAN: return (CCranes::CarsCollectedMilitaryCrane & 2);
- case MI_ENFORCER: return (CCranes::CarsCollectedMilitaryCrane & 4);
- case MI_FBICAR: return (CCranes::CarsCollectedMilitaryCrane & 8);
- case MI_RHINO: return (CCranes::CarsCollectedMilitaryCrane & 0x10);
- case MI_BARRACKS: return (CCranes::CarsCollectedMilitaryCrane & 0x20);
- case MI_POLICE: return (CCranes::CarsCollectedMilitaryCrane & 0x40);
+ case MI_FIRETRUCK: return (CarsCollectedMilitaryCrane & 1);
+ case MI_AMBULAN: return (CarsCollectedMilitaryCrane & 2);
+ case MI_ENFORCER: return (CarsCollectedMilitaryCrane & 4);
+ case MI_FBICAR: return (CarsCollectedMilitaryCrane & 8);
+ case MI_RHINO: return (CarsCollectedMilitaryCrane & 0x10);
+ case MI_BARRACKS: return (CarsCollectedMilitaryCrane & 0x20);
+ case MI_POLICE: return (CarsCollectedMilitaryCrane & 0x40);
default: break;
}
return false;
@@ -481,20 +481,20 @@ bool CCranes::DoesMilitaryCraneHaveThisOneAlready(uint32 mi)
void CCranes::RegisterCarForMilitaryCrane(uint32 mi)
{
switch (mi) {
- case MI_FIRETRUCK: CCranes::CarsCollectedMilitaryCrane |= 1; break;
- case MI_AMBULAN: CCranes::CarsCollectedMilitaryCrane |= 2; break;
- case MI_ENFORCER: CCranes::CarsCollectedMilitaryCrane |= 4; break;
- case MI_FBICAR: CCranes::CarsCollectedMilitaryCrane |= 8; break;
- case MI_RHINO: CCranes::CarsCollectedMilitaryCrane |= 0x10; break;
- case MI_BARRACKS: CCranes::CarsCollectedMilitaryCrane |= 0x20; break;
- case MI_POLICE: CCranes::CarsCollectedMilitaryCrane |= 0x40; break;
+ case MI_FIRETRUCK: CarsCollectedMilitaryCrane |= 1; break;
+ case MI_AMBULAN: CarsCollectedMilitaryCrane |= 2; break;
+ case MI_ENFORCER: CarsCollectedMilitaryCrane |= 4; break;
+ case MI_FBICAR: CarsCollectedMilitaryCrane |= 8; break;
+ case MI_RHINO: CarsCollectedMilitaryCrane |= 0x10; break;
+ case MI_BARRACKS: CarsCollectedMilitaryCrane |= 0x20; break;
+ case MI_POLICE: CarsCollectedMilitaryCrane |= 0x40; break;
default: break;
}
}
bool CCranes::HaveAllCarsBeenCollectedByMilitaryCrane()
{
- return (CCranes::CarsCollectedMilitaryCrane & 0x7F) == 0x7F;
+ return (CarsCollectedMilitaryCrane & 0x7F) == 0x7F;
}
bool CCrane::GoTowardsTarget(float fAngleToTarget, float fDistanceToTarget, float fTargetHeight, float fSpeedMultiplier)
@@ -509,8 +509,7 @@ bool CCrane::GoTowardsTarget(float fAngleToTarget, float fDistanceToTarget, floa
if (Abs(fHookAngleDelta) < fHookAngleChangeThisFrame) {
m_fHookAngle = fAngleToTarget;
bAngleMovementFinished = true;
- }
- else {
+ } else {
if (fHookAngleDelta < 0.0f) {
m_fHookAngle -= fHookAngleChangeThisFrame;
if (m_fHookAngle < 0.0f)
@@ -528,8 +527,7 @@ bool CCrane::GoTowardsTarget(float fAngleToTarget, float fDistanceToTarget, floa
if (Abs(fHookOffsetDelta) < fHookOffsetChangeThisFrame) {
m_fHookOffset = fDistanceToTarget;
bOffsetMovementFinished = true;
- }
- else {
+ } else {
if (fHookOffsetDelta < 0.0f)
m_fHookOffset -= fHookOffsetChangeThisFrame;
else
@@ -541,8 +539,7 @@ bool CCrane::GoTowardsTarget(float fAngleToTarget, float fDistanceToTarget, floa
if (Abs(fHookHeightDelta) < fHookHeightChangeThisFrame) {
m_fHookHeight = fTargetHeight;
bHeightMovementFinished = true;
- }
- else {
+ } else {
if (fHookHeightDelta < 0.0f)
m_fHookHeight -= fHookHeightChangeThisFrame;
else
@@ -560,8 +557,7 @@ bool CCrane::GoTowardsHeightTarget(float fTargetHeight, float fSpeedMultiplier)
if (Abs(fHookHeightDelta) < fHookHeightChangeThisFrame) {
m_fHookHeight = fTargetHeight;
bHeightMovementFinished = true;
- }
- else {
+ } else {
if (fHookHeightDelta < 0.0f)
m_fHookHeight -= fHookHeightChangeThisFrame;
else
@@ -587,7 +583,7 @@ void CCrane::CalcHookCoordinates(float* pX, float* pY, float* pZ)
void CCrane::SetHookMatrix()
{
- if (!m_pHook)
+ if (m_pHook == nil)
return;
m_pHook->GetPosition() = m_vecHookCurPos;
CVector up(m_vecHookInitPos.x - m_vecHookCurPos.x, m_vecHookInitPos.y - m_vecHookCurPos.y, 20.0f);
@@ -632,48 +628,44 @@ void CCranes::Save(uint8* buf, uint32* size)
{
INITSAVEBUF
- *size = 2 * sizeof(uint32) + NUM_CRANES * sizeof(CCrane);
+ *size = 2 * sizeof(uint32) + sizeof(aCranes);
WriteSaveBuf(buf, NumCranes);
WriteSaveBuf(buf, CarsCollectedMilitaryCrane);
for (int i = 0; i < NUM_CRANES; i++) {
- CCrane* pCrane = WriteSaveBuf(buf, aCranes[i]);
- if (pCrane->m_pCraneEntity)
- pCrane->m_pCraneEntity = (CBuilding*)(CPools::GetBuildingPool()->GetJustIndex((CBuilding*)pCrane->m_pCraneEntity) + 1);
- if (pCrane->m_pHook)
- pCrane->m_pHook = (CObject*)(CPools::GetObjectPool()->GetJustIndex((CObject*)pCrane->m_pHook) + 1);
- if (pCrane->m_pVehiclePickedUp)
- pCrane->m_pVehiclePickedUp = (CVehicle*)(CPools::GetVehiclePool()->GetJustIndex((CVehicle*)pCrane->m_pVehiclePickedUp) + 1);
+ CCrane *pCrane = WriteSaveBuf(buf, aCranes[i]);
+ if (pCrane->m_pCraneEntity != nil)
+ pCrane->m_pCraneEntity = (CBuilding*)(CPools::GetBuildingPool()->GetJustIndex(pCrane->m_pCraneEntity) + 1);
+ if (pCrane->m_pHook != nil)
+ pCrane->m_pHook = (CObject*)(CPools::GetObjectPool()->GetJustIndex(pCrane->m_pHook) + 1);
+ if (pCrane->m_pVehiclePickedUp != nil)
+ pCrane->m_pVehiclePickedUp = (CVehicle*)(CPools::GetVehiclePool()->GetJustIndex(pCrane->m_pVehiclePickedUp) + 1);
}
VALIDATESAVEBUF(*size);
}
-void CranesLoad(uint8* buf, uint32 size)
+void CCranes::Load(uint8* buf, uint32 size)
{
INITSAVEBUF
- CCranes::NumCranes = ReadSaveBuf<int32>(buf);
- CCranes::CarsCollectedMilitaryCrane = ReadSaveBuf<uint32>(buf);
+ NumCranes = ReadSaveBuf<int32>(buf);
+ CarsCollectedMilitaryCrane = ReadSaveBuf<uint32>(buf);
for (int i = 0; i < NUM_CRANES; i++)
- CCranes::aCranes[i] = ReadSaveBuf<CCrane>(buf);
+ aCranes[i] = ReadSaveBuf<CCrane>(buf);
for (int i = 0; i < NUM_CRANES; i++) {
- CCrane* pCrane = &CCranes::aCranes[i];
- if (pCrane->m_pCraneEntity)
+ CCrane *pCrane = &aCranes[i];
+ if (pCrane->m_pCraneEntity != nil)
pCrane->m_pCraneEntity = CPools::GetBuildingPool()->GetSlot((uint32)pCrane->m_pCraneEntity - 1);
- if (pCrane->m_pHook)
+ if (pCrane->m_pHook != nil)
pCrane->m_pHook = CPools::GetObjectPool()->GetSlot((uint32)pCrane->m_pHook - 1);
- if (pCrane->m_pVehiclePickedUp)
- pCrane->m_pVehiclePickedUp = CPools::GetVehiclePool()->GetSlot((uint32)pCrane->m_pVehiclePickedUp + 1);
+ if (pCrane->m_pVehiclePickedUp != nil)
+ pCrane->m_pVehiclePickedUp = CPools::GetVehiclePool()->GetSlot((uint32)pCrane->m_pVehiclePickedUp - 1);
}
for (int i = 0; i < NUM_CRANES; i++) {
- CCranes::aCranes[i].m_nAudioEntity = DMAudio.CreateEntity(AUDIOTYPE_CRANE, &CCranes::aCranes[i]);
- if (CCranes::aCranes[i].m_nAudioEntity)
- DMAudio.SetEntityStatus(CCranes::aCranes[i].m_nAudioEntity, 1);
+ aCranes[i].m_nAudioEntity = DMAudio.CreateEntity(AUDIOTYPE_CRANE, &aCranes[i]);
+ if (aCranes[i].m_nAudioEntity != 0)
+ DMAudio.SetEntityStatus(aCranes[i].m_nAudioEntity, 1);
}
VALIDATESAVEBUF(size);
}
-
-STARTPATCHES
- InjectHook(0x5454D0, CranesLoad, PATCH_JUMP); // GenericLoad
-ENDPATCHES
diff --git a/src/control/Cranes.h b/src/vehicles/Cranes.h
index d9817282..c0502638 100644
--- a/src/control/Cranes.h
+++ b/src/vehicles/Cranes.h
@@ -89,10 +89,9 @@ public:
static bool IsThisCarBeingCarriedByAnyCrane(CVehicle* pVehicle);
static bool IsThisCarBeingTargettedByAnyCrane(CVehicle* pVehicle);
static void Save(uint8* buf, uint32* size);
+ static void Load(uint8* buf, uint32 size); // on mobile it's CranesLoad outside of the class
- static uint32& CarsCollectedMilitaryCrane;
- static int32& NumCranes;
- static CCrane(&aCranes)[NUM_CRANES];
+ static uint32 CarsCollectedMilitaryCrane;
+ static int32 NumCranes;
+ static CCrane aCranes[NUM_CRANES];
};
-
-void CranesLoad(uint8*, uint32); // is this really outside CCranes?
diff --git a/src/vehicles/Vehicle.h b/src/vehicles/Vehicle.h
index ede9f8fe..f9becda0 100644
--- a/src/vehicles/Vehicle.h
+++ b/src/vehicles/Vehicle.h
@@ -130,7 +130,8 @@ public:
int8 m_nGettingInFlags;
int8 m_nGettingOutFlags;
uint8 m_nNumMaxPassengers;
- char field_1CD[19];
+ char field_1CD[3];
+ float field_1D0[4];
CEntity *m_pCurGroundEntity;
CFire *m_pCarFire;
float m_fSteerAngle;