summaryrefslogtreecommitdiffstats
path: root/src/Streaming.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Streaming.cpp')
-rw-r--r--src/Streaming.cpp275
1 files changed, 275 insertions, 0 deletions
diff --git a/src/Streaming.cpp b/src/Streaming.cpp
index 7d633d90..f75f358a 100644
--- a/src/Streaming.cpp
+++ b/src/Streaming.cpp
@@ -19,6 +19,11 @@
#include "CullZones.h"
#include "Radar.h"
#include "Camera.h"
+#include "Record.h"
+#include "CarCtrl.h"
+#include "Population.h"
+#include "Gangs.h"
+#include "CutsceneMgr.h"
#include "CdStream.h"
#include "Streaming.h"
@@ -47,6 +52,7 @@ int32 &CStreaming::ms_currentPedGrp = *(int32*)0x8F2BBC;
int32 CStreaming::ms_currentPedLoading;
int32 CStreaming::ms_lastCullZone;
uint16 &CStreaming::ms_loadedGangs = *(uint16*)0x95CC60;
+uint16 &CStreaming::ms_loadedGangCars = *(uint16*)0x95CC2E;
int32 *CStreaming::ms_imageOffsets = (int32*)0x6E60A0;
int32 &CStreaming::ms_lastImageRead = *(int32*)0x880E2C;
int32 &CStreaming::ms_imageSize = *(int32*)0x8F1A34;
@@ -241,6 +247,53 @@ CStreaming::Shutdown(void)
}
void
+CStreaming::Update(void)
+{
+ CEntity *train;
+ CVector playerPos;
+ CStreamingInfo *si, *prev;
+ bool requestedSubway = false;
+
+ UpdateMemoryUsed();
+
+ if(ms_channelError != -1){
+ RetryLoadFile(ms_channelError);
+ return;
+ }
+
+ if(CTimer::GetIsPaused())
+ return;
+
+ train = FindPlayerTrain();
+ if(train && train->GetPosition().z < 0.0f){
+ RequestSubway();
+ requestedSubway = true;
+ }else if(!ms_disableStreaming)
+ AddModelsToRequestList(TheCamera.GetPosition());
+
+ DeleteFarAwayRwObjects(TheCamera.GetPosition());
+
+ if(!ms_disableStreaming &&
+ !CCutsceneMgr::IsRunning() &&
+ !requestedSubway &&
+ !CGame::playingIntro &&
+ ms_numModelsRequested < 5 &&
+ !CRenderer::m_loadingPriority){
+ StreamVehiclesAndPeds();
+ FindPlayerCoors(playerPos);
+ StreamZoneModels(playerPos);
+ }
+
+ LoadRequestedModels();
+
+ for(si = ms_endRequestedList.m_prev; si != &ms_startRequestedList; si = prev){
+ prev = si->m_prev;
+ if((si->m_flags & (STREAMFLAGS_KEEP_IN_MEMORY|STREAMFLAGS_PRIORITY)) == 0)
+ RemoveModel(si - ms_aInfoForModel);
+ }
+}
+
+void
CStreaming::LoadCdDirectory(void)
{
char dirname[132];
@@ -705,6 +758,18 @@ CStreaming::RequestSpecialChar(int32 charId, const char *modelName, int32 flags)
RequestSpecialModel(charId + MI_SPECIAL01, modelName, flags);
}
+bool
+CStreaming::HasSpecialCharLoaded(int32 id)
+{
+ return HasModelLoaded(id + MI_SPECIAL01);
+}
+
+void
+CStreaming::SetMissionDoesntRequireSpecialChar(int32 id)
+{
+ return SetMissionDoesntRequireModel(id + MI_SPECIAL01);
+}
+
void
CStreaming::DecrementRef(int32 id)
{
@@ -1176,6 +1241,181 @@ CStreaming::LoadInitialVehicles(void)
RequestModel(id, STREAMFLAGS_DONT_REMOVE);
}
+void
+CStreaming::StreamVehiclesAndPeds(void)
+{
+ int i, model;
+ static int timeBeforeNextLoad = 0;
+ static int modelQualityClass = 0;
+
+ if(CRecordDataForGame::RecordingState == RECORDSTATE_1 ||
+ CRecordDataForGame::RecordingState == RECORDSTATE_2)
+ return;
+
+ if(FindPlayerPed()->m_pWanted->AreSwatRequired()){
+ RequestModel(MI_ENFORCER, STREAMFLAGS_DONT_REMOVE);
+ RequestModel(MI_SWAT, STREAMFLAGS_DONT_REMOVE);
+ }else{
+ SetModelIsDeletable(MI_ENFORCER);
+ if(!HasModelLoaded(MI_ENFORCER))
+ SetModelIsDeletable(MI_SWAT);
+ }
+
+ if(FindPlayerPed()->m_pWanted->AreFbiRequired()){
+ RequestModel(MI_FBICAR, STREAMFLAGS_DONT_REMOVE);
+ RequestModel(MI_FBI, STREAMFLAGS_DONT_REMOVE);
+ }else{
+ SetModelIsDeletable(MI_FBICAR);
+ if(!HasModelLoaded(MI_FBICAR))
+ SetModelIsDeletable(MI_FBI);
+ }
+
+ if(FindPlayerPed()->m_pWanted->AreArmyRequired()){
+ RequestModel(MI_RHINO, STREAMFLAGS_DONT_REMOVE);
+ RequestModel(MI_BARRACKS, STREAMFLAGS_DONT_REMOVE);
+ RequestModel(MI_ARMY, STREAMFLAGS_DONT_REMOVE);
+ }else{
+ SetModelIsDeletable(MI_RHINO);
+ SetModelIsDeletable(MI_BARRACKS);
+ if(!HasModelLoaded(MI_RHINO) && !HasModelLoaded(MI_BARRACKS))
+ SetModelIsDeletable(MI_ARMY);
+ }
+
+ if(FindPlayerPed()->m_pWanted->NumOfHelisRequired() > 0)
+ RequestModel(MI_CHOPPER, STREAMFLAGS_DONT_REMOVE);
+ else
+ SetModelIsDeletable(MI_CHOPPER);
+
+ if(timeBeforeNextLoad >= 0)
+ timeBeforeNextLoad--;
+ else if(ms_numVehiclesLoaded <= desiredNumVehiclesLoaded){
+ for(i = 0; i <= 10; i++){
+ model = CCarCtrl::ChooseCarModel(modelQualityClass);
+ modelQualityClass++;
+ if(modelQualityClass >= NUM_VEHICLE_CLASSES)
+ modelQualityClass = 0;
+
+ // check if we want to load this model
+ if(ms_aInfoForModel[model].m_loadState == STREAMSTATE_NOTLOADED &&
+ ((CVehicleModelInfo*)CModelInfo::GetModelInfo(model))->m_level & (1 << (CGame::currLevel-1)))
+ break;
+ }
+
+ if(i <= 10){
+ RequestModel(model, STREAMFLAGS_DEPENDENCY);
+ timeBeforeNextLoad = 500;
+ }
+ }
+}
+
+void
+CStreaming::StreamZoneModels(const CVector &pos)
+{
+ int i;
+ uint16 gangsToLoad, gangCarsToLoad, bit;
+ CZoneInfo info;
+
+ CTheZones::GetZoneInfoForTimeOfDay(&pos, &info);
+
+ if(info.pedGroup != ms_currentPedGrp){
+
+ // unload pevious group
+ if(ms_currentPedGrp != -1)
+ for(i = 0; i < 8; i++){
+ if(CPopulation::ms_pPedGroups[ms_currentPedGrp].models[i] == -1)
+ break;
+ SetModelIsDeletable(CPopulation::ms_pPedGroups[ms_currentPedGrp].models[i]);
+ SetModelTxdIsDeletable(CPopulation::ms_pPedGroups[ms_currentPedGrp].models[i]);
+ }
+
+ ms_currentPedGrp = info.pedGroup;
+
+ for(i = 0; i < 8; i++){
+ if(CPopulation::ms_pPedGroups[ms_currentPedGrp].models[i] == -1)
+ break;
+ RequestModel(CPopulation::ms_pPedGroups[ms_currentPedGrp].models[i], STREAMFLAGS_DONT_REMOVE);
+ }
+ }
+ RequestModel(MI_MALE01, STREAMFLAGS_DONT_REMOVE);
+
+ gangsToLoad = 0;
+ gangCarsToLoad = 0;
+ if(info.gangDensity[0] != 0) gangsToLoad |= 1<<0;
+ if(info.gangDensity[1] != 0) gangsToLoad |= 1<<1;
+ if(info.gangDensity[2] != 0) gangsToLoad |= 1<<2;
+ if(info.gangDensity[3] != 0) gangsToLoad |= 1<<3;
+ if(info.gangDensity[4] != 0) gangsToLoad |= 1<<4;
+ if(info.gangDensity[5] != 0) gangsToLoad |= 1<<5;
+ if(info.gangDensity[6] != 0) gangsToLoad |= 1<<6;
+ if(info.gangDensity[7] != 0) gangsToLoad |= 1<<7;
+ if(info.gangDensity[8] != 0) gangsToLoad |= 1<<8;
+ if(info.gangThreshold[0] != info.copDensity) gangCarsToLoad |= 1<<0;
+ if(info.gangThreshold[1] != info.gangThreshold[0]) gangCarsToLoad |= 1<<1;
+ if(info.gangThreshold[2] != info.gangThreshold[1]) gangCarsToLoad |= 1<<2;
+ if(info.gangThreshold[3] != info.gangThreshold[2]) gangCarsToLoad |= 1<<3;
+ if(info.gangThreshold[4] != info.gangThreshold[3]) gangCarsToLoad |= 1<<4;
+ if(info.gangThreshold[5] != info.gangThreshold[4]) gangCarsToLoad |= 1<<5;
+ if(info.gangThreshold[6] != info.gangThreshold[5]) gangCarsToLoad |= 1<<6;
+ if(info.gangThreshold[7] != info.gangThreshold[6]) gangCarsToLoad |= 1<<7;
+ if(info.gangThreshold[8] != info.gangThreshold[7]) gangCarsToLoad |= 1<<8;
+
+ if(gangsToLoad == ms_loadedGangs && gangCarsToLoad == ms_loadedGangCars)
+ return;
+
+ // This makes things simpler than the game does it
+ gangsToLoad |= gangCarsToLoad;
+
+ for(i = 0; i < NUM_GANGS; i++){
+ bit = 1<<i;
+
+ if(gangsToLoad & bit && (ms_loadedGangs & bit) == 0){
+ RequestModel(MI_GANG01 + i*2, STREAMFLAGS_DONT_REMOVE);
+ RequestModel(MI_GANG01 + i*2 + 1, STREAMFLAGS_DONT_REMOVE);
+ ms_loadedGangs |= bit;
+ }else if((gangsToLoad & bit) == 0 && ms_loadedGangs & bit){
+ SetModelIsDeletable(MI_GANG01 + i*2);
+ SetModelIsDeletable(MI_GANG01 + i*2 + 1);
+ SetModelTxdIsDeletable(MI_GANG01 + i*2);
+ SetModelTxdIsDeletable(MI_GANG01 + i*2 + 1);
+ ms_loadedGangs &= ~bit;
+ }
+
+ if(gangCarsToLoad & bit && (ms_loadedGangCars & bit) == 0){
+ RequestModel(CGangs::GetGangInfo(i)->m_nVehicleMI, STREAMFLAGS_DONT_REMOVE);
+ }else if((gangCarsToLoad & bit) == 0 && ms_loadedGangCars & bit){
+ SetModelIsDeletable(CGangs::GetGangInfo(i)->m_nVehicleMI);
+ SetModelTxdIsDeletable(CGangs::GetGangInfo(i)->m_nVehicleMI);
+ }
+ }
+ ms_loadedGangCars = gangCarsToLoad;
+}
+
+void
+CStreaming::RemoveCurrentZonesModels(void)
+{
+ int i;
+
+ if(ms_currentPedGrp != -1)
+ for(i = 0; i < 8; i++){
+ if(CPopulation::ms_pPedGroups[ms_currentPedGrp].models[i] == -1)
+ break;
+ if(CPopulation::ms_pPedGroups[ms_currentPedGrp].models[i] != MI_MALE01)
+ SetModelIsDeletable(CPopulation::ms_pPedGroups[ms_currentPedGrp].models[i]);
+ }
+
+ for(i = 0; i < NUM_GANGS; i++){
+ SetModelIsDeletable(MI_GANG01 + i*2);
+ SetModelIsDeletable(MI_GANG01 + i*2 + 1);
+ if(CGangs::GetGangInfo(i)->m_nVehicleMI != -1)
+ SetModelIsDeletable(CGangs::GetGangInfo(i)->m_nVehicleMI);
+ }
+
+ ms_currentPedGrp = -1;
+ ms_loadedGangs = 0;
+ ms_loadedGangCars = 0;
+}
+
+
// Find starting offset of the cdimage we next want to read
// Not useful at all on PC...
@@ -2166,9 +2406,35 @@ CStreaming::LoadScene(const CVector &pos)
debug("End load scene\n");
}
+void
+CStreaming::MemoryCardSave(uint8 *buffer, uint32 *length)
+{
+ int i;
+
+ *length = NUM_DEFAULT_MODELS;
+ for(i = 0; i < NUM_DEFAULT_MODELS; i++)
+ if(ms_aInfoForModel[i].m_loadState == STREAMSTATE_LOADED)
+ buffer[i] = ms_aInfoForModel[i].m_flags;
+ else
+ buffer[i] = 0xFF;
+}
+
+void
+CStreaming::MemoryCardLoad(uint8 *buffer, uint32 length)
+{
+ uint32 i;
+
+ assert(length == NUM_DEFAULT_MODELS);
+ for(i = 0; i < length; i++)
+ if(ms_aInfoForModel[i].m_loadState == STREAMSTATE_LOADED)
+ if(buffer[i] != 0xFF)
+ ms_aInfoForModel[i].m_flags = buffer[i];
+}
+
STARTPATCHES
InjectHook(0x406430, CStreaming::Init, PATCH_JUMP);
InjectHook(0x406C80, CStreaming::Shutdown, PATCH_JUMP);
+ InjectHook(0x4076C0, CStreaming::Update, PATCH_JUMP);
InjectHook(0x406CC0, (void (*)(void))CStreaming::LoadCdDirectory, PATCH_JUMP);
InjectHook(0x406DA0, (void (*)(const char*, int))CStreaming::LoadCdDirectory, PATCH_JUMP);
InjectHook(0x409740, CStreaming::ConvertBufferToObject, PATCH_JUMP);
@@ -2179,6 +2445,9 @@ STARTPATCHES
InjectHook(0x408210, CStreaming::RequestIslands, PATCH_JUMP);
InjectHook(0x40A890, CStreaming::RequestSpecialModel, PATCH_JUMP);
InjectHook(0x40ADA0, CStreaming::RequestSpecialChar, PATCH_JUMP);
+ InjectHook(0x54A5F0, CStreaming::HasModelLoaded, PATCH_JUMP);
+ InjectHook(0x40ADC0, CStreaming::HasSpecialCharLoaded, PATCH_JUMP);
+ InjectHook(0x40ADE0, CStreaming::SetMissionDoesntRequireSpecialChar, PATCH_JUMP);
InjectHook(0x408830, CStreaming::RemoveModel, PATCH_JUMP);
InjectHook(0x4083A0, CStreaming::RemoveUnusedBuildings, PATCH_JUMP);
@@ -2202,6 +2471,9 @@ STARTPATCHES
InjectHook(0x40AA00, CStreaming::LoadInitialPeds, PATCH_JUMP);
InjectHook(0x40ADF0, CStreaming::LoadInitialVehicles, PATCH_JUMP);
+ InjectHook(0x40AE60, CStreaming::StreamVehiclesAndPeds, PATCH_JUMP);
+ InjectHook(0x40AA30, CStreaming::StreamZoneModels, PATCH_JUMP);
+ InjectHook(0x40AD00, CStreaming::RemoveCurrentZonesModels, PATCH_JUMP);
InjectHook(0x409BE0, CStreaming::ProcessLoadingChannel, PATCH_JUMP);
InjectHook(0x40A610, CStreaming::FlushChannels, PATCH_JUMP);
@@ -2228,6 +2500,9 @@ STARTPATCHES
InjectHook(0x409B70, CStreaming::MakeSpaceFor, PATCH_JUMP);
InjectHook(0x40A6D0, CStreaming::LoadScene, PATCH_JUMP);
+ InjectHook(0x40B210, CStreaming::MemoryCardSave, PATCH_JUMP);
+ InjectHook(0x40B250, CStreaming::MemoryCardLoad, PATCH_JUMP);
+
InjectHook(0x4063E0, &CStreamingInfo::GetCdPosnAndSize, PATCH_JUMP);
InjectHook(0x406410, &CStreamingInfo::SetCdPosnAndSize, PATCH_JUMP);
InjectHook(0x4063D0, &CStreamingInfo::GetCdSize, PATCH_JUMP);