Files
GTASource/game/script/commands_streaming.cpp

2370 lines
90 KiB
C++
Raw Permalink Normal View History

2025-02-23 17:40:52 +08:00
//
// filename: commands_streaming.cpp
// description: Commands for streaming
//
// --- Include Files ------------------------------------------------------------
#include "script/commands_streaming.h"
// C headers
// Rage headers
#include "script/hash.h"
#include "script/wrapper.h"
// Framework headers
#include "fwscene/stores/mapdatastore.h"
#include "fwanimation/anim_channel.h"
#include "fwanimation/animmanager.h"
#include "fwrenderer/renderthread.h"
#include "fwscene/stores/imapgroup.h"
#include "fwscene/stores/boxstreamerassets.h"
#include "fwscene/stores/staticboundsstore.h"
#include "vfx/channel.h"
#include "vfx/ptfx/ptfxmanager.h"
// Game headers
#include "camera/CamInterface.h"
#include "camera/switch/SwitchDirector.h"
#include "control/replay/Effects/ParticleMiscFxPacket.h"
#include "ModelInfo/ModelInfo.h"
#include "ModelInfo/ModelInfo_Factories.h"
#include "modelInfo/PedModelInfo.h"
#include "modelInfo/MloModelInfo.h"
#include "modelInfo/VehicleModelInfo.h"
#include "network/NetworkInterface.h"
#include "scene/entities/compEntity.h"
#include "scene/FocusEntity.h"
#include "scene/LoadScene.h"
#include "scene/playerswitch/PlayerSwitchInterface.h"
#include "scene/streamer/SceneStreamerMgr.h"
#include "scene/streamer/StreamVolume.h"
#include "scene/WarpManager.h"
#include "scene/world/GameWorldHeightMap.h"
#include "script/Handlers/GameScriptResources.h"
#include "script/script.h"
#include "script/script_cars_and_peds.h"
#include "script/script_helper.h"
#include "streaming/IslandHopper.h"
#include "streaming/populationstreaming.h"
#include "streaming/streaming.h"
#include "streaming/streamingmodule.h"
#include "streaming/streamingengine.h"
#include "streaming/streamingrequestlist.h"
#include "scene/portals/portal.h"
#include "scene/lod/LodMgr.h"
#include "scene/lod/LodScale.h"
#include "fwsys/timer.h"
#include "scene/ipl/IplCullBox.h"
#include "scene/texLod.h"
#include "spatialdata/sphere.h"
#include "vfx/systems/vfxscript.h"
#include "peds/ped.h"
#include "renderer/HorizonObjects.h"
#include "vehicleai/pathfind.h"
#include "control/gamelogic.h"
#include "peds/PlayerInfo.h"
#include "vfx/particles/PtFxManager.h"
#include "system/FileMgr.h"
#if __BANK
#include "debug/Rendering/DebugLighting.h"
#endif
#if __ASSERT
#include "frontend/PauseMenu.h"
#include "frontend/loadingscreens.h"
#endif
// --- Defines ------------------------------------------------------------------
// --- Constants ----------------------------------------------------------------
// --- Structure/Class Definitions ----------------------------------------------
// --- Globals ------------------------------------------------------------------
// --- Static Globals -----------------------------------------------------------
// --- Static class members -----------------------------------------------------
#if __ASSERT
u32 g_lastLoadSceneFrame = 0;
class scrThread* g_lastLoadThread = NULL;
Vector3 g_lastLoadSceneCoord(0.0f, 0.0f, 0.0f);
#define SET_LOAD_SCENE_FRAME(vCoord) { g_lastLoadSceneFrame = fwTimer::GetSystemFrameCount(); g_lastLoadThread = scrThread::GetActiveThread(); g_lastLoadSceneCoord=vCoord;}
#define ASSERT_NO_LOAD_SCENE(cmd) Assertf(g_lastLoadSceneFrame != fwTimer::GetSystemFrameCount() || g_lastLoadThread != scrThread::GetActiveThread(), "SCRIPT: %s Running %s after a load scene could remove some of the scene you have just loaded", CTheScripts::GetCurrentScriptNameAndProgramCounter(), cmd);
#define ASSERT_NO_LOAD_SCENE_AT_COORDS(cmd, vCoord) Assertf(g_lastLoadSceneFrame != fwTimer::GetSystemFrameCount() || g_lastLoadThread != scrThread::GetActiveThread() || (g_lastLoadSceneCoord.Dist(vCoord) < 5.0f), "SCRIPT: %s Running %s after a load scene could remove some of the scene you have just loaded. Original Coord=%f,%f,%f, New Coord=%f,%f,%f", CTheScripts::GetCurrentScriptNameAndProgramCounter(), cmd, g_lastLoadSceneCoord.x, g_lastLoadSceneCoord.y, g_lastLoadSceneCoord.z, vCoord.x, vCoord.y, vCoord.z);
#else
#define SET_LOAD_SCENE_FRAME(vCoord)
#define ASSERT_NO_LOAD_SCENE(cmd)
#define ASSERT_NO_LOAD_SCENE_AT_COORDS(cmd, vCoord)
#endif
// --- Code ---------------------------------------------------------------------
namespace streaming_commands
{
u32 g_additionalStreamingRequestFlags=0;
//PURPOSE: Does checks on HasLoaded requests from streaming
class CScriptStreamingChecker
{
struct HasLoadedRecord
{
HasLoadedRecord() {numberOfChecks = 0;}
bool IsOld() {return fwTimer::GetSystemFrameCount() - lastCheckTime > 1;}
void IncrementCheck() {lastCheckTime = fwTimer::GetSystemFrameCount(); numberOfChecks++;}
int lastCheckTime;
int numberOfChecks;
};
public:
bool HasObjectLoaded(strLocalIndex objId, int moduleId);
void RemoveEntry(int id) {m_hasLoadedRecordMap.Delete(id);}
void RemoveOld()
{
atMap<int, HasLoadedRecord>::Iterator iHasLoaded = m_hasLoadedRecordMap.CreateIterator();
while(!iHasLoaded.AtEnd())
{
if(iHasLoaded.GetData().IsOld())
{
m_hasLoadedRecordMap.Delete(iHasLoaded.GetKey());
iHasLoaded.Start();
}
else
iHasLoaded.Next();
}
}
void IncrementCheck(int id) {m_hasLoadedRecordMap[id].IncrementCheck();}
int GetNumberOfChecks(int id) {return m_hasLoadedRecordMap[id].numberOfChecks;}
private:
atMap<int, HasLoadedRecord> m_hasLoadedRecordMap;
};
bool CScriptStreamingChecker::HasObjectLoaded(strLocalIndex objId, int moduleId)
{
#if __ASSERT
int streamingId = strStreamingEngine::GetInfo().GetModuleMgr().GetModule(moduleId)->GetStreamingIndex(strLocalIndex(objId)).Get();
RemoveOld();
IncrementCheck(streamingId);
int checks = GetNumberOfChecks(streamingId);
if(checks > 100 && (checks%20) == 0)
Displayf("Waiting on %s to load (%d times)", strStreamingEngine::GetInfo().GetModuleMgr().GetModule(moduleId)->GetName(strLocalIndex(objId)), checks);
#endif
bool rt = CStreaming::HasObjectLoaded(objId, moduleId);
#if __ASSERT
// Graeme already checks for this so this isnt necessary
// scriptAssertf(rt == true || CStreaming::IsObjectRequested(objId, moduleId) || CStreaming::IsObjectLoading(objId, moduleId),
// "You must request %s before checking if it has loaded", strStreamingEngine::GetInfo().GetModuleMgr().GetModule(moduleId)->GetName(objId));
if(rt)
RemoveEntry(streamingId);
#endif
return rt;
}
static CScriptStreamingChecker g_streamingChecker;
//
// name: CommandRequestModel
// description: Request a model to be loaded
void CommandRequestModel(int ModelHashKey)
{
ASSERT_NO_LOAD_SCENE("REQUEST_MODEL");
fwModelId ModelId;
CBaseModelInfo* pModelInfo = CModelInfo::GetBaseModelInfoFromHashKey((u32) ModelHashKey, &ModelId);
if (scriptVerifyf(pModelInfo, "%s: REQUEST_MODEL - model with hash %d does not exist", CTheScripts::GetCurrentScriptNameAndProgramCounter(), ModelHashKey))
{
if (scriptVerifyf(ModelId.IsValid(), "%s: REQUEST_MODEL - model with hash %d exists but its model index is invalid", CTheScripts::GetCurrentScriptNameAndProgramCounter(), ModelHashKey))
{
CScriptResource_Model model(ModelHashKey, g_additionalStreamingRequestFlags);
bool bHasJustBeenAdded = false;
CTheScripts::GetCurrentGtaScriptHandler()->RegisterScriptResource(model, &bHasJustBeenAdded);
if (bHasJustBeenAdded)
{
scriptHandler *pAnotherScriptWhichHasRequestedThisModel = CTheScripts::GetScriptHandlerMgr().GetScriptHandlerForResource(CGameScriptResource::SCRIPT_RESOURCE_MODEL, ModelHashKey, CTheScripts::GetCurrentGtaScriptHandler());
if (pAnotherScriptWhichHasRequestedThisModel == NULL)
{
fwArchetypeManager::AddArchetypeToTypeFileRef(pModelInfo);
}
else
{
scriptDisplayf("%s: REQUEST_MODEL - another script (%s) has already requested the model with hash %d so don't call AddArchetypeToTypeFileRef() for it", CTheScripts::GetCurrentScriptNameAndProgramCounter(), pAnotherScriptWhichHasRequestedThisModel->GetLogName(), ModelHashKey);
}
}
g_additionalStreamingRequestFlags = 0;
}
}
}
void CommandRequestMenuPedModel(int ModelHashKey)
{
g_additionalStreamingRequestFlags |= STRFLAG_PRIORITY_LOAD | STRFLAG_FORCE_LOAD;
CommandRequestModel(ModelHashKey);
}
//
// name: HasModelLoaded
// description: Return if a model has loaded
bool HasModelLoaded(int ModelHashKey)
{
fwModelId modelId;
CBaseModelInfo* pModelInfo = CModelInfo::GetBaseModelInfoFromHashKey(ModelHashKey, &modelId);
if(SCRIPT_VERIFY( modelId.IsValid(), "HAS_MODEL_LOADED - this is not a valid model index"))
{
if(scriptVerifyf(pModelInfo, "HAS_MODEL_LOADED - Model [%d] does not exist", ModelHashKey))
{
#if !__FINAL
if (CTheScripts::GetCurrentGtaScriptHandler())
{
scriptAssertf(CTheScripts::GetCurrentGtaScriptHandler()->GetScriptResource(CGameScriptResource::SCRIPT_RESOURCE_MODEL, ModelHashKey), "HAS_MODEL_LOADED - %s has not requested model %s", CTheScripts::GetCurrentScriptNameAndProgramCounter(), CModelInfo::GetBaseModelInfoName(modelId) );
}
#endif
// if not a MLO then check the object, otherwise check all objects in room 0 of MLO
if (pModelInfo->GetModelType() == MI_TYPE_MLO)
{
return(static_cast<CMloModelInfo*>(pModelInfo)->HaveObjectsInRoomLoaded("limbo")); // "limbo" is always the name of room 0
}
else
{
strLocalIndex transientLocalIdx = CModelInfo::LookupLocalIndex(modelId);
return (g_streamingChecker.HasObjectLoaded(transientLocalIdx, CModelInfo::GetStreamingModuleId()));
}
}
}
return false;
}
//
// name: RequestInteriorModels
// description: Request that all the models in the given room load in
void RequestInteriorModels(int ModelHashKey, const char* pRoomName)
{
fwModelId ModelId;
CBaseModelInfo* pModelInfo = CModelInfo::GetBaseModelInfoFromHashKey((u32) ModelHashKey, &ModelId);
if(SCRIPT_VERIFY( ModelId.IsValid(), "REQUEST_INTERIOR_MODELS - this is not a valid model index"))
{
if(SCRIPT_VERIFY( (pModelInfo->GetModelType() == MI_TYPE_MLO), "REQUEST_INTERIOR_MODELS - model is not an interior"))
{
static_cast<CMloModelInfo*>(pModelInfo)->RequestObjectsInRoom("limbo", g_additionalStreamingRequestFlags); // always attempt to load room 0 objects too
static_cast<CMloModelInfo*>(pModelInfo)->RequestObjectsInRoom((char *) pRoomName, g_additionalStreamingRequestFlags);
}
}
g_additionalStreamingRequestFlags = 0;
}
// issue model requests for the given room in this interior
void RequestModelsInRoom(int InteriorProxyIndex, const char* roomName)
{
if (SCRIPT_VERIFY( InteriorProxyIndex != NULL_IN_SCRIPTING_LANGUAGE, "REQUEST_MODELS_IN_ROOM - Interior index isn't valid"))
{
// get the interior
CInteriorProxy *pIntProxy = CInteriorProxy::GetPool()->GetAt(InteriorProxyIndex);
if (SCRIPT_VERIFY(pIntProxy, "REQUEST_MODELS_IN_ROOM - Interior proxy doesn't exist"))
{
// get the interior
CInteriorInst *pIntInst = pIntProxy->GetInteriorInst();
if (SCRIPT_VERIFY(pIntInst, "REQUEST_MODELS_IN_ROOM - Interior is not yet populated"))
{
s32 roomId = pIntInst->FindRoomByHashcode(atHashString(roomName));
if (scriptVerifyf(roomId > -1, "%s: REQUEST_MODELS_IN_ROOM - unknown room (%s) in interior (%s)",
CTheScripts::GetCurrentScriptNameAndProgramCounter(), roomName, pIntProxy->GetName().GetCStr()))
{
pIntInst->RequestRoom(roomId, g_additionalStreamingRequestFlags);
}
}
}
}
}
//
// name: LoadSceneForRoomByKey
// description: Loads the room models
void LoadSceneForRoomByKey(int interiorInstance, int roomKey)
{
CInteriorProxy* pIntProxy = CInteriorProxy::GetPool()->GetAt(interiorInstance);
Assert(pIntProxy);
CInteriorInst* pInterior = pIntProxy->GetInteriorInst();
if(SCRIPT_VERIFY(pInterior, "LOAD_SCENE_FOR_ROOM_BY_KEY - Interior doesn't exist"))
{
s32 roomIndex = pInterior->FindRoomByHashcode(roomKey);
if(SCRIPT_VERIFY(roomIndex > 0, "LOAD_SCENE_FOR_ROOM_BY_KEY - room key invalid"))
{
g_SceneStreamerMgr.LoadInteriorRoom(pInterior, roomIndex);
}
}
}
void CommandActivateInterior(int interiorInstance, bool bActivate)
{
CInteriorProxy* pIntProxy = CInteriorProxy::GetPool()->GetAt(interiorInstance);
Assert(pIntProxy);
CInteriorInst* pInterior = pIntProxy->GetInteriorInst();
if(SCRIPT_VERIFY(pInterior, "SET_INTERIOR_ACTIVE - Interior doesn't exist"))
{
if (bActivate)
{
// CPortal::AddToActiveInteriorList(pInterior);
}
else
{
// CPortal::RemoveFromActiveInteriorList(pInterior);
}
}
}
//
// name: CommandMarkModelAsNoLongerNeeded
// description: Set model to be deleteable
void CommandMarkModelAsNoLongerNeeded(int ModelHashKey)
{
fwModelId ModelId;
CBaseModelInfo* pModelInfo = CModelInfo::GetBaseModelInfoFromHashKey((u32) ModelHashKey, &ModelId);
if (SCRIPT_VERIFY( pModelInfo, "SET_MODEL_AS_NO_LONGER_NEEDED - model does not exist"))
{
if (CTheScripts::GetCurrentGtaScriptHandler())
{
CTheScripts::GetCurrentGtaScriptHandler()->RemoveScriptResource(CGameScriptResource::SCRIPT_RESOURCE_MODEL, ModelHashKey);
}
}
}
//
// name: RequestCollisionAtPosn
// description: Request collision about point is loaded
void RequestCollisionAtPosn(const scrVector & scrVecCoors)
{
ASSERT_ONLY(Vector3 vCoord(scrVecCoors);)
ASSERT_NO_LOAD_SCENE_AT_COORDS("REQUEST_COLLISION_AT_COORD", vCoord);
g_StaticBoundsStore.GetBoxStreamer().Deprecated_AddSecondarySearch((Vec3V) scrVecCoors);
}
//
// name: RequestMoverCollisionOnly
// description: sets the standard collision streaming to only request mover collision and ignore weapon collision.
// should be called each frame, otherwise we revert to requesting both weapon and mover collision
void RequestMoverCollisionOnly()
{
g_StaticBoundsStore.GetBoxStreamer().OverrideRequiredAssets(fwBoxStreamerAsset::FLAG_STATICBOUNDS_MOVER);
}
//
// name: RequestCollision
// description: Request that collision (physics dictionary) be loaded
void RequestCollisionForModel(int ModelHashKey)
{
CommandRequestModel(ModelHashKey);
}
bool HasCollisionForModelLoaded(int ModelHashKey)
{
fwModelId ModelId;
CBaseModelInfo* pModelInfo = CModelInfo::GetBaseModelInfoFromHashKey((u32) ModelHashKey, &ModelId); // ignores return value
if(SCRIPT_VERIFY( ModelId.IsValid(), "HAS_COLLISION_FOR_MODEL_LOADED - this is not a valid model index"))
{
if (pModelInfo->GetHasLoaded() && pModelInfo->GetHasBoundInDrawable())
return true;
return (pModelInfo->GetPhysics() != NULL);
}
return false;
}
//
// name: DoesAnimDictExist
// description: Return if animation dictionary exists
bool DoesAnimDictExist(const char* pName)
{
strLocalIndex index = fwAnimManager::FindSlot(pName);
if(index.IsValid())
{
return true;
}
return false;
}
//
// name: RequestAnimDict
// description: Request that animation dictionary be loaded
void RequestAnimDict(const char* pName)
{
ASSERT_NO_LOAD_SCENE("REQUEST_ANIMS");
strLocalIndex index = fwAnimManager::FindSlot(pName);
animDebugf3("REQUEST_ANIM_DICT - %s - Anim Dict %s (Slot index: %d)", CTheScripts::GetCurrentScriptNameAndProgramCounter(), pName, index.Get());
if(SCRIPT_VERIFY_TWO_STRINGS(index.IsValid(), "REQUEST_ANIM_DICT - Anim dict name does not exist: ", pName))
{
if (CTheScripts::GetCurrentGtaScriptHandler())
{
CScriptResource_Animation animation(index.Get(), g_additionalStreamingRequestFlags);
CTheScripts::GetCurrentGtaScriptHandler()->RegisterScriptResource(animation);
}
}
g_additionalStreamingRequestFlags = 0;
}
//
// name: HasAnimDictLoaded
// description: Return if animation dictionary is in memory
bool HasAnimDictLoaded(const char* pName)
{
strLocalIndex index = fwAnimManager::FindSlot(pName);
animDebugf3("HAS_ANIM_DICT_LOADED - %s - Anim Dict %s (Slot index: %d)", CTheScripts::GetCurrentScriptNameAndProgramCounter(), pName, index.Get());
if(SCRIPT_VERIFY_TWO_STRINGS(index != -1, "HAS_ANIM_DICT_LOADED - Anim dict name does not exist: ", pName))
{
if (CTheScripts::GetCurrentGtaScriptHandler())
{
scriptAssertf(CTheScripts::GetCurrentGtaScriptHandler()->GetScriptResource(CGameScriptResource::SCRIPT_RESOURCE_ANIMATION, index.Get()), "HAS_ANIM_DICT_LOADED - %s has not requested %s", CTheScripts::GetCurrentScriptNameAndProgramCounter(), pName);
}
return g_streamingChecker.HasObjectLoaded(index, fwAnimManager::GetStreamingModuleId());
}
return false;
}
//
// name: RemoveAnimDict
// description: Remove animation dictionary
void RemoveAnimDict(const char* pName)
{
s32 index = fwAnimManager::FindSlot(pName).Get();
animDebugf3("REMOVE_ANIM_DICT - %s - Anim Dict %s (Slot index: %d)", CTheScripts::GetCurrentScriptNameAndProgramCounter(), pName, index);
if(SCRIPT_VERIFY_TWO_STRINGS(index != -1, "REMOVE_ANIM_DICT - Anim dict name does not exist: ", pName))
{
if (CTheScripts::GetCurrentGtaScriptHandler())
{
CTheScripts::GetCurrentGtaScriptHandler()->RemoveScriptResource(CGameScriptResource::SCRIPT_RESOURCE_ANIMATION, index);
}
}
}
//
// name: RequestClipSet
// description: Requests a clipset (and its fallbacks) to load
void RequestClipSet(const char* pName)
{
ASSERT_NO_LOAD_SCENE("REQUEST_CLIP_SET");
fwMvClipSetId clipSetId(pName);
animDebugf3("REQUEST_CLIP_SET - %s - ClipSet %s (ClipSetId: %u)", CTheScripts::GetCurrentScriptNameAndProgramCounter(), pName, clipSetId.GetHash());
fwClipSet* pSet = fwClipSetManager::GetClipSet(clipSetId);
if (SCRIPT_VERIFY_TWO_STRINGS(pSet != NULL, "REQUEST_CLIP_SET - Invalid ClipSet name: ", pName))
{
scriptResource* pResource = CTheScripts::GetCurrentGtaScriptHandler()->GetScriptResource(CGameScriptResource::SCRIPT_RESOURCE_CLIP_SET, clipSetId);
if (!pResource)
{
CScriptResource_ClipSet newClipSetResource(clipSetId);
CTheScripts::GetCurrentGtaScriptHandler()->RegisterScriptResource(newClipSetResource);
fwClipSetManager::Script_AddAndRequestClipSet(clipSetId);
}
else
{
fwClipSetManager::Script_RequestClipSet(clipSetId);
}
}
}
//
// name: HasClipSetLoaded
// description: Return if the clipset is in memory
bool HasClipSetLoaded(const char* pName)
{
fwMvClipSetId clipSetId(pName);
fwClipSet* pSet = fwClipSetManager::GetClipSet(clipSetId);
animDebugf3("HAS_CLIP_SET_LOADED - %s - ClipSet %s (ClipSetId: %u)", CTheScripts::GetCurrentScriptNameAndProgramCounter(), pName, clipSetId.GetHash());
if (SCRIPT_VERIFY_TWO_STRINGS(pSet != NULL, "HAS_CLIP_SET_LOADED - Invalid ClipSet name: ", pName))
{
scriptResource* pResource = CTheScripts::GetCurrentGtaScriptHandler()->GetScriptResource(CGameScriptResource::SCRIPT_RESOURCE_CLIP_SET, clipSetId);
if (pResource)
{
return fwClipSetManager::Script_HasClipSetLoaded(clipSetId);
}
else
{
scriptWarningf("HAS_CLIP_SET_LOADED - Could not find clip set resource for %s - was this clipset requested?", clipSetId.TryGetCStr());
}
}
return false;
}
//
// name: RemoveClipSet
// description: Remove/Unload a clipset (and its fallbacks).
void RemoveClipSet(const char* pName)
{
fwMvClipSetId clipSetId(pName);
fwClipSet* pSet = fwClipSetManager::GetClipSet(clipSetId);
animDebugf3("REMOVE_CLIP_SET - %s - ClipSet %s (ClipSetId: %u)", CTheScripts::GetCurrentScriptNameAndProgramCounter(), pName, clipSetId.GetHash());
if (SCRIPT_VERIFY_TWO_STRINGS(pSet != NULL, "REMOVE_CLIP_SET - Invalid ClipSet name: ", pName))
{
scriptResource* pResource = CTheScripts::GetCurrentGtaScriptHandler()->GetScriptResource(CGameScriptResource::SCRIPT_RESOURCE_CLIP_SET, clipSetId);
if (pResource)
{
CTheScripts::GetCurrentGtaScriptHandler()->RemoveScriptResource(CGameScriptResource::SCRIPT_RESOURCE_CLIP_SET, clipSetId, false, true);
}
else
{
scriptWarningf("REMOVE_CLIP_SET - Could not find clip set resource for %s - was this clipset requested?", clipSetId.TryGetCStr());
}
}
}
//
// name: RequestIpl
// description: Request Ipl file
void RequestIpl(const char* pName)
{
s32 index = INSTANCE_STORE.FindSlot(pName).Get();
if(SCRIPT_VERIFY_TWO_STRINGS(index != -1, "REQUEST_IPL - IPL group does not exist", pName))
{
u32 iplNameHash = atStringHash(pName);
Displayf("%s called REQUEST_IPL(%s)", CTheScripts::GetCurrentScriptNameAndProgramCounter(), pName);
scriptAssertf(!g_LoadScene.IsActive(), "[script] Don't modify Ipl groups (%s) whilst load scene is active! (Load scene triggered by %s)", pName, g_LoadScene.WasStartedByScript() ? g_LoadScene.GetScriptName().c_str() : "CODE");
INSTANCE_STORE.RequestGroup(strLocalIndex(index), iplNameHash);
CCompEntity::UpdateCompEntitiesUsingGroup(index, CE_STATE_INIT);
// url:bugstar:6571961 - enable the heightmap specifically for the heist island
if(iplNameHash == ATSTRINGHASH("h4_islandx_mansion", 0x9a95c101))
{
CGameWorldHeightMap::EnableHeightmap("heightmapheistisland", true);
}
}
}
//
// name: RemoveIpl
// description: Remove Ipl file
void RemoveIpl(const char* pName)
{
strLocalIndex index = strLocalIndex(INSTANCE_STORE.FindSlot(pName));
if(SCRIPT_VERIFY_TWO_STRINGS(index != -1, "REMOVE_IPL - IPL group does not exist", pName))
{
u32 iplNameHash = atStringHash(pName);
Displayf("%s called REMOVE_IPL(%s)", CTheScripts::GetCurrentScriptNameAndProgramCounter(), pName);
scriptAssertf(!g_LoadScene.IsActive(), "[script] Don't modify Ipl groups (%s) whilst load scene is active! (Load scene triggered by %s)", pName, g_LoadScene.WasStartedByScript() ? g_LoadScene.GetScriptName().c_str() : "CODE");
CCompEntity::UpdateCompEntitiesUsingGroup(index.Get(), CE_STATE_ABANDON);
//////////////////////////////////////////////////////////////////////////
fwMapDataDef* pDef = fwMapDataStore::GetStore().GetSlot(index);
if (pDef && (pDef->GetContentFlags()&fwMapData::CONTENTFLAG_MASK_LODLIGHTS)!=0)
{
#if __ASSERT
const bool bGameIsNotRendering = (camInterface::IsFadedOut() || CLoadingScreens::AreActive() || CPauseMenu::GetPauseRenderPhasesStatus());
// special case - these types of IMAP files contain data that is consumed by GPU so may need to force RT flush
if (!bGameIsNotRendering)
{
scriptWarningf("Script %s called REMOVE_IPL(%s) but the screen is not faded out - this is unsafe because %s contains LOD lights",
CTheScripts::GetCurrentScriptNameAndProgramCounter(), pName, pName );
}
#endif
gRenderThreadInterface.Flush();
}
//////////////////////////////////////////////////////////////////////////
INSTANCE_STORE.RemoveGroup(index, iplNameHash);
// url:bugstar:6571961 - disable the heightmap specifically for the heist island
if(iplNameHash == ATSTRINGHASH("h4_islandx_mansion", 0x9a95c101))
{
CGameWorldHeightMap::EnableHeightmap("heightmapheistisland", false);
}
}
}
//
// name: IsIplActive
// description: return if the named ipl is set to be streamable or not
bool IsIplActive(const char* pName)
{
strLocalIndex index = strLocalIndex(INSTANCE_STORE.FindSlot(pName));
if(SCRIPT_VERIFY_TWO_STRINGS(index != -1, "IS_IPL_ACTIVE - IPL group does not exist", pName))
{
return(INSTANCE_STORE.GetIsStreamable(index));
}
return(false);
}
//
// Loads selected water.xml file:
// 0 - main V water file
// 1 - Island Heist DLC water file
//
void LoadGlobalWaterFile(s32 waterXmlID)
{
Assertf((waterXmlID==Water::WATERXML_V_DEFAULT) || (waterXmlID==Water::WATERXML_ISLANDHEIST), "LOAD_GLOBAL_WATER_FILE: Invalid waterID id (%d)!", waterXmlID);
Water::RequestGlobalWaterXmlFile(waterXmlID);
}
//
//
//
//
s32 GetGlobalWaterFile()
{
return Water::GetGlobalWaterXmlFile();
}
//
// name: LoadAllObjectsNow
// description: Loads all the objects on the request list
void LoadAllObjectsNow()
{
Assertf(!camInterface::IsFadedIn(), "Don't call LOAD_ALL_OBJECTS_NOW while the game isn't faded out - it will cause stutters on disc builds.");
// Ensure that all requests are issued this frame
ThePaths.UpdateStreaming(true);
CStreaming::LoadAllRequestedObjects();
}
//
// name: LoadScene
// description: Load scene about point
void LoadScene(const scrVector & scrVecCoors)
{
if ( scriptVerifyf(!g_PlayerSwitch.IsActive(), "Calling LOAD_SCENE while a player switch is in progress is not safe! %s", CTheScripts::GetCurrentScriptNameAndProgramCounter()) )
{
SCRIPT_ASSERT( !NetworkInterface::IsGameInProgress(), "You should use NETWORK_START_LOAD_SCENE/NETWORK_UPDATE_LOAD_SCENE in network games!");
Vector3 VecCoors (scrVecCoors);
ASSERT_NO_LOAD_SCENE_AT_COORDS("LOAD_SCENE", VecCoors);
Printf("Script \"%s\" requested a load scene at %f,%f,%f\n", CTheScripts::GetCurrentScriptName(), VecCoors.x, VecCoors.y, VecCoors.z);
g_SceneStreamerMgr.LoadScene(VecCoors);
SET_LOAD_SCENE_FRAME(VecCoors);
}
}
//
// name: StartLoadScene
// description: Load scene about point
void StartLoadScene(const scrVector & scrVecCoors)
{
SCRIPT_ASSERT(false, "Script is calling NETWORK_START_LOAD_SCENE. Don't use that, use the NEW_LOAD_SCENE commands instead. Game may crash soon.");
Vector3 VecCoors (scrVecCoors);
ASSERT_NO_LOAD_SCENE_AT_COORDS("NETWORK_START_LOAD_SCENE", VecCoors);
Printf("Script \"%s\" requested a load scene at %f,%f,%f\n", CTheScripts::GetCurrentScriptName(),VecCoors.x, VecCoors.y, VecCoors.z);
g_SceneStreamerMgr.StartLoadScene(VecCoors);
}
//
// name: UpdateLoadScene
// description: Load scene about point
bool UpdateLoadScene()
{
return g_SceneStreamerMgr.UpdateLoadScene();
}
// name: StopLoadScene
// description: abandon an async load scene if there is one in progress
void StopLoadScene()
{
Printf("Script %s called NETWORK_STOP_LOAD_SCENE\n", CTheScripts::GetCurrentScriptName());
// if (g_SceneStreamerMgr.IsLoading())
{
g_SceneStreamerMgr.StopLoadScene();
}
}
bool IsLoadSceneActive()
{
return g_SceneStreamerMgr.IsLoading();
}
//
// name: IsModelInCdImage
// description: Returns if model is currently valid
bool IsModelInCdImage(s32 modelHash)
{
fwModelId modelId;
CModelInfo::GetBaseModelInfoFromHashKey(modelHash, &modelId);
if (!modelId.IsValid())
{
return false;
}
return true;
}
bool CommandIsModelValid(s32 modelHash)
{
fwModelId modelId;
CModelInfo::GetBaseModelInfoFromHashKey(modelHash, &modelId);
if (modelId.IsValid())
{
if (modelId.IsGlobal())
{
return true;
}
}
return false;
}
bool CommandGetPedModelFromIndex(int iPedModelIndex, int &ReturnPedModelHashKey)
{
ReturnPedModelHashKey = 0;
// Returns false if there is no ped model with that index.
// iPedModelIndex starts at 0 and counts up till it returns false.
fwArchetypeDynamicFactory<CPedModelInfo>& pedModelInfoStore = CModelInfo::GetPedModelInfoStore();
atArray<CPedModelInfo*> pedTypesArray;
pedModelInfoStore.GatherPtrs(pedTypesArray);
int numPedsAvail = pedTypesArray.GetCount();
if (iPedModelIndex >= numPedsAvail)
{
return false;
}
CPedModelInfo& pedModelInfo = *pedTypesArray[iPedModelIndex];
ReturnPedModelHashKey = (int) pedModelInfo.GetHashKey();
return true;
}
bool CommandGetVehicleModelFromIndex(int iVehicleModelIndex, int &ReturnVehicleModelHashKey)
{
ReturnVehicleModelHashKey = 0;
// Returns false if there is no vehicle model with that index.
// iVehicleModelIndex starts at 0 and counts up till it returns false.
fwArchetypeDynamicFactory<CVehicleModelInfo>& vehicleModelInfoStore = CModelInfo::GetVehicleModelInfoStore();
atArray<CVehicleModelInfo*> vehicleTypes;
vehicleModelInfoStore.GatherPtrs(vehicleTypes);
int numVehiclesAvail = vehicleTypes.GetCount();
if (iVehicleModelIndex >= numVehiclesAvail)
{
return false;
}
CVehicleModelInfo& vehicleModelInfo = *vehicleTypes[iVehicleModelIndex];
ReturnVehicleModelHashKey = (int) vehicleModelInfo.GetHashKey();
return true;
}
bool CommandIsThisModelAPed(int ModelHashKey)
{
bool LatestCmpFlagResult = false;
CBaseModelInfo* pModelInfo = CModelInfo::GetBaseModelInfoFromHashKey((u32) ModelHashKey, NULL);
if(pModelInfo && pModelInfo->GetModelType()==MI_TYPE_PED)
{
LatestCmpFlagResult = true;
}
return LatestCmpFlagResult;
}
bool CommandIsThisModelAVehicle(int ModelHashKey)
{
bool LatestCmpFlagResult = false;
CBaseModelInfo* pModelInfo = CModelInfo::GetBaseModelInfoFromHashKey((u32) ModelHashKey, NULL);
if(pModelInfo && pModelInfo->GetModelType()==MI_TYPE_VEHICLE)
{
LatestCmpFlagResult = true;
}
return LatestCmpFlagResult;
}
//
// name: SwitchStreaming
// description: Switch streaming on and off
void SwitchStreaming(bool bOn)
{
if (bOn)
{
CStreaming::EnableStreaming();
}
else
{
CStreaming::DisableStreaming();
}
}
//
// name: EnableSceneStreaming
// description: Enable/Disable scene streaming
void EnableSceneStreaming(bool bEnable)
{
CStreaming::EnableSceneStreaming(bEnable);
}
// Ensure game loads collision and ipls around an additional point. This function needs calling every frame the
// additional data is required
void AddNeededAtPosn(const scrVector & scrVecCoors)
{
g_StaticBoundsStore.GetBoxStreamer().Deprecated_AddSecondarySearch((Vec3V)scrVecCoors);
}
// This should only be called by the end credits script. The credits will call it with FALSE at the start and
// TRUE at the end. This is to stop the scrolling of the credits from pausing when the player warps from
// one area of the city to another during the screen fades.
void AllowGameToPauseForStreaming(bool bAllowPause)
{
CTheScripts::SetAllowGameToPauseForStreaming(bAllowPause);
}
void SetReducePedModelBudget(bool bReduce)
{
gPopStreaming.SetReduceAmbientPedModelBudget(bReduce);
}
void SetReduceVehicleModelBudget(bool bReduce)
{
gPopStreaming.SetReduceAmbientVehicleModelBudget(bReduce);
}
void SetDitchPoliceModels(bool UNUSED_PARAM(bDitch))
{
}
s32 GetNumStreamingRequests()
{
return strStreamingEngine::GetInfo().GetNumberRealObjectsRequested();
}
bool IsStreamingPriorityRequests()
{
return strStreamingEngine::GetIsLoadingPriorityObjects();
}
//
// name: RequestPtFxAsset
// description: Request the particle asset be loaded
void RequestPtFxAsset()
{
ASSERT_NO_LOAD_SCENE("REQUEST_PTFX_ASSET");
const char* pScriptName = CTheScripts::GetCurrentScriptName();
atHashWithStringNotFinal ptfxAssetName = g_vfxScript.GetScriptPtFxAssetName(pScriptName);
if (ptfxVerifyf(ptfxAssetName.GetHash(), "script %s has no particle asset set up - can't request the asset", pScriptName))
{
strLocalIndex slot = ptfxManager::GetAssetStore().FindSlotFromHashKey(ptfxAssetName);
if (scriptVerifyf(slot.IsValid(), "%s REQUEST_PTFX_ASSET - cannot find particle asset slot (%s)", CTheScripts::GetCurrentScriptNameAndProgramCounter(), ptfxAssetName.GetCStr()))
{
CScriptResource_PTFX_Asset ptfxAsset(slot.Get(), g_additionalStreamingRequestFlags);
CTheScripts::GetCurrentGtaScriptHandler()->RegisterScriptResource(ptfxAsset);
#if GTA_REPLAY
g_ptFxManager.SetReplayScriptPtfxAssetID(slot.Get());
#endif
}
}
g_additionalStreamingRequestFlags = 0;
}
//
// name: HasPtFxAssetLoaded
// description: Return if particle asset is in memory
bool HasPtFxAssetLoaded()
{
const char* pScriptName = CTheScripts::GetCurrentScriptName();
atHashWithStringNotFinal ptfxAssetName = g_vfxScript.GetScriptPtFxAssetName(pScriptName);
if (ptfxVerifyf(ptfxAssetName.GetHash(), "script %s has no particle asset set up - can't check if the asset has loaded", pScriptName))
{
strLocalIndex slot = strLocalIndex(ptfxManager::GetAssetStore().FindSlotFromHashKey(ptfxAssetName));
if (scriptVerifyf(slot.IsValid(), "%s HAS_PTFX_ASSET_LOADED - cannot find particle asset slot (%s)", CTheScripts::GetCurrentScriptNameAndProgramCounter(), ptfxAssetName.GetCStr()))
{
if (CTheScripts::GetCurrentGtaScriptHandler())
{
scriptAssertf(CTheScripts::GetCurrentGtaScriptHandler()->GetScriptResource(CGameScriptResource::SCRIPT_RESOURCE_PTFX_ASSET, slot.Get()), "HAS_PTFX_ASSET_LOADED - %s has not requested %s", CTheScripts::GetCurrentScriptNameAndProgramCounter(), ptfxAssetName.GetCStr());
}
return ptfxManager::GetAssetStore().HasObjectLoaded(slot);
}
}
return false;
}
//
// name: RemovePtFxAsset
// description: Remove particle asset
void RemovePtFxAsset()
{
const char* pScriptName = CTheScripts::GetCurrentScriptName();
atHashWithStringNotFinal ptfxAssetName = g_vfxScript.GetScriptPtFxAssetName(pScriptName);
if (ptfxVerifyf(ptfxAssetName.GetHash(), "script %s has no particle asset set up - can't remove the asset", pScriptName))
{
if (SCRIPT_VERIFY(ptfxAssetName, "invalid particle asset name"))
{
strLocalIndex slot = ptfxManager::GetAssetStore().FindSlotFromHashKey(ptfxAssetName);
if (scriptVerifyf(slot.IsValid(), "%s REMOVE_PTFX_ASSET - cannot find particle asset slot (%s)", CTheScripts::GetCurrentScriptNameAndProgramCounter(), ptfxAssetName.GetCStr()))
{
CTheScripts::GetCurrentGtaScriptHandler()->RemoveScriptResource(CGameScriptResource::SCRIPT_RESOURCE_PTFX_ASSET, slot.Get());
#if GTA_REPLAY
g_ptFxManager.SetReplayScriptPtfxAssetID(-1);
#endif
}
}
}
}
//
// name: RequestNamedPtFxAsset
// description: Request that a named particle asset be loaded
void RequestNamedPtFxAsset(const char* pPtFxAssetName)
{
ASSERT_NO_LOAD_SCENE("REQUEST_NAMED_PTFX_ASSET");
u32 assetHash = atStringHash(pPtFxAssetName);
s32 slot = ptfxManager::GetAssetStore().FindSlotFromHashKey(assetHash).Get();
if (scriptVerifyf(slot != -1, "%s REQUEST_NAMED_PTFX_ASSET - cannot find particle asset slot (%s)", CTheScripts::GetCurrentScriptNameAndProgramCounter(), pPtFxAssetName))
{
CScriptResource_PTFX_Asset ptfxAsset(slot, g_additionalStreamingRequestFlags);
CTheScripts::GetCurrentGtaScriptHandler()->RegisterScriptResource(ptfxAsset);
#if GTA_REPLAY
if(CPacketRequestNamedPtfxAsset::CheckRequestedHash(assetHash))
{
CReplayMgr::RecordFx<CPacketRequestNamedPtfxAsset>(CPacketRequestNamedPtfxAsset(assetHash));
}
#endif // GTA_REPLAY
}
g_additionalStreamingRequestFlags = 0;
}
//
// name: HasNamedPtFxAssetLoaded
// description: Return if particle asset is in memory
bool HasNamedPtFxAssetLoaded(const char* pPtFxAssetName)
{
s32 slot = ptfxManager::GetAssetStore().FindSlotFromHashKey(atStringHash(pPtFxAssetName)).Get();
if (scriptVerifyf(slot != -1, "%s HAS_NAMED_PTFX_ASSET_LOADED - cannot find particle asset slot (%s)", CTheScripts::GetCurrentScriptNameAndProgramCounter(), pPtFxAssetName))
{
if (CTheScripts::GetCurrentGtaScriptHandler())
{
scriptAssertf(CTheScripts::GetCurrentGtaScriptHandler()->GetScriptResource(CGameScriptResource::SCRIPT_RESOURCE_PTFX_ASSET, slot), "HAS_NAMED_PTFX_ASSET_LOADED - %s has not requested %s", CTheScripts::GetCurrentScriptNameAndProgramCounter(), pPtFxAssetName);
}
return ptfxManager::GetAssetStore().HasObjectLoaded(strLocalIndex(slot));
}
return false;
}
//
// name: RemoveNamedPtFxAsset
// description: Remove particle asset
void RemoveNamedPtFxAsset(const char* pPtFxAssetName)
{
u32 assetHash = atStringHash(pPtFxAssetName);
s32 slot = ptfxManager::GetAssetStore().FindSlotFromHashKey(assetHash).Get();
if (scriptVerifyf(slot != -1, "%s REMOVE_NAMED_PTFX_ASSET - cannot find particle asset slot (%s)", CTheScripts::GetCurrentScriptNameAndProgramCounter(), pPtFxAssetName))
{
CTheScripts::GetCurrentGtaScriptHandler()->RemoveScriptResource(CGameScriptResource::SCRIPT_RESOURCE_PTFX_ASSET, slot);
REPLAY_ONLY(CPacketRequestNamedPtfxAsset::RemoveRequestedHash(assetHash));
}
}
//
// name: SetVehiclePopulationBudget
// description: Set the memory budget level for the vehicle population
void SetVehiclePopulationBudget(int budgetLevel)
{
Displayf("SET_VEHICLE_POPULATION_BUDGET(%i) - called from script \"%s\".", budgetLevel, CTheScripts::GetCurrentScriptNameAndProgramCounter());
if (SCRIPT_VERIFY(budgetLevel >= 0 && budgetLevel < MAX_MEM_LEVELS, "Invalid vehicle population budget level specified"))
{
gPopStreaming.SetVehMemoryBudgetLevel(budgetLevel);
}
}
//
// name: SetPedPopulationBudget
// description: Set the memory budget level for the ped population
void SetPedPopulationBudget(int budgetLevel)
{
Displayf("SET_PED_POPULATION_BUDGET(%i) - called from script \"%s\".", budgetLevel, CTheScripts::GetCurrentScriptNameAndProgramCounter());
if (SCRIPT_VERIFY(budgetLevel >= 0 && budgetLevel < MAX_MEM_LEVELS, "Invalid ped population budget level specified"))
{
gPopStreaming.SetPedMemoryBudgetLevel(budgetLevel);
}
}
//
// name: ClearFocus
// description: resets the streaming focus entity to default (player ped)
void ClearFocus()
{
CFocusEntityMgr::GetMgr().SetDefault();
#if !__FINAL
scriptDebugf1("%s: CLEAR_FOCUS()", CTheScripts::GetCurrentScriptNameAndProgramCounter());
scrThread::PrePrintStackTrace();
#endif //__FINAL
}
//
// name: SetFocusPosAndVel
// description: overrides the streaming focus to specified position and velocity
void SetFocusPosAndVel(const scrVector & pos, const scrVector & vel)
{
#if __ASSERT
if (g_PlayerSwitch.IsActive())
{
Displayf("Changing focus during player switch! Call stack follows");
scrThread::PrePrintStackTrace();
}
#endif
if ( Verifyf(!g_PlayerSwitch.IsActive(), "%s called SET_FOCUS_POS_AND_VEL during player switch - this is unsafe!", CTheScripts::GetCurrentScriptNameAndProgramCounter()) )
{
SCRIPT_ASSERT(!(pos.x == 0.0f && pos.y == 0.0f && pos.z == 0.0f), "SET_FOCUS_POS_AND_VEL was passed a zero vector for the position");
Displayf("Script %s called SET_FOCUS_POS_AND_VEL() pos=(%.2f, %.2f, %.2f), vel=(%.2f, %.2f, %.2f)",
CTheScripts::GetCurrentScriptNameAndProgramCounter(),
pos.x, pos.y, pos.z, vel.x, vel.y, vel.z
);
Vector3 vFocusPos(pos);
Vector3 vFocusVel(vel);
#if GTA_REPLAY
bool shouldRecord = false;
CPed* pPlayer = FindPlayerPed();
if(pPlayer)
{
// For url:bugstar:4252330 - Record the focus entity manager being given a position and velocity...
// BUT only do it if we're in the interior of the Avenger (as this call is used in many places in script
// and we don't want to risk suddenly recording something we've managed without so far and causing bother)
fwInteriorLocation interiorLoc = pPlayer->GetInteriorLocation();
CInteriorProxy *pInteriorProxy = CInteriorProxy::GetFromLocation(interiorLoc);
if(pInteriorProxy)
{
const u32 interiorHashesForRoomOneToRecord[] = {
0xdababf3e, /*"xm_x17dlc_int_01"*/ // Avenger interior
0x90d05f68, /*"ba_dlc_int_03_ba"*/ // Terrorbyte truck interior - url:bugstar:5065997
0x82396e18, /*"ch_dlc_plan"*/ // Arcade interior - url:bugstar:6139015
};
const u32 interiorHashesForAnyRoomTorRecord[] = {
0x92455476, /*"h4_int_sub_h4"*/ // Submarine interior - url:bugstar:6794037
};
bool matchesInterior = false;
if(interiorLoc.GetRoomIndex() == 1)
{
for(int i = 0; i < NELEM(interiorHashesForRoomOneToRecord); ++i)
{
if(interiorHashesForRoomOneToRecord[i] == pInteriorProxy->GetNameHash())
matchesInterior = true;
}
}
else
{
for(int i = 0; i < NELEM(interiorHashesForAnyRoomTorRecord); ++i)
{
if(interiorHashesForAnyRoomTorRecord[i] == pInteriorProxy->GetNameHash())
matchesInterior = true;
}
}
if(matchesInterior)
{
if(CFocusEntityMgr::GetMgr().GetFocusState() != CFocusEntityMgr::FOCUS_OVERRIDE_POS)
{
shouldRecord = true;
}
else if(CFocusEntityMgr::GetMgr().GetPos() != pos || CFocusEntityMgr::GetMgr().GetVel() != vel)
{
shouldRecord = true;
}
}
}
}
#endif // GTA_REPLAY
CFocusEntityMgr::GetMgr().SetPosAndVel(vFocusPos, vFocusVel);
#if !__FINAL
scriptDebugf1("%s: SET_FOCUS_POS_AND_VEL((%.2f, %.2f, %.2f),(%.2f, %.2f, %.2f))", CTheScripts::GetCurrentScriptNameAndProgramCounter(), pos.x, pos.y, pos.z, vel.x, vel.y, vel.z);
scrThread::PrePrintStackTrace();
#endif //__FINAL
#if GTA_REPLAY
if(CReplayMgr::ShouldRecord() && shouldRecord)
{
CReplayMgr::RecordFx<CPacketFocusPosAndVel>(CPacketFocusPosAndVel(vFocusPos, vFocusVel));
}
#endif // GTA_REPLAY
}
}
//
// name: SetFocusEntity
// description: overrides the streaming focus to specified entity
void SetFocusEntity(int entityIndex)
{
#if __ASSERT
if (g_PlayerSwitch.IsActive())
{
Displayf("Changing focus during player switch! Call stack follows");
scrThread::PrePrintStackTrace();
}
#endif
if ( Verifyf(!g_PlayerSwitch.IsActive(), "%s called SET_FOCUS_ENTITY during player switch - this is unsafe!", CTheScripts::GetCurrentScriptNameAndProgramCounter()) )
{
const CEntity* pEntity = CTheScripts::GetEntityToQueryFromGUID<CEntity>(entityIndex, CTheScripts::GUID_ASSERT_FLAG_ENTITY_EXISTS);
if (SCRIPT_VERIFY(pEntity, "SET_FOCUS_ENTITY - entity does not exist"))
{
CFocusEntityMgr::GetMgr().SetEntity(*pEntity);
#if !__FINAL
scriptDebugf1("%s: SET_FOCUS_ENITTY(%d)", CTheScripts::GetCurrentScriptNameAndProgramCounter(), entityIndex);
scrThread::PrePrintStackTrace();
#endif //__FINAL
#if GTA_REPLAY
if(CReplayMgr::ShouldRecord())
{
const u32 entityHashes[] = {0x5993f939, /*"trailerlarge"*/
0x81bd2ed0, /*avenger*/
0x897afc65, /*"terbyte"*/};
bool recordPacket = false;
for(int i = 0; i < NELEM(entityHashes); ++i)
{
if(pEntity->GetModelNameHash() == entityHashes[i])
{
recordPacket = true;
break;
}
}
if(recordPacket)
{
CReplayMgr::RecordFx<CPacketFocusEntity>(CPacketFocusEntity(), pEntity);
}
}
#endif // GTA_REPLAY
}
}
}
// very special case - restore focus to specified entity after player switch
void SetRestoreFocusEntity(int entityIndex)
{
#if __ASSERT
if (!g_PlayerSwitch.IsActive())
{
Displayf("Changing restore focus only permitted during player switch! Call stack follows");
scrThread::PrePrintStackTrace();
}
#endif
if ( Verifyf(g_PlayerSwitch.IsActive(), "%s called SET_RESTORE_FOCUS_ENTITY outside of player switch - this is unsafe!", CTheScripts::GetCurrentScriptNameAndProgramCounter()) )
{
const CEntity* pEntity = CTheScripts::GetEntityToQueryFromGUID<CEntity>(entityIndex, CTheScripts::GUID_ASSERT_FLAG_ENTITY_EXISTS);
if (SCRIPT_VERIFY(pEntity, "SET_RESTORE_FOCUS_ENTITY - entity does not exist"))
{
CFocusEntityMgr::GetMgr().SetSavedOverrideEntity(*pEntity);
#if !__FINAL
scriptDebugf1("%s: SET_RESTORE_FOCUS_ENTITY(%d)", CTheScripts::GetCurrentScriptNameAndProgramCounter(), entityIndex);
scrThread::PrePrintStackTrace();
#endif //__FINAL
}
}
}
bool IsEntityFocus(int entityIndex)
{
const CEntity* pEntity = CTheScripts::GetEntityToQueryFromGUID<CEntity>(entityIndex, CTheScripts::GUID_ASSERT_FLAG_ENTITY_EXISTS);
if ( pEntity && pEntity==CFocusEntityMgr::GetMgr().GetEntity() )
{
return true;
}
return false;
}
//
// name: SetMapDataCullBoxEnabled
// description: allows script to enable and disable specific map data cull boxes referred to by name.
// typically in GTAV this allows us to cull out the entire GTAV map when playing prologue
void SetMapDataCullBoxEnabled(const char* boxName, bool bEnabled)
{
u32 nameHash = atStringHash(boxName);
// If the cullbox isn't already enabled and it's to be enabled then regenerate the cull list
// as the map data may have changed
if(bEnabled && !CIplCullBox::IsBoxEnabled(nameHash))
{
INSTANCE_STORE.CreateChildrenCache();
CIplCullBox::GenerateCullListForBox(nameHash);
#if !__BANK
INSTANCE_STORE.DestroyChildrenCache(); // used by cull box editor
#endif // !__BANK
}
CIplCullBox::SetBoxEnabled(nameHash, bEnabled);
}
//
// name: SetAllMapDataCulled
// description: allows script to cull all map data in one go, or not
void SetAllMapDataCulled(bool /*bCulled*/)
{
//I am killing off this command - IK
// CIplCullBox::CullEverything(bCulled);
// CHorizonObjects::CullEverything(bCulled);
}
//
// name: SetHorizonObjectsCulled
// description: allows script to cull all horizon objects
void SetHorizonObjectsCulled(bool bCulled)
{
CHorizonObjects::CullEverything(bCulled);
}
//
// name: CommandStreamVolCreateSphere
// description: registers a new spherical stream volume for the specified asset types
int CommandStreamVolCreateSphere(const scrVector & vPos, float fRadius, s32 assetFlags, s32 lodFlags=LODTYPES_MASK_ALL)
{
if ( scriptVerifyf(!g_PlayerSwitch.IsActive(), "Calling STREAMVOL_CREATE_SPHERE while a player switch is in progress is not safe! %s", CTheScripts::GetCurrentScriptNameAndProgramCounter()) )
{
// create spherical streaming volume
GtaThread* pGtaThread = CTheScripts::GetCurrentGtaScriptThread();
bool bSceneStreaming = ( assetFlags & fwBoxStreamerAsset::MASK_MAPDATA ) != 0;
spdSphere streamVolSphere((Vec3V)vPos, ScalarV(fRadius));
CStreamVolumeMgr::RegisterSphere(streamVolSphere, (fwBoxStreamerAssetFlags)assetFlags, bSceneStreaming, CStreamVolumeMgr::VOLUME_SLOT_PRIMARY);
CStreamVolumeMgr::SetVolumeScriptInfo(pGtaThread->GetThreadId(), pGtaThread->GetScriptName());
// only request specific lod levels
CStreamVolume& volume = CStreamVolumeMgr::GetVolume( CStreamVolumeMgr::VOLUME_SLOT_PRIMARY );
if ( volume.IsActive() )
{
volume.SetLodMask( lodFlags );
}
}
return 0;
}
int CommandStreamVolCreateFrustum(const scrVector & vPos, const scrVector & vDir, float fFarClip, s32 assetFlags, s32 lodFlags=LODTYPES_MASK_ALL)
{
if ( scriptVerifyf(!g_PlayerSwitch.IsActive(), "Calling STREAMVOL_CREATE_FRUSTUM while a player switch is in progress is not safe! %s", CTheScripts::GetCurrentScriptNameAndProgramCounter()) )
{
// create frustum streaming volume
GtaThread* pGtaThread = CTheScripts::GetCurrentGtaScriptThread();
bool bSceneStreaming = ( assetFlags & fwBoxStreamerAsset::MASK_MAPDATA ) != 0;
CStreamVolumeMgr::RegisterFrustum(Vec3V(vPos), Vec3V(vDir), fFarClip, (fwBoxStreamerAssetFlags)assetFlags, bSceneStreaming, CStreamVolumeMgr::VOLUME_SLOT_PRIMARY);
CStreamVolumeMgr::SetVolumeScriptInfo(pGtaThread->GetThreadId(), pGtaThread->GetScriptName());
// only request specific lod levels
CStreamVolume& volume = CStreamVolumeMgr::GetVolume( CStreamVolumeMgr::VOLUME_SLOT_PRIMARY );
if ( volume.IsActive() )
{
volume.SetLodMask( lodFlags );
}
}
return 0;
}
int CommandStreamVolCreateLine(const scrVector & vPos1, const scrVector & vPos2, s32 assetFlags)
{
if ( scriptVerifyf(!g_PlayerSwitch.IsActive(), "Calling STREAMVOL_CREATE_LINE while a player switch is in progress is not safe! %s", CTheScripts::GetCurrentScriptNameAndProgramCounter()) )
{
// create line segment streaming volume
scriptAssertf(assetFlags==fwBoxStreamerAsset::FLAG_STATICBOUNDS_MOVER,
"STREAMVOL_CREATE_LINE only supports mover collision at present- %s",
CTheScripts::GetCurrentScriptNameAndProgramCounter()
);
GtaThread* pGtaThread = CTheScripts::GetCurrentGtaScriptThread();
bool bSceneStreaming = ( assetFlags & fwBoxStreamerAsset::MASK_MAPDATA ) != 0;
CStreamVolumeMgr::RegisterLine(Vec3V(vPos1), Vec3V(vPos2), (fwBoxStreamerAssetFlags)assetFlags, bSceneStreaming, CStreamVolumeMgr::VOLUME_SLOT_PRIMARY);
CStreamVolumeMgr::SetVolumeScriptInfo(pGtaThread->GetThreadId(), pGtaThread->GetScriptName());
}
return 0;
}
//
// name: CommandStreamVolDelete
// description: removes an existing streaming volume, specified by index
void CommandStreamVolDelete(int UNUSED_PARAM(volumeIndex))
{
if ( scriptVerifyf(!g_LoadScene.IsActive(), "Calling STREAMVOL_DELETE while a new load scene is in progress is not permitted. Calling script is %s, new load scene started by %s", CTheScripts::GetCurrentScriptNameAndProgramCounter(), g_LoadScene.GetScriptName().c_str() ))
{
CStreamVolumeMgr::Deregister( CStreamVolumeMgr::VOLUME_SLOT_PRIMARY );
}
}
//
// name: CommandStreamVolHasLoaded
// description: returns true if the stream volume at the specified index is all loaded, false otherwise
bool CommandStreamVolHasLoaded(int UNUSED_PARAM(volumeIndex))
{
return CStreamVolumeMgr::HasLoaded( CStreamVolumeMgr::VOLUME_SLOT_PRIMARY );
}
//
// name: CommandStreamVolIsValid
// description: returns true if there is a valid, active stream volume at the specified index, false otherwise
bool CommandStreamVolIsValid(int UNUSED_PARAM(volumeIndex))
{
return CStreamVolumeMgr::IsVolumeActive( CStreamVolumeMgr::VOLUME_SLOT_PRIMARY );
}
//
// name: CommandIsStreamVolActive
// description: return true if there is some active streaming volume currently
bool CommandIsStreamVolActive()
{
return CStreamVolumeMgr::IsVolumeActive( CStreamVolumeMgr::VOLUME_SLOT_PRIMARY );
}
//
// name: CommandNewLoadSceneStartFrustum
// description: starts a new load scene at the specified pos, with specified camera direction and farclip
bool CommandNewLoadSceneStartFrustum(const scrVector & vPos, const scrVector & vDir, float fFarClip, s32 controlFlags=0)
{
if ( scriptVerifyf(!g_PlayerSwitch.IsActive(), "Calling NEW_LOAD_SCENE_START while a player switch is in progress is not safe! %s", CTheScripts::GetCurrentScriptNameAndProgramCounter()) )
{
Displayf("Script %s called NEW_LOAD_SCENE_START pos=(%.2f, %.2f, %.2f), dir=(%.2f, %.2f, %.2f), farClip=%.2f, flags=%d",
CTheScripts::GetCurrentScriptNameAndProgramCounter(),
vPos.x, vPos.y, vPos.z, vDir.x, vDir.y, vDir.z, fFarClip, controlFlags
);
GtaThread* pGtaThread = CTheScripts::GetCurrentGtaScriptThread();
g_LoadScene.StartFromScript((Vec3V) vPos, (Vec3V) vDir, fFarClip, pGtaThread->GetThreadId(), true, controlFlags);
return true;
}
return false;
}
//
// name: CommandNewLoadSceneStartSphere
// description: starts a new load scene at the specified pos, and radius
bool CommandNewLoadSceneStartSphere(const scrVector & vPos, float fRadius, s32 controlFlags=0)
{
if ( scriptVerifyf(!g_PlayerSwitch.IsActive(), "Calling NEW_LOAD_SCENE_START_SPHERE while a player switch is in progress is not safe! %s", CTheScripts::GetCurrentScriptNameAndProgramCounter()) )
{
Displayf("Script %s called NEW_LOAD_SCENE_START_SPHERE pos=(%.2f, %.2f, %.2f), radius=%.2f, flags=%d",
CTheScripts::GetCurrentScriptNameAndProgramCounter(),
vPos.x, vPos.y, vPos.z, fRadius, controlFlags
);
GtaThread* pGtaThread = CTheScripts::GetCurrentGtaScriptThread();
g_LoadScene.StartFromScript((Vec3V) vPos, Vec3V(V_ZERO), fRadius, pGtaThread->GetThreadId(), false, controlFlags);
return true;
}
return false;
}
//
// name: CommandNewLoadSceneStop
// description: stops the new load scene, if active
void CommandNewLoadSceneStop()
{
Displayf("Script %s called NEW_LOAD_SCENE_STOP", CTheScripts::GetCurrentScriptNameAndProgramCounter() );
g_LoadScene.Stop();
}
//
// name: CommandIsNewLoadSceneActive
// description: returns true if the new load scene is active, false otherwise
bool CommandIsNewLoadSceneActive()
{
return g_LoadScene.IsActive();
}
//
// name: CommandIsNewLoadSceneLoaded
// description: returns true of the new load scene is fully loaded, false otherwise
bool CommandIsNewLoadSceneLoaded()
{
scriptAssertf( g_LoadScene.IsActive(), "IS_NEW_LOAD_SCENE_LOADED called, but no load scene is currently active: %s", CTheScripts::GetCurrentScriptNameAndProgramCounter() );
return g_LoadScene.IsLoaded();
}
//
// name: CommandIsSafeToStartPlayerSwitch
// description: Sees if it's OK to start a player switch, not in the middle of death or arrest
bool CommandIsSafeToStartPlayerSwitch()
{
#if __BANK
//////////////////////////////////////////////////////////////////////////
// some debug spew to help track down B* 1941681
//
if ( !CGameLogic::IsGameStateInPlay() )
{
scriptDisplayf("Script %s call to IS_SAFE_TO_START_PLAYER_SWITCH returns false because gamestate is not PLAYING (state=%d)", CTheScripts::GetCurrentScriptName(), CGameLogic::GetGameState() );
}
else
{
CPlayerInfo* pPlayerInfo = CGameWorld::GetMainPlayerInfo();
if (!pPlayerInfo)
{
scriptDisplayf("Script %s call to IS_SAFE_TO_START_PLAYER_SWITCH returns false because player info is NULL", CTheScripts::GetCurrentScriptName() );
}
else
{
if ( !pPlayerInfo->GetPlayerPed() )
{
scriptDisplayf("Script %s call to IS_SAFE_TO_START_PLAYER_SWITCH returns false because player ped is NULL", CTheScripts::GetCurrentScriptName() );
}
else if ( pPlayerInfo->GetPlayerState() != CPlayerInfo::PLAYERSTATE_PLAYING )
{
scriptDisplayf("Script %s call to IS_SAFE_TO_START_PLAYER_SWITCH returning false because player state is not PLAYING (state=%d)", CTheScripts::GetCurrentScriptName(), pPlayerInfo->GetPlayerState() );
}
}
}
//////////////////////////////////////////////////////////////////////////
#endif //__BANK
if( CGameLogic::IsGameStateInPlay() )
{
// We're in the GAME_PLAY state
CPlayerInfo *pPlayerInfo = CGameWorld::GetMainPlayerInfo();
// Is the player about to die or get arrested?
if( pPlayerInfo && pPlayerInfo->GetPlayerPed())
{
if( pPlayerInfo->GetPlayerState() == CPlayerInfo::PLAYERSTATE_PLAYING )
{
// no
return true;
}
}
}
return false;
}
//
// name: CommandStartPlayerSwitch
// description: starts a player switch
void CommandStartPlayerSwitch(int oldPedIndex, int newPedIndex, int flags, s32 switchType=CPlayerSwitchInterface::SWITCH_TYPE_AUTO)
{
scriptAssertf( CommandIsSafeToStartPlayerSwitch(), "Script %s called START_PLAYER_SWITCH but IS_SAFE_TO_START_PLAYER_SWITCH is false", CTheScripts::GetCurrentScriptNameAndProgramCounter() );
scriptAssertf( !CWarpManager::IsActive(), "Script %s calling START_PLAYER_SWITCH while a warp is in progress!", CTheScripts::GetCurrentScriptNameAndProgramCounter() );
CPed *pOldPed = CTheScripts::GetEntityToModifyFromGUID<CPed>(oldPedIndex, 0);
CPed *pNewPed = CTheScripts::GetEntityToModifyFromGUID<CPed>(newPedIndex, 0);
scriptAssertf(pOldPed, "Invalid old ped index %d passed from script %s. Switch will not proceed", oldPedIndex, CTheScripts::GetCurrentScriptNameAndProgramCounter());
scriptAssertf(pNewPed, "Invalid new ped index %d passed from script %s. Switch will not proceed", newPedIndex, CTheScripts::GetCurrentScriptNameAndProgramCounter());
#if !__FINAL
if (!pOldPed || !pNewPed)
return;
Vector3 vOldPos = VEC3V_TO_VECTOR3( pOldPed->GetTransform().GetPosition() );
Vector3 vNewPos = VEC3V_TO_VECTOR3( pNewPed->GetTransform().GetPosition() );
Displayf( "START_PLAYER_SWITCH called by %s", CTheScripts::GetCurrentScriptNameAndProgramCounter() );
Displayf( "... src=(%.2f, %.2f, %.2f) dst=(%.2f, %.2f, %.2f) flags=0x%x switchType=%d",
vOldPos.x, vOldPos.y, vOldPos.z, vNewPos.x, vNewPos.y, vNewPos.z, flags, switchType );
#endif //!__FINAL
#if __ASSERT
//////////////////////////////////////////////////////////////////////////
// check to see if script is forcing us to do a switch that is unlikely to work well
if ((flags & CPlayerSwitchInterface::CONTROL_FLAG_UNKNOWN_DEST) != 0)
{
scriptAssertf( switchType!=CPlayerSwitchInterface::SWITCH_TYPE_SHORT,
"Script %s is calling START_PLAYER_SWITCH for short range switch to unknown destination. That won't work",
CTheScripts::GetCurrentScriptNameAndProgramCounter() );
}
else
{
s32 idealSwitchType = g_PlayerSwitch.GetIdealSwitchType( pOldPed->GetTransform().GetPosition(), pNewPed->GetTransform().GetPosition() );
switch (switchType)
{
case CPlayerSwitchInterface::SWITCH_TYPE_MEDIUM:
scriptAssertf( idealSwitchType!=CPlayerSwitchInterface::SWITCH_TYPE_LONG,
"Script %s forcing START_PLAYER_SWITCH to do a medium range switch over too great a distance",
CTheScripts::GetCurrentScriptNameAndProgramCounter() );
break;
case CPlayerSwitchInterface::SWITCH_TYPE_SHORT:
// scriptWarningf( idealSwitchType!=CPlayerSwitchInterface::SWITCH_TYPE_MEDIUM,
// "Script %s forcing START_PLAYER_SWITCH to do a short range switch over too great a distance",
// CTheScripts::GetCurrentScriptNameAndProgramCounter() );
break;
default:
break;
}
}
//////////////////////////////////////////////////////////////////////////
#endif //__ASSERT
if ( pOldPed && pNewPed && scriptVerifyf(!g_PlayerSwitch.IsActive(), "START_PLAYER_SWITCH - a switch is already in progress") )
{
g_PlayerSwitch.Start(switchType, *pOldPed, *pNewPed, flags);
}
}
//
// name: CommandGetPlayerSwitchType
// description: returns the current player switch type
s32 CommandGetPlayerSwitchType()
{
return g_PlayerSwitch.GetSwitchType();
}
//
// name: CommandGetIdealPlayerSwitchType
// description: returns the ideal desired switch type based on the distance from start to end
s32 CommandGetIdealPlayerSwitchType(const scrVector & vStartPos, const scrVector & vEndPos)
{
return g_PlayerSwitch.GetIdealSwitchType((Vec3V) vStartPos, (Vec3V) vEndPos);
}
// name: CommandSetPlayerSwitchOutro
// description: overrides the end scene which is streamed - use if the end scene position differs from the ped pos
void CommandSetPlayerSwitchOutro(const scrVector & vCamPos, const scrVector & vCamRot, float fCamFov, float fCamFarClip, int rotOrder)
{
if (scriptVerifyf(g_PlayerSwitch.IsActive(), "SET_PLAYER_SWITCH_OUTRO called by %s but switch is not active", CTheScripts::GetCurrentScriptNameAndProgramCounter()))
{
if (scriptVerifyf( g_PlayerSwitch.GetSwitchType()!=CPlayerSwitchInterface::SWITCH_TYPE_SHORT, "SET_PLAYER_SWITCH_OUTRO called by %s but that's not valid for a short range switch", CTheScripts::GetCurrentScriptNameAndProgramCounter()))
{
// Vector3 vPos(vCamPos);
Vector3 vRot(vCamRot);
Matrix34 worldMatrix;
CScriptEulers::MatrixFromEulers( worldMatrix, vRot*DtoR, static_cast<EulerAngleOrder>(rotOrder) );
worldMatrix.d = vCamPos;
g_PlayerSwitch.GetLongRangeMgr().OverrideOutroScene( RCC_MAT34V(worldMatrix), fCamFov, fCamFarClip );
}
}
}
// name: CommandSetPlayerSwitchEstablishingShot
// description: sets an establishing which occurs before the outro
void CommandSetPlayerSwitchEstablishingShot(const char* pszShotName)
{
g_PlayerSwitch.GetLongRangeMgr().SetEstablishingShot(atHashString(pszShotName));
}
//
// name: CommandIsPlayerSwitchInProgress
// description: returns true if a switch is in progress, false otherwise
bool CommandIsPlayerSwitchInProgress()
{
return g_PlayerSwitch.IsActive();
}
//
// name: CommandGetPlayerSwitchState
// description: returns the current state of an active player switch
int CommandGetPlayerSwitchState()
{
scriptAssertf( g_PlayerSwitch.IsActive(),
"GET_PLAYER_SWITCH_STATE called by %s but switch is not active",
CTheScripts::GetCurrentScriptNameAndProgramCounter()
);
scriptAssertf(g_PlayerSwitch.GetSwitchType()!=CPlayerSwitchInterface::SWITCH_TYPE_SHORT,
"GET_PLAYER_SWITCH_STATE called by %s - not valid for short range switches",
CTheScripts::GetCurrentScriptNameAndProgramCounter()
);
return g_PlayerSwitch.GetLongRangeMgr().GetState();
}
//
// name: CommandGetPlayerShortSwitchState
// description: returns the current state of an active player short-range switch
int CommandGetPlayerShortSwitchState()
{
scriptAssertf( g_PlayerSwitch.IsActive(),
"GET_PLAYER_SHORT_SWITCH_STATE called by %s but switch is not active",
CTheScripts::GetCurrentScriptNameAndProgramCounter()
);
scriptAssertf(g_PlayerSwitch.GetSwitchType()==CPlayerSwitchInterface::SWITCH_TYPE_SHORT,
"GET_PLAYER_SHORT_SWITCH_STATE called by %s - only valid for short range switches",
CTheScripts::GetCurrentScriptNameAndProgramCounter()
);
return g_PlayerSwitch.GetShortRangeMgr().GetState();
}
void CommandSetPlayerShortSwitchStyle(int style)
{
scriptAssertf( style >= 0,
"SET_PLAYER_SHORT_SWITCH_STYLE - called by %s, invalid style",
CTheScripts::GetCurrentScriptNameAndProgramCounter() );
scriptAssertf( style < CPlayerSwitchMgrShort::NUM_SHORT_SWITCH_STYLES,
"SET_PLAYER_SHORT_SWITCH_STYLE - called by %s, invalid style",
CTheScripts::GetCurrentScriptNameAndProgramCounter() );
g_PlayerSwitch.GetShortRangeMgr().SetStyle( (CPlayerSwitchMgrShort::eStyle)style );
}
//
// name: CommandGetPlayerSwitchJumpCutIndex
// description: returns the index of the current jump cut of an active player switch
int CommandGetPlayerSwitchJumpCutIndex()
{
scriptAssertf( g_PlayerSwitch.IsActive(),
"GET_PLAYER_SWITCH_JUMP_CUT_INDEX called by %s but switch is not active",
CTheScripts::GetCurrentScriptNameAndProgramCounter()
);
scriptAssertf(g_PlayerSwitch.GetSwitchType()!=CPlayerSwitchInterface::SWITCH_TYPE_SHORT,
"GET_PLAYER_SWITCH_JUMP_CUT_INDEX called by %s - not valid for short range switches",
CTheScripts::GetCurrentScriptNameAndProgramCounter()
);
return static_cast<int>(g_PlayerSwitch.GetLongRangeMgr().GetCurrentJumpCutIndex());
}
//
// name: CommandAllowPlayerSwitchPan
// description: if script requires the switch to pause before proceeding with the pan
// (e.g. to stream in some script requested assets etc) this command
// gives the switch mgr the go-ahead to proceed
void CommandAllowPlayerSwitchPan()
{
if ( scriptVerifyf(g_PlayerSwitch.IsActive(), "ALLOW_PLAYER_SWITCH_PAN called by %s but switch is not active", CTheScripts::GetCurrentScriptNameAndProgramCounter()) )
{
scriptAssertf(g_PlayerSwitch.GetSwitchType()!=CPlayerSwitchInterface::SWITCH_TYPE_SHORT,
"ALLOW_PLAYER_SWITCH_PAN called by %s - not valid for short range switches",
CTheScripts::GetCurrentScriptNameAndProgramCounter()
);
g_PlayerSwitch.GetLongRangeMgr().SetControlFlag(CPlayerSwitchInterface::CONTROL_FLAG_PAUSE_BEFORE_PAN, false);
}
}
//
// name: CommandAllowPlayerSwitchOutro
// description: if script requires the switch to pause before proceeding with the outro
// (e.g. to stream in some script requested assets etc) this command
// gives the switch mgr the go-ahead to proceed
void CommandAllowPlayerSwitchOutro()
{
if ( scriptVerifyf(g_PlayerSwitch.IsActive(), "ALLOW_PLAYER_SWITCH_OUTRO called by %s but switch is not active", CTheScripts::GetCurrentScriptNameAndProgramCounter()) )
{
scriptAssertf(g_PlayerSwitch.GetSwitchType()!=CPlayerSwitchInterface::SWITCH_TYPE_SHORT,
"ALLOW_PLAYER_SWITCH_OUTRO called by %s - not valid for short range switches",
CTheScripts::GetCurrentScriptNameAndProgramCounter()
);
g_PlayerSwitch.GetLongRangeMgr().SetControlFlag(CPlayerSwitchInterface::CONTROL_FLAG_PAUSE_BEFORE_OUTRO, false);
}
}
//
// name: CommandAllowPlayerSwitchAscent
// description: if script requires the switch to pause before proceeding with the ascent
// this command gives the switch mgr the go-ahead to proceed when ready
void CommandAllowPlayerSwitchAscent()
{
if ( scriptVerifyf(g_PlayerSwitch.IsActive(), "ALLOW_PLAYER_SWITCH_ASCENT called by %s but switch is not active", CTheScripts::GetCurrentScriptNameAndProgramCounter()) )
{
scriptAssertf(g_PlayerSwitch.GetSwitchType()!=CPlayerSwitchInterface::SWITCH_TYPE_SHORT,
"ALLOW_PLAYER_SWITCH_ASCENT called by %s - not valid for short range switches",
CTheScripts::GetCurrentScriptNameAndProgramCounter()
);
g_PlayerSwitch.GetLongRangeMgr().SetControlFlag(CPlayerSwitchInterface::CONTROL_FLAG_PAUSE_BEFORE_ASCENT, false);
}
}
//
// name: CommandAllowPlayerSwitchDescent
// description: if script requires the switch to pause before proceeding with the descent
// this command gives the switch mgr the go-ahead to proceed when ready
void CommandAllowPlayerSwitchDescent()
{
if ( scriptVerifyf(g_PlayerSwitch.IsActive(), "ALLOW_PLAYER_SWITCH_DESCENT called by %s but switch is not active", CTheScripts::GetCurrentScriptNameAndProgramCounter()) )
{
scriptAssertf(g_PlayerSwitch.GetSwitchType()!=CPlayerSwitchInterface::SWITCH_TYPE_SHORT,
"ALLOW_PLAYER_SWITCH_DESCENT called by %s - not valid for short range switches",
CTheScripts::GetCurrentScriptNameAndProgramCounter()
);
g_PlayerSwitch.GetLongRangeMgr().SetControlFlag(CPlayerSwitchInterface::CONTROL_FLAG_PAUSE_BEFORE_DESCENT, false);
}
}
bool CommandIsSwitchReadyForAscent()
{
if ( scriptVerifyf(g_PlayerSwitch.IsActive(), "IS_SWITCH_READY_FOR_ASCENT called by %s but switch is not active", CTheScripts::GetCurrentScriptNameAndProgramCounter()) )
{
scriptAssertf(g_PlayerSwitch.GetSwitchType()!=CPlayerSwitchInterface::SWITCH_TYPE_SHORT,
"IS_SWITCH_READY_FOR_ASCENT called by %s - not valid for short range switches",
CTheScripts::GetCurrentScriptNameAndProgramCounter()
);
return g_PlayerSwitch.GetLongRangeMgr().ReadyForAscent();
}
return false;
}
bool CommandIsSwitchReadyForDescent()
{
if ( scriptVerifyf(g_PlayerSwitch.IsActive(), "IS_SWITCH_READY_FOR_DESCENT called by %s but switch is not active", CTheScripts::GetCurrentScriptNameAndProgramCounter()) )
{
scriptAssertf(g_PlayerSwitch.GetSwitchType()!=CPlayerSwitchInterface::SWITCH_TYPE_SHORT,
"IS_SWITCH_READY_FOR_DESCENT called by %s - not valid for short range switches",
CTheScripts::GetCurrentScriptNameAndProgramCounter()
);
return g_PlayerSwitch.GetLongRangeMgr().ReadyForDescent();
}
return false;
}
void CommandEnableSwitchPauseBeforeDescent()
{
if ( scriptVerifyf(g_PlayerSwitch.IsActive(), "ENABLE_SWITCH_PAUSE_BEFORE_DESCENT called by %s but switch is not active", CTheScripts::GetCurrentScriptNameAndProgramCounter()) )
{
scriptAssertf(g_PlayerSwitch.GetSwitchType()!=CPlayerSwitchInterface::SWITCH_TYPE_SHORT,
"ENABLE_SWITCH_PAUSE_BEFORE_DESCENT called by %s - not valid for short range switches",
CTheScripts::GetCurrentScriptNameAndProgramCounter()
);
Displayf("[Playerswitch] Script %s calling ENABLE_SWITCH_PAUSE_BEFORE_DESCENT. Switch will hang before descent until script permit progress", CTheScripts::GetCurrentScriptName());
g_PlayerSwitch.GetLongRangeMgr().EnablePauseBeforeDescent();
}
}
void CommandDisableSwitchOutroFX()
{
if ( scriptVerifyf(g_PlayerSwitch.IsActive(), "DISABLE_SWITCH_OUTRO_FX called by %s but switch is not active", CTheScripts::GetCurrentScriptNameAndProgramCounter()) )
{
Displayf("[Playerswitch] Script %s calling DISABLE_SWITCH_OUTRO_FX. Switch will skip outro FX", CTheScripts::GetCurrentScriptName());
s32 switchType = g_PlayerSwitch.GetSwitchType();
CPlayerSwitchMgrBase* mgr = g_PlayerSwitch.GetMgr(switchType);
mgr->SetControlFlag(CPlayerSwitchInterface::CONTROL_FLAG_SUPPRESS_OUTRO_FX,true);
}
}
bool CommandIsSwitchSkippingDescent()
{
if ( scriptVerifyf(g_PlayerSwitch.IsActive(), "IS_SWITCH_SKIPPING_DESCENT called by %s but switch is not active", CTheScripts::GetCurrentScriptNameAndProgramCounter()) )
{
return g_PlayerSwitch.GetLongRangeMgr().IsSkippingDescent();
}
return false;
}
//
// name: CommandSwitchToMultiFirstPart
// description: perform the first part of the player switch (ascent part) when the destination
// is currently unknown (pending user input during character selection screen etc)
void CommandSwitchToMultiFirstPart(int oldPedIndex, int flags, s32 switchType=CPlayerSwitchInterface::SWITCH_TYPE_LONG)
{
scriptAssertf( !CWarpManager::IsActive(), "Script %s calling SWITCH_TO_MULTI_FIRSTPART while a warp is in progress!", CTheScripts::GetCurrentScriptNameAndProgramCounter() );
scriptAssertf( CommandIsSafeToStartPlayerSwitch(), "Script %s called SWITCH_TO_MULTI_FIRSTPART but IS_SAFE_TO_START_PLAYER_SWITCH is false", CTheScripts::GetCurrentScriptNameAndProgramCounter() );
CPed *pOldPed = CTheScripts::GetEntityToModifyFromGUID<CPed>(oldPedIndex, 0);
if ( pOldPed && scriptVerifyf(!g_PlayerSwitch.IsActive(), "SWITCH_TO_MULTI_FIRSTPART - a switch is already in progress") )
{
#if !__FINAL
Vector3 vOldPos = VEC3V_TO_VECTOR3( pOldPed->GetTransform().GetPosition() );
Displayf( "SWITCH_TO_MULTI_FIRSTPART called by %s", CTheScripts::GetCurrentScriptNameAndProgramCounter() );
Displayf( "... src=(%.2f, %.2f, %.2f) flags=0x%x type=%d", vOldPos.x, vOldPos.y, vOldPos.z, flags, switchType );
#endif //!__FINAL
g_PlayerSwitch.Start(switchType, *pOldPed, *pOldPed, flags | CPlayerSwitchInterface::CONTROL_FLAG_UNKNOWN_DEST);
}
}
//
// name: CommandIsSwitchToMultiFirstPartFinished
// description: returns true if the player switch is currently finished its ascent and is holding,
// waiting for more information about the destination of the switch
bool CommandIsSwitchToMultiFirstPartFinished()
{
return ( g_PlayerSwitch.GetLongRangeMgr().GetState() == CPlayerSwitchMgrLong::STATE_WAITFORINPUT );
}
//
// name: CommandSwitchToMultiSecondPart
// description: perform the second part of the player switch (pan and descent parts) because the destination ped
// is now known.
void CommandSwitchToMultiSecondPart(int newPedIndex)
{
CPed *pNewPed = CTheScripts::GetEntityToModifyFromGUID<CPed>(newPedIndex, 0);
if ( pNewPed && scriptVerifyf(g_PlayerSwitch.IsActive(), "START_PLAYER_SWITCH - a switch is not already in progress") )
{
#if !__FINAL
Vector3 vNewPos = VEC3V_TO_VECTOR3( pNewPed->GetTransform().GetPosition() );
Displayf( "[Playerswitch] SWITCH_TO_MULTI_SECONDPART called by %s", CTheScripts::GetCurrentScriptNameAndProgramCounter() );
Displayf( "... dst=(%.2f, %.2f, %.2f)", vNewPos.x, vNewPos.y, vNewPos.z );
#endif //!__FINAL
#if __ASSERT
scriptAssertf(g_PlayerSwitch.GetSwitchType()!=CPlayerSwitchInterface::SWITCH_TYPE_SHORT, "SWITCH_TO_MULTI_SECOND_PART is not valid for short range switching");
//////////////////////////////////////////////////////////////////////////
s32 idealSwitchType = g_PlayerSwitch.GetIdealSwitchType( g_PlayerSwitch.GetLongRangeMgr().GetStartPos(), pNewPed->GetTransform().GetPosition() );
switch (g_PlayerSwitch.GetSwitchType())
{
case CPlayerSwitchInterface::SWITCH_TYPE_MEDIUM:
scriptAssertf( idealSwitchType!=CPlayerSwitchInterface::SWITCH_TYPE_LONG,
"Script %s forcing SWITCH_TO_MULTI_SECOND_PART to do a medium range switch over too great a distance!",
CTheScripts::GetCurrentScriptNameAndProgramCounter() );
break;
case CPlayerSwitchInterface::SWITCH_TYPE_SHORT:
scriptAssertf( idealSwitchType!=CPlayerSwitchInterface::SWITCH_TYPE_MEDIUM,
"Script %s forcing SWITCH_TO_MULTI_SECOND_PART to do a short range switch over too great a distance",
CTheScripts::GetCurrentScriptNameAndProgramCounter() );
break;
default:
break;
}
//////////////////////////////////////////////////////////////////////////
#endif //__ASSERT
g_PlayerSwitch.SetDest(*pNewPed);
}
}
//
// name: CommandSstopPlayerSwitch
// description: abandon a switch, if active
void CommandStopPlayerSwitch()
{
Displayf( "STOP_PLAYER_SWITCH called by %s", CTheScripts::GetCurrentScriptNameAndProgramCounter() );
if (g_PlayerSwitch.IsActive())
{
g_PlayerSwitch.Stop();
}
}
// name: CommandGetPlayerSwitchInterpOutDuration
// description: returns the duration of any interpolation out of an establishing shot, in milliseconds, or 0 if invalid
int CommandGetPlayerSwitchInterpOutDuration()
{
const CPlayerSwitchEstablishingShotMetadata* pEstablishingShotData = g_PlayerSwitch.GetLongRangeMgr().GetEstablishingShotData();
s32 duration = pEstablishingShotData ? static_cast<s32>(pEstablishingShotData->m_InterpolateOutDuration) : 0;
return duration;
}
void CommandSetSceneStreamingTracksCamPosThisFrame()
{
CSceneStreamerMgr::ForceSceneStreamerToTrackWithCameraPosThisFrame();
}
float CommandGetLodScale()
{
return g_LodScale.GetGlobalScale();
}
// name: CommandGetPlayerSwitchInterpOutCurrentTime
// description: returns the current interpolation time out of an establishing shot, in milliseconds. -1 will be returned if interpolation is not in progress
int CommandGetPlayerSwitchInterpOutCurrentTime()
{
const camSwitchDirector& switchDirector = camInterface::GetSwitchDirector();
camBaseDirector::eRenderStates renderState = switchDirector.GetRenderState();
s32 currentTime = (renderState == camBaseDirector::RS_INTERPOLATING_OUT) ? switchDirector.GetInterpolationTime() : -1;
return currentTime;
}
//
// name: CommandOverrideLodScaleThisFrame
//
void CommandOverrideLodScaleThisFrame(float fLodScale)
{
g_LodScale.SetGlobalScaleFromScript(fLodScale);
}
void CommandRemapLodScaleRangeThisFrame(float fOldMin, float fOldMax, float fNewMin, float fNewMax)
{
g_LodScale.SetRemappingFromScript(fOldMin, fOldMax, fNewMin, fNewMax);
}
void CommandSuppressHdMapStreamingThisFrame()
{
CStreaming::ScriptSuppressHdImapsThisFrame();
}
void CommandForceAllowTimeBasedFadingThisFrame()
{
g_LodMgr.ScriptForceAllowTimeBasedFadingThisFrame();
}
//
// name: CommandSetRenderHdOnly
//
void CommandSetRenderHdOnly(bool bHdOnly)
{
if ( scriptVerifyf(!g_PlayerSwitch.IsActive(), "Calling SET_RENDER_HD_ONLY while a player switch is in progress is not safe! %s", CTheScripts::GetCurrentScriptNameAndProgramCounter()) )
{
Displayf( "Script called SET_RENDER_HD_ONLY(%s) - %s", (bHdOnly?"true":"false"), CTheScripts::GetCurrentScriptNameAndProgramCounter() );
if (bHdOnly)
{
g_LodMgr.ScriptRequestRenderHdOnly();
}
else
{
g_LodMgr.StopSlodMode();
}
}
}
//
// name: CommandIplGroupSwapStart
//
// allows user to seamlessly switch between two IPL groups in a frame, by pre-streaming the assets for the second group
// before switching it on (and switching off the first one)
//
void CommandIplGroupSwapStart(const char* iplGroupBefore, const char* iplGroupAfter)
{
Displayf("Script %s called IPL_GROUP_SWAP_START(%s, %s)", CTheScripts::GetCurrentScriptNameAndProgramCounter(), iplGroupBefore, iplGroupAfter);
strLocalIndex indexBefore = strLocalIndex(INSTANCE_STORE.FindSlot(iplGroupBefore));
strLocalIndex indexAfter = strLocalIndex(INSTANCE_STORE.FindSlot(iplGroupAfter));
scriptAssertf(indexBefore!=-1, "IPL_GROUP_SWAP_START called by %s but %s is missing", CTheScripts::GetCurrentScriptNameAndProgramCounter(), iplGroupBefore);
scriptAssertf(indexAfter!=-1, "IPL_GROUP_SWAP_START called by %s but %s is missing", CTheScripts::GetCurrentScriptNameAndProgramCounter(), iplGroupAfter);
const bool bBothIplGroupsExist = (indexBefore != -1) && (indexAfter != -1);
if (bBothIplGroupsExist)
{
scriptAssertf( g_MapDataStore.GetIsStreamable(indexBefore), "IPL_GROUP_SWAP_START: %s should be enabled", iplGroupBefore );
scriptAssertf( !g_MapDataStore.GetIsStreamable(indexAfter), "IPL_GROUP_SWAP_START: %s should be disabled", iplGroupAfter );
const bool bCorrectInitialState = (g_MapDataStore.GetIsStreamable(indexBefore) && !g_MapDataStore.GetIsStreamable(indexAfter));
if (bCorrectInitialState)
{
// register new swap, mark as script owned, and return swap index
atHashString startNameHash(iplGroupBefore);
atHashString endNameHash(iplGroupAfter);
GtaThread* pGtaThread = CTheScripts::GetCurrentGtaScriptThread();
g_MapDataStore.GetGroupSwapper().CreateNewSwapForScript(startNameHash, endNameHash, pGtaThread->GetThreadId());
}
}
}
//
// name: CommandIplGroupSwapIsReady
//
// returns true if the IPL group swap is fully loaded and ready to transition, false otherwise
//
bool CommandIplGroupSwapIsReady()
{
return g_MapDataStore.GetGroupSwapper().GetIsLoaded(fwImapGroupMgr::SCRIPT_INDEX);
}
//
// name: CommandIplGroupSwapFinish
//
// performs the swap - switches on the end state, switches off the start state, removes the active swapper
//
void CommandIplGroupSwapFinish()
{
Displayf("Script %s called IPL_GROUP_SWAP_FINISH", CTheScripts::GetCurrentScriptNameAndProgramCounter());
scriptAssertf(g_MapDataStore.GetGroupSwapper().GetIsActive(fwImapGroupMgr::SCRIPT_INDEX), "IPL group swap is not active (ie has been completed or canceled)");
g_MapDataStore.GetGroupSwapper().CompleteSwap(fwImapGroupMgr::SCRIPT_INDEX, false);
}
//
// name: CommandIplGroupSwapCancel
//
// abandon a currently active IPL group swap
void CommandIplGroupSwapCancel()
{
Displayf("Script %s called IPL_GROUP_SWAP_CANCEL", CTheScripts::GetCurrentScriptNameAndProgramCounter());
scriptAssertf( g_MapDataStore.GetGroupSwapper().GetIsActive(fwImapGroupMgr::SCRIPT_INDEX), "IPL group swap is not active (ie has been completed or canceled)");
g_MapDataStore.GetGroupSwapper().AbandonSwap(fwImapGroupMgr::SCRIPT_INDEX);
}
bool CommandIplGroupSwapIsActive()
{
return g_MapDataStore.GetGroupSwapper().GetIsActive(fwImapGroupMgr::SCRIPT_INDEX);
}
#if __BANK
//////////////////////////////////////////////////////////////////////////
// TRAILER 2 ONLY
void CommandEnableExtraDistantLights(const scrVector & vPos, float fRadius)
{
DebugLighting::EnableExtraDistantLights(vPos, fRadius);
}
void CommandDisableExtraDistantLights()
{
// TRAILER 2 ONLY
DebugLighting::DisableExtraDistantLights();
}
//////////////////////////////////////////////////////////////////////////
#else
void CommandEnableExtraDistantLights(const scrVector &, float) {}
void CommandDisableExtraDistantLights() {}
#endif
void CommandPrefetchSrl(const char *srlName)
{
gStreamingRequestList.BeginPrestream(srlName, true);
}
bool CommandIsSrlLoaded()
{
return gStreamingRequestList.AreAllAssetsLoaded();
}
void CommandBeginSrl()
{
gStreamingRequestList.Start();
}
void CommandEndSrl()
{
gStreamingRequestList.Finish();
}
void CommandSetSrlTime(float time)
{
gStreamingRequestList.SetTime(time);
}
void CommandSetSrlPostCutsceneCamera(const scrVector & vPos, const scrVector & vDir)
{
gStreamingRequestList.SetPostCutsceneCamera(vPos, vDir);
}
void CommandSetSrlReadAheadTimes(int prestreamMap, int prestreamAssets, int playbackMap, int playbackAssets)
{
gStreamingRequestList.SetSrlReadAheadTimes(prestreamMap, prestreamAssets, playbackMap, playbackAssets);
}
void CommandSetSrlLongJumpMode(bool enableLongJumpMode)
{
gStreamingRequestList.SetLongJumpMode(enableLongJumpMode);
}
void CommandSetSrlForcePrestream(s32 prestreamMode)
{
gStreamingRequestList.SetPrestreamMode((SrlPrestreamMode) prestreamMode);
}
void CommandSetHdArea(const scrVector& scrPos, float radius)
{
CTexLod::SetHdArea(scrPos.x, scrPos.y, scrPos.z, radius);
}
void CommandClearHdArea()
{
CTexLod::ClearHdArea();
}
void CommandInitCreatorBudget()
{
MissionCreatorAssets::Init();
}
void CommandShutdownCreatorBudget()
{
MissionCreatorAssets::Shutdown();
}
bool CommandHasRoomForModelInCreatorBudget(int modelHash)
{
fwModelId modelId;
CBaseModelInfo* pModelInfo = CModelInfo::GetBaseModelInfoFromHashKey((u32)modelHash, &modelId);
if (scriptVerifyf(pModelInfo, "%s: HAS_ROOM_FOR_MODEL_IN_CREATOR_BUDGET - model with hash %d does not exist", CTheScripts::GetCurrentScriptNameAndProgramCounter(), modelHash))
{
if (scriptVerifyf(modelId.IsValid(), "%s: HAS_ROOM_FOR_MODEL_IN_CREATOR_BUDGET - model with hash %d exists but its model index is invalid", CTheScripts::GetCurrentScriptNameAndProgramCounter(), modelHash))
{
return MissionCreatorAssets::HasRoomForModel(modelId);
}
}
return false;
}
bool CommandAddModelToCreatorBudget(int modelHash)
{
fwModelId modelId;
CBaseModelInfo* pModelInfo = CModelInfo::GetBaseModelInfoFromHashKey((u32)modelHash, &modelId);
if (scriptVerifyf(pModelInfo, "%s: ADD_MODEL_TO_CREATOR_BUDGET - model with hash %d does not exist", CTheScripts::GetCurrentScriptNameAndProgramCounter(), modelHash))
{
if (scriptVerifyf(modelId.IsValid(), "%s: ADD_MODEL_TO_CREATOR_BUDGET - model with hash %d exists but its model index is invalid", CTheScripts::GetCurrentScriptNameAndProgramCounter(), modelHash))
{
return MissionCreatorAssets::AddModel(modelId);
}
}
return false;
}
void CommandRemoveModelFromCreatorBudget(int modelHash)
{
fwModelId modelId;
CBaseModelInfo* pModelInfo = CModelInfo::GetBaseModelInfoFromHashKey((u32)modelHash, &modelId);
if (scriptVerifyf(pModelInfo, "%s: REMOVE_MODEL_FROM_CREATOR_BUDGET - model with hash %d does not exist", CTheScripts::GetCurrentScriptNameAndProgramCounter(), modelHash))
{
if (scriptVerifyf(modelId.IsValid(), "%s: REMOVE_MODEL_FROM_CREATOR_BUDGET - model with hash %d exists but its model index is invalid", CTheScripts::GetCurrentScriptNameAndProgramCounter(), modelHash))
{
MissionCreatorAssets::RemoveModel(modelId);
}
}
}
float CommandGetUsedCreatorBudget()
{
return MissionCreatorAssets::GetUsedBudget();
}
void CommandSetIslandEnabled(char const* pIslandName, bool enable)
{
CIslandHopper::GetInstance().RequestToggleIsland(pIslandName, enable);
}
bool CommandAreIslandIPLsActive()
{
return CIslandHopper::GetInstance().AreCurrentIslandIPLsActive();
}
bool CommandIsGameInstalled()
{
return CFileMgr::IsGameInstalled();
}
//
// name: SetupScriptCommands
// description: Setup streaming script commands
void SetupScriptCommands()
{
SCR_REGISTER_SECURE(LOAD_ALL_OBJECTS_NOW,0x0f3dc7925afebdfc, LoadAllObjectsNow);
SCR_REGISTER_SECURE(LOAD_SCENE,0x42c4310e76ad635a, LoadScene);
SCR_REGISTER_UNUSED(NETWORK_START_LOAD_SCENE,0xba65ca1a62ca5efa, StartLoadScene);
SCR_REGISTER_SECURE(NETWORK_UPDATE_LOAD_SCENE,0x5ee9da6c0c12274b, UpdateLoadScene);
SCR_REGISTER_UNUSED(NETWORK_STOP_LOAD_SCENE,0x61c0d41714aac740, StopLoadScene);
SCR_REGISTER_SECURE(IS_NETWORK_LOADING_SCENE,0x340c8b9022477b2f, IsLoadSceneActive);
SCR_REGISTER_UNUSED(LOAD_SCENE_FOR_ROOM_BY_KEY,0x77266ff77886d086, LoadSceneForRoomByKey);
SCR_REGISTER_SECURE(SET_INTERIOR_ACTIVE,0x28a0a1eb9d59910d, CommandActivateInterior);
SCR_REGISTER_SECURE(REQUEST_MODEL,0xd69a0c3662175e68, CommandRequestModel);
SCR_REGISTER_SECURE(REQUEST_MENU_PED_MODEL,0x24f2c68f9513392f, CommandRequestMenuPedModel);
SCR_REGISTER_SECURE(HAS_MODEL_LOADED,0x0152aa00fa3130f1, HasModelLoaded);
SCR_REGISTER_UNUSED(REQUEST_INTERIOR_MODELS,0x620e68adda3d0a93, RequestInteriorModels);
SCR_REGISTER_SECURE(REQUEST_MODELS_IN_ROOM,0x0f1bef3db99b3f66, RequestModelsInRoom);
SCR_REGISTER_SECURE(SET_MODEL_AS_NO_LONGER_NEEDED,0xf1a23b343dfedfd0, CommandMarkModelAsNoLongerNeeded);
SCR_REGISTER_SECURE(IS_MODEL_IN_CDIMAGE,0x51046eee00e2bbda, IsModelInCdImage);
SCR_REGISTER_SECURE(IS_MODEL_VALID,0x61adf697df551da6, CommandIsModelValid);
SCR_REGISTER_UNUSED(GET_PED_MODEL_FROM_INDEX,0x25a52190ae4733a7, CommandGetPedModelFromIndex);
SCR_REGISTER_UNUSED(GET_VEHICLE_MODEL_FROM_INDEX,0x0c5271cf0ccaf6e4, CommandGetVehicleModelFromIndex);
SCR_REGISTER_SECURE(IS_MODEL_A_PED,0x5a01a43be2689db0, CommandIsThisModelAPed);
SCR_REGISTER_SECURE(IS_MODEL_A_VEHICLE,0x2886b1bfe0896a9a, CommandIsThisModelAVehicle);
SCR_REGISTER_UNUSED(REQUEST_MOVER_COLLISION_ONLY,0xfeab902a1748345f, RequestMoverCollisionOnly);
SCR_REGISTER_SECURE(REQUEST_COLLISION_AT_COORD,0xe49a23f069c82c93, RequestCollisionAtPosn);
SCR_REGISTER_SECURE(REQUEST_COLLISION_FOR_MODEL,0xb557c195bbd7d051, RequestCollisionForModel);
SCR_REGISTER_SECURE(HAS_COLLISION_FOR_MODEL_LOADED,0x30229254f181806b, HasCollisionForModelLoaded);
SCR_REGISTER_SECURE(REQUEST_ADDITIONAL_COLLISION_AT_COORD,0x616bf5910d72dca9, AddNeededAtPosn);
SCR_REGISTER_SECURE(DOES_ANIM_DICT_EXIST,0xa430c2581c66a9ad, DoesAnimDictExist);
SCR_REGISTER_SECURE(REQUEST_ANIM_DICT,0x8fb472886552d737, RequestAnimDict);
SCR_REGISTER_SECURE(HAS_ANIM_DICT_LOADED,0x6f940c2636c076ad, HasAnimDictLoaded);
SCR_REGISTER_SECURE(REMOVE_ANIM_DICT,0xafc1fbf3f6ae7b9a, RemoveAnimDict);
// START OF DEPRECATED
SCR_REGISTER_SECURE(REQUEST_ANIM_SET,0x3aca4f727ac4606e, RequestClipSet);
SCR_REGISTER_SECURE(HAS_ANIM_SET_LOADED,0xbb103a5dec572725,HasClipSetLoaded);
SCR_REGISTER_SECURE(REMOVE_ANIM_SET,0x5f75840181672fad, RemoveClipSet);
// END OF DEPRECATED
SCR_REGISTER_SECURE(REQUEST_CLIP_SET,0x511a0af0e8b0bf9a, RequestClipSet);
SCR_REGISTER_SECURE(HAS_CLIP_SET_LOADED,0xa7a5d14f877c9047,HasClipSetLoaded);
SCR_REGISTER_SECURE(REMOVE_CLIP_SET,0x840dce5f5f53d8e0, RemoveClipSet);
SCR_REGISTER_SECURE(REQUEST_IPL,0x13a763a67ba2a95b, RequestIpl);
SCR_REGISTER_SECURE(REMOVE_IPL,0x9d2accf306f3a0c5, RemoveIpl);
SCR_REGISTER_SECURE(IS_IPL_ACTIVE,0x8dd54478cfa35f08, IsIplActive);
SCR_REGISTER_SECURE(SET_STREAMING,0x8e4329fd81081a2a, SwitchStreaming);
SCR_REGISTER_UNUSED(SET_SCENE_STREAMING,0xafa0231603f22be9, EnableSceneStreaming);
SCR_REGISTER_SECURE(LOAD_GLOBAL_WATER_FILE,0x11f9af5e230d40d6, LoadGlobalWaterFile);
SCR_REGISTER_SECURE(GET_GLOBAL_WATER_FILE,0xcb446f8296efd9bb, GetGlobalWaterFile);
SCR_REGISTER_SECURE(SET_GAME_PAUSES_FOR_STREAMING,0x47c032cd609587ee, AllowGameToPauseForStreaming);
SCR_REGISTER_SECURE(SET_REDUCE_PED_MODEL_BUDGET,0x718886bcae2bd894, SetReducePedModelBudget);
SCR_REGISTER_SECURE(SET_REDUCE_VEHICLE_MODEL_BUDGET,0x9a78aa1fbfc8a2ac, SetReduceVehicleModelBudget);
SCR_REGISTER_SECURE(SET_DITCH_POLICE_MODELS,0x2613fa815056d2d9, SetDitchPoliceModels);
SCR_REGISTER_SECURE(GET_NUMBER_OF_STREAMING_REQUESTS,0xee21e8a6031cea47, GetNumStreamingRequests);
SCR_REGISTER_UNUSED(IS_STREAMING_PRIORITY_REQUESTS,0x443cd194a3b45769, IsStreamingPriorityRequests);
SCR_REGISTER_SECURE(REQUEST_PTFX_ASSET,0x9e63031c188793e1, RequestPtFxAsset);
SCR_REGISTER_SECURE(HAS_PTFX_ASSET_LOADED,0x51b6c2ef8dbe2e1a, HasPtFxAssetLoaded);
SCR_REGISTER_SECURE(REMOVE_PTFX_ASSET,0xe6239ccb98b8ab66, RemovePtFxAsset);
SCR_REGISTER_SECURE(REQUEST_NAMED_PTFX_ASSET,0xd86c99569d4749b0, RequestNamedPtFxAsset);
SCR_REGISTER_SECURE(HAS_NAMED_PTFX_ASSET_LOADED,0x6264b811e8d92198, HasNamedPtFxAssetLoaded);
SCR_REGISTER_SECURE(REMOVE_NAMED_PTFX_ASSET,0x416ba6ce9f7e648b, RemoveNamedPtFxAsset);
SCR_REGISTER_SECURE(SET_VEHICLE_POPULATION_BUDGET,0xa121d58142738a8d, SetVehiclePopulationBudget);
SCR_REGISTER_SECURE(SET_PED_POPULATION_BUDGET,0x8c5e1b04c94ff212, SetPedPopulationBudget);
SCR_REGISTER_SECURE(CLEAR_FOCUS,0x5639e771f6085bf6, ClearFocus);
SCR_REGISTER_SECURE(SET_FOCUS_POS_AND_VEL,0x7d5c42a7cdb11db6, SetFocusPosAndVel);
SCR_REGISTER_SECURE(SET_FOCUS_ENTITY,0x34582635da718e5a, SetFocusEntity);
SCR_REGISTER_SECURE(IS_ENTITY_FOCUS,0xf184bef0dbd3ad20, IsEntityFocus);
SCR_REGISTER_SECURE(SET_RESTORE_FOCUS_ENTITY,0xe35fcef2127afccf, SetRestoreFocusEntity);
SCR_REGISTER_SECURE(SET_MAPDATACULLBOX_ENABLED,0xa624331352defdcd, SetMapDataCullBoxEnabled);
SCR_REGISTER_SECURE(SET_ALL_MAPDATA_CULLED,0x4c6cbcfdd1730e10, SetAllMapDataCulled);
SCR_REGISTER_UNUSED(SET_HORIZON_OBJECTS_CULLED,0x0243893e8540fa67, SetHorizonObjectsCulled);
SCR_REGISTER_SECURE(STREAMVOL_CREATE_SPHERE,0xd6d670d39e5eb332, CommandStreamVolCreateSphere);
SCR_REGISTER_SECURE(STREAMVOL_CREATE_FRUSTUM,0xedf40cc24ee4ff61, CommandStreamVolCreateFrustum);
SCR_REGISTER_SECURE(STREAMVOL_CREATE_LINE,0x83a445abf2242661, CommandStreamVolCreateLine);
SCR_REGISTER_SECURE(STREAMVOL_DELETE,0x7de67eeefec38205, CommandStreamVolDelete);
SCR_REGISTER_SECURE(STREAMVOL_HAS_LOADED,0x247b9cd82fd64f32, CommandStreamVolHasLoaded);
SCR_REGISTER_SECURE(STREAMVOL_IS_VALID,0x52d132f41e04cb67, CommandStreamVolIsValid);
SCR_REGISTER_SECURE(IS_STREAMVOL_ACTIVE,0xff4a0a9572c2f565, CommandIsStreamVolActive);
SCR_REGISTER_SECURE(NEW_LOAD_SCENE_START,0xb37c5672ee23d04f, CommandNewLoadSceneStartFrustum);
SCR_REGISTER_SECURE(NEW_LOAD_SCENE_START_SPHERE,0xca60df1d01dbd440, CommandNewLoadSceneStartSphere);
SCR_REGISTER_SECURE(NEW_LOAD_SCENE_STOP,0xee3a19a84a10f8b9, CommandNewLoadSceneStop);
SCR_REGISTER_SECURE(IS_NEW_LOAD_SCENE_ACTIVE,0x2981c54770e1d19c, CommandIsNewLoadSceneActive);
SCR_REGISTER_SECURE(IS_NEW_LOAD_SCENE_LOADED,0x8a6ab093d1ee5368, CommandIsNewLoadSceneLoaded);
SCR_REGISTER_SECURE(IS_SAFE_TO_START_PLAYER_SWITCH,0x3510bf4043201732, CommandIsSafeToStartPlayerSwitch);
SCR_REGISTER_SECURE(START_PLAYER_SWITCH,0xccd7aa32a884016d, CommandStartPlayerSwitch);
SCR_REGISTER_SECURE(STOP_PLAYER_SWITCH,0x310f3c51704851d4, CommandStopPlayerSwitch);
SCR_REGISTER_SECURE(IS_PLAYER_SWITCH_IN_PROGRESS,0x04458b4e5d9e466a, CommandIsPlayerSwitchInProgress);
SCR_REGISTER_SECURE(GET_PLAYER_SWITCH_TYPE,0xb6bdac890771ed04, CommandGetPlayerSwitchType);
SCR_REGISTER_SECURE(GET_IDEAL_PLAYER_SWITCH_TYPE,0x22c67338735160aa, CommandGetIdealPlayerSwitchType);
SCR_REGISTER_SECURE(GET_PLAYER_SWITCH_STATE,0xeefb36b938654045, CommandGetPlayerSwitchState);
SCR_REGISTER_SECURE(GET_PLAYER_SHORT_SWITCH_STATE,0xaa8fd727e9cd9929, CommandGetPlayerShortSwitchState);
SCR_REGISTER_SECURE(SET_PLAYER_SHORT_SWITCH_STYLE,0xe48e4b99dba9eaa1, CommandSetPlayerShortSwitchStyle);
SCR_REGISTER_SECURE(GET_PLAYER_SWITCH_JUMP_CUT_INDEX,0x39c67356e2acaf22, CommandGetPlayerSwitchJumpCutIndex);
SCR_REGISTER_SECURE(SET_PLAYER_SWITCH_OUTRO,0xd6466d9b50e967e5, CommandSetPlayerSwitchOutro);
SCR_REGISTER_SECURE(SET_PLAYER_SWITCH_ESTABLISHING_SHOT,0x6c31ccf5981b2c06, CommandSetPlayerSwitchEstablishingShot);
SCR_REGISTER_SECURE(ALLOW_PLAYER_SWITCH_PAN,0x4e554357e32f827c, CommandAllowPlayerSwitchPan);
SCR_REGISTER_SECURE(ALLOW_PLAYER_SWITCH_OUTRO,0x92fe9bfdb58c08b1, CommandAllowPlayerSwitchOutro);
SCR_REGISTER_SECURE(ALLOW_PLAYER_SWITCH_ASCENT,0x01aa29ae1a82b574, CommandAllowPlayerSwitchAscent);
SCR_REGISTER_SECURE(ALLOW_PLAYER_SWITCH_DESCENT,0x2192f61b6fb23e19, CommandAllowPlayerSwitchDescent);
SCR_REGISTER_UNUSED(IS_SWITCH_READY_FOR_ASCENT,0xa7589c3c447ac818, CommandIsSwitchReadyForAscent);
SCR_REGISTER_SECURE(IS_SWITCH_READY_FOR_DESCENT,0xf7fa5e5f48d7ef30, CommandIsSwitchReadyForDescent);
SCR_REGISTER_SECURE(ENABLE_SWITCH_PAUSE_BEFORE_DESCENT,0xe28d19155d6799a8, CommandEnableSwitchPauseBeforeDescent);
SCR_REGISTER_SECURE(DISABLE_SWITCH_OUTRO_FX,0x3e99c894fa419af2, CommandDisableSwitchOutroFX);
SCR_REGISTER_SECURE(SWITCH_TO_MULTI_FIRSTPART,0xa1bc090595ba935f, CommandSwitchToMultiFirstPart);
SCR_REGISTER_SECURE(SWITCH_TO_MULTI_SECONDPART,0xbaac2fbaae6257db, CommandSwitchToMultiSecondPart);
SCR_REGISTER_SECURE(IS_SWITCH_TO_MULTI_FIRSTPART_FINISHED,0x5e9ec8eea03bcec7, CommandIsSwitchToMultiFirstPartFinished);
SCR_REGISTER_SECURE(GET_PLAYER_SWITCH_INTERP_OUT_DURATION,0x78fd52dd96d53522, CommandGetPlayerSwitchInterpOutDuration);
SCR_REGISTER_SECURE(GET_PLAYER_SWITCH_INTERP_OUT_CURRENT_TIME,0x5ad9f5341c05bc7d, CommandGetPlayerSwitchInterpOutCurrentTime);
SCR_REGISTER_SECURE(IS_SWITCH_SKIPPING_DESCENT,0x9fd60deda01f20a5, CommandIsSwitchSkippingDescent);
SCR_REGISTER_SECURE(SET_SCENE_STREAMING_TRACKS_CAM_POS_THIS_FRAME,0xa63f1768421c7a80, CommandSetSceneStreamingTracksCamPosThisFrame);
SCR_REGISTER_SECURE(GET_LODSCALE,0xb32301583643b6b3, CommandGetLodScale);
SCR_REGISTER_SECURE(OVERRIDE_LODSCALE_THIS_FRAME,0x9b8b94a1196f345f, CommandOverrideLodScaleThisFrame);
SCR_REGISTER_SECURE(REMAP_LODSCALE_RANGE_THIS_FRAME,0x34666baa70bf66df, CommandRemapLodScaleRangeThisFrame);
SCR_REGISTER_SECURE(SUPPRESS_HD_MAP_STREAMING_THIS_FRAME,0xb1a39942d4e31aa5, CommandSuppressHdMapStreamingThisFrame);
SCR_REGISTER_SECURE(SET_RENDER_HD_ONLY,0xd2726749ba8dac02, CommandSetRenderHdOnly);
SCR_REGISTER_SECURE(FORCE_ALLOW_TIME_BASED_FADING_THIS_FRAME,0x7426ead34c015246, CommandForceAllowTimeBasedFadingThisFrame);
SCR_REGISTER_SECURE(IPL_GROUP_SWAP_START,0x25cf3b0410cd653c, CommandIplGroupSwapStart);
SCR_REGISTER_SECURE(IPL_GROUP_SWAP_CANCEL,0x8de9b7e224bcb723, CommandIplGroupSwapCancel);
SCR_REGISTER_SECURE(IPL_GROUP_SWAP_IS_READY,0x329d6926716ee57f, CommandIplGroupSwapIsReady);
SCR_REGISTER_SECURE(IPL_GROUP_SWAP_FINISH,0x015da57f7a0fa1a6, CommandIplGroupSwapFinish);
SCR_REGISTER_SECURE(IPL_GROUP_SWAP_IS_ACTIVE,0x29978d4627985414, CommandIplGroupSwapIsActive);
SCR_REGISTER_UNUSED(ENABLE_EXTRA_DISTANTLIGHTS,0x0ea9823cbd5fc533, CommandEnableExtraDistantLights);
SCR_REGISTER_UNUSED(DISABLE_EXTRA_DISTANTLIGHTS,0x04ea50ecc60d4da3, CommandDisableExtraDistantLights);
SCR_REGISTER_SECURE(PREFETCH_SRL,0x0728c4d61e5ace06, CommandPrefetchSrl);
SCR_REGISTER_SECURE(IS_SRL_LOADED,0xd66fb6b74ee3da66, CommandIsSrlLoaded);
SCR_REGISTER_SECURE(BEGIN_SRL,0x670baa84466115ca, CommandBeginSrl);
SCR_REGISTER_SECURE(END_SRL,0x7e8f5ae44588d398, CommandEndSrl);
SCR_REGISTER_SECURE(SET_SRL_TIME,0x7e887f52de52d931, CommandSetSrlTime);
SCR_REGISTER_SECURE(SET_SRL_POST_CUTSCENE_CAMERA,0xf5d67a1497505f00, CommandSetSrlPostCutsceneCamera);
SCR_REGISTER_SECURE(SET_SRL_READAHEAD_TIMES,0x125f5e3a0150ab0d, CommandSetSrlReadAheadTimes);
SCR_REGISTER_SECURE(SET_SRL_LONG_JUMP_MODE,0xa694a53a397fc676, CommandSetSrlLongJumpMode);
SCR_REGISTER_SECURE(SET_SRL_FORCE_PRESTREAM,0xa8b7321f953cff17, CommandSetSrlForcePrestream);
SCR_REGISTER_SECURE(SET_HD_AREA,0x74f17c1a1b5f2f56, CommandSetHdArea);
SCR_REGISTER_SECURE(CLEAR_HD_AREA,0x41bb0bac020b994f, CommandClearHdArea);
SCR_REGISTER_SECURE(INIT_CREATOR_BUDGET,0x3e2d4acdeb176503, CommandInitCreatorBudget);
SCR_REGISTER_SECURE(SHUTDOWN_CREATOR_BUDGET,0xdd631a688bd16327, CommandShutdownCreatorBudget);
SCR_REGISTER_UNUSED(HAS_ROOM_FOR_MODEL_IN_CREATOR_BUDGET,0x9fa7ce1e863f69fb, CommandHasRoomForModelInCreatorBudget);
SCR_REGISTER_SECURE(ADD_MODEL_TO_CREATOR_BUDGET,0x66eb6fa2c84f8e14, CommandAddModelToCreatorBudget);
SCR_REGISTER_SECURE(REMOVE_MODEL_FROM_CREATOR_BUDGET,0xac51edc6ac06cfee, CommandRemoveModelFromCreatorBudget);
SCR_REGISTER_SECURE(GET_USED_CREATOR_BUDGET,0x67b39fa5cb56f775, CommandGetUsedCreatorBudget);
SCR_REGISTER_SECURE(SET_ISLAND_ENABLED,0x17d70b6d85547996, CommandSetIslandEnabled);
SCR_REGISTER_UNUSED(ARE_ISLAND_IPLS_ACTIVE,0x24bed3d8303d66b6, CommandAreIslandIPLsActive);
#if GEN9_STANDALONE_ENABLED
SCR_REGISTER_UNUSED(IS_GAME_INSTALLED,0xa6fa11b890aaa882, CommandIsGameInstalled);
#endif
}
};