3121 lines
95 KiB
C++
3121 lines
95 KiB
C++
// Filename: FileLoader.cpp
|
|
// Creator: Adam Fowler
|
|
// $Author: $
|
|
// $Date: $
|
|
// $Revision: $
|
|
// Description: Class used to load GTA data files
|
|
//
|
|
|
|
// This File
|
|
#include "scene/FileLoader.h"
|
|
|
|
// Rage
|
|
#include "diag/art_channel.h"
|
|
#include "file/default_paths.h"
|
|
#include "file/stream.h"
|
|
#include "grcore/texturedefault.h"
|
|
#include "paging/rscbuilder.h"
|
|
#include "parser/manager.h"
|
|
#include "system/cache.h"
|
|
#include "system/memory.h"
|
|
#include "spatialdata/sphere.h"
|
|
#include "string/stringutil.h"
|
|
|
|
// Framework headers
|
|
#include "fwscene/lod/lodattach.h"
|
|
#include "fwscene/lod/lodtypes.h"
|
|
#include "fwscene/lod/ContainerLod.h"
|
|
#include "fwscene/mapdata/maptypes.h"
|
|
#include "fwscene/stores/drawablestore.h"
|
|
#include "fwscene/stores/fragmentstore.h"
|
|
#include "fwscene/stores/maptypesstore.h"
|
|
#include "fwscene/stores/mapdatastore.h"
|
|
#include "fwscene/stores/staticboundsstore.h"
|
|
#include "fwscene/world/entitydesc.h"
|
|
#include "fwsys/fileexts.h"
|
|
#include "streaming/packfilemanager.h"
|
|
#include "vfx/ptfx/ptfxmanager.h"
|
|
|
|
// Game headers
|
|
#include "control/garages.h"
|
|
#include "control/slownesszones.h"
|
|
#include "core/game.h"
|
|
#include "debug/Debug.h"
|
|
#include "debug/debugscene.h"
|
|
#include "game/modelindices.h"
|
|
#include "game/zones.h"
|
|
#include "modelinfo/Basemodelinfo.h"
|
|
#include "modelinfo/Mlomodelinfo.h"
|
|
#include "ModelInfo/ModelInfo.h"
|
|
#include "ModelInfo/ModelInfo_Factories.h"
|
|
#include "modelinfo/Pedmodelinfo.h"
|
|
#include "modelinfo/timemodelinfo.h"
|
|
#include "modelinfo/Vehiclemodelinfo.h"
|
|
#include "modelinfo/Weaponmodelinfo.h"
|
|
#include "objects/CoverTuning.h"
|
|
#include "objects/DoorTuning.h"
|
|
#include "objects/DummyObject.h"
|
|
#include "objects/object.h"
|
|
#include "pathserver/ExportCollision.h"
|
|
#include "physics/Deformable.h"
|
|
#include "physics/Tunable.h"
|
|
#include "Peds/Action/BrawlingStyle.h"
|
|
#include "Peds/Horse/horseTune.h"
|
|
#include "Peds/Horse/horseComponent.h"
|
|
#include "Peds/HealthConfig.h"
|
|
#include "Peds/NavCapabilities.h"
|
|
#include "Peds/PedCapsule.h"
|
|
#include "Peds/PedComponentSetInfo.h"
|
|
#include "Peds/PedIKSettings.h"
|
|
#include "Peds/TaskData.h"
|
|
#include "peds/pedpopulation.h"
|
|
#include "peds/PlayerSpecialAbility.h"
|
|
#include "peds/popzones.h"
|
|
#include "renderer/Lights/LightSource.h"
|
|
#include "renderer/occlusion.h"
|
|
#include "renderer/renderer.h"
|
|
#include "renderer/water.h"
|
|
#include "renderer/ZoneCull.h"
|
|
#include "scene/AnimatedBuilding.h"
|
|
#include "scene/Building.h"
|
|
#include "scene/datafilemgr.h"
|
|
#include "scene/dlc_channel.h"
|
|
#include "scene/DownloadableTextureManager.h"
|
|
#include "scene/Entity.h"
|
|
#include "scene/entities/compEntity.h"
|
|
#include "scene/ExtraContent.h"
|
|
#include "scene/InstancePriority.h"
|
|
#include "scene/ipl/IplCullBox.h"
|
|
#include "scene/loader/ManagedImapGroup.h"
|
|
#include "scene/loader/mapTypes.h"
|
|
#include "scene/loader/mapdata.h"
|
|
#include "scene/loader/MapData_Buildings.h"
|
|
#include "scene/loader/MapData_Interiors.h"
|
|
#include "scene/loader/MapData_Extensions.h"
|
|
#include "scene/loader/Map_TxdParents.h"
|
|
#include "scene/loader/mapFileMgr.h"
|
|
#include "scene/lod/LodMgr.h"
|
|
#include "scene/MapChange.h"
|
|
#include "scene/playerswitch/PlayerSwitchInterface.h"
|
|
#include "scene/portals/InteriorInst.h"
|
|
#include "scene/scene.h"
|
|
#include "scene/scene_channel.h"
|
|
#include "scene/texLod.h"
|
|
#include "scene/world/gameWorld.h"
|
|
#include "scene/worldpoints.h"
|
|
#include "streaming/CacheLoader.h"
|
|
#include "streaming/streaming.h"
|
|
#include "streaming/streamingengine.h"
|
|
#include "system/FileMgr.h"
|
|
#include "Task/Default/Patrol/PatrolRoutes.h"
|
|
#include "Task/Scenario/ScenarioManager.h"
|
|
#include "Task/Scenario/ScenarioPointManager.h"
|
|
#include "Task/Scenario/TaskScenario.h"
|
|
#include "Task/System/DefaultTaskData.h"
|
|
#include "Task/System/MotionTaskData.h"
|
|
#include "Task/System/TaskTypes.h"
|
|
#include "TimeCycle/TimeCycle.h"
|
|
#include "vehicleAi/pathfind.h"
|
|
#include "vehicles/cargen.h"
|
|
#include "vehicles/handlingmgr.h"
|
|
#include "vehicles/train.h"
|
|
#include "vehicles/vehiclefactory.h"
|
|
#include "vehicles/vehiclepopulation.h"
|
|
#include "Vfx/Misc/Scrollbars.h"
|
|
#include "Vfx/VisualEffects.h"
|
|
#include "weapons/Explosion.h"
|
|
#include "control/gamelogic.h"
|
|
#include "frontend/LoadingScreens.h"
|
|
|
|
#include "fwsys/metadatastore.h"
|
|
#include "fwscene/stores/mapdatastore.h"
|
|
#include "objects/Door.h"
|
|
#include "network/Stats/NetworkStockMarketStats.h"
|
|
|
|
#if RSG_PC
|
|
#include "core/app.h"
|
|
#endif // RSG_PC
|
|
|
|
#if __PS3 && !__FINAL && __DEV && 0
|
|
#include <sn/libsntuner.h>
|
|
#define PROFLOAD_ONLY(x) x
|
|
#else
|
|
#define PROFLOAD_ONLY(x)
|
|
#endif // #if __PS3 && !__FINAL
|
|
|
|
XPARAM(PartialDynArch);
|
|
#if !__FINAL
|
|
XPARAM(ptfxassetoverride);
|
|
#endif
|
|
|
|
SCENE_OPTIMISATIONS()
|
|
|
|
RAGE_DEFINE_CHANNEL(fileloader)
|
|
|
|
#define fileloaderAssert(cond) RAGE_ASSERT(fileloader,cond)
|
|
#define fileloaderAssertf(cond,fmt,...) RAGE_ASSERTF(fileloader,cond,fmt,##__VA_ARGS__)
|
|
#define fileloaderVerifyf(cond,fmt,...) RAGE_VERIFYF(fileloader,cond,fmt,##__VA_ARGS__)
|
|
#define fileloaderErrorf(fmt,...) RAGE_ERRORF(fileloader,fmt,##__VA_ARGS__)
|
|
#define fileloaderWarningf(fmt,...) RAGE_WARNINGF(fileloader,fmt,##__VA_ARGS__)
|
|
#define fileloaderDisplayf(fmt,...) RAGE_DISPLAYF(fileloader,fmt,##__VA_ARGS__)
|
|
#define fileloaderDebugf1(fmt,...) RAGE_DEBUGF1(fileloader,fmt,##__VA_ARGS__)
|
|
#define fileloaderDebugf2(fmt,...) RAGE_DEBUGF2(fileloader,fmt,##__VA_ARGS__)
|
|
#define fileloaderDebugf3(fmt,...) RAGE_DEBUGF3(fileloader,fmt,##__VA_ARGS__)
|
|
#define fileloaderLogf(severity,fmt,...) RAGE_LOGF(fileloader,severity,fmt,##__VA_ARGS__)
|
|
#define fileloaderCondLogf(cond,severity,fmt,...) RAGE_CONDLOGF(cond,fileloader,severity,fmt,##__VA_ARGS__)
|
|
|
|
//PARAM(imposterDivisions,"Number of tree imposter divisons");
|
|
PARAM(fileloader_tty_windows, "Create RAG windows for Fileloader related TTY.");
|
|
|
|
PARAM(override_script, "[FileLoader] Use this file instead of script.rpf. The replacement .rpf has to be in the same folder as the original script.rpf. You don't need to specify the .rpf extension");
|
|
PARAM(override_script_dlc, "[FileLoader] Use this file instead of script_RELEASE.rpf in DLC packs. The replacement .rpf has to be in the same folder as the original script_RELEASE.rpf. You don't need to specify the .rpf extension");
|
|
PARAM(usefatcuts, "[FileLoader] Use the fat cutscenes");
|
|
#if __BANK
|
|
PARAM(fileMountWidgets, "Add Data File Mount widgets to the bank");
|
|
#endif
|
|
|
|
#include "Network\NetworkInterface.h"
|
|
|
|
#define FILELOADER_COMMENT_CHAR '#'
|
|
|
|
// --- Globals ---------------------------------------
|
|
CMapTypes* s_MapTypes = NULL;
|
|
CMloArchetypeDef* s_CurrentMloArchetypeDef = NULL;
|
|
u32 s_CurrentMloObject = 0xffffffff;
|
|
u32 s_CurrentMloPortal = 0xffffffff;
|
|
u32 s_CurrentMloRoom = 0xffffffff;
|
|
|
|
char CFileLoader::ms_line[MAX_LINE_LENGTH];
|
|
atArray<s32> CFileLoader::ms_permItyp;
|
|
bool CFileLoader::ms_requestDLCItypes = false;
|
|
CSettings::eSettingsLevel CFileLoader::ms_ptfxSetting = CSettings::Medium;
|
|
|
|
|
|
CDataFileMgr::DataFileType CFileLoader::ms_validRpfTypesPreInstall[] =
|
|
{
|
|
CDataFileMgr::RPF_FILE_PRE_INSTALL,
|
|
CDataFileMgr::RPF_FILE_PRE_INSTALL_ONLY,
|
|
};
|
|
|
|
CDataFileMgr::DataFileType CFileLoader::ms_validRpfTypes[] =
|
|
{
|
|
CDataFileMgr::RPF_FILE_PRE_INSTALL,
|
|
CDataFileMgr::RPF_FILE,
|
|
CDataFileMgr::PEDSTREAM_FILE
|
|
};
|
|
|
|
#if __DEV
|
|
char CFileLoader::sm_currentFile[RAGE_MAX_PATH];
|
|
static CPedModelInfo::InitDataList s_PedModelInfoInitList;
|
|
#endif
|
|
|
|
namespace
|
|
{
|
|
// This is kind of a hack to get around some compiler problems. If the compiler thinks
|
|
// that nothing in a translation unit (a .cpp) is getting used it can strip out the whole
|
|
// translation unit. In this case since it doesn't think CMapTypes is getting used it strips
|
|
// out all of maptypes.cpp, including the parser autoregistration code in that .cpp which will
|
|
// in fact reference CMapTypes (and therefore everything else in the .cpp).
|
|
bool g_alwaysTrue = true;
|
|
void DummyFactory()
|
|
{
|
|
if (g_alwaysTrue)
|
|
{
|
|
return;
|
|
}
|
|
REGISTER_PARSABLE_CLASS(CMapTypes);
|
|
}
|
|
}
|
|
|
|
class CBrawlingStyleMetaDataFileMounter : public CDataFileMountInterface
|
|
{
|
|
virtual bool LoadDataFile(const CDataFileMgr::DataFile & file)
|
|
{
|
|
dlcDebugf3("CBrawlingStyleMetaDataFileMounter::LoadDataFile: %s type = %d", file.m_filename, file.m_fileType);
|
|
CBrawlingStyleManager::Shutdown();
|
|
CBrawlingStyleManager::Init(file.m_filename);
|
|
return true;
|
|
}
|
|
|
|
virtual void UnloadDataFile(const CDataFileMgr::DataFile & OUTPUT_ONLY(file))
|
|
{
|
|
dlcDebugf3("CBrawlingStyleMetaDataFileMounter::UnloadDataFile %s type = %d", file.m_filename, file.m_fileType);
|
|
CBrawlingStyleManager::Shutdown();
|
|
CBrawlingStyleManager::Init("common:/data/pedbrawlingstyle.meta");
|
|
}
|
|
|
|
} g_BrawlingStyleMetaDataFileMounter;
|
|
|
|
class CWeaponMetaDataFileMounter : public CDataFileMountInterface
|
|
{
|
|
virtual bool LoadDataFile(const CDataFileMgr::DataFile & file)
|
|
{
|
|
CFileLoader::LoadObjectTypesXml(file.m_filename, CDataFileMgr::WEAPON_METADATA_FILE, false, fwFactory::EXTRA);
|
|
return true;
|
|
}
|
|
|
|
virtual void UnloadDataFile(const CDataFileMgr::DataFile & ) {}
|
|
|
|
} g_WeaponMetaDataFileMounter;
|
|
|
|
class CDLCItypFileMounter : public CDataFileMountInterface
|
|
{
|
|
virtual bool LoadDataFile(const CDataFileMgr::DataFile & file)
|
|
{
|
|
CFileLoader::AddDLCItypeFile(file.m_filename);
|
|
return true;
|
|
}
|
|
|
|
virtual void UnloadDataFile(const CDataFileMgr::DataFile & file)
|
|
{
|
|
CFileLoader::RemoveDLCItypeFile(file.m_filename);
|
|
}
|
|
|
|
} g_DLCItypeFileMounter;
|
|
|
|
//
|
|
// name: CFileLoader::InitClass
|
|
// description: Basic initialization of the file loader class.
|
|
//
|
|
void CFileLoader::InitClass()
|
|
{
|
|
CDataFileMount::RegisterMountInterface(CDataFileMgr::PED_BRAWLING_STYLE_FILE, &g_BrawlingStyleMetaDataFileMounter, eDFMI_UnloadFirst);
|
|
CDataFileMount::RegisterMountInterface(CDataFileMgr::WEAPON_METADATA_FILE, &g_WeaponMetaDataFileMounter);
|
|
CDataFileMount::RegisterMountInterface(CDataFileMgr::DLC_ITYP_REQUEST, &g_DLCItypeFileMounter, eDFMI_UnloadLast);
|
|
CInteriorProxy::RegisterMountInterface();
|
|
}
|
|
|
|
bool CFileLoader::IsValidRpfType(const CDataFileMgr::DataFileType &type)
|
|
{
|
|
for(int i=0;i<NELEM(ms_validRpfTypes);i++)
|
|
{
|
|
if(ms_validRpfTypes[i]==type)
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
#if RSG_PC||!__FINAL
|
|
#define FINAL_PCONLY(x) x
|
|
#else
|
|
#define FINAL_PCONLY(x)
|
|
#endif
|
|
bool CFileLoader::CheckFileForReplacements(const char* finalName,char* replacementName,size_t /*bufferSize*/)
|
|
{
|
|
bool isReplaced = false;
|
|
char expandedName[RAGE_MAX_PATH]={0};
|
|
const char *filename = ASSET.FileName(finalName);
|
|
size_t string_length_of_path = filename - finalName;
|
|
bool optionalReplacement = true;
|
|
|
|
// Set this to force using script_rel, useful when you have a disc burned with both types of scripts.
|
|
#define FORCE_SCRIPT_REL __FINAL || 0
|
|
|
|
#if !__FINAL
|
|
const char *overrideScriptRpfName = 0;
|
|
const char *overrideDlcScriptRpfName = 0;
|
|
PARAM_override_script.Get(overrideScriptRpfName);
|
|
PARAM_override_script_dlc.Get(overrideDlcScriptRpfName);
|
|
#endif
|
|
|
|
//Checks for script.rpf filename overrides
|
|
if(stricmp(filename,"script.rpf")==0||stricmp(filename,"script_install.rpf")==0||stricmp(filename,"script_release.rpf")==0)
|
|
{
|
|
#if FORCE_SCRIPT_REL
|
|
// Add 4 below for the length of "_rel" suffix
|
|
if (Verifyf( ( strlen(finalName) + 4) < RAGE_MAX_PATH, "CFileLoader::LoadRpfFiles - path to override script rpf is too long"))
|
|
{
|
|
safecpy(replacementName, finalName, string_length_of_path);
|
|
strcat(replacementName, "/");
|
|
strcat(replacementName, filename);
|
|
ASSET.RemoveExtensionFromPath(replacementName,RAGE_MAX_PATH,replacementName);
|
|
strcat(replacementName, "_rel.rpf");
|
|
isReplaced = true;
|
|
optionalReplacement = false;
|
|
Displayf("Script pack %s being replaced with %s",finalName,replacementName);
|
|
}
|
|
#else
|
|
const char* overrideName = (strnicmp(finalName,"dlc",3)!=0) ? overrideScriptRpfName : overrideDlcScriptRpfName;
|
|
if(overrideName)
|
|
{
|
|
// Add 5 below for the length of ".rpf" and for a forward slash before the filename
|
|
if (Verifyf( (string_length_of_path + strlen(overrideName) + 5) < RAGE_MAX_PATH, "CFileLoader::LoadRpfFiles - path to override script rpf is too long"))
|
|
{
|
|
safecpy(replacementName, finalName, string_length_of_path);
|
|
strcat(replacementName, "/");
|
|
strcat(replacementName, overrideName);
|
|
strcat(replacementName, ".rpf");
|
|
isReplaced = true;
|
|
}
|
|
optionalReplacement = false;
|
|
isReplaced = true;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#if !__FINAL
|
|
|
|
//Check for fatcuts
|
|
else if(PARAM_usefatcuts.Get())
|
|
{
|
|
// Check path is at least as long as cutscene platform path and matches cutscene platform path i.e. platform:/anim/ should not be remappedconst char *cutscene_platform_path = "platform:/anim/cutscene/";
|
|
const char *cutscene_platform_path = "platform:/anim/cutscene/";
|
|
static const size_t string_length_of_cutscene_platform_path = strlen(cutscene_platform_path);
|
|
if (stricmp(filename, "common_cutscene.meta") == 0)
|
|
{
|
|
safecpy(replacementName, finalName, string_length_of_path);
|
|
strcat(replacementName, "/");
|
|
strcat(replacementName, "common_cutscene_fat.meta");
|
|
|
|
isReplaced = true;
|
|
optionalReplacement = false;
|
|
}
|
|
else if (stricmp(filename, "cuts.meta") == 0)
|
|
{
|
|
safecpy(replacementName, finalName, string_length_of_path);
|
|
strcat(replacementName, "/");
|
|
strcat(replacementName, "cuts_fat.meta");
|
|
|
|
isReplaced = true;
|
|
optionalReplacement = false;
|
|
}
|
|
else if (string_length_of_path >= string_length_of_cutscene_platform_path && strnicmp(finalName, cutscene_platform_path, string_length_of_path) == 0)
|
|
{
|
|
char buildPath[RAGE_MAX_PATH];
|
|
safecpy(buildPath, "assets:/non_final/build/dev");
|
|
#ifdef RS_BRANCHSUFFIX
|
|
safecat(buildPath, RS_BRANCHSUFFIX);
|
|
#endif
|
|
safecat(buildPath, "/");
|
|
#if RSG_ORBIS
|
|
// the orbis are in the ps4 specific folder, adding ps4 specific fix, can move to RSG_PLATFORM_ID when that changes to PS4
|
|
safecat(buildPath, RSG_PLATFORM);
|
|
#else
|
|
safecat(buildPath, RSG_PLATFORM_ID);
|
|
#endif
|
|
safecat(buildPath, "/anim/cutscene/");
|
|
safecpy(replacementName, buildPath, RAGE_MAX_PATH);
|
|
|
|
strcat(replacementName, filename);
|
|
|
|
isReplaced = true;
|
|
optionalReplacement = true;
|
|
}
|
|
#if __BANK
|
|
else
|
|
{
|
|
const char * source = stristr(finalName , RSG_PLATFORM_ID"/anim/cutscene/");
|
|
if(source)
|
|
{
|
|
|
|
char buildPath[RAGE_MAX_PATH];
|
|
safecpy(buildPath, "assets:/non_final/build/dev");
|
|
#ifdef RS_BRANCHSUFFIX
|
|
safecat(buildPath, RS_BRANCHSUFFIX);
|
|
#endif
|
|
safecat(buildPath, "/");
|
|
#if RSG_ORBIS
|
|
// the orbis are in the ps4 specific folder, adding ps4 specific fix, can move to RSG_PLATFORM_ID when that changes to PS4
|
|
safecat(buildPath, RSG_PLATFORM);
|
|
#else
|
|
safecat(buildPath, RSG_PLATFORM_ID);
|
|
#endif
|
|
safecat(buildPath, "/anim/cutscene/");
|
|
|
|
safecpy(replacementName, buildPath, RAGE_MAX_PATH);
|
|
|
|
strcat(replacementName, filename);
|
|
|
|
isReplaced = true;
|
|
optionalReplacement = true;
|
|
}
|
|
}
|
|
#endif // __BANK
|
|
}
|
|
#endif
|
|
|
|
//PTFX settings
|
|
if (stricmp(filename, "ptfx.rpf") == 0 )
|
|
{
|
|
#if RSG_PC
|
|
//PC specific
|
|
safecpy(replacementName, finalName, string_length_of_path);
|
|
strcat(replacementName, "/ptfx");
|
|
strcat(replacementName, GetPtfxFileSuffix());
|
|
strcat(replacementName, ".rpf");
|
|
isReplaced = true;
|
|
#endif // __RSG_PC
|
|
|
|
#if !__FINAL
|
|
//Check for ptfx debug overrides
|
|
if (PARAM_ptfxassetoverride.Get())
|
|
{
|
|
const char* pPtfxAssetOverride = NULL;
|
|
PARAM_ptfxassetoverride.Get(pPtfxAssetOverride);
|
|
|
|
safecpy(replacementName, finalName, string_length_of_path);
|
|
strcat(replacementName, "/ptfx");
|
|
strcat(replacementName, pPtfxAssetOverride);
|
|
strcat(replacementName, ".rpf");
|
|
isReplaced = true;
|
|
optionalReplacement = true;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
DATAFILEMGR.ExpandFilename(replacementName,expandedName,RAGE_MAX_PATH);
|
|
if(isReplaced)
|
|
{
|
|
if(ASSET.Exists(expandedName,""))
|
|
{
|
|
Displayf("Found replacement for %s New file: %s",finalName,replacementName);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
Warningf("Couldn't find %s, falling back to the default version %s",replacementName,finalName);
|
|
Assertf(optionalReplacement,"Tried to replace %s, but we couldn't find the replacement file: %s",finalName,replacementName);
|
|
return false;
|
|
}
|
|
}
|
|
return isReplaced;
|
|
}
|
|
|
|
|
|
//
|
|
// name: CFileLoader::LoadLine
|
|
// description: Load line from ASCII file and clear out all crap (commas etc)
|
|
// in: fid = file handle
|
|
// out: pointer to start of text in line
|
|
//
|
|
char* CFileLoader::LoadLine(FileHandle fid)
|
|
{
|
|
s32 linePosn = 0;
|
|
char *pLineStart = &ms_line[0];
|
|
|
|
if(!CFileMgr::ReadLine(fid, &ms_line[0], MAX_LINE_LENGTH))
|
|
return NULL;
|
|
|
|
// first, strip out all commas and escape sequence chars, and replace them with spaces
|
|
while (ms_line[linePosn] != '\0')
|
|
{
|
|
if (ms_line[linePosn] < ' ' || ms_line[linePosn] == ',')
|
|
{
|
|
ms_line[linePosn] = ' ';
|
|
}
|
|
linePosn++;
|
|
}
|
|
|
|
// get beginning of line first non-space/non-control character
|
|
while(*pLineStart <= ' ' && *pLineStart != '\0')
|
|
pLineStart++;
|
|
|
|
//!XBOX - for some reason lines are picking up trailing spaces in xbox version. Need removed.
|
|
#if defined (GTA_XBOX)
|
|
if (ms_line[linePosn-1] == ' ')
|
|
{
|
|
ms_line[linePosn-1] = '\0';
|
|
}
|
|
#endif //GTA_XBOX
|
|
|
|
return pLineStart;
|
|
}
|
|
|
|
//
|
|
// name: CFileLoader::LoadLine
|
|
// description: Load line from ASCII file and clear out all crap (commas etc)
|
|
// in: fid = file handle
|
|
// out: pointer to start of text in line
|
|
//
|
|
char* CFileLoader::LoadLine(u8** ppData, s32& size)
|
|
{
|
|
static char gLine[512];
|
|
char *pLineStart = &gLine[0];
|
|
u8* pData = *ppData;
|
|
|
|
if(size <= 0 || *pData == '\0')
|
|
return NULL;
|
|
|
|
// copy line striping out commas and escape sequence chars by replacing them
|
|
// with spaces
|
|
while(size-- && *pData != '\n' && *pData != '\0')
|
|
{
|
|
if(*pData < ' ' || *pData == ',')
|
|
*pLineStart = ' ';
|
|
else
|
|
*pLineStart = *pData;
|
|
|
|
pLineStart++;
|
|
pData++;
|
|
//size--; // moved to while to make sure carriage returns are counted as taken off of data as well.
|
|
}
|
|
|
|
pData++;
|
|
*ppData = pData;
|
|
|
|
// end line
|
|
|
|
*pLineStart = '\0';
|
|
pLineStart = &gLine[0];
|
|
|
|
// get beginning of line first non-space/non-control character
|
|
while(*pLineStart <= ' ' && *pLineStart != '\0')
|
|
pLineStart++;
|
|
|
|
return pLineStart;
|
|
}
|
|
|
|
s32 CFileLoader::AddRpfFile(const CDataFileMgr::DataFile *pData, bool registerFiles)
|
|
{
|
|
strLocalIndex imageIndex = strLocalIndex(-1);
|
|
|
|
s32 cachePartition = -1; // This used to be read from gta5.dat as a number after the filename
|
|
const char *finalName = pData->m_filename;
|
|
|
|
while (true)
|
|
{
|
|
strStreamingEngine::GetLoader().CallKeepAliveCallbackIfNecessary();
|
|
#if (__XENON || __PS3)
|
|
// don't attempt to completely load meta data on last gen platforms - there isn't enough memory to do it.
|
|
imageIndex = strPackfileManager::AddImageToList(finalName, true, cachePartition, pData->m_locked, (u8) pData->m_contents, false, pData->m_overlay);
|
|
#else //(__XENON || __PS3)
|
|
imageIndex = strPackfileManager::AddImageToList(finalName, true, cachePartition, pData->m_locked, (u8) pData->m_contents, pData->m_loadCompletely, pData->m_overlay, pData->m_patchFile);
|
|
#endif //(__XENON || __PS3)
|
|
|
|
if (imageIndex != -1)
|
|
{
|
|
#if __DEV
|
|
strPackfileManager::SetEnforceLsnSorting(imageIndex.Get(), pData->m_enforceLsnSorting);
|
|
#endif // __DEV
|
|
|
|
if (registerFiles)
|
|
{
|
|
bool wasUnloaded = strPackfileManager::GetStreamingModule()->GetStreamingInfo(imageIndex)->GetStatus() == STRINFO_NOTLOADED;
|
|
|
|
strPackfileManager::LoadImageIfUnloaded(imageIndex.Get(), false);
|
|
// If it was not loaded before, keep it that way.
|
|
if (wasUnloaded)
|
|
{
|
|
strPackfileManager::UnloadRpf(imageIndex.Get());
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
{
|
|
#if RSG_PC || !__NO_OUTPUT
|
|
const char *source = "?";
|
|
#endif // RSG_PC || !__NO_OUTPUT
|
|
|
|
#if !__FINAL
|
|
source = pData->m_Source.GetCStr();
|
|
#endif // !__FINAL
|
|
Quitf(ERR_SYS_FILELOAD,"RPF file '%s' is missing. a) Make sure you have it locally, get it from Perforce if necessary. Maybe you're using a label that doesn't have this file. b) The file is referenced by '%s', maybe it shouldn't be.",
|
|
finalName, source);
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
return imageIndex.Get();
|
|
}
|
|
void CFileLoader::ChangeSetAction_LoadRPF( CDataFileMgr::DataFile* pData )
|
|
{
|
|
// If it's not already enabled, enable and load it.
|
|
if (pData->m_disabled)
|
|
{
|
|
fileloaderDebugf1("ChangeSetAction_LoadRPF: Enabling RPF file %s", pData->m_filename);
|
|
|
|
pData->m_disabled = false;
|
|
s32 archiveIndex = AddRpfFile(pData, true);
|
|
|
|
// When loading map changes make sure we re-validate hierarchies
|
|
if (EXTRACONTENT.GetMapChangeState() == MCS_UPDATE)
|
|
strStreamingEngine::GetInfo().ModifyHierarchyStatusForArchive(archiveIndex, HMT_ENABLE);
|
|
|
|
if (archiveIndex != -1 && pData->m_locked)
|
|
{
|
|
// Normally, user-locked RPFs get their ref count incremented by OpenImageList, which
|
|
// is not getting called in this case.
|
|
strPackfileManager::AddStreamableReference(archiveIndex);
|
|
|
|
// Re-enable this archive again.
|
|
strPackfileManager::SetEnabled(archiveIndex, true);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fileloaderDebugf1("ChangeSetAction_LoadRPF: RPF file %s was already enabled", pData->m_filename);
|
|
}
|
|
}
|
|
|
|
void CFileLoader::ChangeSetAction_UnloadRPF(CDataFileMgr::DataFile* pData)
|
|
{
|
|
// If it's not already disabled, unload and disable it.
|
|
if (!pData->m_disabled)
|
|
{
|
|
char filename[RAGE_MAX_PATH];
|
|
ASSET.FullPath(filename, sizeof(filename), pData->m_filename, "");
|
|
|
|
fileloaderDebugf1("ChangeSetAction_UnloadRPF: Disabling RPF file %s", filename);
|
|
|
|
strLocalIndex archiveIndex = strLocalIndex(strPackfileManager::FindImage(filename));
|
|
|
|
if (Verifyf(archiveIndex != -1, "RPF file '%s' has never been registered - are we calling DisableAllRpfsByContent() before AddAllRpfFiles()?", filename))
|
|
{
|
|
// Remove the user lock, if there is one.
|
|
strPackfileManager::RemoveUserLock(archiveIndex.Get());
|
|
|
|
// When unloading map changes make sure we invalidate hierarchies
|
|
if (EXTRACONTENT.GetMapChangeState() == MCS_UPDATE)
|
|
{
|
|
eHierarchyModType modType = HMT_DISABLE;
|
|
|
|
if (pData->m_overlay)
|
|
modType = HMT_FLUSH;
|
|
|
|
// Attempt to stream out any files in this archive before we invalidate it, hopefully meaning it won't be in use.
|
|
strStreamingEngine::GetInfo().ModifyHierarchyStatusForArchive(archiveIndex.Get(), modType);
|
|
}
|
|
|
|
// We're planning on killing all streamables using this archive, so we have to invalidate their handles.
|
|
// TODO: Consider passing "true" here - that way, we free up the strStreamingInfos. But let's wait with that at least
|
|
// until we have paged pools enabled.
|
|
strStreamingEngine::GetInfo().InvalidateFilesForArchive(archiveIndex.Get(), false);
|
|
|
|
// Now try to unload the RPF file. We're assuming that there are no dependencies
|
|
// on this RPF - if the user calls this function while this RPF is needed,
|
|
// the function we're calling here will assert.
|
|
strPackfileManager::CloseArchive(archiveIndex.Get());
|
|
|
|
// Don't open this archive again.
|
|
strPackfileManager::SetEnabled(archiveIndex.Get(), false);
|
|
}
|
|
|
|
pData->m_disabled = true;
|
|
}
|
|
else
|
|
{
|
|
fileloaderDebugf1("ChangeSetAction_UnloadRPF: RPF file %s was already disable", pData->m_filename);
|
|
}
|
|
}
|
|
void CFileLoader::ChangeSetAction_LoadTxd(const atHashString * txd)
|
|
{
|
|
strLocalIndex index = strLocalIndex(g_TxdStore.FindSlotFromHashKey(*txd));
|
|
|
|
if (Verifyf(index != -1, "Unable to find TXD '%s' that we're meant to load", txd->TryGetCStr()))
|
|
{
|
|
fileloaderDebugf1("ChangeSetAction_LoadTxd: Loading TXD %s", g_TxdStore.GetName(index));
|
|
|
|
strIndex stIndex = g_TxdStore.GetStreamingIndex(index);
|
|
strStreamingEngine::GetInfo().RequestObject(stIndex, STRFLAG_FORCE_LOAD);
|
|
}
|
|
}
|
|
|
|
void CFileLoader::ChangeSetAction_UnloadTxd(const atHashString * txd)
|
|
{
|
|
strLocalIndex index = strLocalIndex(g_TxdStore.FindSlotFromHashKey(*txd));
|
|
|
|
if (Verifyf(index != -1, "Unable to find TXD '%s' that we're meant to unload", txd->TryGetCStr()))
|
|
{
|
|
fileloaderDebugf1("ChangeSetAction_UnloadTxd: Unloading TXD %s", g_TxdStore.GetName(index));
|
|
|
|
g_TxdStore.RemoveRef(index, REF_OTHER);
|
|
int refCnt = g_TxdStore.GetNumRefs(index);
|
|
|
|
if (Verifyf(refCnt == 0, "TXD '%s' that we're meant to unload still has ref count %d", txd->TryGetCStr(), refCnt))
|
|
{
|
|
strIndex stIndex = g_TxdStore.GetStreamingIndex(index);
|
|
strStreamingEngine::GetInfo().RemoveObject(stIndex);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void CFileLoader::ChangeSetAction_LoadResidentResource(const CDataFileMgr::ResourceReference * ref)
|
|
{
|
|
strIndex index = ref->Resolve();
|
|
|
|
if (index.IsValid())
|
|
{
|
|
fileloaderDebugf1("ChangeSetAction_LoadResidentResource: Loading file %s", strStreamingEngine::GetObjectName(index));
|
|
strStreamingEngine::GetInfo().RequestObject(index, STRFLAG_DONTDELETE);
|
|
}
|
|
}
|
|
|
|
void CFileLoader::ChangeSetAction_UnloadResidentResource(const CDataFileMgr::ResourceReference * ref)
|
|
{
|
|
strIndex index = ref->Resolve();
|
|
|
|
if (index.IsValid())
|
|
{
|
|
fileloaderDebugf1("ChangeSetAction_UnloadResidentResource: removing file %s", strStreamingEngine::GetObjectName(index));
|
|
strStreamingEngine::GetInfo().SetObjectIsDeletable(index);
|
|
strStreamingEngine::GetInfo().RemoveObject(index);
|
|
}
|
|
}
|
|
|
|
void CFileLoader::ChangeSetAction_UnregisterResource(const CDataFileMgr::ResourceReference * ref)
|
|
{
|
|
strIndex index = ref->Resolve();
|
|
|
|
if (index.IsValid())
|
|
{
|
|
fileloaderDebugf1("ChangeSetAction_UnregisterResource: unregistering file %s", strStreamingEngine::GetObjectName(index));
|
|
|
|
#if __ASSERT
|
|
strStreamingInfo &info = strStreamingEngine::GetInfo().GetStreamingInfoRef(index);
|
|
Assertf(info.GetStatus() == STRINFO_NOTLOADED, "Trying to unregister %s, but it's still %s", strStreamingEngine::GetObjectName(index), info.GetFriendlyStatusName());
|
|
#endif // __ASSERT
|
|
|
|
strStreamingModule *module = strStreamingEngine::GetInfo().GetModule(index);
|
|
strLocalIndex objIndex = module->GetObjectIndex(index);
|
|
|
|
module->RemoveSlot(objIndex);
|
|
}
|
|
}
|
|
|
|
void CFileLoader::ChangeSetAction_ModifyFileValidity(s32 archiveIndex, bool invalid)
|
|
{
|
|
if (Verifyf(archiveIndex != -1, "ChangeSetAction_ModifyFileValidity: RPF file has never been registered!"))
|
|
{
|
|
if ( strPackfileManager::GetImageFile(archiveIndex) )
|
|
{
|
|
fileloaderDebugf1("ChangeSetAction_ModifyFileValidity: Invalidating RPF file %s", strPackfileManager::GetImageFile(archiveIndex)->m_name.GetCStr());
|
|
|
|
strStreamingEngine::GetInfo().ModifyHierarchyStatusForArchive(archiveIndex, invalid ? HMT_DISABLE : HMT_ENABLE);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CFileLoader::ExecuteChangeSetAction(const CDataFileMgr::ChangeSetAction &action)
|
|
{
|
|
strStreamingEngine::GetLoader().CallKeepAliveCallbackIfNecessary();
|
|
|
|
switch (action.m_actionType)
|
|
{
|
|
case CDataFileMgr::ChangeSetAction::CHANGE_SET_ACTION_INVALIDATE_FILE:
|
|
{
|
|
ChangeSetAction_ModifyFileValidity(action.archiveIndex, action.m_add);
|
|
}
|
|
break;
|
|
|
|
case CDataFileMgr::ChangeSetAction::CHANGE_SET_ACTION_INVALIDATE_INTERIOR:
|
|
{
|
|
if (CInteriorProxy* pProxy = CInteriorProxy::FindProxy(action.archiveIndex))
|
|
{
|
|
pProxy->SetIsDisabledDLC(action.m_add);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case CDataFileMgr::ChangeSetAction::CHANGE_SET_ACTION_INVALIDATE_STREAMABLE:
|
|
{
|
|
if (action.m_strIndex.IsValid())
|
|
{
|
|
strStreamingEngine::GetInfo().RemoveObjectAndDependents(action.m_strIndex, action.m_add ? HMT_DISABLE : HMT_ENABLE);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case CDataFileMgr::ChangeSetAction::CHANGE_SET_ACTION_RPF:
|
|
{
|
|
if (action.m_add)
|
|
{
|
|
fileloaderDebugf1("ChangeSetAction_LoadRPF %s", action.m_file->m_filename);
|
|
ChangeSetAction_LoadRPF(action.m_file);
|
|
}
|
|
else
|
|
{
|
|
fileloaderDebugf1("ChangeSetAction_UnloadRPF %s", action.m_file->m_filename);
|
|
ChangeSetAction_UnloadRPF(action.m_file);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case CDataFileMgr::ChangeSetAction::CHANGE_SET_ACTION_DATA_FILE:
|
|
{
|
|
bool skipDisable = IsValidRpfType(action.m_file->m_fileType);
|
|
if (action.m_add)
|
|
{
|
|
fileloaderDebugf1("ChangeSetAction:Loading data file %s", action.m_file->m_filename);
|
|
action.m_file->m_disabled = !skipDisable ? false : action.m_file->m_disabled;
|
|
CDataFileMount::LoadFile(*action.m_file);
|
|
}
|
|
else
|
|
{
|
|
fileloaderDebugf1("ChangeSetAction:Unloading data file %s", action.m_file->m_filename);
|
|
action.m_file->m_disabled = !skipDisable ? true : action.m_file->m_disabled;
|
|
CDataFileMount::UnloadFile(*action.m_file);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case CDataFileMgr::ChangeSetAction::CHANGE_SET_ACTION_TXD:
|
|
{
|
|
if (action.m_add)
|
|
ChangeSetAction_LoadTxd(action.m_txd);
|
|
else
|
|
ChangeSetAction_UnloadTxd(action.m_txd);
|
|
}
|
|
break;
|
|
|
|
case CDataFileMgr::ChangeSetAction::CHANGE_SET_ACTION_RESIDENT_RESOURCE:
|
|
{
|
|
if (action.m_add)
|
|
ChangeSetAction_LoadResidentResource(action.m_residentResource);
|
|
else
|
|
ChangeSetAction_UnloadResidentResource(action.m_residentResource);
|
|
}
|
|
break;
|
|
|
|
case CDataFileMgr::ChangeSetAction::CHANGE_SET_ACTION_LOAD_REQUESTED_OBJECTS:
|
|
{
|
|
if (action.m_add) //doesn't have any meaning unloading
|
|
{
|
|
fileloaderDebugf1("ChangeSetAction: LoadAllRequestedObjects");
|
|
CStreaming::LoadAllRequestedObjects();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case CDataFileMgr::ChangeSetAction::CHANGE_SET_ACTION_UNREGISTER_RESOURCE:
|
|
{
|
|
if (action.m_add)
|
|
{
|
|
fileloaderDebugf1("ChangeSetAction: UnregisterResource");
|
|
ChangeSetAction_UnregisterResource(action.m_residentResource);
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
{
|
|
fileloaderWarningf("Unexpected CCS action type : %d",action.m_actionType);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void CFileLoader::ExecuteContentChangeSet(const CDataFileMgr::ContentChangeSet &contentChangeSet)
|
|
{
|
|
fileloaderDebugf1("Executing content change set %s", contentChangeSet.m_changeSetName.c_str());
|
|
|
|
atArray<CDataFileMgr::ChangeSetAction> actionList;
|
|
u32 actionMask = CDataFileMgr::ChangeSetAction::CCS_ALL_ACTIONS;
|
|
|
|
BuildContentChangeSetActionList(contentChangeSet, actionList, actionMask, CDataFileMgr::ChangeSetAction::CSA_FIRST_PRIORITY, true);
|
|
|
|
int numActions = actionList.GetCount();
|
|
for (int i = 0; i < numActions; i++)
|
|
{
|
|
ExecuteChangeSetAction(actionList[i]);
|
|
}
|
|
|
|
// MASSIVE HACK:
|
|
if (atStringHash(contentChangeSet.m_changeSetName.c_str()) == ATSTRINGHASH("MPBUSINESS_AUTOGEN", 0xA02B068C))
|
|
MeshBlendManager::GetInstance().ExtraContentUpdated(true);
|
|
}
|
|
|
|
void CFileLoader::RevertContentChangeSet(const CDataFileMgr::ContentChangeSet &contentChangeSet, u32 actionMask)
|
|
{
|
|
fileloaderDebugf1("Reverting content change set %s", contentChangeSet.m_changeSetName.c_str());
|
|
|
|
atArray<CDataFileMgr::ChangeSetAction> actionList;
|
|
|
|
BuildContentChangeSetActionList(contentChangeSet, actionList, actionMask, CDataFileMgr::ChangeSetAction::CSA_LAST_PRIORITY, false);
|
|
|
|
// MASSIVE HACK:
|
|
if (atStringHash(contentChangeSet.m_changeSetName.c_str()) == ATSTRINGHASH("MPBUSINESS_AUTOGEN", 0xA02B068C))
|
|
MeshBlendManager::GetInstance().ExtraContentUpdated(false);
|
|
|
|
int numActions = actionList.GetCount();
|
|
for (int i = numActions-1; i >= 0; i--)
|
|
{
|
|
actionList[i].m_add = !actionList[i].m_add;
|
|
ExecuteChangeSetAction(actionList[i]);
|
|
}
|
|
|
|
}
|
|
CDataFileMgr::ChangeSetAction & CFileLoader::AppendChangeSetAction(atArray<CDataFileMgr::ChangeSetAction> & actionList, CDataFileMgr::ChangeSetAction::actionTypeEnum type, bool add,
|
|
u32 priority /* = CDataFileMgr::ChangeSetAction::NO_PRIORITY */)
|
|
{
|
|
fileloaderDebugf3("AppendChangeSetAction index:%d type:%d add:%d",actionList.GetCount(),type,add);
|
|
CDataFileMgr::ChangeSetAction & action = actionList.Grow();
|
|
action.m_actionType = type;
|
|
action.m_add = add;
|
|
action.m_priority = (u8)priority;
|
|
return action;
|
|
}
|
|
|
|
u32 CFileLoader::GetDataTypePriority(CDataFileMgr::DataFileType type, const CDataFileMgr::DataFileType * typeList, int listLen)
|
|
{
|
|
for (int i = 0 ; i < listLen; i ++)
|
|
{
|
|
if (typeList[i] == type)
|
|
return (i + 1); // Allow space for CSA_FIRST_PRIORITY
|
|
}
|
|
|
|
return CDataFileMgr::ChangeSetAction::CSA_NO_PRIORITY;
|
|
}
|
|
|
|
#if __ASSERT
|
|
#define CHECK_DATA_FILES(ptr,expandedFilename,changeSetName)\
|
|
const fiDevice *device = fiDevice::GetDevice(expandedFilename,false);\
|
|
char path[RAGE_MAX_PATH]={0};\
|
|
if(device)\
|
|
device->FixRelativeName(path, RAGE_MAX_PATH, expandedFilename);\
|
|
if(strcmp(path,expandedFilename)==0)\
|
|
{\
|
|
Assertf(ptr,"File %s not found in CCS %s it is likely that the DLC rpf's need updating",expandedFilename,changeSetName);\
|
|
}\
|
|
else\
|
|
{\
|
|
Assertf(ptr,"File %s not found in CCS %s , Full Path: %s",expandedFilename,changeSetName,path);\
|
|
}
|
|
#else
|
|
#define CHECK_DATA_FILES(ptr,expandedFilename,changeSetName)
|
|
#endif
|
|
|
|
#define ENUMERATE_DATA_FILES(array,ptr) for (const atString * filename = (array).begin(); filename != (array).end(); filename++)\
|
|
{\
|
|
char expandedFilename[RAGE_MAX_PATH];\
|
|
DATAFILEMGR.ExpandFilename(*filename, expandedFilename, sizeof(expandedFilename));\
|
|
CDataFileMgr::DataFile * ptr = DATAFILEMGR.FindDataFile(atStringHash(expandedFilename));\
|
|
CHECK_DATA_FILES(ptr,expandedFilename,contentChangeSet.m_changeSetName.c_str())\
|
|
if (ptr)
|
|
|
|
#define ENUMERATE_DATA_FILES_END }
|
|
|
|
strIndex GetStreamIndexFromFileAndExt(const char* filePath)
|
|
{
|
|
strIndex returnIndex = strIndex();
|
|
const char* extPattern = ASSET.FindExtensionInPath(filePath);
|
|
char newPath[256] = { 0 };
|
|
|
|
if (extPattern)
|
|
{
|
|
extPattern++;
|
|
|
|
if (const char* platformExt = strStreamingEngine::GetInfo().GetModuleMgr().getPlatExtFromExtPattern(extPattern))
|
|
{
|
|
if (strStreamingModule* module = strStreamingEngine::GetInfo().GetModuleMgr().GetModuleFromFileExtension(platformExt))
|
|
{
|
|
ASSET.RemoveExtensionFromPath(newPath, sizeof(newPath), filePath);
|
|
|
|
strLocalIndex slot = module->FindSlot(newPath);
|
|
|
|
if (Verifyf(slot.IsValid(), "Cannot find %s in module %s", filePath, module->GetModuleName()))
|
|
returnIndex = module->GetStreamingIndex(slot);
|
|
}
|
|
}
|
|
}
|
|
|
|
return returnIndex;
|
|
}
|
|
|
|
void CFileLoader::BuildInvalidateList(const atArray<atString>& filesToInvalidate, atArray<CDataFileMgr::ChangeSetAction>& actionList, u32 actionMask)
|
|
{
|
|
for (u32 i = 0; i < filesToInvalidate.GetCount(); i++)
|
|
{
|
|
const atString& currFile = filesToInvalidate[i];
|
|
const char* extension = ASSET.FindExtensionInPath(currFile.c_str());
|
|
|
|
// Check the extension and store the image index as map data files are removed from DataFileManager after being loaded...
|
|
if (extension)
|
|
{
|
|
char filename[RAGE_MAX_PATH] = { 0 };
|
|
|
|
++extension;
|
|
|
|
// Able to invalidate a whole RPF, an interior or a single streamable
|
|
if (stricmp(extension, PI_ARCHIVE_FILE_EXT) == 0 && BIT_ISSET((u32)CDataFileMgr::ChangeSetAction::CHANGE_SET_ACTION_INVALIDATE_FILE, actionMask))
|
|
{
|
|
char expandedFilename[RAGE_MAX_PATH] = { 0 };
|
|
|
|
ASSET.FullPath(filename, sizeof(filename), currFile.c_str(), "");
|
|
DATAFILEMGR.ExpandFilename(filename, expandedFilename, sizeof(expandedFilename));
|
|
|
|
s32 archiveIndex = strPackfileManager::FindImage(expandedFilename);
|
|
|
|
if (const atArray<s32>* associatedFiles = strStreamingEngine::GetInfo().GetPackfileRelationships(archiveIndex))
|
|
{
|
|
for (s32 k = 0; k < associatedFiles->GetCount(); k++)
|
|
{
|
|
archiveIndex = (*associatedFiles)[k];
|
|
|
|
if (Verifyf(archiveIndex != -1, "BuildInvalidateList - cannot find archive %s", currFile.c_str()))
|
|
{
|
|
AppendChangeSetAction(actionList, CDataFileMgr::ChangeSetAction::CHANGE_SET_ACTION_INVALIDATE_FILE,
|
|
true, CDataFileMgr::ChangeSetAction::CSA_FIRST_PRIORITY).archiveIndex = archiveIndex;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (Verifyf(archiveIndex != -1, "BuildInvalidateList - cannot find archive %s", currFile.c_str()))
|
|
{
|
|
AppendChangeSetAction(actionList, CDataFileMgr::ChangeSetAction::CHANGE_SET_ACTION_INVALIDATE_FILE,
|
|
true, CDataFileMgr::ChangeSetAction::CSA_FIRST_PRIORITY).archiveIndex = archiveIndex;
|
|
}
|
|
}
|
|
}
|
|
else if (stricmp(extension, "interior") == 0 && BIT_ISSET((u32)CDataFileMgr::ChangeSetAction::CHANGE_SET_ACTION_INVALIDATE_INTERIOR, actionMask))
|
|
{
|
|
ASSET.RemoveExtensionFromPath(filename, sizeof(filename), currFile.c_str());
|
|
strLocalIndex slotIndex = fwMapDataStore::GetStore().FindSlot(filename);
|
|
|
|
if (Verifyf(slotIndex != -1, "BuildInvalidateList - cannot find interior %s", currFile.c_str()))
|
|
{
|
|
AppendChangeSetAction(actionList, CDataFileMgr::ChangeSetAction::CHANGE_SET_ACTION_INVALIDATE_INTERIOR,
|
|
true, CDataFileMgr::ChangeSetAction::CSA_FIRST_PRIORITY).archiveIndex = slotIndex.Get();
|
|
}
|
|
}
|
|
else if (BIT_ISSET((u32)CDataFileMgr::ChangeSetAction::CHANGE_SET_ACTION_INVALIDATE_STREAMABLE, actionMask))
|
|
{
|
|
strIndex tempStrIdx = GetStreamIndexFromFileAndExt(currFile.c_str());
|
|
|
|
if (Verifyf(tempStrIdx.IsValid(), "BuildInvalidateList - cannot find streamable %s", currFile.c_str()))
|
|
{
|
|
AppendChangeSetAction(actionList, CDataFileMgr::ChangeSetAction::CHANGE_SET_ACTION_INVALIDATE_STREAMABLE,
|
|
true, CDataFileMgr::ChangeSetAction::CSA_FIRST_PRIORITY).m_strIndex = tempStrIdx;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CFileLoader::BuildRPFEnablementList(const CDataFileMgr::ContentChangeSet& ASSERT_ONLY(contentChangeSet), const atArray<atString>& fileList,
|
|
atArray<CDataFileMgr::ChangeSetAction>& actionList, bool add, u32 mapDataPriority)
|
|
{
|
|
ENUMERATE_DATA_FILES(fileList, dataFile)
|
|
{
|
|
if (IsValidRpfType(dataFile->m_fileType))
|
|
{
|
|
u32 priority = CDataFileMgr::ChangeSetAction::CSA_NO_PRIORITY;
|
|
|
|
if (dataFile->m_contents == CDataFileMgr::CONTENTS_DLC_MAP_DATA)
|
|
priority = mapDataPriority;
|
|
|
|
AppendChangeSetAction(actionList, CDataFileMgr::ChangeSetAction::CHANGE_SET_ACTION_RPF, add, priority).m_file = dataFile;
|
|
}
|
|
}
|
|
ENUMERATE_DATA_FILES_END
|
|
}
|
|
|
|
void CFileLoader::BuildDataFileEnablementList(const CDataFileMgr::ContentChangeSet& ASSERT_ONLY(contentChangeSet), const atArray<atString>& fileList,
|
|
atArray<CDataFileMgr::ChangeSetAction>& actionList, bool add, bool inverter)
|
|
{
|
|
//File types in this list will be loaded before streaming objects are requested
|
|
CDataFileMgr::DataFileType earlyDataTypes[] =
|
|
{
|
|
CDataFileMgr::WEAPONCOMPONENTSINFO_FILE,
|
|
CDataFileMgr::CLIP_SETS_FILE,
|
|
CDataFileMgr::WEAPON_ANIMATIONS_FILE,
|
|
CDataFileMgr::WEAPON_METADATA_FILE,
|
|
CDataFileMgr::INTERIOR_PROXY_ORDER_FILE,
|
|
CDataFileMgr::HANDLING_FILE,
|
|
CDataFileMgr::VEHICLE_LAYOUTS_FILE,
|
|
CDataFileMgr::PED_METADATA_FILE,
|
|
CDataFileMgr::DLC_POP_GROUPS
|
|
};
|
|
|
|
int numEarlyDataTypes = NELEM(earlyDataTypes);
|
|
|
|
ENUMERATE_DATA_FILES(fileList, dataFile)
|
|
{
|
|
u32 priority = GetDataTypePriority(dataFile->m_fileType, earlyDataTypes, numEarlyDataTypes);
|
|
|
|
if (dataFile->m_fileType != CDataFileMgr::RPF_FILE && dataFile->m_fileType != CDataFileMgr::RPF_FILE_PRE_INSTALL && (inverter == (priority == CDataFileMgr::ChangeSetAction::CSA_NO_PRIORITY)))
|
|
{
|
|
AppendChangeSetAction(actionList, CDataFileMgr::ChangeSetAction::CHANGE_SET_ACTION_DATA_FILE, add, priority).m_file = dataFile;
|
|
}
|
|
}
|
|
ENUMERATE_DATA_FILES_END
|
|
}
|
|
|
|
void CFileLoader::BuildTxdEnablementList(const atArray<atHashString>& fileList, atArray<CDataFileMgr::ChangeSetAction>& actionList, bool add)
|
|
{
|
|
for (const atHashString * txd = fileList.begin(); txd != fileList.end(); txd++)
|
|
AppendChangeSetAction(actionList, CDataFileMgr::ChangeSetAction::CHANGE_SET_ACTION_TXD, add).m_txd = txd;
|
|
}
|
|
|
|
void CFileLoader::BuildContentChangeSetActionList(const CDataFileMgr::ContentChangeSet &contentChangeSet,
|
|
atArray<CDataFileMgr::ChangeSetAction> & actionList, u32 actionMask, u32 mapDataPriority, bool execute)
|
|
{
|
|
fileloaderDebugf1("BuildContentChangeSetActionList");
|
|
|
|
// ----- Invalidate files
|
|
fileloaderDebugf2("BuildContentChangeSetActionList: Invalidate file(s)");
|
|
BuildInvalidateList(contentChangeSet.m_filesToInvalidate, actionList, actionMask);
|
|
|
|
for (u32 i = 0; i < contentChangeSet.m_mapChangeSetData.GetCount(); i++)
|
|
{
|
|
if (contentChangeSet.m_mapChangeSetData[i].IsValid(execute))
|
|
BuildInvalidateList(contentChangeSet.m_mapChangeSetData[i].m_filesToInvalidate, actionList, actionMask);
|
|
}
|
|
|
|
if (BIT_ISSET((u32)CDataFileMgr::ChangeSetAction::CHANGE_SET_ACTION_TXD, actionMask))
|
|
{
|
|
// ----- Unload txds
|
|
fileloaderDebugf2("BuildContentChangeSetActionList: Unload txds");
|
|
|
|
BuildTxdEnablementList(contentChangeSet.m_txdToUnload, actionList, false);
|
|
|
|
for (u32 i = 0; i < contentChangeSet.m_mapChangeSetData.GetCount(); i++)
|
|
{
|
|
if (contentChangeSet.m_mapChangeSetData[i].IsValid(execute))
|
|
BuildTxdEnablementList(contentChangeSet.m_mapChangeSetData[i].m_txdToUnload, actionList, false);
|
|
}
|
|
}
|
|
|
|
if (BIT_ISSET((u32)CDataFileMgr::ChangeSetAction::CHANGE_SET_ACTION_RPF, actionMask))
|
|
{
|
|
// ----- Disable RPFs
|
|
fileloaderDebugf2("BuildContentChangeSetActionList: Disable RPFs");
|
|
|
|
BuildRPFEnablementList(contentChangeSet, contentChangeSet.m_filesToDisable, actionList, false, mapDataPriority);
|
|
|
|
for (u32 i = 0; i < contentChangeSet.m_mapChangeSetData.GetCount(); i++)
|
|
{
|
|
if (contentChangeSet.m_mapChangeSetData[i].IsValid(execute))
|
|
BuildRPFEnablementList(contentChangeSet, contentChangeSet.m_mapChangeSetData[i].m_filesToDisable, actionList, false, mapDataPriority);
|
|
}
|
|
}
|
|
|
|
if (BIT_ISSET((u32)CDataFileMgr::ChangeSetAction::CHANGE_SET_ACTION_RPF, actionMask))
|
|
{
|
|
// ----- Enable RPFs
|
|
fileloaderDebugf2("BuildContentChangeSetActionList: Enable RPFs");
|
|
|
|
BuildRPFEnablementList(contentChangeSet, contentChangeSet.m_filesToEnable, actionList, true, mapDataPriority);
|
|
|
|
for (u32 i = 0; i < contentChangeSet.m_mapChangeSetData.GetCount(); i++)
|
|
{
|
|
if (contentChangeSet.m_mapChangeSetData[i].IsValid(execute))
|
|
BuildRPFEnablementList(contentChangeSet, contentChangeSet.m_mapChangeSetData[i].m_filesToEnable, actionList, true, mapDataPriority);
|
|
}
|
|
}
|
|
|
|
if (BIT_ISSET((u32)CDataFileMgr::ChangeSetAction::CHANGE_SET_ACTION_TXD, actionMask))
|
|
{
|
|
// ----- Load txds
|
|
fileloaderDebugf2("BuildContentChangeSetActionList: Load txds");
|
|
|
|
BuildTxdEnablementList(contentChangeSet.m_txdToLoad, actionList, true);
|
|
|
|
for (u32 i = 0; i < contentChangeSet.m_mapChangeSetData.GetCount(); i++)
|
|
{
|
|
if (contentChangeSet.m_mapChangeSetData[i].IsValid(execute))
|
|
BuildTxdEnablementList(contentChangeSet.m_mapChangeSetData[i].m_txdToLoad, actionList, true);
|
|
}
|
|
}
|
|
|
|
if (BIT_ISSET((u32)CDataFileMgr::ChangeSetAction::CHANGE_SET_ACTION_DATA_FILE, actionMask))
|
|
{
|
|
// ----- Early data
|
|
fileloaderDebugf2("BuildContentChangeSetActionList: Early data (disable)");
|
|
|
|
BuildDataFileEnablementList(contentChangeSet, contentChangeSet.m_filesToDisable, actionList, false, false);
|
|
|
|
for (u32 i = 0; i < contentChangeSet.m_mapChangeSetData.GetCount(); i++)
|
|
{
|
|
if (contentChangeSet.m_mapChangeSetData[i].IsValid(execute))
|
|
BuildDataFileEnablementList(contentChangeSet, contentChangeSet.m_mapChangeSetData[i].m_filesToDisable, actionList, false, false);
|
|
}
|
|
}
|
|
|
|
size_t filesToEnableOffset = actionList.GetCount();
|
|
|
|
std::sort(actionList.begin(), actionList.end());
|
|
|
|
if (BIT_ISSET((u32)CDataFileMgr::ChangeSetAction::CHANGE_SET_ACTION_DATA_FILE, actionMask))
|
|
{
|
|
fileloaderDebugf2("BuildContentChangeSetActionList: Early data (enable)");
|
|
|
|
BuildDataFileEnablementList(contentChangeSet, contentChangeSet.m_filesToEnable, actionList, true, false);
|
|
|
|
for (u32 i = 0; i < contentChangeSet.m_mapChangeSetData.GetCount(); i++)
|
|
{
|
|
if (contentChangeSet.m_mapChangeSetData[i].IsValid(execute))
|
|
BuildDataFileEnablementList(contentChangeSet, contentChangeSet.m_mapChangeSetData[i].m_filesToEnable, actionList, true, false);
|
|
}
|
|
}
|
|
|
|
std::sort(actionList.begin() + filesToEnableOffset, actionList.end());
|
|
|
|
if (BIT_ISSET((u32)CDataFileMgr::ChangeSetAction::CHANGE_SET_ACTION_RESIDENT_RESOURCE, actionMask))
|
|
{
|
|
// ----- Request objs
|
|
fileloaderDebugf2("BuildContentChangeSetActionList: Request objs");
|
|
for (const CDataFileMgr::ResourceReference * residentResource = contentChangeSet.m_residentResources.begin(); residentResource != contentChangeSet.m_residentResources.end(); residentResource++)
|
|
AppendChangeSetAction(actionList, CDataFileMgr::ChangeSetAction::CHANGE_SET_ACTION_RESIDENT_RESOURCE, true).m_residentResource = residentResource;
|
|
}
|
|
|
|
// ----- Wait for loading objs
|
|
fileloaderDebugf2("BuildContentChangeSetActionList: Wait for loading objs");
|
|
AppendChangeSetAction(actionList, CDataFileMgr::ChangeSetAction::CHANGE_SET_ACTION_LOAD_REQUESTED_OBJECTS, true);
|
|
|
|
if (BIT_ISSET((u32)CDataFileMgr::ChangeSetAction::CHANGE_SET_ACTION_DATA_FILE, actionMask))
|
|
{
|
|
// ----- Rest of data
|
|
fileloaderDebugf2("BuildContentChangeSetActionList: Rest of data (disable)");
|
|
BuildDataFileEnablementList(contentChangeSet, contentChangeSet.m_filesToDisable, actionList, false, true);
|
|
|
|
for (u32 i = 0; i < contentChangeSet.m_mapChangeSetData.GetCount(); i++)
|
|
{
|
|
if (contentChangeSet.m_mapChangeSetData[i].IsValid(execute))
|
|
BuildDataFileEnablementList(contentChangeSet, contentChangeSet.m_mapChangeSetData[i].m_filesToDisable, actionList, false, true);
|
|
}
|
|
}
|
|
|
|
if (BIT_ISSET((u32)CDataFileMgr::ChangeSetAction::CHANGE_SET_ACTION_DATA_FILE, actionMask))
|
|
{
|
|
fileloaderDebugf2("BuildContentChangeSetActionList: Rest of data (enable)");
|
|
BuildDataFileEnablementList(contentChangeSet, contentChangeSet.m_filesToEnable, actionList, true, true);
|
|
|
|
for (u32 i = 0; i < contentChangeSet.m_mapChangeSetData.GetCount(); i++)
|
|
{
|
|
if (contentChangeSet.m_mapChangeSetData[i].IsValid(execute))
|
|
BuildDataFileEnablementList(contentChangeSet, contentChangeSet.m_mapChangeSetData[i].m_filesToEnable, actionList, true, true);
|
|
}
|
|
}
|
|
|
|
if (BIT_ISSET((u32)CDataFileMgr::ChangeSetAction::CHANGE_SET_ACTION_UNREGISTER_RESOURCE, actionMask))
|
|
{
|
|
fileloaderDebugf2("BuildContentChangeSetActionList: Unregister objs");
|
|
for (const CDataFileMgr::ResourceReference * residentResource = contentChangeSet.m_unregisterResources.begin(); residentResource != contentChangeSet.m_unregisterResources.end(); residentResource++)
|
|
{
|
|
AppendChangeSetAction(actionList, CDataFileMgr::ChangeSetAction::CHANGE_SET_ACTION_UNREGISTER_RESOURCE, true).m_residentResource = residentResource;
|
|
}
|
|
}
|
|
}
|
|
|
|
#undef ENUMERATE_DATA_FILES
|
|
|
|
#undef ENUMERATE_DATA_FILES_END
|
|
|
|
|
|
void CFileLoader::AddAllRpfFiles(bool registerFiles)
|
|
{
|
|
USE_MEMBUCKET(MEMBUCKET_WORLD);
|
|
|
|
const u32 preInstallCount = NELEM(ms_validRpfTypesPreInstall);
|
|
const u32 count = NELEM(ms_validRpfTypes);
|
|
|
|
u32 iType = 0;
|
|
|
|
do
|
|
{
|
|
// Load RPF files
|
|
const CDataFileMgr::DataFile* pData = DATAFILEMGR.GetFirstFile(CFileMgr::IsGameInstalled() ? ms_validRpfTypes[iType] : ms_validRpfTypesPreInstall[iType]);
|
|
|
|
while(DATAFILEMGR.IsValid(pData))
|
|
{
|
|
strStreamingEngine::GetLoader().CallKeepAliveCallbackIfNecessary();
|
|
|
|
// Don't add disabled files.
|
|
if (!pData->m_disabled)
|
|
{
|
|
AddRpfFile(pData, registerFiles);
|
|
}
|
|
|
|
pData = DATAFILEMGR.GetNextFile(pData);
|
|
|
|
PS3_ONLY(pfDummySync());
|
|
}
|
|
} while (++iType < (CFileMgr::IsGameInstalled() ? count : preInstallCount));
|
|
}
|
|
|
|
void CFileLoader::LoadRpfFiles()
|
|
{
|
|
DummyFactory(); // See above for the reason for this
|
|
|
|
fileloaderDebugf3("LoadRpfFiles");
|
|
|
|
PF_START_STARTUPBAR("Add All RPF files");
|
|
strStreamingEngine::GetLoader().CallKeepAliveCallback();
|
|
AddAllRpfFiles(false);
|
|
PF_START_STARTUPBAR("Streaming InitLevel");
|
|
strStreamingEngine::GetLoader().CallKeepAliveCallback();
|
|
CStreaming::LoadAllRequestedObjects();
|
|
CStreaming::InitLevelWithMapUnloaded();
|
|
strStreamingEngine::GetLoader().CallKeepAliveCallback();
|
|
}
|
|
|
|
// default.ide and peds.ide used to be loaded before any rpf files
|
|
void CFileLoader::LoadWeaponMetaData()
|
|
{
|
|
fileloaderDebugf3("LoadWeaponMetaData");
|
|
|
|
USE_MEMBUCKET(MEMBUCKET_WORLD);
|
|
|
|
// Load IDE_XML files
|
|
//@@: location CFILELOADER_LOADWEAPONMETADATA_GETFIRSTFILE
|
|
const CDataFileMgr::DataFile* pData = DATAFILEMGR.GetFirstFile(CDataFileMgr::WEAPON_METADATA_FILE);
|
|
|
|
while(DATAFILEMGR.IsValid(pData))
|
|
{
|
|
if (!pData->m_disabled)
|
|
{
|
|
LoadObjectTypesXml(pData->m_filename, CDataFileMgr::WEAPON_METADATA_FILE);
|
|
}
|
|
|
|
pData = DATAFILEMGR.GetNextFile(pData);
|
|
}
|
|
|
|
}
|
|
|
|
// default.ide and peds.ide used to be loaded before any rpf files
|
|
void CFileLoader::LoadPedMetaData()
|
|
{
|
|
fileloaderDebugf3("LoadPedMetaData");
|
|
|
|
USE_MEMBUCKET(MEMBUCKET_WORLD);
|
|
|
|
CPedModelInfo::LoadPedPersonalityData();
|
|
|
|
CPedModelInfo::LoadPedPerceptionData();
|
|
|
|
// Load IDE_XML files
|
|
const CDataFileMgr::DataFile* pData = DATAFILEMGR.GetFirstFile(CDataFileMgr::PED_METADATA_FILE);
|
|
|
|
while(DATAFILEMGR.IsValid(pData))
|
|
{
|
|
if(!pData->m_disabled)
|
|
{
|
|
LoadObjectTypesXml(pData->m_filename, CDataFileMgr::PED_METADATA_FILE);
|
|
}
|
|
|
|
pData = DATAFILEMGR.GetNextFile(pData);
|
|
}
|
|
|
|
}
|
|
|
|
void CFileLoader::LoadVehicleMetaData()
|
|
{
|
|
fileloaderDebugf3("LoadVehicleMetaData");
|
|
|
|
const CDataFileMgr::DataFile* pData = DATAFILEMGR.GetFirstFile(CDataFileMgr::VEHICLE_METADATA_FILE);
|
|
|
|
while(DATAFILEMGR.IsValid(pData))
|
|
{
|
|
if (!pData->m_disabled)
|
|
{
|
|
#if __DEV
|
|
SetCurrentLoadingFile(pData->m_filename);
|
|
#endif
|
|
|
|
CVehicleModelInfo::LoadVehicleMetaFile(pData->m_filename, true, fwFactory::GLOBAL);
|
|
|
|
#if __DEV
|
|
SetCurrentLoadingFile(NULL);
|
|
#endif
|
|
}
|
|
|
|
pData = DATAFILEMGR.GetNextFile(pData);
|
|
}
|
|
}
|
|
|
|
// have to load object data after loading IDE files but before IPL files
|
|
void CFileLoader::PreLoadIplPostLoadIde()
|
|
{
|
|
fileloaderDebugf3("PreLoadIplPostLoadIde");
|
|
|
|
USE_MEMBUCKET(MEMBUCKET_WORLD);
|
|
|
|
// PreProcess before all IPLs are loaded
|
|
}
|
|
|
|
void CFileLoader::LoadIplFiles()
|
|
{
|
|
PF_START_STARTUPBAR("Begin load IPL files");
|
|
fileloaderDebugf3("LoadIplFiles");
|
|
|
|
USE_MEMBUCKET(MEMBUCKET_WORLD);
|
|
|
|
const CDataFileMgr::DataFile* pData = DATAFILEMGR.GetFirstFile(CDataFileMgr::IPL_FILE);
|
|
atArray<const fiDevice*> m_iplDeviceArray;
|
|
atArray<u32> m_filenameHashArray;
|
|
|
|
m_iplDeviceArray.Reserve(100);
|
|
m_filenameHashArray.Reserve(100);
|
|
|
|
while(DATAFILEMGR.IsValid(pData))
|
|
{
|
|
char basename[32];
|
|
ASSET.BaseName(basename, sizeof(basename), ASSET.FileName(pData->m_filename));
|
|
const fiDevice* pDevice = fiDevice::GetDevice(pData->m_filename);
|
|
u32 filenameHash = atStringHash(basename);
|
|
|
|
// search for file in list with different device. If we find one then don't load this one
|
|
s32 i;
|
|
for(i=0; i<m_iplDeviceArray.GetCount(); i++)
|
|
{
|
|
if(m_iplDeviceArray[i] != pDevice &&
|
|
m_filenameHashArray[i] == filenameHash)
|
|
break;
|
|
}
|
|
|
|
// If a version of this file hasn't been loaded already then load it
|
|
if(i == m_iplDeviceArray.GetCount())
|
|
{
|
|
//PF_START_STARTUPBAR_TEMPNAME(pData->m_filename);
|
|
LoadScene(pData->m_filename); // DW - IPLs are loaded here
|
|
}
|
|
else {
|
|
artDisplayf("Ignoring %s as we have loaded a version of this already", pData->m_filename);
|
|
}
|
|
|
|
// add to lists
|
|
m_iplDeviceArray.PushAndGrow(pDevice);
|
|
m_filenameHashArray.PushAndGrow(filenameHash);
|
|
|
|
pData = DATAFILEMGR.GetNextFile(pData);
|
|
}
|
|
}
|
|
|
|
// pedbounds.xml loading
|
|
void CFileLoader::LoadCapsuleFile()
|
|
{
|
|
fileloaderDebugf3("LoadCapsuleFile");
|
|
|
|
USE_MEMBUCKET(MEMBUCKET_WORLD);
|
|
|
|
// Load files
|
|
const CDataFileMgr::DataFile* pData = DATAFILEMGR.GetFirstFile(CDataFileMgr::PED_BOUNDS_FILE);
|
|
|
|
while(DATAFILEMGR.IsValid(pData))
|
|
{
|
|
if(!pData->m_disabled)
|
|
{
|
|
CPedCapsuleInfoManager::Init(pData->m_filename);
|
|
}
|
|
|
|
pData = DATAFILEMGR.GetNextFile(pData);
|
|
}
|
|
}
|
|
|
|
// pedhealth.meta loading
|
|
void CFileLoader::LoadHealthConfigFile()
|
|
{
|
|
fileloaderDebugf3("LoadHealthConfigFile");
|
|
|
|
USE_MEMBUCKET(MEMBUCKET_WORLD);
|
|
|
|
// Load files
|
|
const CDataFileMgr::DataFile* pData = DATAFILEMGR.GetFirstFile(CDataFileMgr::PED_HEALTH_FILE);
|
|
|
|
while(DATAFILEMGR.IsValid(pData))
|
|
{
|
|
CHealthConfigInfoManager::Init(pData->m_filename);
|
|
|
|
pData = DATAFILEMGR.GetNextFile(pData);
|
|
}
|
|
}
|
|
|
|
#if ENABLE_HORSE
|
|
// mounttune.xml loading
|
|
void CFileLoader::LoadMountTuneFile()
|
|
{
|
|
fileloaderDebugf3("LoadMountTuneFile");
|
|
|
|
USE_MEMBUCKET(MEMBUCKET_WORLD);
|
|
|
|
// Load files
|
|
const CDataFileMgr::DataFile* pData = DATAFILEMGR.GetFirstFile(CDataFileMgr::MOUNT_TUNE_FILE);
|
|
|
|
while(DATAFILEMGR.IsValid(pData))
|
|
{
|
|
HRSSIMTUNEMGR.Load(pData->m_filename);
|
|
|
|
pData = DATAFILEMGR.GetNextFile(pData);
|
|
}
|
|
}
|
|
|
|
void CFileLoader::LoadHorseReinsFile()
|
|
{
|
|
fileloaderDebugf3("LoadHorseReinsFile");
|
|
|
|
USE_MEMBUCKET(MEMBUCKET_WORLD);
|
|
|
|
// Load files
|
|
const CDataFileMgr::DataFile* pData = DATAFILEMGR.GetFirstFile(CDataFileMgr::HORSE_REINS_FILE);
|
|
|
|
while(DATAFILEMGR.IsValid(pData))
|
|
{
|
|
CReins* defaultReins = CReins::GetDefaultReins();
|
|
Assert( defaultReins );
|
|
defaultReins->Load(pData->m_filename);
|
|
|
|
pData = DATAFILEMGR.GetNextFile(pData);
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
void CFileLoader::LoadDoorTypeTuningFile()
|
|
{
|
|
fileloaderDebugf3("LoadDoorTypeTuningFile");
|
|
|
|
USE_MEMBUCKET(MEMBUCKET_WORLD);
|
|
|
|
CDoorTuningManager::InitClass();
|
|
|
|
// Load files
|
|
const CDataFileMgr::DataFile* pData = DATAFILEMGR.GetFirstFile(CDataFileMgr::DOOR_TUNING_FILE);
|
|
while(DATAFILEMGR.IsValid(pData))
|
|
{
|
|
CDoorTuningManager::GetInstance().Load(pData->m_filename);
|
|
pData = DATAFILEMGR.GetNextFile(pData);
|
|
}
|
|
|
|
CDoorTuningManager::GetInstance().FinishedLoading();
|
|
}
|
|
|
|
void CFileLoader::LoadObjectCoverTuningFile()
|
|
{
|
|
fileloaderDebugf3("LoadObjectCoverTuningFile");
|
|
|
|
USE_MEMBUCKET(MEMBUCKET_WORLD);
|
|
|
|
CCoverTuningManager::InitClass();
|
|
|
|
// Load files
|
|
const CDataFileMgr::DataFile* pData = DATAFILEMGR.GetFirstFile(CDataFileMgr::OBJ_COVER_TUNING_FILE);
|
|
while(DATAFILEMGR.IsValid(pData))
|
|
{
|
|
CCoverTuningManager::GetInstance().Load(pData->m_filename);
|
|
pData = DATAFILEMGR.GetNextFile(pData);
|
|
}
|
|
}
|
|
|
|
// pedmotiontaskdata.xml loading
|
|
void CFileLoader::LoadMotionTaskDataFile()
|
|
{
|
|
fileloaderDebugf3("LoadMotionTaskDataFile");
|
|
|
|
USE_MEMBUCKET(MEMBUCKET_WORLD);
|
|
|
|
// Load files
|
|
const CDataFileMgr::DataFile* pData = DATAFILEMGR.GetFirstFile(CDataFileMgr::MOTION_TASK_DATA_FILE);
|
|
|
|
while(DATAFILEMGR.IsValid(pData))
|
|
{
|
|
CMotionTaskDataManager::Init(pData->m_filename);
|
|
|
|
pData = DATAFILEMGR.GetNextFile(pData);
|
|
}
|
|
}
|
|
|
|
// defaulttaskdata.xml loading
|
|
void CFileLoader::LoadDefaultTaskDataFile()
|
|
{
|
|
fileloaderDebugf3("LoadDefaultTaskDataFile");
|
|
|
|
USE_MEMBUCKET(MEMBUCKET_WORLD);
|
|
|
|
// Load files
|
|
const CDataFileMgr::DataFile* pData = DATAFILEMGR.GetFirstFile(CDataFileMgr::DEFAULT_TASK_DATA_FILE);
|
|
|
|
while(DATAFILEMGR.IsValid(pData))
|
|
{
|
|
CDefaultTaskDataManager::Init(pData->m_filename);
|
|
|
|
pData = DATAFILEMGR.GetNextFile(pData);
|
|
}
|
|
}
|
|
|
|
// pedcomponentcloth.xml loading
|
|
void CFileLoader::LoadPedComponentClothFile()
|
|
{
|
|
fileloaderDebugf3("LoadPedComponentClothFile");
|
|
|
|
USE_MEMBUCKET(MEMBUCKET_WORLD);
|
|
|
|
// Load files
|
|
const CDataFileMgr::DataFile* pData = DATAFILEMGR.GetFirstFile(CDataFileMgr::PED_COMPONENT_CLOTH_FILE);
|
|
|
|
while(DATAFILEMGR.IsValid(pData))
|
|
{
|
|
CPedComponentClothManager::Init(pData->m_filename);
|
|
|
|
pData = DATAFILEMGR.GetNextFile(pData);
|
|
}
|
|
}
|
|
|
|
// pedcomponentsets.xml loading
|
|
void CFileLoader::LoadPedComponentSetsFile()
|
|
{
|
|
fileloaderDebugf3("LoadPedComponentSetsFile");
|
|
|
|
USE_MEMBUCKET(MEMBUCKET_WORLD);
|
|
|
|
// Load files
|
|
const CDataFileMgr::DataFile* pData = DATAFILEMGR.GetFirstFile(CDataFileMgr::PED_COMPONENT_SETS_FILE);
|
|
|
|
while(DATAFILEMGR.IsValid(pData))
|
|
{
|
|
if(!pData->m_disabled)
|
|
{
|
|
CPedComponentSetManager::Init(pData->m_filename);
|
|
}
|
|
|
|
pData = DATAFILEMGR.GetNextFile(pData);
|
|
}
|
|
}
|
|
|
|
// pedcomponentsets.xml loading
|
|
void CFileLoader::LoadPedIKSettingsFile()
|
|
{
|
|
fileloaderDebugf3("LoadPedIKSettingsFile");
|
|
|
|
USE_MEMBUCKET(MEMBUCKET_WORLD);
|
|
|
|
// Load files
|
|
const CDataFileMgr::DataFile* pData = DATAFILEMGR.GetFirstFile(CDataFileMgr::PED_IK_SETTINGS_FILE);
|
|
|
|
while(DATAFILEMGR.IsValid(pData))
|
|
{
|
|
CPedIKSettingsInfoManager::Init(pData->m_filename);
|
|
|
|
pData = DATAFILEMGR.GetNextFile(pData);
|
|
}
|
|
}
|
|
|
|
// task data loading
|
|
void CFileLoader::LoadTaskDataFile()
|
|
{
|
|
fileloaderDebugf3("LoadTaskDataFile");
|
|
|
|
USE_MEMBUCKET(MEMBUCKET_WORLD);
|
|
|
|
// Load files
|
|
const CDataFileMgr::DataFile* pData = DATAFILEMGR.GetFirstFile(CDataFileMgr::PED_TASK_DATA_FILE);
|
|
|
|
while(DATAFILEMGR.IsValid(pData))
|
|
{
|
|
CTaskDataInfoManager::Init(pData->m_filename);
|
|
|
|
pData = DATAFILEMGR.GetNextFile(pData);
|
|
}
|
|
}
|
|
|
|
// playerspecialabilities.xml loading
|
|
void CFileLoader::LoadSpecialAbilitiesFiles()
|
|
{
|
|
fileloaderDebugf3("LoadSpecialAbilitiesFile");
|
|
|
|
USE_MEMBUCKET(MEMBUCKET_WORLD);
|
|
|
|
// Load files
|
|
const CDataFileMgr::DataFile* pData = DATAFILEMGR.GetFirstFile(CDataFileMgr::PED_SPECIAL_ABILITIES_FILE);
|
|
|
|
while(DATAFILEMGR.IsValid(pData))
|
|
{
|
|
CPlayerSpecialAbilityManager::Init(pData->m_filename);
|
|
|
|
pData = DATAFILEMGR.GetNextFile(pData);
|
|
}
|
|
}
|
|
|
|
void CFileLoader::LoadExplosionInfoFiles()
|
|
{
|
|
fileloaderDebugf3("LoadExplosionInfoFile");
|
|
|
|
USE_MEMBUCKET(MEMBUCKET_GAMEPLAY);
|
|
|
|
// Load files
|
|
const CDataFileMgr::DataFile* pData = DATAFILEMGR.GetFirstFile(CDataFileMgr::EXPLOSION_INFO_FILE);
|
|
|
|
while (DATAFILEMGR.IsValid(pData))
|
|
{
|
|
CExplosionInfoManager::Init(pData->m_filename);
|
|
pData = DATAFILEMGR.GetNextFile(pData);
|
|
}
|
|
}
|
|
|
|
void CFileLoader::LoadBrawlingStyleFiles()
|
|
{
|
|
fileloaderDebugf3("LoadBrawlingStyleFile");
|
|
|
|
USE_MEMBUCKET(MEMBUCKET_GAMEPLAY);
|
|
|
|
// Load files
|
|
const CDataFileMgr::DataFile* pData = DATAFILEMGR.GetFirstFile(CDataFileMgr::PED_BRAWLING_STYLE_FILE);
|
|
|
|
while(DATAFILEMGR.IsValid(pData))
|
|
{
|
|
CBrawlingStyleManager::Init(pData->m_filename);
|
|
pData = DATAFILEMGR.GetNextFile(pData);
|
|
}
|
|
}
|
|
|
|
void CFileLoader::LoadDeformableObjectFile()
|
|
{
|
|
fileloaderDebugf3("LoadDeformableObjectsFile");
|
|
|
|
USE_MEMBUCKET(MEMBUCKET_WORLD);
|
|
|
|
// Load file.
|
|
const CDataFileMgr::DataFile* pData = DATAFILEMGR.GetFirstFile(CDataFileMgr::DEFORMABLE_OBJECTS_FILE);
|
|
|
|
while(DATAFILEMGR.IsValid(pData))
|
|
{
|
|
CDeformableObjectManager::Load(pData->m_filename);
|
|
|
|
pData = DATAFILEMGR.GetNextFile(pData);
|
|
}
|
|
}
|
|
|
|
void CFileLoader::LoadTunableObjectFile()
|
|
{
|
|
fileloaderDebugf3("LoadTunableObjectsFile");
|
|
|
|
USE_MEMBUCKET(MEMBUCKET_WORLD);
|
|
|
|
// Load file.
|
|
const CDataFileMgr::DataFile* pData = DATAFILEMGR.GetFirstFile(CDataFileMgr::TUNABLE_OBJECTS_FILE);
|
|
|
|
while(DATAFILEMGR.IsValid(pData))
|
|
{
|
|
CTunableObjectManager::Load(pData->m_filename);
|
|
|
|
pData = DATAFILEMGR.GetNextFile(pData);
|
|
}
|
|
}
|
|
|
|
void CFileLoader::LoadNavCapabilitiesDataFile()
|
|
{
|
|
fileloaderDebugf3("LoadNavCapabilitiesDataFile");
|
|
|
|
USE_MEMBUCKET(MEMBUCKET_WORLD);
|
|
|
|
// Load files
|
|
const CDataFileMgr::DataFile* pData = DATAFILEMGR.GetFirstFile(CDataFileMgr::PED_NAV_CAPABILITES_FILE);
|
|
|
|
while(DATAFILEMGR.IsValid(pData))
|
|
{
|
|
CPedNavCapabilityInfoManager::Init(pData->m_filename);
|
|
|
|
pData = DATAFILEMGR.GetNextFile(pData);
|
|
}
|
|
}
|
|
|
|
void CFileLoader::LoadScenarioPointFiles()
|
|
{
|
|
fileloaderDebugf3("LoadScenarioPointFiles");
|
|
|
|
USE_MEMBUCKET(MEMBUCKET_WORLD);
|
|
|
|
SCENARIOPOINTMGR.Load();
|
|
}
|
|
|
|
void CFileLoader::LoadItypFiles()
|
|
{
|
|
// load permanent files
|
|
for(s32 index=0; index<g_MapTypesStore.GetSize(); index++)
|
|
{
|
|
fwMapTypesDef* pDef = g_MapTypesStore.GetSlot(strLocalIndex(index));
|
|
if (pDef && pDef->GetIsPermanent()/* && !pDef->GetIsDelayLoading()*/)
|
|
{
|
|
g_MapTypesStore.StreamingRequest(strLocalIndex(index), STRFLAG_PRIORITY_LOAD | STRFLAG_FORCE_LOAD | STRFLAG_DONTDELETE);
|
|
}
|
|
}
|
|
|
|
strStreamingEngine::GetLoader().LoadAllRequestedObjects();
|
|
|
|
for(s32 index=0; index<g_MapTypesStore.GetSize(); index++)
|
|
{
|
|
fwMapTypesDef* pDef = g_MapTypesStore.GetSlot(strLocalIndex(index));
|
|
if (pDef && pDef->GetIsPermanent()/* && !pDef->GetIsDelayLoading()*/)
|
|
{
|
|
if (!g_MapTypesStore.HasObjectLoaded(strLocalIndex(index))){
|
|
// fail safe - if can't load all in one go, then bring the unloaded ones in one at a time
|
|
g_MapTypesStore.StreamingRequest(strLocalIndex(index), STRFLAG_PRIORITY_LOAD | STRFLAG_FORCE_LOAD | STRFLAG_DONTDELETE);
|
|
strStreamingEngine::GetLoader().LoadAllRequestedObjects();
|
|
|
|
Assertf(g_MapTypesStore.HasObjectLoaded(strLocalIndex(index)), "file %s was requested (twice) but did not load\n",g_MapTypesStore.GetName(strLocalIndex(index)));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CFileLoader::AddDLCItypeFile(const char* fileName)
|
|
{
|
|
char achBaseName[RAGE_MAX_PATH] = { 0 };
|
|
ASSET.BaseName(achBaseName, sizeof(achBaseName), ASSET.FileName(fileName));
|
|
strLocalIndex index = g_MapTypesStore.FindSlotFromHashKey(atHashString(achBaseName));
|
|
if (Verifyf(index.IsValid(),"DLC_ITYP_REQUEST file :%s not found", fileName))
|
|
{
|
|
#if !__FINAL && 0 //disabled for now but may be useful
|
|
char tempStr[256] = { 0 };
|
|
const char *refCntString = g_MapTypesStore.GetRefCountString(index, tempStr, sizeof(tempStr));
|
|
|
|
Displayf("TOMW: AddDLCItypeFile - %s - %i - %s", g_MapTypesStore.GetName(index), g_MapTypesStore.GetNumRefs(index), refCntString);
|
|
#endif
|
|
|
|
g_MapTypesStore.StreamingRequest(index, STRFLAG_PRIORITY_LOAD | STRFLAG_FORCE_LOAD | STRFLAG_DONTDELETE);
|
|
g_MapTypesStore.GetSlot(index)->SetIsPermanentDLC(true);
|
|
g_MapTypesStore.GetSlot(index)->SetIsDependency(true);
|
|
ms_requestDLCItypes = true;
|
|
}
|
|
}
|
|
|
|
void CFileLoader::RemoveDLCItypeFile(const char* fileName)
|
|
{
|
|
char achBaseName[RAGE_MAX_PATH] = { 0 };
|
|
ASSET.BaseName(achBaseName, sizeof(achBaseName), ASSET.FileName(fileName));
|
|
|
|
strLocalIndex index = g_MapTypesStore.FindSlotFromHashKey(atHashString(achBaseName));
|
|
if (index.IsValid())
|
|
{
|
|
#if !__FINAL && 0 //disabled for now but may be useful
|
|
char tempStr[256] = { 0 };
|
|
const char *refCntString = g_MapTypesStore.GetRefCountString(index, tempStr, sizeof(tempStr));
|
|
|
|
Displayf("TOMW: RemoveDLCItypeFile - %s - %i - %s", g_MapTypesStore.GetName(index), g_MapTypesStore.GetNumRefs(index), refCntString);
|
|
#endif
|
|
|
|
g_MapTypesStore.ClearRequiredFlag(index.Get(), STRFLAG_DONTDELETE);
|
|
g_MapTypesStore.GetSlot(index)->SetIsPermanentDLC(false);
|
|
|
|
#if !__FINAL // Temporary non-final output for over-reffed archetypes in a departing ITYP
|
|
if (g_MapTypesStore.GetNumRefs(index) > 1) {
|
|
Displayf("Too many refs on ITYP '%s'", g_MapTypesStore.GetName(index));
|
|
|
|
fwArchetypeManager::ForAllArchetypesInFile(index.Get(), [](fwArchetype *pArchetype) {
|
|
Displayf("Archetype %s has %u refs still", pArchetype->GetModelName(), pArchetype->GetNumRefs());
|
|
});
|
|
}
|
|
#endif
|
|
|
|
strStreamingEngine::GetInfo().RemoveObjectAndDependents(g_MapTypesStore.GetStreamingIndex(index), HMT_FLUSH);
|
|
}
|
|
}
|
|
|
|
void CFileLoader::RequestDLCItypFiles()
|
|
{
|
|
if (ms_requestDLCItypes)
|
|
{
|
|
strStreamingEngine::GetLoader().LoadAllRequestedObjects();
|
|
ms_requestDLCItypes = false;
|
|
}
|
|
}
|
|
|
|
void CFileLoader::RequestPermanentItypFiles()
|
|
{
|
|
fileloaderDebugf3("RequestPermanentItypFiles");
|
|
|
|
USE_MEMBUCKET(MEMBUCKET_WORLD);
|
|
|
|
PF_START_STARTUPBAR("Request all files");
|
|
|
|
{
|
|
// Load IDE files
|
|
const CDataFileMgr::DataFile* pData = DATAFILEMGR.GetFirstFile(CDataFileMgr::PERMANENT_ITYP_FILE);
|
|
ms_permItyp.Reset();
|
|
|
|
while(DATAFILEMGR.IsValid(pData))
|
|
{
|
|
if ( !pData->m_filename )
|
|
continue;
|
|
|
|
char achBaseName[RAGE_MAX_PATH];
|
|
ASSET.BaseName(achBaseName, 32, ASSET.FileName(pData->m_filename));
|
|
|
|
strLocalIndex index = strLocalIndex(g_MapTypesStore.FindSlotFromHashKey(atHashString(achBaseName)));
|
|
if (index.Get() >= 0)
|
|
{
|
|
ms_permItyp.PushAndGrow(index.Get());
|
|
g_MapTypesStore.GetSlot(index)->SetIsPermanent(true);
|
|
g_MapTypesStore.StreamingRequest(index, STRFLAG_PRIORITY_LOAD | STRFLAG_FORCE_LOAD | STRFLAG_DONTDELETE);
|
|
}
|
|
|
|
pData = DATAFILEMGR.GetNextFile(pData);
|
|
}
|
|
|
|
strStreamingEngine::GetLoader().LoadRequestedObjects();
|
|
}
|
|
}
|
|
|
|
// default.ide and peds.ide used to be loaded before any rpf files
|
|
void CFileLoader::LoadPermanentItypFiles()
|
|
{
|
|
fileloaderDebugf3("LoadPermanentItypFiles");
|
|
|
|
USE_MEMBUCKET(MEMBUCKET_WORLD);
|
|
|
|
PF_PUSH_STARTUPBAR("Wait for files to stream");
|
|
{
|
|
for (s32 i = 0; i < ms_permItyp.GetCount(); ++i)
|
|
{
|
|
if (g_MapTypesStore.GetStreamingInfo(strLocalIndex(ms_permItyp[i]))->GetStatus() != STRINFO_LOADED)
|
|
{
|
|
strStreamingEngine::GetLoader().LoadAllRequestedObjects();
|
|
break;
|
|
}
|
|
}
|
|
ms_permItyp.Reset();
|
|
}
|
|
|
|
PF_POP_STARTUPBAR();
|
|
|
|
PF_START_STARTUPBAR("Checking files");
|
|
|
|
#if __DEV
|
|
//verify that all type files loaded...
|
|
const CDataFileMgr::DataFile* pData = DATAFILEMGR.GetFirstFile(CDataFileMgr::PERMANENT_ITYP_FILE);
|
|
|
|
while(DATAFILEMGR.IsValid(pData))
|
|
{
|
|
if ( !pData->m_filename )
|
|
continue;
|
|
|
|
char achBaseName[RAGE_MAX_PATH];
|
|
ASSET.BaseName(achBaseName, 32, ASSET.FileName(pData->m_filename));
|
|
|
|
strLocalIndex index = strLocalIndex(g_MapTypesStore.FindSlotFromHashKey(atHashString(achBaseName)));
|
|
if (index.Get() >= 0 && (g_MapTypesStore.GetSlot(index)->GetIsPermanent())) // only load global .ityp files
|
|
{
|
|
if (!g_MapTypesStore.HasObjectLoaded(index)){
|
|
// fail safe - if can't load all in one go, then bring the unloaded ones in one at a time
|
|
//PF_START_STARTUPBAR_TEMPNAME(achBaseName);
|
|
g_MapTypesStore.StreamingRequest(index, STRFLAG_PRIORITY_LOAD | STRFLAG_FORCE_LOAD | STRFLAG_DONTDELETE);
|
|
strStreamingEngine::GetLoader().LoadAllRequestedObjects();
|
|
|
|
Assertf(g_MapTypesStore.HasObjectLoaded(index), "file %s was requested (twice) but did not load\n",pData->m_filename);
|
|
}
|
|
}
|
|
|
|
pData = DATAFILEMGR.GetNextFile(pData);
|
|
}
|
|
|
|
Displayf("*** total archetypes :%" SIZETFMT "u\n", fwArchetypeManager::GetPool().GetCount());
|
|
|
|
|
|
#endif //__DEV
|
|
}
|
|
|
|
void CFileLoader::MarkArchetypesWhichCannotBeDummy()
|
|
{
|
|
// mark specific skinned animated objects to never be dummy objects (because they won't render properly as dummy objects)
|
|
// this is just for pump jacks and windmills, so a very special case really
|
|
|
|
static const u32 adwNeverDummyModels[] =
|
|
{
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// stuff that just doesn't render as a dummy due to being animated objects using skinning etc
|
|
0x28cadfdb, //P_Oil_Pjack_01_FRG_S
|
|
0x5c80b38, //P_Oil_Pjack_02_FRG_S
|
|
0x5f4a5f22, //P_Oil_Pjack_03_FRG_S
|
|
0x21dfb7cf, //p_oil_pjack_01_s
|
|
0x708d300f, //p_oil_pjack_02_s
|
|
0x134f68e5, //p_oil_pjack_03_s
|
|
0x745f3383, //prop_windmill_01
|
|
0x427a3150, //prop_storagetank_02
|
|
0x8973a868, //prop_air_bigradar
|
|
0x3b9e6ecc, //prop_rural_windmill
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// rail junctions - so they can lower when trains are passing despite being some distance away
|
|
0xd639398a, //prop_railway_barrier_01
|
|
0xa9755fff, //prop_railway_barrier_02
|
|
0xc8dad835, //prop_traffic_rail_1c
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// large, low-LOD buoyancy objects which sit at inappropriate heights when in the distance
|
|
0xbf8918de, //prop_jetski_ramp_01
|
|
0x73e498db, //prop_dock_bouy_3
|
|
0xdea4ebf4, //prop_byard_float_01
|
|
0x4653780, //prop_byard_float_02
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// large static props that really should have been baked into the static collisions
|
|
0xbc4649e5, //prop_rub_railwreck_2
|
|
0xbe862050, //prop_portacabin01
|
|
0x2e042597, //prop_container_01c
|
|
0x12bdebf2, //prop_container_03a
|
|
0x69381681, //prop_container_05a
|
|
0xda76fe6e, //prop_container_01a
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// special case stuff
|
|
0x8da1c0e, //prop_juicestand - a ball you can roll across the map
|
|
0xeb2e00e0, //prop_game_clock_02 - clock in the window of the tattoo parlor for family reunion
|
|
0xa49287f8, //p_tumbler_cs2_s tumbler is Michael's house
|
|
0x1d18abd6, //p_whiskey_bottle_s whiskey bottle
|
|
0xe0545565, //prop_tanktrailer_01a
|
|
0x17236aa7, //prop_skip_08a
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// ambient vehicles passing through gates
|
|
0xd8809a3, //prop_fnclink_02gate6_r
|
|
0x5afd248c, //prop_fnclink_02gate6_l
|
|
0x87024c72, //prop_arm_gate_l
|
|
|
|
// mpApartments - Yacht
|
|
0x4fcad2e0, //apa_mp_apa_yacht
|
|
|
|
// Arena Wars - pump jack
|
|
0x6b676d83, //xs_prop_arena_oil_Jack_02a
|
|
|
|
0
|
|
};
|
|
|
|
const u32* pCurrent = &adwNeverDummyModels[0];
|
|
while (*pCurrent)
|
|
{
|
|
u32 index;
|
|
CBaseModelInfo* pModelInfo = (CBaseModelInfo*) fwArchetypeManager::GetArchetypeFromHashKey(*pCurrent, &index);
|
|
if (pModelInfo)
|
|
{
|
|
Displayf("Setting model %s to never dummy", pModelInfo->GetModelName());
|
|
pModelInfo->SetNeverDummyFlag(true);
|
|
}
|
|
pCurrent++;
|
|
}
|
|
}
|
|
|
|
void CFileLoader::MarkArchetypesWhichIntentionallyLeakObjects()
|
|
{
|
|
// usually map objects get removed when the corresponding map data is streamed out.
|
|
// however some frags are fun to play with and push around the map (e.g. a big orange ball that can be pushed about the world etc)
|
|
// so we mark them as being permitted to leak
|
|
//
|
|
// only allowed for permanent archetypes
|
|
static const u32 adwAllowedToLeakModels[] =
|
|
{
|
|
0x8da1c0e, //prop_juicestand - a ball you can roll across the map
|
|
|
|
0
|
|
};
|
|
|
|
const u32* pCurrent = &adwAllowedToLeakModels[0];
|
|
while (*pCurrent)
|
|
{
|
|
u32 index;
|
|
CBaseModelInfo* pModelInfo = (CBaseModelInfo*) fwArchetypeManager::GetArchetypeFromHashKey(*pCurrent, &index);
|
|
if (pModelInfo)
|
|
{
|
|
Displayf("Setting model %s to allow intentional object leaking", pModelInfo->GetModelName());
|
|
pModelInfo->SetLeakObjectsFlag(true);
|
|
}
|
|
pCurrent++;
|
|
}
|
|
}
|
|
|
|
bool CFileLoader::CacheLoadStart(const char* pDatFilename)
|
|
{
|
|
atMap<s32, bool> cacheLoaderArchives;
|
|
|
|
PF_PUSH_STARTUPBAR("Cache Load Init");
|
|
fileloaderDisplayf("CacheLoadStart");
|
|
|
|
USE_MEMBUCKET(MEMBUCKET_PHYSICS);
|
|
|
|
WIN32PC_ONLY(CApp::CheckExit());
|
|
|
|
// CacheLoader attempt (bracketed to clearly define the specific code...
|
|
strCacheLoader::Init(pDatFilename, NULL, SCL_DEFAULT, cacheLoaderArchives);
|
|
// if(CExtraContentManagerSingleton::IsInstantiated() && EXTRACONTENT.GetEnabledContentMask() != 0)
|
|
// strCacheLoader::SetReadOnly();
|
|
PF_START_STARTUPBAR("Cache Load Load");
|
|
bool bCacheLoaded = strCacheLoader::Load();
|
|
PF_START_STARTUPBAR("Update changed static bounds");
|
|
|
|
WIN32PC_ONLY(CApp::CheckExit());
|
|
|
|
g_StaticBoundsStore.UpdateChangedStaticBounds();
|
|
|
|
WIN32PC_ONLY(CApp::CheckExit());
|
|
|
|
PF_POP_STARTUPBAR();
|
|
|
|
return bCacheLoaded;
|
|
} // end of CacheLoader attempt
|
|
|
|
// Cacheloader must save AFTER the IPLs have loaded.
|
|
void CFileLoader::CacheLoadEnd()
|
|
{
|
|
fileloaderDisplayf("CacheLoadEnd");
|
|
|
|
PF_PUSH_STARTUPBAR("Fix up entries after reg");
|
|
INSTANCE_STORE.FixupAllEntriesAfterRegistration(true);
|
|
CManagedImapGroupMgr::MarkManagedImapFiles();
|
|
PF_POP_STARTUPBAR();
|
|
|
|
PF_START_STARTUPBAR("Register IPL Cullbox containers");
|
|
CIplCullBox::RegisterContainers();
|
|
|
|
PF_START_STARTUPBAR("Cache save");
|
|
strCacheLoader::Save();
|
|
|
|
PF_START_STARTUPBAR("Cache shutdown");
|
|
strCacheLoader::Shutdown();
|
|
|
|
|
|
{
|
|
////////////////////////////////////////////////////////////////////////
|
|
// GTAV map only - mark important emissive IPLs to stay in memory - late in the day GTAV hack
|
|
|
|
const s32 downtownEmissiveIndex = g_MapDataStore.FindSlot("dt1_emissive").Get(); // downtown skyscrapers!
|
|
if (downtownEmissiveIndex>0)
|
|
{
|
|
CEntity::ms_DowntownIplIndex = (u32) downtownEmissiveIndex;
|
|
}
|
|
const s32 vinewoodEmissiveIndex = g_MapDataStore.FindSlot("ch2_03").Get(); // vinewood sign!
|
|
if (vinewoodEmissiveIndex>0)
|
|
{
|
|
CEntity::ms_VinewoodIplIndex = (u32) vinewoodEmissiveIndex;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
}
|
|
|
|
}
|
|
|
|
//Post process after IPL files are loaded
|
|
void CFileLoader::PostProcessIplLoad()
|
|
{
|
|
fileloaderDebugf3("PostProcessIplLoad");
|
|
|
|
PF_START_STARTUPBAR("static bounds postRegistration");
|
|
g_StaticBoundsStore.PostRegistration();
|
|
|
|
PF_START_STARTUPBAR("INSTANCE STORE postProcess");
|
|
INSTANCE_STORE.GetBoxStreamer().PostProcess();
|
|
|
|
PF_START_STARTUPBAR("static bounds postProcess");
|
|
g_StaticBoundsStore.GetBoxStreamer().PostProcess();
|
|
|
|
PF_START_STARTUPBAR("metadata postProcess");
|
|
g_fwMetaDataStore.GetBoxStreamer().PostProcess();
|
|
|
|
PF_START_STARTUPBAR("Remove All");
|
|
g_StaticBoundsStore.RemoveAll();
|
|
|
|
PF_START_STARTUPBAR("IPL cull box load");
|
|
CIplCullBox::Load();
|
|
g_PlayerSwitch.LoadSettings();
|
|
}
|
|
|
|
|
|
//
|
|
// name: CFileLoader::LoadLevelInstanceInfo
|
|
// description: Load IPL files after all IDE files have been loaded
|
|
void CFileLoader::LoadLevelInstanceInfo(const char* pDatFilename)
|
|
{
|
|
strStreamingEngine::GetLoader().CallKeepAliveCallback();
|
|
|
|
PF_PUSH_STARTUPBAR(pDatFilename);
|
|
fileloaderDebugf3("LoadLevelInstanceInfo %s", pDatFilename);
|
|
|
|
PROFLOAD_ONLY(pfDummySync());
|
|
PF_START_STARTUPBAR("Reset Level Instance Info");
|
|
PROFLOAD_ONLY(pfDummySync());
|
|
ResetLevelInstanceInfo();
|
|
|
|
PF_PUSH_STARTUPBAR("Load RPF files");
|
|
|
|
PROFLOAD_ONLY(pfDummySync());
|
|
|
|
CVisualEffects::InitDefinitionsPreRpfs();
|
|
|
|
WIN32PC_ONLY(CApp::CheckExit());
|
|
|
|
LoadRpfFiles();
|
|
|
|
WIN32PC_ONLY(CApp::CheckExit());
|
|
|
|
CVisualEffects::InitDefinitionsPostRpfs();
|
|
|
|
RequestPermanentItypFiles();
|
|
|
|
PROFLOAD_ONLY(pfDummySync());
|
|
PROFLOAD_ONLY(snStopCapture());
|
|
|
|
PROFLOAD_ONLY(pfDummySync());
|
|
PROFLOAD_ONLY(pfDummySync());
|
|
|
|
PF_POP_STARTUPBAR();
|
|
|
|
CScaleformMgr::LoadPreallocationInfo(SCALEFORM_PREALLOC_XML_FILENAME);
|
|
|
|
#if !__FINAL
|
|
CStreaming::BeginRecordingStartupSequence();
|
|
#endif // !__FINAL
|
|
CStreaming::ReplayStartupSequenceRecording();
|
|
|
|
// We need to load capsule information prior to loading IDE files as peds reference capsule information
|
|
PF_START_STARTUPBAR("Load Capsule files");
|
|
LoadCapsuleFile();
|
|
|
|
PROFLOAD_ONLY(pfDummySync());
|
|
|
|
//LOAD EXPLOSION DATA
|
|
PF_START_STARTUPBAR("Load Explosion Info File");
|
|
LoadExplosionInfoFiles();
|
|
|
|
PF_START_STARTUPBAR("Load Ped Health files");
|
|
LoadHealthConfigFile();
|
|
|
|
// We need to load component set information prior to loading IDE files as peds reference this
|
|
PF_START_STARTUPBAR("Load Ped Component Cloth file");
|
|
LoadPedComponentClothFile();
|
|
//@@: range FILELOADER_LOADLEVELINSTANCEINFO_LOAD_PED_STUFF {
|
|
|
|
// We need to load component set information prior to loading IDE files as peds reference this
|
|
PF_START_STARTUPBAR("Load Ped Component Set files");
|
|
LoadPedComponentSetsFile();
|
|
|
|
// We need to load component set information prior to loading IDE files as peds reference this
|
|
PF_START_STARTUPBAR("Load Ped IK Settings files");
|
|
LoadPedIKSettingsFile();
|
|
|
|
//@@: } FILELOADER_LOADLEVELINSTANCEINFO_LOAD_PED_STUFF
|
|
|
|
// We need to load component set information prior to loading IDE files as peds reference this
|
|
PF_START_STARTUPBAR("Load Task Data files");
|
|
LoadTaskDataFile();
|
|
|
|
// We need to load special ability information prior to loading IDE files as peds reference them
|
|
PF_START_STARTUPBAR("Load Special Abilities file");
|
|
LoadSpecialAbilitiesFiles();
|
|
|
|
// We need to load brawling style information prior to loading IDE files as peds reference them
|
|
PF_START_STARTUPBAR("Load Brawling Style file");
|
|
LoadBrawlingStyleFiles();
|
|
|
|
// We need to load the motion task data info prior to loading IDE files as peds reference them
|
|
PF_START_STARTUPBAR("Load Motion Task Data files");
|
|
LoadMotionTaskDataFile();
|
|
|
|
PF_START_STARTUPBAR("Load Default Task Data files");
|
|
LoadDefaultTaskDataFile();
|
|
|
|
PF_START_STARTUPBAR("Load Nav Capabilities Data files");
|
|
LoadNavCapabilitiesDataFile();
|
|
|
|
#if ENABLE_HORSE
|
|
PF_START_STARTUPBAR("Load Mount tuning file");
|
|
LoadMountTuneFile();
|
|
|
|
PF_START_STARTUPBAR("Load Horse Reins file");
|
|
LoadHorseReinsFile();
|
|
#endif
|
|
|
|
PF_START_STARTUPBAR("Load Door Type Tuning file");
|
|
LoadDoorTypeTuningFile();
|
|
|
|
PF_START_STARTUPBAR("Load Object Cover Tuning file");
|
|
LoadObjectCoverTuningFile();
|
|
|
|
PF_PUSH_STARTUPBAR("Load .ityp files");
|
|
|
|
CMapFileMgr::GetInstance().LoadGlobalTxdParents();
|
|
|
|
if (!PARAM_PartialDynArch.Get()){
|
|
LoadPermanentItypFiles();
|
|
CMapFileMgr::GetInstance().SetMapFileDependencies(); // need to know permanent .ityps
|
|
g_MapTypesStore.VerifyItypFiles(); // check that all .ityp files have been processed
|
|
MarkArchetypesWhichCannotBeDummy();
|
|
MarkArchetypesWhichIntentionallyLeakObjects();
|
|
} else{
|
|
LoadItypFiles();
|
|
}
|
|
|
|
PF_POP_STARTUPBAR();
|
|
|
|
PF_PUSH_STARTUPBAR("Load Scenario Point Files");
|
|
LoadScenarioPointFiles();
|
|
PF_POP_STARTUPBAR();
|
|
|
|
PF_START_STARTUPBAR("Load Ped Metadata");
|
|
LoadPedMetaData();
|
|
|
|
PF_START_STARTUPBAR("Load Weapon Metadata");
|
|
LoadWeaponMetaData();
|
|
|
|
PF_START_STARTUPBAR("Load Vehicle Metadata");
|
|
LoadVehicleMetaData();
|
|
// Need to Initialize the water fog texture slots after loading RPF Files
|
|
Water::InitFogTextureTxdSlots();
|
|
|
|
fwArchetypeManager::LockPermanentArchetypes();
|
|
|
|
// snStartCapture(); // Necessary if driving Tuner from
|
|
// the command line (ignored otherwise)
|
|
|
|
// DummySync();
|
|
|
|
|
|
// snStopCapture(); // Signal to host app to finalize
|
|
// // // the tuning session
|
|
// //
|
|
// DummySync();
|
|
// DummySync();
|
|
|
|
PF_START_STARTUPBAR("PreLoadIplPostLoadIde");
|
|
PreLoadIplPostLoadIde();
|
|
|
|
WIN32PC_ONLY(CApp::CheckExit());
|
|
|
|
CacheLoadStart(pDatFilename);
|
|
|
|
WIN32PC_ONLY(CApp::CheckExit());
|
|
|
|
PF_START_STARTUPBAR("Time cycle modifier files");
|
|
g_timeCycle.LoadModifierFiles();
|
|
|
|
PF_PUSH_STARTUPBAR("Load IPL files");
|
|
|
|
LoadIplFiles();
|
|
|
|
PF_POP_STARTUPBAR();
|
|
|
|
PF_START_STARTUPBAR("Cache load end");
|
|
|
|
WIN32PC_ONLY(CApp::CheckExit());
|
|
|
|
CacheLoadEnd();
|
|
|
|
WIN32PC_ONLY(CApp::CheckExit());
|
|
|
|
#if __ASSERT
|
|
CDownloadableTextureManager::CheckTXDStoreCapacity();
|
|
#endif
|
|
|
|
CInteriorProxy::Sort();
|
|
CInteriorProxy::AddAllDummyBounds(0);
|
|
|
|
PF_START_STARTUPBAR("Post process IPL Load");
|
|
PostProcessIplLoad();
|
|
|
|
DATAFILEMGR.RemoveMapDataFiles();
|
|
|
|
PF_START_STARTUPBAR("Load All Requested");
|
|
CStreaming::LoadAllRequestedObjects();
|
|
|
|
PF_START_STARTUPBAR("Modelinfo Post Load");
|
|
CModelInfo::PostLoad();
|
|
|
|
PF_START_STARTUPBAR("Load deformable objects file");
|
|
LoadDeformableObjectFile();
|
|
|
|
PF_START_STARTUPBAR("Load tunable objects file");
|
|
LoadTunableObjectFile();
|
|
|
|
CInstancePriority::Init();
|
|
|
|
CMapFileMgr::GetInstance().Cleanup(); // cleanup up all our file meta data now loading is done
|
|
|
|
PF_POP_STARTUPBAR();
|
|
}
|
|
|
|
void CFileLoader::ResetLevelInstanceInfo(void)
|
|
{
|
|
// clear lod trees before loading etc
|
|
g_LodMgr.Reset();
|
|
g_ContainerLodMap.Reset();
|
|
g_MapChangeMgr.Reset();
|
|
CIplCullBox::Reset();
|
|
|
|
CBrawlingStyleManager::Shutdown();
|
|
CHealthConfigInfoManager::Shutdown();
|
|
CDefaultTaskDataManager::Shutdown();
|
|
CMotionTaskDataManager::Shutdown();
|
|
CPedCapsuleInfoManager::Shutdown();
|
|
CPedComponentSetManager::Shutdown();
|
|
CPedComponentClothManager::Shutdown();
|
|
CPedIKSettingsInfoManager::Shutdown();
|
|
CPedNavCapabilityInfoManager::Shutdown();
|
|
CPedPerceptionInfoManager::Shutdown();
|
|
CPlayerSpecialAbilityManager::Shutdown();
|
|
CSlownessZoneManager::Shutdown();
|
|
CTaskDataInfoManager::Shutdown();
|
|
CDoorTuningManager::ShutdownClass();
|
|
CExplosionInfoManager::Shutdown();
|
|
CCoverTuningManager::ShutdownClass();
|
|
}
|
|
|
|
#if __BANK
|
|
|
|
void CFileLoader::InitWidgets()
|
|
{
|
|
if (PARAM_fileloader_tty_windows.Get())
|
|
{
|
|
BANKMGR.CreateOutputWindow("fileloader", "NamedColor:Green");
|
|
BANKMGR.CreateOutputWindow("fileloader_cacheloader", "NamedColor:Green");
|
|
BANKMGR.CreateOutputWindow("fileloader_iplstore", "NamedColor:Green");
|
|
}
|
|
|
|
if(PARAM_fileMountWidgets.Get())
|
|
{
|
|
if( bkBank *pBank = &BANKMGR.CreateBank("Data File Mount", 0, 0, false) )
|
|
{
|
|
pBank->AddButton("Dump valid interfaces list", &CDataFileMount::DebugOutputTable);
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
//
|
|
// name: CFileLoader::LoadAudioGroup
|
|
// description: Load an audio group
|
|
//
|
|
void CFileLoader::LoadAudioGroup(const char* pLine)
|
|
{
|
|
char pedmodel[STORE_NAME_LENGTH];
|
|
char groupname[STORE_NAME_LENGTH];
|
|
s32 headcomponent;
|
|
|
|
if (sscanf(pLine, "%s %s %d", pedmodel, groupname, &headcomponent ) != 3)
|
|
{
|
|
Assert(0);
|
|
}
|
|
|
|
u32 iModelIndex = CModelInfo::GetModelIdFromName(pedmodel).GetModelIndex();
|
|
|
|
Assert(CModelInfo::IsValidModelInfo(iModelIndex));
|
|
if( !CModelInfo::IsValidModelInfo(iModelIndex) )
|
|
return;
|
|
|
|
CPedModelInfo* pPedModelInfo = static_cast<CPedModelInfo*>(CModelInfo::GetBaseModelInfo(fwModelId(strLocalIndex(iModelIndex))));
|
|
|
|
Assert(pPedModelInfo);
|
|
if( pPedModelInfo == NULL )
|
|
return;
|
|
|
|
pPedModelInfo->AddAudioGroupMap(headcomponent, atStringHash(groupname));
|
|
}
|
|
|
|
//
|
|
// name: CFileLoader::Load2dEffect
|
|
// description:
|
|
void CFileLoader::Load2dEffect(const char* pLine)
|
|
{
|
|
char name[STORE_NAME_LENGTH];
|
|
s32 type;
|
|
float x,y,z;
|
|
|
|
float qx, qy, qz, qw; // all data currently gets exported with rotation, but in a lot of cases it gets ignored
|
|
::sscanf(pLine, "%s %f %f %f %d %f %f %f %f", &name[0], &x, &y, &z, &type, &qx, &qy, &qz, &qw);
|
|
|
|
C2dEffect* pEffect = NULL;
|
|
|
|
switch(type)
|
|
{
|
|
case(ET_LIGHT):
|
|
Assertf(0, "Unrecognised 2d effect %d", type);
|
|
break;
|
|
|
|
case(ET_LIGHT_SHAFT):
|
|
{
|
|
Assertf(0, "Unrecognised 2d effect %d", type);
|
|
}
|
|
break;
|
|
|
|
case(ET_PARTICLE):
|
|
{
|
|
Assertf(0, "Unrecognised 2d effect %d", type);
|
|
}
|
|
break;
|
|
|
|
case(ET_EXPLOSION):
|
|
{
|
|
Assertf(0, "Unrecognised 2d effect %d", type);
|
|
}
|
|
break;
|
|
|
|
case ET_PROCEDURALOBJECTS :
|
|
{
|
|
Assertf(0, "Unrecognised 2d effect %d", type);
|
|
break;
|
|
}
|
|
|
|
case ET_COORDSCRIPT :
|
|
{
|
|
// THIS IS STILL AN ACTIVE CODE PATH - FOR FUCKS SAKE!
|
|
{
|
|
pEffect = CModelInfo::GetWorldPointStore().CreateItem(fwFactory::GLOBAL);
|
|
CWorldPointAttr* wp = pEffect->GetWorldPoint();
|
|
|
|
char FullLine[256];
|
|
char seperators[] = " ,\t\n";
|
|
|
|
Assertf(strlen(pLine) < 256, "%s:CFileLoader::Load2dEffect - line for coord script is too long to copy", name);
|
|
strncpy(FullLine, pLine, 256); // make a copy of this string as strtok will destroy it
|
|
|
|
int token_number = 0;
|
|
char *pToken = NULL;
|
|
bool bReadFirstToken = false;
|
|
int num_of_extra_coords = 0;
|
|
|
|
while (token_number <= 10)
|
|
{
|
|
if (bReadFirstToken == false)
|
|
{
|
|
bReadFirstToken = true;
|
|
pToken = strtok( FullLine, seperators );
|
|
Assertf(pToken, "%s:CFileLoader::Load2dEffect - failed to load first token from script coord line for this model", name);
|
|
}
|
|
else
|
|
{
|
|
pToken = strtok( NULL, seperators );
|
|
Assertf(pToken || token_number >= 11, "%s:CFileLoader::Load2dEffect - failed to load token from script coord line for this model", name);
|
|
}
|
|
|
|
if (pToken) // This 'if' can be removed when all have been re-exported with 15 params
|
|
{
|
|
switch (token_number)
|
|
{
|
|
case 0 : // model name
|
|
case 1 : // x offset
|
|
case 2 : // y offset
|
|
case 3 : // z offset
|
|
case 4 : // 2d effect type
|
|
case 5 : // quaternion x
|
|
case 6 : // quaternion y
|
|
case 7 : // quaternion z
|
|
case 8 : // quaternion w
|
|
break;
|
|
|
|
case 9 : // script name
|
|
wp->m_scriptName.SetFromString( pToken );
|
|
break;
|
|
|
|
case 10 : // number of extra coordinates
|
|
num_of_extra_coords = atoi(pToken);
|
|
wp->num_of_extra_coords = (s8) num_of_extra_coords;
|
|
break;
|
|
|
|
}
|
|
}
|
|
token_number++;
|
|
}
|
|
|
|
// Calculate the first orientation
|
|
Matrix34 matRotation;
|
|
matRotation.FromQuaternion(Quaternion(qx, qy, qz, qw));
|
|
float fHeading = rage::Atan2f(-matRotation.b.x, matRotation.b.y);
|
|
wp->extraCoordOrientations[0] = RtoD*fHeading;
|
|
|
|
Assertf(num_of_extra_coords <= MAX_NUMBER_OF_EXTRA_WORLD_POINT_COORDS, "%s:CFileLoader::Load2dEffect - too many extra coords for a script coord attached to this model", name);
|
|
for (int current_extra_coord = 0; current_extra_coord < num_of_extra_coords; current_extra_coord++)
|
|
{
|
|
pToken = strtok( NULL, seperators );
|
|
Assertf(pToken, "%s:CFileLoader::Load2dEffect - failed to load token from script coord line for this model (extra coord x)", name);
|
|
wp->extraCoords[current_extra_coord].x = static_cast<float> (atof(pToken));
|
|
|
|
pToken = strtok( NULL, seperators );
|
|
Assertf(pToken, "%s:CFileLoader::Load2fX, fY, fZ, dEffect - failed to load token from script coord line for this model (extra coord y)", name);
|
|
wp->extraCoords[current_extra_coord].y = static_cast<float> (atof(pToken));
|
|
|
|
pToken = strtok( NULL, seperators );
|
|
Assertf(pToken, "%s:CFileLoader::Load2dEffect - failed to load token from script coord line for this model (extra coord z)", name);
|
|
wp->extraCoords[current_extra_coord].z = static_cast<float> (atof(pToken));
|
|
|
|
pToken = strtok( NULL, seperators );
|
|
Assertf(pToken, "%s:CFileLoader::Load2dEffect - failed to load token from script coord line for this model (orientation)", name);
|
|
wp->extraCoordOrientations[current_extra_coord+1] = static_cast<float> (atof(pToken));
|
|
}
|
|
|
|
pToken = strtok( NULL, seperators );
|
|
Assertf(pToken == NULL, "%s:CFileLoader::Load2dEffect - unexpected token at end of script coord line for this model", name);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case ET_LADDER :
|
|
{
|
|
Assertf(0, "Unrecognised 2d effect %d", type);
|
|
|
|
break;
|
|
}
|
|
|
|
case ET_AUDIOEFFECT:
|
|
{
|
|
Assertf(0, "Unrecognised 2d effect %d", type);
|
|
}
|
|
|
|
break;
|
|
|
|
case ET_SCROLLBAR:
|
|
{
|
|
Assertf(0, "Unrecognised 2d effect %d", type);
|
|
}
|
|
break;
|
|
|
|
case(ET_BUOYANCY):
|
|
{
|
|
Assertf(0, "Unrecognised 2d effect %d", type);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
//temporarily commented out until we get rid of
|
|
//the old 2dfx GRS
|
|
Assertf(0, "Unrecognised 2d effect %d", type);
|
|
|
|
}// end of switch(type)...
|
|
|
|
{
|
|
if(pEffect)
|
|
{
|
|
pEffect->SetPos(Vector3(x,y,z));
|
|
|
|
C2dEffect** ppEffect = NULL;
|
|
|
|
// The ipl (ambient.ipl, scenarios.ipl, worldlights.ipl, worldparticles.ipl contain 2d effects that are not connected to objects
|
|
{
|
|
ppEffect = &CModelInfo::GetWorld2dEffectArray().Append();
|
|
*ppEffect = pEffect;
|
|
}
|
|
|
|
Assert(ppEffect);
|
|
}
|
|
}
|
|
// g_TxdStore.PopCurrentTxd();
|
|
}
|
|
|
|
bool CFileLoader::LoadObjectTypesXml(const char* pLevelName, CDataFileMgr::DataFileType dataType, bool permanent, s32 mapTypeDefIndex /* = fwFactory::GLOBAL */)
|
|
{
|
|
bool success = false;
|
|
#if __DEV
|
|
SetCurrentLoadingFile(pLevelName);
|
|
#endif
|
|
|
|
switch(dataType){
|
|
case(CDataFileMgr::PED_METADATA_FILE) :
|
|
{
|
|
success = CPedModelInfo::LoadPedMetaFile(pLevelName, permanent, mapTypeDefIndex);
|
|
break;
|
|
}
|
|
case(CDataFileMgr::WEAPON_METADATA_FILE) :
|
|
{
|
|
fwPsoStoreLoadInstance instance;
|
|
fwPsoStoreLoader loader = fwPsoStoreLoader::MakeSimpleFileLoader<CWeaponModelInfo::InitDataList>();
|
|
|
|
loader.Load(pLevelName, instance);
|
|
|
|
struct CWeaponModelInfo::InitDataList * pInitDataList = reinterpret_cast<CWeaponModelInfo::InitDataList*>(instance.GetInstance());
|
|
if (instance.IsLoaded() && pInitDataList)
|
|
{
|
|
for(int i=0;i<pInitDataList->m_InitDatas.GetCount();i++)
|
|
{
|
|
CWeaponModelInfo * pModelInfo = CModelInfo::AddWeaponModel(pInitDataList->m_InitDatas[i].m_modelName.c_str(), permanent, mapTypeDefIndex);
|
|
pModelInfo->Init(pInitDataList->m_InitDatas[i]);
|
|
pModelInfo->SetIsTypeObject(true);
|
|
|
|
if (!permanent)
|
|
{
|
|
CModelInfo::PostLoad(pModelInfo);
|
|
}
|
|
}
|
|
success = true;
|
|
}
|
|
loader.Unload(instance);
|
|
|
|
break;
|
|
}
|
|
default:
|
|
fileloaderAssertf(false,"unrecognised xml data type");
|
|
}
|
|
|
|
|
|
#if __DEV
|
|
SetCurrentLoadingFile(NULL);
|
|
#endif
|
|
return success;
|
|
}
|
|
|
|
|
|
//
|
|
// name: CFileLoader::LoadScene
|
|
// description: Load Object instance information from IPL file
|
|
// in: pLevelName = pointer to level name string e.g "INDUSTRIAL"
|
|
//
|
|
void CFileLoader::LoadScene(const char* pFilename)
|
|
{
|
|
fileloaderDebugf3("LoadScene");
|
|
|
|
enum IPLLoadingStatus {
|
|
LOADING_NOTHING,
|
|
LOADING_IGNORE,
|
|
LOADING_INSTANCES,
|
|
LOADING_MULTIBUILDINGS,
|
|
LOADING_POPZONES,
|
|
LOADING_MAPAREAS,
|
|
LOADING_CULLZONES,
|
|
LOADING_OCCLUSION,
|
|
LOADING_GARAGE,
|
|
LOADING_ENTRYEXIT,
|
|
LOADING_PICKUPS,
|
|
LOADING_CARGENERATORS,
|
|
LOADING_STUNTJUMPS,
|
|
LOADING_TIMECYCLEMODS,
|
|
LOADING_AUDIOZONES,
|
|
LOADING_BLOCKS,
|
|
LOADING_MLOAPPEND,
|
|
LOADING_2DEFFECTS,
|
|
LOADING_STREAM_BOXES,
|
|
LOADING_SLOWNESS_ZONES
|
|
};
|
|
|
|
// Displayf("Creating objects from %s...", pFilename);
|
|
fileloaderDebugf1("Creating objects from %s...", pFilename);
|
|
|
|
gWorldMgr.PreScan();
|
|
|
|
char binaryIplName[RAGE_MAX_PATH];
|
|
strcpy(binaryIplName, pFilename);
|
|
char* pDotIndex;
|
|
pDotIndex = strrchr(binaryIplName,'.');
|
|
*pDotIndex = '\0';
|
|
if(ASSET.Exists(binaryIplName, PLACEMENTS_FILE_EXT))
|
|
return;
|
|
|
|
char* pLine;
|
|
IPLLoadingStatus status = LOADING_NOTHING;
|
|
FileHandle fid;
|
|
|
|
fid = CFileMgr::OpenFile(pFilename, "rb");
|
|
Assertf( CFileMgr::IsValidFileHandle(fid), "Can not open '%s'", pFilename);
|
|
if(!CFileMgr::IsValidFileHandle(fid))
|
|
return;
|
|
|
|
#if __DEV
|
|
SetCurrentLoadingFile(pFilename);
|
|
#endif
|
|
|
|
// first, strip out all commas and escape sequence chars, and replace them with spaces
|
|
while ((pLine = CFileMgr::ReadLine(fid)) != NULL)
|
|
{
|
|
// if beginning of line is the end it is empty
|
|
if(*pLine == '\0')
|
|
continue;
|
|
|
|
// ignore lines starting with # they are comments
|
|
if(*pLine == FILELOADER_COMMENT_CHAR)
|
|
continue;
|
|
|
|
if(status == LOADING_NOTHING)
|
|
{
|
|
// 'inst' tag indicates start of object instance section of file
|
|
if(*pLine == 'i' && *(pLine+1) == 'n' && *(pLine+2) == 's' && *(pLine+3) =='t')
|
|
status = LOADING_INSTANCES;
|
|
// 'inst' tag indicates start of object instance section of file
|
|
if(*pLine == 'm' && *(pLine+1) == 'u' && *(pLine+2) == 'l' && *(pLine+3) =='t')
|
|
status = LOADING_MULTIBUILDINGS;
|
|
// 'zone' tag indicates start of population zone objects section of file
|
|
else if(*pLine == 'z' && *(pLine+1) == 'o' && *(pLine+2) == 'n' && *(pLine+3) =='e')
|
|
status = LOADING_POPZONES;
|
|
// 'mzon' tag indicates start of map area objects section of file
|
|
else if (*pLine == 'm' && *(pLine+1) == 'z' && *(pLine+2) == 'o' && *(pLine+3) =='n')
|
|
status = LOADING_MAPAREAS;
|
|
// 'cull' tag indicates start of cullzone objects section of file
|
|
else if(*pLine == 'c' && *(pLine+1) == 'u' && *(pLine+2) == 'l' && *(pLine+3) =='l')
|
|
status = LOADING_CULLZONES;
|
|
// 'occl' tag indicates start of occlusion volumes section of file
|
|
else if(*pLine == 'o' && *(pLine+1) == 'c' && *(pLine+2) == 'c' && *(pLine+3) =='l')
|
|
status = LOADING_OCCLUSION;
|
|
// 'grge' tag indicates start of garage section of file
|
|
else if(*pLine == 'g' && *(pLine+1) == 'r' && *(pLine+2) == 'g' && *(pLine+3) =='e')
|
|
status = LOADING_GARAGE;
|
|
// 'enex' tag indicates start of entry exit section of file
|
|
else if(*pLine == 'e' && *(pLine+1) == 'n' && *(pLine+2) == 'e' && *(pLine+3) =='x')
|
|
status = LOADING_ENTRYEXIT;
|
|
else if(*pLine == 'p' && *(pLine+1) == 'i' && *(pLine+2) == 'c' && *(pLine+3) =='k')
|
|
status = LOADING_PICKUPS;
|
|
else if(*pLine == 'c' && *(pLine+1) == 'a' && *(pLine+2) == 'r' && *(pLine+3) =='s')
|
|
status = LOADING_CARGENERATORS;
|
|
else if(*pLine == 'j' && *(pLine+1) == 'u' && *(pLine+2) == 'm' && *(pLine+3) =='p')
|
|
status = LOADING_STUNTJUMPS;
|
|
else if(*pLine == 't' && *(pLine+1) == 'c' && *(pLine+2) == 'y' && *(pLine+3) =='c')
|
|
status = LOADING_TIMECYCLEMODS;
|
|
else if(*pLine == 'a' && *(pLine+1) == 'u' && *(pLine+2) == 'z' && *(pLine+3) =='o')
|
|
status = LOADING_AUDIOZONES;
|
|
else if(*pLine == 'b' && *(pLine+1) == 'l' && *(pLine+2) == 'o' && *(pLine+3) =='k')
|
|
status = LOADING_BLOCKS;
|
|
else if (*pLine == 'm' && *(pLine+1) == 'l' && *(pLine+2) == 'o' && *(pLine+3) =='+')
|
|
status = LOADING_MLOAPPEND;
|
|
else if (*pLine == '2' && *(pLine+1) == 'd' && *(pLine+2) == 'f' && *(pLine+3) =='x')
|
|
status = LOADING_2DEFFECTS;
|
|
// else if (*pLine == 'r' && *(pLine+1) == 't' && *(pLine+2) == 'f' && *(pLine+3) =='x')
|
|
// status = LOADING_ROOT_SCRIPT;
|
|
else if(*pLine == 'l' && *(pLine+1) == 'o' && *(pLine+2) == 'd' && *(pLine+3) =='m')
|
|
status = LOADING_STREAM_BOXES;
|
|
else if(*pLine == 's' && *(pLine+1) == 'l' && *(pLine+2) == 'o' && *(pLine+3) =='w')
|
|
status = LOADING_SLOWNESS_ZONES;
|
|
|
|
}
|
|
else
|
|
{
|
|
// 'end' tag indicates end of current section
|
|
if(*pLine == 'e' && *(pLine+1) == 'n' && *(pLine+2) == 'd')
|
|
{
|
|
status = LOADING_NOTHING;
|
|
}
|
|
else
|
|
{
|
|
switch(status)
|
|
{
|
|
case LOADING_INSTANCES:
|
|
Assert(0); // IanK
|
|
break;
|
|
case LOADING_MULTIBUILDINGS:
|
|
Assert(0); // IanK
|
|
break;
|
|
case LOADING_POPZONES:
|
|
LoadPopZone(pLine);
|
|
break;
|
|
case LOADING_MAPAREAS:
|
|
LoadMapArea(pLine);
|
|
break;
|
|
case LOADING_CULLZONES:
|
|
LoadCullZone(pLine);
|
|
break;
|
|
case LOADING_OCCLUSION:
|
|
Assertf(0, "Loading occlusion data through IPL's is no longer supported");
|
|
break;
|
|
case LOADING_AUDIOZONES:
|
|
Assert(0); //IanK
|
|
break;
|
|
case LOADING_ENTRYEXIT:
|
|
LoadEntryExit(pLine);
|
|
break;
|
|
case LOADING_GARAGE:
|
|
LoadGarage(pLine);
|
|
break;
|
|
case LOADING_PICKUPS:
|
|
Assert(0); // IanK
|
|
break;
|
|
case LOADING_CARGENERATORS:
|
|
Assert(0); // IanK
|
|
break;
|
|
case LOADING_STUNTJUMPS:
|
|
Assert(0); // IanK
|
|
break;
|
|
case LOADING_TIMECYCLEMODS:
|
|
Assert(0);
|
|
break;
|
|
case LOADING_MLOAPPEND:
|
|
Assert(0); // IanK - JohnW plans to fix this with new map data
|
|
break;
|
|
case LOADING_2DEFFECTS:
|
|
Load2dEffect(pLine);
|
|
break;
|
|
case LOADING_BLOCKS:
|
|
break;
|
|
case LOADING_IGNORE:
|
|
break;
|
|
case LOADING_STREAM_BOXES:
|
|
break;
|
|
case LOADING_SLOWNESS_ZONES:
|
|
Assert(0);
|
|
break;
|
|
|
|
default:
|
|
Assert(0);
|
|
break;
|
|
}
|
|
}
|
|
// If status is still IGNORE then found a line so jump out of reading
|
|
// this file
|
|
if(status == LOADING_IGNORE)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
CFileMgr::CloseFile(fid);
|
|
#if __DEV
|
|
SetCurrentLoadingFile(NULL);
|
|
#endif
|
|
}
|
|
|
|
#define EE_FLAG_RUBBISH (1<<0)
|
|
#define EE_FLAG_OLDSTYLE (1<<1)
|
|
#define EE_FLAG_LINK (1<<2)
|
|
#define EE_FLAG_SHOP (1<<3)
|
|
#define EE_FLAG_SHOP_EXIT (1<<4)
|
|
#define EE_FLAG_CAR_WARP (1<<5)
|
|
#define EE_FLAG_BIKE_WARP (1<<6)
|
|
#define EE_FLAG_MIRROR (1<<7)
|
|
|
|
//
|
|
// name: CFileLoader::LoadEntryExit
|
|
// description: Loads one entry exit from an ipl file
|
|
void CFileLoader::LoadEntryExit(const char* pLine)
|
|
{
|
|
float px,py,pz,prot;
|
|
float wx,wy,wz;
|
|
float spawnx,spawny,spawnz,spawnrot;
|
|
s32 areacode,flags,extracol;
|
|
char cTemp[32];
|
|
char* p_cIndex;
|
|
s32 numRandomPeds = 2;
|
|
s32 openTime = 0;
|
|
s32 shutTime = 24;
|
|
|
|
ASSERT_ONLY( s32 iNumVals = )sscanf(pLine, "%f %f %f %f %f %f %f %f %f %f %f %d %d %s %d %d %d %d",
|
|
&px,&py,&pz,&prot,
|
|
&wx,&wy,&wz,
|
|
&spawnx,&spawny,&spawnz,&spawnrot,
|
|
&areacode,&flags,cTemp,&extracol,
|
|
&numRandomPeds,
|
|
&openTime, &shutTime);
|
|
|
|
|
|
Assertf(iNumVals == 18,"incorrect num args for entry exit");
|
|
|
|
p_cIndex = strrchr(cTemp,'\"');//"
|
|
|
|
if(p_cIndex)
|
|
{
|
|
//if it has a speech mark at the end of the string
|
|
//then it better have one at the start
|
|
|
|
*p_cIndex = '\0';
|
|
|
|
p_cIndex = cTemp;
|
|
p_cIndex++;
|
|
}
|
|
}
|
|
|
|
//
|
|
// name: CFileLoader::LoadGarage
|
|
// description: Loads one garage from an ipl file
|
|
void CFileLoader::LoadGarage(const char* UNUSED_PARAM(pLine))
|
|
{
|
|
//float x1,y1,z1;
|
|
//float x2,y2;
|
|
//float x3,y3;
|
|
//float ztop;
|
|
//s32 flag;
|
|
//s32 type;
|
|
//char cBuffer[GARAGE_NAME_LENGTH + 1];
|
|
|
|
//if(sscanf(pLine, "%f %f %f %f %f %f %f %f %d %d %s", &x1,&y1,&z1,&x2,&y2,&x3,&y3,&ztop,&flag,&type,cBuffer ) != 11)
|
|
// return;
|
|
|
|
//artAssertf(strlen(cBuffer) < 8, "garage name %s should be less than eight characters", cBuffer);
|
|
//CGarages::AddOne(x1, y1, z1, x2, y2, x3, y3, ztop, type, 0, cBuffer, flag);
|
|
}
|
|
|
|
//
|
|
// name: CFileLoader::LoadPopZone
|
|
// description: Load a zone from a line in the IPL
|
|
//
|
|
void CFileLoader::LoadPopZone(const char* pLine)
|
|
{
|
|
char zoneIdNameBuff[STORE_NAME_LENGTH];
|
|
Vector3 min,max;
|
|
char associateTextLabelNameBuff[STORE_NAME_LENGTH];
|
|
s32 zoneCategory;
|
|
|
|
s32 numArgs = sscanf(pLine, "%s %f %f %f %f %f %f %s %d",
|
|
&zoneIdNameBuff[0],
|
|
&min.x, &min.y, &min.z,
|
|
&max.x, &max.y, &max.z,
|
|
&associateTextLabelNameBuff[0],
|
|
&zoneCategory);
|
|
|
|
if (numArgs==8)
|
|
{
|
|
zoneCategory = ZONECAT_NAVIGATION;
|
|
}
|
|
else if (numArgs != 9)
|
|
{
|
|
return;
|
|
}
|
|
|
|
switch (zoneCategory)
|
|
{
|
|
case ZONECAT_NAVIGATION :
|
|
case ZONECAT_LOCAL_NAVIGATION :
|
|
break;
|
|
|
|
default:
|
|
Assertf(0, "CFileLoader::LoadPopZone - expected zoneCategory to be NAVIGATION or LOCAL_NAVIGATION. Setting to NAVIGATION for %s", zoneIdNameBuff);
|
|
zoneCategory = ZONECAT_NAVIGATION;
|
|
break;
|
|
}
|
|
|
|
CPopZones::CreatePopZone(zoneIdNameBuff, Vector3(min.x, min.y, min.z), Vector3(max.x, max.y, max.z), associateTextLabelNameBuff, static_cast<eZoneCategory>(zoneCategory));
|
|
}
|
|
|
|
|
|
//
|
|
// name: CFileLoader::LoadMapArea
|
|
// description: Load a map zone from a line in the IPL
|
|
//
|
|
void CFileLoader::LoadMapArea(const char* pLine)
|
|
{
|
|
Vector3 min,max;
|
|
char BoxName[STORE_NAME_LENGTH];
|
|
u32 HashOfAreaName = 0;
|
|
|
|
s32 numArgs = sscanf(pLine, "%f %f %f %f %f %f %s %u",
|
|
&min.x, &min.y, &min.z,
|
|
&max.x, &max.y, &max.z,
|
|
&BoxName[0], &HashOfAreaName);
|
|
|
|
if(numArgs != 8)
|
|
{
|
|
Assertf(0, "CFileLoader::LoadMapZone - line in maparea.ipl doesn't contain the correct number of values");
|
|
return;
|
|
}
|
|
|
|
CMapAreas::AddAreaBoxToArea(Vector3(min.x, min.y, min.z),Vector3(max.x, max.y, max.z), HashOfAreaName);
|
|
}
|
|
|
|
//
|
|
// name: CFileLoader::LoadCullZone
|
|
// description: Loads one cull zone
|
|
void CFileLoader::LoadCullZone(const char* pLine)
|
|
{
|
|
Vector3 posn;
|
|
float Vec1X, Vec1Y, MinZ, Vec2X, Vec2Y, MaxZ;
|
|
s32 Flags;
|
|
s32 wantedLevelDrop=0;
|
|
float MirrorNormalX, MirrorNormalY, MirrorNormalZ, MirrorV;
|
|
|
|
// First test whether this might be a mirror attribute zone.
|
|
if (sscanf(pLine, "%f %f %f %f %f %f %f %f %f %d %f %f %f %f",
|
|
&posn.x, &posn.y, &posn.z, &Vec1X, &Vec1Y, &MinZ, &Vec2X, &Vec2Y, &MaxZ,
|
|
&Flags, &MirrorNormalX, &MirrorNormalY, &MirrorNormalZ, &MirrorV) == 14)
|
|
{
|
|
CCullZones::AddMirrorAttributeZone(posn,
|
|
Vec1X, Vec1Y, MinZ,
|
|
Vec2X, Vec2Y, MaxZ,
|
|
static_cast<u16>(Flags),
|
|
MirrorV, MirrorNormalX, MirrorNormalY, MirrorNormalZ);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
sscanf(pLine, "%f %f %f %f %f %f %f %f %f %d %d",
|
|
&posn.x, &posn.y, &posn.z, &Vec1X, &Vec1Y, &MinZ, &Vec2X, &Vec2Y, &MaxZ,
|
|
&Flags, &wantedLevelDrop);
|
|
|
|
CCullZones::AddCullZone(posn,
|
|
Vec1X, Vec1Y, MinZ,
|
|
Vec2X, Vec2Y, MaxZ,
|
|
static_cast<u16>(Flags),
|
|
static_cast<s16>(wantedLevelDrop));
|
|
}
|
|
|
|
inline void Accurate_Normalize(Quaternion& q)
|
|
{
|
|
float mag2 = q.Mag2();
|
|
float invSqrtf = invsqrtf_precise(mag2);
|
|
q.Scale(invSqrtf);
|
|
}
|