Files
GTASource/game/modelinfo/ModelInfo.cpp

1883 lines
70 KiB
C++
Raw Permalink Normal View History

2025-02-23 17:40:52 +08:00
//
//
// Filename: ModelInfo.cpp
// Creator: Adam Fowler
// $Author: $
// $Date: $
// $Revision: $
// Description:
//
//
// Rage headers
#include "atl/binmap.h"
#include "diag/art_channel.h"
#include "file/asset.h"
#include "file/packfile.h"
#include "fragment/resourceversions.h"
#include "paging/rscbuilder.h"
#include "system/ipc.h"
#include "grcore/effect.h"
#if __BANK
#include "fragment/tune.h"
#endif // __BANK
// Framework headers
#include "entity/archetypemanager.h"
#include "entity/archetypestreamingmodule.h"
#include "fwtl/pool.h"
#include "entity/entity.h"
#include "fwanimation/animmanager.h"
#include "fwanimation/expressionsets.h"
#include "fwanimation/facialclipsetgroups.h"
#include "fwpheffects/ropedatamanager.h"
#include "entity/archetypemanager.h"
#include "fwutil/xmacro.h"
#include "fwscene/stores/blendshapestore.h"
#include "fwscene/stores/clothstore.h"
#include "fwscene/stores/drawablestore.h"
#include "fwscene/stores/dwdstore.h"
#include "fwscene/stores/expressionsdictionarystore.h"
#include "fwscene/stores/fragmentstore.h"
#include "fwscene/stores/mapdatastore.h"
#include "fwscene/stores/txdstore.h"
#include "fwsys/fileexts.h"
#include "fwsys/metadatastore.h"
#include "fwsys/timer.h"
#include "streaming/streaming_channel.h"
#include "vfx/channel.h"
#include "vfx/ptfx/ptfxmanager.h"
// Game headers
#include "audio/northaudioengine.h"
#include "core/game.h"
#include "cutscene/cutscenemanagernew.h"
#include "game/config.h"
#include "game/modelindices.h"
#include "modelinfo.h"
#include "modelinfo/basemodelinfo.h"
#include "modelinfo/compentitymodelinfo.h"
#include "modelinfo/mlomodelinfo.h"
#include "modelinfo/pedmodelinfo.h"
#include "modelinfo/timemodelinfo.h"
#include "modelinfo/vehiclemodelinfo.h"
#include "modelinfo/weaponmodelinfo.h"
#include "Network/Live/NetworkTelemetry.h"
#include "objects/dummyobject.h"
#include "objects/object.h"
#include "objects/Door.h"
#include "peds/ped.h"
#include "renderer/gtadrawable.h"
#include "renderer/Lights/LightEntity.h"
#include "scene/Building.h"
#include "scene/AnimatedBuilding.h"
#include "peds/ped.h"
#include "vehicles/vehicle.h"
#include "scene/2deffect.h"
#include "scene/loader/MapData.h"
#include "scene/loader/MapData_Extensions.h"
#include "scene/loader/MapData_Buildings.h"
#include "scene/loader/MapData_Composite.h"
#include "scene/loader/MapData_Interiors.h"
#include "streaming/populationstreaming.h"
#include "streaming/streaming.h"
#include "streaming/streamingengine.h"
#include "streaming/streaminginfo.h"
#include "streaming/streamingmodule.h"
#include "system/memory.h"
#include "system/memmanager.h"
#include "vehicles/vehicle.h"
#include "vfx/systems/VfxEntity.h"
#include "task/Scenario/ScenarioPoint.h"
#include "scene/DynamicEntity.h"
#include "fwscene/stores/maptypesstore.h"
#include "scene/ExtraMetadataMgr.h"
#include "Stats/MoneyInterface.h"
STREAMING_OPTIMISATIONS();
//#include "tempColModels.h"
RAGE_DEFINE_CHANNEL(modelinfo)
FW_INSTANTIATE_CLASS_POOL(CArchetypeStreamSlot, 255, atHashString("ArchetypeStreamSlots",0xdc81ceeb)); // only storing 8 bits in baseModelInfo for this!! Arrgh!
// for extension factories
FW_INSTANTIATE_CLASS_POOL(CLightExtension, CONFIGURED_FROM_FILE, atHashString("CLightExtension",0x97930a24));
FW_INSTANTIATE_CLASS_POOL(CDoorExtension, CONFIGURED_FROM_FILE, atHashString("CDoorExtension",0xb4e04aa4));
FW_INSTANTIATE_CLASS_POOL(CSpawnPointOverrideExtension, CONFIGURED_FROM_FILE, atHashString("CSpawnPointOverrideExtension",0xa38f3d93));
u32 CArchetypeStreamSlot::ms_timer = 0;
// archetype factories
static fwArchetypeDynamicFactory<CBaseModelInfo> gBaseModelStore;
static fwArchetypeDynamicFactory<CTimeModelInfo> gTimeModelStore;
static fwArchetypeDynamicFactory<CMloModelInfo> gMloModelStore;
static fwArchetypeDynamicFactory<CCompEntityModelInfo> gCompEntityModelStore;
static fwArchetypeDynamicFactory<CWeaponModelInfo> gWeaponModelStore;
static fwArchetypeDynamicFactory<CVehicleModelInfo> gVehicleModelStore;
static fwArchetypeDynamicFactory<CPedModelInfo> gPedModelStore;
// Archetype Extensions
static fwArchetypeExtensionFactory<CLadderInfo> gLadderStore2;
static fwArchetypeExtensionFactory<CProcObjAttr> gProcObjStore2;
static fwArchetypeExtensionFactory<CParticleAttr> gParticleStore2;
static fwArchetypeExtensionFactory<CExplosionAttr> gExplosionStore2;
static fwArchetypeExtensionFactory<CDecalAttr> gDecalStore2;
static fwArchetypeExtensionFactory<CWindDisturbanceAttr> gWindDisturbanceStore2;
static fwArchetypeExtensionFactory<CLightShaftAttr> gLightShaftStore2;
static fwArchetypeExtensionFactory<CScrollBarAttr> gScrollStore2;
static fwArchetypeExtensionFactory<CSpawnPoint> gSpawnPointStore2;
static fwArchetypeExtensionFactory<CBuoyancyAttr> gBuoyancyStore2;
static fwArchetypeExtensionFactory<CAudioAttr> gAudioStore2;
static fwArchetypeExtensionFactory<CWorldPointAttr> gWorldPointStore2;
static fwArchetypeExtensionFactory<CExpressionExtension> gExpressionExtensionStore2;
static fwArchetypeExtensionFactory<CAudioCollisionInfo> gAudioCollisionStore2;
// ---
// 2d effects free in world
// not a factory, probably shouldn't be in here...
atArray<C2dEffect*> CModelInfo::ms_World2dEffectArray;
// Entity Extensions
static fwExtensionPoolFactory<CDoorExtension> gDoorExtensionStore;
static fwExtensionPoolFactory<CLightExtension> gLightExtensionStore;
static fwExtensionPoolFactory<CSpawnPointOverrideExtension> gSpawnPointOverrideExtensionStore;
static fwExtensionPoolFactory<fwClothCollisionsExtension> gClothCollisionsStore;
// copied out data - looking for mods
const u32 obfuscationMask = 0x5695a421;
u32 CModelInfo::ms_obfMaleMPPlayerModelId = 0;
u32 CModelInfo::ms_obfFemaleMPPlayerModelId = 0;
//default audio model collision settings id
const u32 g_defaultAudModelCollisions = ATSTRINGHASH("MOD_DEFAULT", 0x05f03e8c2);
//
// name: CModelInfoStreamingModule
// description: Streaming Module class. This is the interface to the streaming system for modelinfos
class CModelInfoStreamingModule : public fwArchetypeStreamingModule
{
public:
CModelInfoStreamingModule() : fwArchetypeStreamingModule(fwArchetypeManager::GetMaxArchetypeIndex()) {}
virtual strLocalIndex Register(const char* name);
virtual strLocalIndex FindSlot(const char* name) const;
virtual void GetModelMapTypeIndex(strLocalIndex slotIndex, strIndex& retIndex) const;
virtual int GetDependencies(strLocalIndex index, strIndex *pIndices, int indexArraySize) const;
virtual void Remove(strLocalIndex index);
virtual void RemoveSlot(strLocalIndex index);
virtual bool Load(strLocalIndex index, void* object, int size);
private:
void GetExpressionSetDependencies(const fwMvExpressionSetId &expressionSetId, strIndex *pIndices, int &count, int indexArraySize, strIndex streamingIndex) const;
void GetClipSetDependencies(const fwMvClipSetId &clipSetId, strIndex *pIndices, int &count, int indexArraySize, strIndex streamingIndex) const;
};
// --- CModelInfoStreamingModule ---------------------------------------------------------------------------------------
strLocalIndex CModelInfoStreamingModule::FindSlot(const char* name) const
{
fwModelId modelId;
CBaseModelInfo* pModelInfo = CModelInfo::GetBaseModelInfoFromName(name, &modelId);
if(pModelInfo)
return strLocalIndex(modelId.GetModelIndex());
return strLocalIndex(-1);
}
strLocalIndex CModelInfoStreamingModule::Register(const char* UNUSED_PARAM(name))
{
Assert(false);
return strLocalIndex(-1);
}
void CModelInfoStreamingModule::RemoveSlot(strLocalIndex UNUSED_PARAM(index))
{
Assert(false);
}
void CModelInfoStreamingModule::GetModelMapTypeIndex(strLocalIndex slotIndex, strIndex& retIndex) const
{
if (CBaseModelInfo* pModelInfo = CModelInfo::GetModelInfoFromLocalIndex(slotIndex.Get()))
{
const fwModelId& modelId = fwArchetypeManager::LookupModelId((fwArchetype*)pModelInfo);
if (modelId.IsValid())
{
strLocalIndex mapTypeIndex = modelId.GetMapTypeDefIndex();
if (mapTypeIndex.IsValid() && mapTypeIndex.Get() != fwModelId::TF_INVALID)
retIndex = g_MapTypesStore.GetStreamingIndex(mapTypeIndex);
}
}
}
int CModelInfoStreamingModule::GetDependencies(strLocalIndex index, strIndex *pIndices, int indexArraySize) const
{
Assert(index.Get() >= 0);
s32 count = fwArchetypeStreamingModule::GetDependencies(index, pIndices, indexArraySize);
CBaseModelInfo* pModelInfo = CModelInfo::GetModelInfoFromLocalIndex(index.Get());
modelinfoAssert(pModelInfo);
strIndex streamingIndex = GetStreamingIndex(index);
strLocalIndex clipDictionaryIndex = pModelInfo->GetClipDictionaryIndex();
if (clipDictionaryIndex != -1) {
AddDependencyOutput(pIndices, count, g_ClipDictionaryStore.GetStreamingIndex(clipDictionaryIndex), indexArraySize, streamingIndex);
}
// check if expression data file is actually in the dictionary before making it dependent
strLocalIndex expressionFileIndex = strLocalIndex(pModelInfo->GetExpressionDictionaryIndex());
if (expressionFileIndex != -1)
{
AddDependencyOutput(pIndices, count, g_ExpressionDictionaryStore.GetStreamingIndex(expressionFileIndex), indexArraySize, streamingIndex);
}
fwMvExpressionSetId expressionSet = pModelInfo->GetExpressionSet();
if (expressionSet!=EXPRESSION_SET_ID_INVALID)
{
// If using expression sets, get all the dependencies
GetExpressionSetDependencies(expressionSet, pIndices, count, indexArraySize, streamingIndex);
}
// main particle asset dependency
u32 ptfxAssetSlot = pModelInfo->GetPtFxAssetSlot();
if (ptfxAssetSlot != -1)
{
AddDependencyOutput(pIndices, count, ptfxManager::GetAssetStore().GetStreamingIndex(strLocalIndex(ptfxAssetSlot)), indexArraySize, streamingIndex);
}
if (pModelInfo->GetModelType() == MI_TYPE_BASE)
{
// If the model has an expression extension update
// the expression dictionary index and the expression hash
// the creature metadata
GET_2D_EFFECTS_NOLIGHTS(pModelInfo);
for(s32 effect = 0; effect < iNumEffects; effect++)
{
if((*pa2dEffects)[effect] != NULL && (*pa2dEffects)[effect]->GetType() == ET_EXPRESSION)
{
CExpressionExtension* pExpressionExtension = (*pa2dEffects)[effect]->GetExpression();
if (pExpressionExtension)
{
if (pExpressionExtension->m_expressionDictionaryName.IsNotNull() && pExpressionExtension->m_expressionName.IsNotNull())
{
pModelInfo->SetExpressionDictionaryIndex(pExpressionExtension->m_expressionDictionaryName.GetCStr());
pModelInfo->SetExpressionHash(pExpressionExtension->m_expressionName.GetCStr());
}
if (pExpressionExtension->m_creatureMetadataName.IsNotNull())
{
pModelInfo->SetCreatureMetadataFile(pExpressionExtension->m_creatureMetadataName.GetCStr());
}
}
}
}
// check if expression data file is actually in the dictionary before making it dependent
strLocalIndex expressionFileIndex = pModelInfo->GetExpressionDictionaryIndex();
if (expressionFileIndex != -1)
{
AddDependencyOutput(pIndices, count, g_ExpressionDictionaryStore.GetStreamingIndex(expressionFileIndex), indexArraySize, streamingIndex);
}
// check if creatureMetadata file is actually exists before making it dependent
strLocalIndex creatureMetadataFileIndex = strLocalIndex(pModelInfo->GetCreatureMetadataFileIndex());
if (creatureMetadataFileIndex != -1)
{
AddDependencyOutput(pIndices, count, g_fwMetaDataStore.GetStreamingIndex(creatureMetadataFileIndex), indexArraySize, streamingIndex);
}
}
if (pModelInfo->GetModelType() == MI_TYPE_PED)
{
CPedModelInfo *pPedModelInfo = (CPedModelInfo *) pModelInfo;
// check if props file is actually in the dictionary before making it dependent
strLocalIndex propsFileIndex = strLocalIndex(pModelInfo->GetPropsFileIndex());
if (propsFileIndex != -1 && pModelInfo->GetModelType() == MI_TYPE_PED && g_DwdStore.IsObjectInImage(propsFileIndex))
{
AddDependencyOutput(pIndices, count, g_DwdStore.GetStreamingIndex(propsFileIndex), indexArraySize, streamingIndex);
}
// check if drawable file is actually in the dictionary before making it dependent
strLocalIndex pedCompFileIndex = strLocalIndex(pPedModelInfo->GetPedComponentFileIndex());
if (pedCompFileIndex != -1 && g_DwdStore.IsObjectInImage(pedCompFileIndex))
{
AddDependencyOutput(pIndices, count, g_DwdStore.GetStreamingIndex(pedCompFileIndex), indexArraySize, streamingIndex);
}
#if ENABLE_BLENDSHAPES
// check if blendshape file is actually in the dictionary before making it dependent
s32 blendShapeFileIndex = pModelInfo->GetBlendShapeFileIndex();
if(blendShapeFileIndex != -1 && g_BlendShapeStore.IsObjectInImage(blendShapeFileIndex))
{
AddDependencyOutput(pIndices, count, g_BlendShapeStore.GetStreamingIndex(blendShapeFileIndex), indexArraySize, streamingIndex);
}
#endif // ENABLE_BLENDSHAPES
// check if meta data file is actually in the dictionary before making it dependent
#if LIVE_STREAMING
if (pPedModelInfo->GetNumPedMetaDataFiles() == 0)
pPedModelInfo->SetPedMetaDataFile(pPedModelInfo->GetModelName());
#endif // LIVE_STREAMING
for (s32 meta = 0; meta < pPedModelInfo->GetNumPedMetaDataFiles(); ++meta)
if (pPedModelInfo->GetPedMetaDataFileIndex(meta) != -1)
AddDependencyOutput(pIndices, count, g_fwMetaDataStore.GetStreamingIndex(strLocalIndex(pPedModelInfo->GetPedMetaDataFileIndex(meta))), indexArraySize, streamingIndex);
atFixedArray<SPedDLCMetaFileQueryData, STREAMING_MAX_DEPENDENCIES> creatureIndicesToLoad;
EXTRAMETADATAMGR.GetCreatureMetaDataIndices(pPedModelInfo, creatureIndicesToLoad);
for (u32 cmIdx = 0; cmIdx < creatureIndicesToLoad.GetCount(); cmIdx++)
{
// check if creatureMetadata data file is actually in the dictionary before making it dependent
strLocalIndex creatureMetadataFileIndex = strLocalIndex(creatureIndicesToLoad[cmIdx].m_storeIndex);
if (creatureMetadataFileIndex != -1)
{
AddDependencyOutput(pIndices, count, g_fwMetaDataStore.GetStreamingIndex(creatureMetadataFileIndex), indexArraySize, streamingIndex);
}
}
// add the strafe movement anim set
strLocalIndex clothFileIndex = g_ClothStore.FindSlotFromHashKey(pModelInfo->GetModelNameHash());
if (clothFileIndex != -1)
{
AddDependencyOutput(pIndices, count, g_ClothStore.GetStreamingIndex(clothFileIndex), indexArraySize, streamingIndex);
}
// Facial Clipset Group dependencies
// We only care about the base clipset as a dependency. The variations are optional and will be streamed in on demand.
fwFacialClipSetGroup* pFacialClipSetGroup = fwFacialClipSetGroupManager::GetFacialClipSetGroup(pPedModelInfo->GetFacialClipSetGroupId());
if (pFacialClipSetGroup)
{
fwMvClipSetId facialBaseClipSetId(pFacialClipSetGroup->GetBaseClipSetName());
Assertf(fwClipSetManager::GetClipSet(facialBaseClipSetId), "%s:Unrecognised facial base clipset", pFacialClipSetGroup->GetBaseClipSetName().GetCStr());
GetClipSetDependencies(facialBaseClipSetId, pIndices, count, indexArraySize, streamingIndex);
}
GetClipSetDependencies(pPedModelInfo->GetMovementClipSet(), pIndices, count, indexArraySize, streamingIndex);
for(s32 i = 0; i < pPedModelInfo->GetMovementClipSets().GetCount(); i++)
{
GetClipSetDependencies(pPedModelInfo->GetMovementClipSets()[i], pIndices, count, indexArraySize, streamingIndex);
}
GetClipSetDependencies(pPedModelInfo->GetStrafeClipSet(), pIndices, count, indexArraySize, streamingIndex);
GetClipSetDependencies(pPedModelInfo->GetInjuredStrafeClipSet(), pIndices, count, indexArraySize, streamingIndex);
//GetClipSetDependencies(pPedModelInfo->GetStealthClipSet(), pIndices, count, indexArraySize, streamingIndex);
GetClipSetDependencies(pPedModelInfo->GetFullBodyDamageClipSet(), pIndices, count, indexArraySize, streamingIndex);
GetClipSetDependencies(pPedModelInfo->GetAdditiveDamageClipSet(), pIndices, count, indexArraySize, streamingIndex);
}
else if(pModelInfo->GetModelType() == MI_TYPE_VEHICLE)
{
// Maybe could just have a virtual function on base model info to fill this out for all different types?
strIndex iVehicleDeps[STREAMING_MAX_DEPENDENCIES];
CVehicleModelInfo* vmi = (CVehicleModelInfo*)pModelInfo;
int iVehicleCount = vmi->GetStreamingDependencies(iVehicleDeps,STREAMING_MAX_DEPENDENCIES);
// Copy over dependencies
for(int i = 0; i < iVehicleCount; i++)
{
AddDependencyOutput(pIndices, count, iVehicleDeps[i], indexArraySize, streamingIndex);
}
if (vmi->NeedsRopeTexture())
{
strLocalIndex txdSlot = g_TxdStore.FindSlot(ropeDataManager::GetRopeTxdName());
if (txdSlot != -1)
AddDependencyOutput(pIndices, count, g_TxdStore.GetStreamingIndex(txdSlot), indexArraySize, streamingIndex);
}
}
return count;
}
void CModelInfoStreamingModule::Remove(strLocalIndex index)
{
CBaseModelInfo* pModelInfo = CModelInfo::GetModelInfoFromLocalIndex(index.Get());
modelinfoAssertf(pModelInfo, "Trying to remove a model that doesn't exist");
//modelinfoAssert(pModelInfo->GetHasLoaded());
// The following bit of code tells the PopulationStreaming a ped/vehicle has been loaded out.
gPopStreaming.ModelHasBeenStreamedOut(index.Get());
// clean up the allocated stuff which we add on top of the base drawable and fragments
switch (pModelInfo->GetDrawableType())
{
case CBaseModelInfo::DT_FRAGMENT:
pModelInfo->DeleteMasterFragData(); // this will clear drawable too...
break;
case CBaseModelInfo::DT_DRAWABLE:
case CBaseModelInfo::DT_DRAWABLEDICTIONARY:
pModelInfo->DeleteMasterDrawableData();
break;
default:
break;
}
pModelInfo->SetHasLoaded(false);
}
// the dependencies for this model info are satisfied. Initialise the master object and register with population
bool CModelInfoStreamingModule::Load(strLocalIndex index, void* object, int size)
{
bool result = fwArchetypeStreamingModule::Load(index, object, size);
if (result) {
CBaseModelInfo* pModelInfo = CModelInfo::GetModelInfoFromLocalIndex(index.Get());
modelinfoAssert(pModelInfo);
switch (pModelInfo->GetDrawableType()) {
case fwArchetype::DT_DRAWABLE:
case fwArchetype::DT_DRAWABLEDICTIONARY:
pModelInfo->InitMasterDrawableData(index.Get());
break;
case fwArchetype::DT_FRAGMENT:
pModelInfo->InitMasterFragData(index.Get());
break;
default:
break;
}
// The following bit of code tells the PopulationStreaming a ped/vehicle has been loaded in.
gPopStreaming.ModelHasBeenStreamedIn(index.Get());
}
return result;
}
void CModelInfoStreamingModule::GetExpressionSetDependencies(const fwMvExpressionSetId &expressionSetId, strIndex *pIndices, int &count, int indexArraySize, strIndex streamingIndex) const
{
fwExpressionSet* pExpressionSet = fwExpressionSetManager::GetExpressionSet(expressionSetId);
if (pExpressionSet)
{
strLocalIndex index = strLocalIndex(g_ExpressionDictionaryStore.FindSlotFromHashKey(pExpressionSet->GetDictionaryName()));
// If cannot find slot then create one.
if(index == -1)
{
index = g_ExpressionDictionaryStore.AddSlot(pExpressionSet->GetDictionaryName());
}
else
{
Assertf(!stricmp(pExpressionSet->GetDictionaryName().GetCStr(), g_ExpressionDictionaryStore.GetName(index)), "%s:Hash name clash", pExpressionSet->GetDictionaryName().GetCStr());
}
if (index != -1)
{
AddDependencyOutput(pIndices, count, g_ExpressionDictionaryStore.GetStreamingIndex(index), indexArraySize, streamingIndex);
}
}
}
void CModelInfoStreamingModule::GetClipSetDependencies(const fwMvClipSetId &clipSetId, strIndex *pIndices, int &count, int indexArraySize, strIndex streamingIndex) const
{
fwClipSet* pClipSet = fwClipSetManager::GetClipSet(clipSetId);
if (pClipSet)
{
do
{
strLocalIndex dictionaryIndex = pClipSet->GetClipDictionaryIndex();
if (dictionaryIndex != -1)
{
const fwClipDictionaryMetadata *pClipDictionaryMetadata = fwClipSetManager::GetClipDictionaryMetadata(pClipSet->GetClipDictionaryName());
if (pClipDictionaryMetadata == NULL)
{
// It is valid not to have a clipdictionary entry it implies streaming
AddDependencyOutput(pIndices, count, g_ClipDictionaryStore.GetStreamingIndex(dictionaryIndex), indexArraySize, streamingIndex);
}
else if (pClipDictionaryMetadata && !(pClipDictionaryMetadata->GetStreamingPolicy() & SP_SINGLEPLAYER_RESIDENT))
{
AddDependencyOutput(pIndices, count, g_ClipDictionaryStore.GetStreamingIndex(dictionaryIndex), indexArraySize, streamingIndex);
}
}
pClipSet = pClipSet->GetFallbackSet();
} while (pClipSet);
}
}
//
// name: PrintModelInfoStoreUsage
// description: Print how many of each modelinfo there are
void CModelInfo::PrintModelInfoStoreUsage()
{
modelinfoDisplayf("Base ModelInfo %d", gBaseModelStore.GetCount(fwFactory::GLOBAL));
modelinfoDisplayf("Time ModelInfo %d", gTimeModelStore.GetCount(fwFactory::GLOBAL));
modelinfoDisplayf("Weapon ModelInfo %d", gWeaponModelStore.GetCount(fwFactory::GLOBAL));
modelinfoDisplayf("Vehicle ModelInfo %d", gVehicleModelStore.GetCount(fwFactory::GLOBAL));
modelinfoDisplayf("Ped ModelInfo %d", gPedModelStore.GetCount(fwFactory::GLOBAL));
modelinfoDisplayf("World 2dEffect %d", ms_World2dEffectArray.GetCount());
modelinfoDisplayf("Mlo ModelInfo %d", gMloModelStore.GetCount(fwFactory::GLOBAL));
modelinfoDisplayf("Comp Entity model info %d", gCompEntityModelStore.GetCount(fwFactory::GLOBAL));
}
void CModelInfo::Init(unsigned initMode)
{
if(initMode == INIT_CORE)
{
fwTransform::InitPools();
fwArchetypeManager::Init(MI_HIGHEST_FACTORY_ID);
fwExtensionManager::Init(EXT_HIGHEST_FACTORY_ID);
const CModelInfoConfig& cfgModel = CGameConfig::Get().GetConfigModelInfo();
const C2dEffectConfig& cfg2d = CGameConfig::Get().GetConfig2dEffects();
const CExtensionConfig& cfgExt = CGameConfig::Get().GetConfigExtensions();
{
RAGE_TRACK(ModelInfoStore);
gBaseModelStore.Init( fwArchetypeManager::GetMaxArchetypeIndex() );
gTimeModelStore.Init( cfgModel.m_MaxTimeModelInfos );
gWeaponModelStore.Init( cfgModel.m_MaxWeaponModelInfos );
gVehicleModelStore.Init( cfgModel.m_MaxVehicleModelInfos );
gPedModelStore.Init( cfgModel.m_MaxPedModelInfos );
gMloModelStore.Init( cfgModel.m_MaxMloModelInfos );
gCompEntityModelStore.Init( cfgModel.m_MaxCompEntityModelInfos );
fwArchetypeManager::RegisterArchetypeFactory( MI_TYPE_BASE, gBaseModelStore );
fwArchetypeManager::RegisterArchetypeFactory( MI_TYPE_TIME, gTimeModelStore );
fwArchetypeManager::RegisterArchetypeFactory( MI_TYPE_WEAPON, gWeaponModelStore );
fwArchetypeManager::RegisterArchetypeFactory( MI_TYPE_VEHICLE, gVehicleModelStore );
fwArchetypeManager::RegisterArchetypeFactory( MI_TYPE_PED, gPedModelStore );
fwArchetypeManager::RegisterArchetypeFactory( MI_TYPE_MLO, gMloModelStore );
fwArchetypeManager::RegisterArchetypeFactory( MI_TYPE_COMPOSITE, gCompEntityModelStore );
fwMapTypes::AssociateArchetypeDef(CBaseArchetypeDef::parser_GetStaticStructure()->GetNameHash(), MI_TYPE_BASE);
fwMapTypes::AssociateArchetypeDef(CTimeArchetypeDef::parser_GetStaticStructure()->GetNameHash(), MI_TYPE_TIME);
fwMapTypes::AssociateArchetypeDef(CMloArchetypeDef::parser_GetStaticStructure()->GetNameHash(), MI_TYPE_MLO);
fwMapTypes::AssociateArchetypeDef(CCompositeEntityArchetypeDef::parser_GetStaticStructure()->GetNameHash(), MI_TYPE_COMPOSITE);
{
#if (__PS3 || __XENON) && !__TOOL && !__RESOURCECOMPILER
sysMemAutoUseFragCacheMemory mem;
#endif
fwArchetypeManager::GetArchetypeFactory(MI_TYPE_BASE)->AddStorageBlock(fwFactory::GLOBAL, cfgModel.m_MaxBaseModelInfos); // to handle portal and light archetypes
fwArchetypeManager::GetArchetypeFactory(MI_TYPE_COMPOSITE)->AddStorageBlock(fwFactory::GLOBAL, cfgModel.m_MaxCompEntityModelInfos);
fwArchetypeManager::GetArchetypeFactory(MI_TYPE_WEAPON)->AddStorageBlock(fwFactory::GLOBAL, cfgModel.m_MaxWeaponModelInfos);
fwArchetypeManager::GetArchetypeFactory(MI_TYPE_VEHICLE)->AddStorageBlock(fwFactory::GLOBAL, cfgModel.m_MaxVehicleModelInfos);
fwArchetypeManager::GetArchetypeFactory(MI_TYPE_PED)->AddStorageBlock(fwFactory::GLOBAL, cfgModel.m_MaxPedModelInfos);
}
}
{
RAGE_TRACK(2DEffectStore);
ms_World2dEffectArray.Reset();
ms_World2dEffectArray.Reserve(cfg2d.m_MaxEffectsWorld2d );
}
{
RAGE_TRACK(2DEffects);
gLadderStore2.Init( cfg2d.m_MaxAttrsLadder );
gProcObjStore2.Init( cfg2d.m_MaxAttrsProcObj );
gParticleStore2.Init( cfg2d.m_MaxAttrsParticle );
gExplosionStore2.Init( cfg2d.m_MaxAttrsExplosion );
gDecalStore2.Init( cfg2d.m_MaxAttrsDecal );
gWindDisturbanceStore2.Init( cfg2d.m_MaxAttrsWindDisturbance );
gLightShaftStore2.Init( cfg2d.m_MaxAttrsLightShaft );
gScrollStore2.Init( cfg2d.m_MaxAttrsScrollBar );
gSpawnPointStore2.Init( cfg2d.m_MaxAttrsSpawnPoint );
gBuoyancyStore2.Init( cfg2d.m_MaxAttrsBuoyancy );
gAudioStore2.Init( cfg2d.m_MaxAttrsAudio );
gWorldPointStore2.Init( cfg2d.m_MaxAttrsWorldPoint );
gExpressionExtensionStore2.Init( cfgExt.m_MaxExpressionExtensions );
gAudioCollisionStore2.Init(cfg2d.m_MaxAttrsAudioCollision);
fwArchetypeManager::Register2dEffectFactory( EXT_TYPE_LADDER, gLadderStore2);
fwArchetypeManager::Register2dEffectFactory( EXT_TYPE_PROCOBJ, gProcObjStore2);
fwArchetypeManager::Register2dEffectFactory( EXT_TYPE_EXPLOSION, gExplosionStore2);
fwArchetypeManager::Register2dEffectFactory( EXT_TYPE_PARTICLE, gParticleStore2);
fwArchetypeManager::Register2dEffectFactory( EXT_TYPE_DECAL, gDecalStore2);
fwArchetypeManager::Register2dEffectFactory( EXT_TYPE_WINDDISTURBANCE, gWindDisturbanceStore2);
fwArchetypeManager::Register2dEffectFactory( EXT_TYPE_LIGHTSHAFT, gLightShaftStore2);
fwArchetypeManager::Register2dEffectFactory( EXT_TYPE_SCROLL, gScrollStore2);
fwArchetypeManager::Register2dEffectFactory( EXT_TYPE_SPAWNPOINT, gSpawnPointStore2);
fwArchetypeManager::Register2dEffectFactory( EXT_TYPE_BUOYANCY, gBuoyancyStore2);
fwArchetypeManager::Register2dEffectFactory( EXT_TYPE_AUDIO, gAudioStore2);
fwArchetypeManager::Register2dEffectFactory( EXT_TYPE_WORLDPOINT, gWorldPointStore2);
fwArchetypeManager::Register2dEffectFactory( EXT_TYPE_EXPRESSION, gExpressionExtensionStore2);
fwArchetypeManager::Register2dEffectFactory( EXT_TYPE_AUDIO_COLLISIONS, gAudioCollisionStore2);
CMapTypes::AssociateExtensionDef(CExtensionDefLadder::parser_GetStaticStructure()->GetNameHash(), EXT_TYPE_LADDER);
CMapTypes::AssociateExtensionDef(CExtensionDefProcObject::parser_GetStaticStructure()->GetNameHash(), EXT_TYPE_PROCOBJ);
CMapTypes::AssociateExtensionDef(CExtensionDefExplosionEffect::parser_GetStaticStructure()->GetNameHash(), EXT_TYPE_EXPLOSION);
CMapTypes::AssociateExtensionDef(CExtensionDefParticleEffect::parser_GetStaticStructure()->GetNameHash(), EXT_TYPE_PARTICLE);
CMapTypes::AssociateExtensionDef(CExtensionDefDecal::parser_GetStaticStructure()->GetNameHash(), EXT_TYPE_DECAL);
CMapTypes::AssociateExtensionDef(CExtensionDefWindDisturbance::parser_GetStaticStructure()->GetNameHash(), EXT_TYPE_WINDDISTURBANCE);
CMapTypes::AssociateExtensionDef(CExtensionDefLightShaft::parser_GetStaticStructure()->GetNameHash(), EXT_TYPE_LIGHTSHAFT);
CMapTypes::AssociateExtensionDef(CExtensionDefScrollbars::parser_GetStaticStructure()->GetNameHash(), EXT_TYPE_SCROLL);
CMapTypes::AssociateExtensionDef(CExtensionDefBuoyancy::parser_GetStaticStructure()->GetNameHash(), EXT_TYPE_BUOYANCY);
CMapTypes::AssociateExtensionDef(CExtensionDefAudioEmitter::parser_GetStaticStructure()->GetNameHash(), EXT_TYPE_AUDIO);
CMapTypes::AssociateExtensionDef(CExtensionDefSpawnPoint::parser_GetStaticStructure()->GetNameHash(), EXT_TYPE_SPAWNPOINT);
CMapTypes::AssociateExtensionDef(CExtensionDefExpression::parser_GetStaticStructure()->GetNameHash(), EXT_TYPE_EXPRESSION);
CMapTypes::AssociateExtensionDef(CExtensionDefAudioCollisionSettings::parser_GetStaticStructure()->GetNameHash(), EXT_TYPE_AUDIO_COLLISIONS);
{
#if (__PS3 || __XENON) && !__TOOL && !__RESOURCECOMPILER
sysMemAutoUseFragCacheMemory mem;
#endif
fwArchetypeManager::Get2dEffectFactory(EXT_TYPE_SPAWNPOINT)->AddStorageBlock(fwFactory::GLOBAL, cfg2d.m_MaxAttrsSpawnPoint);
fwArchetypeManager::Get2dEffectFactory(EXT_TYPE_WORLDPOINT)->AddStorageBlock(fwFactory::GLOBAL, cfg2d.m_MaxAttrsWorldPoint);
}
}
{
RAGE_TRACK(Extensions);
gDoorExtensionStore.Init( 0 );
gLightExtensionStore.Init( 0 );
gSpawnPointOverrideExtensionStore.Init( 0 );
gClothCollisionsStore.Init(0);
CDoorExtension::InitPool(cfgExt.m_MaxDoorExtensions, MEMBUCKET_WORLD);
CLightExtension::InitPool(cfgExt.m_MaxLightExtensions, MEMBUCKET_WORLD);
CSpawnPointOverrideExtension::InitPool(cfgExt.m_MaxSpawnPointOverrideExtensions, MEMBUCKET_WORLD);
fwClothCollisionsExtension::InitPool( cfgExt.m_MaxClothCollisionsExtensions, MEMBUCKET_WORLD );
gDoorExtensionStore.SetStoragePool(CDoorExtension::GetPool());
gLightExtensionStore.SetStoragePool(CLightExtension::GetPool());
gSpawnPointOverrideExtensionStore.SetStoragePool(CSpawnPointOverrideExtension::GetPool());
gClothCollisionsStore.SetStoragePool(fwClothCollisionsExtension::GetPool());
fwExtensionManager::RegisterFactory( EXT_TYPE_DOOR, gDoorExtensionStore );
fwExtensionManager::RegisterFactory( EXT_TYPE_LIGHT, gLightExtensionStore );
fwExtensionManager::RegisterFactory( EXT_TYPE_SPAWN_POINT_OVERRIDE, gSpawnPointOverrideExtensionStore );
fwExtensionManager::RegisterFactory( EXT_TYPE_CLOTH_COLLISIONS, gClothCollisionsStore );
fwMapData::AssociateExtensionDef(CExtensionDefDoor::parser_GetStaticStructure()->GetNameHash(), EXT_TYPE_DOOR);
fwMapData::AssociateExtensionDef(CExtensionDefLightEffect::parser_GetStaticStructure()->GetNameHash(), EXT_TYPE_LIGHT);
fwMapData::AssociateExtensionDef(CExtensionDefSpawnPointOverride::parser_GetStaticStructure()->GetNameHash(), EXT_TYPE_SPAWN_POINT_OVERRIDE);
fwMapData::AssociateExtensionDef(phVerletClothCustomBounds::parser_GetStaticStructure()->GetNameHash(), EXT_TYPE_CLOTH_COLLISIONS);
}
fwMapTypes::SetMaxFactoryId(NUM_MI_TYPES);
// construct any static data associated with vehicle models
CVehicleModelInfo::ConstructStaticData();
}
else if(initMode == INIT_BEFORE_MAP_LOADED)
{
fwArchetypeManager::ClearArchetypePtrStore();
}
else if(initMode == INIT_SESSION)
{
const CModelInfoConfig& cfgModel = CGameConfig::Get().GetConfigModelInfo();
fwArchetypeManager::GetArchetypeFactory(MI_TYPE_WEAPON)->AddStorageBlock(fwFactory::EXTRA, cfgModel.m_MaxExtraWeaponModelInfos);
fwArchetypeManager::GetArchetypeFactory(MI_TYPE_VEHICLE)->AddStorageBlock(fwFactory::EXTRA, cfgModel.m_MaxExtraVehicleModelInfos);
fwArchetypeManager::GetArchetypeFactory(MI_TYPE_PED)->AddStorageBlock(fwFactory::EXTRA, cfgModel.m_MaxExtraPedModelInfos);
}
}
//
// name: CModelInfo::ShutdownLevelWithMapUnloaded
// description: Remove all allocated memory after map has finished
//
void CModelInfo::Shutdown(unsigned shutdownMode)
{
if(shutdownMode == SHUTDOWN_CORE)
{
gBaseModelStore.Shutdown();
// gDamageAtomicModelStore.Init();
gTimeModelStore.Shutdown();
gWeaponModelStore.Shutdown();
gVehicleModelStore.Shutdown();
CVehicleModelInfo::DestroyStaticData();
gPedModelStore.Shutdown();
gMloModelStore.Shutdown();
gCompEntityModelStore.Shutdown();
//extensions
gLadderStore2.Shutdown();
gProcObjStore2.Shutdown();
gExplosionStore2.Shutdown();
gParticleStore2.Shutdown();
gDecalStore2.Shutdown();
gWindDisturbanceStore2.Shutdown();
gLightShaftStore2.Shutdown();
gScrollStore2.Shutdown();
gSpawnPointStore2.Shutdown();
gBuoyancyStore2.Shutdown();
gAudioStore2.Shutdown();
gWorldPointStore2.Shutdown();
ms_World2dEffectArray.Reset();
// ---
fwArchetypeManager::Shutdown();
fwTransform::ShutdownPools();
CDoorExtension::ShutdownPool();
CLightExtension::ShutdownPool();
CSpawnPointOverrideExtension::ShutdownPool();
}
else if(shutdownMode == SHUTDOWN_WITH_MAP_LOADED)
{
gBaseModelStore.ForAllItemsUsed(&CBaseModelInfo::Shutdown);
gTimeModelStore.ForAllItemsUsed(&CTimeModelInfo::Shutdown);
gWeaponModelStore.ForAllItemsUsed(&CWeaponModelInfo::Shutdown);
gVehicleModelStore.ForAllItemsUsed(&CVehicleModelInfo::Shutdown);
gPedModelStore.ForAllItemsUsed(&CPedModelInfo::Shutdown);
gMloModelStore.ForAllItemsUsed(&CMloModelInfo::Shutdown);
gCompEntityModelStore.ForAllItemsUsed(&CCompEntityModelInfo::Shutdown);
gBaseModelStore.Reset();
gTimeModelStore.Reset();
gWeaponModelStore.Reset();
gVehicleModelStore.Reset();
gPedModelStore.Reset();
gMloModelStore.Reset();
gCompEntityModelStore.Reset();
// extensions
gLadderStore2.Reset();
gProcObjStore2.Reset();
gExplosionStore2.Reset();
gParticleStore2.Reset();
gDecalStore2.Reset();
gWindDisturbanceStore2.Reset();
gLightShaftStore2.Reset();
gScrollStore2.Reset();
gSpawnPointStore2.Reset();
gBuoyancyStore2.Reset();
gAudioStore2.Reset();
gWorldPointStore2.Reset();
ms_World2dEffectArray.Reset();
// ---
fwArchetypeManager::Reset();
}
else if(shutdownMode == SHUTDOWN_SESSION)
{
CStreaming::GetCleanup().DeleteAllDrawableReferences();
// get streaming to remove all the models
const s32 maxModelInfos = fwArchetypeManager::GetMaxArchetypeIndex();
strStreamingModule *module = GetStreamingModule();
for(s32 i=0; i<maxModelInfos; i++)
{
if (module->IsAllocated(i))
{
if(module->IsObjectInImage(strLocalIndex(i)))
{
module->ClearRequiredFlag(i, STR_DONTDELETE_MASK);
module->StreamingRemove(strLocalIndex(i));
}
}
}
// Remove any extra data from the global model infos
gVehicleModelStore.ForAllUsed(fwFactory::GLOBAL, &CModelInfo::ShutdownModelInfoExtra);
gWeaponModelStore.ForAllUsed(fwFactory::GLOBAL, &CModelInfo::ShutdownModelInfoExtra);
gPedModelStore.ForAllUsed(fwFactory::GLOBAL, &CModelInfo::ShutdownModelInfoExtra);
// Shutdown any extra model infos
fwArchetypeManager::FreeArchetypes(fwFactory::EXTRA);
}
}
void CModelInfo::ShutdownModelInfoExtra(rage::fwArchetype *arch)
{
if (CBaseModelInfo* pInfo = static_cast<CBaseModelInfo*>(arch))
pInfo->ShutdownExtra();
}
void CModelInfo::CopyOutCurrentMPPedMapping()
{
MoneyInterface::MemoryTampering( false );
#if (__PS3 || __XENON)
fwModelId modelID;
GetBaseModelInfoFromHashKey(ATSTRINGHASH("mp_m_freemode_01",0x705e61f2), &modelID);
modelinfoDisplayf("tamper check : store - male : %d,%d : %d\n",(modelID.GetMapTypeDefIndex()).Get(), modelID.GetModelIndex(), modelID.ConvertToU32());
ms_obfMaleMPPlayerModelId = (obfuscationMask ^ modelID.ConvertToU32());
GetBaseModelInfoFromHashKey(ATSTRINGHASH("mp_f_freemode_01",0x9c9effd8), &modelID);
ms_obfFemaleMPPlayerModelId = (obfuscationMask ^ modelID.ConvertToU32());
modelinfoDisplayf("tamper check : store - female : %d,%d : %d\n",(modelID.GetMapTypeDefIndex()).Get(), modelID.GetModelIndex(), modelID.ConvertToU32());
#endif //(__PS3 || __XENON)
}
void CModelInfo::ValidateCurrentMPPedMapping()
{
// if (NetworkInterface::IsGameInProgress())
// {
// CPed *pPlayer = CPedFactory::GetFactory()->GetLocalPlayer();
// if (pPlayer)
// {
// u32 playerHash = pPlayer->GetArchetype()->GetModelNameHash();
//
// if (playerHash != ATSTRINGHASH("mp_m_freemode_01",0x705e61f2) &&
// playerHash != ATSTRINGHASH("mp_f_freemode_01",0x9c9effd8))
// {
// modelinfoDisplayf("tamper check : not a valid MP model\n");
// // Quitf("tamper check : not a valid MP model\n");
// }
// }
// }
#if (__PS3 || __XENON)
MoneyInterface::MemoryTampering( false );
bool bMaleValidated = true;
bool bFemaleValidated = true;
fwModelId modelID;
GetBaseModelInfoFromHashKey(ATSTRINGHASH("mp_m_freemode_01",0x705e61f2), &modelID);
bMaleValidated = (ms_obfMaleMPPlayerModelId == (obfuscationMask ^ modelID.ConvertToU32()));
modelinfoDisplayf("tamper check : test - male : %d,%d : %d\n",modelID.GetMapTypeDefIndex(), modelID.GetModelIndex(), modelID.ConvertToU32());
if (!bMaleValidated)
{
modelinfoDisplayf("male check failed");
MoneyInterface::MemoryTampering( true );
//report memory modification to MP player archetype
Assertf(false,"Failed male MP ped fwModelID validation - indicates memory tampering using (%x)",modelID.ConvertToU32());
CNetworkTelemetry::AppendMetricMem(ATSTRINGHASH("mp_m_freemode_01",0x705e61f2), modelID.ConvertToU32());
}
GetBaseModelInfoFromHashKey(ATSTRINGHASH("mp_f_freemode_01",0x9c9effd8), &modelID);
bFemaleValidated = (ms_obfFemaleMPPlayerModelId == (obfuscationMask ^ modelID.ConvertToU32()));
modelinfoDisplayf("tamper check : test - female : %d,%d : %d\n",modelID.GetMapTypeDefIndex(), modelID.GetModelIndex(), modelID.ConvertToU32());
if (!bFemaleValidated)
{
modelinfoDisplayf("female check failed");
MoneyInterface::MemoryTampering( true );
//report memory modification to MP player archetype
Assertf(false,"Failed female MP ped fwModelID validation - indicates memory tampering using (%x)",modelID.ConvertToU32());
CNetworkTelemetry::AppendMetricMem(ATSTRINGHASH("mp_f_freemode_01",0x9c9effd8), modelID.ConvertToU32());
}
#endif //(__PS3 || __XENON)
}
//
// name: CModelInfo::AddBaseModel
// description: Allocate a new model from one of the model stores and give it an index
// in: index = index model will have in model array
CBaseModelInfo* CModelInfo::AddBaseModel(const char* name, u32 *modelIndex)
{
ASSERT_ONLY(fwArchetypeManager::VerifyNameClashes(name));
Assertf(gBaseModelStore.GetCount(fwFactory::GLOBAL) < gBaseModelStore.GetCapacity(fwFactory::GLOBAL), "Reached limit of base models allowed (%d)!", gBaseModelStore.GetCapacity(fwFactory::GLOBAL));
CBaseModelInfo *pModel = gBaseModelStore.CreateItem(fwFactory::GLOBAL);
pModel->Init();
pModel->SetModelName(name);
u32 newIndex = fwArchetypeManager::RegisterPermanentArchetype(pModel, fwMapTypes::GLOBAL, false);
if (modelIndex) {
*modelIndex = newIndex;
}
return pModel;
}
CWeaponModelInfo* CModelInfo::AddWeaponModel(const char* name, bool permanent /*= true*/, s32 mapTypeDefIndex /* = fwMapTypes::GLOBAL */)
{
ASSERT_ONLY(fwArchetypeManager::VerifyNameClashes(name));
Assertf(gWeaponModelStore.GetCount(fwFactory::GLOBAL) < gWeaponModelStore.GetCapacity(fwFactory::GLOBAL), "Reached limit of weapon models allowed (%d)!", gWeaponModelStore.GetCapacity(fwFactory::GLOBAL));
CWeaponModelInfo *pModel = gWeaponModelStore.CreateItem(mapTypeDefIndex);
pModel->Init();
pModel->SetModelName(name);
if (permanent)
{
fwArchetypeManager::RegisterPermanentArchetype(pModel, mapTypeDefIndex, true);
}
else
{
fwArchetypeManager::RegisterStreamedArchetype(pModel, mapTypeDefIndex);
}
char audioName[128];
formatf(audioName, "MOD_%s", name);
pModel->SetAudioCollisionSettings(audNorthAudioEngine::GetObject<ModelAudioCollisionSettings>(audioName), atStringHash(audioName));
return pModel;
}
CVehicleModelInfo* CModelInfo::AddVehicleModel(const char* name, bool permanent /*= true*/, s32 mapTypeDefIndex /* = fwMapTypes::GLOBAL */)
{
ASSERT_ONLY(fwArchetypeManager::VerifyNameClashes(name));
Assertf(gVehicleModelStore.GetCount(mapTypeDefIndex) < gVehicleModelStore.GetCapacity(mapTypeDefIndex), "Reached limit of vehicle models allowed (%d)!", gVehicleModelStore.GetCapacity(mapTypeDefIndex));
CVehicleModelInfo *pModel = gVehicleModelStore.CreateItem(mapTypeDefIndex);
GAMETOOL_ONLY(if (pModel))
{
pModel->Init();
pModel->SetModelName(name);
if (permanent)
{
fwArchetypeManager::RegisterPermanentArchetype(pModel, mapTypeDefIndex, true);
}
else
{
fwArchetypeManager::RegisterStreamedArchetype(pModel, mapTypeDefIndex);
}
}
return pModel;
}
CPedModelInfo* CModelInfo::AddPedModel(const char* name, bool permanent /*= true*/, s32 mapTypeDefIndex /* = fwMapTypes::GLOBAL */)
{
ASSERT_ONLY(fwArchetypeManager::VerifyNameClashes(name));
// ToDo - new version of verifyNameClashes for all builds, which prevents dup'ed archetypes - because that can be fatal much later.
u32 hash = atStringHash(name);
if (fwArchetypeManager::GetArchetypeExistsForHashKey(hash))
{
modelinfoAssertf(false, "(%s) has already been registered, skipping it", name);
return(NULL);
}
Assertf(gPedModelStore.GetCount(fwFactory::GLOBAL) < gPedModelStore.GetCapacity(fwFactory::GLOBAL), "Reached limit of ped models allowed (%d)!", gPedModelStore.GetCapacity(fwFactory::GLOBAL));
CPedModelInfo *pModel = gPedModelStore.CreateItem(mapTypeDefIndex);
pModel->Init();
pModel->SetModelName(name);
if (permanent)
{
fwArchetypeManager::RegisterPermanentArchetype(pModel, mapTypeDefIndex, true);
}
else
{
fwArchetypeManager::RegisterStreamedArchetype(pModel, mapTypeDefIndex);
}
return pModel;
}
CCompEntityModelInfo* CModelInfo::AddCompEntityModel(const char* name)
{
ASSERT_ONLY(fwArchetypeManager::VerifyNameClashes(name));
Assertf(gCompEntityModelStore.GetCount(fwFactory::GLOBAL) < gCompEntityModelStore.GetCapacity(fwFactory::GLOBAL), "Reached limit of comp entity models allowed (%d)!", gCompEntityModelStore.GetCapacity(fwFactory::GLOBAL));
CCompEntityModelInfo *pModel = gCompEntityModelStore.CreateItem(fwFactory::GLOBAL);
pModel->Init();
pModel->SetModelName(name);
fwArchetypeManager::RegisterPermanentArchetype(pModel, fwMapTypes::GLOBAL, false);
return pModel;
}
//
// name: FinishAddingModels
// description: Finalize modelinfo map
void CModelInfo::PostLoad()
{
const char *modelName = "unknown";
/* sysTimer t;*/
// s32 fredFrag = g_FragmentStore.FindSlot("platform:/models/z_z_fred");
// s32 wilmaFrag = g_FragmentStore.FindSlot("platform:/models/z_z_wilma");
u32 maxModelInfos = fwArchetypeManager::GetMaxArchetypeIndex();
for(u32 model= fwArchetypeManager::GetStartArchetypeIndex(); model<maxModelInfos; model++)
{
CBaseModelInfo* pModelInfo = CModelInfo::GetBaseModelInfo(fwModelId(strLocalIndex(model)));
if(pModelInfo == NULL)
continue;
#if !__FINAL
modelName = pModelInfo->GetModelName();
#endif //!__FINAL
// go through each model info attaching it to a drawable dictionary, drawable or fragment store entry of the same name
if(pModelInfo->GetDrawableType() == CBaseModelInfo::DT_DRAWABLEDICTIONARY)
{
ASSERT_ONLY(u32 drawDictIndex = pModelInfo->GetDrawDictIndex();)
Assert(drawDictIndex != -1);
Assertf(g_DwdStore.IsObjectInImage(strLocalIndex(drawDictIndex)),"model type %s (from %s.ityp) is missing drawable dictionary",pModelInfo->GetModelName(), fwArchetypeManager::LookupModelId(pModelInfo).GetTypeFileName());
if (CStreaming::RegisterDummyObject(
modelName, strLocalIndex(model), CModelInfo::GetStreamingModuleId()) == strIndex(strIndex::INVALID_INDEX)) // note: this is NOT -1
{
modelinfoAssertf(false,
"The object '%s' exists as a separate drawable file AND inside a drawable dictionary '%s' - the name clash will lead to crashes later on! This needs to be fixed before commiting this file.\n",
pModelInfo->GetModelName(),
g_DwdStore.GetName(strLocalIndex(drawDictIndex))
);
pModelInfo->SetDrawDictFile("NULL", -1);
}
}
else if (pModelInfo->GetModelType() == MI_TYPE_COMPOSITE)
{
(void)AssertVerify(CStreaming::RegisterDummyObject(modelName, strLocalIndex(model), CModelInfo::GetStreamingModuleId()) != strIndex(strIndex::INVALID_INDEX)); // note: this is NOT -1
}
else if (pModelInfo->GetDrawableType() == CBaseModelInfo::DT_FRAGMENT)
{
ASSERT_ONLY(u32 fragIndex = pModelInfo->GetFragmentIndex();)
Assert(fragIndex != -1);
Assertf(g_FragmentStore.IsObjectInImage(strLocalIndex(fragIndex)),"model type %s (from %s.ityp) is missing fragment model",pModelInfo->GetModelName(), fwArchetypeManager::LookupModelId(pModelInfo).GetTypeFileName());
if (CStreaming::RegisterDummyObject(
modelName, strLocalIndex(model), CModelInfo::GetStreamingModuleId()) == strIndex(strIndex::INVALID_INDEX)) // note: this is NOT -1
{
modelinfoAssertf(false,
"The model '%s' exists as a separate file AND as a fragment '%s' - the name clash will lead to crashes later on! This needs to be fixed before commiting this file.\n",
pModelInfo->GetModelName(),
g_FragmentStore.GetName(strLocalIndex(pModelInfo->GetFragmentIndex()))
);
pModelInfo->ResetAssetReference();
}
}
else if (pModelInfo->GetDrawableType() == CBaseModelInfo::DT_DRAWABLE)
{
ASSERT_ONLY(u32 drawableIndex = pModelInfo->GetDrawableIndex();)
Assert(drawableIndex != -1);
Assertf(g_DrawableStore.IsObjectInImage(strLocalIndex(drawableIndex)),"model type %s (from %s.ityp) is missing drawable model",pModelInfo->GetModelName(), fwArchetypeManager::LookupModelId(pModelInfo).GetTypeFileName());
if (CStreaming::RegisterDummyObject(
modelName, strLocalIndex(model), CModelInfo::GetStreamingModuleId()) == strIndex(strIndex::INVALID_INDEX)) // note: this is NOT -1
{
modelinfoAssertf(false,
"The model '%s' exists as a separate file AND as a drawable '%s' - the name clash will lead to crashes later on! This needs to be fixed before commiting this file.\n",
pModelInfo->GetModelName(),
g_DrawableStore.GetName(strLocalIndex(pModelInfo->GetDrawableIndex()))
);
pModelInfo->ResetAssetReference();
}
}
else if (pModelInfo->GetDrawableType() == CBaseModelInfo::DT_ASSETLESS){
// this is ok - the archetype has been marked as having no assets - this is expected!
}
else
{
// couldn't find anything to attach to this model info - display warning
modelinfoWarningf("Modelinfo %s cannot attach to any streamed graphics component.",pModelInfo->GetModelName());
}
pModelInfo->CheckForHDTxdSlots(); // check the assets assigned to this modelinfo for HD upgrade ability
}
// modelinfoDisplayf("%f ms in ModelInfo::PostLoad",t.GetMsTime());
// modelinfoDisplayf("");
}
//------
// mediated streaming interface
CBaseModelInfo* CModelInfo::GetModelInfoFromLocalIndex(s32 idx)
{
// find the streaming index assigned to this model info (if it has one)
fwModelId modelId;
modelId.ConvertFromStreamingIndex(idx);
return(CModelInfo::GetBaseModelInfo(modelId));
}
strLocalIndex CModelInfo::AssignLocalIndexToModelInfo2(fwModelId modelId){
// does this archetype already have an assigned streaming slot?
CBaseModelInfo* pModelInfo = GetBaseModelInfo(modelId);
Assert(pModelInfo);
// valid stream slot already assigned, so just return it
if (pModelInfo->GetStreamSlot().Get() > 0) {
return(pModelInfo->GetStreamSlot());
}
CArchetypeStreamSlot::Pool* pPool = CArchetypeStreamSlot::GetPool();
CArchetypeStreamSlot* pNewEntry = rage_new CArchetypeStreamSlot (modelId);
Assert(pNewEntry);
strLocalIndex streamSlot = strLocalIndex(pPool->GetJustIndex(pNewEntry));
pModelInfo->SetTempStreamSlot((u8)streamSlot.Get()); // only 256 of these for now!
const char *modelName = "unknown";
#if !__FINAL
modelName = pModelInfo->GetModelName();
#endif //!__FINAL
if (CStreaming::RegisterDummyObject(
modelName, streamSlot, CModelInfo::GetStreamingModuleId()) == strIndex(strIndex::INVALID_INDEX)) // note: this is NOT -1
{
modelinfoAssertf(false,
"Failed to register slot %d to model %s during local index assignment\n", streamSlot.Get(), pModelInfo->GetModelName());
pModelInfo->ResetAssetReference();
ReleaseAssignedLocalIndex(modelId);
streamSlot = 0;
}
return(streamSlot);
}
void CModelInfo::ReleaseAssignedLocalIndex(fwModelId modelId){
CBaseModelInfo* pModelInfo = GetBaseModelInfo(modelId);
Assert(pModelInfo);
strLocalIndex streamSlot = pModelInfo->GetStreamSlot();
if (streamSlot == 0){
return;
}
//u32 streamIndex = lookup(StreamSlot);
//CStreamingInfo::UnregisterObject(streamIndex);
CArchetypeStreamSlot::Pool* pPool = CArchetypeStreamSlot::GetPool();
CArchetypeStreamSlot* pEntry = pPool->GetSlot(streamSlot.Get());
delete pEntry;
pModelInfo->InvalidateStreamSlot();
}
void CModelInfo::UpdateArchetypeStreamSlots(void)
{
CArchetypeStreamSlot::Update(); // inc timer so anything allocated this frame isn't immediately recycled
CArchetypeStreamSlot::Pool* pPool = CArchetypeStreamSlot::GetPool();
Assert(pPool);
CArchetypeStreamSlot* pArchetypeStreamSlot = NULL;
s32 poolSize=pPool->GetSize();
s32 offset = 0;
while(offset < poolSize)
{
pArchetypeStreamSlot = CArchetypeStreamSlot::GetPool()->GetSlot(offset);
if (pArchetypeStreamSlot && pArchetypeStreamSlot->IsDueForRecycling()){
fwModelId modelId = pArchetypeStreamSlot->GetModelId();
ReleaseAssignedLocalIndex(modelId);
// CBaseModelInfo* pModelInfo = CModelInfo::GetBaseModelInfo(modelId);
// Assert(pModelInfo);
// pModelInfo->SetStreamSlot(0);
// delete pArchetypeStreamSlot;
}
offset++;
}
}
bool CModelInfo::HaveAssetsLoaded(fwModelId modelId)
{
return(CStreaming::HasObjectLoaded(modelId.ConvertToStreamingIndex(), CModelInfo::GetStreamingModuleId()));
}
bool CModelInfo::HaveAssetsLoaded(atHashString modelName)
{
CBaseModelInfo* modelInfo = CModelInfo::GetBaseModelInfoFromHashKey(modelName, NULL);
return HaveAssetsLoaded(modelInfo);
}
bool CModelInfo::HaveAssetsLoaded(CBaseModelInfo* pModelInfo)
{
return(CStreaming::HasObjectLoaded(pModelInfo->GetStreamSlot(), CModelInfo::GetStreamingModuleId()));
}
bool CModelInfo::AreAssetsLoading(fwModelId modelId)
{
return(CModelInfo::GetStreamingModule()->IsObjectLoading(modelId.ConvertToStreamingIndex()));
}
bool CModelInfo::AreAssetsRequested(fwModelId modelId)
{
return(CModelInfo::GetStreamingModule()->IsObjectRequested(modelId.ConvertToStreamingIndex()));
}
bool CModelInfo::RequestAssets(fwModelId modelId, u32 streamFlags)
{
return(CStreaming::RequestObject(modelId.ConvertToStreamingIndex(), CModelInfo::GetStreamingModuleId(), streamFlags));
}
bool CModelInfo::RequestAssets(CBaseModelInfo* pModelInfo, u32 streamFlags)
{
return(CStreaming::RequestObject(pModelInfo->GetStreamSlot(), CModelInfo::GetStreamingModuleId(), streamFlags));
}
void CModelInfo::SetAssetsAreDeletable(fwModelId modelId)
{
CStreaming::SetObjectIsDeletable(modelId.ConvertToStreamingIndex(), CModelInfo::GetStreamingModuleId());
}
bool CModelInfo::GetAssetsAreDeletable(fwModelId modelId)
{
return(CStreaming::GetObjectIsDeletable(modelId.ConvertToStreamingIndex(), CModelInfo::GetStreamingModuleId()));
}
u32 CModelInfo::GetAssetStreamFlags(fwModelId modelId)
{
return(CStreaming::GetObjectFlags(modelId.ConvertToStreamingIndex(), CModelInfo::GetStreamingModuleId()));
}
void CModelInfo::RemoveAssets(fwModelId modelId)
{
CStreaming::RemoveObject(modelId.ConvertToStreamingIndex(), CModelInfo::GetStreamingModuleId());
}
bool CModelInfo::GetAssetRequiredFlag(fwModelId modelId)
{
return (CModelInfo::GetStreamingModule()->IsObjectRequired(modelId.ConvertToStreamingIndex()));
}
void CModelInfo::SetAssetRequiredFlag(fwModelId modelId, u32 streamFlags)
{
CModelInfo::GetStreamingModule()->SetRequiredFlag(modelId.ConvertToStreamingIndex().Get(), streamFlags);
}
void CModelInfo::ClearAssetRequiredFlag(fwModelId modelId,u32 streamFlags)
{
CModelInfo::GetStreamingModule()->ClearRequiredFlag(modelId.ConvertToStreamingIndex().Get(), streamFlags);
}
void CModelInfo::GetObjectAndDependencies(fwModelId modelId, atArray<strIndex>& allDeps, const strIndex* ignoreList, s32 numIgnores)
{
strLocalIndex streamingIndex = CModelInfo::LookupLocalIndex(modelId);
if (streamingIndex == CModelInfo::INVALID_LOCAL_INDEX){
return;
}
CStreaming::GetObjectAndDependencies(streamingIndex, CModelInfo::GetStreamingModuleId(), allDeps, ignoreList, numIgnores);
}
void CModelInfo::GetObjectAndDependenciesSizes(fwModelId modelId, u32& virtualSize, u32& physicalSize, const strIndex* ignoreList, s32 numIgnores, bool mayFail)
{
strLocalIndex streamingIndex = CModelInfo::LookupLocalIndex(modelId);
if (streamingIndex == CModelInfo::INVALID_LOCAL_INDEX){
return;
}
CStreaming::GetObjectAndDependenciesSizes(streamingIndex, CModelInfo::GetStreamingModuleId(), virtualSize, physicalSize, ignoreList, numIgnores, mayFail);
}
void CModelInfo::SetGlobalResidentTxd(int txd)
{
// Whizz through the txd, look for const char *name & const grcTexture *texture
fwTxd *pTxd = g_TxdStore.GetSafeFromIndex(strLocalIndex(txd));
for (int i=0; i<pTxd->GetCount(); i++)
{
rage::grcTexture *pTexture = pTxd->GetEntry(i);
const char *pName = pTexture->GetName();
grcTextureFactory::GetInstance().RegisterTextureReference(pName, pTexture);
}
}
// -----
//
// name: PostLoad
// description: Finalize this modelinfo (fix up any required ptrs)
void CModelInfo::PostLoad(fwArchetype* pArchetype)
{
const char *modelName = "unknown";
CBaseModelInfo* pMI = smart_cast<CBaseModelInfo*>(pArchetype);
#if !__FINAL
modelName = pMI->GetModelName();
#endif //!__FINAL
strLocalIndex streamId = pMI->GetStreamSlot();
Assert(streamId != fwArchetypeManager::INVALID_STREAM_SLOT);
// go through each model info attaching it to a drawable dictionary, drawable or fragment store entry of the same name
if(pMI->GetDrawableType() == CBaseModelInfo::DT_DRAWABLEDICTIONARY)
{
ASSERT_ONLY(u32 drawDictIndex = pMI->GetDrawDictIndex();)
Assert(drawDictIndex != -1);
Assertf(g_DwdStore.IsObjectInImage(strLocalIndex(drawDictIndex)),"model type %s (from %s.ityp) is missing drawable dictionary",pMI->GetModelName(), fwArchetypeManager::LookupModelId(pMI).GetTypeFileName());
if (CStreaming::RegisterDummyObject(
modelName, streamId, CModelInfo::GetStreamingModuleId()) == strIndex(strIndex::INVALID_INDEX)) // note: this is NOT -1
{
modelinfoAssertf(false,
"The object '%s' exists as a separate drawable file AND inside a drawable dictionary '%s' - the name clash will lead to crashes later on! This needs to be fixed before commiting this file.\n",
pMI->GetModelName(),
g_DwdStore.GetName(strLocalIndex(drawDictIndex))
);
pMI->SetDrawDictFile("NULL", -1);
}
}
else if (pMI->GetModelType() == MI_TYPE_COMPOSITE)
{
(void)AssertVerify(CStreaming::RegisterDummyObject(modelName, streamId, CModelInfo::GetStreamingModuleId()) != strIndex(strIndex::INVALID_INDEX)); // note: this is NOT -1
}
else if (pMI->GetDrawableType() == CBaseModelInfo::DT_FRAGMENT)
{
ASSERT_ONLY(u32 fragIndex = pMI->GetFragmentIndex();)
Assert(fragIndex != -1);
Assertf(g_FragmentStore.IsObjectInImage(strLocalIndex(fragIndex)),"model type %s (from %s.ityp) is missing fragment",pMI->GetModelName(), fwArchetypeManager::LookupModelId(pMI).GetTypeFileName());
if (CStreaming::RegisterDummyObject(
modelName, streamId, CModelInfo::GetStreamingModuleId()) == strIndex(strIndex::INVALID_INDEX)) // note: this is NOT -1
{
modelinfoAssertf(false,
"The model '%s' exists as a separate file AND as a fragment '%s' - the name clash will lead to crashes later on! This needs to be fixed before commiting this file.\n",
pMI->GetModelName(),
g_FragmentStore.GetName(strLocalIndex(pMI->GetFragmentIndex()))
);
pMI->ResetAssetReference();
}
}
else if (pMI->GetDrawableType() == CBaseModelInfo::DT_DRAWABLE)
{
ASSERT_ONLY(u32 drawableIndex = pMI->GetDrawableIndex();)
Assert(drawableIndex != -1);
Assertf(g_DrawableStore.IsObjectInImage(strLocalIndex(drawableIndex)),"model type %s (from %s.ityp) is missing drawable",pMI->GetModelName(), fwArchetypeManager::LookupModelId(pMI).GetTypeFileName());
if (CStreaming::RegisterDummyObject(
modelName, streamId, CModelInfo::GetStreamingModuleId()) == strIndex(strIndex::INVALID_INDEX)) // note: this is NOT -1
{
modelinfoAssertf(false,
"The model '%s' exists as a separate file AND as a drawable '%s' - the name clash will lead to crashes later on! This needs to be fixed before commiting this file.\n",
pMI->GetModelName(),
g_DrawableStore.GetName(strLocalIndex(pMI->GetDrawableIndex()))
);
pMI->ResetAssetReference();
}
}
else if (pMI->GetDrawableType() == CBaseModelInfo::DT_ASSETLESS){
// this is ok - the archetype has been marked as having no assets - this is expected!
if (CStreaming::RegisterDummyObject(
modelName, streamId, CModelInfo::GetStreamingModuleId()) == strIndex(strIndex::INVALID_INDEX)) // note: this is NOT -1
{
modelinfoAssertf(false,
"The model '%s' exists as a separate file AND as a drawable '%s' - the name clash will lead to crashes later on! This needs to be fixed before commiting this file.",
pMI->GetModelName(),
g_DrawableStore.GetName(strLocalIndex(pMI->GetDrawableIndex()))
);
pMI->ResetAssetReference();
}
}
else
{
#if __DEV
// couldn't find anything to attach to this model info - display warning
modelinfoWarningf("Modelinfo %s cannot attach to any streamed graphics component.",pMI->GetModelName());
#endif //__DEV
}
// ensure that this archetype doesn't have an existing physics bound loaded - it can't be handled yet!
pMI->CheckForHDTxdSlots(); // check the assets assigned to this modelinfo for HD upgrade ability
}
void CModelInfo::UpdateVehicleClassInfos()
{
gVehicleModelStore.ForAllItemsUsed(&CVehicleModelInfo::UpdateVehicleClassInfo);
}
#if __BANK
void CModelInfo::UpdateVehicleHandlingInfos()
{
gVehicleModelStore.ForAllItemsUsed(&CVehicle::UpdateVehicleHandlingInfo);
}
#endif // __BANK
#if __DEV
void CModelInfo::CheckMissingVehicleColours()
{
gVehicleModelStore.ForAllItemsUsed(&CVehicleModelInfo::CheckMissingColour);
}
#endif
#if __DEV
void CModelInfo::UpdateVfxPedInfos()
{
gPedModelStore.ForAllItemsUsed(&CVfxPedInfoMgr::UpdatePedModelInfo);
}
#endif
#if __DEV
void CModelInfo::UpdateVfxVehicleInfos()
{
gVehicleModelStore.ForAllItemsUsed(&CVfxVehicleInfoMgr::UpdateVehicleModelInfo);
}
#endif
#if __BANK
void CModelInfo::CheckVehicleAssetDependencies()
{
gVehicleModelStore.ForAllItemsUsed(&CVehicleModelInfo::CheckDependenciesAreLoaded);
}
void CModelInfo::DumpVehicleModelInfos()
{
CVehicleModelInfo::ms_numLoadedInfos = 0;
gVehicleModelStore.ForAllItemsUsed(&CVehicleModelInfo::DumpVehicleModelInfos);
Displayf("Num loaded infos: %d\n", CVehicleModelInfo::ms_numLoadedInfos);
}
enum eDebugFloatCompareType
{
DFCT_MAIN,
DFCT_VRAM,
DFCT_MAIN_HD,
DFCT_VRAM_HD,
DFCT_COMBINED,
DFCT_COMBINED_HD,
};
eDebugFloatCompareType g_compareType;
int DebugFloatCompare(sDebugSize const* lhs, sDebugSize const* rhs)
{
switch (g_compareType)
{
case DFCT_MAIN:
return lhs->main - rhs->main;
break;
case DFCT_VRAM:
return lhs->vram - rhs->vram;
break;
case DFCT_MAIN_HD:
return lhs->mainHd - rhs->mainHd;
break;
case DFCT_VRAM_HD:
return lhs->vramHd - rhs->vramHd;
break;
case DFCT_COMBINED:
return (lhs->main + lhs->vram) - (rhs->main + rhs->vram);
break;
case DFCT_COMBINED_HD:
return (lhs->mainHd + lhs->vramHd) - (rhs->mainHd + rhs->vramHd);
break;
}
Assert(false);
return 0;
}
void CalculateAverageAndMedianSizes(atArray<sDebugSize>& sizes, u32& totalMain, u32& totalVram, u32& totalMainHd, u32& totalVramHd, u32& count, u32& countHd, u32& medianMain, u32& medianVram, u32& medianMainHd, u32& medianVramHd, u32& combinedMedian, u32& combinedMedianHd)
{
totalMain = totalVram = totalMainHd = totalVramHd = count = countHd = medianMain = medianVram = medianMainHd = medianVramHd = combinedMedian = combinedMedianHd = 0;
count = sizes.GetCount();
if (count > 0)
{
for (s32 i = 0; i < count; ++i)
{
totalMain += sizes[i].main;
totalVram += sizes[i].vram;
if (sizes[i].mainHd > 0 || sizes[i].vramHd > 0)
countHd++;
totalMainHd += sizes[i].mainHd;
totalVramHd += sizes[i].vramHd;
}
g_compareType = DFCT_MAIN;
sizes.QSort(0, -1, DebugFloatCompare);
medianMain = sizes[count >> 1].main;
g_compareType = DFCT_VRAM;
sizes.QSort(0, -1, DebugFloatCompare);
medianVram = sizes[count >> 1].vram;
g_compareType = DFCT_MAIN_HD;
sizes.QSort(0, -1, DebugFloatCompare);
medianMainHd = sizes[count >> 1].mainHd;
g_compareType = DFCT_VRAM_HD;
sizes.QSort(0, -1, DebugFloatCompare);
medianVramHd = sizes[count >> 1].vramHd;
g_compareType = DFCT_COMBINED;
sizes.QSort(0, -1, DebugFloatCompare);
combinedMedian = sizes[count >> 1].main + sizes[count >> 1].vram;
g_compareType = DFCT_COMBINED_HD;
sizes.QSort(0, -1, DebugFloatCompare);
combinedMedianHd = sizes[count >> 1].mainHd + sizes[count >> 1].vramHd;
}
}
void CModelInfo::DumpAverageVehicleSize()
{
CVehicleModelInfo::ms_vehicleSizes.Reset();
gVehicleModelStore.ForAllItemsUsed(&CVehicleModelInfo::DumpAverageVehicleSize);
u32 totalMain = 0;
u32 totalVram = 0;
u32 totalMainHd = 0;
u32 totalVramHd = 0;
u32 count = 0;
u32 countHd = 0;
u32 medianMain = 0;
u32 medianVram = 0;
u32 medianMainHd = 0;
u32 medianVramHd = 0;
u32 combinedMedian = 0;
u32 combinedMedianHd = 0;
CalculateAverageAndMedianSizes(CVehicleModelInfo::ms_vehicleSizes, totalMain, totalVram, totalMainHd, totalVramHd, count, countHd, medianMain, medianVram, medianMainHd, medianVramHd, combinedMedian, combinedMedianHd);
u32 total = totalMain + totalVram;
u32 totalHd = totalMainHd + totalVramHd;
Displayf("Total vehicle models: %d - average size: %d (m%d - v%d) - average hd: %d (m%d - v%d) - median size: %d (m%d - v%d) - median hd: %d (m%d - v%d)\n", count,
total / count, totalMain / count, totalVram / count, totalHd / countHd, totalMainHd / countHd, totalVramHd / countHd,
combinedMedian, medianMain, medianVram, combinedMedianHd, medianMainHd, medianVramHd);
FileHandle file = CFileMgr::OpenFileForWriting("vehicle_sizes.xls");
if (CFileMgr::IsValidFileHandle(file))
{
g_compareType = DFCT_COMBINED;
CVehicleModelInfo::ms_vehicleSizes.QSort(0, -1, DebugFloatCompare);
char line[256];
formatf(line, "Total vehicle models: %d - average size: %d (m%d - v%d) - average hd: %d (m%d - v%d) - median size: %d (m%d - v%d) - median hd: %d (m%d - v%d)\n\n", count,
total / count, totalMain / count, totalVram / count, totalHd / countHd, totalMainHd / countHd, totalVramHd / countHd,
combinedMedian, medianMain, medianVram, combinedMedianHd, medianMainHd, medianVramHd);
CFileMgr::Write(file, line, istrlen(line));
formatf(line, "Model, Main, Vram, Main Hd, Vram Hd\n");
CFileMgr::Write(file, line, istrlen(line));
for (s32 i = 0; i < count; ++i)
{
formatf(line, "%s\t%d\t%d\t%d\t%d\n",
CVehicleModelInfo::ms_vehicleSizes[i].name,
CVehicleModelInfo::ms_vehicleSizes[i].main,
CVehicleModelInfo::ms_vehicleSizes[i].vram,
CVehicleModelInfo::ms_vehicleSizes[i].mainHd,
CVehicleModelInfo::ms_vehicleSizes[i].vramHd);
CFileMgr::Write(file, line, istrlen(line));
}
CFileMgr::CloseFile(file);
}
CVehicleModelInfo::ms_vehicleSizes.Reset();
}
void CModelInfo::DumpAveragePedSize()
{
CPedModelInfo::ms_pedSizes.Reset();
gPedModelStore.ForAllItemsUsed(&CPedModelInfo::DumpAveragePedSize);
u32 totalMain = 0;
u32 totalVram = 0;
u32 totalMainHd = 0;
u32 totalVramHd = 0;
u32 count = 0;
u32 countHd = 0;
u32 medianMain = 0;
u32 medianVram = 0;
u32 medianMainHd = 0;
u32 medianVramHd = 0;
u32 combinedMedian = 0;
u32 combinedMedianHd = 0;
CalculateAverageAndMedianSizes(CPedModelInfo::ms_pedSizes, totalMain, totalVram, totalMainHd, totalVramHd, count, countHd, medianMain, medianVram, medianMainHd, medianVramHd, combinedMedian, combinedMedianHd);
u32 total = totalMain + totalVram;
u32 totalHd = totalMainHd + totalVramHd;
Displayf("Total (pack) ped models: %d - average size: %d (m%d - v%d) - average hd: %d (m%d - v%d) - median size: %d (m%d - v%d) - median hd: %d (m%d - v%d)\n", count,
total / count, totalMain / count, totalVram / count, totalHd / countHd, totalMainHd / countHd, totalVramHd / countHd,
combinedMedian, medianMain, medianVram, combinedMedianHd, medianMainHd, medianVramHd);
FileHandle file = CFileMgr::OpenFileForWriting("ped_sizes.xls");
if (CFileMgr::IsValidFileHandle(file))
{
g_compareType = DFCT_COMBINED;
CPedModelInfo::ms_pedSizes.QSort(0, -1, DebugFloatCompare);
char line[256];
formatf(line, "Total (pack) ped models: %d - average size: %d (m%d - v%d) - average hd: %d (m%d - v%d) - median size: %d (m%d - v%d) - median hd: %d (m%d - v%d)\n\n", count,
total / count, totalMain / count, totalVram / count, totalHd / countHd, totalMainHd / countHd, totalVramHd / countHd,
combinedMedian, medianMain, medianVram, combinedMedianHd, medianMainHd, medianVramHd);
CFileMgr::Write(file, line, istrlen(line));
formatf(line, "Model, Main, Vram, Main Hd, Vram Hd\n");
CFileMgr::Write(file, line, istrlen(line));
for (s32 i = 0; i < count; ++i)
{
formatf(line, "%s\t%d\t%d\t%d\t%d\n",
CPedModelInfo::ms_pedSizes[i].name,
CPedModelInfo::ms_pedSizes[i].main,
CPedModelInfo::ms_pedSizes[i].vram,
CPedModelInfo::ms_pedSizes[i].mainHd,
CPedModelInfo::ms_pedSizes[i].vramHd);
CFileMgr::Write(file, line, istrlen(line));
}
CFileMgr::CloseFile(file);
}
CPedModelInfo::ms_pedSizes.Reset();
}
void CModelInfo::DebugRecalculateAllVehicleCoverPoints()
{
gVehicleModelStore.ForAllItemsUsed(&CVehicleModelInfo::DebugRecalculateVehicleCoverPoints);
}
#endif // __BANK
void CModelInfo::ClearAllCountedAsScenarioPedFlags()
{
gPedModelStore.ForAllItemsUsed(&CPedModelInfo::ClearCountedAsScenarioPed);
}
void CModelInfo::RegisterStreamingModule()
{
static CModelInfoStreamingModule modelinfoStreamingModule;
fwArchetypeManager::SetStreamingModuleId(strStreamingEngine::GetInfo().GetModuleMgr().AddModule(&modelinfoStreamingModule));
}
#if DEBUGINFO_2DFX
void CModelInfo::DebugInfo2dEffect()
{
s32 size = sizeof(C2dEffect);
//model effects
s32 i,used = g2dEffectStore.GetItemsUsed();
s32 CurrentSize = used * size;
s32 RealSize = 0;
s32 SizeHeader = sizeof(Vector3) + sizeof(u32);
s32 SizeLightStruct = sizeof(CLightAttr);
s32 SizeParticleStruct = sizeof(CParticleAttr);
s32 SizeExplosionStruct = sizeof(CExplosionAttr);
s32 SizeDecalStruct = sizeof(CDecalAttr);
s32 SizeWindDisturbanceStruct = sizeof(CWindDisturbanceAttr);
s32 SizeProceduralStruct = sizeof(CProcObjAttr);
s32 SizeCoordScriptStruct = sizeof(CWorldPointAttr);
s32 SizeLadderStruct = sizeof(CLadderInfo);
s32 SizeAudioEffectStruct = sizeof(CAudioAttr);
s32 SizeSpawnPointStruct = sizeof(CSpawnPoint);
s32 SizeLightsShaftStruct = sizeof(CLightShaftAttr);
s32 SizeScrollBarStruct = sizeof(CScrollBarAttr);
s32 SizeSwayableStruct = sizeof(CSwayableAttr);
s32 SizeBuoyancyStruct = sizeof(CBuoyancyAttr);
s32 NumLights = 0;
s32 NumParticles = 0;
s32 NumExplosions = 0;
s32 NumDecals = 0;
s32 NumWindDisturbances = 0;
s32 NumEscalators = 0;
s32 NumProcedurals = 0;
s32 NumCoordScripts = 0;
s32 NumLadders = 0;
s32 NumAudioEffects = 0;
s32 NumSpawnPoints = 0;
s32 NumLightsShafts = 0;
s32 NumScrollBars = 0;
s32 NumSwayables = 0;
s32 NumBuoyancys = 0;
s32 NumWalkDontWalks = 0;
for(i=0;i<used;i++)
{
switch((g2dEffectStore[i])->GetType())
{
case ET_LIGHT:
NumLights++;
break;
case ET_PARTICLE:
NumParticles++;
break;
case ET_EXPLOSION:
NumExplosions++;
break;
case ET_DECAL:
NumDecals++;
break;
case ET_WINDDISTURBANCE:
NumWindDisturbances++;
break;
case ET_PROCEDURALOBJECTS:
NumProcedurals++;
break;
case ET_COORDSCRIPT:
NumCoordScripts++;
break;
case ET_LADDER:
NumLadders++;
break;
case ET_AUDIOEFFECT:
NumAudioEffects++;
break;
case ET_SPAWN_POINT:
NumSpawnPoints++;
break;
case ET_LIGHT_SHAFT:
NumLightsShafts++;
break;
case ET_SCROLLBAR:
NumScrollBars++;
break;
case ET_BUOYANCY:
NumBuoyancys++;
break;
}
}
RealSize = 0;
RealSize += (sizeof(CLightAttr) + SizeHeader) * NumLights;
RealSize += (sizeof(CParticleAttr) + SizeHeader) * NumParticles;
RealSize += (sizeof(CExplosionAttr) + SizeHeader) * NumExplosions;
RealSize += (sizeof(CDecalAttr) + SizeHeader) * NumDecals;
RealSize += (sizeof(CWindDisturbanceAttr) + SizeHeader) * NumWindDisturbances;
RealSize += (sizeof(CProcObjAttr) + SizeHeader) * NumProcedurals;
RealSize += (sizeof(CWorldPointAttr) + SizeHeader) * NumCoordScripts;
RealSize += (sizeof(CLadderInfo) + SizeHeader) * NumLadders;
RealSize += (sizeof(CAudioAttr) + SizeHeader) * NumAudioEffects;
RealSize += (sizeof(CSpawnPoint) + SizeHeader) * NumSpawnPoints;
RealSize += (sizeof(CLightShaftAttr) + SizeHeader) * NumLightsShafts;
RealSize += (sizeof(CScrollBarAttr) + SizeHeader) * NumScrollBars;
RealSize += (sizeof(CSwayableAttr) + SizeHeader) * NumSwayables;
RealSize += (sizeof(CBuoyancyAttr) + SizeHeader) * NumBuoyancys;
//world effects
used = ms_World2dEffectArray.GetCount();
CurrentSize = used * size;
RealSize = 0;
SizeHeader = sizeof(Vector3) + sizeof(u32);
SizeLightStruct = sizeof(CLightAttr);
SizeParticleStruct = sizeof(CParticleAttr);
SizeExplosionStruct = sizeof(CExplosionAttr);
SizeDecalStruct = sizeof(CDecalAttr);
SizeWindDisturbanceStruct = sizeof(CWindDisturbanceAttr);
SizeProceduralStruct = sizeof(CProcObjAttr);
SizeCoordScriptStruct = sizeof(CWorldPointAttr);
SizeLadderStruct = sizeof(CLadderInfo);
SizeAudioEffectStruct = sizeof(CAudioAttr);
SizeSpawnPointStruct = sizeof(CSpawnPoint);
SizeLightsShaftStruct = sizeof(CLightShaftAttr);
SizeScrollBarStruct = sizeof(CScrollBarAttr);
SizeSwayableStruct = sizeof(CSwayableAttr);
SizeBuoyancyStruct = sizeof(CBuoyancyAttr);
NumLights = 0;
NumParticles = 0;
NumExplosions = 0;
NumDecals = 0;
NumWindDisturbances = 0;
NumEscalators = 0;
NumProcedurals = 0;
NumCoordScripts = 0;
NumLadders = 0;
NumAudioEffects = 0;
NumSpawnPoints = 0;
NumLightsShafts = 0;
NumScrollBars = 0;
NumSwayables = 0;
NumBuoyancys = 0;
NumWalkDontWalks = 0;
for(i=0;i<used;i++)
{
switch(ms_World2dEffectArray[i]->GetType())
{
case ET_LIGHT:
NumLights++;
break;
case ET_PARTICLE:
NumParticles++;
break;
case ET_EXPLOSION:
NumExplosions++;
break;
case ET_DECAL:
NumDecals++;
break;
case ET_WINDDISTURBANCE:
NumWindDisturbances++;
break;
case ET_PROCEDURALOBJECTS:
NumProcedurals++;
break;
case ET_COORDSCRIPT:
NumCoordScripts++;
break;
case ET_LADDER:
NumLadders++;
break;
case ET_AUDIOEFFECT:
NumAudioEffects++;
break;
case ET_SPAWN_POINT:
NumSpawnPoints++;
break;
case ET_LIGHT_SHAFT:
NumLightsShafts++;
break;
case ET_SCROLLBAR:
NumScrollBars++;
break;
case ET_BUOYANCY:
NumBuoyancys++;
break;
case ET_WALKDONTWALK:
NumWalkDontWalks++;
break;
}
}
RealSize = 0;
RealSize += (sizeof(CLightAttr) + SizeHeader) * NumLights;
RealSize += (sizeof(CParticleAttr) + SizeHeader) * NumParticles;
RealSize += (sizeof(CExplosionAttr) + SizeHeader) * NumExplosions;
RealSize += (sizeof(CDecalAttr) + SizeHeader) * NumDecals;
RealSize += (sizeof(CWindDisturbanceAttr) + SizeHeader) * NumWindDisturbances;
RealSize += (sizeof(CProcObjAttr) + SizeHeader) * NumProcedurals;
RealSize += (sizeof(CWorldPointAttr) + SizeHeader) * NumCoordScripts;
RealSize += (sizeof(CLadderInfo) + SizeHeader) * NumLadders;
RealSize += (sizeof(CAudioAttr) + SizeHeader) * NumAudioEffects;
RealSize += (sizeof(CSpawnPoint) + SizeHeader) * NumSpawnPoints;
RealSize += (sizeof(CLightShaftAttr) + SizeHeader) * NumLightsShafts;
RealSize += (sizeof(CScrollBarAttr) + SizeHeader) * NumScrollBars;
RealSize += (sizeof(CSwayableAttr) + SizeHeader) * NumSwayables;
RealSize += (sizeof(CBuoyancyAttr) + SizeHeader) * NumBuoyancys;
}
#endif //DEBUGINFO_2DFX