Files
gtav-src/script/dev_ng/singleplayer/scripts/main/startup_positioning.sc
T
2025-09-29 00:52:08 +02:00

815 lines
34 KiB
Python
Executable File

//Compile out Title Update changes to header functions.
//Must be before includes.
CONST_INT USE_TU_CHANGES 1
USING "player_ped_scenes.sch"
USING "player_scene_initialiser.sch"
// *****************************************************************************************
// *****************************************************************************************
// *****************************************************************************************
//
// MISSION NAME : startup_positioning.sc
// AUTHOR : Alwyn
// DESCRIPTION :
//
// *****************************************************************************************
// *****************************************************************************************
// *****************************************************************************************
SCRIPT
CPRINTLN(DEBUG_INIT_SP, "startup_positioning.sc started.")
// Graeme - this doesn't seem like a good thing to do, but I need to make the script either safe for network game
// or make it clean up when HAS_FORCE_CLEANUP_OCCURRED(FORCE_CLEANUP_FLAG_SP_TO_MP) returns TRUE.
// The second option doesn't seem like a good idea either. How are we going to deal with the player entering
// multiplayer while this script is running e.g. the player accepts an invite on the XMB/Dashboard
NETWORK_SET_SCRIPT_IS_SAFE_FOR_NETWORK_GAME()
VECTOR vStartPos
FLOAT fStartHeading
BOOL bSafehouseValid, bFadeIn, bSnapToGround
bSafehouseValid = GET_SAVE_HOUSE_DETAILS_AFTER_SUCCESSFUL_LOAD(vStartPos, fStartHeading, bFadeIn, bSnapToGround)
//Don't use eOverridePed if the load is from a quicksave
IF NOT ARE_VECTORS_EQUAL(g_savedGlobals.sRepeatPlayData.mPlayerStruct.vPos, <<0.0,0.0,0.0>>)
g_savedGlobals.sPlayerData.eOverridePed = NO_CHARACTER
ENDIF
//Check for respawning Player away from mission blips at safehouse #939375
IF (NOT bSafehouseValid
OR SHOULD_PROCESS_DESCENT_SWITCH_ON_LOAD()
OR g_savedGlobals.sPlayerData.eOverridePed <> NO_CHARACTER)
AND NOT ( IS_COMMANDLINE_END_USER_BENCHMARK() OR LANDING_SCREEN_STARTED_END_USER_BENCHMARK())
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> perform post-load switch.")
#ENDIF
enumCharacterList eCurrentPlayer = GET_CURRENT_PLAYER_PED_ENUM()
IF NOT IS_PLAYER_PED_PLAYABLE(eCurrentPlayer)
SCRIPT_ASSERT("Do_Player_Post_Load_Positioning(): Invalid SP player character. Switching to valid character as failsafe.")
CPRINTLN(DEBUG_INIT_SP, "startup_positioning.sc Invalid SP player character. Switching to valid character as failsafe.")
INT iPlayerCharIndex
BOOL bPlayerSelected = FALSE
REPEAT 3 iPlayerCharIndex
IF NOT bPlayerSelected
enumCharacterList eNewPlayer = INT_TO_ENUM(enumCharacterList, iPlayerCharIndex)
IF IS_PLAYER_PED_AVAILABLE(eNewPlayer)
CPRINTLN(DEBUG_INIT_SP, "startup_positioning.sc Selected ", GET_PLAYER_PED_STRING(eNewPlayer), " as failsafe SP starting character.")
eCurrentPlayer = eNewPlayer
bPlayerSelected = TRUE
ENDIF
ENDIF
ENDREPEAT
IF eCurrentPlayer != GET_CURRENT_PLAYER_PED_ENUM()
CPRINTLN(DEBUG_INIT_SP, "startup_positioning.sc Starting switch to character ", GET_PLAYER_PED_STRING(eCurrentPlayer),".")
SELECTOR_SLOTS_ENUM newSelectorPed = GET_SELECTOR_SLOT_FROM_PLAYER_PED_ENUM(eCurrentPlayer)
WHILE NOT SET_CURRENT_SELECTOR_PED(newSelectorPed)
WAIT(0)
ENDWHILE
CPRINTLN(DEBUG_INIT_SP, "startup_positioning.sc Finished switch to character ", GET_PLAYER_PED_STRING(eCurrentPlayer),".")
ENDIF
ENDIF
#IF IS_DEBUG_BUILD
IF NOT bSafehouseValid
SCRIPT_ASSERT("Do_Player_Post_Load_Positioning(): Invalid savehouse spawn position passed to script from code. Bug GraemeW.")
CPRINTLN(DEBUG_INIT_SP, "startup_positioning.sc Invalid savehouse spawn position passed to script from code. Bug GraemeW.")
ENDIF
#ENDIF
Initialise_Player_Scene_Global_Variables_On_SP_Startup()
// Valid SP player character so set default info
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
AND IS_PLAYER_PED_PLAYABLE(GET_CURRENT_PLAYER_PED_ENUM())
RESTORE_PLAYER_PED_WEAPONS(PLAYER_PED_ID())
RESTORE_PLAYER_PED_ARMOUR(PLAYER_PED_ID())
RESTORE_PLAYER_PED_TATTOOS(PLAYER_PED_ID())
RESTORE_PLAYER_PED_VARIATIONS(PLAYER_PED_ID())
SET_PED_CAN_LOSE_PROPS_ON_DAMAGE(PLAYER_PED_ID(), FALSE)
IF (GET_FOLLOW_PED_CAM_VIEW_MODE() = CAM_VIEW_MODE_CINEMATIC)
CPRINTLN(DEBUG_INIT_SP, "Set follow ped cam view mode - third person.")
SET_FOLLOW_PED_CAM_VIEW_MODE(CAM_VIEW_MODE_THIRD_PERSON)
ENDIF
ENDIF
PED_SCENE_STRUCT sSceneData
// Setup the scene data
sSceneData.iStage = 0
sSceneData.eScene = PR_SCENE_INVALID
sSceneData.ePed = GET_CURRENT_PLAYER_PED_ENUM() //g_sPlayerPedRequest.ePed
PED_SCENE_STRUCT sPedScene
PLAYER_TIMETABLE_SCENE_STRUCT sPassedScene
IF (g_savedGlobals.sPlayerData.eOverridePed <> NO_CHARACTER)
sSceneData.ePed = g_savedGlobals.sPlayerData.eOverridePed
CPRINTLN(DEBUG_INIT_SP, "eOverridePed is ", GET_PLAYER_PED_STRING(sSceneData.ePed), ".")
g_savedGlobals.sPlayerData.eOverridePed = NO_CHARACTER
ENDIF
g_bBlipSystemStartupLeash = FALSE //unleash the blip system
INT iBlipTimeout = GET_GAME_TIMER() + 5000
WHILE (g_bBlipSystemRefreshDetector
OR (GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(HASH("blip_controller")) < 1))
AND iBlipTimeout > GET_GAME_TIMER()
//IF (GET_GAME_TIMER() % 250) = 0
CDEBUG3LN(DEBUG_INIT_SP, "startup_positioning waiting for blips and controller type 1 [iBlipTimeout: ", iBlipTimeout-GET_GAME_TIMER(), "]")
//ENDIF
WAIT(0)
ENDWHILE
FLOAT fScenePercent
#IF IS_DEBUG_BUILD
IF GET_COMMANDLINE_PARAM_EXISTS("sc_ForceNamedSwitch")
GET_PLAYER_PED_SCENE_FOR_CURRENT_TIME(sSceneData.ePed, sSceneData.eScene, fScenePercent, sPedScene, sPassedScene, TRUE)
ELSE
#ENDIF
SWITCH sSceneData.ePed
CASE CHAR_MICHAEL
GetMichaelSceneForCurrentTime(sSceneData.eScene, fScenePercent, sPedScene, sPassedScene, TRUE)
BREAK
CASE CHAR_FRANKLIN
GetFranklinSceneForCurrentTime(sSceneData.eScene, fScenePercent, sPedScene, sPassedScene, TRUE)
BREAK
CASE CHAR_TREVOR
GetTrevorSceneForCurrentTime(sSceneData.eScene, fScenePercent, sPedScene, sPassedScene, TRUE)
BREAK
ENDSWITCH
#IF IS_DEBUG_BUILD
ENDIF
#ENDIF
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> GET_PLAYER_PED_SCENE_FOR_CURRENT_TIME[\"", Get_String_From_Ped_Request_Scene_Enum(sSceneData.eScene), "\"] fScenePercent:", fScenePercent, "%", " - perform post-load switch (url:bugstar:939375)")
#ENDIF
IF NOT IS_ENTITY_DEAD(PLAYER_PED_ID())
VECTOR vCreateCoords
FLOAT fCreateHead
TEXT_LABEL_31 tRoom
IF GET_PLAYER_PED_POSITION_FOR_SCENE(sSceneData.eScene, vCreateCoords, fCreateHead, tRoom)
VECTOR vRespawnDescentCoords
vRespawnDescentCoords = GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(vCreateCoords, fCreateHead, <<0,0,5>>)
SET_ENTITY_COORDS(PLAYER_PED_ID(), vRespawnDescentCoords)
SET_ENTITY_SHOULD_FREEZE_WAITING_ON_COLLISION(PLAYER_PED_ID(), TRUE)
FREEZE_ENTITY_POSITION(PLAYER_PED_ID(), TRUE)
// load the stream vol
NEW_LOAD_SCENE_START_SPHERE(vCreateCoords, 2000, NEWLOADSCENE_FLAG_REQUIRE_COLLISION)
INT iNewLoadSceneTimer = 0
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> Wait for new load scene.")
WHILE NOT IS_NEW_LOAD_SCENE_LOADED()
AND (iNewLoadSceneTimer < 15000)
WAIT(0)
iNewLoadSceneTimer += ROUND(GET_FRAME_TIME()*1000)
ENDWHILE
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> New load scene loaded [", GET_GAME_TIMER() - iNewLoadSceneTimer, "ms].")
// get rid of the new load scene
NEW_LOAD_SCENE_STOP()
ENDIF
ENDIF
//If the player hasn't already chosen to boot into MP check one last time before
//allowing SP to start.
RUN_SECOND_MULTIPLAYER_ON_STARTUP_CHECK()
IF g_bRunMultiplayerOnStartup
CPRINTLN(DEBUG_INIT_SP, "<LOAD-CHOICE> Clearing any startup positioning SP skycams in preparation for late MP switch.")
#IF USE_FINAL_PRINTS
PRINTLN_FINAL("<2140379> <LOAD-CHOICE> Clearing any startup positioning SP skycams in preparation for late MP switch.")
#ENDIF
STOP_PLAYER_SWITCH()
NET_NL()NET_PRINT("<LOAD-CHOICE> STOP_PLAYER_SWITCH() near top of startup_positioning ")
SET_SKYSWOOP_STAGE(SKYSWOOP_NONE)
TAKE_CONTROL_OF_TRANSITION(FALSE)
SET_SELECTOR_CAM_ACTIVE(FALSE)
ELSE
BOOL bHaveShutdownLoadingScreen = FALSE
WHILE NOT PROCESS_PLAYER_PED_SCENE(sSceneData, ENUM_TO_INT(SWITCH_FLAG_DESCENT_ONLY))
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> PROCESS_PLAYER_PED_SCENE[\"", Get_String_From_Ped_Request_Scene_Enum(sSceneData.eScene), "\"] stage: ", sPedScene.iStage)
#ENDIF
IF NOT bHaveShutdownLoadingScreen
IF sPedScene.iStage > 0
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> call SHUTDOWN_LOADING_SCREEN - sPedScene.iStage > 0")
SHUTDOWN_LOADING_SCREEN()
bHaveShutdownLoadingScreen = TRUE
ENDIF
ENDIF
IF NOT bHaveShutdownLoadingScreen
IF IS_SCREEN_FADING_IN() OR IS_SCREEN_FADED_IN()
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> call SHUTDOWN_LOADING_SCREEN - fading or faded in")
SHUTDOWN_LOADING_SCREEN()
bHaveShutdownLoadingScreen = TRUE
ENDIF
ENDIF
WAIT(0)
ENDWHILE
IF NOT bHaveShutdownLoadingScreen
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> call SHUTDOWN_LOADING_SCREEN - fallthrough [\"", Get_String_From_Ped_Request_Scene_Enum(sSceneData.eScene), "\"]!?!")
DO_SCREEN_FADE_IN(DEFAULT_FADE_TIME)
SHUTDOWN_LOADING_SCREEN()
bHaveShutdownLoadingScreen = TRUE
ENDIF
ENDIF
ELIF IS_COMMANDLINE_END_USER_BENCHMARK() OR LANDING_SCREEN_STARTED_END_USER_BENCHMARK()
CPRINTLN(DEBUG_INIT, "Loading into level GTA5. Skipping startup positioning due to benchmark commandline.")
SHUTDOWN_LOADING_SCREEN()
ELSE
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> ignore post-load switch.")
INT iDebugFrameCount = 0
#ENDIF
IF g_savedGlobals.sFlowCustom.wasFadedOut AND ARE_VECTORS_EQUAL(g_savedGlobals.sRepeatPlayData.mPlayerStruct.vPos, <<0.0,0.0,0.0>>)
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> wasFadedOut is true and vPos is zero.") //1325321
ELSE
CONST_FLOAT fClear_Area_Radius 15.0 //5.0
VEHICLE_INDEX mPlayerVehicle
VECTOR vVehicleVelocity
INT iWantedLevel
PED_PARACHUTE_STATE eParachuteState = PPS_INVALID
BOOL bCPRINTLNCalled = FALSE
// suppress cougars, so player doesn't get killed by one straight away
SET_SCENARIO_TYPE_ENABLED("WORLD_MOUNTAIN_LION_WANDER", FALSE)
IF NOT g_savedGlobals.sFlowCustom.wasFadedOut
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> wasFadedOut is false.")
bCPRINTLNCalled = TRUE
ENDIF
IF NOT ARE_VECTORS_EQUAL(g_savedGlobals.sRepeatPlayData.mPlayerStruct.vPos, <<0.0,0.0,0.0>>)
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> vPos is non-zero ", g_savedGlobals.sRepeatPlayData.mPlayerStruct.vPos)
bCPRINTLNCalled = TRUE
ENDIF
IF NOT bCPRINTLNCalled
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> bCPRINTLNCalled is false???")
ENDIF
// if we're going to restore player's vehicle, start loading it now
IF NOT ARE_VECTORS_EQUAL(g_savedGlobals.sRepeatPlayData.mPlayerStruct.vPos, <<0.0,0.0,0.0>>)
IF IsSnapshotVehicleAvailable(g_savedGlobals.sRepeatPlayData.mVehicleStruct)
RequestSnapshotVehicleModel(g_savedGlobals.sRepeatPlayData.mVehicleStruct)
ENDIF
ENDIF
BOOL bWarpedIntoVehGen = FALSE
// move the player and the camera
IF DOES_ENTITY_EXIST(PLAYER_PED_ID())
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
CLEAR_AREA(vStartPos, fClear_Area_Radius, TRUE)
VECTOR vTestCreateCoords
FLOAT fTestCreateHead
enumBlockedPedCoordZone eTestCreateZone
IF Is_Ped_Last_Known_Coords_In_Blocked_Zone(vStartPos, vTestCreateCoords, fTestCreateHead, eTestCreateZone)
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> vStartPos ", vStartPos, " inside invalid zone \"", eTestCreateZone, "\", move to ", vTestCreateCoords, ", dist: ", VDIST(vStartPos, vTestCreateCoords), "m")
vStartPos = vTestCreateCoords
fStartHeading = fTestCreateHead
ENDIF
// Before we do this - move them nearby so we can spawn all the vehicle gens in
// Once we do this, warp the player into the nearest vehicle gen if player is in the bounds.
SET_ENTITY_COORDS_NO_OFFSET(PLAYER_PED_ID(), vStartPos+<<0.0, 0.0, 5.0>>)
FREEZE_ENTITY_POSITION(PLAYER_PED_ID(), TRUE)
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> Starting to wait for nearby vehicle gens to load in...")
#IF IS_DEBUG_BUILD
iDebugFrameCount = 0
#ENDIF
RESET_VEHICLE_GEN_LOADED_CHECKS()
WHILE NOT HAVE_ALL_VEHICLE_GENS_LOADED_NEAR_PLAYER()
CDEBUG1LN(DEBUG_INIT_SP, "<startup_positioning> waiting for nearby vehicle gens to load in...")
#IF IS_DEBUG_BUILD
iDebugFrameCount++
#ENDIF
WAIT(0)
ENDWHILE
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> Finished waiting for nearby vehicle gens to load. It took ", iDebugFrameCount, " frames.")
#ENDIF
// If there is a vehicle gen at this spot, warp the player inside.
INT iVehGen
#IF IS_DEBUG_BUILD
FLOAT fSmallestDist2 = 9999999.0
INT iClosestVehGen = NUMBER_OF_VEHICLES_TO_GEN
#ENDIF
REPEAT NUMBER_OF_VEHICLES_TO_GEN iVehGen
IF DOES_ENTITY_EXIST(g_sVehicleGenNSData.vehicleID[iVehGen])
AND (NOT IS_ENTITY_DEAD(g_sVehicleGenNSData.vehicleID[iVehGen]))
AND IS_VEHICLE_DRIVEABLE(g_sVehicleGenNSData.vehicleID[iVehGen])
IF DOES_ENTITY_EXIST(PLAYER_PED_ID())
AND NOT IS_PED_INJURED(PLAYER_PED_ID())
FLOAT fDist2 = VDIST2(vStartPos, GET_ENTITY_COORDS(g_sVehicleGenNSData.vehicleID[iVehGen]))
FLOAT fMAX_DIST_FROM_VEH_GEN = 2.5 //magnitude of vector <<1.5,1.5,1.5>>
IF GET_ENTITY_MODEL(g_sVehicleGenNSData.vehicleID[iVehGen]) = MILJET
fMAX_DIST_FROM_VEH_GEN = 10.0
ENDIF
IF fDist2 < (fMAX_DIST_FROM_VEH_GEN*fMAX_DIST_FROM_VEH_GEN)
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> warping player into vehicle gen ", iVehGen, ", dist ", SQRT(fDist2), "m, model: ", GET_MODEL_NAME_OF_VEHICLE_FOR_DEBUG_ONLY(g_sVehicleGenNSData.vehicleID[iVehGen]))
FREEZE_ENTITY_POSITION(PLAYER_PED_ID(), FALSE)
SET_PED_INTO_VEHICLE(PLAYER_PED_ID(), g_sVehicleGenNSData.vehicleID[iVehGen])
bWarpedIntoVehGen = TRUE
iVehGen = NUMBER_OF_VEHICLES_TO_GEN+1// Bail
ENDIF
#IF IS_DEBUG_BUILD
IF fDist2 < fSmallestDist2
iClosestVehGen = iVehGen
fSmallestDist2 = fDist2
ENDIF
#ENDIF
ENDIF
ENDIF
ENDREPEAT
IF NOT bWarpedIntoVehGen
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> iClosestVehGen ", iClosestVehGen, ", fSmallestDist ", SQRT(fSmallestDist2), "m)")
ENDIF
IF DOES_ENTITY_EXIST(PLAYER_PED_ID())
AND NOT IS_PED_INJURED(PLAYER_PED_ID())
IF NOT bWarpedIntoVehGen
SET_ENTITY_COORDS_NO_OFFSET(PLAYER_PED_ID(), vStartPos)
SET_ENTITY_HEADING(PLAYER_PED_ID(), fStartHeading)
ENDIF
FREEZE_ENTITY_POSITION(PLAYER_PED_ID(), FALSE)
SET_GAMEPLAY_CAM_RELATIVE_PITCH(0.0)
SET_GAMEPLAY_CAM_RELATIVE_HEADING(0.0)
RESET_PED_AUDIO_FLAGS(PLAYER_PED_ID())
ENDIF
ResetLastKnownPedInfo(g_savedGlobals.sPlayerData.sInfo, SP_MISSION_NONE)
ENDIF
ENDIF
// If we saved in trigger area of an RC that was waiting for player to leave area
// we need to restore that flag now so it doesnt try to immediately launch
// (needs to be done before waiting for world to stream)
IF g_savedGlobals.sRepeatPlayData.eRCMissionToBlock <> NO_RC_MISSION
g_RandomChars[g_savedGlobals.sRepeatPlayData.eRCMissionToBlock].rcLeaveAreaCheck = TRUE
CPRINTLN(DEBUG_INIT_SP, "Loaded in near an RC mission that should wait for player to leave area. Restoring details: ", GET_RC_MISSION_DISPLAY_STRING_FROM_ID(g_savedGlobals.sRepeatPlayData.eRCMissionToBlock))
ENDIF
// wait a frame for the camera to catch up before pausing
WAIT(0)
//Removed as the maintransition will hold now for this script to finish.
// IF IS_PLAYSTATION_PLATFORM() AND NETWORK_HAVE_PLATFORM_SUBSCRIPTION() = FALSE
// AND IS_PLAYER_SWITCH_IN_PROGRESS()
// CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> IF IS_PLAYSTATION_PLATFORM() AND NETWORK_HAVE_PLATFORM_SUBSCRIPTION() = FALSE AND IS_PLAYER_SWITCH_IN_PROGRESS")
// KILL_PLAYER_SWITCH_NOW()
// CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> KILL_PLAYER_SWITCH_NOW")
// WAIT(0)
// ENDIF
SET_GAME_PAUSED(TRUE)
// load the stream vol
NEW_LOAD_SCENE_START_SPHERE(vStartPos, 2000, NEWLOADSCENE_FLAG_REQUIRE_COLLISION)
INT iNewLoadSceneTimer = 0
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> Starting to wait for new load scene...")
WHILE NOT IS_NEW_LOAD_SCENE_LOADED()
AND (iNewLoadSceneTimer < 15000)
WAIT(0)
iNewLoadSceneTimer += ROUND(GET_FRAME_TIME()*1000)
ENDWHILE
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> New load scene loaded. It took ", GET_GAME_TIMER() - iNewLoadSceneTimer, " ms.")
// ground the player (needs to be done after world has loaded in)
CLEAR_AREA(vStartPos, fClear_Area_Radius, TRUE)
SET_GAME_PAUSED(FALSE)
WAIT(10) //allow objects to load before attempting to restore player vehicle from snapshot (shape tests)
//B*-2300539
//If in interior (bugged for tunnels) wait for ped to settle / tunnel to load
INTERIOR_INSTANCE_INDEX tunnelInterior = GET_INTERIOR_AT_COORDS(vStartPos)
IF tunnelInterior != NULL
AND IS_VALID_INTERIOR(tunnelInterior)
and DOES_ENTITY_EXIST(PLAYER_PED_ID())
AND NOT IS_PED_INJURED(PLAYER_PED_ID())
FLOAT groundZ = 0.0
vector playerPosition = GET_PED_BONE_COORDS(player_ped_id(),BONETAG_L_TOE,<<0,0,0>>)
bool getGround = GET_GROUND_Z_FOR_3D_COORD(playerPosition,groundZ)
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> playerPosition...", playerPosition)
WHILE((NOT IS_PED_INJURED(PLAYER_PED_ID()) AND IS_PED_FALLING(PLAYER_PED_ID()) OR (NOT ARE_VECTORS_ALMOST_EQUAL(<<0,0,playerPosition.Z>>,<<0,0,groundZ>>))) AND getGround AND GET_GAME_TIMER() < iNewLoadSceneTimer + 15000)
playerPosition = GET_PED_BONE_COORDS(player_ped_id(),BONETAG_L_TOE,<<0,0,0>>)
getGround = GET_GROUND_Z_FOR_3D_COORD(playerPosition,groundZ)
WAIT(0)
ENDWHILE
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> playerPosition...", playerPosition)
ENDIF
// Was the player standing in a mission lead-in when they saved? If so grab a reference to the mission
// to use later.
SP_MISSIONS eLeadInToCreate = SP_MISSION_NONE
IF g_savedGlobals.sRepeatPlayData.eMission != SP_MISSION_NONE
//Adding check if the player is a char that cant trigger the lead in skip and dont request.
INT iTriggerIndexToCreate = ENUM_TO_INT(g_savedGlobals.sRepeatPlayData.eMission)
IF Is_Mission_Triggerable_By_Character(g_sMissionStaticData[iTriggerIndexToCreate].triggerCharBitset,GET_CURRENT_PLAYER_PED_ENUM())
eLeadInToCreate = g_savedGlobals.sRepeatPlayData.eMission //Store this value to use after the struct reset.
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> The player saved in a mission lead-in area for mission ", GET_SP_MISSION_DISPLAY_STRING_FROM_ID(eLeadInToCreate), ".")
ELSE
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> The player is in leadin area but is not able to trigger. Do not request assests.")
ENDIF
ENDIF
//Run last minute shape test for collision B*-2217238
IF NOT bWarpedIntoVehGen
AND eLeadInToCreate = SP_MISSION_NONE
IF NOT START_UP_SHAPETEST(vStartPos,fStartHeading)
CPRINTLN(DEBUG_INIT_SP,"<startup_positioning> SHAPE_TEST: FAIL at ",vStartPos)
IF START_UP_ROAD_NODE_TEST(vStartPos, fStartHeading)
CPRINTLN(DEBUG_INIT_SP,"<startup_positioning> ROAD_NODE_TEST: PASS at ",vStartPos)
//B* 2290998: The chosen road node is below Floyd's appartment, keep player close to the ground
IF VDIST2(vStartPos,<< -1155.25, -1519.25, 3.34375 >>) < 1
vStartPos += <<0,0,1>>
ELSE
vStartPos += <<0,0,5.0>> //Add Z offset, keeps player from spawning inside props
ENDIF
SET_ENTITY_COORDS_NO_OFFSET(PLAYER_PED_ID(), vStartPos)
SET_ENTITY_HEADING(PLAYER_PED_ID(), fStartHeading)
SET_GAMEPLAY_CAM_RELATIVE_PITCH(0.0)
SET_GAMEPLAY_CAM_RELATIVE_HEADING(0.0)
WAIT(1000)
ELSE
CPRINTLN(DEBUG_INIT_SP,"<startup_positioning> ROAD_NODE_TEST: FAIL")
ENDIF
ELSE
CPRINTLN(DEBUG_INIT_SP,"<startup_positioning> SHAPE_TEST: PASS")
ENDIF
ENDIF
// get rid of the new load scene
NEW_LOAD_SCENE_STOP()
SET_GAME_PAUSED(TRUE)
// Valid SP player character so set default info
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
AND IS_PLAYER_PED_PLAYABLE(GET_CURRENT_PLAYER_PED_ENUM())
RESTORE_PLAYER_PED_WEAPONS(PLAYER_PED_ID(),DEFAULT,TRUE)
RESTORE_PLAYER_PED_ARMOUR(PLAYER_PED_ID())
RESTORE_PLAYER_PED_TATTOOS(PLAYER_PED_ID())
RESTORE_PLAYER_PED_VARIATIONS(PLAYER_PED_ID())
SET_PED_CAN_LOSE_PROPS_ON_DAMAGE(PLAYER_PED_ID(), FALSE)
g_bPlayerSetupByQuickSave = TRUE // stop player controller doing this again
ENDIF
// If we're restoring a quick save or repeat play save (the start snapshot won't be empty)
// We need to respawn the player where they were when they saved the game
IF NOT ARE_VECTORS_EQUAL(g_savedGlobals.sRepeatPlayData.mPlayerStruct.vPos, <<0.0,0.0,0.0>>)
BOOL bSkipVehicleCreation = FALSE
IF bWarpedIntoVehGen
AND IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
VEHICLE_INDEX tempVeh = GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID())
IF DOES_ENTITY_EXIST(tempVeh)
AND IS_VEHICLE_DRIVEABLE(tempVeh)
AND GET_ENTITY_MODEL(tempVeh) = g_savedGlobals.sRepeatPlayData.mVehicleStruct.mVehicle.eModel
bSkipVehicleCreation = TRUE
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> Skipping snapshot vehicle creation as player was warped into the vehicle gen version.")
IF g_savedGlobals.sRepeatPlayData.mVehicleStruct.bTrackedForImpound
AND g_savedGlobals.sVehicleGenData.bTrackingImpoundVehicle
g_vCarToTrackForImpound = tempVeh
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> Startup vehicle \"", GET_MODEL_NAME_OF_VEHICLE_FOR_DEBUG_ONLY(tempVeh), "\" was being tracked for impound do update vehicle gen flag [bWarpedIntoVehGen]")
ENDIF
ENDIF
ENDIF
IF NOT bSkipVehicleCreation
IF (g_savedGlobals.sRepeatPlayData.mVehicleStruct.mVehicle.eModel = JET)
INT iPlayerHashKey = GET_ROOM_KEY_FROM_ENTITY(PLAYER_PED_ID())
IF ((iPlayerHashKey = 0 OR iPlayerHashKey = HASH("")) AND IS_POINT_IN_ANGLED_AREA(g_savedGlobals.sRepeatPlayData.mVehicleStruct.vVehiclePos, <<-1690.650391,-3130.950928,12.958889>>, <<-1625.340332,-3169.572754,29.694946>>, 75.000000))
bSkipVehicleCreation = TRUE
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> Skipping snapshot vehicle creation it is inside the hanger.")
ELSE
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> Allowing snapshot vehicle creation as iPlayerHashKey: \"", iPlayerHashKey, "\" and vVehiclePos: ", g_savedGlobals.sRepeatPlayData.mVehicleStruct.vVehiclePos, ".")
ENDIF
ENDIF
ENDIF
IF NOT bSkipVehicleCreation
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> Trying to recreate player's snapshot vehicle for quick save / repeat play save.")
IF RestoreSnapshotVehicle(g_savedGlobals.sRepeatPlayData.mVehicleStruct, mPlayerVehicle, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE)
IF DOES_ENTITY_EXIST(mPlayerVehicle)
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> Freezing vehicle \"", GET_MODEL_NAME_OF_VEHICLE_FOR_DEBUG_ONLY(mPlayerVehicle), "\" now")
FREEZE_ENTITY_POSITION(mPlayerVehicle, TRUE)
vVehicleVelocity = g_savedGlobals.sRepeatPlayData.mVehicleStruct.vVehicleVelocity
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> vVehicleVelocity ", vVehicleVelocity)
IF g_savedGlobals.sRepeatPlayData.mVehicleStruct.bTrackedForImpound
AND g_savedGlobals.sVehicleGenData.bTrackingImpoundVehicle
g_vCarToTrackForImpound = mPlayerVehicle
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> Startup vehicle \"", GET_MODEL_NAME_OF_VEHICLE_FOR_DEBUG_ONLY(mPlayerVehicle), "\" was being tracked for impound do update vehicle gen flag [NOT bSkipVehicleCreation]")
ENDIF
ENDIF
ENDIF
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_INIT_SP, "Finished trying to recreate player's snapshot vehicle.")
IF DOES_ENTITY_EXIST(mPlayerVehicle)
VECTOR vVehPos = GET_ENTITY_COORDS(mPlayerVehicle)
CPRINTLN(DEBUG_INIT_SP, "Vehicle position was ", vVehPos, ".")
ENDIF
#ENDIF
ENDIF
// also freeze the player (mainly for cases where he is in the air)
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
IF NOT IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> Freezing player now")
FREEZE_ENTITY_POSITION(PLAYER_PED_ID(), TRUE)
// restore parachute task if needed
eParachuteState = g_savedGlobals.sRepeatPlayData.mPlayerStruct.eParachuteState
IF eParachuteState = PPS_SKYDIVING
OR eParachuteState = PPS_PARACHUTING
OR eParachuteState = PPS_DEPLOYING
WAIT(0) // need to wait as we've removed parachute in RESTORE_PLAYER_PED_VARIATIONS
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
TASK_PARACHUTE(PLAYER_PED_ID(), TRUE)
ENDIF
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> Restoring parachute state: ", g_savedGlobals.sRepeatPlayData.mPlayerStruct.eParachuteState)
ENDIF
ENDIF
ENDIF
iWantedLevel = g_savedGlobals.sRepeatPlayData.mPlayerStruct.iWantedLevel
// clear the repeat play snapshot so it doesn't affect any future saves
Reset_RepeatPlay_Snapshot()
ENDIF
IF (GET_FOLLOW_PED_CAM_VIEW_MODE() = CAM_VIEW_MODE_CINEMATIC)
CPRINTLN(DEBUG_INIT_SP, "Set follow ped cam view mode - third person.")
SET_FOLLOW_PED_CAM_VIEW_MODE(CAM_VIEW_MODE_THIRD_PERSON)
ENDIF
SET_GAMEPLAY_CAM_RELATIVE_PITCH(0.0)
SET_GAMEPLAY_CAM_RELATIVE_HEADING(0.0)
//unpause when all is done
SET_GAME_PAUSED(FALSE)
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> Starting to wait for ped and veh population to fill...")
#IF IS_DEBUG_BUILD
iDebugFrameCount = 0
#ENDIF
INSTANTLY_FILL_PED_POPULATION()
INSTANTLY_FILL_VEHICLE_POPULATION()
POPULATE_NOW()
INT iPopTimeout = GET_GAME_TIMER() + 1500
WHILE NOT HAS_INSTANT_FILL_VEHICLE_POPULATION_FINISHED()
AND iPopTimeout > GET_GAME_TIMER()
#IF IS_DEBUG_BUILD
iDebugFrameCount++
#ENDIF
WAIT(0)
ENDWHILE
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> Finished waiting for ped and veh population to fill. It took ", iDebugFrameCount, " frames.")
#ENDIF
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> Doing small 3.5m clear area around player as a safeguard.")
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
CLEAR_AREA(GET_ENTITY_COORDS(PLAYER_PED_ID()), 3.5, TRUE)
ENDIF
// force parachute open if needed
IF eParachuteState = PPS_PARACHUTING
OR eParachuteState = PPS_DEPLOYING
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
FORCE_PED_TO_OPEN_PARACHUTE(PLAYER_PED_ID())
ENDIF
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> Forcing parachute open for state: ", eParachuteState)
ENDIF
Set_Leave_Area_Flag_For_All_Blipped_Missions()
//Wait for any lead-in scene to finish loading assets and allow it to create.
IF eLeadInToCreate != SP_MISSION_NONE
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> waiting for SP scripts to intialise before preloading mission lead-in.")
WHILE NOT g_isSPMainInitialised
WAIT(0)
ENDWHILE
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> SP scripts intialised.")
MISSION_FLOW_PRELOAD_ASSETS_FOR_MISSION_TRIGGER(eLeadInToCreate)
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> Starting to wait for mission trigger to pick up preload request.")
WHILE g_eMissionSceneToPreLoad != SP_MISSION_NONE
WAIT(0)
ENDWHILE
WAIT(0)
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> Finished waiting for mission trigger to pick up preload request.")
CPRINTLN(DEBUG_INIT_SP, "Starting to wait for lead-in to finish loading assets.")
WHILE g_bMissionTriggerLoading
WAIT(0)
ENDWHILE
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> Lead-in scene loaded. Unflagging leave area flag so the scene creates.")
g_bBlipSystemStartupLeash = FALSE //unleash the blip system
INT iBlipTimeout = GET_GAME_TIMER() + 5000
WHILE (g_bBlipSystemRefreshDetector
OR (GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(HASH("blip_controller")) < 1))
AND iBlipTimeout > GET_GAME_TIMER()
//IF (GET_GAME_TIMER() % 50) = 0
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> waiting for blips and controller type (create leadin ", eLeadInToCreate, ")")
//ENDIF
WAIT(0)
ENDWHILE
Set_Leave_Area_Flag_For_Mission(eLeadInToCreate, FALSE)
ELSE
g_bBlipSystemStartupLeash = FALSE //unleash the blip system
INT iBlipTimeout = GET_GAME_TIMER() + 5000
WHILE (g_bBlipSystemRefreshDetector
OR (GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(HASH("blip_controller")) < 1))
AND iBlipTimeout > GET_GAME_TIMER()
//IF (GET_GAME_TIMER() % 50) = 0
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> waiting for blips and controller type (no leadin to create)")
//ENDIF
WAIT(0)
ENDWHILE
ENDIF
// if player in stripclub, wait for it to setup
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
IF IS_ENTITY_IN_STRIPCLUB(PLAYER_PED_ID())
INT iEarlyOut = GET_GAME_TIMER() + 5000
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> Player loaded in strip club, wait for it to load.")
WHILE NOT IS_BITMASK_AS_ENUM_SET(g_StripclubGlobals.iStripclubFlags, GSF_IN_CLUB)
AND GET_GAME_TIMER() < iEarlyOut
WAIT(0)
ENDWHILE
IF GET_GAME_TIMER() < iEarlyOut
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> Stripclub set up complete.")
ELSE
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> Stripclub set up took too long, early out.")
ENDIF
ELSE
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> Player not loaded in stripclub.")
ENDIF
ENDIF
// restore the player's wanted level
IF iWantedLevel > 0
IF IS_PLAYER_PLAYING(PLAYER_ID())
SET_PLAYER_WANTED_LEVEL(PLAYER_ID(), iWantedLevel)
SET_PLAYER_WANTED_LEVEL_NOW(PLAYER_ID())
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> Restored wanted level as ", iWantedLevel)
ENDIF
ENDIF
// If we froze the player's vehicles position, unfreeze now
IF DOES_ENTITY_EXIST(mPlayerVehicle)
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> Unfreezing vehicle + setting velocity now")
FREEZE_ENTITY_POSITION(mPlayerVehicle, FALSE)
IF IS_VEHICLE_DRIVEABLE(mPlayerVehicle)
SET_ENTITY_VELOCITY(mPlayerVehicle, vVehicleVelocity)
ENDIF
//B* 2059523: If this is a boat, activate physics on it just to be safe
IF IS_THIS_MODEL_A_BOAT(GET_ENTITY_MODEL(mPlayerVehicle))
OR IS_THIS_MODEL_A_JETSKI(GET_ENTITY_MODEL(mPlayerVehicle))
ACTIVATE_PHYSICS(mPlayerVehicle)
ENDIF
SET_VEHICLE_AS_NO_LONGER_NEEDED(mPlayerVehicle)
ENDIF
// unfreeze player too
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
IF NOT IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
CPRINTLN(DEBUG_INIT_SP, "<startup_positioning> Unfreezing player now")
FREEZE_ENTITY_POSITION(PLAYER_PED_ID(), FALSE)
ENDIF
ENDIF
//If we've preloaded a lead-in give it 1 second to create before fading in.
//Hides ped variations popping in.
IF eLeadInToCreate != SP_MISSION_NONE
WAIT(1000)
ENDIF
//If the player hasn't already chosen to boot into MP check one last time before
//allowing SP to start.
RUN_SECOND_MULTIPLAYER_ON_STARTUP_CHECK()
IF g_bRunMultiplayerOnStartup
CPRINTLN(DEBUG_INIT_SP, "<LOAD-CHOICE> Clearing any startup positioning SP skycams in preparation for late MP switch.")
#IF USE_FINAL_PRINTS
PRINTLN_FINAL("<2140379> <LOAD-CHOICE> Clearing any startup positioning SP skycams in preparation for late MP switch.")
#ENDIF
STOP_PLAYER_SWITCH()
NET_NL()NET_PRINT("<LOAD-CHOICE> STOP_PLAYER_SWITCH() further down startup positioning ")
#IF USE_FINAL_PRINTS
PRINTLN_FINAL("<2140379> <LOAD-CHOICE> STOP_PLAYER_SWITCH() further down startup positioning ")
#ENDIF
SET_SKYSWOOP_STAGE(SKYSWOOP_NONE)
TAKE_CONTROL_OF_TRANSITION(FALSE)
SET_SELECTOR_CAM_ACTIVE(FALSE)
ELSE
SHUTDOWN_LOADING_SCREEN()
//Fade the screen in
IF IS_SCREEN_FADED_OUT()
OR IS_SCREEN_FADING_OUT()
IF NOT IS_SCREEN_FADING_IN()
DO_SCREEN_FADE_IN(DEFAULT_FADE_TIME_LONG)
ENDIF
ENDIF
// un-suppress cougars,
SET_SCENARIO_TYPE_ENABLED("WORLD_MOUNTAIN_LION_WANDER", TRUE)
ENDIF
ENDIF
ENDIF
g_savedGlobals.sPlayerData.eOverridePed = NO_CHARACTER
IF NOT IS_CHARACTER_MODEL_CHECK_DONE()
IF IS_TRANSITION_ACTIVE()
CPRINTLN(DEBUG_INIT_SP, "A multiplayer transition started while startup positioning was in progress.")
CPRINTLN(DEBUG_INIT_SP, "Cancelling SP model check.")
#IF USE_FINAL_PRINTS
PRINTLN_FINAL("<2140379> A multiplayer transition started while startup positioning was in progress.")
PRINTLN_FINAL("<2140379> Cancelling SP model check.")
#ENDIF
SET_CHARACTER_MODEL_CHECK_DONE(TRUE)
ENDIF
ENDIF
CPRINTLN(DEBUG_INIT_SP, "startup_positioning.sc ended.\n")
TERMINATE_THIS_THREAD()
ENDSCRIPT