Files
gtav-src/script/dev_ng/singleplayer/include/public/asset_management_public.sch
T
2025-09-29 00:52:08 +02:00

2586 lines
89 KiB
XML
Executable File

// *****************************************************************************************
// *****************************************************************************************
// *****************************************************************************************
//
// MISSION NAME : stage_management_public.sch
// AUTHOR : Michael Wadelin
// DESCRIPTION : Contains systems that help with asset management during skips.
// It can be used for j/p/z/retry skips to manage what is already
// loaded and what needs loading between stages without the need to
// stream assets out and instantly back in.
//
// *****************************************************************************************
// *****************************************************************************************
// *****************************************************************************************
USING "rage_builtins.sch"
USING "globals.sch"
USING "commands_script.sch"
USING "commands_streaming.sch"
USING "commands_audio.sch"
USING "commands_hud.sch"
USING "dialogue_public.sch"
// maximum number of assets (per asset type) that can be tracked with this system
CONST_INT ASSETS_MAX_NUM_MODELS 30
CONST_INT ASSETS_MAX_NUM_VEH_ASSETS 10
CONST_INT ASSETS_MAX_NUM_WEAP_ASSETS 10
CONST_INT ASSETS_MAX_NUM_ANIM_DICTS 20
CONST_INT ASSETS_MAX_NUM_WAYPOINTS 20
CONST_INT ASSETS_MAX_NUM_VEH_RECS 30
CONST_INT ASSETS_MAX_NUM_SCALEFORM 5
CONST_INT ASSETS_MAX_NUM_MOVIE_MESH_SETS 7
CONST_INT ASSETS_MAX_NUM_AUDIO_BANKS 5
CONST_INT ASSETS_MAX_NUM_INTERIORS 3
CONST_INT ASSETS_MAX_NUM_ASSISTED_LINES 10
CONST_INT ASSETS_MAX_NUM_ALARMS 5
CONST_INT ASSETS_MAC_NUM_TEXTURE_DICTS 5
STRUCT ASSET_STATUS
BOOL bRequested
BOOL bLoaded
BOOL bCleanup
INT iTimestamp
ENDSTRUCT
STRUCT ASSET_MODEL
ASSET_STATUS status
MODEL_NAMES modelName
ENDSTRUCT
STRUCT ASSET_STRING
ASSET_STATUS status
STRING strAssetName
ENDSTRUCT
STRUCT ASSET_SCALEFORM
ASSET_STATUS status
STRING strScaleformName
SCALEFORM_INDEX sfi
ENDSTRUCT
STRUCT ASSET_VEH_REC
ASSET_STATUS status
STRING strRecName
INT iRecNo
ENDSTRUCT
STRUCT ASSET_MOVIE_MESH_SET
ASSET_STATUS status
STRING strMeshSetName
MOVIE_MESH_SET_ID mmsi
INTERIOR_INSTANCE_INDEX interior
ENDSTRUCT
STRUCT ASSET_WEAPON
ASSET_STATUS status
WEAPON_TYPE weapType
WEAPON_RESOURCE_FLAGS weapReqFlags
EXTRA_WEAPON_COMPONENT_RESOURCE_FLAGS weapCompFlags
ENDSTRUCT
STRUCT ASSET_INTERIOR
ASSET_STATUS status
INTERIOR_INSTANCE_INDEX iii
ENDSTRUCT
STRUCT ASSET_TEXT_BLOCK
ASSET_STATUS status
STRING strBlockName
ENDSTRUCT
STRUCT ASSET_NEW_LOAD_SCENE
ASSET_STATUS status
VECTOR vCoord
VECTOR vDir
FLOAT fDist
ENDSTRUCT
// Used with the asset management system to hold all the assets currently loaded and the state of the streaming loop.
STRUCT ASSET_MANAGEMENT_DATA
ASSET_MODEL sModels[ASSETS_MAX_NUM_MODELS]
ASSET_MODEL sVehicleAssets[ASSETS_MAX_NUM_VEH_ASSETS]
ASSET_WEAPON sWeapons[ASSETS_MAX_NUM_WEAP_ASSETS]
ASSET_STRING sAnimDicts[ASSETS_MAX_NUM_ANIM_DICTS]
ASSET_STRING sWaypoints[ASSETS_MAX_NUM_WAYPOINTS]
ASSET_VEH_REC sVehRecs[ASSETS_MAX_NUM_VEH_RECS]
ASSET_SCALEFORM sScaleformMovies[ASSETS_MAX_NUM_SCALEFORM]
ASSET_MOVIE_MESH_SET sMovieMeshSets[ASSETS_MAX_NUM_MOVIE_MESH_SETS]
ASSET_STRING sAudioBanks[ASSETS_MAX_NUM_AUDIO_BANKS]
ASSET_INTERIOR sInteriors[ASSETS_MAX_NUM_INTERIORS]
ASSET_TEXT_BLOCK sTextBlocks[NUM_ADDITIONAL_TEXT_SLOTS]
ASSET_STATUS sPTFX
ASSET_STATUS sRopes
ASSET_NEW_LOAD_SCENE sLoadScene
ASSET_STRING sAssistedLines[ASSETS_MAX_NUM_ASSISTED_LINES]
ASSET_STRING sAlarms[ASSETS_MAX_NUM_ALARMS]
#IF USE_TU_CHANGES
ASSET_STRING sStreamedTextureDicts[ASSETS_MAX_NUM_ALARMS]
#ENDIF
BOOL bStreamingLoopAwake
BOOL bIsSkipWarping
BOOL bUnfreezePlayerAtEnd
#IF IS_DEBUG_BUILD
BOOL bDrawDebugInfo
#ENDIF
ENDSTRUCT
//PURPOSE: Gets the number of asset slots
FUNC INT Get_Num_Assets_Loaded(ASSET_MANAGEMENT_DATA &sAssetData, BOOL bLoadedOnly = FALSE)
INT i, iAssets
REPEAT ASSETS_MAX_NUM_MODELS i
IF sAssetData.sModels[i].status.bRequested
IF (bLoadedOnly = FALSE) OR (sAssetData.sModels[i].status.bLoaded)
iAssets++
ENDIF
ENDIF
ENDREPEAT
REPEAT ASSETS_MAX_NUM_VEH_ASSETS i
IF sAssetData.sVehicleAssets[i].status.bRequested
IF (bLoadedOnly = FALSE) OR (sAssetData.sVehicleAssets[i].status.bLoaded)
iAssets++
ENDIF
ENDIF
ENDREPEAT
REPEAT ASSETS_MAX_NUM_WEAP_ASSETS i
IF sAssetData.sWeapons[i].status.bRequested
IF (bLoadedOnly = FALSE) OR (sAssetData.sWeapons[i].status.bLoaded)
iAssets++
ENDIF
ENDIF
ENDREPEAT
REPEAT ASSETS_MAX_NUM_ANIM_DICTS i
IF sAssetData.sAnimDicts[i].status.bRequested
IF (bLoadedOnly = FALSE) OR (sAssetData.sAnimDicts[i].status.bLoaded)
iAssets++
ENDIF
ENDIF
ENDREPEAT
REPEAT ASSETS_MAX_NUM_WAYPOINTS i
IF sAssetData.sWaypoints[i].status.bRequested
IF (bLoadedOnly = FALSE) OR (sAssetData.sWaypoints[i].status.bLoaded)
iAssets++
ENDIF
ENDIF
ENDREPEAT
REPEAT ASSETS_MAX_NUM_VEH_RECS i
IF sAssetData.sVehRecs[i].status.bRequested
IF (bLoadedOnly = FALSE) OR (sAssetData.sVehRecs[i].status.bLoaded)
iAssets++
ENDIF
ENDIF
ENDREPEAT
REPEAT ASSETS_MAX_NUM_SCALEFORM i
IF sAssetData.sScaleformMovies[i].status.bRequested
IF (bLoadedOnly = FALSE) OR (sAssetData.sScaleformMovies[i].status.bLoaded)
iAssets++
ENDIF
ENDIF
ENDREPEAT
REPEAT ASSETS_MAX_NUM_MOVIE_MESH_SETS i
IF sAssetData.sMovieMeshSets[i].status.bRequested
IF (bLoadedOnly = FALSE) OR (sAssetData.sMovieMeshSets[i].status.bLoaded)
iAssets++
ENDIF
ENDIF
ENDREPEAT
REPEAT ASSETS_MAX_NUM_AUDIO_BANKS i
IF sAssetData.sAudioBanks[i].status.bRequested
IF (bLoadedOnly = FALSE) OR (sAssetData.sAudioBanks[i].status.bLoaded)
iAssets++
ENDIF
ENDIF
ENDREPEAT
REPEAT ASSETS_MAX_NUM_INTERIORS i
IF sAssetData.sInteriors[i].status.bRequested
IF (bLoadedOnly = FALSE) OR (sAssetData.sInteriors[i].status.bLoaded)
iAssets++
ENDIF
ENDIF
ENDREPEAT
REPEAT ASSETS_MAX_NUM_ASSISTED_LINES i
IF sAssetData.sAssistedLines[i].status.bRequested
IF (bLoadedOnly = FALSE) OR (sAssetData.sAssistedLines[i].status.bLoaded)
iAssets++
ENDIF
ENDIF
ENDREPEAT
REPEAT ASSETS_MAX_NUM_ALARMS i
IF sAssetData.sAlarms[i].status.bRequested
IF (bLoadedOnly = FALSE) OR (sAssetData.sAlarms[i].status.bLoaded)
iAssets++
ENDIF
ENDIF
ENDREPEAT
REPEAT COUNT_OF(sAssetData.sTextBlocks) i
IF sAssetData.sTextBlocks[i].status.bRequested
IF (bLoadedOnly = FALSE) OR (sAssetData.sTextBlocks[i].status.bLoaded)
iAssets++
ENDIF
ENDIF
ENDREPEAT
IF sAssetData.sPTFX.bRequested
IF (bLoadedOnly = FALSE) OR (sAssetData.sPTFX.bLoaded)
iAssets++
ENDIF
ENDIF
IF sAssetData.sRopes.bRequested
IF (bLoadedOnly = FALSE) OR (sAssetData.sRopes.bLoaded)
iAssets++
ENDIF
ENDIF
IF sAssetData.sLoadScene.status.bRequested
IF (bLoadedOnly = FALSE) OR (sAssetData.sLoadScene.status.bLoaded)
iAssets++
ENDIF
ENDIF
RETURN iAssets
ENDFUNC
//PURPOSE: Resets the status of an asset
PROC Reset_Asset_Slot(ASSET_STATUS &asset)
asset.bRequested = FALSE
asset.bLoaded = FALSE
asset.bCleanup = FALSE
asset.iTimestamp = -1
ENDPROC
//PURPOSE: Unloads an model asset
PROC Unload_Asset_Model(ASSET_MANAGEMENT_DATA &sAssetData, MODEL_NAMES model)
INT i
REPEAT COUNT_OF(sAssetData.sModels) i
IF sAssetData.sModels[i].status.bRequested
IF sAssetData.sModels[i].modelName = model
IF sAssetData.sModels[i].status.bLoaded
SET_MODEL_AS_NO_LONGER_NEEDED(model)
Reset_Asset_Slot(sAssetData.sModels[i].status)
EXIT
ELSE
sAssetData.sModels[i].status.bCleanup = TRUE
sAssetData.bStreamingLoopAwake = TRUE
EXIT
ENDIF
ENDIF
ENDIF
ENDREPEAT
ENDPROC
//PURPOSE: Unloads a waypoint asset
PROC Unload_Asset_Waypoint(ASSET_MANAGEMENT_DATA &sAssetData, string waypointName)
INT i
REPEAT COUNT_OF(sAssetData.sWaypoints) i
IF sAssetData.sWaypoints[i].status.bRequested
IF ARE_STRINGS_EQUAL(sAssetData.sWaypoints[i].strAssetName, waypointName)
IF sAssetData.sWaypoints[i].status.bLoaded
REMOVE_WAYPOINT_RECORDING(waypointName)
Reset_Asset_Slot(sAssetData.sWaypoints[i].status)
EXIT
ELSE
sAssetData.sWaypoints[i].status.bCleanup = TRUE
sAssetData.bStreamingLoopAwake = TRUE
EXIT
ENDIF
ENDIF
ENDIF
ENDREPEAT
ENDPROC
//PURPOSE: Unloads a anim dictionary asset
PROC Unload_Asset_Anim_Dict(ASSET_MANAGEMENT_DATA &sAssetData, string dictionaryName)
IF NOT IS_STRING_NULL_OR_EMPTY(dictionaryName)
INT i
REPEAT COUNT_OF(sAssetData.sAnimDicts) i
IF sAssetData.sAnimDicts[i].status.bRequested
IF ARE_STRINGS_EQUAL(sAssetData.sAnimDicts[i].strAssetName, dictionaryName)
IF sAssetData.sAnimDicts[i].status.bLoaded
REMOVE_ANIM_DICT(dictionaryName)
Reset_Asset_Slot(sAssetData.sAnimDicts[i].status)
EXIT
ELSE
sAssetData.sAnimDicts[i].status.bCleanup = TRUE
sAssetData.bStreamingLoopAwake = TRUE
EXIT
ENDIF
ENDIF
ENDIF
ENDREPEAT
ENDIF
ENDPROC
//PURPOSE: Unloads a anim dictionary asset
PROC Unload_Asset_Weapon_Asset(ASSET_MANAGEMENT_DATA &sAssetData, WEAPON_TYPE weapAsset)
INT i
REPEAT COUNT_OF(sAssetData.sWeapons) i
IF sAssetData.sWeapons[i].status.bRequested
IF sAssetData.sWeapons[i].weapType = weapAsset
IF sAssetData.sWeapons[i].status.bLoaded
REMOVE_WEAPON_ASSET(weapAsset)
Reset_Asset_Slot(sAssetData.sWeapons[i].status)
EXIT
ELSE
sAssetData.sWeapons[i].status.bCleanup = TRUE
sAssetData.bStreamingLoopAwake = TRUE
EXIT
ENDIF
ENDIF
ENDIF
ENDREPEAT
ENDPROC
//PURPOSE: Unloads a anim dictionary asset
PROC Unload_Asset_Vehicle_Aseet(ASSET_MANAGEMENT_DATA &sAssetData, MODEL_NAMES vehicleAsset)
INT i
REPEAT COUNT_OF(sAssetData.sVehicleAssets) i
IF sAssetData.sVehicleAssets[i].status.bRequested
IF sAssetData.sVehicleAssets[i].modelName = vehicleAsset
IF sAssetData.sVehicleAssets[i].status.bLoaded
REMOVE_VEHICLE_ASSET(vehicleAsset)
Reset_Asset_Slot(sAssetData.sVehicleAssets[i].status)
EXIT
ELSE
sAssetData.sVehicleAssets[i].status.bCleanup = TRUE
sAssetData.bStreamingLoopAwake = TRUE
EXIT
ENDIF
ENDIF
ENDIF
ENDREPEAT
ENDPROC
//PURPOSE: Unloads an scaleform asset
PROC Unload_Asset_Scaleform(ASSET_MANAGEMENT_DATA &sAssetData, SCALEFORM_INDEX &sf_mov)
INT i
REPEAT COUNT_OF(sAssetData.sScaleformMovies) i
IF sAssetData.sScaleformMovies[i].status.bRequested
IF sAssetData.sScaleformMovies[i].sfi = sf_mov
IF sAssetData.sScaleformMovies[i].status.bLoaded
SET_SCALEFORM_MOVIE_AS_NO_LONGER_NEEDED(sf_mov)
Reset_Asset_Slot(sAssetData.sScaleformMovies[i].status)
EXIT
ELSE
sAssetData.sScaleformMovies[i].status.bCleanup = TRUE
sAssetData.bStreamingLoopAwake = TRUE
EXIT
ENDIF
ENDIF
ENDIF
ENDREPEAT
ENDPROC
//PURPOSE: Unloads a recording asset
PROC Unload_Asset_Recording(ASSET_MANAGEMENT_DATA &sAssetData, INT iRecNo, STRING strRecName)
INT i
REPEAT COUNT_OF(sAssetData.sVehRecs) i
IF sAssetData.sVehRecs[i].status.bRequested
IF sAssetData.sVehRecs[i].iRecNo = iRecNo
AND ARE_STRINGS_EQUAL(sAssetData.sVehRecs[i].strRecName, strRecName)
IF sAssetData.sVehRecs[i].status.bLoaded
REMOVE_VEHICLE_RECORDING(iRecNo, strRecName)
Reset_Asset_Slot(sAssetData.sVehRecs[i].status)
EXIT
ELSE
sAssetData.sVehRecs[i].status.bCleanup = TRUE
sAssetData.bStreamingLoopAwake = TRUE
EXIT
ENDIF
ENDIF
ENDIF
ENDREPEAT
ENDPROC
//PURPOSE: Unloads a movie mesh set
PROC Unload_Asset_Movie_Mesh(ASSET_MANAGEMENT_DATA &sAssetData, STRING meshSetName)
INT i
REPEAT COUNT_OF(sAssetData.sMovieMeshSets) i
IF sAssetData.sMovieMeshSets[i].status.bRequested
IF ARE_STRINGS_EQUAL(sAssetData.sMovieMeshSets[i].strMeshSetName, meshSetName)
IF sAssetData.sMovieMeshSets[i].status.bLoaded
RELEASE_MOVIE_MESH_SET(sAssetData.sMovieMeshSets[i].mmsi)
Reset_Asset_Slot(sAssetData.sMovieMeshSets[i].status)
EXIT
ELSE
sAssetData.sMovieMeshSets[i].status.bCleanup = TRUE
sAssetData.bStreamingLoopAwake = TRUE
EXIT
ENDIF
ENDIF
ENDIF
ENDREPEAT
ENDPROC
//PURPOSE: Unloads a audio bank
PROC Unload_Asset_Audio_Bank(ASSET_MANAGEMENT_DATA &sAssetData, STRING bankName)
INT i
REPEAT COUNT_OF(sAssetData.sAudioBanks) i
IF sAssetData.sAudioBanks[i].status.bRequested
IF ARE_STRINGS_EQUAL(sAssetData.sAudioBanks[i].strAssetName, bankName)
IF sAssetData.sAudioBanks[i].status.bLoaded
RELEASE_NAMED_SCRIPT_AUDIO_BANK(bankName)
Reset_Asset_Slot(sAssetData.sAudioBanks[i].status)
EXIT
ELSE
sAssetData.sAudioBanks[i].status.bCleanup = TRUE
sAssetData.bStreamingLoopAwake = TRUE
EXIT
ENDIF
ENDIF
ENDIF
ENDREPEAT
ENDPROC
//PURPOSE: Unloads an scaleform asset
PROC Unload_Asset_Interior(ASSET_MANAGEMENT_DATA &sAssetData, INTERIOR_INSTANCE_INDEX interiorID)
INT i
REPEAT COUNT_OF(sAssetData.sInteriors) i
IF sAssetData.sInteriors[i].status.bRequested
IF sAssetData.sInteriors[i].iii = interiorID
IF sAssetData.sInteriors[i].status.bLoaded
UNPIN_INTERIOR(interiorID)
Reset_Asset_Slot(sAssetData.sInteriors[i].status)
EXIT
ELSE
sAssetData.sInteriors[i].status.bCleanup = TRUE
sAssetData.bStreamingLoopAwake = TRUE
EXIT
ENDIF
ENDIF
ENDIF
ENDREPEAT
ENDPROC
//PURPOSE: Unloads the mission ptfx asset
PROC Unload_Asset_PTFX(ASSET_MANAGEMENT_DATA &sAssetData)
IF sAssetData.sPTFX.bRequested
IF sAssetData.sPTFX.bLoaded
REMOVE_PTFX_ASSET()
Reset_Asset_Slot(sAssetData.sPTFX)
ELSE
sAssetData.sPTFX.bCleanup = TRUE
sAssetData.bStreamingLoopAwake = TRUE
ENDIF
ENDIF
ENDPROC
//PURPOSE: Unloads the mission ropes asset
PROC Unload_Asset_Ropes(ASSET_MANAGEMENT_DATA &sAssetData)
IF sAssetData.sRopes.bRequested
IF sAssetData.sRopes.bLoaded
ROPE_UNLOAD_TEXTURES()
Reset_Asset_Slot(sAssetData.sRopes)
ELSE
sAssetData.sRopes.bCleanup = TRUE
sAssetData.bStreamingLoopAwake = TRUE
ENDIF
ENDIF
ENDPROC
//PURPOSE: Unloads the text block by name
PROC Unload_Asset_Additional_Text(ASSET_MANAGEMENT_DATA &sAssetData, STRING textBlockName)
INT i
REPEAT COUNT_OF(sAssetData.sTextBlocks) i
IF sAssetData.sTextBlocks[i].status.bRequested
IF ARE_STRINGS_EQUAL(sAssetData.sTextBlocks[i].strBlockName, textBlockName)
IF sAssetData.sTextBlocks[i].status.bLoaded
CLEAR_ADDITIONAL_TEXT(INT_TO_ENUM(TEXT_BLOCK_SLOTS, i), TRUE)
Reset_Asset_Slot(sAssetData.sTextBlocks[i].status)
EXIT
ELSE
sAssetData.sTextBlocks[i].status.bCleanup = TRUE
sAssetData.bStreamingLoopAwake = TRUE
EXIT
ENDIF
ENDIF
ENDIF
ENDREPEAT
ENDPROC
//PURPOSE: Stops the current load scene if there is one
PROC Unload_Asset_NewLoadScene(ASSET_MANAGEMENT_DATA &sAssetData)
IF IS_NEW_LOAD_SCENE_ACTIVE()
// New load scenes can be stopped at any point, do not need to check if loaded
NEW_LOAD_SCENE_STOP()
Reset_Asset_Slot(sAssetData.sLoadScene.status)
ENDIF
ENDPROC
//PURPOSE: Unloads an assisted movement asset
PROC Unload_Asset_AssistedLine(ASSET_MANAGEMENT_DATA &sAssetData, string lineName)
INT i
REPEAT COUNT_OF(sAssetData.sAssistedLines) i
IF sAssetData.sAssistedLines[i].status.bRequested
IF ARE_STRINGS_EQUAL(sAssetData.sAssistedLines[i].strAssetName, lineName)
IF sAssetData.sAssistedLines[i].status.bLoaded
ASSISTED_MOVEMENT_REMOVE_ROUTE(lineName)
Reset_Asset_Slot(sAssetData.sAssistedLines[i].status)
EXIT
ELSE
sAssetData.sAssistedLines[i].status.bCleanup = TRUE
sAssetData.bStreamingLoopAwake = TRUE
EXIT
ENDIF
ENDIF
ENDIF
ENDREPEAT
ENDPROC
//PURPOSE: Unloads an alarm asset
PROC Unload_Asset_Alarm(ASSET_MANAGEMENT_DATA &sAssetData, string alarmName, BOOL bInstant)
INT i
REPEAT COUNT_OF(sAssetData.sAlarms) i
IF sAssetData.sAlarms[i].status.bRequested
IF ARE_STRINGS_EQUAL(sAssetData.sAlarms[i].strAssetName, alarmName)
IF sAssetData.sAlarms[i].status.bLoaded
STOP_ALARM(alarmName, bInstant)
Reset_Asset_Slot(sAssetData.sAlarms[i].status)
EXIT
ELSE
sAssetData.sAlarms[i].status.bCleanup = TRUE
sAssetData.bStreamingLoopAwake = TRUE
EXIT
ENDIF
ENDIF
ENDIF
ENDREPEAT
ENDPROC
#IF USE_TU_CHANGES
//PURPOSE: Unloads a streamed texture dictionary
PROC Unload_Asset_Texture_Dict(ASSET_MANAGEMENT_DATA &sAssetData, STRING strTextureDictName)
INT i
REPEAT COUNT_OF(sAssetData.sStreamedTextureDicts) i
IF sAssetData.sStreamedTextureDicts[i].status.bRequested
IF ARE_STRINGS_EQUAL(sAssetData.sStreamedTextureDicts[i].strAssetName, strTextureDictName)
IF sAssetData.sStreamedTextureDicts[i].status.bLoaded
RELEASE_NAMED_SCRIPT_AUDIO_BANK(strTextureDictName)
SET_STREAMED_TEXTURE_DICT_AS_NO_LONGER_NEEDED(strTextureDictName)
Reset_Asset_Slot(sAssetData.sStreamedTextureDicts[i].status)
EXIT
ELSE
sAssetData.sStreamedTextureDicts[i].status.bCleanup = TRUE
sAssetData.bStreamingLoopAwake = TRUE
EXIT
ENDIF
ENDIF
ENDIF
ENDREPEAT
ENDPROC
#ENDIF
//PURPOSE: Loads a model asset
FUNC BOOL Load_Asset_Model(ASSET_MANAGEMENT_DATA &sAssetData, MODEL_NAMES model)
IF model = DUMMY_MODEL_FOR_SCRIPT
RETURN FALSE
ENDIF
INT i
INT iFreeSlot = -1
REPEAT COUNT_OF(sAssetData.sModels) i
IF sAssetData.sModels[i].status.bRequested
IF sAssetData.sModels[i].modelName = model
// Either way if its loaded or not we dont want it to clean up!
sAssetData.sModels[i].status.bCleanup = FALSE
// NOT LOADED
IF NOT sAssetData.sModels[i].status.bLoaded
sAssetData.bStreamingLoopAwake = TRUE
RETURN TRUE
// ALREADY LOADED
ELSE
RETURN TRUE
ENDIF
ENDIF
// nothing requested, this is a free slot
ELIF iFreeSlot = -1
iFreeSlot = i
ENDIF
ENDREPEAT
// Wasn't already loaded, find a free slot and load it
IF iFreeSlot >= 0
REQUEST_MODEL(model)
sAssetData.sModels[iFreeSlot].status.bRequested = TRUE
sAssetData.sModels[iFreeSlot].status.iTimestamp = GET_GAME_TIMER()
sAssetData.sModels[iFreeSlot].modelName = model
sAssetData.bStreamingLoopAwake = TRUE
RETURN TRUE
// No free slots, failed to load
ELSE
RETURN FALSE
ENDIF
ENDFUNC
//PURPOSE: Used for loading assets which take a string as their name, ie, waypoint recs, anim dicts, etc
FUNC BOOL Load_Asset_Waypoint(ASSET_MANAGEMENT_DATA &sAssetData, STRING waypointName)
IF IS_STRING_NULL_OR_EMPTY(waypointName)
RETURN FALSE
ENDIF
// Looking for already loaded
INT i
INT iFreeSlot = -1
REPEAT COUNT_OF(sAssetData.sWaypoints) i
IF sAssetData.sWaypoints[i].status.bRequested
IF ARE_STRINGS_EQUAL(sAssetData.sWaypoints[i].strAssetName, waypointName)
// Either way if its loaded or not we dont want it to clean up!
sAssetData.sWaypoints[i].status.bCleanup = FALSE
// NOT LOADED
IF NOT sAssetData.sWaypoints[i].status.bLoaded
sAssetData.bStreamingLoopAwake = TRUE
RETURN TRUE
// ALREADY LOADED
ELSE
RETURN TRUE
ENDIF
ENDIF
// nothing requested, this is a free slot
ELIF iFreeSlot = -1
iFreeSlot = i
ENDIF
ENDREPEAT
// Wasn't already loaded, find a free slot and load it
IF iFreeSlot >= 0
REQUEST_WAYPOINT_RECORDING(waypointName)
sAssetData.sWaypoints[iFreeSlot].status.bRequested = TRUE
sAssetData.sWaypoints[iFreeSlot].status.iTimestamp = GET_GAME_TIMER()
sAssetData.sWaypoints[iFreeSlot].strAssetName = waypointName
sAssetData.bStreamingLoopAwake = TRUE
RETURN TRUE
// No free slots, failed to load
ELSE
RETURN FALSE
ENDIF
ENDFUNC
//PURPOSE: Used for loading assets which take a string as their name, ie, waypoint recs, anim dicts, etc
FUNC BOOL Load_Asset_AnimDict(ASSET_MANAGEMENT_DATA &sAssetData, STRING dictionaryName)
IF IS_STRING_NULL_OR_EMPTY(dictionaryName)
RETURN FALSE
ENDIF
// Looking for already loaded
INT i
INT iFreeSlot = -1
REPEAT COUNT_OF(sAssetData.sAnimDicts) i
IF sAssetData.sAnimDicts[i].status.bRequested
IF ARE_STRINGS_EQUAL(sAssetData.sAnimDicts[i].strAssetName, dictionaryName)
// Either way if its loaded or not we dont want it to clean up!
sAssetData.sAnimDicts[i].status.bCleanup = FALSE
// NOT LOADED
IF NOT sAssetData.sAnimDicts[i].status.bLoaded
sAssetData.bStreamingLoopAwake = TRUE
RETURN TRUE
// ALREADY LOADED
ELSE
RETURN TRUE
ENDIF
ENDIF
// nothing requested, this is a free slot
ELIF iFreeSlot = -1
iFreeSlot = i
ENDIF
ENDREPEAT
// Wasn't already loaded, find a free slot and load it
IF iFreeSlot >= 0
REQUEST_ANIM_DICT(dictionaryName)
sAssetData.sAnimDicts[iFreeSlot].status.bRequested = TRUE
sAssetData.sAnimDicts[iFreeSlot].status.iTimestamp = GET_GAME_TIMER()
sAssetData.sAnimDicts[iFreeSlot].strAssetName = dictionaryName
sAssetData.bStreamingLoopAwake = TRUE
RETURN TRUE
// No free slots, failed to load
ELSE
RETURN FALSE
ENDIF
ENDFUNC
//PURPOSE: Loads a vehicle recording
FUNC BOOL Load_Asset_Recording(ASSET_MANAGEMENT_DATA &sAssetData, INT recNo, STRING recName)
IF IS_STRING_NULL_OR_EMPTY(recName)
OR recNo < 1
RETURN FALSE
ENDIF
// Looking for already loaded
INT i
INT iFreeSlot = -1
REPEAT COUNT_OF(sAssetData.sVehRecs) i
IF sAssetData.sVehRecs[i].status.bRequested
IF sAssetData.sVehRecs[i].iRecNo = recNo
AND ARE_STRINGS_EQUAL(sAssetData.sVehRecs[i].strRecName, recName)
// Either way if its loaded or not we dont want it to clean up!
sAssetData.sVehRecs[i].status.bCleanup = FALSE
// NOT LOADED
IF NOT sAssetData.sVehRecs[i].status.bLoaded
sAssetData.bStreamingLoopAwake = TRUE
RETURN TRUE
// ALREADY LOADED
ELSE
RETURN TRUE
ENDIF
ENDIF
// nothing requested, this is a free slot
ELIF iFreeSlot = -1
iFreeSlot = i
ENDIF
ENDREPEAT
// Wasn't already loaded, find a free slot and load it
IF iFreeSlot >= 0
REQUEST_VEHICLE_RECORDING(recNo, recName)
sAssetData.sVehRecs[iFreeSlot].status.bRequested = TRUE
sAssetData.sVehRecs[iFreeSlot].status.iTimestamp = GET_GAME_TIMER()
sAssetData.sVehRecs[iFreeSlot].strRecName = recName
sAssetData.sVehRecs[iFreeSlot].iRecNo = recNo
sAssetData.bStreamingLoopAwake = TRUE
RETURN TRUE
// No free slots, failed to load
ELSE
RETURN FALSE
ENDIF
ENDFUNC
//PURPOSE: Loads a scaleform movie
FUNC BOOL Load_Asset_Scaleform(ASSET_MANAGEMENT_DATA &sAssetData, STRING assetName, SCALEFORM_INDEX &sf_mov, BOOL bDoesNotDrawWhilePaused = FALSE)
IF IS_STRING_NULL_OR_EMPTY(assetName)
RETURN FALSE
ENDIF
// Looking for already loaded
INT i
INT iFreeSlot = -1
REPEAT COUNT_OF(sAssetData.sScaleformMovies) i
IF sAssetData.sScaleformMovies[i].status.bRequested
IF ARE_STRINGS_EQUAL(sAssetData.sScaleformMovies[i].strScaleformName, assetName)
// Either way if its loaded or not we dont want it to clean up!
sAssetData.sScaleformMovies[i].status.bCleanup = FALSE
sf_mov = sAssetData.sScaleformMovies[i].sfi
// NOT LOADED
IF NOT sAssetData.sScaleformMovies[i].status.bLoaded
sAssetData.bStreamingLoopAwake = TRUE
RETURN TRUE
// ALREADY LOADED
ELSE
RETURN TRUE
ENDIF
ENDIF
// nothing requested, this is a free slot
ELIF iFreeSlot = -1
iFreeSlot = i
ENDIF
ENDREPEAT
// Wasn't already loaded, find a free slot and load it
IF iFreeSlot >= 0
IF bDoesNotDrawWhilePaused
sf_mov = REQUEST_SCALEFORM_MOVIE_SKIP_RENDER_WHILE_PAUSED(assetName)
ELSE
sf_mov = REQUEST_SCALEFORM_MOVIE(assetName)
ENDIF
sAssetData.sScaleformMovies[iFreeSlot].status.bRequested = TRUE
sAssetData.sScaleformMovies[iFreeSlot].status.iTimestamp = GET_GAME_TIMER()
sAssetData.sScaleformMovies[iFreeSlot].strScaleformName = assetName
sAssetData.sScaleformMovies[iFreeSlot].sfi = sf_mov
sAssetData.bStreamingLoopAwake = TRUE
RETURN TRUE
// No free slots, failed to load
ELSE
RETURN FALSE
ENDIF
ENDFUNC
//PURPOSE: Loads a scaleform movie
FUNC BOOL Load_Asset_Movie_Mesh_Set(ASSET_MANAGEMENT_DATA &sAssetData, STRING assetName, INTERIOR_INSTANCE_INDEX interiorInstance)
IF IS_STRING_NULL_OR_EMPTY(assetName)
OR NOT IS_VALID_INTERIOR(interiorInstance)
RETURN FALSE
ENDIF
// Looking for already loaded
INT i
INT iFreeSlot = -1
REPEAT COUNT_OF(sAssetData.sMovieMeshSets) i
IF sAssetData.sMovieMeshSets[i].status.bRequested
IF ARE_STRINGS_EQUAL(sAssetData.sMovieMeshSets[i].strMeshSetName, assetName)
// Either way if its loaded or not we dont want it to clean up!
sAssetData.sMovieMeshSets[i].status.bCleanup = FALSE
// NOT LOADED
IF NOT sAssetData.sMovieMeshSets[i].status.bLoaded
sAssetData.bStreamingLoopAwake = TRUE
RETURN TRUE
// ALREADY LOADED
ELSE
RETURN TRUE
ENDIF
ENDIF
// nothing requested, this is a free slot
ELIF iFreeSlot = -1
iFreeSlot = i
ENDIF
ENDREPEAT
// Wasn't already loaded, find a free slot and load it
IF iFreeSlot >= 0
IF IS_INTERIOR_READY(interiorInstance)
sAssetData.sMovieMeshSets[iFreeSlot].mmsi = LOAD_MOVIE_MESH_SET(assetName)
sAssetData.sMovieMeshSets[iFreeSlot].status.bRequested = TRUE
ELSE
sAssetData.sMovieMeshSets[iFreeSlot].status.bRequested = FALSE
ENDIF
sAssetData.sMovieMeshSets[iFreeSlot].interior = interiorInstance
sAssetData.sMovieMeshSets[iFreeSlot].status.iTimestamp = GET_GAME_TIMER()
sAssetData.sMovieMeshSets[iFreeSlot].strMeshSetName = assetName
sAssetData.bStreamingLoopAwake = TRUE
RETURN TRUE
// No free slots, failed to load
ELSE
RETURN FALSE
ENDIF
ENDFUNC
/// PURPOSE:
/// Checks if the movie mesh set requested through the asset management system has loaded.
/// PARAMS:
/// sAssetData - asset management data struct, keeps track of whats been requested, loaded, cleaned up, etc.
/// assetName - the name of the asset
/// mmsi - return ID of the movie mesh set that has been loaded
/// RETURNS:
/// Returns TRUE if has successfully loaded and will set mms_ID to reference the loaded movie mesh set
FUNC BOOL Has_Asset_Movie_Mesh_Set_Loaded(ASSET_MANAGEMENT_DATA &sAssetData, STRING assetName, MOVIE_MESH_SET_ID &mmsi)
INT i
REPEAT COUNT_OF(sAssetData.sMovieMeshSets) i
IF sAssetData.sMovieMeshSets[i].status.bRequested
IF ARE_STRINGS_EQUAL(sAssetData.sMovieMeshSets[i].strMeshSetName, assetName)
IF sAssetData.sMovieMeshSets[i].status.bLoaded
mmsi = sAssetData.sMovieMeshSets[i].mmsi
RETURN TRUE
ELSE
RETURN FALSE
ENDIF
ENDIF
ENDIF
ENDREPEAT
CPRINTLN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT] Has_Asset_Movie_Mesh_Set_Loaded() asset: ", "\"",assetName," \" was not found in the requests list")
SCRIPT_ASSERT("[ASSET MANAGEMENT] Has_Asset_Movie_Mesh_Set_Loaded() failed to find queried asset in requests list. See script mission debug channel TTY for info")
RETURN FALSE
ENDFUNC
/// PURPOSE: Loads a vehicle asset (entry/exit anims)
FUNC BOOL Load_Asset_Vehicle_Asset(ASSET_MANAGEMENT_DATA &sAssetData, MODEL_NAMES vehicleAsset)
IF vehicleAsset = DUMMY_MODEL_FOR_SCRIPT
RETURN FALSE
ENDIF
// Looking for already loaded
INT i
INT iFreeSlot = -1
REPEAT COUNT_OF(sAssetData.sVehicleAssets) i
IF sAssetData.sVehicleAssets[i].status.bRequested
IF sAssetData.sVehicleAssets[i].modelName = vehicleAsset
// Either way if its loaded or not we dont want it to clean up!
sAssetData.sVehicleAssets[i].status.bCleanup = FALSE
// NOT LOADED
IF NOT sAssetData.sVehicleAssets[i].status.bLoaded
sAssetData.bStreamingLoopAwake = TRUE
RETURN TRUE
// ALREADY LOADED
ELSE
RETURN TRUE
ENDIF
ENDIF
// nothing requested, this is a free slot
ELIF iFreeSlot = -1
iFreeSlot = i
ENDIF
ENDREPEAT
// Wasn't already loaded, find a free slot and load it
IF iFreeSlot >= 0
REQUEST_VEHICLE_ASSET(vehicleAsset)
sAssetData.sVehicleAssets[iFreeSlot].status.bRequested = TRUE
sAssetData.sVehicleAssets[iFreeSlot].status.iTimestamp = GET_GAME_TIMER()
sAssetData.sVehicleAssets[iFreeSlot].modelName = vehicleAsset
sAssetData.bStreamingLoopAwake = TRUE
RETURN TRUE
// No free slots, failed to load
ELSE
RETURN FALSE
ENDIF
ENDFUNC
/// PURPOSE: Loads a weapon asset
FUNC BOOL Load_Asset_Weapon_Asset(ASSET_MANAGEMENT_DATA &sAssetData, WEAPON_TYPE weapAsset, WEAPON_RESOURCE_FLAGS wrFlag = WRF_REQUEST_ALL_ANIMS, EXTRA_WEAPON_COMPONENT_RESOURCE_FLAGS weapCompFlags = WEAPON_COMPONENT_NONE)
IF weapAsset = WEAPONTYPE_UNARMED
RETURN FALSE
ENDIF
// Looking for already loaded
INT i
INT iFreeSlot = -1
REPEAT COUNT_OF(sAssetData.sWeapons) i
IF sAssetData.sWeapons[i].status.bRequested
IF sAssetData.sWeapons[i].weapType = weapAsset
// Either way if its loaded or not we dont want it to clean up!
sAssetData.sWeapons[i].status.bCleanup = FALSE
IF sAssetData.sWeapons[i].weapReqFlags != wrFlag
OR sAssetData.sWeapons[i].weapCompFlags != weapCompFlags
sAssetData.sWeapons[i].status.bLoaded = FALSE
REQUEST_WEAPON_ASSET(weapAsset, enum_to_int(wrFlag), weapCompFlags)
sAssetData.sWeapons[i].weapReqFlags = wrFlag
sAssetData.sWeapons[i].weapCompFlags = weapCompFlags
ELSE
// NOT LOADED
IF NOT sAssetData.sWeapons[i].status.bLoaded
sAssetData.bStreamingLoopAwake = TRUE
RETURN TRUE
// ALREADY LOADED
ELSE
RETURN TRUE
ENDIF
ENDIF
ENDIF
// nothing requested, this is a free slot
ELIF iFreeSlot = -1
iFreeSlot = i
ENDIF
ENDREPEAT
// Wasn't already loaded, find a free slot and load it
IF iFreeSlot >= 0
REQUEST_WEAPON_ASSET(weapAsset, enum_to_int(wrFlag), weapCompFlags)
sAssetData.sWeapons[iFreeSlot].status.bRequested = TRUE
sAssetData.sWeapons[iFreeSlot].status.iTimestamp = GET_GAME_TIMER()
sAssetData.sWeapons[iFreeSlot].weapType = weapAsset
sAssetData.sWeapons[iFreeSlot].weapReqFlags = wrFlag
sAssetData.sWeapons[iFreeSlot].weapCompFlags = weapCompFlags
sAssetData.bStreamingLoopAwake = TRUE
RETURN TRUE
// No free slots, failed to load
ELSE
RETURN FALSE
ENDIF
ENDFUNC
//PURPOSE:
FUNC BOOL Load_Asset_Audiobank(ASSET_MANAGEMENT_DATA &sAssetData, STRING bankName)
IF IS_STRING_NULL_OR_EMPTY(bankName)
RETURN FALSE
ENDIF
// Looking for already loaded
INT i
INT iFreeSlot = -1
REPEAT COUNT_OF(sAssetData.sAudioBanks) i
IF sAssetData.sAudioBanks[i].status.bRequested
IF ARE_STRINGS_EQUAL(sAssetData.sAudioBanks[i].strAssetName, bankName)
// Either way if its loaded or not we dont want it to clean up!
sAssetData.sAudioBanks[i].status.bCleanup = FALSE
// NOT LOADED
IF NOT sAssetData.sAudioBanks[i].status.bLoaded
sAssetData.bStreamingLoopAwake = TRUE
RETURN TRUE
// ALREADY LOADED
ELSE
RETURN TRUE
ENDIF
ENDIF
// nothing requested, this is a free slot
ELIF iFreeSlot = -1
iFreeSlot = i
ENDIF
ENDREPEAT
// Wasn't already loaded, find a free slot and load it
IF iFreeSlot >= 0
REQUEST_SCRIPT_AUDIO_BANK(bankName)
sAssetData.sAudioBanks[iFreeSlot].status.bRequested = TRUE
sAssetData.sAudioBanks[iFreeSlot].status.iTimestamp = GET_GAME_TIMER()
sAssetData.sAudioBanks[iFreeSlot].strAssetName = bankName
sAssetData.bStreamingLoopAwake = TRUE
RETURN TRUE
// No free slots, failed to load
ELSE
RETURN FALSE
ENDIF
ENDFUNC
//PURPOSE: Pins and interior in memory
FUNC BOOL Load_Asset_Interior(ASSET_MANAGEMENT_DATA &sAssetData, INTERIOR_INSTANCE_INDEX interiorID)
IF NOT IS_VALID_INTERIOR(interiorID)
RETURN FALSE
ENDIF
// Looking for already loaded
INT i
INT iFreeSlot = -1
REPEAT COUNT_OF(sAssetData.sInteriors) i
IF sAssetData.sInteriors[i].status.bRequested
IF sAssetData.sInteriors[i].iii = interiorID
// Either way if its loaded or not we dont want it to clean up!
sAssetData.sInteriors[i].status.bCleanup = FALSE
// NOT LOADED
IF NOT sAssetData.sInteriors[i].status.bLoaded
sAssetData.bStreamingLoopAwake = TRUE
RETURN TRUE
// ALREADY LOADED
ELSE
RETURN TRUE
ENDIF
ENDIF
// nothing requested, this is a free slot
ELIF iFreeSlot = -1
iFreeSlot = i
ENDIF
ENDREPEAT
// Wasn't already loaded, find a free slot and load it
IF iFreeSlot >= 0
PIN_INTERIOR_IN_MEMORY(interiorID)
sAssetData.sInteriors[iFreeSlot].status.bRequested = TRUE
sAssetData.sInteriors[iFreeSlot].status.iTimestamp = GET_GAME_TIMER()
sAssetData.sInteriors[iFreeSlot].iii = interiorID
sAssetData.bStreamingLoopAwake = TRUE
RETURN TRUE
// No free slots, failed to load
ELSE
RETURN FALSE
ENDIF
ENDFUNC
//PURPOSE: Loads the mission PTFX assets
PROC Load_Asset_PTFX(ASSET_MANAGEMENT_DATA &sAssetData)
sAssetData.sPTFX.bCleanup = FALSE
IF NOT sAssetData.sPTFX.bLoaded
IF NOT sAssetData.sPTFX.bRequested
REQUEST_PTFX_ASSET()
sAssetData.sPTFX.bRequested = TRUE
ENDIF
sAssetData.bStreamingLoopAwake = TRUE
ENDIF
ENDPROC
//PURPOSE: Loads the mission ropes assets
PROC Load_Asset_Ropes(ASSET_MANAGEMENT_DATA &sAssetData)
sAssetData.sRopes.bCleanup = FALSE
IF NOT sAssetData.sRopes.bLoaded
IF NOT sAssetData.sRopes.bRequested
ROPE_LOAD_TEXTURES()
sAssetData.sRopes.bRequested = TRUE
ENDIF
sAssetData.bStreamingLoopAwake = TRUE
ENDIF
ENDPROC
//PURPOSE: Loads the additional text into the specified slot
FUNC BOOL Load_Asset_Additional_Text(ASSET_MANAGEMENT_DATA &sAssetData, STRING textBlockName, TEXT_BLOCK_SLOTS slot)
// slot already occupied with a loaded or requested item...
IF sAssetData.sTextBlocks[slot].status.bLoaded
OR sAssetData.sTextBlocks[slot].status.bRequested
// ... the requested item, return true
IF ARE_STRINGS_EQUAL(sAssetData.sTextBlocks[slot].strBlockName, textBlockName)
sAssetData.sTextBlocks[slot].status.bCleanup = FALSE
sAssetData.bStreamingLoopAwake = TRUE
RETURN TRUE
// ... something else is occupying the slot, return false
ELSE
RETURN FALSE
ENDIF
// not loaded or requested
ELSE
#IF USE_TU_CHANGES
IF enum_to_int( slot ) >= enum_to_int( DLC_TEXT_SLOT0 )
REQUEST_ADDITIONAL_TEXT_FOR_DLC(textBlockName, slot)
ELSE
REQUEST_ADDITIONAL_TEXT(textBlockName, slot)
ENDIF
#ENDIF
#IF NOT USE_TU_CHANGES
REQUEST_ADDITIONAL_TEXT(textBlockName, slot)
#ENDIF
sAssetData.sTextBlocks[slot].status.bRequested = TRUE
sAssetData.sTextBlocks[slot].status.iTimestamp = GET_GAME_TIMER()
sAssetData.sTextBlocks[slot].strBlockName = textBlockName
sAssetData.bStreamingLoopAwake = TRUE
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
//PURPOSE: Trigger a new load scene sphere
FUNC BOOL Load_Asset_NewLoadScene_Sphere(ASSET_MANAGEMENT_DATA &sAssetData, VECTOR vCoord, FLOAT fRadius, NEWLOADSCENE_FLAGS loadSceneFlags = 0)
IF IS_VECTOR_ZERO(vCoord)
OR fRadius <= 0
RETURN FALSE
ENDIF
IF sAssetData.sLoadScene.status.bRequested
IF ARE_VECTORS_EQUAL(sAssetData.sLoadScene.vCoord, vCoord)
AND sAssetData.sLoadScene.fDist = fRadius
// Either way if its loaded or not we dont want it to clean up!
sAssetData.sLoadScene.status.bCleanup = FALSE
// NOT LOADED
IF NOT sAssetData.sLoadScene.status.bLoaded
sAssetData.bStreamingLoopAwake = TRUE
RETURN TRUE
// ALREADY LOADED
ELSE
RETURN TRUE
ENDIF
// a load scene already exists so overrite it with a new one
ELSE
ENDIF
// start a new one
ENDIF
NEW_LOAD_SCENE_START_SPHERE(vCoord, fRadius, loadSceneFlags)
sAssetData.sLoadScene.status.bRequested = TRUE
sAssetData.sLoadScene.status.iTimestamp = GET_GAME_TIMER()
sAssetData.sLoadScene.vCoord = vCoord
sAssetData.sLoadScene.vDir = <<0,0,0>>
sAssetData.sLoadScene.fDist = fRadius
sAssetData.bStreamingLoopAwake = TRUE
RETURN TRUE
ENDFUNC
//PURPOSE: Trigger a new load scene frustum
FUNC BOOL Load_Asset_NewLoadScene_Frustum(ASSET_MANAGEMENT_DATA &sAssetData, VECTOR vCoord, VECTOR vDir, FLOAT fFarClip, NEWLOADSCENE_FLAGS loadSceneFlags = 0)
IF IS_VECTOR_ZERO(vCoord)
OR IS_VECTOR_ZERO(vDir)
RETURN FALSE
ENDIF
IF sAssetData.sLoadScene.status.bRequested
IF ARE_VECTORS_EQUAL(sAssetData.sLoadScene.vCoord, vCoord)
AND ARE_VECTORS_EQUAL(sAssetData.sLoadScene.vDir, vDir)
AND sAssetData.sLoadScene.fDist = fFarClip
// Either way if its loaded or not we dont want it to clean up!
sAssetData.sLoadScene.status.bCleanup = FALSE
// NOT LOADED
IF NOT sAssetData.sLoadScene.status.bLoaded
sAssetData.bStreamingLoopAwake = TRUE
RETURN TRUE
// ALREADY LOADED
ELSE
RETURN TRUE
ENDIF
// a load scene already exists
ELSE
RETURN FALSE
ENDIF
// start a new one
ELSE
NEW_LOAD_SCENE_START(vCoord, vDir, fFarClip, loadSceneFlags)
sAssetData.sLoadScene.status.bRequested = TRUE
sAssetData.sLoadScene.status.iTimestamp = GET_GAME_TIMER()
sAssetData.sLoadScene.vCoord = vCoord
sAssetData.sLoadScene.vDir = vDir
sAssetData.sLoadScene.fDist = fFarClip
sAssetData.bStreamingLoopAwake = TRUE
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
//PURPOSE: Used for loading an assisted line
FUNC BOOL Load_Asset_AssistedLine(ASSET_MANAGEMENT_DATA &sAssetData, STRING lineName)
IF IS_STRING_NULL_OR_EMPTY(lineName)
RETURN FALSE
ENDIF
// Looking for already loaded
INT i
INT iFreeSlot = -1
REPEAT COUNT_OF(sAssetData.sAssistedLines) i
IF sAssetData.sAssistedLines[i].status.bRequested
IF ARE_STRINGS_EQUAL(sAssetData.sAssistedLines[i].strAssetName, lineName)
// Either way if its loaded or not we dont want it to clean up!
sAssetData.sAssistedLines[i].status.bCleanup = FALSE
// NOT LOADED
IF NOT sAssetData.sAssistedLines[i].status.bLoaded
sAssetData.bStreamingLoopAwake = TRUE
RETURN TRUE
// ALREADY LOADED
ELSE
RETURN TRUE
ENDIF
ENDIF
// nothing requested, this is a free slot
ELIF iFreeSlot = -1
iFreeSlot = i
ENDIF
ENDREPEAT
// Wasn't already loaded, find a free slot and load it
IF iFreeSlot >= 0
ASSISTED_MOVEMENT_REQUEST_ROUTE(lineName)
sAssetData.sAssistedLines[iFreeSlot].status.bRequested = TRUE
sAssetData.sAssistedLines[iFreeSlot].status.iTimestamp = GET_GAME_TIMER()
sAssetData.sAssistedLines[iFreeSlot].strAssetName = lineName
sAssetData.bStreamingLoopAwake = TRUE
RETURN TRUE
// No free slots, failed to load
ELSE
RETURN FALSE
ENDIF
ENDFUNC
/// PURPOSE:
/// Use for loading an alarm via the asset management system
/// PARAMS:
/// sAssetData -
/// alarmName -
/// RETURNS:
///
FUNC BOOL Load_Asset_Alarm(ASSET_MANAGEMENT_DATA &sAssetData, STRING alarmName)
IF IS_STRING_NULL_OR_EMPTY(alarmName)
RETURN FALSE
ENDIF
// Looking for already loaded
INT i
INT iFreeSlot = -1
REPEAT COUNT_OF(sAssetData.sAlarms) i
IF sAssetData.sAlarms[i].status.bRequested
IF ARE_STRINGS_EQUAL(sAssetData.sAlarms[i].strAssetName, alarmName)
// Either way if its loaded or not we dont want it to clean up!
sAssetData.sAlarms[i].status.bCleanup = FALSE
// NOT LOADED
IF NOT sAssetData.sAlarms[i].status.bLoaded
sAssetData.bStreamingLoopAwake = TRUE
RETURN TRUE
// ALREADY LOADED
ELSE
RETURN TRUE
ENDIF
ENDIF
// nothing requested, this is a free slot
ELIF iFreeSlot = -1
iFreeSlot = i
ENDIF
ENDREPEAT
// Wasn't already loaded, find a free slot and load it
IF iFreeSlot >= 0
PREPARE_ALARM(alarmName)
sAssetData.sAlarms[iFreeSlot].status.bRequested = TRUE
sAssetData.sAlarms[iFreeSlot].status.iTimestamp = GET_GAME_TIMER()
sAssetData.sAlarms[iFreeSlot].strAssetName = alarmName
sAssetData.bStreamingLoopAwake = TRUE
RETURN TRUE
// No free slots, failed to load
ELSE
RETURN FALSE
ENDIF
ENDFUNC
#IF USE_TU_CHANGES
/// PURPOSE:
/// Use for loading a streamed texture dictionary via the asset management system
/// PARAMS:
/// sAssetData -
/// alarmName -
/// RETURNS:
///
FUNC BOOL Load_Asset_Texture_Dict(ASSET_MANAGEMENT_DATA &sAssetData, STRING strTextureDictName)
IF IS_STRING_NULL_OR_EMPTY(strTextureDictName)
RETURN FALSE
ENDIF
// Looking for already loaded
INT i
INT iFreeSlot = -1
REPEAT COUNT_OF(sAssetData.sStreamedTextureDicts) i
IF sAssetData.sStreamedTextureDicts[i].status.bRequested
IF ARE_STRINGS_EQUAL(sAssetData.sStreamedTextureDicts[i].strAssetName, strTextureDictName)
// Either way if its loaded or not we dont want it to clean up!
sAssetData.sStreamedTextureDicts[i].status.bCleanup = FALSE
// NOT LOADED
IF NOT sAssetData.sStreamedTextureDicts[i].status.bLoaded
sAssetData.bStreamingLoopAwake = TRUE
RETURN TRUE
// ALREADY LOADED
ELSE
RETURN TRUE
ENDIF
ENDIF
// nothing requested, this is a free slot
ELIF iFreeSlot = -1
iFreeSlot = i
ENDIF
ENDREPEAT
// Wasn't already loaded, find a free slot and load it
IF iFreeSlot >= 0
REQUEST_STREAMED_TEXTURE_DICT(strTextureDictName)
sAssetData.sStreamedTextureDicts[iFreeSlot].status.bRequested = TRUE
sAssetData.sStreamedTextureDicts[iFreeSlot].status.iTimestamp = GET_GAME_TIMER()
sAssetData.sStreamedTextureDicts[iFreeSlot].strAssetName = strTextureDictName
sAssetData.bStreamingLoopAwake = TRUE
RETURN TRUE
// No free slots, failed to load
ELSE
RETURN FALSE
ENDIF
ENDFUNC
#ENDIF
/// PURPOSE:
/// Performs a skip warp which should be done behind a fadeout
/// PARAMS:
/// sAssetData - asset management struct
/// vCoord - coord warping to
/// fHeading - heading you want the player to face
/// fRadius - size of area to stream in
/// RETURNS:
/// Returns TRUE if successfully started a skip warp
FUNC BOOL Mission_Skip_Player_Warp_Sphere(ASSET_MANAGEMENT_DATA &sAssetData, VECTOR vCoord, FLOAT fHeading, FLOAT fRadius, BOOL bUnfreezeAfterSceneIsStreamed = TRUE)
IF Load_Asset_NewLoadScene_Sphere(sAssetData, vCoord, fRadius, NEWLOADSCENE_FLAG_REQUIRE_COLLISION)
SET_ENTITY_COORDS(PLAYER_PED_ID(), vCoord)
SET_ENTITY_HEADING(PLAYER_PED_ID(), fHeading)
FREEZE_ENTITY_POSITION(PLAYER_PED_ID(), TRUE)
sAssetData.bIsSkipWarping = TRUE
sAssetData.bUnfreezePlayerAtEnd = bUnfreezeAfterSceneIsStreamed
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// Performs a skip warp which should be done behind a fadeout
/// PARAMS:
/// sAssetData - asset management struct
/// vCoord - player ped coord to warp to
/// fHeading - player ped heading
/// vFrustumCoord -
/// vFrustumDir -
/// fFrustumFarClip -
/// bUnfreezeAfterSceneIsStreamed -
/// RETURNS:
/// Returns TRUE once successfully started a skip warp
FUNC BOOL Mission_Skip_Player_Warp_Frustum(ASSET_MANAGEMENT_DATA &sAssetData, VECTOR vCoord, FLOAT fHeading, VECTOR vFrustumCoord, VECTOR vFrustumDir, FLOAT fFrustumFarClip, BOOL bUnfreezeAfterSceneIsStreamed = TRUE)
IF Load_Asset_NewLoadScene_Frustum(sAssetData, vFrustumCoord, vFrustumDir, fFrustumFarClip, NEWLOADSCENE_FLAG_REQUIRE_COLLISION)
SET_ENTITY_COORDS(PLAYER_PED_ID(), vCoord)
SET_ENTITY_HEADING(PLAYER_PED_ID(), fHeading)
FREEZE_ENTITY_POSITION(PLAYER_PED_ID(), TRUE)
sAssetData.bIsSkipWarping = TRUE
sAssetData.bUnfreezePlayerAtEnd = bUnfreezeAfterSceneIsStreamed
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
//PURPOSE: Loading loop that manages asset loading and clean up, must be called everyframe
FUNC BOOL Process_Streaming(ASSET_MANAGEMENT_DATA &sAssetData)
IF sAssetData.bStreamingLoopAwake
BOOL bStreamingProcessed = TRUE
INT i
REPEAT ASSETS_MAX_NUM_MODELS i
// Process models
IF sAssetData.sModels[i].status.bRequested
IF NOT sAssetData.sModels[i].status.bLoaded
IF HAS_MODEL_LOADED(sAssetData.sModels[i].modelName)
CDEBUG3LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] LOADED Model: \"", sAssetData.sModels[i].modelName, "\"")
sAssetData.sModels[i].status.bLoaded = TRUE
ELSE
CDEBUG3LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] NOT_LOADED Model: \"", sAssetData.sModels[i].modelName, "\"")
bStreamingProcessed = FALSE
ENDIF
ENDIF
// Cleanup
IF sAssetData.sModels[i].status.bCleanup
IF sAssetData.sModels[i].status.bLoaded
SET_MODEL_AS_NO_LONGER_NEEDED(sAssetData.sModels[i].modelName)
CDEBUG3LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] CLEANED_UP Model: \"", sAssetData.sModels[i].modelName, "\"")
Reset_Asset_Slot(sAssetData.sModels[i].status)
ELSE
bStreamingProcessed = FALSE
ENDIF
ENDIF
ENDIF
ENDREPEAT
REPEAT ASSETS_MAX_NUM_ANIM_DICTS i
// Process animation dictionaries
IF sAssetData.sAnimDicts[i].status.bRequested
IF NOT sAssetData.sAnimDicts[i].status.bLoaded
IF HAS_ANIM_DICT_LOADED(sAssetData.sAnimDicts[i].strAssetName)
CDEBUG3LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] LOADED Animation dictionary: \"", sAssetData.sAnimDicts[i].strAssetName, "\"")
sAssetData.sAnimDicts[i].status.bLoaded = TRUE
ELSE
CDEBUG3LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] NOT_LOADED Animation dictionary: \"", sAssetData.sAnimDicts[i].strAssetName, "\"")
bStreamingProcessed = FALSE
ENDIF
ENDIF
IF sAssetData.sAnimDicts[i].status.bCleanup
IF sAssetData.sAnimDicts[i].status.bLoaded
CDEBUG3LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] CLEANED_UP Animation dictionary: \"", sAssetData.sAnimDicts[i].strAssetName, "\"")
REMOVE_ANIM_DICT(sAssetData.sAnimDicts[i].strAssetName)
Reset_Asset_Slot(sAssetData.sAnimDicts[i].status)
ELSE
bStreamingProcessed = FALSE
ENDIF
ENDIF
ENDIF
ENDREPEAT
REPEAT ASSETS_MAX_NUM_WAYPOINTS i
// Process waypoint recordings
IF sAssetData.sWaypoints[i].status.bRequested
IF NOT sAssetData.sWaypoints[i].status.bLoaded
IF GET_IS_WAYPOINT_RECORDING_LOADED(sAssetData.sWaypoints[i].strAssetName)
CDEBUG3LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] LOADED Waypoint recording: \"", sAssetData.sWaypoints[i].strAssetName, "\"")
sAssetData.sWaypoints[i].status.bLoaded = TRUE
ELSE
CDEBUG3LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] NOT_LOADED Waypoint recording: \"", sAssetData.sWaypoints[i].strAssetName, "\"")
bStreamingProcessed = FALSE
ENDIF
ENDIF
IF sAssetData.sWaypoints[i].status.bCleanup
IF sAssetData.sWaypoints[i].status.bLoaded
CDEBUG3LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] CLEANED_UP waypoint recording: \"", sAssetData.sAnimDicts[i].strAssetName, "\"")
REMOVE_WAYPOINT_RECORDING(sAssetData.sWaypoints[i].strAssetName)
Reset_Asset_Slot(sAssetData.sWaypoints[i].status)
ELSE
bStreamingProcessed = FALSE
ENDIF
ENDIF
ENDIF
ENDREPEAT
REPEAT ASSETS_MAX_NUM_SCALEFORM i
// Process scaleform movies
IF sAssetData.sScaleformMovies[i].status.bRequested
IF NOT sAssetData.sScaleformMovies[i].status.bLoaded
IF HAS_SCALEFORM_MOVIE_LOADED(sAssetData.sScaleformMovies[i].sfi)
CDEBUG3LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] LOADED Scaleform movie: \"", sAssetData.sScaleformMovies[i].strScaleformName, "\"")
sAssetData.sScaleformMovies[i].status.bLoaded = TRUE
ELSE
CDEBUG3LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] NOT_LOADED Scaleform movie: \"", sAssetData.sScaleformMovies[i].strScaleformName, "\"")
bStreamingProcessed = FALSE
ENDIF
ENDIF
IF sAssetData.sScaleformMovies[i].status.bCleanup
IF sAssetData.sScaleformMovies[i].status.bLoaded
CDEBUG3LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] CLEANED_UP waypoint recording: \"", sAssetData.sScaleformMovies[i].strScaleformName, "\"")
SET_SCALEFORM_MOVIE_AS_NO_LONGER_NEEDED(sAssetData.sScaleformMovies[i].sfi)
Reset_Asset_Slot(sAssetData.sScaleformMovies[i].status)
ELSE
bStreamingProcessed = FALSE
ENDIF
ENDIF
ENDIF
ENDREPEAT
REPEAT ASSETS_MAX_NUM_VEH_RECS i
// Process vehicle recordings
IF sAssetData.sVehRecs[i].status.bRequested
IF NOT sAssetData.sVehRecs[i].status.bLoaded
IF HAS_VEHICLE_RECORDING_BEEN_LOADED(sAssetData.sVehRecs[i].iRecNo, sAssetData.sVehRecs[i].strRecName)
CDEBUG3LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] LOADED VehicleRec: \"", sAssetData.sVehRecs[i].strRecName, sAssetData.sVehRecs[i].iRecNo, "\"")
sAssetData.sVehRecs[i].status.bLoaded = TRUE
ELSE
CDEBUG3LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] NOT_LOADED VehicleRec: \"", sAssetData.sVehRecs[i].strRecName, sAssetData.sVehRecs[i].iRecNo, "\"")
bStreamingProcessed = FALSE
ENDIF
ENDIF
IF sAssetData.sVehRecs[i].status.bCleanup
IF sAssetData.sVehRecs[i].status.bLoaded
CDEBUG3LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] CLEANED_UP VehicleRec: \"", sAssetData.sVehRecs[i].strRecName, sAssetData.sVehRecs[i].iRecNo, "\"")
REMOVE_VEHICLE_RECORDING(sAssetData.sVehRecs[i].iRecNo, sAssetData.sVehRecs[i].strRecName)
Reset_Asset_Slot(sAssetData.sVehRecs[i].status)
ELSE
bStreamingProcessed = FALSE
ENDIF
ENDIF
ENDIF
ENDREPEAT
REPEAT ASSETS_MAX_NUM_WEAP_ASSETS i
// Process weapon assets
IF sAssetData.sWeapons[i].status.bRequested
IF NOT sAssetData.sWeapons[i].status.bLoaded
IF HAS_WEAPON_ASSET_LOADED(sAssetData.sWeapons[i].weapType)
CDEBUG3LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] LOADED Weapon asset: \"", sAssetData.sWeapons[i].weapType, "\"")
sAssetData.sWeapons[i].status.bLoaded = TRUE
ELSE
CDEBUG3LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] NOT_LOADED Weapon asset: \"", sAssetData.sWeapons[i].weapType, "\"")
bStreamingProcessed = FALSE
ENDIF
ENDIF
IF sAssetData.sWeapons[i].status.bCleanup
IF sAssetData.sWeapons[i].status.bLoaded
CDEBUG3LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] CLEANED_UP Weapon asset: \"", sAssetData.sWeapons[i].weapType, "\"")
REMOVE_WEAPON_ASSET(sAssetData.sWeapons[i].weapType)
Reset_Asset_Slot(sAssetData.sWeapons[i].status)
ELSE
bStreamingProcessed = FALSE
ENDIF
ENDIF
ENDIF
ENDREPEAT
REPEAT ASSETS_MAX_NUM_VEH_ASSETS i
// Process vehicle asset
IF sAssetData.sVehicleAssets[i].status.bRequested
IF NOT sAssetData.sVehicleAssets[i].status.bLoaded
IF HAS_VEHICLE_ASSET_LOADED(sAssetData.sVehicleAssets[i].modelName)
CDEBUG3LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] LOADED Vehicle asset: \"", sAssetData.sVehicleAssets[i].modelName, "\"")
sAssetData.sVehicleAssets[i].status.bLoaded = TRUE
ELSE
CDEBUG3LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] NOT_LOADED Vehicle asset: \"", sAssetData.sVehicleAssets[i].modelName, "\"")
bStreamingProcessed = FALSE
ENDIF
ENDIF
// Cleanup
IF sAssetData.sVehicleAssets[i].status.bCleanup
IF sAssetData.sVehicleAssets[i].status.bLoaded
REMOVE_VEHICLE_ASSET(sAssetData.sVehicleAssets[i].modelName)
CDEBUG3LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] CLEANED_UP Vehicle asset: \"", sAssetData.sVehicleAssets[i].modelName, "\"")
Reset_Asset_Slot(sAssetData.sVehicleAssets[i].status)
ELSE
bStreamingProcessed = FALSE
ENDIF
ENDIF
ENDIF
ENDREPEAT
REPEAT ASSETS_MAX_NUM_AUDIO_BANKS i
// Process audiobanks
IF sAssetData.sAudiobanks[i].status.bRequested
IF NOT sAssetData.sAudiobanks[i].status.bLoaded
IF REQUEST_SCRIPT_AUDIO_BANK(sAssetData.sAudiobanks[i].strAssetName)
CDEBUG3LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] LOADED Audiobank: \"", sAssetData.sAudiobanks[i].strAssetName, "\"")
sAssetData.sAudiobanks[i].status.bLoaded = TRUE
ELSE
CDEBUG3LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] NOT_LOADED Audiobank: \"", sAssetData.sAudiobanks[i].strAssetName, "\"")
bStreamingProcessed = FALSE
ENDIF
ENDIF
IF sAssetData.sAudiobanks[i].status.bCleanup
IF sAssetData.sAudiobanks[i].status.bLoaded
CDEBUG3LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] CLEANED_UP Audiobank: \"", sAssetData.sAudiobanks[i].strAssetName, "\"")
RELEASE_NAMED_SCRIPT_AUDIO_BANK(sAssetData.sAudiobanks[i].strAssetName)
Reset_Asset_Slot(sAssetData.sAudiobanks[i].status)
ELSE
bStreamingProcessed = FALSE
ENDIF
ENDIF
ENDIF
ENDREPEAT
REPEAT ASSETS_MAX_NUM_INTERIORS i
// Process interiors
IF sAssetData.sInteriors[i].status.bRequested
IF NOT sAssetData.sInteriors[i].status.bLoaded
IF IS_INTERIOR_READY(sAssetData.sInteriors[i].iii)
CDEBUG3LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] LOADED(PINNED) Interior")
sAssetData.sInteriors[i].status.bLoaded = TRUE
ELSE
CDEBUG3LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] NOT_LOADED Interior")
bStreamingProcessed = FALSE
ENDIF
ENDIF
IF sAssetData.sInteriors[i].status.bCleanup
IF sAssetData.sInteriors[i].status.bLoaded
CDEBUG3LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] CLEANED_UP(UNPINNED) Interior")
UNPIN_INTERIOR(sAssetData.sInteriors[i].iii)
Reset_Asset_Slot(sAssetData.sInteriors[i].status)
ELSE
bStreamingProcessed = FALSE
ENDIF
ENDIF
ENDIF
ENDREPEAT
REPEAT ASSETS_MAX_NUM_MOVIE_MESH_SETS i
// Process movie mesh set
IF NOT IS_STRING_NULL_OR_EMPTY(sAssetData.sMovieMeshSets[i].strMeshSetName)
IF sAssetData.sMovieMeshSets[i].status.bRequested
MOVIEMESHSETSTATE mms_state
mms_state = QUERY_MOVIE_MESH_SET_STATE(sAssetData.sMovieMeshSets[i].mmsi)
IF NOT sAssetData.sMovieMeshSets[i].status.bLoaded
SWITCH mms_state
CASE MMS_LOADED
CASE MMS_READY
sAssetData.sMovieMeshSets[i].status.bLoaded = TRUE
CDEBUG3LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] LOADED Movie Mesh Set: \"", sAssetData.sMovieMeshSets[i].strMeshSetName, "\"")
BREAK
CASE MMS_PENDING_LOAD
sAssetData.sMovieMeshSets[i].status.bLoaded = FALSE
CDEBUG3LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] NOT_LOADED Movie Mesh Set: \"", sAssetData.sMovieMeshSets[i].strMeshSetName, "\"")
bStreamingProcessed = FALSE
BREAK
CASE MMS_PENDING_DELETE
sAssetData.sMovieMeshSets[i].status.bLoaded = FALSE
CDEBUG3LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] PENDING_DELETE Movie Mesh Set: \"", sAssetData.sMovieMeshSets[i].strMeshSetName, "\"")
Reset_Asset_Slot(sAssetData.sMovieMeshSets[i].status)
BREAK
CASE MMS_FAILED
sAssetData.sMovieMeshSets[i].status.bLoaded = FALSE
CDEBUG3LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] MOVIE_LOAD_FAILED releasing Movie Mesh Set: \"", sAssetData.sMovieMeshSets[i].strMeshSetName, "\"")
// Rerequest the failed movie mesh directly here
RELEASE_MOVIE_MESH_SET(sAssetData.sMovieMeshSets[i].mmsi)
sAssetData.sMovieMeshSets[i].status.bRequested = FALSE
bStreamingProcessed = FALSE
BREAK
ENDSWITCH
ENDIF
// Not requested yet, attempt to request it
ELSE
IF IS_INTERIOR_READY(sAssetData.sMovieMeshSets[i].interior)
CDEBUG3LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] INTERIOR_READY - Requesting Movie Mesh Set: \"", sAssetData.sMovieMeshSets[i].strMeshSetName, "\"")
sAssetData.sMovieMeshSets[i].mmsi = LOAD_MOVIE_MESH_SET(sAssetData.sMovieMeshSets[i].strMeshSetName)
sAssetData.sMovieMeshSets[i].status.iTimestamp = GET_GAME_TIMER()
sAssetData.sMovieMeshSets[i].status.bRequested = TRUE
ELSE
CDEBUG3LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] INTERIOR_NOT_READY - Movie Mesh Set: \"", sAssetData.sMovieMeshSets[i].strMeshSetName, "\"")
bStreamingProcessed = FALSE
ENDIF
ENDIF
IF sAssetData.sMovieMeshSets[i].status.bCleanup
IF sAssetData.sMovieMeshSets[i].status.bRequested
IF sAssetData.sMovieMeshSets[i].status.bLoaded
CDEBUG3LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] CLEANED_UP Movie Mesh Set: \"", sAssetData.sMovieMeshSets[i].strMeshSetName, "\"")
RELEASE_MOVIE_MESH_SET(sAssetData.sMovieMeshSets[i].mmsi)
Reset_Asset_Slot(sAssetData.sMovieMeshSets[i].status)
sAssetData.sMovieMeshSets[i].strMeshSetName = ""
ELSE
CDEBUG3LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] WAITING_TO_CLEAN_UP Movie Mesh Set: \"", sAssetData.sMovieMeshSets[i].strMeshSetName, "\"")
bStreamingProcessed = FALSE // wait for it to load before we try and clean it up
ENDIF
ELSE
CDEBUG3LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] REMOVED FROM QUEUE Movie Mesh Set: \"", sAssetData.sMovieMeshSets[i].strMeshSetName, "\"")
Reset_Asset_Slot(sAssetData.sMovieMeshSets[i].status)
ENDIF
ENDIF
ENDIF
ENDREPEAT
REPEAT ASSETS_MAX_NUM_ASSISTED_LINES i
// Process assisted lines
IF sAssetData.sAssistedLines[i].status.bRequested
IF NOT sAssetData.sAssistedLines[i].status.bLoaded
IF ASSISTED_MOVEMENT_IS_ROUTE_LOADED(sAssetData.sAssistedLines[i].strAssetName)
CDEBUG3LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] LOADED Assisted Line: \"", sAssetData.sAssistedLines[i].strAssetName, "\"")
sAssetData.sAssistedLines[i].status.bLoaded = TRUE
ELSE
CDEBUG3LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] NOT_LOADED Assisted Line: \"", sAssetData.sAssistedLines[i].strAssetName, "\"")
bStreamingProcessed = FALSE
ENDIF
ENDIF
IF sAssetData.sAssistedLines[i].status.bCleanup
IF sAssetData.sAssistedLines[i].status.bLoaded
CDEBUG3LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] CLEANED_UP Assisted Line: \"", sAssetData.sAssistedLines[i].strAssetName, "\"")
ASSISTED_MOVEMENT_REMOVE_ROUTE(sAssetData.sAssistedLines[i].strAssetName)
Reset_Asset_Slot(sAssetData.sAssistedLines[i].status)
ELSE
bStreamingProcessed = FALSE
ENDIF
ENDIF
ENDIF
ENDREPEAT
REPEAT ASSETS_MAX_NUM_ALARMS i
// Process alarms
IF sAssetData.sAlarms[i].status.bRequested
IF NOT sAssetData.sAlarms[i].status.bLoaded
IF PREPARE_ALARM(sAssetData.sAlarms[i].strAssetName)
CDEBUG3LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] LOADED Alarm: \"", sAssetData.sAlarms[i].strAssetName, "\"")
sAssetData.sAlarms[i].status.bLoaded = TRUE
ELSE
CDEBUG3LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] NOT_LOADED AAlarm: \"", sAssetData.sAlarms[i].strAssetName, "\"")
bStreamingProcessed = FALSE
ENDIF
ENDIF
IF sAssetData.sAlarms[i].status.bCleanup
IF sAssetData.sAlarms[i].status.bLoaded
CDEBUG3LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] CLEANED_UP Alarm: \"", sAssetData.sAlarms[i].strAssetName, "\"")
Reset_Asset_Slot(sAssetData.sAlarms[i].status)
ELSE
bStreamingProcessed = FALSE
ENDIF
ENDIF
ENDIF
ENDREPEAT
// Process text blocks
REPEAT COUNT_OF(sAssetData.sTextBlocks) i
IF sAssetData.sTextBlocks[i].status.bRequested
IF NOT sAssetData.sTextBlocks[i].status.bLoaded
IF HAS_ADDITIONAL_TEXT_LOADED(int_to_enum(TEXT_BLOCK_SLOTS, i))
CDEBUG3LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] LOADED Textblock: \"", sAssetData.sTextBlocks[i].strBlockName, " into slot " , i, "\"")
sAssetData.sTextBlocks[i].status.bLoaded = TRUE
ELSE
CDEBUG3LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] NOT_LOADED Textblock: \"", sAssetData.sTextBlocks[i].strBlockName, " into slot " , i, "\"")
bStreamingProcessed = FALSE
ENDIF
ENDIF
IF sAssetData.sTextBlocks[i].status.bCleanup
IF sAssetData.sTextBlocks[i].status.bLoaded
CDEBUG3LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] CLEANED_UP Textblock: \"", sAssetData.sTextBlocks[i].strBlockName, " from slot " , i, "\"")
CLEAR_ADDITIONAL_TEXT(int_to_enum(TEXT_BLOCK_SLOTS, i), TRUE)
Reset_Asset_Slot(sAssetData.sTextBlocks[i].status)
ELSE
bStreamingProcessed = FALSE
ENDIF
ENDIF
ENDIF
ENDREPEAT
// Process PTFX asset
IF sAssetData.sPTFX.bRequested
IF NOT sAssetData.sPTFX.bLoaded
IF HAS_PTFX_ASSET_LOADED()
sAssetData.sPTFX.bLoaded = TRUE
CDEBUG1LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] LOADED PTFX")
ELSE
CDEBUG1LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] NOT_LOADED PTFX")
bStreamingProcessed = FALSE
ENDIF
ENDIF
IF sAssetData.sPTFX.bCleanup
IF sAssetData.sPTFX.bLoaded
CDEBUG1LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] CLEANED_UP PTFX")
REMOVE_PTFX_ASSET()
Reset_Asset_Slot(sAssetData.sPTFX)
ELSE
bStreamingProcessed = FALSE
ENDIF
ENDIF
ENDIF
// Process ropes asset
IF sAssetData.sRopes.bRequested
IF NOT sAssetData.sRopes.bLoaded
IF ROPE_ARE_TEXTURES_LOADED()
sAssetData.sRopes.bLoaded = TRUE
CDEBUG1LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] LOADED ROPES")
ELSE
CDEBUG1LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] NOT_LOADED ROPES")
bStreamingProcessed = FALSE
ENDIF
ENDIF
IF sAssetData.sRopes.bCleanup
IF sAssetData.sRopes.bLoaded
CDEBUG1LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] CLEANED_UP ROPES")
ROPE_UNLOAD_TEXTURES()
Reset_Asset_Slot(sAssetData.sRopes)
ELSE
bStreamingProcessed = FALSE
ENDIF
ENDIF
ENDIF
// Process new load scene
IF sAssetData.sLoadScene.status.bRequested
AND IS_NEW_LOAD_SCENE_ACTIVE()
IF NOT sAssetData.sLoadScene.status.bLoaded
IF IS_NEW_LOAD_SCENE_LOADED()
sAssetData.sLoadScene.status.bLoaded = TRUE
CDEBUG1LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] LOADED NewLoadScene - Coord: ", sAssetData.sLoadScene.vCoord, " Radius/FarClip: ", sAssetData.sLoadScene.fDist, " Dir: ", sAssetData.sLoadScene.vDir)
IF sAssetData.bIsSkipWarping
FREEZE_ENTITY_POSITION(PLAYER_PED_ID(), FALSE)
Unload_Asset_NewLoadScene(sAssetData)
sAssetData.bIsSkipWarping = FALSE
ENDIF
ELSE
CDEBUG1LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] NOT_LOADED NewLoadScene - Coord: ", sAssetData.sLoadScene.vCoord, " Radius/FarClip: ", sAssetData.sLoadScene.fDist, " Dir: ", sAssetData.sLoadScene.vDir)
bStreamingProcessed = FALSE
ENDIF
ENDIF
// PRECAUTION ONLY: loadscenes can be stopped instantly so doesnt't need to wait for a load the finish
// also shouldn't need a cleanup in here but scripted as a backup
IF sAssetData.sLoadScene.status.bCleanup
NEW_LOAD_SCENE_STOP()
Reset_Asset_Slot(sAssetData.sLoadScene.status)
ENDIF
ENDIF
#IF USE_TU_CHANGES
REPEAT ASSETS_MAC_NUM_TEXTURE_DICTS i
// Process streamed texture dictionaries
IF sAssetData.sStreamedTextureDicts[i].status.bRequested
IF NOT sAssetData.sStreamedTextureDicts[i].status.bLoaded
IF HAS_STREAMED_TEXTURE_DICT_LOADED(sAssetData.sStreamedTextureDicts[i].strAssetName)
CDEBUG3LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] LOADED Streamed Texture Dictionary: \"", sAssetData.sStreamedTextureDicts[i].strAssetName, "\"")
sAssetData.sStreamedTextureDicts[i].status.bLoaded = TRUE
ELSE
CDEBUG3LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] NOT_LOADED Streamed Texture Dictionary: \"", sAssetData.sStreamedTextureDicts[i].strAssetName, "\"")
bStreamingProcessed = FALSE
ENDIF
ENDIF
IF sAssetData.sStreamedTextureDicts[i].status.bCleanup
IF sAssetData.sStreamedTextureDicts[i].status.bLoaded
CDEBUG3LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT][", i,"] CLEANED_UP Steamed Texture Dictionary: \"", sAssetData.sStreamedTextureDicts[i].strAssetName, "\"")
Reset_Asset_Slot(sAssetData.sStreamedTextureDicts[i].status)
ELSE
bStreamingProcessed = FALSE
ENDIF
ENDIF
ENDIF
ENDREPEAT
#ENDIF
// If everything has loaded then put the loaded loop to sleep
IF bStreamingProcessed
sAssetData.bStreamingLoopAwake = FALSE
RETURN TRUE
ELSE
RETURN FALSE
ENDIF
ENDIF
RETURN TRUE
ENDFUNC
//PURPOSE: Informs the asset management system that you are about to perform asset streaming for a skip (z/p/j/retry).
PROC Start_Skip_Streaming(ASSET_MANAGEMENT_DATA &sAssetData)
INT i
REPEAT ASSETS_MAX_NUM_MODELS i
IF sAssetData.sModels[i].status.bRequested
sAssetData.sModels[i].status.bCleanup = TRUE
ENDIF
ENDREPEAT
REPEAT ASSETS_MAX_NUM_VEH_ASSETS i
IF sAssetData.sVehicleAssets[i].status.bRequested
sAssetData.sVehicleAssets[i].status.bCleanup = TRUE
ENDIF
ENDREPEAT
REPEAT ASSETS_MAX_NUM_WEAP_ASSETS i
IF sAssetData.sWeapons[i].status.bRequested
sAssetData.sWeapons[i].status.bCleanup = TRUE
ENDIF
ENDREPEAT
REPEAT ASSETS_MAX_NUM_ANIM_DICTS i
IF sAssetData.sAnimDicts[i].status.bRequested
sAssetData.sAnimDicts[i].status.bCleanup = TRUE
ENDIF
ENDREPEAT
REPEAT ASSETS_MAX_NUM_WAYPOINTS i
IF sAssetData.sWaypoints[i].status.bRequested
sAssetData.sWaypoints[i].status.bCleanup = TRUE
ENDIF
ENDREPEAT
REPEAT ASSETS_MAX_NUM_VEH_RECS i
IF sAssetData.sVehRecs[i].status.bRequested
sAssetData.sVehRecs[i].status.bCleanup = TRUE
ENDIF
ENDREPEAT
REPEAT ASSETS_MAX_NUM_SCALEFORM i
IF sAssetData.sScaleformMovies[i].status.bRequested
sAssetData.sScaleformMovies[i].status.bCleanup = TRUE
ENDIF
ENDREPEAT
REPEAT ASSETS_MAX_NUM_MOVIE_MESH_SETS i
IF sAssetData.sMovieMeshSets[i].status.bRequested
sAssetData.sMovieMeshSets[i].status.bCleanup = TRUE
ENDIF
ENDREPEAT
REPEAT ASSETS_MAX_NUM_AUDIO_BANKS i
IF sAssetData.sAudioBanks[i].status.bRequested
sAssetData.sAudioBanks[i].status.bCleanup = TRUE
ENDIF
ENDREPEAT
REPEAT ASSETS_MAX_NUM_INTERIORS i
IF sAssetData.sInteriors[i].status.bRequested
sAssetData.sInteriors[i].status.bCleanup = TRUE
ENDIF
ENDREPEAT
REPEAT ASSETS_MAX_NUM_ASSISTED_LINES i
IF sAssetData.sAssistedLines[i].status.bRequested
sAssetData.sAssistedLines[i].status.bCleanup = TRUE
ENDIF
ENDREPEAT
REPEAT ASSETS_MAX_NUM_ALARMS i
IF sAssetData.sAlarms[i].status.bRequested
sAssetData.sAlarms[i].status.bCleanup = TRUE
ENDIF
ENDREPEAT
REPEAT NUM_ADDITIONAL_TEXT_SLOTS i
IF sAssetData.sTextBlocks[i].status.bRequested
sAssetData.sTextBlocks[i].status.bCleanup = TRUE
ENDIF
ENDREPEAT
IF sAssetData.sLoadScene.status.bRequested
sAssetData.sLoadScene.status.bCleanup = TRUE
ENDIF
IF sAssetData.sPTFX.bRequested
sAssetData.sPTFX.bCleanup = TRUE
ENDIF
IF sAssetData.sRopes.bRequested
sAssetData.sRopes.bCleanup = TRUE
ENDIF
ENDPROC
/// PURPOSE: Process the streamig during a skip. Call in a loop until returns true.
FUNC BOOL Update_Skip_Streaming(ASSET_MANAGEMENT_DATA &sAssetData)
IF Process_Streaming(sAssetData)
CDEBUG3LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT] Skip streaming complete.")
RETURN TRUE
ELSE
CDEBUG3LN(DEBUG_MIKE_UTIL, "[ASSET MANAGEMENT] Updating skip streaming...")
RETURN FALSE
ENDIF
ENDFUNC
//PURPOSE: Call each frame to update the asset management system during normal mission flow
// Will also draw debug information.
PROC Update_Asset_Management_System(ASSET_MANAGEMENT_DATA &sAssetData)
Process_Streaming(sAssetData)
ENDPROC
STRUCT CUTSCENE_PED_VARIATION
#IF USE_TU_CHANGES
TEXT_LABEL_63 handle
#ENDIF
#IF NOT USE_TU_CHANGES
STRING handle
#ENDIF
MODEL_NAMES model
PED_VARIATION_STRUCT variationData
ENDSTRUCT
//PURPOSE: Resets the ped variation streaming
PROC Reset_Cutscene_Ped_Variation_Streaming(CUTSCENE_PED_VARIATION &sCutscenePedVariationRegister[])
INT i
PED_COMPONENT j
REPEAT COUNT_OF(sCutscenePedVariationRegister) i
IF NOT IS_STRING_NULL_OR_EMPTY(sCutscenePedVariationRegister[i].handle)
CDEBUG2LN(DEBUG_MIKE_UTIL, "[", i, "]", "Resetting stored variation for ped: ", sCutscenePedVariationRegister[i].handle, " model: ", sCutscenePedVariationRegister[i].model)
#IF USE_TU_CHANGES
sCutscenePedVariationRegister[i].handle = "" //NULL
#ENDIF
#IF NOT USE_TU_CHANGES
sCutscenePedVariationRegister[i].handle = NULL
#ENDIF
sCutscenePedVariationRegister[i].model = DUMMY_MODEL_FOR_SCRIPT
REPEAT NUM_PED_COMPONENTS j
sCutscenePedVariationRegister[i].variationData.iDrawableVariation[j] = -1
sCutscenePedVariationRegister[i].variationData.iTextureVariation[j] = -1
ENDREPEAT
ENDIF
ENDREPEAT
ENDPROC
//PURPOSE: Updates the cutscene streaming
PROC Update_Cutscene_Prestreaming(CUTSCENE_PED_VARIATION &sCutscenePedVariationRegister[])
IF IS_CUTSCENE_ACTIVE()
IF CAN_REQUEST_ASSETS_FOR_CUTSCENE_ENTITY()
INT i
PED_COMPONENT j
PED_PROP_POSITION k
REPEAT COUNT_OF(sCutscenePedVariationRegister) i
IF NOT IS_STRING_NULL_OR_EMPTY(sCutscenePedVariationRegister[i].handle)
REPEAT NUM_PED_COMPONENTS j
// only set a particular componenet if it does NOT equal -1
IF sCutscenePedVariationRegister[i].variationData.iDrawableVariation[j] != -1
AND sCutscenePedVariationRegister[i].variationData.iTextureVariation[j] != -1
CDEBUG2LN(DEBUG_MIKE_UTIL, "[", i, "]", "Setting component for ped: ", sCutscenePedVariationRegister[i].handle, " model: ", sCutscenePedVariationRegister[i].model, " component: ", GET_COMP_VARIATION_TYPE_STRING(j), " drawable: ", sCutscenePedVariationRegister[i].variationData.iDrawableVariation[j], " texture: ", sCutscenePedVariationRegister[i].variationData.iTextureVariation[j])
SET_CUTSCENE_PED_COMPONENT_VARIATION(sCutscenePedVariationRegister[i].handle, int_to_enum(PED_COMPONENT, j),
sCutscenePedVariationRegister[i].variationData.iDrawableVariation[j],
sCutscenePedVariationRegister[i].variationData.iTextureVariation[j],
sCutscenePedVariationRegister[i].model)
// once set change the component data to -1
sCutscenePedVariationRegister[i].variationData.iDrawableVariation[j] = -1
sCutscenePedVariationRegister[i].variationData.iTextureVariation[j] = -1
ENDIF
ENDREPEAT
REPEAT COUNT_OF(PED_PROP_POSITION) k
// only set a particular componenet if it does NOT equal -1
IF sCutscenePedVariationRegister[i].variationData.iPropIndex[k] != -1
AND sCutscenePedVariationRegister[i].variationData.iPropTexture[k] != -1
CDEBUG2LN(DEBUG_MIKE_UTIL, "[", i, "]", "Setting prop for ped: ", sCutscenePedVariationRegister[i].handle, " model: ", sCutscenePedVariationRegister[i].model, " prop anchor: ", GET_PROP_POSITION_STRING(k), " propID: ", sCutscenePedVariationRegister[i].variationData.iPropIndex[k], " texture: ", sCutscenePedVariationRegister[i].variationData.iPropTexture[k])
SET_CUTSCENE_PED_PROP_VARIATION(sCutscenePedVariationRegister[i].handle, int_to_enum(PED_PROP_POSITION, k),
sCutscenePedVariationRegister[i].variationData.iPropIndex[k],
sCutscenePedVariationRegister[i].variationData.iPropTexture[k],
sCutscenePedVariationRegister[i].model)
// once set change the component data to -1
sCutscenePedVariationRegister[i].variationData.iPropIndex[k] = -1
sCutscenePedVariationRegister[i].variationData.iPropTexture[k] = -1
ENDIF
ENDREPEAT
#IF USE_TU_CHANGES
sCutscenePedVariationRegister[i].handle = "" //NULL
#ENDIF
#IF NOT USE_TU_CHANGES
sCutscenePedVariationRegister[i].handle = NULL
#ENDIF
sCutscenePedVariationRegister[i].model = DUMMY_MODEL_FOR_SCRIPT
ENDIF
ENDREPEAT
ENDIF
// No cutscene running, reset the streaming array
ELSE
Reset_Cutscene_Ped_Variation_Streaming(sCutscenePedVariationRegister)
ENDIF
ENDPROC
/// PURPOSE:
/// Registers an individual ped variation component with the prestreaming system.
/// PARAMS:
/// pedHandle - ped's cutscene handle
/// comp - component being set
/// iDrawable - the desired drawable
/// iTexture - the desired texture
/// pedModelName - model name (not always needed)
PROC Register_Ped_Variation_For_Cutscene(CUTSCENE_PED_VARIATION &sCutscenePedVariationRegister[], STRING pedHandle, PED_COMPONENT comp, INT iDrawable, INT iTexture, MODEL_NAMES pedModelName = DUMMY_MODEL_FOR_SCRIPT)
IF IS_CUTSCENE_PLAYING()
SCRIPT_ASSERT("Cannot register ped variation for cutscene as cutscene is currently playing.")
ELSE
INT i
INT iFreeSlot = -1
REPEAT COUNT_OF(sCutscenePedVariationRegister) i
IF IS_STRING_NULL_OR_EMPTY(sCutscenePedVariationRegister[i].handle)
// store the index of this free slot
IF iFreeSlot = -1
iFreeSlot = i
ENDIF
ELIF ARE_STRINGS_EQUAL(pedHandle, sCutscenePedVariationRegister[i].handle)
AND pedModelName = sCutscenePedVariationRegister[i].model
// already requested for the specific entity
IF sCutscenePedVariationRegister[i].variationData.iDrawableVariation[comp] != iDrawable
OR sCutscenePedVariationRegister[i].variationData.iTextureVariation[comp] != iTexture
IF sCutscenePedVariationRegister[i].variationData.iDrawableVariation[comp] = -1
AND sCutscenePedVariationRegister[i].variationData.iTextureVariation[comp] = -1
CDEBUG2LN(DEBUG_MIKE_UTIL, "[", i,"] Storing new ped variation for ped: ", pedHandle, " model: ", sCutscenePedVariationRegister[i].model, " component: ", GET_COMP_VARIATION_TYPE_STRING(comp))
ELSE
CDEBUG2LN(DEBUG_MIKE_UTIL, "[", i,"] Overwriting stored variation for ped: ", pedHandle, " model: ", sCutscenePedVariationRegister[i].model, " component: ", GET_COMP_VARIATION_TYPE_STRING(comp))
CDEBUG2LN(DEBUG_MIKE_UTIL, " Old variation - Drawable: ", sCutscenePedVariationRegister[i].variationData.iDrawableVariation[comp], " Textrue: ", sCutscenePedVariationRegister[i].variationData.iTextureVariation[comp])
ENDIF
CDEBUG2LN(DEBUG_MIKE_UTIL, " New variation - Drawable: ", iDrawable, " Textrue: ", iTexture)
// update the component and wake up the looks
sCutscenePedVariationRegister[i].variationData.iDrawableVariation[comp] = iDrawable
sCutscenePedVariationRegister[i].variationData.iTextureVariation[comp] = iTexture
ELSE
CDEBUG2LN(DEBUG_MIKE_UTIL, "[", i,"] Specified ped variation for ped: ", pedHandle, " model: ", sCutscenePedVariationRegister[i].model, " component: ", GET_COMP_VARIATION_TYPE_STRING(comp), " is already set.")
CDEBUG2LN(DEBUG_MIKE_UTIL, " Stored variation - Drawable: ", sCutscenePedVariationRegister[i].variationData.iDrawableVariation[comp], " Textrue: ", sCutscenePedVariationRegister[i].variationData.iTextureVariation[comp])
ENDIF
EXIT
ENDIF
ENDREPEAT
// no variation registered yet, register a new one or a change was detected, update the slot
IF iFreeSlot != -1
sCutscenePedVariationRegister[iFreeSlot].handle = pedHandle
sCutscenePedVariationRegister[iFreeSlot].model = pedModelName
PED_COMPONENT eComp
REPEAT COUNT_OF(PED_COMPONENT) eComp
sCutscenePedVariationRegister[iFreeSlot].variationData.iDrawableVariation[eComp] = -1
sCutscenePedVariationRegister[iFreeSlot].variationData.iTextureVariation[eComp] = -1
ENDREPEAT
PED_PROP_POSITION eAnchor
REPEAT COUNT_OF(PED_PROP_POSITION) eAnchor
sCutscenePedVariationRegister[iFreeSlot].variationData.iPropIndex[eAnchor] = -1
sCutscenePedVariationRegister[iFreeSlot].variationData.iPropTexture[eAnchor] = -1
ENDREPEAT
sCutscenePedVariationRegister[iFreeSlot].variationData.iDrawableVariation[comp] = iDrawable
sCutscenePedVariationRegister[iFreeSlot].variationData.iTextureVariation[comp] = iTexture
CDEBUG2LN(DEBUG_MIKE_UTIL, "[", iFreeSlot,"] Storing new ped variation for ped: ", pedHandle, " model: ", sCutscenePedVariationRegister[iFreeSlot].model, " for component: ", GET_COMP_VARIATION_TYPE_STRING(comp))
CDEBUG2LN(DEBUG_MIKE_UTIL, " New variation - Drawable: ", sCutscenePedVariationRegister[iFreeSlot].variationData.iDrawableVariation[comp], " Textrue: ", sCutscenePedVariationRegister[iFreeSlot].variationData.iTextureVariation[comp])
ELSE
// NO FREE SLOT!
SCRIPT_ASSERT("sCutscenePedVariationRegister is FULL")
ENDIF
ENDIF
ENDPROC
PROC Register_Ped_Outfit_For_Cutscene(CUTSCENE_PED_VARIATION &sCutscenePedVariationRegister[], STRING pedHandle, PED_COMP_NAME_ENUM outfit, MODEL_NAMES pedModelName)
PED_COMP_OUTFIT_DATA_STRUCT sOutfitData = GET_PED_COMPONENT_DATA_FOR_OUTFIT(pedModelName, outfit)
INT i
REPEAT NUMBER_OF_PED_COMP_TYPES i
IF i != enum_to_int(COMP_TYPE_OUTFIT)
AND i != enum_to_int(COMP_TYPE_PROPGROUP)
AND i != enum_to_int(COMP_TYPE_PROPS)
PED_COMP_ITEM_DATA_STRUCT sTemp = GET_PED_COMP_DATA_FOR_ITEM_SP(pedModelName, INT_TO_ENUM(PED_COMP_TYPE_ENUM, i), sOutfitData.eItems[i])
Register_Ped_Variation_For_Cutscene(sCutscenePedVariationRegister, pedHandle, GET_PED_COMPONENT_FROM_TYPE(INT_TO_ENUM(PED_COMP_TYPE_ENUM, i)), sTemp.iDrawable, sTemp.iTexture, pedModelName)
ENDIF
ENDREPEAT
ENDPROC
/// PURPOSE:
/// Registers an individual ped prop variation component with the prestreaming system.
/// PARAMS:
/// pedHandle - ped's cutscene handle
/// comp - component being set
/// iDrawable - the desired drawable
/// iTexture - the desired texture
/// pedModelName - model name (not always needed)
PROC Register_Ped_Prop_For_Cutscene(CUTSCENE_PED_VARIATION &sCutscenePedVariationRegister[], STRING pedHandle, PED_PROP_POSITION anchor, INT iPropIndex, INT iTexture, MODEL_NAMES pedModelName = DUMMY_MODEL_FOR_SCRIPT)
IF IS_CUTSCENE_PLAYING()
SCRIPT_ASSERT("Cannot register prop variation for cutscene as cutscene is currently playing.")
ELSE
INT i
INT iFreeSlot = -1
REPEAT COUNT_OF(sCutscenePedVariationRegister) i
IF IS_STRING_NULL_OR_EMPTY(sCutscenePedVariationRegister[i].handle)
// store the index of this free slot
IF iFreeSlot = -1
iFreeSlot = i
ENDIF
ELIF ARE_STRINGS_EQUAL(pedHandle, sCutscenePedVariationRegister[i].handle)
AND pedModelName = sCutscenePedVariationRegister[i].model
// already requested for the specific entity
IF sCutscenePedVariationRegister[i].variationData.iPropIndex[anchor] != iPropIndex
OR sCutscenePedVariationRegister[i].variationData.iPropTexture[anchor] != iTexture
IF sCutscenePedVariationRegister[i].variationData.iPropIndex[anchor] = -1
AND sCutscenePedVariationRegister[i].variationData.iPropTexture[anchor] = -1
CDEBUG2LN(DEBUG_MIKE_UTIL, "[", i,"] Storing new prop variation for ped: ", pedHandle, " model: ", sCutscenePedVariationRegister[i].model, " prop anchor: ", GET_PROP_POSITION_STRING(anchor))
ELSE
CDEBUG2LN(DEBUG_MIKE_UTIL, "[", i,"] Overwriting stored prop for ped: ", pedHandle, " model: ", sCutscenePedVariationRegister[i].model, " prop anchor: ", GET_PROP_POSITION_STRING(anchor))
CDEBUG2LN(DEBUG_MIKE_UTIL, " Old variation - PropID: ", sCutscenePedVariationRegister[i].variationData.iPropIndex[anchor], " Textrue: ", sCutscenePedVariationRegister[i].variationData.iPropTexture[anchor])
ENDIF
CDEBUG2LN(DEBUG_MIKE_UTIL, " New prop variation - PropID: ", iPropIndex, " Textrue: ", iTexture)
// update the component and wake up the looks
sCutscenePedVariationRegister[i].variationData.iPropIndex[anchor] = iPropIndex
sCutscenePedVariationRegister[i].variationData.iPropTexture[anchor] = iTexture
ELSE
CDEBUG2LN(DEBUG_MIKE_UTIL, "[", i,"] Specified prop variation for ped: ", pedHandle, " model: ", sCutscenePedVariationRegister[i].model, " prop anchor: ", GET_PROP_POSITION_STRING(anchor), " is already set.")
CDEBUG2LN(DEBUG_MIKE_UTIL, " Stored prop variation - PropID: ", sCutscenePedVariationRegister[i].variationData.iPropIndex[anchor], " Textrue: ", sCutscenePedVariationRegister[i].variationData.iPropTexture[anchor])
ENDIF
EXIT
ENDIF
ENDREPEAT
// no variation registered yet, register a new one or a change was detected, update the slot
IF iFreeSlot != -1
sCutscenePedVariationRegister[iFreeSlot].handle = pedHandle
sCutscenePedVariationRegister[iFreeSlot].model = pedModelName
PED_COMPONENT eComp
REPEAT COUNT_OF(PED_COMPONENT) eComp
sCutscenePedVariationRegister[iFreeSlot].variationData.iDrawableVariation[eComp] = -1
sCutscenePedVariationRegister[iFreeSlot].variationData.iTextureVariation[eComp] = -1
ENDREPEAT
PED_PROP_POSITION eAnchor
REPEAT COUNT_OF(PED_PROP_POSITION) eAnchor
sCutscenePedVariationRegister[iFreeSlot].variationData.iPropIndex[eAnchor] = -1
sCutscenePedVariationRegister[iFreeSlot].variationData.iPropTexture[eAnchor] = -1
ENDREPEAT
sCutscenePedVariationRegister[iFreeSlot].variationData.iPropIndex[anchor] = iPropIndex
sCutscenePedVariationRegister[iFreeSlot].variationData.iPropTexture[anchor] = iTexture
CDEBUG2LN(DEBUG_MIKE_UTIL, "[", iFreeSlot,"] Storing new prop variation for ped: ", pedHandle, " model: ", sCutscenePedVariationRegister[iFreeSlot].model, " for prop anchor: ", GET_PROP_POSITION_STRING(anchor))
CDEBUG2LN(DEBUG_MIKE_UTIL, " New prop variation - Drawable: ", sCutscenePedVariationRegister[iFreeSlot].variationData.iPropIndex[anchor], " Textrue: ", sCutscenePedVariationRegister[iFreeSlot].variationData.iPropTexture[anchor])
ELSE
// NO FREE SLOT!
SCRIPT_ASSERT("sCutscenePedVariationRegister is FULL")
ENDIF
ENDIF
ENDPROC
//PURPOSE: Registers a peds variation with a cutscene, can be called anytime before starting a cutscene as long as the cutscene has been requested to load.
PROC Register_Ped_Variation_For_Cutscene_From_Ped(CUTSCENE_PED_VARIATION &sCutscenePedVariationRegister[], PED_INDEX ped, STRING pedHandle, MODEL_NAMES pedModelName = DUMMY_MODEL_FOR_SCRIPT)
IF IS_CUTSCENE_PLAYING()
SCRIPT_ASSERT("Cannot register ped variation for cutscene as cutscene is currently playing.")
ELIF NOT DOES_ENTITY_EXIST(ped)
OR IS_PED_INJURED(ped)
SCRIPT_ASSERT("Cannot register ped variation for cutscene as ped does not exist or is injured.")
ELSE
PED_COMPONENT j
PED_PROP_POSITION k
PED_VARIATION_STRUCT sPedVar
GET_PED_VARIATIONS(ped, sPedVar)
REPEAT COUNT_OF(PED_COMPONENT) j
Register_Ped_Variation_For_Cutscene(sCutscenePedVariationRegister, pedHandle, j, sPedVar.iDrawableVariation[j], sPedVar.iTextureVariation[j], pedModelName)
ENDREPEAT
REPEAT COUNT_OF(PED_PROP_POSITION) k
Register_Ped_Prop_For_Cutscene(sCutscenePedVariationRegister, pedHandle, k, sPedVar.iPropIndex[k], sPedVar.iPropTexture[k], pedModelName)
ENDREPEAT
ENDIF
ENDPROC
STRUCT CLEANUP_QUEUE_ENTITY_STRUCT
ENTITY_INDEX index
INT iTimeRemoveFromQueue
ENDSTRUCT
/// PURPOSE:
/// Adds the specified entity to the cleanup queue.
/// PARAMS:
/// sQueue - the queue array that holds all the entities
/// entity - the entity to clean up
/// iCleanupTime - the time to clean up the entity, 0 means ASAP (system will only ever remove 1 per frame)
FUNC BOOL Add_Entity_To_Cleanup_Queue(CLEANUP_QUEUE_ENTITY_STRUCT &sQueue[], ENTITY_INDEX entity, INT iCleanupTime = 0)
TEXT_LABEL_63 strAssert
IF NOT DOES_ENTITY_EXIST(entity)
strAssert = "entity does not exist"
SCRIPT_ASSERT(strAssert)
RETURN FALSE
ENDIF
IF iCleanUpTime < 0
SCRIPT_ASSERT("Add_Entity_To_Cleanup_Queue() time specified was less than 0, has been clamped to 0")
iCleanUpTime = 0
ENDIF
INT i
BOOL bRunLoop = TRUE
WHILE bRunLoop
IF NOT DOES_ENTITY_EXIST(sQueue[i].index)
// Check for existing references to this object
INT j
REPEAT COUNT_OF(sQueue) j
IF sQueue[j].index = entity
// already in the cleanup queue, ignore
CDEBUG1LN(DEBUG_MIKE_UTIL, "Add_Entity_To_Cleanup_Queue() entity already queued, return successful but don't add dupe to queue")
RETURN TRUE
ENDIF
ENDREPEAT
sQueue[i].index = entity
sQueue[i].iTimeRemoveFromQueue = GET_GAME_TIMER() + iCleanupTime
bRunLoop = FALSE
CDEBUG1LN(DEBUG_MIKE_UTIL, "Add_Entity_To_Cleanup_Queue() Added entity to cleanup queue[", i, "] @ ",GET_GAME_TIMER(), " to cleanup @ ", sQueue[i].iTimeRemoveFromQueue)
RETURN TRUE
ELSE
IF sQueue[i].index = entity
// already in the cleanup queue, ignore
CDEBUG1LN(DEBUG_MIKE_UTIL, "Add_Entity_To_Cleanup_Queue() entity already queued, return successful but don't add dupe to queue")
RETURN TRUE
ENDIF
i++
IF i > COUNT_OF(sQueue)-1
bRunLoop = FALSE
ENDIF
ENDIF
ENDWHILE
SCRIPT_ASSERT("Add_Entity_To_Cleanup_Queue() couldn't find a free slot in the cleanup queue")
RETURN FALSE
ENDFUNC
PROC Add_Ped_To_Cleanup_Queue(CLEANUP_QUEUE_ENTITY_STRUCT &sQueue[], PED_INDEX &ped, INT iCleanupTime = 0)
IF Add_Entity_To_Cleanup_Queue(sQueue, ped, iCleanupTime)
ped = null
ENDIF
ENDPROC
PROC Add_Vehicle_To_Cleanup_Queue(CLEANUP_QUEUE_ENTITY_STRUCT &sQueue[], VEHICLE_INDEX &vehicle, INT iCleanupTime = 0)
IF Add_Entity_To_Cleanup_Queue(sQueue, vehicle, iCleanupTime)
vehicle = null
ENDIF
ENDPROC
PROC Add_Object_To_Cleanup_Queue(CLEANUP_QUEUE_ENTITY_STRUCT &sQueue[], OBJECT_INDEX &object, INT iCleanupTime = 0)
IF Add_Entity_To_Cleanup_Queue(sQueue, object, iCleanupTime)
object = null
ENDIF
ENDPROC
PROC Update_Entity_Cleanup_Queue(CLEANUP_QUEUE_ENTITY_STRUCT &sQueue[], BOOL bClearAllNow = FALSE)
INT i
BOOL bRunLoop = TRUE
WHILE bRunLoop
IF DOES_ENTITY_EXIST(sQueue[i].index)
IF bClearAllNow
OR sQueue[i].iTimeRemoveFromQueue = 0
OR GET_GAME_TIMER() > sQueue[i].iTimeRemoveFromQueue
INT iDummy
iDummy = 0
IF ARE_STRINGS_EQUAL( GET_ENTITY_SCRIPT(sQueue[i].index, iDummy), GET_THIS_SCRIPT_NAME() )
SWITCH GET_ENTITY_TYPE(sQueue[i].index)
CASE ET_PED
PED_INDEX ped
ped = GET_PED_INDEX_FROM_ENTITY_INDEX(sQueue[i].index)
DELETE_PED(ped)
CDEBUG1LN(DEBUG_MIKE_UTIL, " Deleted Ped")
BREAK
CASE ET_VEHICLE
VEHICLE_INDEX veh
veh = GET_VEHICLE_INDEX_FROM_ENTITY_INDEX(sQueue[i].index)
DELETE_VEHICLE(veh)
CDEBUG1LN(DEBUG_MIKE_UTIL, " Deleted Vehicle")
BREAK
CASE ET_OBJECT
OBJECT_INDEX obj
obj = GET_OBJECT_INDEX_FROM_ENTITY_INDEX(sQueue[i].index)
DELETE_OBJECT(obj)
CDEBUG1LN(DEBUG_MIKE_UTIL, " Deleted Object")
BREAK
DEFAULT
DELETE_ENTITY(sQueue[i].index)
CDEBUG1LN(DEBUG_MIKE_UTIL, " Deleted Entity(DEFAULT)")
BREAK
ENDSWITCH
ENDIF
sQueue[i].index = null
sQueue[i].iTimeRemoveFromQueue = 0
IF NOT bClearAllNow
bRunLoop = FALSE
ENDIF
ENDIF
ENDIF
IF bRunLoop
i++
IF i > COUNT_OF(sQueue)-1
bRunLoop = FALSE
ENDIF
ENDIF
ENDWHILE
ENDPROC
// _______ _ _ _ _ _ _ _______ _ _
// (_______)(_) (_) (_) _ (_)| | (_) _ (_______) _ | | | |
// _ _ _ _ ___ ____ _ _ _| |_ _ | | _ _| |_ _ _ _ _ _ _____ _| |_ | |__ ___ __| | ___
// | ||_|| || | /___) / ___) | | | |(_ _)| || | | |(_ _)| | | | | ||_|| || ___ |(_ _)| _ \ / _ \ / _ | /___)
// | | | || ||___ |( (___ | |___| | | |_ | || | | | | |_ | |_| | | | | || ____| | |_ | | | || |_| |( (_| ||___ |
// |_| |_||_|(___/ \____) \_____/ \__)|_| \_)|_| \__) \__ | |_| |_||_____) \__)|_| |_| \___/ \____|(___/
// (____/
//PURPOSE: Checks if it is safe to attempt to display some godtext
FUNC BOOL IS_SAFE_TO_DISPLAY_GODTEXT()
// Already displaying god text, not safe
IF IS_MESSAGE_BEING_DISPLAYED()
RETURN FALSE
ENDIF
IF IS_SUBTITLE_PREFERENCE_SWITCHED_ON()
// Subtitles are being displayed for the currently running conversation
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
AND NOT IS_FACE_TO_FACE_CONVERSATION_PAUSED()
RETURN FALSE
ENDIF
ENDIF
// no text is at the bottom of the screen
RETURN TRUE
ENDFUNC
// PURPOSE: Checks if it is safe to start a conversation
FUNC BOOL IS_SAFE_TO_START_CONVERSATION()
// Already a conversation on going, not safe
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
RETURN FALSE
ENDIF
// Godtext is currently displaying and subtitles are on, not safe
IF IS_SUBTITLE_PREFERENCE_SWITCHED_ON()
IF IS_MESSAGE_BEING_DISPLAYED()
RETURN FALSE
ENDIF
ENDIF
RETURN TRUE
ENDFUNC