// ***************************************************************************************** // ***************************************************************************************** // ***************************************************************************************** // // 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