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

6510 lines
245 KiB
Scheme
Executable File

//////////////////////////////////////////////////////////////////////////////////////////
// //
// MISSION NAME : selector_public.sch //
// AUTHOR : Kenneth Ross //
// DESCRIPTION : Functionality for character swapping. //
// See selector.sc for example use. //
// //
//////////////////////////////////////////////////////////////////////////////////////////
USING "rage_builtins.sch"
USING "globals.sch"
USING "commands_player.sch"
USING "commands_streaming.sch"
USING "commands_camera.sch"
USING "script_player.sch"
USING "commands_graphics.sch"
USING "commands_pad.sch"
USING "commands_ped.sch"
USING "commands_interiors.sch"
USING "commands_stats.sch"
USING "script_MATHS.sch"
USING "player_ped_public.sch"
USING "cellphone_public.sch"
USING "net_comms_public.sch"
USING "mission_control_public.sch"
USING "comms_control_public.sch"
USING "flow_public_core.sch"
USING "drunk_public.sch"
USING "menu_public.sch"
USING "shop_public.sch"
USING "stats_private.sch"
USING "net_spectator_cam_common.sch"
USING "net_spectator_variables.sch"
USING "respawn_location_private.sch"
USING "Transition_Controller.sch"
/// PURPOSE: Returns TRUE if a camera from the RUN_CAM_SPLINE_x procs is currently active
FUNC BOOL IS_SELECTOR_CAM_ACTIVE()
RETURN g_bSelectorCamActive
ENDFUNC
/// PURPOSE: Sets if a switch cam is active or not. This gets called automatically within the RUN_CAM_SPLINE_x procs.
PROC SET_SELECTOR_CAM_ACTIVE(BOOL bIsActive)
#IF IS_DEBUG_BUILD
DEBUG_PRINTCALLSTACK()
#ENDIF
PRINTLN("SET_SELECTOR_CAM_ACTIVE(", bIsActive, ") called by ", GET_THIS_SCRIPT_NAME())
g_bSelectorCamActive = bIsActive
ENDPROC
/// PURPOSE: Returns if a script is wanting the transition to happen
FUNC BOOL IS_TRANSITION_MENU_TRIGGERED()
RETURN g_bBringUpMPHud
ENDFUNC
/// PURPOSE: Sets if a switch cam is active or not. This gets called automatically within the RUN_CAM_SPLINE_x procs.
PROC TRIGGER_TRANSITION_MENU_ACTIVE(BOOL bIsActive)
#IF IS_DEBUG_BUILD
IF bIsActive
DEBUG_PRINTCALLSTACK()
NET_NL()NET_PRINT(" << TRIGGER_TRANSITION_MENU_ACTIVE - TRUE >> ")
ELSE
DEBUG_PRINTCALLSTACK()
NET_NL()NET_PRINT(" << TRIGGER_TRANSITION_MENU_ACTIVE - FALSE >> ")
ENDIF
#ENDIF
g_bBringUpMPHud = bIsActive
ENDPROC
/// PURPOSE: Returns if a script is wanting the transition to happen
FUNC BOOL IS_CREATOR_MENU_TRIGGERED()
RETURN g_bBringUpMainCreator
ENDFUNC
/// PURPOSE: Sets if a switch cam is active or not. This gets called automatically within the RUN_CAM_SPLINE_x procs.
PROC TRIGGER_CREATOR_MENU_ACTIVE(BOOL bIsActive)
#IF IS_DEBUG_BUILD
IF bIsActive
DEBUG_PRINTCALLSTACK()
NET_NL()NET_PRINT(" << TRIGGER_CREATOR_MENU_ACTIVE - TRUE >> ")
ELSE
DEBUG_PRINTCALLSTACK()
NET_NL()NET_PRINT(" << TRIGGER_CREATOR_MENU_ACTIVE - FALSE >> ")
ENDIF
#ENDIF
g_bBringUpMainCreator = bIsActive
ENDPROC
/// PURPOSE: Sets if a switch cam is active or not. This gets called automatically within the RUN_CAM_SPLINE_x procs.
PROC TELL_TRANSITION_BAIL_HAPPENED(BOOL bBailHappened)
#IF IS_DEBUG_BUILD
IF bBailHappened
DEBUG_PRINTCALLSTACK()
NET_NL()NET_PRINT("<<TELL_TRANSITION_BAIL_HAPPENED = TRUE>>")
ELSE
DEBUG_PRINTCALLSTACK()
NET_NL()NET_PRINT("<<TELL_TRANSITION_BAIL_HAPPENED = FALSE>>")
ENDIF
#ENDIF
g_Private_BailHappened = bBailHappened
ENDPROC
/// PURPOSE: Returns if a script is wanting the transition to happen
FUNC BOOL DID_A_BAIL_HAPPEN()
RETURN g_Private_BailHappened
ENDFUNC
/// PURPOSE: Sets if a switch cam is active or not. This gets called automatically within the RUN_CAM_SPLINE_x procs.
PROC TELL_TRANSITION_MAYBE_FRONTEND_QUIT_MP(BOOL bQuitFrontend)
g_Private_QuitMPThroughMenu = bQuitFrontend
ENDPROC
/// PURPOSE: Returns if a script is wanting the transition to happen
FUNC BOOL DID_FRONTEND_QUIT_MP()
RETURN g_Private_QuitMPThroughMenu
ENDFUNC
/// PURPOSE: Block the selector buttons so that we dont perform any actions in game
PROC PROCESS_SELECTOR_INPUT_BLOCKS()
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_SELECT_WEAPON)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_RADIO_WHEEL)
IF !g_bBrowserVisible//1084004
SET_INPUT_EXCLUSIVE(PLAYER_CONTROL, INPUT_CHARACTER_WHEEL)
ENDIF
SET_INPUT_EXCLUSIVE(PLAYER_CONTROL, INPUT_WEAPON_WHEEL_UD)
SET_INPUT_EXCLUSIVE(PLAYER_CONTROL, INPUT_WEAPON_WHEEL_LR)
IF NOT IS_USING_KEYBOARD_AND_MOUSE(FRONTEND_CONTROL)
SET_INPUT_EXCLUSIVE(FRONTEND_CONTROL, INPUT_FRONTEND_X)
SET_INPUT_EXCLUSIVE(FRONTEND_CONTROL, INPUT_FRONTEND_Y)
SET_INPUT_EXCLUSIVE(FRONTEND_CONTROL, INPUT_FRONTEND_CANCEL)
SET_INPUT_EXCLUSIVE(FRONTEND_CONTROL, INPUT_FRONTEND_ACCEPT)
ENDIF
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_HEADLIGHT)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_ATTACK)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_ATTACK2)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_CIN_CAM)
ENDPROC
/// PURPOSE: Checks to see if player is currently pressing the selector UI button
/// RETURNS: TRUE if the player is pressing the button, FALSE if they are not
FUNC BOOL IS_SELECTOR_UI_BUTTON_PRESSED(BOOL bOnlyCheckEnabledControls = TRUE)
// TODO 2031031: Don't allow the selector to be activated while holding
// aim on the sniper scope view. Avoid conflict with zoom -Ben R
IF GET_ALLOW_MOVEMENT_WHILE_ZOOMED()
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
IF IS_AIMING_THROUGH_SNIPER_SCOPE(PLAYER_PED_ID())
IF IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_AIM)
OR IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_VEH_AIM)
RETURN FALSE
ENDIF
ENDIF
ENDIF
ENDIF
// TODO 2060410: Implement replay recording in character select UI
// - pressing a recording button closes the switch UI so dont process until dpad down is released
#IF USE_REPLAY_RECORDING_TRIGGERS
IF g_sSelectorUI.bMustReleaseSelectorUIButton
RETURN FALSE
ENDIF
#ENDIF
IF IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_CHARACTER_WHEEL)
OR (NOT bOnlyCheckEnabledControls AND IS_DISABLED_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_CHARACTER_WHEEL))
RETURN TRUE
ELSE
// PC Character switch shortcut keys
IF IS_PC_VERSION()
IF IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_MICHAEL)
OR IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_FRANKLIN)
OR IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_TREVOR)
OR IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_MULTIPLAYER)
RETURN TRUE
ENDIF
IF NOT bOnlyCheckEnabledControls
IF IS_DISABLED_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_MICHAEL)
OR IS_DISABLED_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_FRANKLIN)
OR IS_DISABLED_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_TREVOR)
OR IS_DISABLED_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_MULTIPLAYER)
RETURN TRUE
ENDIF
ENDIF
ENDIF
RETURN FALSE
ENDIF
ENDFUNC
/// PURPOSE: Checks to see if player has just pressed the selector UI button
/// RETURNS: TRUE if the player has just pressed the button, FALSE if they have not
FUNC BOOL IS_SELECTOR_UI_BUTTON_JUST_PRESSED(BOOL bOnlyCheckEnabledControls = TRUE)
// TODO 2060410: Implement replay recording in character select UI
// - pressing a recording button closes the switch UI so dont process until dpad down is released
#IF USE_REPLAY_RECORDING_TRIGGERS
IF g_sSelectorUI.bMustReleaseSelectorUIButton
RETURN FALSE
ENDIF
#ENDIF
IF IS_CONTROL_JUST_PRESSED(PLAYER_CONTROL, INPUT_CHARACTER_WHEEL)
OR (NOT bOnlyCheckEnabledControls AND IS_DISABLED_CONTROL_JUST_PRESSED(PLAYER_CONTROL, INPUT_CHARACTER_WHEEL))
RETURN TRUE
ELSE
// PC Character switch shortcut keys
IF IS_USING_KEYBOARD_AND_MOUSE(FRONTEND_CONTROL)
IF IS_CONTROL_JUST_PRESSED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_MICHAEL)
OR IS_CONTROL_JUST_PRESSED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_FRANKLIN)
OR IS_CONTROL_JUST_PRESSED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_TREVOR)
OR IS_CONTROL_JUST_PRESSED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_MULTIPLAYER)
RETURN TRUE
ENDIF
IF NOT bOnlyCheckEnabledControls
IF IS_DISABLED_CONTROL_JUST_PRESSED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_MICHAEL)
OR IS_DISABLED_CONTROL_JUST_PRESSED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_FRANKLIN)
OR IS_DISABLED_CONTROL_JUST_PRESSED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_TREVOR)
OR IS_DISABLED_CONTROL_JUST_PRESSED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_MULTIPLAYER)
RETURN TRUE
ENDIF
ENDIF
ENDIF
RETURN FALSE
ENDIF
ENDFUNC
/// PURPOSE: Checks to see if player has just released the selector UI button
/// RETURNS: TRUE if the player has just released the button, FALSE if they have not
FUNC BOOL IS_SELECTOR_UI_BUTTON_JUST_RELEASED(BOOL bOnlyCheckEnabledControls = TRUE)
// TODO 2060410: Implement replay recording in character select UI
// - pressing a recording button closes the switch UI so dont process until dpad down is released
#IF USE_REPLAY_RECORDING_TRIGGERS
IF g_sSelectorUI.bMustReleaseSelectorUIButton
RETURN FALSE
ENDIF
#ENDIF
IF IS_CONTROL_JUST_RELEASED(PLAYER_CONTROL, INPUT_CHARACTER_WHEEL)
OR (NOT bOnlyCheckEnabledControls AND IS_DISABLED_CONTROL_JUST_RELEASED(PLAYER_CONTROL, INPUT_CHARACTER_WHEEL))
RETURN TRUE
ELSE
// PC Character switch shortcut keys
IF IS_PC_VERSION()
// Don't switch unless ALL the player switch keys are not pressed.
// Michael
IF IS_CONTROL_JUST_RELEASED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_MICHAEL)
IF NOT IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_FRANKLIN)
AND NOT IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_TREVOR)
AND NOT IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_MULTIPLAYER)
RETURN TRUE
ENDIF
// Franklin
ELIF IS_CONTROL_JUST_RELEASED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_FRANKLIN)
IF NOT IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_MICHAEL)
AND NOT IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_TREVOR)
AND NOT IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_MULTIPLAYER)
RETURN TRUE
ENDIF
// Trevor
ELIF IS_CONTROL_JUST_RELEASED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_TREVOR)
IF NOT IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_MICHAEL)
AND NOT IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_FRANKLIN)
AND NOT IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_MULTIPLAYER)
RETURN TRUE
ENDIF
// MP
ELIF IS_CONTROL_JUST_RELEASED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_MULTIPLAYER)
IF NOT IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_MICHAEL)
AND NOT IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_FRANKLIN)
AND NOT IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_TREVOR)
RETURN TRUE
ENDIF
ENDIF
IF NOT bOnlyCheckEnabledControls
// Michael
IF IS_DISABLED_CONTROL_JUST_RELEASED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_MICHAEL)
IF NOT IS_DISABLED_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_FRANKLIN)
AND NOT IS_DISABLED_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_TREVOR)
AND NOT IS_DISABLED_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_MULTIPLAYER)
RETURN TRUE
ENDIF
// Franklin
ELIF IS_DISABLED_CONTROL_JUST_RELEASED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_FRANKLIN)
IF NOT IS_DISABLED_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_MICHAEL)
AND NOT IS_DISABLED_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_TREVOR)
AND NOT IS_DISABLED_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_MULTIPLAYER)
RETURN TRUE
ENDIF
// Trevor
ELIF IS_DISABLED_CONTROL_JUST_RELEASED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_TREVOR)
IF NOT IS_DISABLED_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_MICHAEL)
AND NOT IS_DISABLED_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_FRANKLIN)
AND NOT IS_DISABLED_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_MULTIPLAYER)
RETURN TRUE
ENDIF
// MP
ELIF IS_DISABLED_CONTROL_JUST_RELEASED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_MULTIPLAYER)
IF NOT IS_DISABLED_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_MICHAEL)
AND NOT IS_DISABLED_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_FRANKLIN)
AND NOT IS_DISABLED_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_TREVOR)
RETURN TRUE
ENDIF
ENDIF
ENDIF // IF NOT bOnlyCheckEnabledControl
ENDIF // IF IS_PC_VERSION()
RETURN FALSE
ENDIF
ENDFUNC
/// PURPOSE: Returns if a script is wanting the transition to happen
FUNC BOOL IS_TRANSITION_TELLING_CREATOR_TO_CLEANUP()
RETURN g_bTransitionTellCreatorToCleanup
ENDFUNC
/// PURPOSE: Sets if a switch cam is active or not. This gets called automatically within the RUN_CAM_SPLINE_x procs.
PROC TRIGGER_TRANSITION_TELL_CREATOR_TO_CLEANUP(BOOL bIsActive)
#IF IS_DEBUG_BUILD
IF bIsActive
DEBUG_PRINTCALLSTACK()
NET_NL()NET_PRINT(" << TRIGGER_TRANSITION_TELL_CREATOR_TO_CLEANUP - TRUE >> ")
ELSE
DEBUG_PRINTCALLSTACK()
NET_NL()NET_PRINT(" << TRIGGER_TRANSITION_TELL_CREATOR_TO_CLEANUP - FALSE >> ")
ENDIF
#ENDIF
g_bTransitionTellCreatorToCleanup = bIsActive
ENDPROC
/// PURPOSE: Returns if a script is wanting the transition to happen
FUNC BOOL IS_TRANSITION_NEED_TO_REPOSITION_SP_GUY()
RETURN g_bTransitionNeedToPositionSPGuy
ENDFUNC
/// PURPOSE: Sets if a switch cam is active or not. This gets called automatically within the RUN_CAM_SPLINE_x procs.
PROC TRIGGER_TRANSITION_NEED_TO_REPOSITION_SP_GUY(BOOL bIsActive)
#IF IS_DEBUG_BUILD
IF bIsActive
DEBUG_PRINTCALLSTACK()
NET_NL()NET_PRINT(" << TRIGGER_TRANSITION_NEED_TO_REPOSITION_SP_GUY - TRUE >> ")
ELSE
DEBUG_PRINTCALLSTACK()
NET_NL()NET_PRINT(" << TRIGGER_TRANSITION_NEED_TO_REPOSITION_SP_GUY - FALSE >> ")
ENDIF
#ENDIF
g_bTransitionNeedToPositionSPGuy = bIsActive
ENDPROC
/// PURPOSE: Returns if a script is wanting the transition to block the music stop
FUNC BOOL IS_TRANSITION_BLOCKING_MUSIC_STOP()
RETURN g_bTransitionBlockMusicStop
ENDFUNC
/// PURPOSE: Sets to true to block the GTA_ONLINE_STOP_SCORE being called when a transtion starts.
PROC SET_TRANSITION_LAUNCH_BLOCKING_MUSIC_STOP(BOOL bIsActive)
#IF IS_DEBUG_BUILD
IF bIsActive
DEBUG_PRINTCALLSTACK()
NET_NL()NET_PRINT(" << SET_TRANSITION_LAUNCH_BLOCKING_MUSIC_STOP - TRUE >> ")
ELSE
DEBUG_PRINTCALLSTACK()
NET_NL()NET_PRINT(" << SET_TRANSITION_LAUNCH_BLOCKING_MUSIC_STOP - FALSE >> ")
ENDIF
#ENDIF
g_bTransitionBlockMusicStop = bIsActive
ENDPROC
/// PURPOSE: Returns the ped enum equivalent to selector slot enum
FUNC enumCharacterList GET_PLAYER_PED_ENUM_FROM_SELECTOR_SLOT(SELECTOR_SLOTS_ENUM eSlot)
IF eSlot = SELECTOR_PED_MICHAEL
RETURN CHAR_MICHAEL
ELIF eSlot = SELECTOR_PED_TREVOR
RETURN CHAR_TREVOR
ELIF eSlot = SELECTOR_PED_FRANKLIN
RETURN CHAR_FRANKLIN
ENDIF
RETURN NO_CHARACTER
ENDFUNC
/// PURPOSE: Returns the selector slot equivalent to the ped enum
FUNC SELECTOR_SLOTS_ENUM GET_SELECTOR_SLOT_FROM_PLAYER_PED_ENUM(enumCharacterList ePed)
IF ePed = CHAR_MICHAEL
RETURN SELECTOR_PED_MICHAEL
ELIF ePed = CHAR_TREVOR
RETURN SELECTOR_PED_TREVOR
ELIF ePed = CHAR_FRANKLIN
RETURN SELECTOR_PED_FRANKLIN
ELIF ePed = NO_CHARACTER
RETURN SELECTOR_PED_MULTIPLAYER
ENDIF
RETURN NUMBER_OF_SELECTOR_PEDS
ENDFUNC
/// PURPOSE: Returns the z coord for the speicified camera
FUNC FLOAT GET_SELECTOR_CAM_Z_HEIGHT(CAMERA_INDEX selectorCamID)
IF DOES_CAM_EXIST(selectorCamID)
VECTOR vCoords = GET_CAM_COORD(selectorCamID)
RETURN (vCoords.z)
ENDIF
RETURN 0.0
ENDFUNC
/// PURPOSE: Works out the offset vector for a destination cam based on the ZOOM_LEVEL
/// NOTE: Only to be used in selector_public.sch
FUNC VECTOR GET_OFFSET_FOR_DEST_CAM(PED_INDEX ped)
// These offsets were calculated in game using the displacement vector
// of the gameplay camera coords and the player coords.
// This displacement was then transformed to the players local coord system by
// doting the with the players rotation vectors.
// Offsets are just an estimate and only suited for prototype version.
VECTOR vOffset = << 0.247654, -2.8853, 0.528659 >>
// Make sure the ped is alive
IF NOT IS_PED_INJURED(ped)
// Check if we need to use VEHICLE_ZOOM_LEVEL
IF IS_PED_IN_ANY_VEHICLE(ped)
// Grab the VEHICLE_ZOOM_LEVEL
SWITCH GET_FOLLOW_VEHICLE_CAM_ZOOM_LEVEL()
CASE VEHICLE_ZOOM_LEVEL_NEAR
vOffset = << -0.414898, -6.52417, 1.48257 >>
BREAK
CASE VEHICLE_ZOOM_LEVEL_MEDIUM
vOffset = << -0.409924, -7.87737, 1.5684 >>
BREAK
CASE VEHICLE_ZOOM_LEVEL_FAR
vOffset = << -0.403982, -9.22678, 1.65399 >>
BREAK
CASE VEHICLE_ZOOM_LEVEL_BONNET
vOffset = << -0.353964, 1.23187, 0.561746 >>
BREAK
ENDSWITCH
// Have to use PED_ZOOM_LEVEL
ELSE
// Grab the PED_ZOOM_LEVEL
SWITCH GET_FOLLOW_PED_CAM_ZOOM_LEVEL()
CASE PED_ZOOM_LEVEL_NEAR // 0
vOffset = << 0.231316, -1.91668, 0.535791 >>
BREAK
CASE PED_ZOOM_LEVEL_MEDIUM //1
vOffset = << 0.247654, -2.8853, 0.528659 >>
BREAK
CASE PED_ZOOM_LEVEL_FAR //2
vOffset = << 0.263986, -3.85184, 0.521533 >>
BREAK
ENDSWITCH
ENDIF
ENDIF
// #IF USE_TU_CHANGES
IF g_SpawnData.fCamHeading = 180
vOffset.y = -vOffset.y
ENDIF
// #ENDIF
// #IF NOT USE_TU_CHANGES
// IF g_SpawnData_OLD.fCamHeading = 180
// vOffset.y = -vOffset.y
// ENDIF
// #ENDIF
RETURN vOffset
ENDFUNC
/// PURPOSE: Returns the current phase of the selector cam. Ranges from 0.0 to 1.0
FUNC FLOAT GET_SELECTOR_CAM_PHASE(SELECTOR_CAM_STRUCT &sCamDetails)
IF DOES_CAM_EXIST(sCamDetails.camID)
IF IS_CAM_INTERPOLATING(sCamDetails.camID)
RETURN GET_CAM_SPLINE_PHASE(sCamDetails.camID)
ENDIF
ENDIF
RETURN 0.0
ENDFUNC
/// PURPOSE: Returns the current phase of the selector cam. Ranges from 0.0 to 1.0
FUNC BOOL SET_SELECTOR_CAM_PHASE(SELECTOR_CAM_STRUCT &sCamDetails, FLOAT fPhase)
IF DOES_CAM_EXIST(sCamDetails.camID)
IF IS_CAM_INTERPOLATING(sCamDetails.camID)
SET_CAM_SPLINE_PHASE(sCamDetails.camID, fPhase)
RETURN TRUE
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE: Destroys any existing selector cams and resets all the control flags
PROC CLEANUP_SELECTOR_CAM(SELECTOR_CAM_STRUCT &sCamDetails)
INT i
IF DOES_CAM_EXIST(sCamDetails.camID)
DESTROY_CAM(sCamDetails.camID)
SET_SELECTOR_CAM_ACTIVE(FALSE)
ENDIF
IF DOES_CAM_EXIST(sCamDetails.camTo)
DESTROY_CAM(sCamDetails.camTo)
ENDIF
IF DOES_CAM_EXIST(sCamDetails.camSky)
DESTROY_CAM(sCamDetails.camSky)
ENDIF
REPEAT NUM_SELECTOR_INTERP_CAMS i
IF DOES_CAM_EXIST(sCamDetails.camID)
DESTROY_CAM(sCamDetails.camInterpIDs[i])
ENDIF
ENDREPEAT
sCamDetails.bSplineCreated = FALSE
sCamDetails.bSplineActive = FALSE
sCamDetails.bSplineComplete = FALSE
sCamDetails.bOKToSwitchPed = FALSE
sCamDetails.bPedSwitched = FALSE
sCamDetails.bRun = FALSE
sCamDetails.bIsPhoneDisabled = FALSE
sCamDetails.iInterpCams = 0
sCamDetails.iSplineDuration = 0
sCamDetails.fMaxHeight = 0
// //# 1524219
// CASCADE_SHADOWS_SET_AIRCRAFT_MODE(FALSE)
// PRINTLN("CASCADE_SHADOWS_SET_AIRCRAFT_MODE(FALSE) called by ", GET_THIS_SCRIPT_NAME())
#IF IS_DEBUG_BUILD
IF DOES_CAM_EXIST(sCamDetails.camCodeTransition)
DESTROY_CAM(sCamDetails.camCodeTransition)
ENDIF
sCamDetails.bUsingCodeCam = FALSE
#ENDIF
ENDPROC
#IF IS_DEBUG_BUILD
/// PURPOSE: This is a temp debug func which tests the new START_CAM_TRANSITION command.
/// To use this in game, set the g_bUseTransitionCamera flag to TRUE in RAG>>Script>>Selector Globals.
FUNC BOOL test_cam_transition(SELECTOR_CAM_STRUCT &camDetails)
// Create the camera
IF NOT camDetails.bSplineCreated
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
AND NOT IS_PED_INJURED(camDetails.pedTo)
PRINTSTRING("\n Setting up transition camera")PRINTNL()
IF DOES_CAM_EXIST(camDetails.camCodeTransition)
DESTROY_CAM(camDetails.camCodeTransition)
ENDIF
camDetails.camCodeTransition = CREATE_CAM("DEFAULT_SCENE_TRANSITION_CAMERA")
SET_CAM_ACTIVE(camDetails.camCodeTransition, TRUE)
PRINTSTRING("\n Starting scene transition")PRINTNL()
START_CAM_TRANSITION(camDetails.camCodeTransition, GET_ENTITY_COORDS(PLAYER_PED_ID()), GET_ENTITY_COORDS(camDetails.pedTo))
RENDER_SCRIPT_CAMS(TRUE, TRUE)
camDetails.fMaxHeight = GET_SELECTOR_CAM_Z_HEIGHT(camDetails.camCodeTransition)
camDetails.bSplineCreated = TRUE
camDetails.bSplineActive = TRUE
camDetails.iActivateTimer = GET_GAME_TIMER()
camDetails.bUsingCodeCam = TRUE
SET_SELECTOR_CAM_ACTIVE(TRUE)
ELSE
camDetails.bSplineComplete = TRUE // Error
ENDIF
ENDIF
PRINTLN("GENERIC_PED_SCENE - (1) camDetails.bSplineActive: ", camDetails.bSplineActive)
// Wait for the transition to complete
IF camDetails.bSplineActive
PRINTLN("GENERIC_PED_SCENE - (1) DOES_CAM_EXIST(camDetails.camCodeTransition): ", DOES_CAM_EXIST(camDetails.camCodeTransition))
IF DOES_CAM_EXIST(camDetails.camCodeTransition)
PRINTLN("GENERIC_PED_SCENE - (1) IS_CAM_TRANSITIONING(camDetails.camCodeTransition): ", IS_CAM_TRANSITIONING(camDetails.camCodeTransition))
IF NOT IS_CAM_TRANSITIONING(camDetails.camCodeTransition)
camDetails.bSplineComplete = TRUE
ELSE
PRINTSTRING("\n Scene transition phase = ")
PRINTFLOAT(GET_CAM_TRANSITION_PHASE(camDetails.camCodeTransition))
PRINTNL()
PRINTLN("GENERIC_PED_SCENE - (1) GET_CAM_TRANSITION_PHASE(camDetails.camCodeTransition): ", GET_CAM_TRANSITION_PHASE(camDetails.camCodeTransition))
PRINTLN("GENERIC_PED_SCENE - (1) g_sSelectorUI.debug_fSwitchPedAfterPhase: ", g_sSelectorUI.debug_fSwitchPedAfterPhase)
IF GET_CAM_TRANSITION_PHASE(camDetails.camCodeTransition) > g_sSelectorUI.debug_fSwitchPedAfterPhase
camDetails.bOKToSwitchPed = TRUE
PRINTLN("GENERIC_PED_SCENE - Setting bOKToSwitchPed to TRUE (1)")
#IF IS_DEBUG_BUILD
DEBUG_PRINTCALLSTACK()
#ENDIF
ENDIF
ENDIF
ELSE
camDetails.bSplineComplete = TRUE // Error
ENDIF
ENDIF
// Cleanup the camera
IF camDetails.bSplineComplete
RENDER_SCRIPT_CAMS(FALSE, FALSE)
IF DOES_CAM_EXIST(camDetails.camCodeTransition)
SET_CAM_ACTIVE(camDetails.camCodeTransition, FALSE)
DESTROY_CAM(camDetails.camCodeTransition)
ENDIF
DISABLE_CELLPHONE(camDetails.bIsPhoneDisabled)
// Reset all the camera values incase they have to be used again
camDetails.bSplineCreated = FALSE
camDetails.bSplineActive = FALSE
camDetails.bSplineComplete = FALSE
camDetails.bOKToSwitchPed = FALSE
camDetails.bPedSwitched = FALSE
camDetails.bRun = FALSE
camDetails.iInterpCams = 0
camDetails.iSplineDuration = 0
camDetails.bUsingCodeCam = FALSE
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
SET_PLAYER_CONTROL(PLAYER_ID(), TRUE)
SET_PLAYER_INVINCIBLE(PLAYER_ID(), FALSE)
SET_ENTITY_VISIBLE(PLAYER_PED_ID(), TRUE)
//FREEZE_ENTITY_POSITION(PLAYER_PED_ID(), FALSE)
SET_PED_CAN_BE_TARGETTED(PLAYER_PED_ID(), TRUE)
IF NOT IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
SET_ENTITY_COLLISION(PLAYER_PED_ID(), TRUE)
ENDIF
ENDIF
// If we didnt switch players then reset the proofs
IF NOT IS_PED_INJURED(camDetails.pedTo)
SET_ENTITY_INVINCIBLE(camDetails.pedTo, FALSE)
ENDIF
SET_SELECTOR_CAM_ACTIVE(FALSE)
RETURN FALSE // Cam complete
ENDIF
// Hide the HUD
HIDE_HUD_AND_RADAR_THIS_FRAME()
//CLEAR_REMINDER_MESSAGE() //#1421176
RETURN TRUE
ENDFUNC
#ENDIF
FUNC STRING GET_SKYSWOOP_STRING(SKYSWOOP aSwoopStage)
SWITCH aSwoopStage
CASE SKYSWOOP_NONE RETURN "SKYSWOOP_NONE"
CASE SKYSWOOP_GOINGUP RETURN "SKYSWOOP_GOINGUP"
CASE SKYSWOOP_INSKYSTATIC RETURN "SKYSWOOP_INSKYSTATIC"
CASE SKYSWOOP_INSKYMOVING RETURN "SKYSWOOP_INSKYMOVING"
CASE SKYSWOOP_GOINGDOWN RETURN "SKYSWOOP_GOINGDOWN"
ENDSWITCH
RETURN ""
ENDFUNC
/// PURPOSE:
/// Extra function to tell the MP HUD where the swooping camera is at
/// PARAMS:
/// aStage -
PROC SET_SKYSWOOP_STAGE(SKYSWOOP aStage)
#IF IS_DEBUG_BUILD
DEBUG_PRINTCALLSTACK()
NET_PRINT("SET_SKYSWOOP_STAGE() - Called = ")NET_PRINT(GET_SKYSWOOP_STRING(aStage))
NET_NL()
// if going to the SKYSWOOP_GOINGDOWN then re-init the stuck in sky timer
#IF FEATURE_SHORTEN_SKY_HANG
IF (aStage = SKYSWOOP_GOINGDOWN)
AND NOT (g_TransitionData.SwoopStage = SKYSWOOP_GOINGDOWN)
IF HAS_NETWORK_TIME_STARTED()
g_iHangingInSkyState = 0
g_HangingInSkyTimer = GET_NETWORK_TIME()
PRINTLN("[Hanginginsky] SET_SKYSWOOP_STAGE(SKYSWOOP_GOINGDOWN) - resetting timer ")
ENDIF
ENDIF
#ENDIF
#ENDIF
#IF USE_FINAL_PRINTS
PRINTLN_FINAL(" SET_SKYSWOOP_STAGE() - Called = ", GET_SKYSWOOP_STRING(aStage))
#ENDIF
IF aStage = SKYSWOOP_NONE
g_b_skyCamPausedForOutroLastFrame = FALSE
ENDIF
g_TransitionData.SwoopStage = aStage
ENDPROC
PROC DESTROY_TRANSITION_CAMERA(SELECTOR_CAM_STRUCT &camDetails, BOOL bLeaveScriptCamRendering = FALSE)
camDetails.bSplineCreated = FALSE
camDetails.bSplineActive = FALSE
camDetails.bSplineComplete = FALSE
camDetails.bOKToSwitchPed = FALSE
camDetails.bPedSwitched = FALSE
camDetails.bRun = FALSE
IF DOES_CAM_EXIST(camDetails.camID)
IF IS_CAM_ACTIVE(camDetails.camID)
SET_SELECTOR_CAM_ACTIVE(FALSE)
ENDIF
DESTROY_CAM(camDetails.camID)
ENDIF
#IF IS_DEBUG_BUILD
// IF NOT TRUE
// SET_GAMEPLAY_CAM_RELATIVE_HEADING(0.0)
// SET_GAMEPLAY_CAM_RELATIVE_PITCH(0)
// ENDIF
#ENDIF
IF NOT (g_drunkCameraActive)
STOP_GAMEPLAY_CAM_SHAKING(TRUE)
SET_GAMEPLAY_CAM_MOTION_BLUR_SCALING_THIS_UPDATE(0)
SET_GAMEPLAY_CAM_MAX_MOTION_BLUR_STRENGTH_THIS_UPDATE(0)
ENDIF
// #IF USE_TU_CHANGES
g_SpawnData.fCamHeading = 0.0
// #ENDIF
// #IF NOT USE_TU_CHANGES
// g_SpawnData_OLD.fCamHeading = 0.0
// #ENDIF
IF NOT bLeaveScriptCamRendering
RENDER_SCRIPT_CAMS(FALSE, FALSE, 0)
ENDIF
ENDPROC
PROC KILL_SKYCAM(BOOL DoSwitchCameraPart = TRUE, BOOL bLeaveScriptCamRendering = FALSE)
DEBUG_PRINTCALLSTACK()
NET_NL()NET_PRINT("KILL_SKYCAM() - Called ")
DESTROY_TRANSITION_CAMERA(g_SkyCamData,bLeaveScriptCamRendering)
#IF USE_TU_CHANGES
DONT_RENDER_IN_GAME_UI(FALSE)
NET_NL()NET_PRINT(" KILL_SKYCAM: DONT_RENDER_IN_GAME_UI(FALSE) ")
BOOL bDoCodeCamera = TRUE
IF DoSwitchCameraPart
IF bDoCodeCamera = TRUE
// IF IS_SWITCH_TO_MULTI_FIRSTPART_FINISHED()
NET_NL()NET_PRINT("KILL_SKYCAM() - STOP_PLAYER_SWITCH called ")
// SWITCH_TO_MULTI_SECONDPART(PLAYER_PED_ID())
STOP_PLAYER_SWITCH()
SET_SKYSWOOP_STAGE(SKYSWOOP_NONE)
IF DOES_ENTITY_EXIST(PlayerSwitchLeftBehindPed)
IF DOES_ENTITY_BELONG_TO_THIS_SCRIPT(PlayerSwitchLeftBehindPed, FALSE)
IF NOT IS_ENTITY_A_MISSION_ENTITY(PlayerSwitchLeftBehindPed)
SET_ENTITY_AS_MISSION_ENTITY(PlayerSwitchLeftBehindPed, FALSE)
NET_NL()NET_PRINT("KILL_SKYCAM: NOT IS_ENTITY_A_MISSION_ENTITY(PlayerSwitchLeftBehindPed)")
ELSE
NET_NL()NET_PRINT("KILL_SKYCAM: IS_ENTITY_A_MISSION_ENTITY(PlayerSwitchLeftBehindPed)")
ENDIF
NET_NL()NET_PRINT(" KILL_SKYCAM: DELETE_PED(PlayerSwitchLeftBehindPed) ")
DELETE_PED(PlayerSwitchLeftBehindPed)
ENDIF
ENDIF
// ENDIF
ENDIF
ENDIF
#ENDIF
//Must not be changed. -BenR
#IF NOT USE_TU_CHANGES
BOOL bDoCodeCamera = TRUE
IF DoSwitchCameraPart
IF bDoCodeCamera = TRUE
NET_NL()NET_PRINT("KILL_SKYCAM() - STOP_PLAYER_SWITCH called ")
STOP_PLAYER_SWITCH()
ENDIF
ENDIF
SET_SKYSWOOP_STAGE(SKYSWOOP_NONE)
#ENDIF
ENDPROC
PROC TAKE_CONTROL_OF_TRANSITION(BOOL DoSwitchCameraPart = TRUE, BOOL bKillSkycam = TRUE)
DEBUG_PRINTCALLSTACK()
NET_NL()NET_PRINT("TAKE_CONTROL_OF_TRANSITION(")NET_PRINT_BOOL(DoSwitchCameraPart)NET_PRINT(") - Called ")
IF bKillSkycam
CLEAR_BIT(g_BossSpecData.specCamData.iBitSet, SPEC_CAM_BS_DEACTIVATED_DUE_TO_SKYSWOOP_UP)
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_SPECTATOR, "=== CAM === TAKE_CONTROL_OF_TRANSITION called we are killing the skycam and therefore do not need this data anymore; SPEC_CAM_BS_DEACTIVATED_DUE_TO_SKYSWOOP_UP.")
#ENDIF
KILL_SKYCAM(DoSwitchCameraPart)
ENDIF
HUD_CHANGE_STATE(HUD_STATE_NO_DISPLAY)
TRANSITION_CHANGE_STATE(TRANSITION_STATE_TERMINATE_MAINTRANSITION)
ENDPROC
//PROC RUN_TUTORIAL_TANSITION_FAILSAFE()
// HUD_CHANGE_STATE(HUD_STATE_NO_DISPLAY)
// TRANSITION_CHANGE_STATE(TRANSITION_STATE_CNC_SWOOP_DOWN)
//ENDPROC
/// PURPOSE: Obtains the gamplay game relative heading to a look at pos
///
/// NOTES:
/// Author: Lawrence Kerr
func float get_final_gameplay_cam_relative_heading_to_look_at_pos(ped_index &ped_to, vector look_at_pos)
if not is_ped_injured(ped_to)
vector target_vec
target_vec = look_at_pos - get_entity_coords(ped_to)
return (get_heading_from_vector_2d(target_vec.x, target_vec.y) - get_entity_heading(ped_to))
else
#IF IS_DEBUG_BUILD
SCRIPT_ASSERT("Cannot get heading as ped to is dead.")
PRINTSTRING("\nCannot get heading as ped to is dead.")
PRINTNL()
#ENDIF
endif
return 0.0
endfunc
/// PURPOSE: Sets up a camera spline between player and ped.
///
/// NOTES: camDetails.camID will be created in this func unless the calling script has created a custom camera.
/// Calling script should set camDetails.pedTo to the ped that they want to hot-swap to.
/// If eInterpType is SELECTOR_CAM_DEFAULT then the interp type will be determined automatically.
/// Uses bool values to control the process and then returns FALSE when the spline is complete.
/// Should be called each frame from calling script until FALSE is returned.
/// To not alter the gameplay cam set fDestCamRelative... params to a number outside the range -360.0 to 360.0
FUNC BOOL RUN_CAM_SPLINE_FROM_PLAYER_TO_PED(SELECTOR_CAM_STRUCT &camDetails, FLOAT fDestCamRelativePitch = 0.0, FLOAT fDestCamRelativeHeading = 0.0, SELECTOR_CAM_INTERP_TYPE eInterpType = SELECTOR_CAM_DEFAULT, INT iInterpBackToGameDurationOverride = -1, INT iInterpToCamOverride = 0, INT iStraightInterpTime = 800)
///////////////////////////////////////////////////////////////////////////
///*********************************************************************///
/// Test script for the new hotswap camera set up by code ///
/// ///
#IF IS_DEBUG_BUILD
IF g_sSelectorUI.debug_bUseTransitionCamera
OR camDetails.bUsingCodeCam
IF (camDetails.bSplineCreated AND camDetails.bUsingCodeCam)
OR (NOT camDetails.bSplineCreated)
RETURN test_cam_transition(camDetails)
ENDIF
ENDIF
#ENDIF
///*********************************************************************///
///////////////////////////////////////////////////////////////////////////
BOOL bFinalNodeUpdated
INT iCamCount
///////////////////////////////////////////////////////
/// Setup the spline nodes
IF NOT camDetails.bSplineCreated
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
AND NOT IS_PED_INJURED(camDetails.pedTo)
camDetails.iSplineDuration = 0
INT iDuration
FLOAT fSkyNodeAngle, fMaxCamZ, fRotZ
BOOL bPlayerVeh, bPedVeh
VEHICLE_INDEX vehPlayer, vehPed
VECTOR vCamRot
VECTOR vTargetRelativePosition
VECTOR vHorizontalDelta
VECTOR vPedPos = GET_ENTITY_COORDS(camDetails.pedTo)
VECTOR vPlayerPos = GET_ENTITY_COORDS(PLAYER_PED_ID())
FLOAT fPedDist2D = GET_DISTANCE_BETWEEN_COORDS(vPlayerPos, vPedPos, FALSE)
FLOAT fPedDist3D = GET_DISTANCE_BETWEEN_COORDS(vPlayerPos, vPedPos, TRUE)
// Determine what type of cam we will use
IF eInterpType = SELECTOR_CAM_DEFAULT
IF fPedDist3D < 8.0
camDetails.camType = SELECTOR_CAM_STRAIGHT_INTERP
ELIF fPedDist2D < 30.0
camDetails.camType = SELECTOR_CAM_SHORT_SPLINE
ELSE
camDetails.camType = SELECTOR_CAM_LONG_SPLINE
ENDIF
ELSE
camDetails.camType = eInterpType
ENDIF
// Make sure the spline camera has been created
IF NOT DOES_CAM_EXIST(camDetails.camID)
camDetails.camID = CREATE_CAM("DEFAULT_SPLINE_CAMERA", FALSE)
ENDIF
// Destory all the previous interp cams
FOR iCamCount = 0 TO NUM_SELECTOR_INTERP_CAMS-1
IF DOES_CAM_EXIST(camDetails.camInterpIDs[iCamCount])
DESTROY_CAM(camDetails.camInterpIDs[iCamCount])
ENDIF
ENDFOR
// Set up the camera based on type
SWITCH camDetails.camType
CASE SELECTOR_CAM_STRAIGHT_INTERP
// Grab vehicle state and the final rotation
IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
vehPlayer = GET_VEHICLE_PED_IS_USING(PLAYER_PED_ID())
bPlayerVeh = TRUE
ENDIF
IF IS_PED_IN_ANY_VEHICLE(camDetails.pedTo)
vehPed = GET_VEHICLE_PED_IS_USING(camDetails.pedTo)
bPedVeh = TRUE
fRotZ = GET_ENTITY_HEADING(vehPed)
IF fRotZ > 180.0
fRotZ -= 360.0
ENDIF
ELSE
fRotZ = GET_ENTITY_HEADING(camDetails.pedTo)
IF fRotZ > 180.0
fRotZ -= 360.0
ENDIF
ENDIF
vCamRot = GET_FINAL_RENDERED_CAM_ROT()
// Initial camera behind the player
camDetails.iInterpCams = 0
SET_CAM_FOV(camDetails.camID, GET_FINAL_RENDERED_CAM_FOV())
IF NOT DOES_CAM_EXIST(camDetails.camInterpIDs[camDetails.iInterpCams])
camDetails.camInterpIDs[camDetails.iInterpCams] = CREATE_CAM("DEFAULT_SCRIPTED_CAMERA", FALSE)
ENDIF
IF bPlayerVeh
vTargetRelativePosition = GET_OFFSET_FROM_ENTITY_GIVEN_WORLD_COORDS(vehPlayer, GET_FINAL_RENDERED_CAM_COORD())
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams], vehPlayer, vTargetRelativePosition)
ELSE
vTargetRelativePosition = GET_OFFSET_FROM_ENTITY_GIVEN_WORLD_COORDS(PLAYER_PED_ID(), GET_FINAL_RENDERED_CAM_COORD())
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams], PLAYER_PED_ID(), vTargetRelativePosition)
ENDIF
SET_CAM_ROT(camDetails.camInterpIDs[camDetails.iInterpCams], vCamRot)
SET_CAM_FOV(camDetails.camInterpIDs[camDetails.iInterpCams], GET_FINAL_RENDERED_CAM_FOV())
ADD_CAM_SPLINE_NODE_USING_CAMERA(camDetails.camID, camDetails.camInterpIDs[camDetails.iInterpCams], 0, CAM_SPLINE_NODE_SMOOTH_ROT)
camDetails.iInterpCams++
camDetails.iSplineDuration += 0
// Destination camera behind the ped
IF NOT DOES_CAM_EXIST(camDetails.camInterpIDs[camDetails.iInterpCams])
camDetails.camInterpIDs[camDetails.iInterpCams] = CREATE_CAM("DEFAULT_SCRIPTED_CAMERA", FALSE)
ENDIF
IF bPedVeh
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams], vehPed, GET_OFFSET_FOR_DEST_CAM(camDetails.pedTo))
ELSE
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams], camDetails.pedTo, GET_OFFSET_FOR_DEST_CAM(camDetails.pedTo))
ENDIF
SET_CAM_ROT(camDetails.camInterpIDs[camDetails.iInterpCams], << -0.951428, 0.0, fRotZ >>)
SET_CAM_FOV(camDetails.camInterpIDs[camDetails.iInterpCams], GET_FINAL_RENDERED_CAM_FOV())
ADD_CAM_SPLINE_NODE_USING_CAMERA(camDetails.camID, camDetails.camInterpIDs[camDetails.iInterpCams], iStraightInterpTime, CAM_SPLINE_NODE_SMOOTH_ROT)
camDetails.iInterpCams++
camDetails.iSplineDuration += iStraightInterpTime
camDetails.bSplineCreated = TRUE
BREAK
CASE SELECTOR_CAM_SHORT_SPLINE
// Calculate the max node height
IF vPlayerPos.z > vPedPos.z // Player higher
fMaxCamZ = FMAX(vPlayerPos.z + 5.0, vPedPos.z + fPedDist2D)
ELSE // Ped higher
fMaxCamZ = FMAX(vPedPos.z + 5.0, vPlayerPos.z + fPedDist2D)
ENDIF
// Calculate the appropriate translation of the sky node towards the destination ped
fSkyNodeAngle = 10.0
vHorizontalDelta = vPedPos - vPlayerPos
vHorizontalDelta.z = 0.0
vHorizontalDelta = GET_VECTOR_OF_LENGTH(vHorizontalDelta, FMIN(fMaxCamZ * TAN(fSkyNodeAngle), fPedDist2D / 3.0))
// Calculate the duration of the spline when up in the sky
iDuration = ROUND((fPedDist3D / ((30.0 - 7.5) / (800.0 - 200.0)))+500.0)
// Grab vehicle state and the final rotation
IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
vehPlayer = GET_VEHICLE_PED_IS_USING(PLAYER_PED_ID())
bPlayerVeh = TRUE
ENDIF
IF IS_PED_IN_ANY_VEHICLE(camDetails.pedTo)
vehPed = GET_VEHICLE_PED_IS_USING(camDetails.pedTo)
bPedVeh = TRUE
fRotZ = GET_ENTITY_HEADING(vehPed)
IF fRotZ > 180.0
fRotZ -= 360.0
ENDIF
ELSE
fRotZ = GET_ENTITY_HEADING(camDetails.pedTo)
IF fRotZ > 180.0
fRotZ -= 360.0
ENDIF
ENDIF
vCamRot = GET_FINAL_RENDERED_CAM_ROT()
// Initial camera behind the player
camDetails.iInterpCams = 0
SET_CAM_FOV(camDetails.camID, GET_FINAL_RENDERED_CAM_FOV())
IF NOT DOES_CAM_EXIST(camDetails.camInterpIDs[camDetails.iInterpCams])
camDetails.camInterpIDs[camDetails.iInterpCams] = CREATE_CAM("DEFAULT_SCRIPTED_CAMERA", FALSE)
ENDIF
IF bPlayerVeh
vTargetRelativePosition = GET_OFFSET_FROM_ENTITY_GIVEN_WORLD_COORDS(vehPlayer, GET_FINAL_RENDERED_CAM_COORD())
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams], vehPlayer, vTargetRelativePosition)
ELSE
vTargetRelativePosition = GET_OFFSET_FROM_ENTITY_GIVEN_WORLD_COORDS(PLAYER_PED_ID(), GET_FINAL_RENDERED_CAM_COORD())
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams], PLAYER_PED_ID(), vTargetRelativePosition)
ENDIF
SET_CAM_ROT(camDetails.camInterpIDs[camDetails.iInterpCams], vCamRot)
SET_CAM_FOV(camDetails.camInterpIDs[camDetails.iInterpCams], GET_FINAL_RENDERED_CAM_FOV())
ADD_CAM_SPLINE_NODE_USING_CAMERA(camDetails.camID, camDetails.camInterpIDs[camDetails.iInterpCams], 0, CAM_SPLINE_NODE_SMOOTH_ROT)
camDetails.iInterpCams++
camDetails.iSplineDuration += 0
// Camera 5m above player
IF NOT DOES_CAM_EXIST(camDetails.camInterpIDs[camDetails.iInterpCams])
camDetails.camInterpIDs[camDetails.iInterpCams] = CREATE_CAM("DEFAULT_SCRIPTED_CAMERA", FALSE)
ENDIF
IF bPlayerVeh
vTargetRelativePosition = GET_OFFSET_FROM_ENTITY_GIVEN_WORLD_COORDS(vehPlayer, GET_FINAL_RENDERED_CAM_COORD())
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams], vehPlayer, vTargetRelativePosition+<<0.0, 0.0, 15.0>>)
ELSE
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams], PLAYER_PED_ID(), <<0.0, 0.0, 5.0>>, FALSE)
ENDIF
SET_CAM_ROT(camDetails.camInterpIDs[camDetails.iInterpCams], <<-87.5, 0.0, vCamRot.z>>)
SET_CAM_FOV(camDetails.camInterpIDs[camDetails.iInterpCams], GET_FINAL_RENDERED_CAM_FOV())
ADD_CAM_SPLINE_NODE_USING_CAMERA(camDetails.camID, camDetails.camInterpIDs[camDetails.iInterpCams], 400, CAM_SPLINE_NODE_SMOOTH_ROT)
camDetails.iInterpCams++
camDetails.iSplineDuration += 400
// Camera in sky above player
IF NOT DOES_CAM_EXIST(camDetails.camInterpIDs[camDetails.iInterpCams])
camDetails.camInterpIDs[camDetails.iInterpCams] = CREATE_CAM("DEFAULT_SCRIPTED_CAMERA", FALSE)
ENDIF
IF bPlayerVeh
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams], vehPlayer, <<0.0, 0.0, fMaxCamZ>> + vHorizontalDelta, FALSE)
ELSE
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams], PLAYER_PED_ID(), <<0.0, 0.0, fMaxCamZ>> + vHorizontalDelta, FALSE)
ENDIF
SET_CAM_ROT(camDetails.camInterpIDs[camDetails.iInterpCams], <<-87.5, 0.0, vCamRot.z >>)
SET_CAM_FOV(camDetails.camInterpIDs[camDetails.iInterpCams], GET_FINAL_RENDERED_CAM_FOV())
ADD_CAM_SPLINE_NODE_USING_CAMERA(camDetails.camID, camDetails.camInterpIDs[camDetails.iInterpCams], 400, CAM_SPLINE_NODE_SMOOTH_ROT)
camDetails.iInterpCams++
camDetails.iSplineDuration += 400
// Camera in sky above ped
IF NOT DOES_CAM_EXIST(camDetails.camInterpIDs[camDetails.iInterpCams])
camDetails.camInterpIDs[camDetails.iInterpCams] = CREATE_CAM("DEFAULT_SCRIPTED_CAMERA", FALSE)
ENDIF
IF bPedVeh
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams], vehPed, <<0.0, 0.0, fMaxCamZ>> - vHorizontalDelta, FALSE)
ELSE
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams], camDetails.pedTo, <<0.0, 0.0, fMaxCamZ>> - vHorizontalDelta, FALSE)
ENDIF
SET_CAM_ROT(camDetails.camInterpIDs[camDetails.iInterpCams], <<-87.5, 0.0, fRotZ >>)
SET_CAM_FOV(camDetails.camInterpIDs[camDetails.iInterpCams], GET_FINAL_RENDERED_CAM_FOV())
ADD_CAM_SPLINE_NODE_USING_CAMERA(camDetails.camID, camDetails.camInterpIDs[camDetails.iInterpCams], iDuration, CAM_SPLINE_NODE_SMOOTH_ROT)
camDetails.iInterpCams++
camDetails.iSplineDuration += iDuration
// Camera 5m above ped
IF NOT DOES_CAM_EXIST(camDetails.camInterpIDs[camDetails.iInterpCams])
camDetails.camInterpIDs[camDetails.iInterpCams] = CREATE_CAM("DEFAULT_SCRIPTED_CAMERA", FALSE)
ENDIF
IF bPedVeh
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams], vehPed, <<0.0, 0.0, 15.0>>, FALSE)
ELSE
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams], camDetails.pedTo, <<0.0, 0.0, 5.0>>, FALSE)
ENDIF
SET_CAM_ROT(camDetails.camInterpIDs[camDetails.iInterpCams], <<-87.5, 0.0, fRotZ>>)
SET_CAM_FOV(camDetails.camInterpIDs[camDetails.iInterpCams], GET_FINAL_RENDERED_CAM_FOV())
ADD_CAM_SPLINE_NODE_USING_CAMERA(camDetails.camID, camDetails.camInterpIDs[camDetails.iInterpCams], 400, CAM_SPLINE_NODE_SMOOTH_ROT)
camDetails.iInterpCams++
camDetails.iSplineDuration += 400
// Destination camera behind the ped
IF NOT DOES_CAM_EXIST(camDetails.camInterpIDs[camDetails.iInterpCams])
camDetails.camInterpIDs[camDetails.iInterpCams] = CREATE_CAM("DEFAULT_SCRIPTED_CAMERA", FALSE)
ENDIF
IF bPedVeh
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams], vehPed, GET_OFFSET_FOR_DEST_CAM(camDetails.pedTo))
ELSE
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams], camDetails.pedTo, GET_OFFSET_FOR_DEST_CAM(camDetails.pedTo))
ENDIF
SET_CAM_ROT(camDetails.camInterpIDs[camDetails.iInterpCams], << -0.951428, 0.0, fRotZ >>)
SET_CAM_FOV(camDetails.camInterpIDs[camDetails.iInterpCams], GET_FINAL_RENDERED_CAM_FOV())
ADD_CAM_SPLINE_NODE_USING_CAMERA(camDetails.camID, camDetails.camInterpIDs[camDetails.iInterpCams], 400, CAM_SPLINE_NODE_SMOOTH_ROT)
camDetails.iInterpCams++
camDetails.iSplineDuration += 400
camDetails.bSplineCreated = TRUE
BREAK
CASE SELECTOR_CAM_LONG_SPLINE
// Calculate the max node height
fMaxCamZ = 450.0
IF vPlayerPos.z > vPedPos.z // Player higher
fMaxCamZ = FMAX(fMaxCamZ, vPlayerPos.z+25.0)
ELSE // Ped higher
fMaxCamZ = FMAX(fMaxCamZ, vPedPos.z+25.0)
ENDIF
// Calculate the appropriate translation of the sky node towards the destination ped
fSkyNodeAngle = 20.0
vHorizontalDelta = vPedPos - vPlayerPos
vHorizontalDelta.z = 0.0
vHorizontalDelta = GET_VECTOR_OF_LENGTH(vHorizontalDelta, FMIN(fMaxCamZ * TAN(fSkyNodeAngle), fPedDist2D / 3.0))
// Calculate the duration of the spline when up in the sky
fPedDist3D = CLAMP(fPedDist3D, 50.0, 4000.0)
iDuration = ROUND((fPedDist3D / ((4000.0 - 50.0) / (2000.0 - 1000.0)))+1000.0)
// Grab vehicle state and the final rotation
IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
vehPlayer = GET_VEHICLE_PED_IS_USING(PLAYER_PED_ID())
bPlayerVeh = TRUE
ENDIF
IF IS_PED_IN_ANY_VEHICLE(camDetails.pedTo)
vehPed = GET_VEHICLE_PED_IS_USING(camDetails.pedTo)
bPedVeh = TRUE
fRotZ = GET_ENTITY_HEADING(vehPed)
IF fRotZ > 180.0
fRotZ -= 360.0
ENDIF
ELSE
fRotZ = GET_ENTITY_HEADING(camDetails.pedTo)
IF fRotZ > 180.0
fRotZ -= 360.0
ENDIF
ENDIF
vCamRot = GET_FINAL_RENDERED_CAM_ROT()
// Initial camera behind the player
camDetails.iInterpCams = 0
SET_CAM_FOV(camDetails.camID, GET_FINAL_RENDERED_CAM_FOV())
IF NOT DOES_CAM_EXIST(camDetails.camInterpIDs[camDetails.iInterpCams])
camDetails.camInterpIDs[camDetails.iInterpCams] = CREATE_CAM("DEFAULT_SCRIPTED_CAMERA", FALSE)
ENDIF
IF bPlayerVeh
vTargetRelativePosition = GET_OFFSET_FROM_ENTITY_GIVEN_WORLD_COORDS(vehPlayer, GET_FINAL_RENDERED_CAM_COORD())
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams], vehPlayer, vTargetRelativePosition)
ELSE
vTargetRelativePosition = GET_OFFSET_FROM_ENTITY_GIVEN_WORLD_COORDS(PLAYER_PED_ID(), GET_FINAL_RENDERED_CAM_COORD())
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams], PLAYER_PED_ID(), vTargetRelativePosition)
ENDIF
SET_CAM_ROT(camDetails.camInterpIDs[camDetails.iInterpCams], vCamRot)
SET_CAM_FOV(camDetails.camInterpIDs[camDetails.iInterpCams], GET_FINAL_RENDERED_CAM_FOV())
ADD_CAM_SPLINE_NODE_USING_CAMERA(camDetails.camID, camDetails.camInterpIDs[camDetails.iInterpCams], 0, CAM_SPLINE_NODE_SMOOTH_ROT)
camDetails.iInterpCams++
camDetails.iSplineDuration += 0
// Camera 5m above player
IF NOT DOES_CAM_EXIST(camDetails.camInterpIDs[camDetails.iInterpCams])
camDetails.camInterpIDs[camDetails.iInterpCams] = CREATE_CAM("DEFAULT_SCRIPTED_CAMERA", FALSE)
ENDIF
IF bPlayerVeh
vTargetRelativePosition = GET_OFFSET_FROM_ENTITY_GIVEN_WORLD_COORDS(vehPlayer, GET_FINAL_RENDERED_CAM_COORD())
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams], vehPlayer, vTargetRelativePosition+<<0.0, 0.0, 15.0>>)
ELSE
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams], PLAYER_PED_ID(), <<0.0, 0.0, 5.0>>, FALSE)
ENDIF
SET_CAM_ROT(camDetails.camInterpIDs[camDetails.iInterpCams], <<-87.5, 0.0, vCamRot.z>>)
SET_CAM_FOV(camDetails.camInterpIDs[camDetails.iInterpCams], GET_FINAL_RENDERED_CAM_FOV())
ADD_CAM_SPLINE_NODE_USING_CAMERA(camDetails.camID, camDetails.camInterpIDs[camDetails.iInterpCams], 400, CAM_SPLINE_NODE_SMOOTH_ROT)
camDetails.iInterpCams++
camDetails.iSplineDuration += 400
// Camera in sky above player
IF NOT DOES_CAM_EXIST(camDetails.camInterpIDs[camDetails.iInterpCams])
camDetails.camInterpIDs[camDetails.iInterpCams] = CREATE_CAM("DEFAULT_SCRIPTED_CAMERA", FALSE)
ENDIF
IF bPlayerVeh
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams], vehPlayer, <<0.0, 0.0, fMaxCamZ>> + vHorizontalDelta, FALSE)
ELSE
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams], PLAYER_PED_ID(), <<0.0, 0.0, fMaxCamZ>> + vHorizontalDelta, FALSE)
ENDIF
SET_CAM_ROT(camDetails.camInterpIDs[camDetails.iInterpCams], <<-87.5, 0.0, vCamRot.z >>)
SET_CAM_FOV(camDetails.camInterpIDs[camDetails.iInterpCams], GET_FINAL_RENDERED_CAM_FOV())
ADD_CAM_SPLINE_NODE_USING_CAMERA(camDetails.camID, camDetails.camInterpIDs[camDetails.iInterpCams], 800, CAM_SPLINE_NODE_SMOOTH_ROT)
camDetails.iInterpCams++
camDetails.iSplineDuration += 800
// Camera in sky above ped
IF NOT DOES_CAM_EXIST(camDetails.camInterpIDs[camDetails.iInterpCams])
camDetails.camInterpIDs[camDetails.iInterpCams] = CREATE_CAM("DEFAULT_SCRIPTED_CAMERA", FALSE)
ENDIF
IF bPedVeh
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams], vehPed, <<0.0, 0.0, fMaxCamZ>> - vHorizontalDelta, FALSE)
ELSE
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams], camDetails.pedTo, <<0.0, 0.0, fMaxCamZ>> - vHorizontalDelta, FALSE)
ENDIF
SET_CAM_ROT(camDetails.camInterpIDs[camDetails.iInterpCams], <<-87.5, 0.0, fRotZ >>)
SET_CAM_FOV(camDetails.camInterpIDs[camDetails.iInterpCams], GET_FINAL_RENDERED_CAM_FOV())
ADD_CAM_SPLINE_NODE_USING_CAMERA(camDetails.camID, camDetails.camInterpIDs[camDetails.iInterpCams], iDuration, CAM_SPLINE_NODE_SMOOTH_ROT)
camDetails.iInterpCams++
camDetails.iSplineDuration += iDuration
// Camera 5m above ped
IF NOT DOES_CAM_EXIST(camDetails.camInterpIDs[camDetails.iInterpCams])
camDetails.camInterpIDs[camDetails.iInterpCams] = CREATE_CAM("DEFAULT_SCRIPTED_CAMERA", FALSE)
ENDIF
IF bPedVeh
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams], vehPed, <<0.0, 0.0, 15.0>>, FALSE)
ELSE
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams], camDetails.pedTo, <<0.0, 0.0, 5.0>>, FALSE)
ENDIF
SET_CAM_ROT(camDetails.camInterpIDs[camDetails.iInterpCams], <<-87.5, 0.0, fRotZ>>)
SET_CAM_FOV(camDetails.camInterpIDs[camDetails.iInterpCams], GET_FINAL_RENDERED_CAM_FOV())
ADD_CAM_SPLINE_NODE_USING_CAMERA(camDetails.camID, camDetails.camInterpIDs[camDetails.iInterpCams], 800, CAM_SPLINE_NODE_SMOOTH_ROT)
camDetails.iInterpCams++
camDetails.iSplineDuration += 800
// Destination camera behind the ped
IF NOT DOES_CAM_EXIST(camDetails.camInterpIDs[camDetails.iInterpCams])
camDetails.camInterpIDs[camDetails.iInterpCams] = CREATE_CAM("DEFAULT_SCRIPTED_CAMERA", FALSE)
ENDIF
IF bPedVeh
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams], vehPed, GET_OFFSET_FOR_DEST_CAM(camDetails.pedTo))
ELSE
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams], camDetails.pedTo, GET_OFFSET_FOR_DEST_CAM(camDetails.pedTo))
ENDIF
SET_CAM_ROT(camDetails.camInterpIDs[camDetails.iInterpCams], << -0.951428, 0.0, fRotZ >>)
SET_CAM_FOV(camDetails.camInterpIDs[camDetails.iInterpCams], GET_FINAL_RENDERED_CAM_FOV())
ADD_CAM_SPLINE_NODE_USING_CAMERA(camDetails.camID, camDetails.camInterpIDs[camDetails.iInterpCams], 400, CAM_SPLINE_NODE_SMOOTH_ROT)
camDetails.iInterpCams++
camDetails.iSplineDuration += 400
camDetails.bSplineCreated = TRUE
BREAK
ENDSWITCH
ELSE
// Let scripter know that there is a problem
IF IS_PED_INJURED(PLAYER_PED_ID())
#IF IS_DEBUG_BUILD
SCRIPT_ASSERT("Cannot create spline cam as player is dead.")
PRINTSTRING("\nCannot create spline cam as player is dead.")PRINTNL()
#ENDIF
ELIF IS_PED_INJURED(camDetails.pedTo)
#IF IS_DEBUG_BUILD
SCRIPT_ASSERT("Cannot create spline cam as selector ped is dead.")
PRINTSTRING("\nCannot create spline cam as selector ped is dead.")PRINTNL()
#ENDIF
ENDIF
// Problem with peds so cleanup
camDetails.bSplineComplete = TRUE
ENDIF
ENDIF
///////////////////////////////////////////////////////
/// Activate the camera
IF camDetails.bSplineCreated
AND NOT camDetails.bSplineActive
IF DOES_CAM_EXIST(camDetails.camID)
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
AND NOT IS_PED_INJURED(camDetails.pedTo)
camDetails.pedFrom = PLAYER_PED_ID()
SET_PLAYER_CONTROL(PLAYER_ID(), FALSE)
SET_ENTITY_INVINCIBLE(camDetails.pedFrom, TRUE)
SET_ENTITY_INVINCIBLE(camDetails.pedTo, TRUE)
camDetails.bIsPhoneDisabled = IS_CELLPHONE_DISABLED()
DISABLE_CELLPHONE(TRUE)
// IF camDetails.camType = SELECTOR_CAM_SHORT_SPLINE
// OR camDetails.camType = SELECTOR_CAM_LONG_SPLINE
// //# 1524219
// CASCADE_SHADOWS_SET_AIRCRAFT_MODE(TRUE)
// PRINTLN("CASCADE_SHADOWS_SET_AIRCRAFT_MODE(TRUE) called by ", GET_THIS_SCRIPT_NAME())
// ENDIF
//
IF camDetails.iInterpCams > 0
FOR iCamCount = 0 TO camDetails.iInterpCams-1
SET_CAM_ACTIVE(camDetails.camInterpIDs[iCamCount], TRUE)
ENDFOR
ENDIF
TAKE_CONTROL_OF_TRANSITION(FALSE)
SET_CAM_ACTIVE(camDetails.camID, TRUE)
IF iInterpToCamOverride = 0
RENDER_SCRIPT_CAMS(true, FALSE)
ELif iInterpToCamOverride > 0
RENDER_SCRIPT_CAMS(true, TRUE, iInterpToCamOverride)
ENDIF
// SFX - Heading up
IF NOT g_sSelectorUI.bSFX_BlockAudioCalls
IF camDetails.camType = SELECTOR_CAM_LONG_SPLINE
PLAY_SOUND(-1, "CHARACTER_CHANGE_UP_MASTER")
PRINTLN("SWITCH UI - playing sound: CHARACTER_CHANGE_UP_MASTER")
IF (g_sSelectorUI.iSFX_Sky = -1)
g_sSelectorUI.iSFX_Sky = GET_SOUND_ID()
g_sSelectorUI.iSFX_Sky_ScriptHash = GET_HASH_KEY(GET_THIS_SCRIPT_NAME())
ENDIF
PLAY_SOUND(g_sSelectorUI.iSFX_Sky, "CHARACTER_CHANGE_SKY_MASTER")
PRINTLN("SWITCH UI - playing sound: CHARACTER_CHANGE_SKY_MASTER ", g_sSelectorUI.iSFX_Sky)
START_AUDIO_SCENE("CHARACTER_CHANGE_IN_SKY_SCENE")
IF IS_AUDIO_SCENE_ACTIVE("CHARACTER_CHANGE_IN_SKY_SCENE")
PRINTLN("CHARACTER_CHANGE_IN_SKY_SCENE...active!!!")
ELSE
PRINTLN("CHARACTER_CHANGE_IN_SKY_SCENE...is NOT active!!!")
ENDIF
ELIF camDetails.camType = SELECTOR_CAM_SHORT_SPLINE
IF (g_sSelectorUI.iSFX_Sky = -1)
g_sSelectorUI.iSFX_Sky = GET_SOUND_ID()
g_sSelectorUI.iSFX_Sky_ScriptHash = GET_HASH_KEY(GET_THIS_SCRIPT_NAME())
ENDIF
PLAY_SOUND(g_sSelectorUI.iSFX_Sky, "All", "SHORT_PLAYER_SWITCH_SOUND_SET")
PRINTLN("SWITCH UI - playing sound: All SHORT_PLAYER_SWITCH_SOUND_SET")
ENDIF
ENDIF
camDetails.fMaxHeight = GET_SELECTOR_CAM_Z_HEIGHT(camDetails.camID)
camDetails.iActivateTimer = GET_GAME_TIMER()
camDetails.bSplineActive = TRUE
SET_SELECTOR_CAM_ACTIVE(TRUE)
// Process player timecycle modifier
IF GET_ENTITY_MODEL(camDetails.pedTo) = GET_PLAYER_PED_MODEL(CHAR_MICHAEL)
SET_NEXT_PLAYER_TCMODIFIER(GET_PLAYER_PED_TIMECYCLE_MODIFIER(CHAR_MICHAEL))
ELIF GET_ENTITY_MODEL(camDetails.pedTo) = GET_PLAYER_PED_MODEL(CHAR_TREVOR)
SET_NEXT_PLAYER_TCMODIFIER(GET_PLAYER_PED_TIMECYCLE_MODIFIER(CHAR_TREVOR))
ELIF GET_ENTITY_MODEL(camDetails.pedTo) = GET_PLAYER_PED_MODEL(CHAR_FRANKLIN)
SET_NEXT_PLAYER_TCMODIFIER(GET_PLAYER_PED_TIMECYCLE_MODIFIER(CHAR_FRANKLIN))
ELSE
SET_NEXT_PLAYER_TCMODIFIER("")
ENDIF
SET_PLAYER_TCMODIFIER_TRANSITION(0.0)
ELSE
// Problem with peds so cleanup
camDetails.bSplineComplete = TRUE
#IF IS_DEBUG_BUILD
SCRIPT_ASSERT("Cannot activate spline camera as player or ped is dead.")
PRINTSTRING("\nCannot activate spline camera as player or ped is dead.")PRINTNL()
#ENDIF
ENDIF
ELSE
// Problem with camera so cleanup
camDetails.bSplineComplete = TRUE
#IF IS_DEBUG_BUILD
SCRIPT_ASSERT("Cannot activate spline camera as camera doesn't exist.")
PRINTSTRING("\nCannot activate spline camera as camera doesn't exist.")PRINTNL()
#ENDIF
ENDIF
ENDIF
///////////////////////////////////////////////////////
/// Cleanup when the spline has finished
IF camDetails.bSplineActive
IF DOES_CAM_EXIST(camDetails.camID)
// Update the player timecycle modifier
SET_PLAYER_TCMODIFIER_TRANSITION(GET_CAM_SPLINE_PHASE(camDetails.camID))
BOOL bOKToContinue = TRUE
IF camDetails.iInterpCams > 0
FOR iCamCount = 0 TO camDetails.iInterpCams-1
IF NOT DOES_CAM_EXIST(camDetails.camInterpIDs[iCamCount])
bOKToContinue = FALSE
ENDIF
ENDFOR
ENDIF
PRINTLN("GENERIC_PED_SCENE - (3) bOKToContinue: ", bOKToContinue)
IF bOKToContinue
PRINTLN("GENERIC_PED_SCENE - (3) IS_CAM_INTERPOLATING(camDetails.camID): ", IS_CAM_INTERPOLATING(camDetails.camID))
IF IS_CAM_INTERPOLATING(camDetails.camID)
// SFX - Heading down
IF NOT g_sSelectorUI.bSFX_BlockAudioCalls
IF camDetails.camType = SELECTOR_CAM_LONG_SPLINE
FLOAT fCurrentHeight = GET_SELECTOR_CAM_Z_HEIGHT(camDetails.camID)
IF (fCurrentHeight > camDetails.fMaxHeight)
camDetails.fMaxHeight = fCurrentHeight
ELIF (camDetails.fMaxHeight > fCurrentHeight+1.0)
IF g_sSelectorUI.iSFX_HeadDown = -1
g_sSelectorUI.iSFX_HeadDown = GET_SOUND_ID()
g_sSelectorUI.iSFX_HeadDown_ScriptHash = GET_HASH_KEY(GET_THIS_SCRIPT_NAME())
PLAY_SOUND(g_sSelectorUI.iSFX_HeadDown, "CHARACTER_CHANGE_DOWN_MASTER")
ENDIF
IF (g_sSelectorUI.iSFX_Sky != -1)
AND g_sSelectorUI.iSFX_Sky_ScriptHash = GET_HASH_KEY(GET_THIS_SCRIPT_NAME())
PRINTLN("SWITCH UI - stop iSFX_Sky ", g_sSelectorUI.iSFX_Sky)
STOP_SOUND(g_sSelectorUI.iSFX_Sky)
RELEASE_SOUND_ID(g_sSelectorUI.iSFX_Sky)
g_sSelectorUI.iSFX_Sky = -1
g_sSelectorUI.iSFX_Sky_ScriptHash = 0
STOP_AUDIO_SCENE("CHARACTER_CHANGE_IN_SKY_SCENE")
ENDIF
ENDIF
ENDIF
ENDIF
PRINTLN("GENERIC_PED_SCENE - (2) GET_CAM_SPLINE_PHASE(camDetails.camID): ", GET_CAM_SPLINE_PHASE(camDetails.camID))
PRINTLN("GENERIC_PED_SCENE - (2) IS_CAM_RENDERING(camDetails.camID): ", IS_CAM_RENDERING(camDetails.camID))
// Allow ped switch
IF GET_CAM_SPLINE_PHASE(camDetails.camID) > 0.5
AND IS_CAM_RENDERING(camDetails.camID)
camDetails.bOKToSwitchPed = TRUE
PRINTLN("GENERIC_PED_SCENE - Setting bOKToSwitchPed to TRUE (2)")
#IF IS_DEBUG_BUILD
DEBUG_PRINTCALLSTACK()
#ENDIF
ENDIF
// Update final spline node
IF camDetails.bOKToSwitchPed
IF PLAYER_PED_ID() = camDetails.pedTo
IF NOT IS_PED_INJURED(camDetails.pedTo)
IF camDetails.iInterpCams >= 1
IF DOES_CAM_EXIST(camDetails.camInterpIDs[camDetails.iInterpCams - 1])
IF IS_PED_IN_ANY_VEHICLE(camDetails.pedTo)
VEHICLE_INDEX vehPed = GET_VEHICLE_PED_IS_USING(camDetails.pedTo)
VECTOR vTargetRelativePosition = GET_OFFSET_FROM_ENTITY_GIVEN_WORLD_COORDS(vehPed, GET_GAMEPLAY_CAM_COORD())
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams - 1], vehPed, vTargetRelativePosition)
ELSE
VECTOR vTargetRelativePosition = GET_OFFSET_FROM_ENTITY_GIVEN_WORLD_COORDS(camDetails.pedTo, GET_GAMEPLAY_CAM_COORD())
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams - 1], camDetails.pedTo, vTargetRelativePosition)
ENDIF
SET_CAM_ROT(camDetails.camInterpIDs[camDetails.iInterpCams - 1], GET_GAMEPLAY_CAM_ROT())
SET_CAM_FOV(camDetails.camInterpIDs[camDetails.iInterpCams - 1], GET_GAMEPLAY_CAM_FOV())
bFinalNodeUpdated = TRUE
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ELSE
PRINTLN("GENERIC_PED_SCENE - (3) camDetails.bOKToSwitchPed: ", camDetails.bOKToSwitchPed)
// Allow ped switch
IF NOT camDetails.bOKToSwitchPed
camDetails.bOKToSwitchPed = TRUE
PRINTLN("GENERIC_PED_SCENE - Setting bOKToSwitchPed to TRUE (3)")
#IF IS_DEBUG_BUILD
DEBUG_PRINTCALLSTACK()
#ENDIF
ELSE
camDetails.bSplineComplete = TRUE
ENDIF
ENDIF
ENDIF
ELSE
// Problem with camera so cleanup
camDetails.bSplineComplete = TRUE
#IF IS_DEBUG_BUILD
SCRIPT_ASSERT("Cannot run spline camera as camera doesn't exist.")
PRINTSTRING("\nCannot run spline camera as camera doesn't exist.")PRINTNL()
#ENDIF
ENDIF
ENDIF
///////////////////////////////////////////////////////
/// Cleanup the camera
IF camDetails.bSplineComplete
IF DOES_CAM_EXIST(camDetails.camID)
DESTROY_CAM(camDetails.camID)
ENDIF
IF camDetails.iInterpCams > 0
FOR iCamCount = 0 TO camDetails.iInterpCams-1
IF DOES_CAM_EXIST(camDetails.camInterpIDs[iCamCount])
DESTROY_CAM(camDetails.camInterpIDs[iCamCount])
ENDIF
ENDFOR
ENDIF
DISABLE_CELLPHONE(camDetails.bIsPhoneDisabled)
// //# 1524219
// CASCADE_SHADOWS_SET_AIRCRAFT_MODE(FALSE)
// PRINTLN("CASCADE_SHADOWS_SET_AIRCRAFT_MODE(FALSE) called by ", GET_THIS_SCRIPT_NAME())
// Reset all the camera values incase they have to be used again
camDetails.bSplineCreated = FALSE
camDetails.bSplineActive = FALSE
camDetails.bSplineComplete = FALSE
camDetails.bOKToSwitchPed = FALSE
camDetails.bPedSwitched = FALSE
camDetails.bRun = FALSE
camDetails.iInterpCams = 0
camDetails.iSplineDuration = 0
// SFX - Cleanup
IF (g_sSelectorUI.iSFX_Sky != -1)
AND g_sSelectorUI.iSFX_Sky_ScriptHash = GET_HASH_KEY(GET_THIS_SCRIPT_NAME())
PRINTLN("SWITCH UI - stop iSFX_Sky ", g_sSelectorUI.iSFX_Sky)
STOP_SOUND(g_sSelectorUI.iSFX_Sky)
RELEASE_SOUND_ID(g_sSelectorUI.iSFX_Sky)
g_sSelectorUI.iSFX_Sky = -1
g_sSelectorUI.iSFX_Sky_ScriptHash = 0
ENDIF
IF (g_sSelectorUI.iSFX_HeadDown != -1)
AND g_sSelectorUI.iSFX_HeadDown_ScriptHash = GET_HASH_KEY(GET_THIS_SCRIPT_NAME())
STOP_SOUND(g_sSelectorUI.iSFX_HeadDown)
RELEASE_SOUND_ID(g_sSelectorUI.iSFX_HeadDown)
g_sSelectorUI.iSFX_HeadDown = -1
g_sSelectorUI.iSFX_HeadDown_ScriptHash = 0
ENDIF
// Set the relative heading/pitch if the calling scipt used a custom camera
// If specified out of range then do no set
IF fDestCamRelativeHeading <= 360 AND fDestCamRelativeHeading >= - 360
SET_GAMEPLAY_CAM_RELATIVE_HEADING(fDestCamRelativeHeading)
ENDIF
IF fDestCamRelativePitch <= 360 AND fDestCamRelativePitch >= -360
SET_GAMEPLAY_CAM_RELATIVE_PITCH(fDestCamRelativePitch)
ENDIF
IF NOT (g_drunkCameraActive)
STOP_GAMEPLAY_CAM_SHAKING(TRUE)
SET_GAMEPLAY_CAM_MOTION_BLUR_SCALING_THIS_UPDATE(0)
SET_GAMEPLAY_CAM_MAX_MOTION_BLUR_STRENGTH_THIS_UPDATE(0)
ENDIF
IF iInterpBackToGameDurationOverride = -1
IF bFinalNodeUpdated
RENDER_SCRIPT_CAMS(FALSE, TRUE, 100)
ELSE
RENDER_SCRIPT_CAMS(FALSE, TRUE, 1000)
ENDIF
ELSE
IF iInterpBackToGameDurationOverride = 0
RENDER_SCRIPT_CAMS(FALSE, FALSE)
ELSE
RENDER_SCRIPT_CAMS(FALSE, TRUE, iInterpBackToGameDurationOverride)
ENDIF
ENDIF
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
SET_PLAYER_CONTROL(PLAYER_ID(), TRUE)
SET_ENTITY_VISIBLE(PLAYER_PED_ID(), TRUE)
//FREEZE_ENTITY_POSITION(PLAYER_PED_ID(), FALSE)
SET_PED_CAN_BE_TARGETTED(PLAYER_PED_ID(), TRUE)
IF NOT IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
SET_ENTITY_COLLISION(PLAYER_PED_ID(), TRUE)
ENDIF
ENDIF
SET_SKYSWOOP_STAGE(SKYSWOOP_NONE)
// Reset proofs
IF NOT IS_PED_INJURED(camDetails.pedFrom)
SET_ENTITY_INVINCIBLE(camDetails.pedFrom, FALSE)
ENDIF
IF NOT IS_PED_INJURED(camDetails.pedTo)
SET_ENTITY_INVINCIBLE(camDetails.pedTo, FALSE)
ENDIF
// Update the player timecycle modifier
SET_CURRENT_PLAYER_TCMODIFIER(GET_PLAYER_PED_TIMECYCLE_MODIFIER(GET_CURRENT_PLAYER_PED_ENUM()))
SET_SELECTOR_CAM_ACTIVE(FALSE)
RETURN FALSE // Cam complete
ENDIF
// Hide the HUD
HIDE_HUD_AND_RADAR_THIS_FRAME()
//CLEAR_REMINDER_MESSAGE() //#1421176
RETURN TRUE // Cam still running
ENDFUNC
/// PURPOSE: Sets up a camera spline between player and scripted camera.
///
/// NOTES: camDetails.camID will be initialised/activated in this func.
/// Calling script should create a camera with valid coords/rot/fov etc. and assign it to camDetails.camTo.
/// Uses bool values to control the process and then returns FALSE when the spline is complete,
/// and the scripted camera becomes active.
/// Should be called each frame from calling script until FALSE is returned.
/// interpDurFinalCam sets the duration that it will take to interp to the final cam after running the spline
FUNC BOOL RUN_CAM_SPLINE_FROM_PLAYER_TO_CAM(SELECTOR_CAM_STRUCT &camDetails, INT interpDurFinalCam = 400,INT iInterpToCamOverride = 0)
INT iCamCount
///////////////////////////////////////////////////////
/// Setup the spline nodes
IF NOT camDetails.bSplineCreated
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
AND DOES_CAM_EXIST(camDetails.camTo)
camDetails.iSplineDuration = 0
INT iDuration
FLOAT fSkyNodeAngle, fMaxCamZ, fRotZ
BOOL bPlayerVeh
VEHICLE_INDEX vehPlayer
VECTOR vCamRot
VECTOR vTargetRelativePosition
VECTOR vHorizontalDelta
VECTOR vCamToPos = GET_CAM_COORD(camDetails.camTo)
VECTOR vPlayerPos = GET_ENTITY_COORDS(PLAYER_PED_ID())
FLOAT fPedDist2D = GET_DISTANCE_BETWEEN_COORDS(vPlayerPos, vCamToPos, FALSE)
FLOAT fPedDist3D = GET_DISTANCE_BETWEEN_COORDS(vPlayerPos, vCamToPos, TRUE)
// Make sure the spline camera has been created
IF NOT DOES_CAM_EXIST(camDetails.camID)
camDetails.camID = CREATE_CAM("DEFAULT_SPLINE_CAMERA", FALSE)
ENDIF
// Destory all the previous interp cams
FOR iCamCount = 0 TO NUM_SELECTOR_INTERP_CAMS-1
IF DOES_CAM_EXIST(camDetails.camInterpIDs[iCamCount])
DESTROY_CAM(camDetails.camInterpIDs[iCamCount])
ENDIF
ENDFOR
// Calculate the max node height
fMaxCamZ = 450.0
IF vPlayerPos.z > vCamToPos.z // Player higher
fMaxCamZ = FMAX(fMaxCamZ, vPlayerPos.z+25.0)
ELSE // Cam higher
fMaxCamZ = FMAX(fMaxCamZ, vCamToPos.z+25.0)
ENDIF
// Calculate the appropriate translation of the sky node towards the destination ped
fSkyNodeAngle = 20.0
vHorizontalDelta = vCamToPos - vPlayerPos
vHorizontalDelta.z = 0.0
vHorizontalDelta = GET_VECTOR_OF_LENGTH(vHorizontalDelta, FMIN(fMaxCamZ * TAN(fSkyNodeAngle), fPedDist2D / 3.0))
// Calculate the duration of the spline when up in the sky
fPedDist3D = CLAMP(fPedDist3D, 50.0, 4000.0)
iDuration = ROUND((fPedDist3D / ((4000.0 - 50.0) / (2000.0 - 1000.0)))+1000.0)
// Grab vehicle state and the final rotation
IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
vehPlayer = GET_VEHICLE_PED_IS_USING(PLAYER_PED_ID())
bPlayerVeh = TRUE
ENDIF
vCamRot = GET_CAM_ROT(camDetails.camTo)
fRotZ = vCamRot.z
IF fRotZ > 180.0
fRotZ -= 360.0
ENDIF
vCamRot = GET_FINAL_RENDERED_CAM_ROT()
// Initial camera behind the player
camDetails.iInterpCams = 0
SET_CAM_FOV(camDetails.camID, GET_FINAL_RENDERED_CAM_FOV())
IF NOT DOES_CAM_EXIST(camDetails.camInterpIDs[camDetails.iInterpCams])
camDetails.camInterpIDs[camDetails.iInterpCams] = CREATE_CAM("DEFAULT_SCRIPTED_CAMERA", FALSE)
ENDIF
IF bPlayerVeh
vTargetRelativePosition = GET_OFFSET_FROM_ENTITY_GIVEN_WORLD_COORDS(vehPlayer, GET_FINAL_RENDERED_CAM_COORD())
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams], vehPlayer, vTargetRelativePosition)
ELSE
vTargetRelativePosition = GET_OFFSET_FROM_ENTITY_GIVEN_WORLD_COORDS(PLAYER_PED_ID(), GET_FINAL_RENDERED_CAM_COORD())
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams], PLAYER_PED_ID(), vTargetRelativePosition)
ENDIF
SET_CAM_ROT(camDetails.camInterpIDs[camDetails.iInterpCams], vCamRot)
SET_CAM_FOV(camDetails.camInterpIDs[camDetails.iInterpCams], GET_FINAL_RENDERED_CAM_FOV())
ADD_CAM_SPLINE_NODE_USING_CAMERA(camDetails.camID, camDetails.camInterpIDs[camDetails.iInterpCams], 0, CAM_SPLINE_NODE_SMOOTH_ROT)
camDetails.iInterpCams++
camDetails.iSplineDuration += 0
// Camera 5m above player
IF NOT DOES_CAM_EXIST(camDetails.camInterpIDs[camDetails.iInterpCams])
camDetails.camInterpIDs[camDetails.iInterpCams] = CREATE_CAM("DEFAULT_SCRIPTED_CAMERA", FALSE)
ENDIF
IF bPlayerVeh
vTargetRelativePosition = GET_OFFSET_FROM_ENTITY_GIVEN_WORLD_COORDS(vehPlayer, GET_FINAL_RENDERED_CAM_COORD())
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams], vehPlayer, vTargetRelativePosition+<<0.0, 0.0, 15.0>>)
ELSE
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams], PLAYER_PED_ID(), <<0.0, 0.0, 5.0>>, FALSE)
ENDIF
SET_CAM_ROT(camDetails.camInterpIDs[camDetails.iInterpCams], <<-87.5, 0.0, vCamRot.z>>)
SET_CAM_FOV(camDetails.camInterpIDs[camDetails.iInterpCams], GET_FINAL_RENDERED_CAM_FOV())
ADD_CAM_SPLINE_NODE_USING_CAMERA(camDetails.camID, camDetails.camInterpIDs[camDetails.iInterpCams], 400, CAM_SPLINE_NODE_SMOOTH_ROT)
camDetails.iInterpCams++
camDetails.iSplineDuration += 400
// Camera in sky above player
IF NOT DOES_CAM_EXIST(camDetails.camInterpIDs[camDetails.iInterpCams])
camDetails.camInterpIDs[camDetails.iInterpCams] = CREATE_CAM("DEFAULT_SCRIPTED_CAMERA", FALSE)
ENDIF
IF bPlayerVeh
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams], vehPlayer, <<0.0, 0.0, fMaxCamZ>> + vHorizontalDelta, FALSE)
ELSE
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams], PLAYER_PED_ID(), <<0.0, 0.0, fMaxCamZ>> + vHorizontalDelta, FALSE)
ENDIF
SET_CAM_ROT(camDetails.camInterpIDs[camDetails.iInterpCams], <<-87.5, 0.0, vCamRot.z >>)
SET_CAM_FOV(camDetails.camInterpIDs[camDetails.iInterpCams], GET_FINAL_RENDERED_CAM_FOV())
ADD_CAM_SPLINE_NODE_USING_CAMERA(camDetails.camID, camDetails.camInterpIDs[camDetails.iInterpCams], 800, CAM_SPLINE_NODE_SMOOTH_ROT)
camDetails.iInterpCams++
camDetails.iSplineDuration += 800
// Camera in sky above cam
IF NOT DOES_CAM_EXIST(camDetails.camInterpIDs[camDetails.iInterpCams])
camDetails.camInterpIDs[camDetails.iInterpCams] = CREATE_CAM("DEFAULT_SCRIPTED_CAMERA", FALSE)
ENDIF
SET_CAM_COORD(camDetails.camInterpIDs[camDetails.iInterpCams], GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(GET_CAM_COORD(camDetails.camTo), fRotZ, <<0.0, 0.0, fMaxCamZ>> - vHorizontalDelta))
SET_CAM_ROT(camDetails.camInterpIDs[camDetails.iInterpCams], <<-87.5, 0.0, fRotZ >>)
SET_CAM_FOV(camDetails.camInterpIDs[camDetails.iInterpCams], GET_FINAL_RENDERED_CAM_FOV())
ADD_CAM_SPLINE_NODE_USING_CAMERA(camDetails.camID, camDetails.camInterpIDs[camDetails.iInterpCams], iDuration, CAM_SPLINE_NODE_SMOOTH_ROT)
camDetails.iInterpCams++
camDetails.iSplineDuration += iDuration
// Camera 5m above cam
IF NOT DOES_CAM_EXIST(camDetails.camInterpIDs[camDetails.iInterpCams])
camDetails.camInterpIDs[camDetails.iInterpCams] = CREATE_CAM("DEFAULT_SCRIPTED_CAMERA", FALSE)
ENDIF
SET_CAM_COORD(camDetails.camInterpIDs[camDetails.iInterpCams], GET_CAM_COORD(camDetails.camTo)+<<0.0, 0.0, 5.0>>)
SET_CAM_ROT(camDetails.camInterpIDs[camDetails.iInterpCams], <<-87.5, 0.0, fRotZ>>)
SET_CAM_FOV(camDetails.camInterpIDs[camDetails.iInterpCams], GET_FINAL_RENDERED_CAM_FOV())
ADD_CAM_SPLINE_NODE_USING_CAMERA(camDetails.camID, camDetails.camInterpIDs[camDetails.iInterpCams], 800, CAM_SPLINE_NODE_SMOOTH_ROT)
camDetails.iInterpCams++
camDetails.iSplineDuration += 800
// Destination camera at camTo position
IF NOT DOES_CAM_EXIST(camDetails.camInterpIDs[camDetails.iInterpCams])
camDetails.camInterpIDs[camDetails.iInterpCams] = CREATE_CAM("DEFAULT_SCRIPTED_CAMERA", FALSE)
ENDIF
SET_CAM_COORD(camDetails.camInterpIDs[camDetails.iInterpCams], GET_CAM_COORD(camDetails.camTo))
SET_CAM_ROT(camDetails.camInterpIDs[camDetails.iInterpCams], GET_CAM_ROT(camDetails.camTo))
SET_CAM_FOV(camDetails.camInterpIDs[camDetails.iInterpCams], GET_CAM_FOV(camDetails.camTo))
ADD_CAM_SPLINE_NODE_USING_CAMERA(camDetails.camID, camDetails.camInterpIDs[camDetails.iInterpCams], interpDurFinalCam, CAM_SPLINE_NODE_SMOOTH_ROT)
camDetails.iInterpCams++
camDetails.iSplineDuration += interpDurFinalCam
camDetails.bSplineCreated = TRUE
ELSE
// Problem with peds so cleanup
camDetails.bSplineComplete = TRUE
ENDIF
ENDIF
///////////////////////////////////////////////////////
/// Activate the camera
IF camDetails.bSplineCreated
AND NOT camDetails.bSplineActive
IF DOES_CAM_EXIST(camDetails.camID)
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
SET_PLAYER_CONTROL(PLAYER_ID(), FALSE)
camDetails.bIsPhoneDisabled = IS_CELLPHONE_DISABLED()
DISABLE_CELLPHONE(TRUE)
// //# 1524219
// CASCADE_SHADOWS_SET_AIRCRAFT_MODE(TRUE)
// PRINTLN("CASCADE_SHADOWS_SET_AIRCRAFT_MODE(TRUE) called by ", GET_THIS_SCRIPT_NAME())
IF camDetails.iInterpCams > 0
FOR iCamCount = 0 TO camDetails.iInterpCams-1
SET_CAM_ACTIVE(camDetails.camInterpIDs[iCamCount], TRUE)
ENDFOR
ENDIF
TAKE_CONTROL_OF_TRANSITION(FALSE)
SET_CAM_ACTIVE(camDetails.camID, TRUE)
//SET_WIDESCREEN_BORDERS(TRUE, 500)
if iInterpToCamOverride = 0
RENDER_SCRIPT_CAMS(TRUE, FALSE)
else
RENDER_SCRIPT_CAMS(TRUE, true,iInterpToCamOverride)
endif
// SFX - Heading up
IF NOT g_sSelectorUI.bSFX_BlockAudioCalls
IF camDetails.camType = SELECTOR_CAM_LONG_SPLINE
PLAY_SOUND(-1, "CHARACTER_CHANGE_UP_MASTER")
PRINTLN("SWITCH UI - playing sound: CHARACTER_CHANGE_UP_MASTER")
IF (g_sSelectorUI.iSFX_Sky = -1)
g_sSelectorUI.iSFX_Sky = GET_SOUND_ID()
g_sSelectorUI.iSFX_Sky_ScriptHash = GET_HASH_KEY(GET_THIS_SCRIPT_NAME())
ENDIF
PLAY_SOUND(g_sSelectorUI.iSFX_Sky, "CHARACTER_CHANGE_SKY_MASTER")
PRINTLN("SWITCH UI - playing sound: CHARACTER_CHANGE_SKY_MASTER ", g_sSelectorUI.iSFX_Sky)
START_AUDIO_SCENE("CHARACTER_CHANGE_IN_SKY_SCENE")
IF IS_AUDIO_SCENE_ACTIVE("CHARACTER_CHANGE_IN_SKY_SCENE")
PRINTLN("CHARACTER_CHANGE_IN_SKY_SCENE...active!!!")
ELSE
PRINTLN("CHARACTER_CHANGE_IN_SKY_SCENE...is NOT active!!!")
ENDIF
ENDIF
ENDIF
camDetails.fMaxHeight = GET_SELECTOR_CAM_Z_HEIGHT(camDetails.camID)
camDetails.iActivateTimer = GET_GAME_TIMER()
camDetails.bSplineActive = TRUE
SET_SELECTOR_CAM_ACTIVE(TRUE)
ELSE
// Problem with player so cleanup
camDetails.bSplineComplete = TRUE
ENDIF
ELSE
// Problem with camera so cleanup
camDetails.bSplineComplete = TRUE
ENDIF
ENDIF
///////////////////////////////////////////////////////
/// Cleanup when the spline has finished
IF camDetails.bSplineActive
IF DOES_CAM_EXIST(camDetails.camID)
BOOL bOKToContinue = TRUE
IF camDetails.iInterpCams > 0
FOR iCamCount = 0 TO camDetails.iInterpCams-1
IF NOT DOES_CAM_EXIST(camDetails.camInterpIDs[iCamCount])
bOKToContinue = FALSE
ENDIF
ENDFOR
ENDIF
PRINTLN("GENERIC_PED_SCENE - (4) bOKToContinue: ", bOKToContinue)
IF bOKToContinue
PRINTLN("GENERIC_PED_SCENE - (4) IS_CAM_INTERPOLATING(camDetails.camID): ", IS_CAM_INTERPOLATING(camDetails.camID))
IF IS_CAM_INTERPOLATING(camDetails.camID)
// SFX - Heading down
IF NOT g_sSelectorUI.bSFX_BlockAudioCalls
IF camDetails.camType = SELECTOR_CAM_LONG_SPLINE
FLOAT fCurrentHeight = GET_SELECTOR_CAM_Z_HEIGHT(camDetails.camID)
IF (fCurrentHeight > camDetails.fMaxHeight)
camDetails.fMaxHeight = fCurrentHeight
ELIF (camDetails.fMaxHeight > fCurrentHeight+1.0)
IF g_sSelectorUI.iSFX_HeadDown = -1
g_sSelectorUI.iSFX_HeadDown = GET_SOUND_ID()
g_sSelectorUI.iSFX_HeadDown_ScriptHash = GET_HASH_KEY(GET_THIS_SCRIPT_NAME())
PLAY_SOUND(g_sSelectorUI.iSFX_HeadDown, "CHARACTER_CHANGE_DOWN_MASTER")
PRINTLN("SWITCH UI - playing sound: CHARACTER_CHANGE_DOWN_MASTER")
ENDIF
IF (g_sSelectorUI.iSFX_Sky != -1)
AND g_sSelectorUI.iSFX_Sky_ScriptHash = GET_HASH_KEY(GET_THIS_SCRIPT_NAME())
PRINTLN("SWITCH UI - stop iSFX_Sky ", g_sSelectorUI.iSFX_Sky)
STOP_SOUND(g_sSelectorUI.iSFX_Sky)
RELEASE_SOUND_ID(g_sSelectorUI.iSFX_Sky)
g_sSelectorUI.iSFX_Sky = -1
g_sSelectorUI.iSFX_Sky_ScriptHash = 0
STOP_AUDIO_SCENE("CHARACTER_CHANGE_IN_SKY_SCENE")
ENDIF
ENDIF
ENDIF
ENDIF
PRINTLN("GENERIC_PED_SCENE - (4) GET_CAM_SPLINE_PHASE(camDetails.camID): ", GET_CAM_SPLINE_PHASE(camDetails.camID))
PRINTLN("GENERIC_PED_SCENE - (4) IS_CAM_RENDERING(camDetails.camID): ", IS_CAM_RENDERING(camDetails.camID))
// Allow ped switch
IF GET_CAM_SPLINE_PHASE(camDetails.camID) > 0.5
AND IS_CAM_RENDERING(camDetails.camID)
camDetails.bOKToSwitchPed = TRUE
PRINTLN("GENERIC_PED_SCENE - Setting bOKToSwitchPed to TRUE (4)")
#IF IS_DEBUG_BUILD
DEBUG_PRINTCALLSTACK()
#ENDIF
ENDIF
ELSE
camDetails.bSplineComplete = TRUE
ENDIF
ENDIF
ELSE
// Problem with camera so cleanup
camDetails.bSplineComplete = TRUE
ENDIF
ENDIF
////////////////////////////////////////////////////////////////////
/// Cleanup the spline camera and activate scripted camera
IF camDetails.bSplineComplete
IF DOES_CAM_EXIST(camDetails.camID)
DESTROY_CAM(camDetails.camID)
ENDIF
IF camDetails.iInterpCams > 0
FOR iCamCount = 0 TO camDetails.iInterpCams-1
IF DOES_CAM_EXIST(camDetails.camInterpIDs[iCamCount])
DESTROY_CAM(camDetails.camInterpIDs[iCamCount])
ENDIF
ENDFOR
ENDIF
// Reset all the camera values incase they have to be used again
camDetails.bSplineCreated = FALSE
camDetails.bSplineActive = FALSE
camDetails.bSplineComplete = FALSE
camDetails.bOKToSwitchPed = FALSE
camDetails.bPedSwitched = FALSE
camDetails.bRun = FALSE
camDetails.iInterpCams = 0
camDetails.iSplineDuration = 0
// SFX - Cleanup
IF (g_sSelectorUI.iSFX_Sky != -1)
AND g_sSelectorUI.iSFX_Sky_ScriptHash = GET_HASH_KEY(GET_THIS_SCRIPT_NAME())
PRINTLN("SWITCH UI - stop iSFX_Sky ", g_sSelectorUI.iSFX_Sky)
STOP_SOUND(g_sSelectorUI.iSFX_Sky)
RELEASE_SOUND_ID(g_sSelectorUI.iSFX_Sky)
g_sSelectorUI.iSFX_Sky = -1
g_sSelectorUI.iSFX_Sky_ScriptHash = 0
ENDIF
IF (g_sSelectorUI.iSFX_HeadDown != -1)
AND g_sSelectorUI.iSFX_HeadDown_ScriptHash = GET_HASH_KEY(GET_THIS_SCRIPT_NAME())
STOP_SOUND(g_sSelectorUI.iSFX_HeadDown)
RELEASE_SOUND_ID(g_sSelectorUI.iSFX_HeadDown)
g_sSelectorUI.iSFX_HeadDown = -1
g_sSelectorUI.iSFX_HeadDown_ScriptHash = 0
ENDIF
DISABLE_CELLPHONE(camDetails.bIsPhoneDisabled)
// //# 1524219
// CASCADE_SHADOWS_SET_AIRCRAFT_MODE(FALSE)
// PRINTLN("CASCADE_SHADOWS_SET_AIRCRAFT_MODE(FALSE) called by ", GET_THIS_SCRIPT_NAME())
// This func will end with the scripted camera being set to active
IF DOES_CAM_EXIST(camDetails.camTo)
SET_CAM_ACTIVE(camDetails.camTo, TRUE)
ENDIF
SET_SELECTOR_CAM_ACTIVE(FALSE)
RETURN FALSE // Cam complete
ENDIF
// Hide the HUD
HIDE_HUD_AND_RADAR_THIS_FRAME()
//CLEAR_REMINDER_MESSAGE() //#1421176
RETURN TRUE // Cam still running
ENDFUNC
/// PURPOSE: Sets up a camera spline between player and a camera positioned in the sky
///
/// NOTES: camDetails.camID will be initialised/activated in this func.
/// Calling script should create a camera with valid coords/rot/fov etc. and assign it to camDetails.camSky.
/// Uses bool values to control the process and then returns FALSE when the spline is complete,
/// and the scripted camera becomes active.
/// Should be called each frame from calling script until FALSE is returned.
FUNC BOOL RUN_CAM_SPLINE_FROM_PLAYER_TO_SKY_CAM(SELECTOR_CAM_STRUCT &camDetails, FLOAT fSpeedMultiplier = 1.0)
INT iCamCount
///////////////////////////////////////////////////////
/// Setup the spline nodes
IF NOT camDetails.bSplineCreated
//IF NOT IS_PED_INJURED(PLAYER_PED_ID())
IF DOES_CAM_EXIST(camDetails.camSky)
camDetails.iSplineDuration = 0
INT iDuration
FLOAT fDist3D
VECTOR vCamRot, vTargetRelativePosition
BOOL bPlayerVeh
VEHICLE_INDEX vehPlayer
PED_INDEX pedPlayer
IF IS_A_SPECTATOR_CAM_ACTIVE() = FALSE
pedPlayer = PLAYER_PED_ID()
ELSE
pedPlayer = GET_SPECTATOR_CURRENT_FOCUS_PED()
ENDIF
// Make sure the spline camera has been created
IF DOES_CAM_EXIST(camDetails.camID)
DESTROY_CAM(camDetails.camID)
ENDIF
camDetails.camID = CREATE_CAM("DEFAULT_SPLINE_CAMERA", FALSE)
// Destory all the previous interp cams
FOR iCamCount = 0 TO NUM_SELECTOR_INTERP_CAMS-1
IF DOES_CAM_EXIST(camDetails.camInterpIDs[iCamCount])
DESTROY_CAM(camDetails.camInterpIDs[iCamCount])
ENDIF
ENDFOR
// Calculate the duration of the spline
IF NOT IS_ENTITY_DEAD(pedPlayer)
fDist3D = GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(pedPlayer),GET_CAM_COORD(camDetails.camSky))
ELSE
fDist3D = GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(pedPlayer, FALSE),GET_CAM_COORD(camDetails.camSky))
ENDIF
fDist3D = CLAMP(fDist3D, 50.0, 4000.0)
iDuration = ROUND( (( fDist3D / ((4000.0 - 50.0) / (2000.0 - 1000.0)))+400.0) * fSpeedMultiplier )
// Grab vehicle state and the final rotation
IF IS_PED_IN_ANY_VEHICLE(pedPlayer)
vehPlayer = GET_VEHICLE_PED_IS_USING(pedPlayer)
bPlayerVeh = TRUE
ENDIF
vCamRot = GET_FINAL_RENDERED_CAM_ROT()
// Initial camera behind the player
camDetails.iInterpCams = 0
SET_CAM_FOV(camDetails.camID, GET_FINAL_RENDERED_CAM_FOV())
IF NOT DOES_CAM_EXIST(camDetails.camInterpIDs[camDetails.iInterpCams])
camDetails.camInterpIDs[camDetails.iInterpCams] = CREATE_CAM("DEFAULT_SCRIPTED_CAMERA", FALSE)
ENDIF
IF bPlayerVeh
vTargetRelativePosition = GET_OFFSET_FROM_ENTITY_GIVEN_WORLD_COORDS(vehPlayer, GET_FINAL_RENDERED_CAM_COORD())
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams], vehPlayer, vTargetRelativePosition)
ELSE
vTargetRelativePosition = GET_OFFSET_FROM_ENTITY_GIVEN_WORLD_COORDS(pedPlayer, GET_FINAL_RENDERED_CAM_COORD())
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams], pedPlayer, vTargetRelativePosition)
ENDIF
SET_CAM_ROT(camDetails.camInterpIDs[camDetails.iInterpCams], vCamRot)
SET_CAM_FOV(camDetails.camInterpIDs[camDetails.iInterpCams], GET_FINAL_RENDERED_CAM_FOV())
ADD_CAM_SPLINE_NODE_USING_CAMERA(camDetails.camID, camDetails.camInterpIDs[camDetails.iInterpCams], 0, CAM_SPLINE_NODE_SMOOTH_ROT)
camDetails.iInterpCams++
camDetails.iSplineDuration += 0
// Camera 5m above player
IF NOT DOES_CAM_EXIST(camDetails.camInterpIDs[camDetails.iInterpCams])
camDetails.camInterpIDs[camDetails.iInterpCams] = CREATE_CAM("DEFAULT_SCRIPTED_CAMERA", FALSE)
ENDIF
IF bPlayerVeh
vTargetRelativePosition = GET_OFFSET_FROM_ENTITY_GIVEN_WORLD_COORDS(vehPlayer, GET_FINAL_RENDERED_CAM_COORD())
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams], vehPlayer, vTargetRelativePosition+<<0.0, 0.0, 15.0>>)
ELSE
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams], pedPlayer, <<0.0, 0.0, 5.0>>, FALSE)
ENDIF
SET_CAM_ROT(camDetails.camInterpIDs[camDetails.iInterpCams], <<-87.5, 0.0, vCamRot.z>>)
SET_CAM_FOV(camDetails.camInterpIDs[camDetails.iInterpCams], GET_FINAL_RENDERED_CAM_FOV())
ADD_CAM_SPLINE_NODE_USING_CAMERA(camDetails.camID, camDetails.camInterpIDs[camDetails.iInterpCams], 400, CAM_SPLINE_NODE_SMOOTH_ROT)
camDetails.iInterpCams++
camDetails.iSplineDuration += 400
// Camera 75m above player
IF NOT DOES_CAM_EXIST(camDetails.camInterpIDs[camDetails.iInterpCams])
camDetails.camInterpIDs[camDetails.iInterpCams] = CREATE_CAM("DEFAULT_SCRIPTED_CAMERA", FALSE)
ENDIF
IF bPlayerVeh
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams], vehPlayer, <<0.0, 0.0, 75.0>>, FALSE)
ELSE
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams], pedPlayer, <<0.0, 0.0, 75.0>>, FALSE)
ENDIF
SET_CAM_ROT(camDetails.camInterpIDs[camDetails.iInterpCams], <<-87.5, 0.0, vCamRot.z>>)
SET_CAM_FOV(camDetails.camInterpIDs[camDetails.iInterpCams], GET_FINAL_RENDERED_CAM_FOV())
ADD_CAM_SPLINE_NODE_USING_CAMERA(camDetails.camID, camDetails.camInterpIDs[camDetails.iInterpCams], 400, CAM_SPLINE_NODE_SMOOTH_ROT)
camDetails.iInterpCams++
camDetails.iSplineDuration += 400
// Camera in sky at the specified location
// VECTOR EndCamPos = GET_CAM_COORD(camDetails.camSky)
// EndCamPos.x = 0
VECTOR EndCamRos = GET_CAM_ROT(camDetails.camSky)
EndCamRos.x = 21 //17 // 15
ADD_CAM_SPLINE_NODE(camDetails.camID, GET_CAM_COORD(camDetails.camSky), EndCamRos, iDuration)
camDetails.iSplineDuration += iDuration
camDetails.bSplineCreated = TRUE
ELSE
NET_NL()NET_PRINT("Problem with camera: camDetails.camSky doesn't exist ")
// Problem with player ped or sky cam so cleanup
camDetails.bSplineComplete = TRUE
ENDIF
ENDIF
///////////////////////////////////////////////////////
/// Activate the camera
IF camDetails.bSplineCreated
AND NOT camDetails.bSplineActive
IF DOES_CAM_EXIST(camDetails.camID)
// IF NOT IS_PED_INJURED(PLAYER_PED_ID())
// SET_PLAYER_CONTROL(PLAYER_ID(), FALSE)
// camDetails.bIsPhoneDisabled = IS_CELLPHONE_DISABLED()
IF camDetails.iInterpCams > 0
FOR iCamCount = 0 TO camDetails.iInterpCams-1
SET_CAM_ACTIVE(camDetails.camInterpIDs[iCamCount], TRUE)
ENDFOR
ENDIF
SET_CAM_ACTIVE(camDetails.camID, TRUE)
RENDER_SCRIPT_CAMS(TRUE, FALSE)
// IF NETWORK_IS_IN_SESSION()
// camDetails.iMPActivateTimer =
// ELSE
// camDetails.iMPActivateTimer = GET_GAME_TIMER()
// ENDIF
// SFX - Heading up
IF NOT g_sSelectorUI.bSFX_BlockAudioCalls
PLAY_SOUND(-1, "CHARACTER_CHANGE_UP_MASTER")
PRINTLN("SWITCH UI - playing sound: CHARACTER_CHANGE_UP_MASTER")
IF (g_sSelectorUI.iSFX_Sky = -1)
g_sSelectorUI.iSFX_Sky = GET_SOUND_ID()
g_sSelectorUI.iSFX_Sky_ScriptHash = GET_HASH_KEY(GET_THIS_SCRIPT_NAME())
ENDIF
PLAY_SOUND(g_sSelectorUI.iSFX_Sky, "CHARACTER_CHANGE_SKY_MASTER")
PRINTLN("SWITCH UI - playing sound: CHARACTER_CHANGE_SKY_MASTER ", g_sSelectorUI.iSFX_Sky)
START_AUDIO_SCENE("CHARACTER_CHANGE_IN_SKY_SCENE")
IF IS_AUDIO_SCENE_ACTIVE("CHARACTER_CHANGE_IN_SKY_SCENE")
PRINTLN("CHARACTER_CHANGE_IN_SKY_SCENE...active!!!")
ELSE
PRINTLN("CHARACTER_CHANGE_IN_SKY_SCENE...is NOT active!!!")
ENDIF
ENDIF
camDetails.fMaxHeight = GET_SELECTOR_CAM_Z_HEIGHT(camDetails.camID)
camDetails.bSplineActive = TRUE
SET_SELECTOR_CAM_ACTIVE(TRUE)
// ELSE
// NET_NL()NET_PRINT("Problem with Transition camera: Player is injured")
// Problem with player so cleanup
// camDetails.bSplineComplete = TRUE
// ENDIF
ELSE
NET_NL()NET_PRINT("Problem with Transition camera: camDetails.camID doesn't exist ")
// Problem with camera so cleanup
camDetails.bSplineComplete = TRUE
ENDIF
ENDIF
///////////////////////////////////////////////////////
/// Cleanup when the spline has finished
IF camDetails.bSplineActive
IF DOES_CAM_EXIST(camDetails.camID)
BOOL bOKToContinue = TRUE
IF camDetails.iInterpCams > 0
FOR iCamCount = 0 TO camDetails.iInterpCams-1
IF NOT DOES_CAM_EXIST(camDetails.camInterpIDs[iCamCount])
bOKToContinue = FALSE
ENDIF
ENDFOR
ENDIF
PRINTLN("GENERIC_PED_SCENE - (5) bOKToContinue: ", bOKToContinue)
IF bOKToContinue
PRINTLN("GENERIC_PED_SCENE - (5) IS_CAM_INTERPOLATING(camDetails.camID): ", IS_CAM_INTERPOLATING(camDetails.camID))
IF IS_CAM_INTERPOLATING(camDetails.camID)
PRINTLN("GENERIC_PED_SCENE - (5) GET_CAM_SPLINE_PHASE(camDetails.camID): ", GET_CAM_SPLINE_PHASE(camDetails.camID))
PRINTLN("GENERIC_PED_SCENE - (5) IS_CAM_RENDERING(camDetails.camID): ", IS_CAM_RENDERING(camDetails.camID))
// Allow ped switch
IF GET_CAM_SPLINE_PHASE(camDetails.camID) > 0.5
AND IS_CAM_RENDERING(camDetails.camID)
camDetails.bOKToSwitchPed = TRUE
PRINTLN("GENERIC_PED_SCENE - Setting bOKToSwitchPed to TRUE (5)")
#IF IS_DEBUG_BUILD
DEBUG_PRINTCALLSTACK()
#ENDIF
ENDIF
ELSE
NET_NL()NET_PRINT("RUN_CAM_SPLINE_FROM_PLAYER_TO_SKY_CAM: IS_CAM_INTERPOLATING = FALSE Completed Spline ")
camDetails.bSplineComplete = TRUE
ENDIF
ENDIF
ELSE
NET_NL()NET_PRINT("Problem with Transition camera: camDetails.camID doesn't exist second ")
// Problem with camera so cleanup
camDetails.bSplineComplete = TRUE
ENDIF
ENDIF
///////////////////////////////////////////////////////
/// Cleanup the camera
IF camDetails.bSplineComplete
NET_NL()NET_PRINT("Cleanup the Transition camera")
IF DOES_CAM_EXIST(camDetails.camID)
// copy over details to the camSky
IF DOES_CAM_EXIST(camDetails.camSky)
g_TransitionData.vSkyCamPos = GET_CAM_COORD(camDetails.camID)
g_TransitionData.vSkyCamRot = GET_CAM_ROT(camDetails.camID)
g_TransitionData.fSkyCamFOV = GET_CAM_FOV(camDetails.camID)
SET_CAM_COORD(camDetails.camSky, g_TransitionData.vSkyCamPos)
SET_CAM_ROT(camDetails.camSky, g_TransitionData.vSkyCamRot)
SET_CAM_FOV(camDetails.camSky, g_TransitionData.fSkyCamFOV)
ENDIF
DESTROY_CAM(camDetails.camID)
ENDIF
IF camDetails.iInterpCams > 0
FOR iCamCount = 0 TO camDetails.iInterpCams-1
IF DOES_CAM_EXIST(camDetails.camInterpIDs[iCamCount])
DESTROY_CAM(camDetails.camInterpIDs[iCamCount])
ENDIF
ENDFOR
ENDIF
// Reset all the camera values incase they have to be used again
camDetails.bSplineCreated = FALSE
camDetails.bSplineActive = FALSE
camDetails.bSplineComplete = FALSE
camDetails.bOKToSwitchPed = FALSE
camDetails.bPedSwitched = FALSE
camDetails.bRun = FALSE
camDetails.iInterpCams = 0
camDetails.iSplineDuration = 0
// SFX - Cleanup
IF (g_sSelectorUI.iSFX_Sky != -1)
AND g_sSelectorUI.iSFX_Sky_ScriptHash = GET_HASH_KEY(GET_THIS_SCRIPT_NAME())
PRINTLN("SWITCH UI - stop iSFX_Sky ", g_sSelectorUI.iSFX_Sky)
STOP_SOUND(g_sSelectorUI.iSFX_Sky)
RELEASE_SOUND_ID(g_sSelectorUI.iSFX_Sky)
g_sSelectorUI.iSFX_Sky = -1
g_sSelectorUI.iSFX_Sky_ScriptHash = 0
ENDIF
// Reset the gameplay cam state
SET_GAMEPLAY_CAM_RELATIVE_HEADING(0)
SET_GAMEPLAY_CAM_RELATIVE_PITCH(0)
IF NOT (g_drunkCameraActive)
STOP_GAMEPLAY_CAM_SHAKING(TRUE)
SET_GAMEPLAY_CAM_MOTION_BLUR_SCALING_THIS_UPDATE(0)
SET_GAMEPLAY_CAM_MAX_MOTION_BLUR_STRENGTH_THIS_UPDATE(0)
ENDIF
// This func will end with the scripted camera being set to active
IF DOES_CAM_EXIST(camDetails.camSky)
SET_CAM_ACTIVE(camDetails.camSky, TRUE)
ENDIF
SET_SELECTOR_CAM_ACTIVE(FALSE)
RETURN FALSE // Cam complete
ENDIF
// Hide the HUD
HIDE_HUD_AND_RADAR_THIS_FRAME()
//CLEAR_REMINDER_MESSAGE() //#1421176
RETURN TRUE // Cam still running
ENDFUNC
/// PURPOSE: Sets up a camera spline between the active camer which should be in the sky and the player
///
/// NOTES: camDetails.camID will be initialised/activated in this func.
/// Calling script should ensure that camDetails.camSky is the current active camera.
/// Uses bool values to control the process and then returns FALSE when the spline is complete.
/// Should be called each frame from calling script until FALSE is returned.
FUNC BOOL RUN_CAM_SPLINE_FROM_SKY_TO_PLAYER(SELECTOR_CAM_STRUCT &camDetails, FLOAT fPlayerLocationHeight)
BOOL bFinalNodeUpdated
INT iCamCount
VECTOR vSkyCamCoord = <<99999, 99999, 99999>>
///////////////////////////////////////////////////////
/// Setup the spline nodes
IF NOT camDetails.bSplineCreated
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
AND DOES_CAM_EXIST(camDetails.camSky)
camDetails.iSplineDuration = 0
INT iDuration
FLOAT fDist3D, fRotZ
VECTOR vCamPos, vPlayerPos, vTargetRelativePosition
BOOL bPlayerVeh
VEHICLE_INDEX vehPlayer
// Make sure the spline camera has been created
IF DOES_CAM_EXIST(camDetails.camID)
DESTROY_CAM(camDetails.camID)
ENDIF
camDetails.camID = CREATE_CAM("DEFAULT_SPLINE_CAMERA", FALSE)
// Destory all the previous interp cams
FOR iCamCount = 0 TO NUM_SELECTOR_INTERP_CAMS-1
IF DOES_CAM_EXIST(camDetails.camInterpIDs[iCamCount])
DESTROY_CAM(camDetails.camInterpIDs[iCamCount])
ENDIF
ENDFOR
// Calculate the duration of the spline
vCamPos = GET_CAM_COORD(camDetails.camSky)
IF NOT IS_ENTITY_DEAD(PLAYER_PED_ID())
vPlayerPos = GET_ENTITY_COORDS(PLAYER_PED_ID())
ELSE
vPlayerPos = GET_ENTITY_COORDS(PLAYER_PED_ID(), FALSE)
ENDIF
fDist3D = GET_DISTANCE_BETWEEN_COORDS(vPlayerPos, vCamPos)
fDist3D = CLAMP(fDist3D, 50.0, 4000.0)
iDuration = ROUND( (( fDist3D / ((4000.0 - 50.0) / (2000.0 - 1000.0)))+1000.0))
// Grab vehicle state and the final rotation
IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
vehPlayer = GET_VEHICLE_PED_IS_USING(PLAYER_PED_ID())
bPlayerVeh = TRUE
fRotZ = GET_ENTITY_HEADING(vehPlayer)
IF fRotZ > 180.0
fRotZ -= 360.0
ENDIF
ELSE
fRotZ = GET_ENTITY_HEADING(PLAYER_PED_ID())
IF fRotZ > 180.0
fRotZ -= 360.0
ENDIF
ENDIF
// Initial camera is a copy of the active camera
camDetails.iInterpCams = 0
SET_CAM_FOV(camDetails.camID, GET_CAM_FOV(camDetails.camSky))
ADD_CAM_SPLINE_NODE(camDetails.camID, GET_CAM_COORD(camDetails.camSky), GET_CAM_ROT(camDetails.camSky), 0, CAM_SPLINE_NODE_SMOOTH_ROT)
camDetails.iSplineDuration += 0
// Camera in sky above player
IF NOT DOES_CAM_EXIST(camDetails.camInterpIDs[camDetails.iInterpCams])
camDetails.camInterpIDs[camDetails.iInterpCams] = CREATE_CAM("DEFAULT_SCRIPTED_CAMERA", FALSE)
ENDIF
IF bPlayerVeh
vTargetRelativePosition = GET_OFFSET_FROM_ENTITY_GIVEN_WORLD_COORDS(vehPlayer, << vPlayerPos.x, vPlayerPos.y, vCamPos.z >>)
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams], vehPlayer, vTargetRelativePosition, FALSE)
ELSE
vTargetRelativePosition = GET_OFFSET_FROM_ENTITY_GIVEN_WORLD_COORDS(PLAYER_PED_ID(), << vPlayerPos.x, vPlayerPos.y, vCamPos.z >>)
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams], PLAYER_PED_ID(), vTargetRelativePosition, FALSE)
ENDIF
SET_CAM_ROT(camDetails.camInterpIDs[camDetails.iInterpCams], <<-87.5, 0.0, fRotZ >>)
SET_CAM_FOV(camDetails.camInterpIDs[camDetails.iInterpCams], GET_FINAL_RENDERED_CAM_FOV())
ADD_CAM_SPLINE_NODE_USING_CAMERA(camDetails.camID, camDetails.camInterpIDs[camDetails.iInterpCams], iDuration, CAM_SPLINE_NODE_SMOOTH_ROT)
camDetails.iInterpCams++
camDetails.iSplineDuration += iDuration
// Camera 85m above player
IF NOT DOES_CAM_EXIST(camDetails.camInterpIDs[camDetails.iInterpCams])
camDetails.camInterpIDs[camDetails.iInterpCams] = CREATE_CAM("DEFAULT_SCRIPTED_CAMERA", FALSE)
ENDIF
IF bPlayerVeh
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams], vehPlayer, <<0.0, 0.0, 85.0>>, FALSE)
ELSE
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams], PLAYER_PED_ID(), <<0.0, 0.0, 85.0>>, FALSE)
ENDIF
SET_CAM_ROT(camDetails.camInterpIDs[camDetails.iInterpCams], <<-87.5, 0.0, fRotZ>>)
SET_CAM_FOV(camDetails.camInterpIDs[camDetails.iInterpCams], GET_FINAL_RENDERED_CAM_FOV())
ADD_CAM_SPLINE_NODE_USING_CAMERA(camDetails.camID, camDetails.camInterpIDs[camDetails.iInterpCams], 800, CAM_SPLINE_NODE_SMOOTH_ROT)
camDetails.iInterpCams++
camDetails.iSplineDuration += 800
// Camera 5m above player
IF NOT DOES_CAM_EXIST(camDetails.camInterpIDs[camDetails.iInterpCams])
camDetails.camInterpIDs[camDetails.iInterpCams] = CREATE_CAM("DEFAULT_SCRIPTED_CAMERA", FALSE)
ENDIF
IF bPlayerVeh
vTargetRelativePosition = GET_OFFSET_FROM_ENTITY_GIVEN_WORLD_COORDS(vehPlayer, GET_FINAL_RENDERED_CAM_COORD())
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams], vehPlayer, vTargetRelativePosition+<<0.0, 0.0, 15.0>>)
ELSE
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams], PLAYER_PED_ID(), <<0.0, 0.0, 5.0>>, FALSE)
ENDIF
SET_CAM_ROT(camDetails.camInterpIDs[camDetails.iInterpCams], <<-87.5, 0.0, fRotZ>>)
SET_CAM_FOV(camDetails.camInterpIDs[camDetails.iInterpCams], GET_FINAL_RENDERED_CAM_FOV())
ADD_CAM_SPLINE_NODE_USING_CAMERA(camDetails.camID, camDetails.camInterpIDs[camDetails.iInterpCams], 800, CAM_SPLINE_NODE_SMOOTH_ROT)
camDetails.iInterpCams++
camDetails.iSplineDuration += 800
// Destination camera behind the ped
IF NOT DOES_CAM_EXIST(camDetails.camInterpIDs[camDetails.iInterpCams])
camDetails.camInterpIDs[camDetails.iInterpCams] = CREATE_CAM("DEFAULT_SCRIPTED_CAMERA", FALSE)
ENDIF
IF bPlayerVeh
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams], vehPlayer, GET_OFFSET_FOR_DEST_CAM(PLAYER_PED_ID()))
ELSE
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams], PLAYER_PED_ID(), GET_OFFSET_FOR_DEST_CAM(PLAYER_PED_ID()))
ENDIF
SET_CAM_ROT(camDetails.camInterpIDs[camDetails.iInterpCams], << -0.951428, 0.0, fRotZ >>)
SET_CAM_FOV(camDetails.camInterpIDs[camDetails.iInterpCams], GET_FINAL_RENDERED_CAM_FOV())
ADD_CAM_SPLINE_NODE_USING_CAMERA(camDetails.camID, camDetails.camInterpIDs[camDetails.iInterpCams], 400, CAM_SPLINE_NODE_SMOOTH_ROT)
camDetails.iInterpCams++
camDetails.iSplineDuration += 400
camDetails.bSplineCreated = TRUE
ELSE
// Problem with player ped so cleanup
camDetails.bSplineComplete = TRUE
ENDIF
ENDIF
///////////////////////////////////////////////////////
/// Activate the camera
IF camDetails.bSplineCreated
AND NOT camDetails.bSplineActive
IF DOES_CAM_EXIST(camDetails.camID)
IF DOES_CAM_EXIST(camDetails.camSky)
DESTROY_CAM(camDetails.camSky)
ENDIF
// IF NOT IS_PED_INJURED(PLAYER_PED_ID())
// SET_PLAYER_CONTROL(PLAYER_ID(), FALSE)
IF camDetails.iInterpCams > 0
FOR iCamCount = 0 TO camDetails.iInterpCams-1
SET_CAM_ACTIVE(camDetails.camInterpIDs[iCamCount], TRUE)
ENDFOR
ENDIF
SET_CAM_ACTIVE(camDetails.camID, TRUE)
RENDER_SCRIPT_CAMS(TRUE, FALSE)
// SFX - Heading down
IF NOT g_sSelectorUI.bSFX_BlockAudioCalls
PLAY_SOUND(-1, "CHARACTER_CHANGE_DOWN_MASTER")
PRINTLN("SWITCH UI - playing sound: CHARACTER_CHANGE_DOWN_MASTER")
IF g_sSelectorUI.iSFX_Sky != -1
AND g_sSelectorUI.iSFX_Sky_ScriptHash = GET_HASH_KEY(GET_THIS_SCRIPT_NAME())
PRINTLN("SWITCH UI - stop iSFX_Sky ", g_sSelectorUI.iSFX_Sky)
STOP_SOUND(g_sSelectorUI.iSFX_Sky)
RELEASE_SOUND_ID(g_sSelectorUI.iSFX_Sky)
g_sSelectorUI.iSFX_Sky = -1
g_sSelectorUI.iSFX_Sky_ScriptHash = 0
STOP_AUDIO_SCENE("CHARACTER_CHANGE_IN_SKY_SCENE")
ENDIF
ENDIF
camDetails.bSplineActive = TRUE
SET_SELECTOR_CAM_ACTIVE(TRUE)
// Process player timecycle modifier
IF GET_ENTITY_MODEL(PLAYER_PED_ID()) = GET_PLAYER_PED_MODEL(CHAR_MICHAEL)
SET_NEXT_PLAYER_TCMODIFIER(GET_PLAYER_PED_TIMECYCLE_MODIFIER(CHAR_MICHAEL))
ELIF GET_ENTITY_MODEL(PLAYER_PED_ID()) = GET_PLAYER_PED_MODEL(CHAR_TREVOR)
SET_NEXT_PLAYER_TCMODIFIER(GET_PLAYER_PED_TIMECYCLE_MODIFIER(CHAR_TREVOR))
ELIF GET_ENTITY_MODEL(PLAYER_PED_ID()) = GET_PLAYER_PED_MODEL(CHAR_FRANKLIN)
SET_NEXT_PLAYER_TCMODIFIER(GET_PLAYER_PED_TIMECYCLE_MODIFIER(CHAR_FRANKLIN))
ELSE
SET_NEXT_PLAYER_TCMODIFIER("")
ENDIF
SET_PLAYER_TCMODIFIER_TRANSITION(0.0)
// ELSE
// // Problem with player so cleanup
// camDetails.bSplineComplete = TRUE
// ENDIF
ELSE
// Problem with camera so cleanup
camDetails.bSplineComplete = TRUE
ENDIF
ENDIF
///////////////////////////////////////////////////////
/// Cleanup when the spline has finished
IF camDetails.bSplineActive
IF DOES_CAM_EXIST(camDetails.camID)
// Update the player timecycle modifier
SET_PLAYER_TCMODIFIER_TRANSITION(GET_CAM_SPLINE_PHASE(camDetails.camID))
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
IF GET_ROOM_KEY_FROM_ENTITY(PLAYER_PED_ID()) != 0
vSkyCamCoord = GET_CAM_COORD(camDetails.camID)
IF vSkyCamCoord.z <= 0
vSkyCamCoord.z = 99999
ENDIF
//NET_NL()NET_PRINT(" - CHECK B - PLAYER IN INTERIOR - vSkyCamCoord.z = ")NET_PRINT_FLOAT(vSkyCamCoord.z)NET_PRINT(" fPlayerLocationHeight = ")NET_PRINT_FLOAT(fPlayerLocationHeight)NET_NL()
ENDIF
//NET_NL()NET_PRINT(" - CHECK B - RoomKey = ")NET_PRINT_INT(GET_ROOM_KEY_FROM_ENTITY(PLAYER_PED_ID()))NET_NL()
ENDIF
IF vSkyCamCoord.z < fPlayerLocationHeight
camDetails.bSplineComplete = TRUE
NET_PRINT("vSkyCamCoord.z < fPlayerLocationHeight - camDetails.bSplineComplete = TRUE")
ELSE
BOOL bOKToContinue = TRUE
IF camDetails.iInterpCams > 0
FOR iCamCount = 0 TO camDetails.iInterpCams-1
IF NOT DOES_CAM_EXIST(camDetails.camInterpIDs[iCamCount])
bOKToContinue = FALSE
ENDIF
ENDFOR
ENDIF
IF bOKToContinue
IF IS_CAM_INTERPOLATING(camDetails.camID)
// Update final spline node
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
IF camDetails.iInterpCams >= 1
IF DOES_CAM_EXIST(camDetails.camInterpIDs[camDetails.iInterpCams - 1])
IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
VEHICLE_INDEX vehPed = GET_VEHICLE_PED_IS_USING(PLAYER_PED_ID())
VECTOR vTargetRelativePosition = GET_OFFSET_FROM_ENTITY_GIVEN_WORLD_COORDS(vehPed, GET_GAMEPLAY_CAM_COORD())
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams - 1], vehPed, vTargetRelativePosition)
ELSE
VECTOR vTargetRelativePosition = GET_OFFSET_FROM_ENTITY_GIVEN_WORLD_COORDS(PLAYER_PED_ID(), GET_GAMEPLAY_CAM_COORD())
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams - 1], PLAYER_PED_ID(), vTargetRelativePosition)
ENDIF
SET_CAM_ROT(camDetails.camInterpIDs[camDetails.iInterpCams - 1], GET_GAMEPLAY_CAM_ROT())
SET_CAM_FOV(camDetails.camInterpIDs[camDetails.iInterpCams - 1], GET_GAMEPLAY_CAM_FOV())
bFinalNodeUpdated = TRUE
ENDIF
ENDIF
ENDIF
ELSE
camDetails.bSplineComplete = TRUE
ENDIF
ENDIF
ENDIF
ELSE
// Problem with camera so cleanup
camDetails.bSplineComplete = TRUE
ENDIF
ENDIF
///////////////////////////////////////////////////////
/// Cleanup the camera
IF camDetails.bSplineComplete
IF DOES_CAM_EXIST(camDetails.camID)
DESTROY_CAM(camDetails.camID)
ENDIF
IF camDetails.iInterpCams > 0
FOR iCamCount = 0 TO camDetails.iInterpCams-1
IF DOES_CAM_EXIST(camDetails.camInterpIDs[iCamCount])
DESTROY_CAM(camDetails.camInterpIDs[iCamCount])
ENDIF
ENDFOR
ENDIF
// Reset all the camera values incase they have to be used again
camDetails.bSplineCreated = FALSE
camDetails.bSplineActive = FALSE
camDetails.bSplineComplete = FALSE
camDetails.bOKToSwitchPed = FALSE
camDetails.bPedSwitched = FALSE
camDetails.bRun = FALSE
camDetails.iInterpCams = 0
camDetails.iSplineDuration = 0
// SFX - Cleanup
IF (g_sSelectorUI.iSFX_Sky != -1)
AND g_sSelectorUI.iSFX_Sky_ScriptHash = GET_HASH_KEY(GET_THIS_SCRIPT_NAME())
PRINTLN("SWITCH UI - stop iSFX_Sky ", g_sSelectorUI.iSFX_Sky)
STOP_SOUND(g_sSelectorUI.iSFX_Sky)
RELEASE_SOUND_ID(g_sSelectorUI.iSFX_Sky)
g_sSelectorUI.iSFX_Sky = -1
g_sSelectorUI.iSFX_Sky_ScriptHash = 0
ENDIF
IF (g_sSelectorUI.iSFX_HeadDown != -1)
AND g_sSelectorUI.iSFX_HeadDown_ScriptHash = GET_HASH_KEY(GET_THIS_SCRIPT_NAME())
STOP_SOUND(g_sSelectorUI.iSFX_HeadDown)
RELEASE_SOUND_ID(g_sSelectorUI.iSFX_HeadDown)
g_sSelectorUI.iSFX_HeadDown = -1
g_sSelectorUI.iSFX_HeadDown_ScriptHash = 0
ENDIF
SET_GAMEPLAY_CAM_RELATIVE_HEADING(g_SpawnData.fCamHeading)
SET_GAMEPLAY_CAM_RELATIVE_PITCH(0)
IF NOT (g_drunkCameraActive)
STOP_GAMEPLAY_CAM_SHAKING(TRUE)
SET_GAMEPLAY_CAM_MOTION_BLUR_SCALING_THIS_UPDATE(0)
SET_GAMEPLAY_CAM_MAX_MOTION_BLUR_STRENGTH_THIS_UPDATE(0)
ENDIF
g_SpawnData.fCamHeading = 0.0
//Check if we should do the game cam interp
BOOL bGameCamInterp = FALSE
IF vSkyCamCoord.z = 99999
bGameCamInterp = TRUE
ENDIF
IF bFinalNodeUpdated
RENDER_SCRIPT_CAMS(FALSE, bGameCamInterp, 100, TRUE, TRUE)
ELSE
RENDER_SCRIPT_CAMS(FALSE, bGameCamInterp, 1000, TRUE, TRUE)
ENDIF
IF NOT NETWORK_IS_GAME_IN_PROGRESS()// only do this in sp - added by NeilF 27/06/2011
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
SET_PLAYER_CONTROL(PLAYER_ID(), TRUE)
SET_PLAYER_INVINCIBLE(PLAYER_ID(), FALSE)
SET_ENTITY_VISIBLE(PLAYER_PED_ID(), TRUE)
//FREEZE_ENTITY_POSITION(PLAYER_PED_ID(), FALSE)
SET_PED_CAN_BE_TARGETTED(PLAYER_PED_ID(), TRUE)
IF NOT IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
SET_ENTITY_COLLISION(PLAYER_PED_ID(), TRUE)
ENDIF
ClearInsideDisplacedInteriorFlag()
ENDIF
ENDIF
SET_SELECTOR_CAM_ACTIVE(FALSE)
// Update the player timecycle modifier
SET_CURRENT_PLAYER_TCMODIFIER(GET_PLAYER_PED_TIMECYCLE_MODIFIER(GET_CURRENT_PLAYER_PED_ENUM()))
RETURN FALSE // Cam complete
ENDIF
// Hide the HUD
HIDE_HUD_AND_RADAR_THIS_FRAME()
//CLEAR_REMINDER_MESSAGE() //#1421176
RETURN TRUE // Cam still running
ENDFUNC
/// PURPOSE: Sets up a camera spline between player and a camera positioned in the sky
///
/// NOTES: camDetails.camID will be initialised/activated in this func.
/// Calling script should create a camera with valid coords/rot/fov etc. and assign it to camDetails.camSky.
/// Uses bool values to control the process and then returns FALSE when the spline is complete,
/// and the scripted camera becomes active.
/// Should be called each frame from calling script until FALSE is returned.
FUNC BOOL RUN_CAM_SPLINE_FROM_RENDERED_CAM_TO_SKY_CAM(SELECTOR_CAM_STRUCT &camDetails, FLOAT fSpeedMultiplier = 1.0)
INT iCamCount
///////////////////////////////////////////////////////
/// Setup the spline nodes
IF NOT camDetails.bSplineCreated
//IF NOT IS_PED_INJURED(PLAYER_PED_ID())
IF DOES_CAM_EXIST(camDetails.camSky)
camDetails.iSplineDuration = 0
INT iDuration
FLOAT fDist3D
VECTOR vCamRot
// Make sure the spline camera has been created
IF DOES_CAM_EXIST(camDetails.camID)
DESTROY_CAM(camDetails.camID)
ENDIF
camDetails.camID = CREATE_CAM("DEFAULT_SPLINE_CAMERA", FALSE)
// Destory all the previous interp cams
FOR iCamCount = 0 TO NUM_SELECTOR_INTERP_CAMS-1
IF DOES_CAM_EXIST(camDetails.camInterpIDs[iCamCount])
DESTROY_CAM(camDetails.camInterpIDs[iCamCount])
ENDIF
ENDFOR
// Calculate the duration of the spline
fDist3D = GET_DISTANCE_BETWEEN_COORDS(GET_FINAL_RENDERED_CAM_COORD(),GET_CAM_COORD(camDetails.camSky))
fDist3D = CLAMP(fDist3D, 50.0, 4000.0)
iDuration = ROUND( (( fDist3D / ((4000.0 - 50.0) / (2000.0 - 1000.0)))+400.0) * fSpeedMultiplier )
// Grab the final rotation
vCamRot = GET_FINAL_RENDERED_CAM_ROT()
// Initial camera is a copy of the final rendered cam
camDetails.iInterpCams = 0
SET_CAM_FOV(camDetails.camID, GET_FINAL_RENDERED_CAM_FOV())
IF NOT DOES_CAM_EXIST(camDetails.camInterpIDs[camDetails.iInterpCams])
camDetails.camInterpIDs[camDetails.iInterpCams] = CREATE_CAM("DEFAULT_SCRIPTED_CAMERA", FALSE)
ENDIF
SET_CAM_COORD(camDetails.camInterpIDs[camDetails.iInterpCams], GET_FINAL_RENDERED_CAM_COORD())
SET_CAM_ROT(camDetails.camInterpIDs[camDetails.iInterpCams], GET_FINAL_RENDERED_CAM_ROT())
SET_CAM_FOV(camDetails.camInterpIDs[camDetails.iInterpCams], GET_FINAL_RENDERED_CAM_FOV())
ADD_CAM_SPLINE_NODE_USING_CAMERA(camDetails.camID, camDetails.camInterpIDs[camDetails.iInterpCams], 0, CAM_SPLINE_NODE_SMOOTH_ROT)
camDetails.iInterpCams++
camDetails.iSplineDuration += 0
// Camera 5m above cam
IF NOT DOES_CAM_EXIST(camDetails.camInterpIDs[camDetails.iInterpCams])
camDetails.camInterpIDs[camDetails.iInterpCams] = CREATE_CAM("DEFAULT_SCRIPTED_CAMERA", FALSE)
ENDIF
SET_CAM_COORD(camDetails.camInterpIDs[camDetails.iInterpCams], GET_FINAL_RENDERED_CAM_COORD() + <<0.0, 0.0, 5.0>>)
SET_CAM_ROT(camDetails.camInterpIDs[camDetails.iInterpCams], <<-87.5, 0.0, vCamRot.z>>)
SET_CAM_FOV(camDetails.camInterpIDs[camDetails.iInterpCams], GET_FINAL_RENDERED_CAM_FOV())
ADD_CAM_SPLINE_NODE_USING_CAMERA(camDetails.camID, camDetails.camInterpIDs[camDetails.iInterpCams], 400, CAM_SPLINE_NODE_SMOOTH_ROT)
camDetails.iInterpCams++
camDetails.iSplineDuration += 400
// Camera 75m above cam
IF NOT DOES_CAM_EXIST(camDetails.camInterpIDs[camDetails.iInterpCams])
camDetails.camInterpIDs[camDetails.iInterpCams] = CREATE_CAM("DEFAULT_SCRIPTED_CAMERA", FALSE)
ENDIF
SET_CAM_COORD(camDetails.camInterpIDs[camDetails.iInterpCams], GET_FINAL_RENDERED_CAM_COORD() + <<0.0, 0.0, 75.0>>)
SET_CAM_ROT(camDetails.camInterpIDs[camDetails.iInterpCams], <<-87.5, 0.0, vCamRot.z>>)
SET_CAM_FOV(camDetails.camInterpIDs[camDetails.iInterpCams], GET_FINAL_RENDERED_CAM_FOV())
ADD_CAM_SPLINE_NODE_USING_CAMERA(camDetails.camID, camDetails.camInterpIDs[camDetails.iInterpCams], 400, CAM_SPLINE_NODE_SMOOTH_ROT)
camDetails.iInterpCams++
camDetails.iSplineDuration += 400
// Camera in sky at the specified location
// VECTOR EndCamPos = GET_CAM_COORD(camDetails.camSky)
// EndCamPos.x = 0
VECTOR EndCamRos = GET_CAM_ROT(camDetails.camSky)
EndCamRos.x = 17 // 15
ADD_CAM_SPLINE_NODE(camDetails.camID, GET_CAM_COORD(camDetails.camSky), EndCamRos, iDuration)
camDetails.iSplineDuration += iDuration
camDetails.bSplineCreated = TRUE
ELSE
NET_NL()NET_PRINT("Problem with camera: camDetails.camSky doesn't exist ")
// Problem with player ped or sky cam so cleanup
camDetails.bSplineComplete = TRUE
ENDIF
ENDIF
///////////////////////////////////////////////////////
/// Activate the camera
IF camDetails.bSplineCreated
AND NOT camDetails.bSplineActive
IF DOES_CAM_EXIST(camDetails.camID)
// IF NOT IS_PED_INJURED(PLAYER_PED_ID())
// SET_PLAYER_CONTROL(PLAYER_ID(), FALSE)
// camDetails.bIsPhoneDisabled = IS_CELLPHONE_DISABLED()
IF camDetails.iInterpCams > 0
FOR iCamCount = 0 TO camDetails.iInterpCams-1
SET_CAM_ACTIVE(camDetails.camInterpIDs[iCamCount], TRUE)
ENDFOR
ENDIF
SET_CAM_ACTIVE(camDetails.camID, TRUE)
RENDER_SCRIPT_CAMS(TRUE, FALSE)
IF NETWORK_IS_IN_SESSION()
camDetails.iActivateTimerNetwork = GET_NETWORK_TIME()
ELSE
camDetails.iActivateTimer = GET_GAME_TIMER()
ENDIF
// SFX - Heading up
IF NOT g_sSelectorUI.bSFX_BlockAudioCalls
PLAY_SOUND(-1, "CHARACTER_CHANGE_UP_MASTER")
PRINTLN("SWITCH UI - playing sound: CHARACTER_CHANGE_UP_MASTER")
IF (g_sSelectorUI.iSFX_Sky = -1)
g_sSelectorUI.iSFX_Sky = GET_SOUND_ID()
g_sSelectorUI.iSFX_Sky_ScriptHash = GET_HASH_KEY(GET_THIS_SCRIPT_NAME())
ENDIF
PLAY_SOUND(g_sSelectorUI.iSFX_Sky, "CHARACTER_CHANGE_SKY_MASTER")
PRINTLN("SWITCH UI - playing sound: CHARACTER_CHANGE_SKY_MASTER ", g_sSelectorUI.iSFX_Sky)
START_AUDIO_SCENE("CHARACTER_CHANGE_IN_SKY_SCENE")
IF IS_AUDIO_SCENE_ACTIVE("CHARACTER_CHANGE_IN_SKY_SCENE")
PRINTLN("CHARACTER_CHANGE_IN_SKY_SCENE...active!!!")
ELSE
PRINTLN("CHARACTER_CHANGE_IN_SKY_SCENE...is NOT active!!!")
ENDIF
ENDIF
camDetails.fMaxHeight = GET_SELECTOR_CAM_Z_HEIGHT(camDetails.camID)
camDetails.bSplineActive = TRUE
SET_SELECTOR_CAM_ACTIVE(TRUE)
// ELSE
// NET_NL()NET_PRINT("Problem with Transition camera: Player is injured")
// Problem with player so cleanup
// camDetails.bSplineComplete = TRUE
// ENDIF
ELSE
NET_NL()NET_PRINT("Problem with Transition camera: camDetails.camID doesn't exist ")
// Problem with camera so cleanup
camDetails.bSplineComplete = TRUE
ENDIF
ENDIF
///////////////////////////////////////////////////////
/// Cleanup when the spline has finished
IF camDetails.bSplineActive
IF DOES_CAM_EXIST(camDetails.camID)
BOOL bOKToContinue = TRUE
IF camDetails.iInterpCams > 0
FOR iCamCount = 0 TO camDetails.iInterpCams-1
IF NOT DOES_CAM_EXIST(camDetails.camInterpIDs[iCamCount])
bOKToContinue = FALSE
ENDIF
ENDFOR
ENDIF
PRINTLN("GENERIC_PED_SCENE - (6) bOKToContinue: ", bOKToContinue)
IF bOKToContinue
PRINTLN("GENERIC_PED_SCENE - (6) IS_CAM_INTERPOLATING(camDetails.camID): ", IS_CAM_INTERPOLATING(camDetails.camID))
IF IS_CAM_INTERPOLATING(camDetails.camID)
PRINTLN("GENERIC_PED_SCENE - (6) GET_CAM_SPLINE_PHASE(camDetails.camID): ", GET_CAM_SPLINE_PHASE(camDetails.camID))
PRINTLN("GENERIC_PED_SCENE - (6) IS_CAM_RENDERING(camDetails.camID): ", IS_CAM_RENDERING(camDetails.camID))
// Allow ped switch
IF GET_CAM_SPLINE_PHASE(camDetails.camID) > 0.5
AND IS_CAM_RENDERING(camDetails.camID)
camDetails.bOKToSwitchPed = TRUE
PRINTLN("GENERIC_PED_SCENE - Setting bOKToSwitchPed to TRUE (6)")
#IF IS_DEBUG_BUILD
DEBUG_PRINTCALLSTACK()
#ENDIF
ENDIF
ELSE
NET_NL()NET_PRINT("RUN_CAM_SPLINE_FROM_PLAYER_TO_SKY_CAM: IS_CAM_INTERPOLATING = FALSE Completed Spline ")
camDetails.bSplineComplete = TRUE
ENDIF
ENDIF
ELSE
NET_NL()NET_PRINT("Problem with Transition camera: camDetails.camID doesn't exist second ")
// Problem with camera so cleanup
camDetails.bSplineComplete = TRUE
ENDIF
ENDIF
///////////////////////////////////////////////////////
/// Cleanup the camera
IF camDetails.bSplineComplete
NET_NL()NET_PRINT("Cleanup the Transition camera")
IF DOES_CAM_EXIST(camDetails.camID)
// copy over details to the camSky
IF DOES_CAM_EXIST(camDetails.camSky)
g_TransitionData.vSkyCamPos = GET_CAM_COORD(camDetails.camID)
g_TransitionData.vSkyCamRot = GET_CAM_ROT(camDetails.camID)
g_TransitionData.fSkyCamFOV = GET_CAM_FOV(camDetails.camID)
SET_CAM_COORD(camDetails.camSky, g_TransitionData.vSkyCamPos)
SET_CAM_ROT(camDetails.camSky, g_TransitionData.vSkyCamRot)
SET_CAM_FOV(camDetails.camSky, g_TransitionData.fSkyCamFOV)
ENDIF
DESTROY_CAM(camDetails.camID)
ENDIF
IF camDetails.iInterpCams > 0
FOR iCamCount = 0 TO camDetails.iInterpCams-1
IF DOES_CAM_EXIST(camDetails.camInterpIDs[iCamCount])
DESTROY_CAM(camDetails.camInterpIDs[iCamCount])
ENDIF
ENDFOR
ENDIF
// Reset all the camera values incase they have to be used again
camDetails.bSplineCreated = FALSE
camDetails.bSplineActive = FALSE
camDetails.bSplineComplete = FALSE
camDetails.bOKToSwitchPed = FALSE
camDetails.bPedSwitched = FALSE
camDetails.bRun = FALSE
camDetails.iInterpCams = 0
camDetails.iSplineDuration = 0
// SFX - Cleanup
IF (g_sSelectorUI.iSFX_Sky != -1)
AND g_sSelectorUI.iSFX_Sky_ScriptHash = GET_HASH_KEY(GET_THIS_SCRIPT_NAME())
PRINTLN("SWITCH UI - stop iSFX_Sky ", g_sSelectorUI.iSFX_Sky)
STOP_SOUND(g_sSelectorUI.iSFX_Sky)
RELEASE_SOUND_ID(g_sSelectorUI.iSFX_Sky)
g_sSelectorUI.iSFX_Sky = -1
g_sSelectorUI.iSFX_Sky_ScriptHash = 0
ENDIF
// Reset the gameplay cam state
SET_GAMEPLAY_CAM_RELATIVE_HEADING(0)
SET_GAMEPLAY_CAM_RELATIVE_PITCH(0)
IF NOT (g_drunkCameraActive)
STOP_GAMEPLAY_CAM_SHAKING(TRUE)
SET_GAMEPLAY_CAM_MOTION_BLUR_SCALING_THIS_UPDATE(0)
SET_GAMEPLAY_CAM_MAX_MOTION_BLUR_STRENGTH_THIS_UPDATE(0)
ENDIF
// This func will end with the scripted camera being set to active
IF DOES_CAM_EXIST(camDetails.camSky)
SET_CAM_ACTIVE(camDetails.camSky, TRUE)
ENDIF
SET_SELECTOR_CAM_ACTIVE(FALSE)
RETURN FALSE // Cam complete
ENDIF
// Hide the HUD
HIDE_HUD_AND_RADAR_THIS_FRAME()
//CLEAR_REMINDER_MESSAGE() //#1421176
RETURN TRUE // Cam still running
ENDFUNC
#IF IS_DEBUG_BUILD
FUNC STRING DEBUG_GET_PLAYER_SWITCH_STATE(SWITCH_STATE eState)
SWITCH eState
CASE SWITCH_STATE_INTRO RETURN "SWITCH_STATE_INTRO"
CASE SWITCH_STATE_PREP_DESCENT RETURN "SWITCH_STATE_PREP_DESCENT"
CASE SWITCH_STATE_PREP_FOR_CUT RETURN "SWITCH_STATE_PREP_FOR_CUT"
CASE SWITCH_STATE_JUMPCUT_ASCENT RETURN "SWITCH_STATE_JUMPCUT_ASCENT"
CASE SWITCH_STATE_WAITFORINPUT_INTRO RETURN "SWITCH_STATE_WAITFORINPUT_INTRO"
CASE SWITCH_STATE_WAITFORINPUT RETURN "SWITCH_STATE_WAITFORINPUT"
CASE SWITCH_STATE_WAITFORINPUT_OUTRO RETURN "SWITCH_STATE_WAITFORINPUT_OUTRO"
CASE SWITCH_STATE_PAN RETURN "SWITCH_STATE_PAN"
CASE SWITCH_STATE_JUMPCUT_DESCENT RETURN "SWITCH_STATE_JUMPCUT_DESCENT"
CASE SWITCH_STATE_OUTRO_HOLD RETURN "SWITCH_STATE_OUTRO_HOLD"
CASE SWITCH_STATE_OUTRO_SWOOP RETURN "SWITCH_STATE_OUTRO_SWOOP"
CASE SWITCH_STATE_ESTABLISHING_SHOT RETURN "SWITCH_STATE_ESTABLISHING_SHOT"
CASE SWITCH_STATE_FINISHED RETURN "SWITCH_STATE_FINISHED"
ENDSWITCH
RETURN ""
ENDFUNC
#ENDIF
PROC naughty_SET_VEHICLE_LIMIT_SPEED_WHEN_PLAYER_INACTIVE(VEHICLE_INDEX VehicleIndex, BOOL bVal)
IF IS_ENTITY_A_MISSION_ENTITY(VehicleIndex)
SET_VEHICLE_LIMIT_SPEED_WHEN_PLAYER_INACTIVE(VehicleIndex, bVal)
ELSE
SET_ENTITY_AS_MISSION_ENTITY(VehicleIndex, TRUE, FALSE)
SET_VEHICLE_LIMIT_SPEED_WHEN_PLAYER_INACTIVE(VehicleIndex, bVal)
SET_VEHICLE_AS_NO_LONGER_NEEDED(VehicleIndex)
ENDIF
ENDPROC
/// PURPOSE:
FUNC BOOL PRIVATE_RunPlayerSwitch(SELECTOR_CAM_STRUCT &camDetails,
CAMERA_INDEX camTo, SWITCH_TYPE eSwitchType = SWITCH_TYPE_AUTO,
INT iSwitchFlags = 0,
FLOAT fDestCamRelativePitch = 999.0,FLOAT fDestCamRelativeHeading = 999.0,
BOOL bPauseBeforePan = FALSE, BOOL bPauseBeforeOutro = FALSE, STRING establishingShotName = NULL,
EULER_ROT_ORDER RotOrder = EULER_YXZ, BOOL bMultiplayerSwitch = FALSE, BOOL bOverrideShortRangeSwitchStyle = FALSE, SHORT_SWITCH_STYLE shortRangeSwitchStyle = SHORT_SWITCH_STYLE_ROTATION)
SWITCH_FLAGS eSwitchFlags = INT_TO_ENUM(SWITCH_FLAGS, iSwitchFlags)
///////////////////////////////////////////////////////
/// Activate the camera
IF NOT camDetails.bSplineActive
//#1362143 & #1374002
IF IS_SAFE_TO_START_PLAYER_SWITCH()
IF NOT bMultiplayerSwitch
camDetails.pedFrom = PLAYER_PED_ID() //Always from player
ENDIF
IF (NOT IS_PED_INJURED(camDetails.pedFrom) OR bMultiplayerSwitch)
AND NOT IS_PED_INJURED(camDetails.pedTo)
camDetails.iSplineDuration = 0
//Switch starting. Block lead-ins from streaming in.
g_bBlockTriggerSceneLoadDuringSwitch = TRUE
CPRINTLN(DEBUG_SWITCH, "Player switch starting. Setting lead-in load block flag.")
IF NOT bMultiplayerSwitch
//926174
IF IS_PED_SITTING_IN_ANY_VEHICLE(camDetails.pedFrom)
VEHICLE_INDEX vehFrom = GET_VEHICLE_PED_IS_IN(camDetails.pedFrom)
naughty_SET_VEHICLE_LIMIT_SPEED_WHEN_PLAYER_INACTIVE(vehFrom, FALSE)
ENDIF
SET_PLAYER_CONTROL(PLAYER_ID(), FALSE)
SET_ENTITY_INVINCIBLE(camDetails.pedFrom, TRUE)
SET_ENTITY_INVINCIBLE(camDetails.pedTo, TRUE)
ENDIF
camDetails.bIsPhoneDisabled = IS_CELLPHONE_DISABLED()
DISABLE_CELLPHONE(TRUE)
// //# 1524219
// CASCADE_SHADOWS_SET_AIRCRAFT_MODE(TRUE)
// CPRINTLN(DEBUG_SWITCH, "CASCADE_SHADOWS_SET_AIRCRAFT_MODE(TRUE) called by ", GET_THIS_SCRIPT_NAME())
IF bPauseBeforePan
eSwitchFlags |= SWITCH_FLAG_PAUSE_BEFORE_PAN
ENDIF
IF bPauseBeforeOutro
eSwitchFlags |= SWITCH_FLAG_PAUSE_BEFORE_OUTRO
ENDIF
IF DOES_CAM_EXIST(camTo) OR NOT IS_STRING_NULL_OR_EMPTY(establishingShotName)
eSwitchFlags |= SWITCH_FLAG_SKIP_OUTRO
ENDIF
IF IS_TRANSITION_ACTIVE()
eSwitchFlags |= SWITCH_FLAG_SKIP_INTRO
ENDIF
IF NOT IS_PLAYER_SWITCH_IN_PROGRESS()
// TAKE_CONTROL_OF_TRANSITION(FALSE)
// camDetails.bTakenContolOfTransition = TRUE
START_PLAYER_SWITCH(camDetails.pedFrom, camDetails.pedTo, eSwitchFlags, eSwitchType)
IF bOverrideShortRangeSwitchStyle
SET_PLAYER_SHORT_SWITCH_STYLE(shortRangeSwitchStyle)
ENDIF
#IF IS_DEBUG_BUILD
VECTOR vPedFromCoords = GET_ENTITY_COORDS(camDetails.pedFrom)
VECTOR vPedToCoords = GET_ENTITY_COORDS(camDetails.pedTo)
CPRINTLN(DEBUG_SWITCH, "<", GET_THIS_SCRIPT_NAME(), ":fc ", GET_FRAME_COUNT(), "> START_PLAYER_SWITCH(", vPedFromCoords, ", ", vPedToCoords, ", ", Get_String_From_Switch_Flags(eSwitchFlags), ", ", Get_String_From_Switch_Type(eSwitchType), ")")
#ENDIF
SWITCH GET_PLAYER_PED_ENUM(camDetails.pedFrom)
CASE CHAR_MICHAEL
ANIMPOSTFX_STOP_AND_FLUSH_REQUESTS("SwitchHUDMichaelOut")
BREAK
CASE CHAR_FRANKLIN
ANIMPOSTFX_STOP_AND_FLUSH_REQUESTS("SwitchHUDMichaelOut")
BREAK
CASE CHAR_TREVOR
ANIMPOSTFX_STOP_AND_FLUSH_REQUESTS("SwitchHUDTrevorOut")
BREAK
ENDSWITCH
ANIMPOSTFX_STOP_AND_FLUSH_REQUESTS("SwitchHUDOut")
ELSE
IF IS_SWITCH_TO_MULTI_FIRSTPART_FINISHED()
SWITCH_TO_MULTI_SECONDPART(camDetails.pedTo)
#IF USE_TU_CHANGES
SET_SKYSWOOP_STAGE(SKYSWOOP_NONE)
#ENDIF
#IF IS_DEBUG_BUILD
VECTOR vPedFromCoords = GET_ENTITY_COORDS(camDetails.pedFrom)
VECTOR vPedToCoords = GET_ENTITY_COORDS(camDetails.pedTo)
CPRINTLN(DEBUG_SWITCH, "<", GET_THIS_SCRIPT_NAME(), ":fc ", GET_FRAME_COUNT(), "> SWITCH_TO_MULTI_SECONDPART(", vPedFromCoords, ", ", vPedToCoords, ", ", Get_String_From_Switch_Flags(eSwitchFlags), ", ", Get_String_From_Switch_Type(eSwitchType), ")")
#ENDIF
ELSE
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_SWITCH, "\nCannot start a non-multipart switch while a switch is in progress.")
CASSERTLN(DEBUG_SWITCH, "Cannot start a non-multipart switch while a switch is in progress.")
#ENDIF
RETURN FALSE
ENDIF
ENDIF
IF DOES_CAM_EXIST(camTo)
IF GET_IDEAL_PLAYER_SWITCH_TYPE(GET_ENTITY_COORDS(camDetails.pedFrom), GET_ENTITY_COORDS(camDetails.pedTo)) <> SWITCH_TYPE_SHORT
#IF IS_DEBUG_BUILD
//954886
CONST_FLOAT fMaxDistFromPedToCam_a 65.0 //Distance from destPedPos to destOutroPos should be less than 70m (if overridden outro)
/* CONST_FLOAT fMaxDistFromPedToCam_b 135.0 //Distance from establishingShotPos to destPedPos should be less than 140m */
CONST_FLOAT fMaxDistFromPedToCam_c 135.0 //Distance from establishingShotPos to destOutroPos should be less than 140m (if overridden outro)
FLOAT fMaxDistFromPedToCam = fMaxDistFromPedToCam_a
IF NOT IS_STRING_NULL_OR_EMPTY(establishingShotName)
fMaxDistFromPedToCam = fMaxDistFromPedToCam_c
ENDIF
VECTOR vDiffFromPedToCam
vDiffFromPedToCam = GET_CAM_COORD(camTo) - GET_ENTITY_COORDS(camDetails.pedTo)
IF VMAG2(vDiffFromPedToCam) > (fMaxDistFromPedToCam*fMaxDistFromPedToCam)
VECTOR vCreateCoords, vecCamEndOff
vCreateCoords = GET_ENTITY_COORDS(camDetails.pedTo)
vecCamEndOff = GET_CAM_COORD(camTo) - vCreateCoords
SET_CAM_COORD(camTo, vCreateCoords + (vecCamEndOff*0.75))
VECTOR vCamToCoords = GET_CAM_COORD(camTo)
VECTOR vPedToCoords = GET_ENTITY_COORDS(camDetails.pedTo)
CASSERTLN(DEBUG_SWITCH, "Distance between camTo[", vCamToCoords, "] and pedTo[", vPedToCoords, "] is too large: ", VMAG(vDiffFromPedToCam))
ENDIF
#ENDIF
SET_PLAYER_SWITCH_OUTRO(GET_CAM_COORD(camTo), GET_CAM_ROT(camTo, RotOrder), GET_CAM_FOV(camTo), GET_CAM_FAR_CLIP(camTo), RotOrder)
ENDIF
ENDIF
IF NOT IS_STRING_NULL_OR_EMPTY(establishingShotName)
SET_PLAYER_SWITCH_ESTABLISHING_SHOT(establishingShotName)
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_SWITCH, "SET_PLAYER_SWITCH_ESTABLISHING_SHOT(", establishingShotName, ")")
#ENDIF
ENDIF
// SFX - Heading up
IF NOT g_sSelectorUI.bSFX_BlockAudioCalls
PLAY_SOUND(-1, "CHARACTER_CHANGE_UP_MASTER")
CPRINTLN(DEBUG_SWITCH, "SWITCH UI - playing sound: CHARACTER_CHANGE_UP_MASTER")
IF GET_IDEAL_PLAYER_SWITCH_TYPE(GET_ENTITY_COORDS(camDetails.pedFrom), GET_ENTITY_COORDS(camDetails.pedTo)) = SWITCH_TYPE_SHORT
PLAY_SOUND(-1, "slow", "SHORT_PLAYER_SWITCH_SOUND_SET")
CPRINTLN(DEBUG_SWITCH, "SWITCH UI - playing sound: slow SHORT_PLAYER_SWITCH_SOUND_SET")
ELSE
CPRINTLN(DEBUG_SWITCH, "SWITCH UI - DON'T play sound: slow SHORT_PLAYER_SWITCH_SOUND_SET!!!")
ENDIF
IF (g_sSelectorUI.iSFX_Sky = -1)
g_sSelectorUI.iSFX_Sky = GET_SOUND_ID()
ENDIF
g_sSelectorUI.iSFX_Sky_ScriptHash = GET_HASH_KEY(GET_THIS_SCRIPT_NAME())
PLAY_SOUND(g_sSelectorUI.iSFX_Sky, "CHARACTER_CHANGE_SKY_MASTER")
CPRINTLN(DEBUG_SWITCH, "SWITCH UI - playing sound: CHARACTER_CHANGE_SKY_MASTER: ", g_sSelectorUI.iSFX_Sky, " [", g_sSelectorUI.iSFX_Sky_ScriptHash, ":\"", GET_THIS_SCRIPT_NAME(), "\"]")
START_AUDIO_SCENE("CHARACTER_CHANGE_IN_SKY_SCENE")
IF IS_AUDIO_SCENE_ACTIVE("CHARACTER_CHANGE_IN_SKY_SCENE")
CPRINTLN(DEBUG_SWITCH, "start CHARACTER_CHANGE_IN_SKY_SCENE...active!!!")
ELSE
CPRINTLN(DEBUG_SWITCH, "start CHARACTER_CHANGE_IN_SKY_SCENE...is NOT active!!!")
ENDIF
ENDIF
// SFX - Cleanup
IF (g_sSelectorUI.iSFX_Sky != -1)
AND g_sSelectorUI.iSFX_Sky_ScriptHash = GET_HASH_KEY(GET_THIS_SCRIPT_NAME())
CPRINTLN(DEBUG_SWITCH, "SWITCH UI - need to cleanup iSFX_Sky ", g_sSelectorUI.iSFX_Sky, ", ", g_sSelectorUI.iSFX_Sky_ScriptHash)
STOP_SOUND(g_sSelectorUI.iSFX_Sky)
RELEASE_SOUND_ID(g_sSelectorUI.iSFX_Sky)
g_sSelectorUI.iSFX_Sky = -1
g_sSelectorUI.iSFX_Sky_ScriptHash = 0
ELSE
CPRINTLN(DEBUG_SWITCH, "SWITCH UI - no need to cleanup iSFX_Sky ", g_sSelectorUI.iSFX_Sky, ", ", g_sSelectorUI.iSFX_Sky_ScriptHash)
ENDIF
/*
camDetails.fMaxHeight = GET_SELECTOR_CAM_Z_HEIGHT(camDetails.camID)
*/
camDetails.iActivateTimer = GET_GAME_TIMER()
camDetails.bSplineActive = TRUE
SET_SELECTOR_CAM_ACTIVE(TRUE)
SET_MINIMAP_IN_SPECTATOR_MODE(TRUE, camDetails.pedFrom)
IF (GET_FOLLOW_PED_CAM_VIEW_MODE() = CAM_VIEW_MODE_CINEMATIC)
CPRINTLN(DEBUG_SWITCH, "Set follow ped cam view mode - third person.")
SET_FOLLOW_PED_CAM_VIEW_MODE(CAM_VIEW_MODE_THIRD_PERSON)
ENDIF
IF (GET_FOLLOW_VEHICLE_CAM_VIEW_MODE() = CAM_VIEW_MODE_CINEMATIC)
CPRINTLN(DEBUG_SWITCH, "Set follow veh cam view mode - third person.")
SET_FOLLOW_VEHICLE_CAM_VIEW_MODE(CAM_VIEW_MODE_THIRD_PERSON)
ENDIF
// IF (GET_FOLLOW_VEHICLE_CAM_ZOOM_LEVEL() = VEHICLE_ZOOM_LEVEL_CINEMATIC)
// OR (GET_FOLLOW_VEHICLE_CAM_ZOOM_LEVEL() = VEHICLE_ZOOM_LEVEL_BONNET)
// CPRINTLN(DEBUG_SWITCH, "Set follow veh cam zoom level - medium.")
// SET_FOLLOW_VEHICLE_CAM_ZOOM_LEVEL(VEHICLE_ZOOM_LEVEL_MEDIUM)
// ENDIF
IF NOT bMultiplayerSwitch
// Process player timecycle modifier
IF GET_ENTITY_MODEL(camDetails.pedTo) = GET_PLAYER_PED_MODEL(CHAR_MICHAEL)
SET_NEXT_PLAYER_TCMODIFIER(GET_PLAYER_PED_TIMECYCLE_MODIFIER(CHAR_MICHAEL))
ELIF GET_ENTITY_MODEL(camDetails.pedTo) = GET_PLAYER_PED_MODEL(CHAR_TREVOR)
SET_NEXT_PLAYER_TCMODIFIER(GET_PLAYER_PED_TIMECYCLE_MODIFIER(CHAR_TREVOR))
ELIF GET_ENTITY_MODEL(camDetails.pedTo) = GET_PLAYER_PED_MODEL(CHAR_FRANKLIN)
SET_NEXT_PLAYER_TCMODIFIER(GET_PLAYER_PED_TIMECYCLE_MODIFIER(CHAR_FRANKLIN))
ELSE
SET_NEXT_PLAYER_TCMODIFIER("")
ENDIF
SET_PLAYER_TCMODIFIER_TRANSITION(0.0)
ENDIF
ELSE
// Problem with peds so cleanup
camDetails.bSplineComplete = TRUE
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_SWITCH, "\nCannot run switch as pedFrom or pedTo is dead.")
IF (NOT IS_PED_INJURED(camDetails.pedFrom) OR bMultiplayerSwitch)
CPRINTLN(DEBUG_SWITCH, " pedFrom alive or bMultiplayerSwitch")
ELSE
CPRINTLN(DEBUG_SWITCH, " NOT (pedFrom alive or bMultiplayerSwitch)!!!")
ENDIF
IF NOT IS_PED_INJURED(camDetails.pedTo)
CPRINTLN(DEBUG_SWITCH, " pedTo alive")
ELSE
CPRINTLN(DEBUG_SWITCH, " NOT (pedTo alive)!!!")
ENDIF
SCRIPT_ASSERT("Cannot run switch as player or ped is dead.")
#ENDIF
ENDIF
ELSE
// Problem with IS_SAFE_TO_START_PLAYER_SWITCH() so cleanup
camDetails.bSplineComplete = TRUE
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_SWITCH, "\nNot safe to start a switch???")
SCRIPT_ASSERT("Not safe to start a switch???")
#ENDIF
ENDIF
ENDIF
///////////////////////////////////////////////////////
/// Cleanup when the spline has finished
IF camDetails.bSplineActive
/*
// Update the player timecycle modifier
SET_PLAYER_TCMODIFIER_TRANSITION(GET_CAM_SPLINE_PHASE(camDetails.camID))
*/
PRINTLN("GENERIC_PED_SCENE - IS_PLAYER_SWITCH_IN_PROGRESS: ", IS_PLAYER_SWITCH_IN_PROGRESS())
IF IS_PLAYER_SWITCH_IN_PROGRESS()
#IF IS_DEBUG_BUILD
IF g_bDrawLiteralSceneString
SWITCH_TYPE eThisSwitchType
STRING sThisSwitchType
eThisSwitchType = GET_PLAYER_SWITCH_TYPE()
sThisSwitchType = Get_String_From_Switch_Type(eThisSwitchType)
SWITCH_STATE eThisSwitchState
STRING sThisSwitchState
IF (eThisSwitchType <> SWITCH_TYPE_SHORT)
eThisSwitchState = GET_PLAYER_SWITCH_STATE()
sThisSwitchState = Get_String_From_Switch_State(eThisSwitchState)
ELSE
eThisSwitchState = INT_TO_ENUM(SWITCH_STATE, -1)
SWITCH GET_PLAYER_SHORT_SWITCH_STATE()
CASE SHORT_SWITCH_STATE_INTRO
sThisSwitchState = "SHORT_SWITCH_STATE_INTRO"
BREAK
CASE SHORT_SWITCH_STATE_OUTRO
sThisSwitchState = "SHORT_SWITCH_STATE_OUTRO"
BREAK
ENDSWITCH
ENDIF
TEXT_LABEL_63 sLiteral
sLiteral = ""
sLiteral += "type:"
sLiteral += GET_STRING_FROM_STRING(sThisSwitchType,
GET_LENGTH_OF_LITERAL_STRING("SWITCH_TYPE_"),
GET_LENGTH_OF_LITERAL_STRING(sThisSwitchType))
sLiteral += ", "
IF (eThisSwitchType <> SWITCH_TYPE_SHORT)
sLiteral += "state:"
sLiteral += GET_STRING_FROM_STRING(sThisSwitchState,
GET_LENGTH_OF_LITERAL_STRING("SWITCH_STATE_"),
GET_LENGTH_OF_LITERAL_STRING(sThisSwitchState))
IF (eThisSwitchState <> SWITCH_STATE_ESTABLISHING_SHOT)
sLiteral += ": "
sLiteral += GET_PLAYER_SWITCH_JUMP_CUT_INDEX()
ELSE
sLiteral += " \""
sLiteral += establishingShotName
sLiteral += "\""
ENDIF
ELSE
sLiteral += "state:"
sLiteral += GET_STRING_FROM_STRING(sThisSwitchState,
GET_LENGTH_OF_LITERAL_STRING("SHORT_SWITCH_STATE_"),
GET_LENGTH_OF_LITERAL_STRING(sThisSwitchState))
ENDIF
SET_TEXT_SCALE(0.4, 0.4)
SET_TEXT_COLOUR(255, 255, 255, 255)
SET_TEXT_JUSTIFICATION(FONT_CENTRE)
SET_TEXT_OUTLINE()
DISPLAY_TEXT_WITH_LITERAL_STRING(0.5, 0.925, "STRING", sLiteral)
ENDIF
#ENDIF
// SFX - Heading down
IF NOT g_sSelectorUI.bSFX_BlockAudioCalls
/*
FLOAT fCurrentHeight = GET_SELECTOR_CAM_Z_HEIGHT(camDetails.camID)
IF (fCurrentHeight > camDetails.fMaxHeight)
camDetails.fMaxHeight = fCurrentHeight
ELIF (camDetails.fMaxHeight > fCurrentHeight+1.0)
IF g_sSelectorUI.iSFX_HeadDown = -1
g_sSelectorUI.iSFX_HeadDown = GET_SOUND_ID()
PLAY_SOUND(g_sSelectorUI.iSFX_HeadDown, "CHARACTER_CHANGE_DOWN_MASTER")
ENDIF
IF (g_sSelectorUI.iSFX_Sky != -1)
CPRINTLN(DEBUG_SWITCH, "SWITCH UI - stop iSFX_Sky ", g_sSelectorUI.iSFX_Sky)
STOP_SOUND(g_sSelectorUI.iSFX_Sky)
RELEASE_SOUND_ID(g_sSelectorUI.iSFX_Sky)
g_sSelectorUI.iSFX_Sky = -1
STOP_AUDIO_SCENE("CHARACTER_CHANGE_IN_SKY_SCENE")
ENDIF
ENDIF
*/
ENDIF
IF IS_BITMASK_AS_ENUM_SET(iSwitchFlags, SWITCH_FLAG_PAUSE_BEFORE_DESCENT)
IF NOT IS_SWITCH_READY_FOR_DESCENT()
CPRINTLN(DEBUG_SWITCH, "not IS_SWITCH_READY_FOR_DESCENT???")
ELSE
CPRINTLN(DEBUG_SWITCH, "IS_SWITCH_READY_FOR_DESCENT [", g_iPauseOnOutro, ", ", g_iPausedOnOutroGametime, "]")
IF (g_iPauseOnOutro = 0)
ALLOW_PLAYER_SWITCH_DESCENT()
ENDIF
ENDIF
ENDIF
PRINTLN("GENERIC_PED_SCENE - (7) GET_PLAYER_SWITCH_TYPE: ", Get_String_From_Switch_Type(GET_PLAYER_SWITCH_TYPE()))
IF (GET_PLAYER_SWITCH_TYPE() = SWITCH_TYPE_SHORT)
SWITCH GET_PLAYER_SHORT_SWITCH_STATE()
CASE SHORT_SWITCH_STATE_INTRO
PRINTLN("GENERIC_PED_SCENE - (7) GET_PLAYER_SHORT_SWITCH_STATE: SHORT_SWITCH_STATE_INTRO")
BREAK
CASE SHORT_SWITCH_STATE_OUTRO
PRINTLN("GENERIC_PED_SCENE - (7) GET_PLAYER_SHORT_SWITCH_STATE: SHORT_SWITCH_STATE_OUTRO")
BREAK
ENDSWITCH
ENDIF
// Allow ped switch
IF (GET_PLAYER_SWITCH_TYPE() = SWITCH_TYPE_SHORT)
IF (GET_PLAYER_SHORT_SWITCH_STATE() >= SHORT_SWITCH_STATE_OUTRO)
PRINTLN("GENERIC_PED_SCENE - (7) camDetails.bOKToSwitchPed: ", camDetails.bOKToSwitchPed)
IF NOT camDetails.bOKToSwitchPed
FLUSH_TEXT_MESSAGE_FEED_ENTRIES() //1007225
camDetails.bOKToSwitchPed = TRUE
PRINTLN("GENERIC_PED_SCENE - Setting bOKToSwitchPed to TRUE (7)")
#IF IS_DEBUG_BUILD
DEBUG_PRINTCALLSTACK()
#ENDIF
ENDIF
IF NOT camDetails.bTakenContolOfTransition
CPRINTLN(DEBUG_SWITCH, "TAKE_CONTROL_OF_TRANSITION...short range!!!")
TAKE_CONTROL_OF_TRANSITION(FALSE)
camDetails.bTakenContolOfTransition = TRUE
ENDIF
ENDIF
ELSE
#IF IS_DEBUG_BUILD
PRINTLN("GENERIC_PED_SCENE - (8) GET_PLAYER_SWITCH_STATE: ", DEBUG_GET_PLAYER_SWITCH_STATE(GET_PLAYER_SWITCH_STATE()))
#ENDIF
IF (GET_PLAYER_SWITCH_STATE() >= SWITCH_STATE_JUMPCUT_DESCENT)
PRINTLN("GENERIC_PED_SCENE - (8) camDetails.bOKToSwitchPed: ", camDetails.bOKToSwitchPed)
IF NOT camDetails.bOKToSwitchPed
FLUSH_TEXT_MESSAGE_FEED_ENTRIES() //1007225
camDetails.bOKToSwitchPed = TRUE
PRINTLN("GENERIC_PED_SCENE - Setting bOKToSwitchPed to TRUE (8)")
#IF IS_DEBUG_BUILD
DEBUG_PRINTCALLSTACK()
#ENDIF
ENDIF
ENDIF
#IF USE_TU_CHANGES
PRINTLN("GENERIC_PED_SCENE - (9) camDetails.bOKToSwitchPed: ", camDetails.bOKToSwitchPed)
IF NOT camDetails.bOKToSwitchPed
PRINTLN("GENERIC_PED_SCENE - (9) IS_SWITCH_SKIPPING_DESCENT: ", IS_SWITCH_SKIPPING_DESCENT())
#IF IS_DEBUG_BUILD
PRINTLN("GENERIC_PED_SCENE - (9) GET_PLAYER_SWITCH_STATE: ", DEBUG_GET_PLAYER_SWITCH_STATE(GET_PLAYER_SWITCH_STATE()))
#ENDIF
IF IS_SWITCH_SKIPPING_DESCENT() //#1649473
AND (GET_PLAYER_SWITCH_STATE() = SWITCH_STATE_JUMPCUT_ASCENT)
VECTOR vPlayerCoords = GET_ENTITY_COORDS(PLAYER_PED_ID())
VECTOR vCamCoords = GET_FINAL_RENDERED_CAM_COORD()
FLOAT fDistToProgress = 20.0
FLOAT fCamDist2 = VDIST2(vPlayerCoords, vCamCoords)
PRINTLN("GENERIC_PED_SCENE - (9) fCamDist2: ", fCamDist2)
PRINTLN("GENERIC_PED_SCENE - (9) (fDistToProgress*fDistToProgress): ", (fDistToProgress*fDistToProgress))
IF fCamDist2 < (fDistToProgress*fDistToProgress)
FLUSH_TEXT_MESSAGE_FEED_ENTRIES()
camDetails.bOKToSwitchPed = TRUE
PRINTLN("GENERIC_PED_SCENE - Setting bOKToSwitchPed to TRUE (9)")
#IF IS_DEBUG_BUILD
DEBUG_PRINTCALLSTACK()
#ENDIF
ENDIF
ENDIF
ENDIF
#ENDIF
IF NOT camDetails.bTakenContolOfTransition
IF GET_PLAYER_SWITCH_STATE() > SWITCH_STATE_PREP_FOR_CUT
CPRINTLN(DEBUG_SWITCH, "TAKE_CONTROL_OF_TRANSITION...med/long range!!!")
TAKE_CONTROL_OF_TRANSITION(FALSE)
camDetails.bTakenContolOfTransition = TRUE
ENDIF
ENDIF
IF NOT camDetails.bSetShadowSampleBox3x3
IF GET_PLAYER_SWITCH_STATE() >= SWITCH_STATE_JUMPCUT_ASCENT
CPRINTLN(DEBUG_SWITCH, "CASCADE_SHADOWS_SET_SHADOW_SAMPLE_TYPE(\"CSM_ST_BOX3x3\")...med/long range!!!")
CASCADE_SHADOWS_SET_SHADOW_SAMPLE_TYPE("CSM_ST_BOX3x3")
camDetails.bSetShadowSampleBox3x3 = TRUE
ENDIF
ENDIF
ENDIF
/*
// Update final spline node
IF camDetails.bOKToSwitchPed
IF PLAYER_PED_ID() = camDetails.pedTo
IF NOT IS_PED_INJURED(camDetails.pedTo)
IF camDetails.iInterpCams >= 1
IF DOES_CAM_EXIST(camDetails.camInterpIDs[camDetails.iInterpCams - 1])
IF IS_PED_IN_ANY_VEHICLE(camDetails.pedTo)
VEHICLE_INDEX vehPed = GET_VEHICLE_PED_IS_USING(camDetails.pedTo)
VECTOR vTargetRelativePosition = GET_OFFSET_FROM_ENTITY_GIVEN_WORLD_COORDS(vehPed, GET_GAMEPLAY_CAM_COORD())
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams - 1], vehPed, vTargetRelativePosition)
ELSE
VECTOR vTargetRelativePosition = GET_OFFSET_FROM_ENTITY_GIVEN_WORLD_COORDS(camDetails.pedTo, GET_GAMEPLAY_CAM_COORD())
ATTACH_CAM_TO_ENTITY(camDetails.camInterpIDs[camDetails.iInterpCams - 1], camDetails.pedTo, vTargetRelativePosition)
ENDIF
SET_CAM_ROT(camDetails.camInterpIDs[camDetails.iInterpCams - 1], GET_GAMEPLAY_CAM_ROT())
SET_CAM_FOV(camDetails.camInterpIDs[camDetails.iInterpCams - 1], GET_GAMEPLAY_CAM_FOV())
bFinalNodeUpdated = TRUE
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
*/
ELSE
PRINTLN("GENERIC_PED_SCENE - (10) camDetails.bOKToSwitchPed: ", camDetails.bOKToSwitchPed)
// Allow ped switch
IF NOT camDetails.bOKToSwitchPed
camDetails.bOKToSwitchPed = TRUE
PRINTLN("GENERIC_PED_SCENE - Setting bOKToSwitchPed to TRUE (10)")
#IF IS_DEBUG_BUILD
DEBUG_PRINTCALLSTACK()
#ENDIF
FLUSH_TEXT_MESSAGE_FEED_ENTRIES() //1007225
ENDIF
IF NOT camDetails.bTakenContolOfTransition
CPRINTLN(DEBUG_SWITCH, "TAKE_CONTROL_OF_TRANSITION...fall through!!!")
TAKE_CONTROL_OF_TRANSITION(FALSE)
camDetails.bTakenContolOfTransition = TRUE
ENDIF
camDetails.bSplineComplete = TRUE
ENDIF
ENDIF
///////////////////////////////////////////////////////
/// Cleanup the camera
IF camDetails.bSplineComplete
PED_REQUEST_SCENE_ENUM eScene
eScene = Get_Player_Timetable_Scene_In_Progress()
IF (eScene <> PR_SCENE_Fa_PHONECALL_ARM3)
AND (eScene <> PR_SCENE_Fa_PHONECALL_FAM1)
AND (eScene <> PR_SCENE_Fa_PHONECALL_FAM3)
AND (eScene <> PR_SCENE_Ta_CARSTEAL4)
DISABLE_CELLPHONE(camDetails.bIsPhoneDisabled)
ENDIF
// //# 1524219
// CASCADE_SHADOWS_SET_AIRCRAFT_MODE(FALSE)
// CPRINTLN(DEBUG_SWITCH, "CASCADE_SHADOWS_SET_AIRCRAFT_MODE(FALSE) called by ", GET_THIS_SCRIPT_NAME())
IF camDetails.bSetShadowSampleBox3x3
CASCADE_SHADOWS_CLEAR_SHADOW_SAMPLE_TYPE()
camDetails.bSetShadowSampleBox3x3 = FALSE
ENDIF
// Reset all the camera values incase they have to be used again
camDetails.bSplineActive = FALSE
camDetails.bSplineComplete = FALSE
camDetails.bOKToSwitchPed = FALSE
camDetails.bPedSwitched = FALSE
camDetails.bRun = FALSE
camDetails.iInterpCams = 0
camDetails.iSplineDuration = 0
// SFX - Cleanup
IF (g_sSelectorUI.iSFX_Sky != -1)
AND g_sSelectorUI.iSFX_Sky_ScriptHash = GET_HASH_KEY(GET_THIS_SCRIPT_NAME())
CPRINTLN(DEBUG_SWITCH, "SWITCH UI - stop iSFX_Sky ", g_sSelectorUI.iSFX_Sky, ", ", g_sSelectorUI.iSFX_Sky_ScriptHash)
STOP_SOUND(g_sSelectorUI.iSFX_Sky)
RELEASE_SOUND_ID(g_sSelectorUI.iSFX_Sky)
g_sSelectorUI.iSFX_Sky = -1
g_sSelectorUI.iSFX_Sky_ScriptHash = 0
ELSE
CPRINTLN(DEBUG_SWITCH, "SWITCH UI - don't stop iSFX_Sky ", g_sSelectorUI.iSFX_Sky, ", ", g_sSelectorUI.iSFX_Sky_ScriptHash)
ENDIF
IF IS_AUDIO_SCENE_ACTIVE("CHARACTER_CHANGE_IN_SKY_SCENE")
CPRINTLN(DEBUG_SWITCH, "stop CHARACTER_CHANGE_IN_SKY_SCENE...is STILL active!!!")
STOP_AUDIO_SCENE("CHARACTER_CHANGE_IN_SKY_SCENE")
ELSE
CPRINTLN(DEBUG_SWITCH, "stop CHARACTER_CHANGE_IN_SKY_SCENE...was not active!!!")
ENDIF
IF (g_sSelectorUI.iSFX_HeadDown != -1)
AND g_sSelectorUI.iSFX_HeadDown_ScriptHash = GET_HASH_KEY(GET_THIS_SCRIPT_NAME())
CPRINTLN(DEBUG_SWITCH, "STOP_SOUND iSFX_HeadDown: ", g_sSelectorUI.iSFX_HeadDown, ", ", GET_THIS_SCRIPT_NAME())
STOP_SOUND(g_sSelectorUI.iSFX_HeadDown)
RELEASE_SOUND_ID(g_sSelectorUI.iSFX_HeadDown)
g_sSelectorUI.iSFX_HeadDown = -1
g_sSelectorUI.iSFX_HeadDown_ScriptHash = 0
ENDIF
// Set the relative heading/pitch if the calling scipt used a custom camera
// If specified out of range then do no set
IF fDestCamRelativeHeading <= 360 AND fDestCamRelativeHeading >= - 360
SET_GAMEPLAY_CAM_RELATIVE_HEADING(fDestCamRelativeHeading)
ENDIF
IF fDestCamRelativePitch <= 360 AND fDestCamRelativePitch >= -360
SET_GAMEPLAY_CAM_RELATIVE_PITCH(fDestCamRelativePitch)
ENDIF
IF NOT (g_drunkCameraActive)
STOP_GAMEPLAY_CAM_SHAKING(TRUE)
SET_GAMEPLAY_CAM_MOTION_BLUR_SCALING_THIS_UPDATE(0)
SET_GAMEPLAY_CAM_MAX_MOTION_BLUR_STRENGTH_THIS_UPDATE(0)
ENDIF
IF NOT bMultiplayerSwitch
IF NOT IS_PED_INJURED(camDetails.pedFrom)
SET_ENTITY_VISIBLE(camDetails.pedFrom, TRUE)
SET_PED_CAN_BE_TARGETTED(camDetails.pedFrom, TRUE)
IF NOT IS_PED_IN_ANY_VEHICLE(camDetails.pedFrom)
SET_ENTITY_COLLISION(camDetails.pedFrom, TRUE)
ENDIF
//926174
IF IS_PED_SITTING_IN_ANY_VEHICLE(camDetails.pedFrom)
VEHICLE_INDEX vehFrom = GET_VEHICLE_PED_IS_IN(camDetails.pedFrom)
naughty_SET_VEHICLE_LIMIT_SPEED_WHEN_PLAYER_INACTIVE(vehFrom, TRUE)
ENDIF
ENDIF
ENDIF
SET_SKYSWOOP_STAGE(SKYSWOOP_NONE)
IF NOT bMultiplayerSwitch
// Reset proofs
IF (NOT IS_PED_INJURED(camDetails.pedFrom) OR bMultiplayerSwitch)
SET_ENTITY_INVINCIBLE(camDetails.pedFrom, FALSE)
CPRINTLN(DEBUG_SWITCH, "SET_ENTITY_INVINCIBLE(", GET_PLAYER_PED_STRING(GET_PLAYER_PED_ENUM(camDetails.pedFrom)), ", FALSE) //pedFrom")
ELSE
CPRINTLN(DEBUG_SWITCH, "NOT SET_ENTITY_INVINCIBLE(camDetails.pedFrom, FALSE)")
ENDIF
IF NOT IS_PED_INJURED(camDetails.pedTo)
SET_ENTITY_INVINCIBLE(camDetails.pedTo, FALSE)
CPRINTLN(DEBUG_SWITCH, "SET_ENTITY_INVINCIBLE(", GET_PLAYER_PED_STRING(GET_PLAYER_PED_ENUM(camDetails.pedTo)), ", FALSE) //pedTo")
ELSE
CPRINTLN(DEBUG_SWITCH, "NOT SET_ENTITY_INVINCIBLE(camDetails.pedTo, FALSE)")
ENDIF
SET_PLAYER_CONTROL(PLAYER_ID(), TRUE)
ClearInsideDisplacedInteriorFlag()
// Update the player timecycle modifier
SET_CURRENT_PLAYER_TCMODIFIER(GET_PLAYER_PED_TIMECYCLE_MODIFIER(GET_CURRENT_PLAYER_PED_ENUM()))
ENDIF
SET_SELECTOR_CAM_ACTIVE(FALSE)
SET_MINIMAP_IN_SPECTATOR_MODE(FALSE, NULL)
RETURN FALSE // Cam complete
ENDIF
// Hide the HUD
HIDE_HUD_AND_RADAR_THIS_FRAME()
//CLEAR_REMINDER_MESSAGE() //#1421176
RETURN TRUE // Cam still running
ENDFUNC
// PURPOSE:
FUNC BOOL RUN_SWITCH_CAM_FROM_PLAYER_TO_PED(SELECTOR_CAM_STRUCT &camDetails,
SWITCH_TYPE eSwitchType = SWITCH_TYPE_AUTO,
INT iSwitchFlags = 0,
FLOAT fDestCamRelativePitch = 999.0,FLOAT fDestCamRelativeHeading = 999.0,
BOOL bPauseBeforePan = FALSE, BOOL bPauseBeforeOutro = FALSE,
STRING establishingShotName = NULL, BOOL bOverrideShortRangeSwitchStyle = FALSE, SHORT_SWITCH_STYLE shortRangeSwitchStyle = SHORT_SWITCH_STYLE_ROTATION)
//camDetails.pedFrom = PLAYER_PED_ID() //Always from player
RETURN PRIVATE_RunPlayerSwitch(camDetails,
NULL, eSwitchType,
iSwitchFlags, fDestCamRelativePitch ,fDestCamRelativeHeading,
bPauseBeforePan, bPauseBeforeOutro, establishingShotName,
DEFAULT, FALSE, bOverrideShortRangeSwitchStyle, shortRangeSwitchStyle)
// Adding this extra return case as the DEFAULT param breaks intelisense...
RETURN TRUE
ENDFUNC
// PURPOSE:
FUNC BOOL RUN_SWITCH_CAM_FROM_PLAYER_TO_PED_SHORT_RANGE(SELECTOR_CAM_STRUCT &camDetails,
INT iSwitchFlags = 0,
FLOAT fDestCamRelativePitch = 999.0,FLOAT fDestCamRelativeHeading = 999.0)
//camDetails.pedFrom = PLAYER_PED_ID() //Always from player
RETURN PRIVATE_RunPlayerSwitch(camDetails,
NULL, SWITCH_TYPE_SHORT,
iSwitchFlags, fDestCamRelativePitch ,fDestCamRelativeHeading,
DEFAULT, DEFAULT, DEFAULT,
EULER_MAX, FALSE)
// Adding this extra return case as the DEFAULT param breaks intelisense...
RETURN TRUE
ENDFUNC
// PURPOSE:
FUNC BOOL RUN_SWITCH_CAM_FROM_PLAYER_TO_PED_LONG_RANGE(SELECTOR_CAM_STRUCT &camDetails,
INT iSwitchFlags = 0,
FLOAT fDestCamRelativePitch = 999.0,FLOAT fDestCamRelativeHeading = 999.0)
//camDetails.pedFrom = PLAYER_PED_ID() //Always from player
RETURN PRIVATE_RunPlayerSwitch(camDetails,
NULL, SWITCH_TYPE_LONG,
iSwitchFlags, fDestCamRelativePitch ,fDestCamRelativeHeading,
DEFAULT, DEFAULT, DEFAULT,
EULER_MAX, FALSE)
// Adding this extra return case as the DEFAULT param breaks intelisense...
RETURN TRUE
ENDFUNC
// PURPOSE:
FUNC BOOL NET_RUN_SWITCH_CAM_FROM_PED_TO_PED_LONG_RANGE(SELECTOR_CAM_STRUCT &camDetails,
INT iSwitchFlags = 0,
FLOAT fDestCamRelativePitch = 999.0,FLOAT fDestCamRelativeHeading = 999.0)
RETURN PRIVATE_RunPlayerSwitch(camDetails,
NULL, SWITCH_TYPE_LONG,
iSwitchFlags, fDestCamRelativePitch ,fDestCamRelativeHeading,
DEFAULT, DEFAULT, DEFAULT,
EULER_MAX, TRUE)
// Adding this extra return case as the DEFAULT param breaks intelisense...
RETURN TRUE
ENDFUNC
// PURPOSE:
FUNC BOOL NET_RUN_SWITCH_CAM_FROM_PED_TO_PED(SELECTOR_CAM_STRUCT &camDetails,
FLOAT fDestCamRelativePitch = 999.0,FLOAT fDestCamRelativeHeading = 999.0)
RETURN PRIVATE_RunPlayerSwitch(camDetails,
NULL, SWITCH_TYPE_AUTO, 0,
fDestCamRelativePitch ,fDestCamRelativeHeading,
DEFAULT, DEFAULT, DEFAULT,
EULER_MAX, TRUE)
// Adding this extra return case as the DEFAULT param breaks intelisense...
RETURN TRUE
ENDFUNC
// PURPOSE:
FUNC BOOL RUN_SWITCH_CAM_FROM_PLAYER_TO_CAM(SELECTOR_CAM_STRUCT &camDetails, CAMERA_INDEX camTo,
SWITCH_TYPE eSwitchType = SWITCH_TYPE_AUTO,
INT iSwitchFlags = 0,
FLOAT fDestCamRelativePitch = 999.0, FLOAT fDestCamRelativeHeading = 999.0,
BOOL bPauseBeforePan = FALSE, BOOL bPauseBeforeOutro = FALSE,
STRING establishingShotName = NULL,
EULER_ROT_ORDER RotOrder = EULER_YXZ)
//camDetails.pedFrom = PLAYER_PED_ID() //Always from player
RETURN PRIVATE_RunPlayerSwitch(camDetails,
camTo, eSwitchType,
iSwitchFlags, fDestCamRelativePitch, fDestCamRelativeHeading,
bPauseBeforePan, bPauseBeforeOutro, establishingShotName,
RotOrder, FALSE)
// Adding this extra return case as the DEFAULT param breaks intelisense...
RETURN TRUE
ENDFUNC
// PURPOSE:
FUNC BOOL RUN_SWITCH_CAM_FROM_PLAYER_TO_CAM_SHORT_RANGE(SELECTOR_CAM_STRUCT &camDetails, CAMERA_INDEX camTo,
INT iSwitchFlags = 0,
FLOAT fDestCamRelativePitch = 999.0, FLOAT fDestCamRelativeHeading = 999.0,
EULER_ROT_ORDER RotOrder = EULER_YXZ)
//camDetails.pedFrom = PLAYER_PED_ID() //Always from player
RETURN PRIVATE_RunPlayerSwitch(camDetails,
camTo, SWITCH_TYPE_SHORT,
iSwitchFlags, fDestCamRelativePitch,fDestCamRelativeHeading,
DEFAULT, DEFAULT, DEFAULT,
RotOrder, FALSE)
// Adding this extra return case as the DEFAULT param breaks intelisense...
RETURN TRUE
ENDFUNC
// PURPOSE:
FUNC BOOL RUN_SWITCH_CAM_FROM_PLAYER_TO_CAM_LONG_RANGE(SELECTOR_CAM_STRUCT &camDetails, CAMERA_INDEX camTo,
INT iSwitchFlags = 0,
FLOAT fDestCamRelativePitch = 999.0, FLOAT fDestCamRelativeHeading = 999.0,
EULER_ROT_ORDER RotOrder = EULER_YXZ)
//camDetails.pedFrom = PLAYER_PED_ID() //Always from player
RETURN PRIVATE_RunPlayerSwitch(camDetails,
camTo, SWITCH_TYPE_LONG,
iSwitchFlags, fDestCamRelativePitch,fDestCamRelativeHeading,
DEFAULT, DEFAULT, DEFAULT,
RotOrder, FALSE)
// Adding this extra return case as the DEFAULT param breaks intelisense...
RETURN TRUE
ENDFUNC
/// PURPOSE: Changes the player ped to selectorPeds.pedID[selectorPeds.eNewSelectorPed]
///
/// NOTE: The players ped ID will be changed to the selector peds ped ID and vice versa
FUNC BOOL TAKE_CONTROL_OF_SELECTOR_PED(SELECTOR_PED_STRUCT &selectorPeds, BOOL bKeepPlayerReplacement = TRUE, BOOL bKeepTasks = FALSE, TAKE_CONTROL_OF_PED_FLAGS eFlags = TCF_NONE)
// Ensure a selection has been made
IF NOT selectorPeds.bInitialised
#IF IS_DEBUG_BUILD
PRINTLN("TAKE_CONTROL_OF_SELECTOR_PED")
PRINTLN("...player = ", GET_PLAYER_PED_STRING(GET_CURRENT_PLAYER_PED_ENUM()))
PRINTLN("...selected ped = ", GET_PLAYER_PED_STRING(GET_PLAYER_PED_ENUM_FROM_SELECTOR_SLOT(selectorPeds.eNewSelectorPed)))
SCRIPT_ASSERT("TAKE_CONTROL_OF_SELECTOR_PED - Ped selection has not taken place. See Kenneth R.")
#ENDIF
// Bail out if no-one was set.
IF selectorPeds.eNewSelectorPed = NUMBER_OF_SELECTOR_PEDS
PRINTLN("GENERIC_PED_SCENE - TAKE_CONTROL_OF_SELECTOR_PED - Returning TRUE")
RETURN TRUE
ENDIF
ENDIF
PRINTLN("GENERIC_PED_SCENE - TAKE_CONTROL_OF_SELECTOR_PED - IS_PED_INJURED(selectorPeds.pedID[selectorPeds.eNewSelectorPed]): ", IS_PED_INJURED(selectorPeds.pedID[selectorPeds.eNewSelectorPed]))
PRINTLN("GENERIC_PED_SCENE - TAKE_CONTROL_OF_SELECTOR_PED - IS_PED_INJURED(PLAYER_PED_ID()): ", IS_PED_INJURED(PLAYER_PED_ID()))
IF selectorPeds.pedID[selectorPeds.eNewSelectorPed] != PLAYER_PED_ID()
PRINTLN("GENERIC_PED_SCENE - TAKE_CONTROL_OF_SELECTOR_PED - ectorPeds.pedID[selectorPeds.eNewSelectorPed] != PLAYER_PED_ID()")
ELSE
PRINTLN("GENERIC_PED_SCENE - TAKE_CONTROL_OF_SELECTOR_PED - ectorPeds.pedID[selectorPeds.eNewSelectorPed] = PLAYER_PED_ID()")
ENDIF
IF NOT IS_PED_INJURED(selectorPeds.pedID[selectorPeds.eNewSelectorPed])
AND NOT IS_PED_INJURED(PLAYER_PED_ID())
AND selectorPeds.pedID[selectorPeds.eNewSelectorPed] != PLAYER_PED_ID()
//////////////////////////////////////////////////////////////////////////////////
/// *** Temp fix so that the player doesn't lose control
///
IF NOT bKeepTasks
IF IS_PED_RAGDOLL(PLAYER_PED_ID())
AND NOT IS_ENTITY_ON_FIRE(PLAYER_PED_ID())
AND NOT IS_PED_GETTING_INTO_A_VEHICLE(PLAYER_PED_ID())
CLEAR_PED_TASKS_IMMEDIATELY(PLAYER_PED_ID())
ELSE
CLEAR_PED_TASKS(PLAYER_PED_ID())
ENDIF
IF IS_PED_RAGDOLL(selectorPeds.pedID[selectorPeds.eNewSelectorPed])
AND NOT IS_ENTITY_ON_FIRE(selectorPeds.pedID[selectorPeds.eNewSelectorPed])
AND NOT IS_PED_GETTING_INTO_A_VEHICLE(selectorPeds.pedID[selectorPeds.eNewSelectorPed])
CLEAR_PED_TASKS_IMMEDIATELY(selectorPeds.pedID[selectorPeds.eNewSelectorPed])
ELSE
CLEAR_PED_TASKS(selectorPeds.pedID[selectorPeds.eNewSelectorPed])
ENDIF
ENDIF
///
//////////////////////////////////////////////////////////////////////////////////
PED_INDEX originalPlayerPedID
enumCharacterList ePedRep, ePedSel
//////////////////////////////////////////////////////////////////////////////////
/// [1] Store the current players details
///
originalPlayerPedID = PLAYER_PED_ID()
ePedRep = GET_CURRENT_PLAYER_PED_ENUM()
IF (NOT selectorPeds.bAmbient)
// OR (selectorPeds.bAmbient) // AND g_sPlayerPedRequest.eType <> PR_TYPE_AMBIENT)
STORE_PLAYER_PED_INFO(originalPlayerPedID)
ENDIF
UNREGISTER_PLAYER_PED_WITH_AUTOMATIC_DOORS(ePedRep, originalPlayerPedID)
SET_PED_CONFIG_FLAG(originalPlayerPedID, PCF_WillFlyThroughWindscreen, TRUE)
SET_PED_CONFIG_FLAG(originalPlayerPedID, PCF_WillTakeDamageWhenVehicleCrashes, TRUE)
CPRINTLN(DEBUG_FLOW, "SWITCH from script ", GET_THIS_SCRIPT_NAME(), " setting ped flags for old player ped.")
CPRINTLN(DEBUG_FLOW, "Set WillFlyThroughWindscreen to TRUE for PED_INDEX[",NATIVE_TO_INT(originalPlayerPedID),"].")
CPRINTLN(DEBUG_FLOW, "Set WillTakeDamageWhenVehicleCrashes to TRUE for PED_INDEX[",NATIVE_TO_INT(originalPlayerPedID),"].")
//////////////////////////////////////////////////////////////////////////////////
/// [2] Store the selector peds details
///
ePedSel = GET_PLAYER_PED_ENUM_FROM_SELECTOR_SLOT(selectorPeds.eNewSelectorPed)
STORE_PLAYER_PED_INFO(selectorPeds.pedID[selectorPeds.eNewSelectorPed])
// Track selected peds health perc so we can ensure player has 25%+ when we switch
FLOAT fSelectedPedHealthPerc = (((TO_FLOAT(GET_ENTITY_HEALTH(selectorPeds.pedID[selectorPeds.eNewSelectorPed]))-100.0) / (TO_FLOAT(GET_PED_MAX_HEALTH(selectorPeds.pedID[selectorPeds.eNewSelectorPed]))-100.0)) * 100.0)
//////////////////////////////////////////////////////////////////////////////////
/// [3] Replace selector ped with player
///
#IF IS_DEBUG_BUILD
PRINTSTRING("\n Changing current player character from ")PRINTSTRING(GET_PLAYER_PED_STRING(ePedRep))PRINTSTRING(" to ")PRINTSTRING(GET_PLAYER_PED_STRING(ePedSel))PRINTNL()PRINTNL()
#ENDIF
#IF USE_FINAL_PRINTS
PRINTLN_FINAL("<2140379> Changing current player character from ", ENUM_TO_INT(ePedRep), " to ", ENUM_TO_INT(ePedSel), ".")
#ENDIF
SWITCH GET_PLAYER_PED_ENUM(PLAYER_PED_ID())
CASE CHAR_MICHAEL
IF ANIMPOSTFX_IS_RUNNING("BulletTime")
ANIMPOSTFX_STOP("BulletTime")
ENDIF
IF ANIMPOSTFX_IS_RUNNING("BulletTimeOut")
ANIMPOSTFX_STOP("BulletTimeOut")
ENDIF
BREAK
CASE CHAR_FRANKLIN
IF ANIMPOSTFX_IS_RUNNING("DrivingFocus")
ANIMPOSTFX_STOP("DrivingFocus")
ENDIF
IF ANIMPOSTFX_IS_RUNNING("DrivingFocusOut")
ANIMPOSTFX_STOP("DrivingFocusOut")
ENDIF
BREAK
CASE CHAR_TREVOR
IF ANIMPOSTFX_IS_RUNNING("REDMIST")
ANIMPOSTFX_STOP("REDMIST")
ENDIF
IF ANIMPOSTFX_IS_RUNNING("REDMISTOut")
ANIMPOSTFX_STOP("REDMISTOut")
ENDIF
BREAK
ENDSWITCH
// B* 2312133 - Should fix Assert 2.
IF IS_PLAYER_PED_PLAYABLE(GET_CURRENT_PLAYER_PED_ENUM())
IF IS_SPECIAL_ABILITY_ACTIVE(PLAYER_ID())
SPECIAL_ABILITY_DEACTIVATE_FAST(PLAYER_ID())
ENDIF
ENDIF
CDEBUG1LN(DEBUG_INIT_SP, " - selector_public - Changing player ped.")
CHANGE_PLAYER_PED(PLAYER_ID(), selectorPeds.pedID[selectorPeds.eNewSelectorPed], bKeepTasks, FALSE)
// Prevent cash from displaying (bug 1234294)
HIDE_HUD_COMPONENT_THIS_FRAME(NEW_HUD_CASH)
HIDE_HUD_COMPONENT_THIS_FRAME(NEW_HUD_CASH_CHANGE)
IF (eFlags & TCF_CLEAR_TASK_INTERRUPT_CHECKS) != TCF_NONE
SET_PED_CONFIG_FLAG(PLAYER_PED_ID(), PCF_WaitingForPlayerControlInterrupt, FALSE)
ENDIF
// Increment switch count for current mission if manual switch took place
IF IS_CURRENTLY_ON_MISSION_TO_TYPE(MISSION_TYPE_STORY)
OR IS_CURRENTLY_ON_MISSION_TO_TYPE(MISSION_TYPE_STORY_FRIENDS)
IF g_sSelectorUI.bManualSelection
// NOTE: We can use GET_THIS_SCRIPT_NAME() to get the current mission
// but it's probably safer to stay in sync with the flow.
// Determine the current running mission
INT availableMissionIndex
#IF USE_CLF_DLC
REPEAT MAX_MISSIONS_AVAILABLE_TU availableMissionIndex
IF IS_BIT_SET(g_availableMissionsTU[availableMissionIndex].bitflags, BITS_AVAILABLE_MISSION_RUNNING)
INT theCoreVarsIndex = g_availableMissionsTU[availableMissionIndex].index
#ENDIF
#IF USE_NRM_DLC
REPEAT MAX_MISSIONS_AVAILABLE_TU availableMissionIndex
IF IS_BIT_SET(g_availableMissionsTU[availableMissionIndex].bitflags, BITS_AVAILABLE_MISSION_RUNNING)
INT theCoreVarsIndex = g_availableMissionsTU[availableMissionIndex].index
#ENDIF
#IF NOT USE_SP_DLC
REPEAT MAX_MISSIONS_AVAILABLE availableMissionIndex
IF IS_BIT_SET(g_availableMissions[availableMissionIndex].bitflags, BITS_AVAILABLE_MISSION_RUNNING)
INT theCoreVarsIndex = g_availableMissions[availableMissionIndex].index
#ENDIF
TEXT_LABEL_63 tlStatName
tlStatName = "MISS_SWITCH_"
tlStatName += g_sMissionStaticData[g_flowUnsaved.coreVars[theCoreVarsIndex].iValue1].scriptName
PRINTLN("STAT_INCREMENT - ", tlStatName)
STAT_INCREMENT(INT_TO_ENUM(STATSENUM, GET_HASH_KEY(tlStatName)), 1)
//Necessary to keep intellisense happy.
#IF USE_CLF_DLC
ENDIF
ENDREPEAT
#ENDIF
#IF USE_NRM_DLC
ENDIF
ENDREPEAT
#ENDIF
#IF NOT USE_SP_DLC
ENDIF
ENDREPEAT
#ENDIF
ENDIF
ENDIF
// Clear the manual selection flag (also gets cleared when we force a switch with SET_CURRENT_SELECTOR_PED())
g_sSelectorUI.bManualSelection = FALSE
//////////////////////////////////////////////////////////////////////////////////
/// [4] Update the references that we have to the selector peds
///
selectorPeds.ePreviousSelectorPed = GET_SELECTOR_SLOT_FROM_PLAYER_PED_ENUM(ePedRep)
// If the ePreviousSelectorPed points to an invalid slot, we must be returning from multi-player
IF selectorPeds.ePreviousSelectorPed = NUMBER_OF_SELECTOR_PEDS
selectorPeds.ePreviousSelectorPed = SELECTOR_PED_MULTIPLAYER
ENDIF
selectorPeds.pedID[selectorPeds.ePreviousSelectorPed] = originalPlayerPedID
selectorPeds.pedID[selectorPeds.eNewSelectorPed] = NULL // currently points to the player's ped index
selectorPeds.eCurrentSelectorPed = GET_SELECTOR_SLOT_FROM_PLAYER_PED_ENUM(ePedSel)
selectorPeds.eNewSelectorPed = NUMBER_OF_SELECTOR_PEDS
//////////////////////////////////////////////////////////////////////////////////
/// [5] Update the players info
///
PED_INDEX currentPlayerPedID = PLAYER_PED_ID()
//FREEZE_ENTITY_POSITION(PLAYER_PED_ID(), FALSE)
SET_ENTITY_VISIBLE(PLAYER_PED_ID(), TRUE)
//RESTORE_PLAYER_PED_COMPONENT_VARIATIONS(currentPlayerPedID)
//RESTORE_PLAYER_PED_PROPS(currentPlayerPedID)
//RESTORE_PLAYER_PED_WEAPONS(currentPlayerPedID)
//RESTORE_PLAYER_PED_ARMOUR(currentPlayerPedID
RESTORE_PLAYER_PED_HEALTH(currentPlayerPedID)
SET_PED_CAN_LOSE_PROPS_ON_DAMAGE(currentPlayerPedID, FALSE)
// Make sure the player now has atleast 25% when we switch to them
IF fSelectedPedHealthPerc < 25.0
AND NOT IS_PED_SWIMMING_UNDER_WATER(PLAYER_PED_ID())
PRINTLN("Players health is low so increasing to 25%")
SET_ENTITY_HEALTH(PLAYER_PED_ID(), ROUND(((25.0 / 100.0) * (TO_FLOAT(GET_PED_MAX_HEALTH(PLAYER_PED_ID())) - 100.0)) + 100.0))
ENDIF
//////////////////////////////////////////////////////////////////////////////////
/// [6] Update the previous players info
///
IF bKeepPlayerReplacement
IF DOES_ENTITY_EXIST(originalPlayerPedID)
//FREEZE_ENTITY_POSITION(originalPlayerPedID, FALSE)
SET_ENTITY_VISIBLE(originalPlayerPedID, TRUE)
//RESTORE_PLAYER_PED_COMPONENT_VARIATIONS(originalPlayerPedID)
//RESTORE_PLAYER_PED_PROPS(originalPlayerPedID)
//RESTORE_PLAYER_PED_WEAPONS(originalPlayerPedID)
//RESTORE_PLAYER_PED_ARMOUR(originalPlayerPedID)
RESTORE_PLAYER_PED_HEALTH(originalPlayerPedID)
SET_PED_CAN_LOSE_PROPS_ON_DAMAGE(originalPlayerPedID, FALSE)
SET_PED_STEALTH_MOVEMENT(originalPlayerPedID, FALSE)
ENDIF
ELSE
IF DOES_ENTITY_EXIST(originalPlayerPedID)
// B* 2312133 - Should fix Assert 3.
INT iEntityInstanceID
STRING strEntityScript = GET_ENTITY_SCRIPT(originalPlayerPedID, iEntityInstanceID)
CDEBUG1LN(DEBUG_INIT_SP, " - selector_public - strEntityScript: ", strEntityScript)
IF NOT IS_STRING_NULL(strEntityScript) // Ensure that the entity is owned by script
IF NOT ARE_STRINGS_EQUAL(strEntityScript, GET_THIS_SCRIPT_NAME())
CDEBUG1LN(DEBUG_INIT_SP, " - selector_public - strEntityScript is from a different script.")
CDEBUG1LN(DEBUG_INIT_SP, " - selector_public - Setting originalPlayerPedID to be owned by this script.")
SET_ENTITY_AS_MISSION_ENTITY(originalPlayerPedID, FALSE, TRUE) // Ensure that the entity is owned by THIS script
ENDIF
PRINTLN("TAKE_CONTROL_OF_SELECTOR_PED - Deleting previous player ped")
DELETE_PED(originalPlayerPedID)
ENDIF
ENDIF
ENDIF
// Player switched so perform some maintenance routines.
g_bPerformCustomStatUpdate = TRUE
UPDATE_PED_AMMO_SO_IT_IS_NOT_INFINITE(PLAYER_PED_ID())
UPDATE_PLAYER_PED_BLIP_NAME()
UPDATE_PLAYER_CHARACTER_RELATIONSHIPS(ePedSel)
UPDATE_PLAYER_PED_VARIATION_STATS()
UPDATE_ALL_PLAYER_STAT_SETTINGS(ePedSel)
Update_Savehouse_Door_States(GET_CLOSEST_SAVEHOUSE(GET_ENTITY_COORDS(PLAYER_PED_ID()), NO_CHARACTER, FALSE))
RESET_PLAYER_STAMINA(PLAYER_ID())
SET_ENTITY_ONLY_DAMAGED_BY_PLAYER(PLAYER_PED_ID(), FALSE)
SET_PED_CAN_BE_DRAGGED_OUT(PLAYER_PED_ID(), TRUE)
//Reinstate player's scuba gear and parachute state.
#IF USE_CLF_DLC
IF IS_PLAYER_PLAYING(PLAYER_ID())
SET_AUTO_GIVE_PARACHUTE_WHEN_ENTER_PLANE(PLAYER_ID(), true)
SET_AUTO_GIVE_SCUBA_GEAR_WHEN_EXIT_VEHICLE(PLAYER_ID(), true)
ENDIF
#ENDIF
#IF USE_NRM_DLC
IF IS_PLAYER_PLAYING(PLAYER_ID())
SET_AUTO_GIVE_PARACHUTE_WHEN_ENTER_PLANE(PLAYER_ID(), true)
SET_AUTO_GIVE_SCUBA_GEAR_WHEN_EXIT_VEHICLE(PLAYER_ID(), true)
ENDIF
#ENDIF
#IF NOT USE_SP_DLC
IF IS_PLAYER_PLAYING(PLAYER_ID())
SET_AUTO_GIVE_PARACHUTE_WHEN_ENTER_PLANE(PLAYER_ID(), GET_MISSION_FLOW_FLAG_STATE(FLOWFLAG_AIR_VEHICLE_PARACHUTE_UNLOCKED))
ENDIF
IF IS_PLAYER_PLAYING(PLAYER_ID())
SET_AUTO_GIVE_SCUBA_GEAR_WHEN_EXIT_VEHICLE(PLAYER_ID(), GET_MISSION_FLOW_FLAG_STATE(FLOWFLAG_WATER_VEHICLE_SCUBA_GEAR_UNLOCKED))
ENDIF
#ENDIF
REGISTER_PLAYER_PED_WITH_AUTOMATIC_DOORS(ePedSel, currentPlayerPedID)
IF IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_STORY)
OR IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_STORY_FRIENDS)
OR IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_STORY_PREP)
OR IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_RANDOM_CHAR)
CPRINTLN(DEBUG_FLOW, "SWITCH from script ", GET_THIS_SCRIPT_NAME(), " setting ped flags for new player while on Story or RC mission.")
CPRINTLN(DEBUG_FLOW, "Set WillFlyThroughWindscreen to FALSE for PED_INDEX[",NATIVE_TO_INT(currentPlayerPedID),"].")
CPRINTLN(DEBUG_FLOW, "Set WillTakeDamageWhenVehicleCrashes to FALSE for PED_INDEX[",NATIVE_TO_INT(currentPlayerPedID),"].")
SET_PED_CONFIG_FLAG(currentPlayerPedID, PCF_WillFlyThroughWindscreen, FALSE)
SET_PED_CONFIG_FLAG(currentPlayerPedID, PCF_WillTakeDamageWhenVehicleCrashes, FALSE)
ELSE
CPRINTLN(DEBUG_FLOW, "SWITCH from script ", GET_THIS_SCRIPT_NAME(), " setting ped flags for new player while not on mission.")
CPRINTLN(DEBUG_FLOW, "Set WillFlyThroughWindscreen to TRUE for PED_INDEX[",NATIVE_TO_INT(currentPlayerPedID),"].")
CPRINTLN(DEBUG_FLOW, "Set WillTakeDamageWhenVehicleCrashes to TRUE for PED_INDEX[",NATIVE_TO_INT(currentPlayerPedID),"].")
SET_PED_CONFIG_FLAG(currentPlayerPedID, PCF_WillFlyThroughWindscreen, TRUE)
SET_PED_CONFIG_FLAG(currentPlayerPedID, PCF_WillTakeDamageWhenVehicleCrashes, TRUE)
ENDIF
IF NOT IS_SELECTOR_CAM_ACTIVE()
UPDATE_PLAYER_PED_TIMECYCLE_MODIFIER()
ENDIF
//Clear lead-in streaming block.
g_bBlockTriggerSceneLoadDuringSwitch = FALSE
CPRINTLN(DEBUG_TRIGGER, "Player ped just switched. Clearing lead-in load block flag.")
RETURN TRUE // Player now taken control of selector ped
// Problems with peds
ELSE
IF IS_PED_INJURED(PLAYER_PED_ID())
PRINTLN("Cannot take control of selector ped as the PLAYER is dead or do not exist.")
#IF IS_DEBUG_BUILD
CWARNINGLN(DEBUG_TRIGGER, "Cannot take control of selector ped as the PLAYER is dead or do not exist.")
#ENDIF
ENDIF
IF IS_PED_INJURED(selectorPeds.pedID[selectorPeds.eNewSelectorPed])
PRINTLN("Cannot take control of selector ped as the PED is dead or do not exist.")
#IF IS_DEBUG_BUILD
CWARNINGLN(DEBUG_TRIGGER, "Cannot take control of selector ped as the PED is dead or do not exist.")
#ENDIF
ENDIF
IF (PLAYER_PED_ID() = selectorPeds.pedID[selectorPeds.eNewSelectorPed])
PRINTLN("Cannot take control of selector ped as PLAYER = PED[", GET_PLAYER_PED_STRING(GET_PLAYER_PED_ENUM_FROM_SELECTOR_SLOT(selectorPeds.eNewSelectorPed)), "].")
#IF IS_DEBUG_BUILD
CWARNINGLN(DEBUG_TRIGGER, "Cannot take control of selector ped as PLAYER = PED[", GET_PLAYER_PED_STRING(GET_PLAYER_PED_ENUM_FROM_SELECTOR_SLOT(selectorPeds.eNewSelectorPed)), "].")
#ENDIF
ENDIF
ENDIF
RETURN FALSE // Come across an error
ENDFUNC
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// SELECTOR UI COMMANDS ///
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// PURPOSE: Returns TRUE if the selector is disabled
FUNC BOOL IS_SELECTOR_DISABLED()
RETURN (g_sSelectorUI.bDisabled OR g_sSelectorUI.bDisabledThisFrame)
ENDFUNC
// PURPOSE: Returns TRUE if the selector UI is on screen
FUNC BOOL IS_SELECTOR_ONSCREEN(BOOL bFullUI = TRUE)
IF bFullUI
RETURN (g_sSelectorUI.bOnScreen AND g_sSelectorUI.eUIStateCurrent = SELECTOR_UI_FULL)
ELSE
RETURN (g_sSelectorUI.bOnScreen)
ENDIF
ENDFUNC
FUNC BOOL IS_REPLAY_RECORDING_FEED_BUTTONS_ONSCREEN()
RETURN (g_sSelectorUI.bFeedAddedForRecording)
ENDFUNC
// PURPOSE: Allow the selector hud to operate
PROC ENABLE_SELECTOR()
#IF IS_DEBUG_BUILD
PRINTSTRING("\n ENABLE_SELECTOR() called by '")PRINTSTRING(GET_THIS_SCRIPT_NAME())PRINTSTRING("'")PRINTNL()
#ENDIF
g_sSelectorUI.bDisabled = FALSE
ENDPROC
// PURPOSE: Prevent the selector hud from working
PROC DISABLE_SELECTOR()
#IF IS_DEBUG_BUILD
PRINTSTRING("\n DISABLE_SELECTOR() called by '")PRINTSTRING(GET_THIS_SCRIPT_NAME())PRINTSTRING("'")PRINTNL()
#ENDIF
g_sSelectorUI.bDisabled = TRUE
ENDPROC
// PURPOSE: Prevent the selector hud from working
PROC DISABLE_SELECTOR_THIS_FRAME()
#IF IS_DEBUG_BUILD
IF IS_STRING_NULL_OR_EMPTY(g_sSelectorUI.tlDisableScript)
OR NOT ARE_STRINGS_EQUAL(GET_THIS_SCRIPT_NAME(), g_sSelectorUI.tlDisableScript)
DEBUG_PRINTCALLSTACK()
PRINTSTRING("\n DISABLE_SELECTOR_THIS_FRAME() called by '")PRINTSTRING(GET_THIS_SCRIPT_NAME())PRINTSTRING("'")PRINTNL()
g_sSelectorUI.tlDisableScript = GET_THIS_SCRIPT_NAME()
ENDIF
#ENDIF
g_sSelectorUI.bDisabledThisFrame = TRUE
ENDPROC
// PURPOSE: Prevent the selector hud from overriding the players position on the map
PROC DISABLE_SELECTOR_MAP_UPDATE_THIS_FRAME()
g_sSelectorUI.bDisableMapOverrideThisFrame = TRUE
ENDPROC
// PURPOSE: Prevent the selector hud from rendering
PROC HIDE_SELECTOR_THIS_FRAME(BOOL bHide = TRUE, BOOL bAllowSelection = FALSE)
#IF IS_DEBUG_BUILD
IF IS_STRING_NULL_OR_EMPTY(g_sSelectorUI.tlHideScript)
OR NOT ARE_STRINGS_EQUAL(GET_THIS_SCRIPT_NAME(), g_sSelectorUI.tlHideScript)
IF bHide
PRINTSTRING("\n HIDE_SELECTOR_THIS_FRAME(TRUE) called by '")PRINTSTRING(GET_THIS_SCRIPT_NAME())PRINTSTRING("'")PRINTNL()
ELSE
PRINTSTRING("\n HIDE_SELECTOR_THIS_FRAME(FALSE) called by '")PRINTSTRING(GET_THIS_SCRIPT_NAME())PRINTSTRING("'")PRINTNL()
ENDIF
g_sSelectorUI.tlHideScript = GET_THIS_SCRIPT_NAME()
ENDIF
#ENDIF
g_sSelectorUI.bHiddenThisFrame = bHide
g_sSelectorUI.bAllowSelectionWhenHidden = bAllowSelection
ENDPROC
// PURPOSE: Prevent the selector hud from rendering
PROC FORCE_LOAD_SELECTOR_THIS_FRAME()
g_sSelectorUI.bForceLoadThisFrame = TRUE
ENDPROC
PROC DISABLE_SELECTOR_QUICK_SWITCH_TO_DAMAGED_PED(BOOL bDisable)
#IF IS_DEBUG_BUILD
IF bDisable
PRINTSTRING("\n DISABLE_SELECTOR_QUICK_SWITCH_TO_DAMAGED_PED(TRUE) called by '")PRINTSTRING(GET_THIS_SCRIPT_NAME())PRINTSTRING("'")PRINTNL()
ELSE
PRINTSTRING("\n DISABLE_SELECTOR_QUICK_SWITCH_TO_DAMAGED_PED(FALSE) called by '")PRINTSTRING(GET_THIS_SCRIPT_NAME())PRINTSTRING("'")PRINTNL()
ENDIF
#ENDIF
g_sSelectorUI.bBlockQuickSwitchToDamagedPed = bDisable
ENDPROC
// PURPOSE: Allow the selector sfx to play
PROC ENABLE_SELECTOR_SFX()
#IF IS_DEBUG_BUILD
PRINTSTRING("\n ENABLE_SELECTOR_SFX() called by '")PRINTSTRING(GET_THIS_SCRIPT_NAME())PRINTSTRING("'")PRINTNL()
#ENDIF
g_sSelectorUI.bSFX_BlockAudioCalls = FALSE
ENDPROC
// PURPOSE: Prevent the selector sfx from playing
PROC DISABLE_SELECTOR_SFX()
#IF IS_DEBUG_BUILD
PRINTSTRING("\n DISABLE_SELECTOR_SFX() called by '")PRINTSTRING(GET_THIS_SCRIPT_NAME())PRINTSTRING("'")PRINTNL()
#ENDIF
g_sSelectorUI.bSFX_BlockAudioCalls = TRUE
ENDPROC
/// PURPOSE: Allows a specific icon to be displayed on the SWITCH UI
/// NTOE: COMMAND NOW OBSOLETE
PROC SET_SELECTOR_PED_ACTIVITY(SELECTOR_PED_STRUCT &sSelectorPeds, SELECTOR_SLOTS_ENUM ePed, SELECTOR_ACTIVITY_ENUM eActivity)
IF ePed <> ePEd
AND eActivity != eActivity
AND sSelectorPeds.bAmbient
ENDIF
ENDPROC
/// PURPOSE: Allows a specific icon to be displayed on the SWITCH UI
PROC SET_SELECTOR_PED_ICON(SELECTOR_PED_STRUCT &sSelectorPeds, SELECTOR_SLOTS_ENUM ePed, SELECTOR_ICON_ENUM eIcon)
IF ePed <> NUMBER_OF_SELECTOR_PEDS
sSelectorPeds.eIcons[ePed] = eIcon
ENDIF
ENDPROC
/// PURPOSE: Sets the fake selector ped state so we can override ui.
PROC SET_SELECTOR_PED_FAKE_STATE(SELECTOR_PED_STRUCT &sSelectorPeds, SELECTOR_SLOTS_ENUM ePed, SELECTOR_STATE_ENUM eState)
IF ePed <> NUMBER_OF_SELECTOR_PEDS
sSelectorPeds.eFakeState[ePed] = eState
g_sSelectorUI.bFakeStateUpdated = TRUE
ENDIF
ENDPROC
/// PURPOSE: Sets the hint flag so that we can indicate who the player should select
PROC SET_SELECTOR_PED_HINT(SELECTOR_PED_STRUCT &sSelectorPeds, SELECTOR_SLOTS_ENUM ePed, BOOL bHinted = TRUE)
IF ePed <> NUMBER_OF_SELECTOR_PEDS
sSelectorPeds.bDisplayHint[ePed] = bHinted
ENDIF
ENDPROC
/// PURPOSE: Sets the damaged flag so that we can indicate who the player should select
PROC SET_SELECTOR_PED_DAMAGED(SELECTOR_PED_STRUCT &sSelectorPeds, SELECTOR_SLOTS_ENUM ePed, BOOL bDamaged = TRUE)
IF ePed <> NUMBER_OF_SELECTOR_PEDS
sSelectorPeds.bDisplayDamage[ePed] = bDamaged
ENDIF
ENDPROC
/// PURPOSE: Sets the priority order when making auto selection
/// NOTE: QUICK SWITCH
PROC SET_SELECTOR_PED_PRIORITY(SELECTOR_PED_STRUCT &sSelectorPeds, SELECTOR_SLOTS_ENUM ePed1, SELECTOR_SLOTS_ENUM ePed2, SELECTOR_SLOTS_ENUM ePed3)
sSelectorPeds.bUseCustomAutoSelectOption = TRUE
sSelectorPeds.eAutoSelectOption1 = ePed1
sSelectorPeds.eAutoSelectOption2 = ePed2
sSelectorPeds.eAutoSelectOption3 = ePed3
ENDPROC
/// PURPOSE: Sets the auto selection priority to use default
PROC CLEAR_SELECTOR_PED_PRIORITY(SELECTOR_PED_STRUCT &sSelectorPeds)
sSelectorPeds.bUseCustomAutoSelectOption = FALSE
ENDPROC
/// PURPOSE: Blocks the selector ped from being selected
PROC SET_SELECTOR_PED_BLOCKED(SELECTOR_PED_STRUCT &sSelectorPeds, SELECTOR_SLOTS_ENUM ePed, BOOL bBlockPed = TRUE)
IF ePed <> NUMBER_OF_SELECTOR_PEDS
sSelectorPeds.bBlockSelectorPed[ePed] = bBlockPed
#IF IS_DEBUG_BUILD
PRINTSTRING("\n SET_SELECTOR_PED_BLOCKED - ")PRINTSTRING(GET_PLAYER_PED_STRING(GET_PLAYER_PED_ENUM_FROM_SELECTOR_SLOT(ePed)))
IF bBlockPed
PRINTSTRING(" blocked")PRINTNL()
ELSE
PRINTSTRING(" unblocked")PRINTNL()
ENDIF
#ENDIF
ENDIF
ENDPROC
/// PURPOSE: Checks to see if a selector ped can be selected at this point in the flow
FUNC BOOL IS_SELECTOR_PED_INTRODUCED_IN_FLOWclf(SELECTOR_SLOTS_ENUM ePed)
IF g_savedGlobalsClifford.sFlow.isGameflowActive
OR IS_REPEAT_PLAY_ACTIVE() // this is also needed for repeat play
// Allow last known player ped when in multiplayer
IF (NOT g_bInMultiplayer)
OR (g_bInMultiplayer AND ePed != GET_SELECTOR_SLOT_FROM_PLAYER_PED_ENUM(GET_LAST_KNOWN_PLAYER_PED_ENUM()))
// Introduced?
IF ePed = SELECTOR_PED_MICHAEL
OR ePed = SELECTOR_PED_FRANKLIN
RETURN FALSE
ENDIF
ENDIF
ENDIF
RETURN TRUE
ENDFUNC
FUNC BOOL IS_SELECTOR_PED_INTRODUCED_IN_FLOWNRM(SELECTOR_SLOTS_ENUM ePed)
IF g_savedGlobalsnorman.sFlow.isGameflowActive
OR IS_REPEAT_PLAY_ACTIVE() // this is also needed for repeat play
// Allow last known player ped when in multiplayer
IF (NOT g_bInMultiplayer)
OR (g_bInMultiplayer AND ePed != GET_SELECTOR_SLOT_FROM_PLAYER_PED_ENUM(GET_LAST_KNOWN_PLAYER_PED_ENUM()))
// Introduced?
// IF ePed = SELECTOR_PED_TREVOR
// OR ePed = SELECTOR_PED_FRANKLIN
// RETURN FALSE
// ENDIF
ENDIF
ENDIF
RETURN TRUE
ENDFUNC
FUNC BOOL IS_SELECTOR_PED_INTRODUCED_IN_FLOW(SELECTOR_SLOTS_ENUM ePed)
#IF USE_CLF_DLC
return IS_SELECTOR_PED_INTRODUCED_IN_FLOWclf(ePed)
#ENDIF
#if USE_NRM_DLC
return IS_SELECTOR_PED_INTRODUCED_IN_FLOWNRM(ePed)
#endif
#if not USE_CLF_DLC
#if not USE_NRM_DLC
IF g_savedGlobals.sFlow.isGameflowActive
OR g_bMagDemoActive
OR IS_REPEAT_PLAY_ACTIVE() // this is also needed for repeat play
// Allow last known player ped when in multiplayer
IF (NOT g_bInMultiplayer)
OR (g_bInMultiplayer AND ePed != GET_SELECTOR_SLOT_FROM_PLAYER_PED_ENUM(GET_LAST_KNOWN_PLAYER_PED_ENUM()))
// Introduced?
IF (ePed = SELECTOR_PED_MICHAEL AND NOT Get_Mission_Flow_Flag_State(FLOWFLAG_PLAYER_PED_INTRODUCED_M))
OR (ePed = SELECTOR_PED_FRANKLIN AND NOT Get_Mission_Flow_Flag_State(FLOWFLAG_PLAYER_PED_INTRODUCED_F))
OR (ePed = SELECTOR_PED_TREVOR AND NOT Get_Mission_Flow_Flag_State(FLOWFLAG_PLAYER_PED_INTRODUCED_T))
RETURN FALSE
ENDIF
ENDIF
ENDIF
RETURN TRUE
#endif
#endif
ENDFUNC
/// PURPOSE: Checks to see if a selector ped can be selected at this point in the flow
FUNC BOOL IS_SELECTOR_PED_AVAILABLE_IN_FLOW(SELECTOR_SLOTS_ENUM ePed)
#IF USE_CLF_DLC
//CLF check
IF g_bLoadedClifford
if ePed = SELECTOR_PED_FRANKLIN or ePed = SELECTOR_PED_MICHAEL
RETURN FALSE
ELSE
RETURN TRUE
ENDIF
ENDIF
#ENDIF
IF g_savedGlobals.sFlow.isGameflowActive
OR g_bMagDemoActive
#IF NOT DEFINED(USE_SELECTOR_CHANGES)
// Allow last known player ped when in multiplayer
IF (NOT g_bInMultiplayer)
OR (g_bInMultiplayer AND ePed != GET_SELECTOR_SLOT_FROM_PLAYER_PED_ENUM(GET_LAST_KNOWN_PLAYER_PED_ENUM()))
#ENDIF
// Available?
IF NOT IS_PLAYER_PED_AVAILABLE(GET_PLAYER_PED_ENUM_FROM_SELECTOR_SLOT(ePed))
RETURN FALSE
ENDIF
#IF NOT DEFINED(USE_SELECTOR_CHANGES)
ENDIF
#ENDIF
ENDIF
RETURN TRUE
ENDFUNC
/// PURPOSE: Checks to see if the specified player character is the same as the current selection
FUNC BOOL HAS_SELECTOR_PED_BEEN_SELECTED(SELECTOR_PED_STRUCT &sSelectorPeds, SELECTOR_SLOTS_ENUM eSelectedPed)
IF sSelectorPeds.bInitialised
IF eSelectedPed = sSelectorPeds.eNewSelectorPed
RETURN TRUE
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE: Checks to see if the specified player character is the same as the current selection
FUNC BOOL HAS_ANY_SELECTOR_PED_BEEN_SELECTED(SELECTOR_PED_STRUCT &sSelectorPeds)
IF sSelectorPeds.bInitialised
IF sSelectorPeds.eNewSelectorPed <> NUMBER_OF_SELECTOR_PEDS
AND sSelectorPeds.eNewSelectorPed <> SELECTOR_PED_MULTIPLAYER
RETURN TRUE
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE: Checks to see if the multiplayer option has been selected
FUNC BOOL HAS_MULTIPLAYER_BEEN_SELECTED(SELECTOR_PED_STRUCT &sSelectorPeds)
IF sSelectorPeds.bInitialised
IF sSelectorPeds.eNewSelectorPed = SELECTOR_PED_MULTIPLAYER
RETURN TRUE
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
FUNC INT GET_SELECTOR_UI_SLOT_FOR_SELECTOR_PED(SELECTOR_SLOTS_ENUM ePed)
IF ePed = SELECTOR_PED_MICHAEL RETURN 3 // Left
ELIF ePed = SELECTOR_PED_FRANKLIN RETURN 0 // Top
ELIF ePed = SELECTOR_PED_TREVOR RETURN 1 // Right
ELIF ePed = SELECTOR_PED_MULTIPLAYER RETURN 2 // Bottom
ENDIF
RETURN 0
ENDFUNC
FUNC SELECTOR_SLOTS_ENUM GET_SELECTOR_PED_FROM_UI_SLOT(INT iSlot)
IF iSlot = 3 RETURN SELECTOR_PED_MICHAEL // Left
ELIF iSlot = 0 RETURN SELECTOR_PED_FRANKLIN // Top
ELIF iSlot = 1 RETURN SELECTOR_PED_TREVOR // Right
ELIF iSlot = 2 RETURN SELECTOR_PED_MULTIPLAYER // Bottom
ENDIF
RETURN SELECTOR_PED_MICHAEL
ENDFUNC
PROC DISPLAY_SELECTOR_PED_AUTOSWITCH_UI(SELECTOR_SLOTS_ENUM eAutoSwitchPed)
// This is currently placeholder - disabling for now.
EXIT
PRINTLN("DISPLAY_SELECTOR_PED_AUTOSWITCH_UI - called for selector ped ", eAutoSwitchPed)
#IF IS_DEBUG_BUILD
DEBUG_PRINTCALLSTACK()
#ENDIF
g_sSelectorUI.bShowAutoSwitch = TRUE
g_sSelectorUI.iAutoSwitchSlot = GET_SELECTOR_UI_SLOT_FOR_SELECTOR_PED(eAutoSwitchPed)
g_sSelectorUI.iAutoSwitchTimer = GET_GAME_TIMER()
ENDPROC
/// PURPOSE: Sets the enum of the ped we want to take control of
/// NOTE: This is the alternative to using the interface
FUNC BOOL MAKE_SELECTOR_PED_SELECTION(SELECTOR_PED_STRUCT &sSelectorPeds, SELECTOR_SLOTS_ENUM eSelectedPed)
// Reset the selected ped
IF NOT sSelectorPeds.bInitialised
sSelectorPeds.eNewSelectorPed = NUMBER_OF_SELECTOR_PEDS
sSelectorPeds.bInitialised = TRUE
ENDIF
IF eSelectedPed <> SELECTOR_PED_MICHAEL
AND eSelectedPed <> SELECTOR_PED_TREVOR
AND eSelectedPed <> SELECTOR_PED_FRANKLIN
#IF IS_DEBUG_BUILD
PRINTLN("\n***")
PRINTLN("NO CHARACTER has been selected for SWITCH!")
PRINTLN("***\n")
#ENDIF
ELSE
#IF IS_DEBUG_BUILD
PRINTLN("MAKE_SELECTOR_PED_SELECTION: ped=", ENUM_TO_INT(eSelectedPed),
", current=", GET_SELECTOR_SLOT_FROM_PLAYER_PED_ENUM(GET_CURRENT_PLAYER_PED_ENUM()) = eSelectedPed,
", fake available=", (sSelectorPeds.eFakeState[eSelectedPed] = SELECTOR_STATE_AVAILABLE),
", fake current=", (sSelectorPeds.eFakeState[eSelectedPed] = SELECTOR_STATE_CURRENT),
", introduced=", IS_SELECTOR_PED_INTRODUCED_IN_FLOW(eSelectedPed),
", available=", IS_SELECTOR_PED_AVAILABLE_IN_FLOW(eSelectedPed),
", blocked=", sSelectorPeds.bBlockSelectorPed[eSelectedPed],
// ", injured=", IS_PED_INJURED(sSelectorPeds.pedID[eSelectedPed]),
", wantedlevel=", GET_PLAYER_WANTED_LEVEL(PLAYER_ID()))
#ENDIF
BOOL bUsingFakePed = (sSelectorPeds.eFakeState[eSelectedPed] = SELECTOR_STATE_AVAILABLE)
IF GET_SELECTOR_SLOT_FROM_PLAYER_PED_ENUM(GET_CURRENT_PLAYER_PED_ENUM()) <> eSelectedPed
OR bUsingFakePed
// If we are in ambient mode then make sure the ped is available
BOOL bPedAvailable = FALSE
#IF USE_CLF_DLC
IF bUsingFakePed
OR (sSelectorPeds.eIcons[eSelectedPed] != SELECTOR_ICON_DEFAULT)
OR (IS_SELECTOR_PED_INTRODUCED_IN_FLOW(eSelectedPed) AND IS_SELECTOR_PED_AVAILABLE_IN_FLOW(eSelectedPed) AND NOT sSelectorPeds.bBlockSelectorPed[eSelectedPed])
#ENDIF
#IF USE_NRM_DLC
IF bUsingFakePed
OR (sSelectorPeds.eIcons[eSelectedPed] != SELECTOR_ICON_DEFAULT)
OR (IS_SELECTOR_PED_INTRODUCED_IN_FLOW(eSelectedPed) AND IS_SELECTOR_PED_AVAILABLE_IN_FLOW(eSelectedPed) AND NOT sSelectorPeds.bBlockSelectorPed[eSelectedPed])
#ENDIF
#IF NOT USE_SP_DLC
IF bUsingFakePed
OR (sSelectorPeds.eIcons[eSelectedPed] != SELECTOR_ICON_DEFAULT)
OR (IS_SELECTOR_PED_INTRODUCED_IN_FLOW(eSelectedPed) AND IS_SELECTOR_PED_AVAILABLE_IN_FLOW(eSelectedPed) AND NOT sSelectorPeds.bBlockSelectorPed[eSelectedPed])
#ENDIF
IF (NOT sSelectorPeds.bAmbient)
IF (NOT IS_PED_INJURED(sSelectorPeds.pedID[eSelectedPed]) OR bUsingFakePed)
IF (sSelectorPeds.eFakeState[eSelectedPed] <> SELECTOR_STATE_UNAVAILABLE)
AND (sSelectorPeds.eFakeState[eSelectedPed] <> SELECTOR_STATE_CURRENT)
PRINTLN("bPedAvailable = TRUE [NOT sSelectorPeds.bAmbient]")
bPedAvailable = TRUE
ENDIF
ENDIF
ELSE
// Fix for bug #725557 - Don't let player switch with wanted level see imran
// - Still need UI to display so we can select multiplayer.
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
AND (NETWORK_IS_GAME_IN_PROGRESS() OR GET_PLAYER_WANTED_LEVEL(PLAYER_ID()) = 0)
//#IF NOT USE_TU_CHANGES
AND NOT IS_BIT_SET(g_sPlayerPedRequest.iBitsetPedInLeadIn, ENUM_TO_INT(eSelectedPed)) //Block switching to player's created in lead-ins.
//#ENDIF
PRINTLN("bPedAvailable = TRUE [sSelectorPeds.bAmbient]")
bPedAvailable = TRUE
ENDIF
ENDIF
#IF USE_CLF_DLC
// allow stats to display when we boot into debug
ELIF NOT (IS_BIT_SET(g_savedGlobalsClifford.sFlow.strandSavedVars[STRAND_CLF].savedBitflags, SAVED_BITS_STRAND_ACTIVATED)
AND NOT IS_REPEAT_PLAY_ACTIVE())
IF (sSelectorPeds.bAmbient)
bPedAvailable = TRUE
IF eSelectedPed = SELECTOR_PED_FRANKLIN OR eSelectedPed = SELECTOR_PED_MICHAEL
PRINTLN("bPedAvailable = TRUE [USE_CLF_DLC]")
bPedAvailable = FALSE
ENDIF
ENDIF
ENDIF
#ENDIF
#IF USE_NRM_DLC
// allow stats to display when we boot into debug
ELIF NOT (IS_BIT_SET(g_savedGlobalsnorman.sFlow.strandSavedVars[STRAND_NRM_SURVIVE].savedBitflags, SAVED_BITS_STRAND_ACTIVATED)
AND NOT IS_REPEAT_PLAY_ACTIVE())
IF (sSelectorPeds.bAmbient)
PRINTLN("bPedAvailable = TRUE [USE_NRM_DLC]")
bPedAvailable = TRUE
ENDIF
ENDIF
#ENDIF
#IF NOT USE_SP_DLC
// allow stats to display when we boot into debug
ELIF NOT (IS_BIT_SET(g_savedGlobals.sFlow.strandSavedVars[STRAND_PROLOGUE].savedBitflags, SAVED_BITS_STRAND_ACTIVATED)
AND NOT g_bMagDemoActive AND NOT IS_REPEAT_PLAY_ACTIVE())
IF (sSelectorPeds.bAmbient)
PRINTLN("bPedAvailable = TRUE [NOT USE_SP_DLC]")
bPedAvailable = TRUE
ENDIF
ENDIF
#ENDIF
IF bPedAvailable
#IF IS_DEBUG_BUILD
PRINTLN("\n***")
PRINTLN(GET_PLAYER_PED_STRING(GET_PLAYER_PED_ENUM_FROM_SELECTOR_SLOT(eSelectedPed)), " has been selected for SWITCH [fc ", GET_FRAME_COUNT(), "]!")
PRINTLN("***\n")
#ENDIF
sSelectorPeds.eNewSelectorPed = eSelectedPed
#IF NOT USE_TU_CHANGES
IF NOT g_sSelectorUI.bOnScreen
DISPLAY_SELECTOR_PED_AUTOSWITCH_UI(eSelectedPed)
ENDIF
#ENDIF
RETURN TRUE
ENDIF
ENDIF
ENDIF
// Set this flag to false to prevent the take control command from hitting array overrun.
sSelectorPeds.bInitialised = FALSE
RETURN FALSE
ENDFUNC
/// PURPOSE: Sets the enum of the ped we want to take control of
/// NOTE: This is the alternative to using the interface
FUNC BOOL MAKE_DIRECTOR_MODE_SELECTOR_PED_SELECTION(SELECTOR_PED_STRUCT &sSelectorPeds, SELECTOR_SLOTS_ENUM eSelectedPed)
// Reset the selected ped
IF NOT sSelectorPeds.bInitialised
sSelectorPeds.eNewSelectorPed = NUMBER_OF_SELECTOR_PEDS
sSelectorPeds.bInitialised = TRUE
ENDIF
#IF IS_DEBUG_BUILD
PRINTLN("MAKE_DIRECTOR_MODE_SELECTOR_PED_SELECTION: ped=", ENUM_TO_INT(eSelectedPed),
", current=", GET_SELECTOR_SLOT_FROM_PLAYER_PED_ENUM(GET_CURRENT_PLAYER_PED_ENUM()) = eSelectedPed,
", introduced=", IS_SELECTOR_PED_INTRODUCED_IN_FLOW(eSelectedPed),
", available=", IS_SELECTOR_PED_AVAILABLE_IN_FLOW(eSelectedPed))
#ENDIF
// If we are in ambient mode then make sure the ped is available
BOOL bPedAvailable = FALSE
#IF USE_CLF_DLC
IF eSelectedPed = SELECTOR_PED_MULTIPLAYER
OR eSelectedPed = GET_SELECTOR_SLOT_FROM_PLAYER_PED_ENUM(g_savedGlobalsClifford.sPlayerData.sInfo.eLastKnownPed)
#ENDIF
#IF USE_NRM_DLC
IF eSelectedPed = SELECTOR_PED_MULTIPLAYER
OR eSelectedPed = GET_SELECTOR_SLOT_FROM_PLAYER_PED_ENUM(g_savedGlobalsnorman.sPlayerData.sInfo.eLastKnownPed)
#ENDIF
#IF NOT USE_SP_DLC
IF eSelectedPed = SELECTOR_PED_MULTIPLAYER
OR eSelectedPed = GET_SELECTOR_SLOT_FROM_PLAYER_PED_ENUM(g_savedGlobals.sPlayerData.sInfo.eLastKnownPed)
#ENDIF
// Fix for bug #725557 - Don't let player switch with wanted level see imran
// - Still need UI to display so we can select multiplayer.
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
PRINTLN("bPedAvailable = TRUE [sSelectorPeds.bAmbient]")
bPedAvailable = TRUE
ENDIF
#IF USE_CLF_DLC
ENDIF
#ENDIF
#IF USE_NRM_DLC
ENDIF
#ENDIF
#IF NOT USE_SP_DLC
ENDIF
#ENDIF
IF bPedAvailable
#IF IS_DEBUG_BUILD
PRINTLN("\n***")
PRINTLN(GET_PLAYER_PED_STRING(GET_PLAYER_PED_ENUM_FROM_SELECTOR_SLOT(eSelectedPed)), " has been selected for SWITCH [fc ", GET_FRAME_COUNT(), "]!")
PRINTLN("***\n")
#ENDIF
sSelectorPeds.eNewSelectorPed = eSelectedPed
RETURN TRUE
ENDIF
// Set this flag to false to prevent the take control command from hitting array overrun.
sSelectorPeds.bInitialised = FALSE
RETURN FALSE
ENDFUNC
FUNC BOOL ARE_ANY_EXTERNAL_WARNING_SCREENS_RUNNING()
IF IS_WARNING_SCREEN_BAIL(WARNINGSCREEN_BAIL_TRANSITION_JOIN_FAILED)
OR IS_WARNING_SCREEN_BAIL(WARNINGSCREEN_BAIL_DROPINVITE_UNDERAGE)
OR IS_WARNING_SCREEN_BAIL(WARNINGSCREEN_BAIL_DROPINVITE_STILL_ON_TUTORIAL)
OR IS_WARNING_SCREEN_BAIL(WARNINGSCREEN_BAIL_DROPINVITE_NO_CHARACTERS)
OR IS_WARNING_SCREEN_BAIL(WARNINGSCREEN_BAIL_DROPINVITE_SESSION_FULL)
OR IS_WARNING_SCREEN_BAIL(WARNINGSCREEN_TRANSITION_CLOUD_DOWN)
OR IS_WARNING_SCREEN_BAIL(WARNINGSCREEN_TRANSITION_CLOUD_UP)
OR IS_WARNING_SCREEN_BAIL(WARNINGSCREEN_BAIL_DROPINVITE_GTAO_NOT_AVAIL)
OR IS_WARNING_SCREEN_BAIL(WARNINGSCREEN_BAIL_DROPINVITE_SP_PROLOGUE_NOT_DONE)
OR IS_WARNING_SCREEN_BAIL(WARNINGSCREEN_BAIL_DROPINVITE_SAME_SESSION)
OR IS_WARNING_SCREEN_BAIL(WARNINGSCREEN_BAIL_DROPINVITE_SAVE_ISSUE)
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE: Sets the multiplayer flag to TRUE
/// NOTE: This is the alternative to using the interface
FUNC BOOL MAKE_MULTIPLAYER_SELECTION(SELECTOR_PED_STRUCT &sSelectorPeds)
// Fix for bug 1596720 - remove text completely
IF NOT IS_GTA_ONLINE_AVAILABLE(TRUE)
#IF IS_DEBUG_BUILD
PRINTLN("\n***")
PRINTLN("Multiplayer not available!")
PRINTLN("***\n")
#ENDIF
RETURN FALSE
ENDIF
// Reset the selected ped
IF NOT sSelectorPeds.bInitialised
sSelectorPeds.eNewSelectorPed = NUMBER_OF_SELECTOR_PEDS
sSelectorPeds.bInitialised = TRUE
ENDIF
IF (NOT NETWORK_IS_GAME_IN_PROGRESS() AND NOT IS_CURRENTLY_ON_MISSION_OF_ANY_TYPE())
// Make sure the block flag is not set and it is an ambient update
IF NOT sSelectorPeds.bBlockSelectorPed[SELECTOR_PED_MULTIPLAYER]
AND sSelectorPeds.bAmbient
AND NOT g_bMagDemoActive
#IF USE_TU_CHANGES
AND IS_GTA_ONLINE_AVAILABLE()
#ENDIF
#IF IS_DEBUG_BUILD
PRINTLN("\n***")
PRINTLN("Multiplayer has been selected for SWITCH!")
PRINTLN("***\n")
#ENDIF
sSelectorPeds.eNewSelectorPed = SELECTOR_PED_MULTIPLAYER
RETURN TRUE
#IF USE_TU_CHANGES
ELSE
IF IS_GTA_ONLINE_AVAILABLE() = FALSE
AND ARE_ANY_EXTERNAL_WARNING_SCREENS_RUNNING() = FALSE
MULTIPLAYER_ACCESS_CODE nAccessCode
SCRIPT_NETWORK_CAN_ACCESS_MULTIPLAYER(nAccessCode)
#IF IS_DEBUG_BUILD
PRINTLN("\n***")
PRINTLN("Multiplayer has been selected for SWITCH! BUT IS_GTA_ONLINE_AVAILABLE() = FALSE ")
PRINTLN("Multiplayer has been selected for SWITCH! BUT IS_PLAYER_ONLINE() = ", IS_PLAYER_ONLINE())
PRINTLN("Multiplayer has been selected for SWITCH! BUT NETWORK_IS_SIGNED_ONLINE() = ", NETWORK_IS_SIGNED_ONLINE())
PRINTLN("Multiplayer has been selected for SWITCH! BUT NETWORK_HAS_VALID_ROS_CREDENTIALS() = ", NETWORK_HAS_VALID_ROS_CREDENTIALS())
PRINTLN("Multiplayer has been selected for SWITCH! BUT NETWORK_CAN_ENTER_MULTIPLAYER() = ", NETWORK_CAN_ENTER_MULTIPLAYER())
PRINTLN("Multiplayer has been selected for SWITCH! BUT SCRIPT_NETWORK_CAN_ACCESS_MULTIPLAYER(nAccessCode) = ", SCRIPT_NETWORK_CAN_ACCESS_MULTIPLAYER(nAccessCode))
#if not USE_CLF_DLC
#if not USE_NRM_DLC
PRINTLN("Multiplayer has been selected for SWITCH! BUT g_savedGlobals.sFlow.missionSavedData[SP_MISSION_PROLOGUE].completed = ", g_savedGlobals.sFlow.missionSavedData[SP_MISSION_PROLOGUE].completed)
#endif
#endif
PRINTLN("Multiplayer has been selected for SWITCH! BUT nAccessCode = ", nAccessCode)
IF IS_PLAYSTATION_PLATFORM()
PRINTLN("Multiplayer has been selected for SWITCH! BUT NETWORK_GET_NP_UNAVAILABLE_REASON = ",GET_UNAVAILABILITY_REASON_STRING(NETWORK_GET_NP_UNAVAILABLE_REASON()))
ENDIF
PRINTLN("***\n")
#ENDIF
IF nAccessCode = ACCESS_DENIED_TUNABLE_NOT_FOUND
SET_WARNING_SCREEN_BAIL(WARNINGSCREEN_BAIL_GTAO_ACCESS_DENIED, TRUE)
ELIF IS_PLAYSTATION_PLATFORM() AND NETWORK_GET_NP_UNAVAILABLE_REASON() = REASON_AGE
SET_WARNING_SCREEN_BAIL(WARNINGSCREEN_TRANSITION_UNDERAGE_NEXTGEN, TRUE)
ELIF IS_PLAYSTATION_PLATFORM() AND NETWORK_GET_NP_UNAVAILABLE_REASON() = REASON_GAME_UPDATE
SET_WARNING_SCREEN_BAIL(WARNINGSCREEN_TRANSITION_GAME_UPDATE, TRUE)
ELIF IS_PLAYSTATION_PLATFORM() AND NETWORK_GET_NP_UNAVAILABLE_REASON() = REASON_SYSTEM_UPDATE
SET_WARNING_SCREEN_BAIL(WARNINGSCREEN_TRANSITION_SYSTEM_UPDATE, TRUE)
ELIF (IS_PLAYER_ONLINE()
AND NETWORK_IS_SIGNED_ONLINE()) = FALSE
//Sign in
SET_WARNING_SCREEN_BAIL(WARNINGSCREEN_BAIL_DROPINVITE_SIGNIN, TRUE)
ELIF NETWORK_HAS_VALID_ROS_CREDENTIALS() = FALSE
ELIF NETWORK_CAN_ENTER_MULTIPLAYER() = FALSE
ELSE
SET_WARNING_SCREEN_BAIL(WARNINGSCREEN_BAIL_GTAO_ACCESS_DENIED, TRUE)
ENDIF
ENDIF
#ENDIF
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
FUNC BOOL IS_PED_EXITING_ANY_AIRBORN_VEHICLE(PED_INDEX PedIndex)
IF (IS_PED_IN_ANY_VEHICLE(PedIndex) AND NOT IS_PED_SITTING_IN_ANY_VEHICLE(PedIndex)) //#769971
VECTOR VecPedCoord = GET_ENTITY_COORDS(PedIndex)
FLOAT fPedCoordGroundZ = 0.0
IF GET_GROUND_Z_FOR_3D_COORD(VecPedCoord, fPedCoordGroundZ) //#800237
IF (VecPedCoord.z > (fPedCoordGroundZ+1.5))
//player is at least 1.5m above the ground
RETURN TRUE
ENDIF
//players vehicle on ground
RETURN FALSE
ELSE
//no groundZ, must be mid-air
RETURN TRUE
ENDIF
ENDIF
//player not exiting vehicle
RETURN FALSE
ENDFUNC
/// PURPOSE: Returns TRUE if the selector UI can be displayed
FUNC BOOL IS_SELECTOR_UI_SAFE_TO_DISPLAY(BOOL bCheckActivationButton = TRUE)
////////////////////////////////////////////////////////////////
/// Dead specific checks
IF IS_PED_INJURED(PLAYER_PED_ID())
AND NOT (g_bInMultiplayer AND IS_A_SPECTATOR_CAM_ACTIVE())
#IF IS_DEBUG_BUILD
IF IS_SELECTOR_UI_BUTTON_JUST_PRESSED(FALSE)
PRINTLN("IS_SELECTOR_UI_SAFE_TO_DISPLAY() = FALSE - Player is dead")
ENDIF
#ENDIF
RETURN FALSE
ENDIF
////////////////////////////////////////////////////////////////
/// Alive specific checks
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
// Do not allow if we are not in a suitable state
IF (IS_PLAYER_BEING_ARRESTED(PLAYER_ID(), TRUE))
OR (IS_PED_RAGDOLL(PLAYER_PED_ID()) AND bCheckActivationButton AND NOT IS_PED_DRUNK(PLAYER_PED_ID()))
OR (Is_Player_Timetable_Scene_In_Progress())
OR IS_PED_EXITING_ANY_AIRBORN_VEHICLE(PLAYER_PED_ID())
//OR (IS_PLAYER_FREE_AIMING(PLAYER_ID()))
//OR (IS_PLAYER_TARGETTING_ANYTHING(PLAYER_ID()))
OR NOT IS_SAFE_TO_START_PLAYER_SWITCH()
OR (g_flowUnsaved.bFlowControllerBusy AND NOT NETWORK_IS_GAME_IN_PROGRESS() AND NOT IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_STORY) AND NOT IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_STORY_FRIENDS) AND NOT IS_CURRENTLY_ON_MISSION_TO_TYPE(MISSION_TYPE_STORY_PREP) AND NOT IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_MINIGAME) AND NOT IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_MINIGAME_FRIENDS))
OR (g_bResultScreenDisplaying)
OR (IS_PED_IN_ANY_TRAIN(PLAYER_PED_ID()) AND GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH( HASH( "franklin0" ) ) = 0 )
#IF IS_DEBUG_BUILD
IF IS_SELECTOR_UI_BUTTON_JUST_PRESSED(FALSE)
IF (IS_PLAYER_BEING_ARRESTED(PLAYER_ID(), TRUE))
PRINTLN("IS_SELECTOR_UI_SAFE_TO_DISPLAY() = FALSE - Player is being arreseted")
ELIF (IS_PED_RAGDOLL(PLAYER_PED_ID()) AND bCheckActivationButton AND NOT IS_PED_DRUNK(PLAYER_PED_ID()))
PRINTLN("IS_SELECTOR_UI_SAFE_TO_DISPLAY() = FALSE - Player is ragdolling")
ELIF (Is_Player_Timetable_Scene_In_Progress())
PRINTLN("IS_SELECTOR_UI_SAFE_TO_DISPLAY() = FALSE - Player timetable scene in progress")
ELIF IS_PED_EXITING_ANY_AIRBORN_VEHICLE(PLAYER_PED_ID())
PRINTLN("IS_SELECTOR_UI_SAFE_TO_DISPLAY() = FALSE - Player exiting a vehice")
/*ELIF IS_PLAYER_FREE_AIMING(PLAYER_ID())
PRINTLN("IS_SELECTOR_UI_SAFE_TO_DISPLAY() = FALSE - Player is free aiming")
ELIF IS_PLAYER_TARGETTING_ANYTHING(PLAYER_ID())
PRINTLN("IS_SELECTOR_UI_SAFE_TO_DISPLAY() = FALSE - Player is targetting something")*/
ELIF NOT IS_SAFE_TO_START_PLAYER_SWITCH()IS_SAFE_TO_START_PLAYER_SWITCH()
PRINTLN("IS_SELECTOR_UI_SAFE_TO_DISPLAY() = FALSE - Not safe to start player switch")
ELIF (g_flowUnsaved.bFlowControllerBusy AND NOT NETWORK_IS_GAME_IN_PROGRESS() AND NOT IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_STORY) AND NOT IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_STORY_FRIENDS) AND NOT IS_CURRENTLY_ON_MISSION_TO_TYPE(MISSION_TYPE_STORY_PREP) AND NOT IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_MINIGAME) AND NOT IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_MINIGAME_FRIENDS))
PRINTLN("IS_SELECTOR_UI_SAFE_TO_DISPLAY() = FALSE - Flow Controller is Busy")
ELIF (g_bResultScreenDisplaying)
PRINTLN("IS_SELECTOR_UI_SAFE_TO_DISPLAY() = FALSE - Result Screen Displaying")
ELIF (IS_PED_IN_ANY_TRAIN(PLAYER_PED_ID()) AND GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH( HASH( "franklin0" ) ) = 0 )
PRINTLN("IS_SELECTOR_UI_SAFE_TO_DISPLAY() = FALSE - Player is in a train")
ELSE
PRINTLN("IS_SELECTOR_UI_SAFE_TO_DISPLAY() = FALSE - some other reason???")
ENDIF
ENDIF
#ENDIF
RETURN FALSE
ENDIF
ENDIF
////////////////////////////////////////////////////////////////
/// Multiplayer specific checks
IF (g_bInMultiplayer)
// KGM 3/10/11: Convert from old MP Comms routine to new MP Comms routine
IF (Is_Any_MP_Comms_Device_Onscreen())
#IF IS_DEBUG_BUILD
IF IS_SELECTOR_UI_BUTTON_JUST_PRESSED(FALSE)
PRINTLN("IS_SELECTOR_UI_SAFE_TO_DISPLAY() = FALSE - MP Comms device on screen")
ENDIF
#ENDIF
RETURN FALSE
ENDIF
INT iMyGBD = NATIVE_TO_INT(PLAYER_ID())
IF iMyGBD != -1
AND IS_BIT_SET(GlobalplayerBD_FM_2[iMyGBD].iBitSet, biIwantToVote)
#IF IS_DEBUG_BUILD
IF IS_SELECTOR_UI_BUTTON_JUST_PRESSED(FALSE)
PRINTLN("IS_SELECTOR_UI_SAFE_TO_DISPLAY() = FALSE - Voting")
ENDIF
#ENDIF
RETURN FALSE
ENDIF
ENDIF
////////////////////////////////////////////////////////////////
/// Singleplayer specific checks
IF (NOT g_bInMultiplayer)
enumCharacterList ePed = GET_CURRENT_PLAYER_PED_ENUM()
IF IS_PLAYER_PED_PLAYABLE(ePed)
IF (GET_PLAYER_CHAR_COMMUNICATION_PRIORITY_LEVEL(ePed) = CPR_VERY_HIGH)
IF NOT IS_REPEAT_PLAY_ACTIVE()
AND NOT IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_STORY)
AND NOT IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_STORY_FRIENDS)
AND NOT IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_STORY_PREP)
#IF IS_DEBUG_BUILD
IF IS_SELECTOR_UI_BUTTON_JUST_PRESSED(FALSE)
PRINTLN("IS_SELECTOR_UI_SAFE_TO_DISPLAY() = FALSE - Communication with priority queued")
ENDIF
#ENDIF
RETURN FALSE
ENDIF
ENDIF
ELIF NOT IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_DIRECTOR)
#IF IS_DEBUG_BUILD
IF IS_SELECTOR_UI_BUTTON_JUST_PRESSED(FALSE)
PRINTLN("IS_SELECTOR_UI_SAFE_TO_DISPLAY() = FALSE - Not a playable character and not in Director Mode.")
ENDIF
#ENDIF
RETURN FALSE
ENDIF
IF NOT g_sSelectorUI.bMissionUpdate
IF (IS_PED_IN_PARACHUTE_FREE_FALL(PLAYER_PED_ID()) AND bCheckActivationButton)
OR (GET_PED_PARACHUTE_STATE(PLAYER_PED_ID()) != PPS_INVALID AND bCheckActivationButton)
#IF IS_DEBUG_BUILD
IF IS_SELECTOR_UI_BUTTON_JUST_PRESSED(FALSE)
IF (IS_PED_IN_PARACHUTE_FREE_FALL(PLAYER_PED_ID()) AND bCheckActivationButton)
PRINTLN("IS_SELECTOR_UI_SAFE_TO_DISPLAY() = FALSE - Player is in parachute free fall")
ELIF (GET_PED_PARACHUTE_STATE(PLAYER_PED_ID()) != PPS_INVALID AND bCheckActivationButton)
PRINTLN("IS_SELECTOR_UI_SAFE_TO_DISPLAY() = FALSE - Player parachute is out")
ENDIF
ENDIF
#ENDIF
RETURN FALSE
ENDIF
IF g_sSelectorUI.bDisableForEndOfMission
#IF IS_DEBUG_BUILD
IF IS_SELECTOR_UI_BUTTON_JUST_PRESSED(FALSE)
PRINTLN("IS_SELECTOR_UI_SAFE_TO_DISPLAY() = FALSE - End of mission delay")
ENDIF
#ENDIF
RETURN FALSE
ENDIF
ENDIF
ENDIF
IF IS_PLAYER_SWITCH_IN_PROGRESS()
#IF IS_DEBUG_BUILD
IF IS_SELECTOR_UI_BUTTON_JUST_PRESSED(FALSE)
PRINTLN("IS_SELECTOR_UI_SAFE_TO_DISPLAY() = FALSE - IS_PLAYER_SWITCH_IN_PROGRESS()")
ENDIF
#ENDIF
RETURN FALSE
ENDIF
////////////////////////////////////////////////////////////////
/// Generic game checks
IF (g_sSelectorUI.bSelection)
OR (IS_SELECTOR_DISABLED())
//OR (IS_SELECTOR_CAM_ACTIVE())
OR (IS_PLAYER_SWITCH_IN_PROGRESS())
OR (IS_PLAYER_PED_SWITCH_IN_PROGRESS())
OR (IS_SCRIPT_HUD_DISPLAYING(HUDPART_TRANSITIONHUD))
OR (IS_CUTSCENE_PLAYING())
OR (IS_PHONE_ACTIVE_OR_OVERLAPPING_HUD_ITEMS()/* AND GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(HASH("appTrackify")) = 0*/)
OR (IS_PAUSE_MENU_ACTIVE())
OR (IS_SYSTEM_UI_BEING_DISPLAYED())
OR (IS_STUNT_JUMP_IN_PROGRESS())
OR (IS_CUSTOM_MENU_ON_SCREEN())
OR (GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(HASH("appCamera")) > 0)
//OR (g_bMissionOverStatTrigger)
OR (g_bPlayerIsInTaxi)
OR (g_bBrowserVisible)
OR (g_bHeistEndscreenDisplaying)
OR (IS_HUD_COMPONENT_ACTIVE(NEW_HUD_WEAPON_WHEEL) AND NOT g_sSelectorUI.bOnScreen)
OR (IS_HUD_COMPONENT_ACTIVE(NEW_HUD_RADIO_STATIONS) AND NOT g_sSelectorUI.bOnScreen)
OR IS_PLAYER_BROWSING_ITEMS_IN_ANY_SHOP()
OR IS_PLAYER_CHANGING_CLOTHES()
OR g_bBrowserVisible
OR g_eMissionTitleState = MTS_DISPLAY_CUTSCENE
OR g_eMissionTitleState = MTS_DISPLAY_GAMEPLAY
#IF USE_TU_CHANGES
OR (IS_PAUSE_MENU_ACTIVE_EX())
OR (IS_STORE_PENDING_NETWORK_SHUTDOWN_TO_OPEN())
#ENDIF
#IF IS_DEBUG_BUILD
IF IS_SELECTOR_UI_BUTTON_JUST_PRESSED(FALSE)
IF (g_sSelectorUI.bSelection)
PRINTLN("IS_SELECTOR_UI_SAFE_TO_DISPLAY() = FALSE - Selection has been made, need to process")
ELIF (IS_SELECTOR_DISABLED())
PRINTLN("IS_SELECTOR_UI_SAFE_TO_DISPLAY() = FALSE - Switch has been disabled")
ELIF (IS_SELECTOR_CAM_ACTIVE())
PRINTLN("IS_SELECTOR_UI_SAFE_TO_DISPLAY() = FALSE - Selector cam is active")
ELIF (IS_PLAYER_SWITCH_IN_PROGRESS())
PRINTLN("IS_SELECTOR_UI_SAFE_TO_DISPLAY() = FALSE - Switch in progress")
ELIF (IS_PLAYER_PED_SWITCH_IN_PROGRESS())
PRINTLN("IS_SELECTOR_UI_SAFE_TO_DISPLAY() = FALSE - Player ped switch in progress")
ELIF (IS_SCRIPT_HUD_DISPLAYING(HUDPART_TRANSITIONHUD))
PRINTLN("IS_SELECTOR_UI_SAFE_TO_DISPLAY() = FALSE - Transition hud on screen")
ELIF (IS_CUTSCENE_PLAYING())
PRINTLN("IS_SELECTOR_UI_SAFE_TO_DISPLAY() = FALSE - Cutscene playing")
ELIF (IS_PHONE_ACTIVE_OR_OVERLAPPING_HUD_ITEMS())
PRINTLN("IS_SELECTOR_UI_SAFE_TO_DISPLAY() = FALSE - Cellphone is active or overlapping hud items")
ELIF (IS_PAUSE_MENU_ACTIVE())
PRINTLN("IS_SELECTOR_UI_SAFE_TO_DISPLAY() = FALSE - Pause menu is active")
ELIF (IS_SYSTEM_UI_BEING_DISPLAYED())
PRINTLN("IS_SELECTOR_UI_SAFE_TO_DISPLAY() = FALSE - System UI is active")
ELIF (IS_STUNT_JUMP_IN_PROGRESS())
PRINTLN("IS_SELECTOR_UI_SAFE_TO_DISPLAY() = FALSE - Stunt jump in progress")
ELIF (IS_CUSTOM_MENU_ON_SCREEN())
PRINTLN("IS_SELECTOR_UI_SAFE_TO_DISPLAY() = FALSE - Custom menu is on screen")
ELIF (IS_CURRENTLY_ON_MISSION_OF_ANY_TYPE() AND NOT g_sSelectorUI.bMissionUpdate)
PRINTLN("IS_SELECTOR_UI_SAFE_TO_DISPLAY() = FALSE - Mission launched and this is ambient switch")
ELIF (GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(HASH("appCamera")) > 0)
PRINTLN("IS_SELECTOR_UI_SAFE_TO_DISPLAY() = FALSE - Phone camera is active")
ELIF (g_bPlayerIsInTaxi)
PRINTLN("IS_SELECTOR_UI_SAFE_TO_DISPLAY() = FALSE - Player in taxi")
ELIF (g_bBrowserVisible)
PRINTLN("IS_SELECTOR_UI_SAFE_TO_DISPLAY() = FALSE - Browser is visible")
ELIF (g_eMissionTitleState = MTS_DISPLAY_CUTSCENE)
PRINTLN("IS_SELECTOR_UI_SAFE_TO_DISPLAY() = FALSE - Mission title displaying during cutscene")
ELIF (g_eMissionTitleState = MTS_DISPLAY_GAMEPLAY)
PRINTLN("IS_SELECTOR_UI_SAFE_TO_DISPLAY() = FALSE - Mission title displaying during gameplay")
ELIF (g_bHeistEndscreenDisplaying)
PRINTLN("IS_SELECTOR_UI_SAFE_TO_DISPLAY() = FALSE - Heist end screen visible")
ELIF (IS_HUD_COMPONENT_ACTIVE(NEW_HUD_WEAPON_WHEEL))
PRINTLN("IS_SELECTOR_UI_SAFE_TO_DISPLAY() = FALSE - Weapon wheel is on screen")
ELIF (IS_HUD_COMPONENT_ACTIVE(NEW_HUD_RADIO_STATIONS))
PRINTLN("IS_SELECTOR_UI_SAFE_TO_DISPLAY() = FALSE - Radio station is on screen")
ELIF (IS_PLAYER_BROWSING_ITEMS_IN_ANY_SHOP())
PRINTLN("IS_SELECTOR_UI_SAFE_TO_DISPLAY() = FALSE - Player borwsing items in shop")
ELIF (IS_PLAYER_CHANGING_CLOTHES())
PRINTLN("IS_SELECTOR_UI_SAFE_TO_DISPLAY() = FALSE - Player changing clothes")
ELIF g_bBrowserVisible
PRINTLN("IS_SELECTOR_UI_SAFE_TO_DISPLAY() = FALSE - Web browser visible")
#IF USE_TU_CHANGES
ELIF (IS_PAUSE_MENU_ACTIVE_EX())
PRINTLN("IS_SELECTOR_UI_SAFE_TO_DISPLAY() = FALSE - Pause menu is active EX")
ELIF (IS_STORE_PENDING_NETWORK_SHUTDOWN_TO_OPEN())
PRINTLN("IS_SELECTOR_UI_SAFE_TO_DISPLAY() = FALSE - Store is opening")
#ENDIF
ELSE
PRINTLN("IS_SELECTOR_UI_SAFE_TO_DISPLAY() = FALSE - Some general fail case!")
ENDIF
ENDIF
#ENDIF
RETURN FALSE
ENDIF
////////////////////////////////////////////////////////////////
/// Debug checks
#IF IS_DEBUG_BUILD
IF NOT NETWORK_IS_GAME_IN_PROGRESS()
IF (GET_GAME_TIMER() - iSelectMissionStageDrawTime) < 100
PRINTLN("IS_SELECTOR_UI_SAFE_TO_DISPLAY() = FALSE - Z-Skip menu on screen")
RETURN FALSE
ENDIF
ENDIF
#ENDIF
// No issues found
RETURN TRUE
ENDFUNC
FUNC BOOL GET_MP_COUNTDOWN_STRING(TEXT_LABEL_31 &tlCountdownText, BOOL bCached)
// Fix for bug 1596720 - remove text completely
tlCountdownText = ""
RETURN FALSE
// Fix for bug 1450768 - remove countdown timer
IF IS_SPECIAL_EDITION_GAME()
OR IS_COLLECTORS_EDITION_GAME()
OR NETWORK_IS_GAME_IN_PROGRESS()
tlCountdownText = "GTA Online"
RETURN FALSE
ENDIF
IF bCached
tlCountdownText = g_sSelectorUI.tlStoredCountdown
ELSE
tlCountdownText = "GTA Online"
IF IS_PLAYER_ONLINE()
//INT iReleaseTime = 1379376000
INT iReleaseTime = g_sMPTunables.iMpCountDownTimer
INT iCurrentTime = GET_CLOUD_TIME_AS_INT()
INT iTimeDifference = (iReleaseTime-iCurrentTime)
INT iDays, iHours, iMinutes
IF iTimeDifference > 0
// DAYS
IF (iTimeDifference/86400) > 0
iDays = (iTimeDifference/86400)
iTimeDifference -= (iDays*86400)
ENDIF
// HOURS
IF (iTimeDifference/3600) > 0
iHours = (iTimeDifference/3600)
iTimeDifference -= (iHours*3600)
ENDIF
// MINUTES
IF (iTimeDifference/60) > 0
iMinutes = (iTimeDifference/60)
iTimeDifference -= (iMinutes*60)
ENDIF
// D H M
/*
tlCountdownText = ""
tlCountdownText += iDays
tlCountdownText += "d "
tlCountdownText += iHours
tlCountdownText += "h "
tlCountdownText += iMinutes
tlCountdownText += "m "
//tlCountdownText += iTimeDifference
//tlCountdownText += "s "
//PRINTLN(tlCountdownText)
*/
// D
tlCountdownText = ""
tlCountdownText += iDays
tlCountdownText += " days"
//tlCountdownText += iHours
//tlCountdownText += "h "
//tlCountdownText += iMinutes
//tlCountdownText += "m "
//tlCountdownText += iTimeDifference
//tlCountdownText += "s "
//PRINTLN(tlCountdownText)
ENDIF
ENDIF
g_sSelectorUI.tlStoredCountdown = tlCountdownText
ENDIF
RETURN (NOT ARE_STRINGS_EQUAL(tlCountdownText, "GTA Online"))
ENDFUNC
/// PURPOSE: Sets up the details of the character for the selector UI
#if USE_CLF_DLC
PROC GET_SELECTOR_PED_ENUM_FOR_UIclf(SELECTOR_PED_STRUCT &sSelectorPeds, SELECTOR_SLOTS_ENUM ePed, INT &iEnum)
//CHAR_MICHAEL = 0
//CHAR_TREVOR = 1
//CHAR_FRANKLIN = 2
//CHAR_MULTIPLAYER = 3
//CHAR_CHOP_RIGHT = 4
//CHAR_CHOP_UP = 5
//CHAR_CHOP_LEFT = 6
//CHAR_MICHAEL_MASKED_PROLOGUE=7
//CHAR_MICHAEL_UNMASKED_PROLOGUE=8
//CHAR_TREVOR_MASKED_PROLOGUE=9
//CHAR_TREVOR_UNMASKED_PROLOGUE=10
// Default slot, enum, and state
SWITCH ePed
CASE SELECTOR_PED_MICHAEL
iEnum = 0 // CHAR_MICHAEL = 0
BREAK
CASE SELECTOR_PED_FRANKLIN
iEnum = 7 // CHAR_JIMMY = 2
BREAK
CASE SELECTOR_PED_TREVOR
iEnum = 9 // CHAR_TRACEY = 1
BREAK
CASE SELECTOR_PED_MULTIPLAYER
iEnum = 3 // CHAR_MULTIPLAYER = 3
BREAK
ENDSWITCH
IF sSelectorPeds.eIcons[ePed] = SELECTOR_ICON_DEFAULT
endif
ENDPROC
#endif
#if USE_NRM_DLC
PROC GET_SELECTOR_PED_ENUM_FOR_UINRM(SELECTOR_PED_STRUCT &sSelectorPeds, SELECTOR_SLOTS_ENUM ePed, INT &iEnum)
//CHAR_MICHAEL = 0
//CHAR_TREVOR = 1
//CHAR_FRANKLIN = 2
//CHAR_MULTIPLAYER = 3
//CHAR_CHOP_RIGHT = 4
//CHAR_CHOP_UP = 5
//CHAR_CHOP_LEFT = 6
//CHAR_MICHAEL_MASKED_PROLOGUE=7
//CHAR_MICHAEL_UNMASKED_PROLOGUE=8
//CHAR_TREVOR_MASKED_PROLOGUE=9
//CHAR_TREVOR_UNMASKED_PROLOGUE=10
// Default slot, enum, and state
SWITCH ePed
CASE SELECTOR_PED_MICHAEL
iEnum = 0 // CHAR_MICHAEL = 0
BREAK
CASE SELECTOR_PED_FRANKLIN
iEnum = 7 // CHAR_JIMMY = 2
BREAK
CASE SELECTOR_PED_TREVOR
iEnum = 9 // CHAR_TRACEY = 1
BREAK
CASE SELECTOR_PED_MULTIPLAYER
iEnum = 3 // CHAR_MULTIPLAYER = 3
BREAK
ENDSWITCH
IF sSelectorPeds.eIcons[ePed] = SELECTOR_ICON_DEFAULT
endif
ENDPROC
#endif
PROC GET_SELECTOR_PED_ENUM_FOR_UI(SELECTOR_PED_STRUCT &sSelectorPeds, SELECTOR_SLOTS_ENUM ePed, INT &iEnum)
#if USE_CLF_DLC
GET_SELECTOR_PED_ENUM_FOR_UIclf(sSelectorPeds, ePed, iEnum)
#endif
#if USE_NRM_DLC
GET_SELECTOR_PED_ENUM_FOR_UINRM(sSelectorPeds, ePed, iEnum)
#endif
#if not USE_CLF_DLC
#if not USE_NRM_DLC
//CHAR_MICHAEL = 0
//CHAR_TREVOR = 1
//CHAR_FRANKLIN = 2
//CHAR_MULTIPLAYER = 3
//CHAR_CHOP_RIGHT = 4
//CHAR_CHOP_UP = 5
//CHAR_CHOP_LEFT = 6
//CHAR_MICHAEL_MASKED_PROLOGUE=7
//CHAR_MICHAEL_UNMASKED_PROLOGUE=8
//CHAR_TREVOR_MASKED_PROLOGUE=9
//CHAR_TREVOR_UNMASKED_PROLOGUE=10
// Default slot, enum, and state
SWITCH ePed
CASE SELECTOR_PED_MICHAEL
iEnum = 0 // CHAR_MICHAEL = 0
BREAK
CASE SELECTOR_PED_FRANKLIN
iEnum = 2 // CHAR_FRANKLIN = 2
BREAK
CASE SELECTOR_PED_TREVOR
iEnum = 1 // CHAR_TREVOR = 1
BREAK
CASE SELECTOR_PED_MULTIPLAYER
iEnum = 3 // CHAR_MULTIPLAYER = 3
BREAK
ENDSWITCH
// Modify the enum?
IF ePed <> NUMBER_OF_SELECTOR_PEDS
IF sSelectorPeds.eIcons[ePed] = SELECTOR_ICON_DEFAULT
// Auto set Prologue
IF GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(HASH("prologue1")) > 0
IF ePed = SELECTOR_PED_MICHAEL
IF Get_Mission_Flow_Flag_State(FLOWFLAG_MIC_PRO_MASK_REMOVED)
iEnum = 8 //CHAR_MICHAEL_UNMASKED_PROLOGUE=8
ELSE
iEnum = 7 //CHAR_MICHAEL_MASKED_PROLOGUE=7
ENDIF
ELIF ePed = SELECTOR_PED_TREVOR
IF Get_Mission_Flow_Flag_State(FLOWFLAG_TRV_PRO_MASK_REMOVED)
iEnum = 10 //CHAR_TREVOR_UNMASKED_PROLOGUE=10
ELSE
iEnum = 9 //CHAR_TREVOR_MASKED_PROLOGUE=9
ENDIF
ENDIF
ENDIF
// Chop
ELIF sSelectorPeds.eIcons[ePed] = SELECTOR_ICON_CHOP
IF ePed = SELECTOR_PED_MICHAEL
iEnum = 6 //CHAR_CHOP_LEFT = 6 (in the left position /michael)
ELIF ePed = SELECTOR_PED_TREVOR
iEnum = 4 //CHAR_CHOP_RIGHT = 4 (in the right position /trevor)
ELIF ePed = SELECTOR_PED_FRANKLIN
iEnum = 5 //CHAR_CHOP_UP = 5 (in the top position /franklin)
ENDIF
// Prologue
ELIF sSelectorPeds.eIcons[ePed] = SELECTOR_ICON_PRO_MICHAEL_MASKED
iEnum = 7 //CHAR_MICHAEL_MASKED_PROLOGUE=7
ELIF sSelectorPeds.eIcons[ePed] = SELECTOR_ICON_PRO_MICHAEL_UNMASKED
iEnum = 8 //CHAR_MICHAEL_UNMASKED_PROLOGUE=8
ELIF sSelectorPeds.eIcons[ePed] = SELECTOR_ICON_PRO_TREVOR_MASKED
iEnum = 9 //CHAR_TREVOR_MASKED_PROLOGUE=9
ELIF sSelectorPeds.eIcons[ePed] = SELECTOR_ICON_PRO_TREVOR_UNMASKED
iEnum = 10 //CHAR_TREVOR_UNMASKED_PROLOGUE=10
ENDIF
ENDIF
#endif
#endif
ENDPROC
/// PURPOSE: Sets up the details of the character for the selector UI
PROC GET_SELECTOR_PED_DETAILS_FOR_UI(SELECTOR_PED_STRUCT &sSelectorPeds, SELECTOR_SLOTS_ENUM ePed, BOOL bGetEnum, INT &iState, INT &iSlot, INT &iEnum, INT &iCurrent)
BOOL bIsPlayer = FALSE
IF NETWORK_IS_GAME_IN_PROGRESS()
IF ePed = SELECTOR_PED_MULTIPLAYER
bIsPlayer = TRUE
ENDIF
ELSE
IF (GET_LAST_KNOWN_PLAYER_PED_ENUM() = GET_PLAYER_PED_ENUM_FROM_SELECTOR_SLOT(ePed))
bIsPlayer = TRUE
ENDIF
ENDIF
// Default slot, enum, and state
SWITCH ePed
CASE SELECTOR_PED_MICHAEL
iSlot = 3 // Left
iCurrent = 0 // No
IF NOT IS_SELECTOR_PED_INTRODUCED_IN_FLOW(ePed)
iState = 3 // NOTMET= 3
ELIF NOT IS_SELECTOR_PED_AVAILABLE_IN_FLOW(ePed)
iState = 2 // UNAVAIL = 2
ELSE
iState = 1 // AVAILABLE = 1
ENDIF
// Unavailable for ambient HUD
IF sSelectorPeds.bAmbient AND iState = 1
IF (NOT NETWORK_IS_GAME_IN_PROGRESS() AND GET_PLAYER_WANTED_LEVEL(PLAYER_ID()) > 0)
OR (IS_CURRENTLY_ON_MISSION_TO_TYPE(MISSION_TYPE_STORY) OR IS_CURRENTLY_ON_MISSION_TO_TYPE(MISSION_TYPE_STORY_FRIENDS) OR IS_CURRENTLY_ON_MISSION_TO_TYPE(MISSION_TYPE_STORY_PREP) OR IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_MINIGAME) OR IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_MINIGAME_FRIENDS))
OR (IS_REPEAT_PLAY_ACTIVE())
OR (g_bCandidateSystemMidProcessing) // Candidate system processing mission trigger
iState = 2 // UNAVAIL = 2
ENDIF
ENDIF
BREAK
CASE SELECTOR_PED_FRANKLIN
iSlot = 0 // Top
iCurrent = 0 // No
IF NOT IS_SELECTOR_PED_INTRODUCED_IN_FLOW(ePed)
iState = 3 // NOTMET= 3
ELIF NOT IS_SELECTOR_PED_AVAILABLE_IN_FLOW(ePed)
iState = 2 // UNAVAIL = 2
ELSE
iState = 1 // AVAILABLE = 1
ENDIF
// Unavailable for ambient HUD
IF sSelectorPeds.bAmbient AND iState = 1
IF (NOT NETWORK_IS_GAME_IN_PROGRESS() AND GET_PLAYER_WANTED_LEVEL(PLAYER_ID()) > 0)
OR (IS_CURRENTLY_ON_MISSION_TO_TYPE(MISSION_TYPE_STORY) OR IS_CURRENTLY_ON_MISSION_TO_TYPE(MISSION_TYPE_STORY_FRIENDS) OR IS_CURRENTLY_ON_MISSION_TO_TYPE(MISSION_TYPE_STORY_PREP) OR IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_MINIGAME) OR IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_MINIGAME_FRIENDS))
OR (IS_REPEAT_PLAY_ACTIVE())
OR (g_bCandidateSystemMidProcessing) // Candidate system processing mission trigger
iState = 2 // UNAVAIL = 2
ENDIF
ENDIF
BREAK
CASE SELECTOR_PED_TREVOR
iSlot = 1 // Right
iCurrent = 0 // No
IF NOT IS_SELECTOR_PED_INTRODUCED_IN_FLOW(ePed)
iState = 3 // NOTMET= 3
ELIF NOT IS_SELECTOR_PED_AVAILABLE_IN_FLOW(ePed)
iState = 2 // UNAVAIL = 2
ELSE
iState = 1 // AVAILABLE = 1
ENDIF
// Unavailable for ambient HUD
IF sSelectorPeds.bAmbient AND iState = 1
IF (NOT NETWORK_IS_GAME_IN_PROGRESS() AND GET_PLAYER_WANTED_LEVEL(PLAYER_ID()) > 0)
OR (IS_CURRENTLY_ON_MISSION_TO_TYPE(MISSION_TYPE_STORY) OR IS_CURRENTLY_ON_MISSION_TO_TYPE(MISSION_TYPE_STORY_FRIENDS) OR IS_CURRENTLY_ON_MISSION_TO_TYPE(MISSION_TYPE_STORY_PREP) OR IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_MINIGAME) OR IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_MINIGAME_FRIENDS))
OR (IS_REPEAT_PLAY_ACTIVE())
OR (g_bCandidateSystemMidProcessing) // Candidate system processing mission trigger
iState = 2 // UNAVAIL = 2
ENDIF
ENDIF
BREAK
CASE SELECTOR_PED_MULTIPLAYER
iSlot = 2 // Bottom
iCurrent = 0 // No
IF NOT sSelectorPeds.bAmbient
OR g_bMagDemoActive
OR (sSelectorPeds.bAmbient AND ((IS_CURRENTLY_ON_MISSION_TO_TYPE(MISSION_TYPE_STORY) OR IS_CURRENTLY_ON_MISSION_TO_TYPE(MISSION_TYPE_STORY_FRIENDS) OR IS_CURRENTLY_ON_MISSION_TO_TYPE(MISSION_TYPE_STORY_PREP) OR IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_MINIGAME) OR IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_MINIGAME_FRIENDS))))
OR (sSelectorPeds.bAmbient AND IS_REPEAT_PLAY_ACTIVE())
OR (sSelectorPeds.bAmbient AND (g_bCandidateSystemMidProcessing)) // Candidate system processing mission trigger
OR NOT DOES_PLAYER_HAVE_PRIVILEGES()
OR NOT IS_GTA_ONLINE_AVAILABLE()
iState = 2 // UNAVAIL = 2
ELSE
iState = 1 // AVAILABLE = 1
ENDIF
// Unavailable for ambient HUD
IF sSelectorPeds.bAmbient AND iState = 1
IF (IS_CURRENTLY_ON_MISSION_TO_TYPE(MISSION_TYPE_STORY) OR IS_CURRENTLY_ON_MISSION_TO_TYPE(MISSION_TYPE_STORY_FRIENDS) OR IS_CURRENTLY_ON_MISSION_TO_TYPE(MISSION_TYPE_STORY_PREP) OR IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_MINIGAME) OR IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_MINIGAME_FRIENDS))
OR (g_bCandidateSystemMidProcessing) // Candidate system processing mission trigger
iState = 2 // UNAVAIL = 2
ENDIF
ENDIF
BREAK
ENDSWITCH
#IF USE_CLF_DLC
// Modify the state?
IF ePed <> SELECTOR_PED_MULTIPLAYER
IF (bIsPlayer)
OR (sSelectorPeds.eFakeState[ePed] = SELECTOR_STATE_AVAILABLE)
iState = 1 // AVAILABLE = 1
ELIF (sSelectorPeds.eFakeState[ePed] = SELECTOR_STATE_UNAVAILABLE)
OR (sSelectorPeds.bBlockSelectorPed[ePed])
OR (NOT sSelectorPeds.bAmbient AND IS_PED_INJURED(sSelectorPeds.pedID[ePed]) AND iState = 1) // AVAILABLE = 1
OR (sSelectorPeds.bAmbient AND IS_BIT_SET(g_sPlayerPedRequest.iBitsetPedInLeadIn, ENUM_TO_INT(ePed))) //Block switching to player's created in lead-ins.
IF iState = 1
iState = 2 // UNAVAIL = 2
ENDIF
ELIF (sSelectorPeds.eIcons[ePed] != SELECTOR_ICON_DEFAULT)
iState = 1 // AVAILABLE = 1
ELIF (sSelectorPeds.bAmbient AND NOT IS_BIT_SET(g_savedGlobalsClifford.sFlow.strandSavedVars[STRAND_CLF].savedBitflags, SAVED_BITS_STRAND_ACTIVATED) AND NOT IS_REPEAT_PLAY_ACTIVE())
IF (IS_CURRENTLY_ON_MISSION_TO_TYPE(MISSION_TYPE_STORY)
OR IS_CURRENTLY_ON_MISSION_TO_TYPE(MISSION_TYPE_STORY_FRIENDS)
OR IS_CURRENTLY_ON_MISSION_TO_TYPE(MISSION_TYPE_STORY_PREP)
OR IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_MINIGAME)
OR IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_MINIGAME_FRIENDS))
// keep blocked on mission.
ELSE
iState = 1 // AVAILABLE = 1
ENDIF
ENDIF
ELSE
// TEXT_LABEL_31 tlTemp
// IF GET_MP_COUNTDOWN_STRING(tlTemp, TRUE)
// iState = 2 // UNAVAIL = 2
// ENDIF
// Fix for bug 1596720 - remove timer
iState = 3 // NOTMET= 3
ENDIF
#ENDIF
#IF USE_NRM_DLC
// Modify the state?
IF ePed <> SELECTOR_PED_MULTIPLAYER
IF (bIsPlayer)
OR (sSelectorPeds.eFakeState[ePed] = SELECTOR_STATE_AVAILABLE)
iState = 1 // AVAILABLE = 1
ELIF (sSelectorPeds.eFakeState[ePed] = SELECTOR_STATE_UNAVAILABLE)
OR (sSelectorPeds.bBlockSelectorPed[ePed])
OR (NOT sSelectorPeds.bAmbient AND IS_PED_INJURED(sSelectorPeds.pedID[ePed]) AND iState = 1) // AVAILABLE = 1
OR (sSelectorPeds.bAmbient AND IS_BIT_SET(g_sPlayerPedRequest.iBitsetPedInLeadIn, ENUM_TO_INT(ePed))) //Block switching to player's created in lead-ins.
IF iState = 1
iState = 2 // UNAVAIL = 2
ENDIF
ELIF (sSelectorPeds.eIcons[ePed] != SELECTOR_ICON_DEFAULT)
iState = 1 // AVAILABLE = 1
ELIF (sSelectorPeds.bAmbient AND NOT IS_BIT_SET(g_savedGlobalsnorman.sFlow.strandSavedVars[STRAND_NRM_SURVIVE].savedBitflags, SAVED_BITS_STRAND_ACTIVATED) AND NOT IS_REPEAT_PLAY_ACTIVE())
IF (IS_CURRENTLY_ON_MISSION_TO_TYPE(MISSION_TYPE_STORY)
OR IS_CURRENTLY_ON_MISSION_TO_TYPE(MISSION_TYPE_STORY_FRIENDS)
OR IS_CURRENTLY_ON_MISSION_TO_TYPE(MISSION_TYPE_STORY_PREP)
OR IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_MINIGAME)
OR IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_MINIGAME_FRIENDS))
// keep blocked on mission.
ELSE
iState = 1 // AVAILABLE = 1
ENDIF
ENDIF
ELSE
// TEXT_LABEL_31 tlTemp
// IF GET_MP_COUNTDOWN_STRING(tlTemp, TRUE)
// iState = 2 // UNAVAIL = 2
// ENDIF
// Fix for bug 1596720 - remove timer
iState = 3 // NOTMET= 3
ENDIF
#ENDIF
#IF NOT USE_SP_DLC
// Modify the state?
IF ePed <> SELECTOR_PED_MULTIPLAYER
IF (bIsPlayer)
OR (sSelectorPeds.eFakeState[ePed] = SELECTOR_STATE_AVAILABLE)
iState = 1 // AVAILABLE = 1
ELIF (sSelectorPeds.eFakeState[ePed] = SELECTOR_STATE_UNAVAILABLE)
OR (sSelectorPeds.bBlockSelectorPed[ePed])
OR (NOT sSelectorPeds.bAmbient AND IS_PED_INJURED(sSelectorPeds.pedID[ePed]) AND iState = 1) // AVAILABLE = 1
OR (sSelectorPeds.bAmbient AND IS_BIT_SET(g_sPlayerPedRequest.iBitsetPedInLeadIn, ENUM_TO_INT(ePed))) //Block switching to player's created in lead-ins.
IF iState = 1
iState = 2 // UNAVAIL = 2
ENDIF
ELIF (sSelectorPeds.eIcons[ePed] != SELECTOR_ICON_DEFAULT)
iState = 1 // AVAILABLE = 1
ELIF (sSelectorPeds.bAmbient AND NOT IS_BIT_SET(g_savedGlobals.sFlow.strandSavedVars[STRAND_PROLOGUE].savedBitflags, SAVED_BITS_STRAND_ACTIVATED) AND NOT g_bMagDemoActive AND NOT IS_REPEAT_PLAY_ACTIVE())
IF (IS_CURRENTLY_ON_MISSION_TO_TYPE(MISSION_TYPE_STORY)
OR IS_CURRENTLY_ON_MISSION_TO_TYPE(MISSION_TYPE_STORY_FRIENDS)
OR IS_CURRENTLY_ON_MISSION_TO_TYPE(MISSION_TYPE_STORY_PREP)
OR IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_MINIGAME)
OR IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_MINIGAME_FRIENDS))
// keep blocked on mission.
ELSE
iState = 1 // AVAILABLE = 1
ENDIF
ENDIF
ELSE
// TEXT_LABEL_31 tlTemp
// IF GET_MP_COUNTDOWN_STRING(tlTemp, TRUE)
// iState = 2 // UNAVAIL = 2
// ENDIF
// Fix for bug 1596720 - remove timer
iState = 3 // NOTMET= 3
ENDIF
#ENDIF
#IF USE_CLF_DLC
if g_bLoadedClifford AND (ePed = SELECTOR_PED_FRANKLIN OR ePed = SELECTOR_PED_MICHAEL)
iState=2
endif
#ENDIF
// Modify the current?
IF (bIsPlayer AND sSelectorPeds.eFakeState[ePed] = SELECTOR_STATE_DEFAULT)
OR (sSelectorPeds.eFakeState[ePed] = SELECTOR_STATE_CURRENT)
IF NOT IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_DIRECTOR)
iCurrent = 1 // Yes
ENDIF
ENDIF
IF bGetEnum
GET_SELECTOR_PED_ENUM_FOR_UI(sSelectorPeds, ePed, iEnum)
ENDIF
ENDPROC
/// PURPOSE: Draws the ped selector HUD and handles keypresses
///
/// NOTES: Updates the eNewSelectorPed and returns TRUE if the player has changed the current selection
/// DPADUP = MICHAEL, DPADLEFT = FRANKLIN, DPADRIGHT = TREVOR, DPADDOWN = MULTIPLAYER
FUNC BOOL UPDATE_SELECTOR_HUD(SELECTOR_PED_STRUCT &sSelectorPeds, BOOL bCheckPlayerIsInControl = TRUE, BOOL bCheckActivationButton = TRUE)
#IF IS_DEBUG_BUILD
// Update details for widget
g_sSelectorUI.debug_pedID[0] = sSelectorPeds.pedID[0]
g_sSelectorUI.debug_pedID[1] = sSelectorPeds.pedID[1]
g_sSelectorUI.debug_pedID[2] = sSelectorPeds.pedID[2]
g_sSelectorUI.debug_pedID[3] = sSelectorPeds.pedID[3]
g_sSelectorUI.debug_bBlockState[0] = sSelectorPeds.bBlockSelectorPed[0]
g_sSelectorUI.debug_bBlockState[1] = sSelectorPeds.bBlockSelectorPed[1]
g_sSelectorUI.debug_bBlockState[2] = sSelectorPeds.bBlockSelectorPed[2]
g_sSelectorUI.debug_bBlockState[3] = sSelectorPeds.bBlockSelectorPed[3]
g_sSelectorUI.debug_bHintState[0] = sSelectorPeds.bDisplayHint[0]
g_sSelectorUI.debug_bHintState[1] = sSelectorPeds.bDisplayHint[1]
g_sSelectorUI.debug_bHintState[2] = sSelectorPeds.bDisplayHint[2]
g_sSelectorUI.debug_bHintState[3] = sSelectorPeds.bDisplayHint[3]
g_sSelectorUI.debug_bDamageState[0] = sSelectorPeds.bDisplayDamage[0]
g_sSelectorUI.debug_bDamageState[1] = sSelectorPeds.bDisplayDamage[1]
g_sSelectorUI.debug_bDamageState[2] = sSelectorPeds.bDisplayDamage[2]
g_sSelectorUI.debug_bDamageState[3] = sSelectorPeds.bDisplayDamage[3]
g_sSelectorUI.debug_iState[0] = -1
g_sSelectorUI.debug_iState[1] = -1
g_sSelectorUI.debug_iState[2] = -1
g_sSelectorUI.debug_iState[3] = -1
#ENDIF
INT iPed, iState, iSlot, iEnum, iCurrent
BOOL bFakeCurrent = FALSE
BOOL bPlayerDead = IS_PED_INJURED(PLAYER_PED_ID())
BOOL bAllowWhenDead = (bPlayerDead AND g_bInMultiplayer AND IS_A_SPECTATOR_CAM_ACTIVE())
BOOL bUIButtonJustReleased = IS_SELECTOR_UI_BUTTON_JUST_RELEASED(bCheckPlayerIsInControl)
// Set the current ped
sSelectorPeds.eCurrentSelectorPed = GET_SELECTOR_SLOT_FROM_PLAYER_PED_ENUM(GET_CURRENT_PLAYER_PED_ENUM())
// Set misc states
g_sSelectorUI.bMissionUpdate = (NOT sSelectorPeds.bAmbient)
g_sSelectorUI.bCheckPlayerControl = bCheckPlayerIsInControl
g_sSelectorUI.bCheckActivationButton = bCheckActivationButton
g_sSelectorUI.bAllowWhenDead = bAllowWhenDead
g_sSelectorUI.bForceUpdate = g_sSelectorUI.bFakeStateUpdated
g_sSelectorUI.bCharAvailable = FALSE
BOOL bGetPedDetails = (g_sSelectorUI.eUIStateCurrent = SELECTOR_UI_FULL OR g_sSelectorUI.eUIStateCurrent = SELECTOR_UI_HIDDEN_TO_FULL OR g_sSelectorUI.eUIStateCurrent = SELECTOR_UI_HINT_TO_FULL)
// Update the ped hints and stored data
FOR iPed = 0 TO ENUM_TO_INT(NUMBER_OF_SELECTOR_PEDS)-1
//GET_SELECTOR_PED_ENUM_FOR_UI(sSelectorPeds, INT_TO_ENUM(SELECTOR_SLOTS_ENUM, iPed), iEnum)
//GET_SELECTOR_PED_DETAILS_FOR_UI(sSelectorPeds, INT_TO_ENUM(SELECTOR_SLOTS_ENUM, iPed), FALSE, iState, iSlot, iEnum, iCurrent)
GET_SELECTOR_PED_DETAILS_FOR_UI(sSelectorPeds, INT_TO_ENUM(SELECTOR_SLOTS_ENUM, iPed), TRUE, iState, iSlot, iEnum, iCurrent)
g_sSelectorUI.iHealth[iPed] = -1
g_sSelectorUI.iArmour[iPed] = -1
g_sSelectorUI.iSpecial[iPed] = -1
g_sSelectorUI.iSpecialMax[iPed] = -1
g_sSelectorUI.bDamaged[iPed] = FALSE
g_sSelectorUI.bFlashDamage[iPed] = FALSE
g_sSelectorUI.vCoords[iPed] = <<0,0,0>>
// [DIRECTOR_TODO]
IF IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_DIRECTOR)
SELECTOR_SLOTS_ENUM ePed = INT_TO_ENUM(SELECTOR_SLOTS_ENUM, iPed)
//Casting trailer is always available.
IF ePed = SELECTOR_PED_MULTIPLAYER
g_sSelectorUI.bCharAvailable = TRUE
ELIF IS_SELECTOR_PED_INTRODUCED_IN_FLOW(ePed)
AND IS_SELECTOR_PED_AVAILABLE_IN_FLOW(ePed)
#IF USE_CLF_DLC
AND ePed = GET_SELECTOR_SLOT_FROM_PLAYER_PED_ENUM(g_savedGlobalsClifford.sPlayerData.sInfo.eLastKnownPed)
#ENDIF
#IF NOT USE_SP_DLC
AND ePed = GET_SELECTOR_SLOT_FROM_PLAYER_PED_ENUM(g_savedGlobals.sPlayerData.sInfo.eLastKnownPed)
#ENDIF
g_sSelectorUI.bCharAvailable = TRUE
ELSE
g_sSelectorUI.bCharAvailable = FALSE
ENDIF
// Set g_sSelectorUI.bCharAvailable = TRUE if the character is unlocked in flow.
// If we want to allow hints to be set (white flash on icon) then we do the following:
//g_sSelectorUI.bHinted[iPed] = sSelectorPeds.bDisplayHint[iPed]
//g_sSelectorUI.iHintEnum[iPed] = iEnum
ELIF g_sSelectorUI.bMissionUpdate
// See if we have an available character
IF NOT g_sSelectorUI.bCharAvailable
IF (NOT IS_PED_INJURED(sSelectorPeds.pedID[iPed]) AND NOT sSelectorPeds.bBlockSelectorPed[iPed] AND sSelectorPeds.pedID[iPed] != PLAYER_PED_ID())
OR (sSelectorPeds.eFakeState[iPed] = SELECTOR_STATE_AVAILABLE)
OR (sSelectorPeds.eIcons[iPed] != SELECTOR_ICON_DEFAULT)
g_sSelectorUI.bCharAvailable = TRUE
#IF USE_CLF_DLC
IF g_bLoadedClifford AND (iPed=ENUM_TO_INT(SELECTOR_PED_FRANKLIN) OR iPed=ENUM_TO_INT(SELECTOR_PED_MICHAEL))
g_sSelectorUI.bCharAvailable=FALSE
ENDIF
#ENDIF
ENDIF
ENDIF
// Check for fake current ped
IF (sSelectorPeds.eFakeState[iPed] = SELECTOR_STATE_CURRENT)
bFakeCurrent = TRUE
ELIF (sSelectorPeds.eCurrentSelectorPed = INT_TO_ENUM(SELECTOR_SLOTS_ENUM, iPed))
IF (sSelectorPeds.eFakeState[iPed] = SELECTOR_STATE_UNAVAILABLE)
OR (sSelectorPeds.eFakeState[iPed] = SELECTOR_STATE_AVAILABLE)
bFakeCurrent = TRUE
ENDIF
ENDIF
// Update hints
IF sSelectorPeds.bDisplayHint[iPed]
// Remove hint if character selected
IF sSelectorPeds.bInitialised
AND (sSelectorPeds.eNewSelectorPed = INT_TO_ENUM(SELECTOR_SLOTS_ENUM, iPed))
sSelectorPeds.bDisplayHint[iPed] = FALSE
// Remove hint if character current
ELIF (sSelectorPeds.eCurrentSelectorPed = INT_TO_ENUM(SELECTOR_SLOTS_ENUM, iPed) AND NOT bFakeCurrent)
OR (sSelectorPeds.eFakeState[iPed] = SELECTOR_STATE_CURRENT)
sSelectorPeds.bDisplayHint[iPed] = FALSE
// Remove hint if character dead
ELIF (IS_PED_INJURED(sSelectorPeds.pedID[iPed]) AND NOT sSelectorPeds.bAmbient)
AND NOT (sSelectorPeds.eFakeState[iPed] = SELECTOR_STATE_AVAILABLE)
PRINTLN("set_selector_ped_hint clearing hint 2")
sSelectorPeds.bDisplayHint[iPed] = FALSE
ENDIF
ENDIF
g_sSelectorUI.bHinted[iPed] = sSelectorPeds.bDisplayHint[iPed]
g_sSelectorUI.iHintEnum[iPed] = iEnum
// Update damaged state
IF DOES_ENTITY_EXIST(sSelectorPeds.pedID[iPed])
AND NOT IS_PED_INJURED(sSelectorPeds.pedID[iPed])
AND sSelectorPeds.pedID[iPed] != PLAYER_PED_ID()
g_sSelectorUI.iHealth[iPed] = FLOOR(((TO_FLOAT(GET_ENTITY_HEALTH(sSelectorPeds.pedID[iPed]))-100.0) / (TO_FLOAT(GET_PED_MAX_HEALTH(sSelectorPeds.pedID[iPed]))-100.0)) * 100.0)
ENDIF
IF (g_sSelectorUI.iHealth[iPed] != -1 AND g_sSelectorUI.iHealth[iPed] < 25.0)
OR sSelectorPeds.bDisplayDamage[iPed]
IF ENUM_TO_INT(sSelectorPeds.eCurrentSelectorPed) != iPed
g_sSelectorUI.bDamaged[iPed] = TRUE
g_sSelectorUI.bFlashDamage[iPed] = (sSelectorPeds.bDisplayDamage[iPed])
ENDIF
ENDIF
ELSE
g_sSelectorUI.bHinted[iPed] = sSelectorPeds.bDisplayHint[iPed]
g_sSelectorUI.iHintEnum[iPed] = iEnum
ENDIF
#IF IS_DEBUG_BUILD
// Update details for widget
g_sSelectorUI.debug_bHintState[iPed] = sSelectorPeds.bDisplayHint[iPed]
g_sSelectorUI.debug_bDamageState[iPed] = sSelectorPeds.bDisplayDamage[iPed]
g_sSelectorUI.debug_bBlockState[iPed] = sSelectorPeds.bBlockSelectorPed[iPed]
#ENDIF
// Update the stored data
IF g_sSelectorUI.bDisplay
g_sSelectorUI.iState[iSlot] = iState
g_sSelectorUI.iEnum[iSlot] = iEnum
g_sSelectorUI.iCurrent[iSlot] = iCurrent
g_sSelectorUI.iMissions[iPed] = 0
g_sSelectorUI.iTxts[iPed] = 0
g_sSelectorUI.iCalls[iPed] = 0
#IF IS_DEBUG_BUILD
// Update details for widget
g_sSelectorUI.debug_iState[iPed] = iState
#ENDIF
IF bGetPedDetails
// Ped location and health states
IF g_sSelectorUI.bMissionUpdate
IF DOES_ENTITY_EXIST(sSelectorPeds.pedID[iPed])
AND NOT IS_PED_INJURED(sSelectorPeds.pedID[iPed])
//g_sSelectorUI.iHealth[iPed] = FLOOR(((TO_FLOAT(GET_ENTITY_HEALTH(sSelectorPeds.pedID[iPed]))-100.0) / (TO_FLOAT(GET_PED_MAX_HEALTH(sSelectorPeds.pedID[iPed]))-100.0)) * 100.0)
g_sSelectorUI.iArmour[iPed] = GET_PED_ARMOUR(sSelectorPeds.pedID[iPed])
IF iPed = 0 // SELECTOR_PED_MICHAEL
STAT_GET_INT(SP0_SPECIAL_ABILITY, g_sSelectorUI.iSpecial[iPed])
STAT_GET_INT(SP0_SPECIAL_ABILITY_UNLOCKED, g_sSelectorUI.iSpecialMax[iPed])
ELIF iPed = 1 // SELECTOR_PED_FRANKLIN
STAT_GET_INT(SP1_SPECIAL_ABILITY, g_sSelectorUI.iSpecial[iPed])
STAT_GET_INT(SP1_SPECIAL_ABILITY_UNLOCKED, g_sSelectorUI.iSpecialMax[iPed])
ELIF iPed = 2 // SELECTOR_PED_TREVOR
STAT_GET_INT(SP2_SPECIAL_ABILITY, g_sSelectorUI.iSpecial[iPed])
STAT_GET_INT(SP2_SPECIAL_ABILITY_UNLOCKED, g_sSelectorUI.iSpecialMax[iPed])
ENDIF
g_sSelectorUI.vCoords[iPed] = GET_ENTITY_COORDS(sSelectorPeds.pedID[iPed])
ENDIF
// Set the mission count for player characters when off mission
ELIF (iPed < ENUM_TO_INT(SELECTOR_PED_MULTIPLAYER))
AND (iState != 3) // NOTMET= 3
AND (NOT IS_CURRENTLY_ON_MISSION_OF_ANY_TYPE() OR IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_DIRECTOR))
g_sSelectorUI.iMissions[iPed] = g_iAvailablePlayerMissions[iPed]
// Fix for bug #1001720 - just put the mission next to Trevor here rather than the sms sign even if he is waiting for the sms to trigger the mission
g_sSelectorUI.iTxts[iPed] = 0
g_sSelectorUI.iMissions[iPed] += g_iQueuedTxts[iPed]
// Fix for bug #975918 - dont put phone icon there - just have a 1 instead
//g_sSelectorUI.iCalls[iSlot] = g_iQueuedCalls[GET_PLAYER_PED_ENUM_FROM_SELECTOR_SLOT(INT_TO_ENUM(SELECTOR_SLOTS_ENUM, iPed))]
g_sSelectorUI.iCalls[iPed] = 0
g_sSelectorUI.iMissions[iPed] += g_iQueuedCalls[iPed]
ENDIF
ENDIF
ENDIF
// Set the default character selection if the movie has not been set up yet
IF (g_sSelectorUI.iSelectedSlot = -1 OR NOT g_sSelectorUI.bFirstSelectionMade)
AND g_sSelectorUI.iSelectedSlot != iSlot
AND NOT IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_DIRECTOR)
IF (sSelectorPeds.eCurrentSelectorPed = INT_TO_ENUM(SELECTOR_SLOTS_ENUM, iPed) AND NOT bFakeCurrent)
OR (sSelectorPeds.eFakeState[iPed] = SELECTOR_STATE_CURRENT)
g_sSelectorUI.iSelectedSlot = iSlot
g_sSelectorUI.bFirstSelectionMade = TRUE
PRINTLN("UPDATE_SELECTOR_HUD() - Setting default character selection to ", iSlot)
ENDIF
ENDIF
ENDFOR
// Check for final selection
IF bUIButtonJustReleased
IF (g_sSelectorUI.bDisplay)
AND (NOT g_sSelectorUI.bHiddenThisFrame OR g_sSelectorUI.bAllowSelectionWhenHidden)
AND (NOT IS_CURRENTLY_ON_MISSION_TO_TYPE(MISSION_TYPE_STORY) OR g_sSelectorUI.bMissionUpdate OR IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_DIRECTOR))
AND (NOT IS_CURRENTLY_ON_MISSION_TO_TYPE(MISSION_TYPE_STORY_FRIENDS) OR g_sSelectorUI.bMissionUpdate OR IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_DIRECTOR))
AND (NOT IS_CURRENTLY_ON_MISSION_TO_TYPE(MISSION_TYPE_STORY_PREP) OR g_sSelectorUI.bMissionUpdate OR IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_DIRECTOR))
AND (NOT IS_CURRENTLY_ON_MISSION_TO_TYPE(MISSION_TYPE_MINIGAME) OR g_sSelectorUI.bMissionUpdate OR IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_DIRECTOR))
AND (NOT IS_CURRENTLY_ON_MISSION_TO_TYPE(MISSION_TYPE_MINIGAME_FRIENDS) OR g_sSelectorUI.bMissionUpdate OR IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_DIRECTOR))
// Manual selection
IF g_sSelectorUI.eUIStateCurrent = SELECTOR_UI_FULL
PRINTLN("UPDATE_SELECTOR_HUD() - Checking character selection")
// [DIRECTOR_TODO]
IF IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_DIRECTOR)
// We should do a custom make_selector_ped_selection set up here
// Check for character being unlocked in flow and available.
// Make a global called g_bSwitchBackToTrailer for when we select the trailer, we can then pick this up in selector.sc to do trailer transition.
IF (g_sSelectorUI.iSelectedSlot = 0) // Top
g_sSelectorUI.bSelection = MAKE_DIRECTOR_MODE_SELECTOR_PED_SELECTION(sSelectorPeds, SELECTOR_PED_FRANKLIN)
ELIF (g_sSelectorUI.iSelectedSlot = 1) // Right
g_sSelectorUI.bSelection = MAKE_DIRECTOR_MODE_SELECTOR_PED_SELECTION(sSelectorPeds, SELECTOR_PED_TREVOR)
ELIF (g_sSelectorUI.iSelectedSlot = 2) // Bottom
g_sSelectorUI.bSelection = MAKE_DIRECTOR_MODE_SELECTOR_PED_SELECTION(sSelectorPeds, SELECTOR_PED_MULTIPLAYER)
ELIF (g_sSelectorUI.iSelectedSlot = 3) // Left
g_sSelectorUI.bSelection = MAKE_DIRECTOR_MODE_SELECTOR_PED_SELECTION(sSelectorPeds, SELECTOR_PED_MICHAEL)
ENDIF
// Casting Trailer selection.
// IF g_sSelectorUI.iSelectedSlot = 2
// PRINTLN("UPDATE_SELECTOR_HUD() - Director Mode overriding MP switch to be the Casting Trailer.")
// g_bSelectorChoseCastingTrailer = TRUE
// ENDIF
ELSE
IF (g_sSelectorUI.iSelectedSlot = 0) // Top
g_sSelectorUI.bSelection = MAKE_SELECTOR_PED_SELECTION(sSelectorPeds, SELECTOR_PED_FRANKLIN)
ELIF (g_sSelectorUI.iSelectedSlot = 1) // Right
g_sSelectorUI.bSelection = MAKE_SELECTOR_PED_SELECTION(sSelectorPeds, SELECTOR_PED_TREVOR)
ELIF (g_sSelectorUI.iSelectedSlot = 2) // Bottom
g_sSelectorUI.bSelection = MAKE_MULTIPLAYER_SELECTION(sSelectorPeds)
ELIF (g_sSelectorUI.iSelectedSlot = 3) // Left
g_sSelectorUI.bSelection = MAKE_SELECTOR_PED_SELECTION(sSelectorPeds, SELECTOR_PED_MICHAEL)
ENDIF
ENDIF
// Quick switch
ELIF g_sSelectorUI.eUIStateCurrent = SELECTOR_UI_HINT_TO_FULL
OR (g_sSelectorUI.bHiddenThisFrame AND g_sSelectorUI.bAllowSelectionWhenHidden)
IF NOT g_sSelectorUI.bSelection
AND g_sSelectorUI.bMissionUpdate
AND (g_sSelectorUI.bCharAvailable)
AND NOT NETWORK_IS_GAME_IN_PROGRESS()
AND NOT (IS_AIMING_THROUGH_SNIPER_SCOPE(PLAYER_PED_ID()) AND (IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_AIM) OR IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_VEH_AIM)))
enumCharacterList eCurrentPed
SELECTOR_SLOTS_ENUM ePed1, ePed2, ePed3
IF sSelectorPeds.eFakeState[SELECTOR_PED_MICHAEL] = SELECTOR_STATE_CURRENT
eCurrentPed = CHAR_MICHAEL
ELIF sSelectorPeds.eFakeState[SELECTOR_PED_FRANKLIN] = SELECTOR_STATE_CURRENT
eCurrentPed = CHAR_FRANKLIN
ELIF sSelectorPeds.eFakeState[SELECTOR_PED_TREVOR] = SELECTOR_STATE_CURRENT
eCurrentPed = CHAR_TREVOR
ELSE
eCurrentPed = GET_CURRENT_PLAYER_PED_ENUM()
ENDIF
SWITCH eCurrentPed
CASE CHAR_MICHAEL
IF sSelectorPeds.bDisplayDamage[SELECTOR_PED_FRANKLIN] AND NOT g_sSelectorUI.bBlockQuickSwitchToDamagedPed
ePed1 = SELECTOR_PED_FRANKLIN
ELIF sSelectorPeds.bDisplayDamage[SELECTOR_PED_TREVOR] AND NOT g_sSelectorUI.bBlockQuickSwitchToDamagedPed
ePed1 = SELECTOR_PED_TREVOR
ELIF sSelectorPeds.bUseCustomAutoSelectOption
ePed1 = sSelectorPeds.eAutoSelectOption1
ePed2 = sSelectorPeds.eAutoSelectOption2
ePed3 = sSelectorPeds.eAutoSelectOption3
ELSE
ePed1 = SELECTOR_PED_FRANKLIN
ePed2 = SELECTOR_PED_TREVOR
ENDIF
BREAK
CASE CHAR_FRANKLIN
IF sSelectorPeds.bDisplayDamage[SELECTOR_PED_TREVOR] AND NOT g_sSelectorUI.bBlockQuickSwitchToDamagedPed
ePed1 = SELECTOR_PED_TREVOR
ELIF sSelectorPeds.bDisplayDamage[SELECTOR_PED_MICHAEL] AND NOT g_sSelectorUI.bBlockQuickSwitchToDamagedPed
ePed1 = SELECTOR_PED_MICHAEL
ELIF sSelectorPeds.bUseCustomAutoSelectOption
ePed1 = sSelectorPeds.eAutoSelectOption1
ePed2 = sSelectorPeds.eAutoSelectOption2
ePed3 = sSelectorPeds.eAutoSelectOption3
ELSE
ePed1 = SELECTOR_PED_TREVOR
ePed2 = SELECTOR_PED_MICHAEL
ENDIF
BREAK
CASE CHAR_TREVOR
IF sSelectorPeds.bDisplayDamage[SELECTOR_PED_MICHAEL] AND NOT g_sSelectorUI.bBlockQuickSwitchToDamagedPed
ePed1 = SELECTOR_PED_MICHAEL
ELIF sSelectorPeds.bDisplayDamage[SELECTOR_PED_FRANKLIN] AND NOT g_sSelectorUI.bBlockQuickSwitchToDamagedPed
ePed1 = SELECTOR_PED_FRANKLIN
ELIF sSelectorPeds.bUseCustomAutoSelectOption
ePed1 = sSelectorPeds.eAutoSelectOption1
ePed2 = sSelectorPeds.eAutoSelectOption2
ePed3 = sSelectorPeds.eAutoSelectOption3
ELSE
ePed1 = SELECTOR_PED_MICHAEL
ePed2 = SELECTOR_PED_FRANKLIN
ENDIF
BREAK
ENDSWITCH
PRINTLN("...ped1 = ", GET_PLAYER_PED_STRING(GET_PLAYER_PED_ENUM_FROM_SELECTOR_SLOT(ePed1)))
PRINTLN("...ped2 = ", GET_PLAYER_PED_STRING(GET_PLAYER_PED_ENUM_FROM_SELECTOR_SLOT(ePed2)))
PRINTLN("...ped3 = ", GET_PLAYER_PED_STRING(GET_PLAYER_PED_ENUM_FROM_SELECTOR_SLOT(ePed3)))
// Normal quick switch cycling is disabled if one of the PC specific shortcut keys has been pressed.
BOOL bNormalQuickSwitch = TRUE
// Direct switching of selected character using keyboard controls.
IF IS_USING_KEYBOARD_AND_MOUSE(FRONTEND_CONTROL)
// Don't want to do this if the player is pressing the normal quick switch)
IF NOT IS_CONTROL_JUST_RELEASED(PLAYER_CONTROL, INPUT_CHARACTER_WHEEL)
IF IS_CONTROL_JUST_RELEASED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_MICHAEL)
bNormalQuickSwitch = FALSE
IF eCurrentPed != CHAR_MICHAEL
IF MAKE_SELECTOR_PED_SELECTION(sSelectorPeds, SELECTOR_PED_MICHAEL)
g_sSelectorUI.bSelection = TRUE
ENDIF
ENDIF
ELIF IS_CONTROL_JUST_RELEASED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_FRANKLIN)
bNormalQuickSwitch = FALSE
IF eCurrentPed != CHAR_FRANKLIN
IF MAKE_SELECTOR_PED_SELECTION(sSelectorPeds, SELECTOR_PED_FRANKLIN)
g_sSelectorUI.bSelection = TRUE
ENDIF
ENDIF
ELIF IS_CONTROL_JUST_RELEASED(PLAYER_CONTROL, INPUT_SELECT_CHARACTER_TREVOR)
bNormalQuickSwitch = FALSE
IF eCurrentPed != CHAR_TREVOR
IF MAKE_SELECTOR_PED_SELECTION(sSelectorPeds, SELECTOR_PED_TREVOR)
g_sSelectorUI.bSelection = TRUE
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
IF bNormalQuickSwitch
IF MAKE_SELECTOR_PED_SELECTION(sSelectorPeds, ePed1)
g_sSelectorUI.bSelection = TRUE
ELIF MAKE_SELECTOR_PED_SELECTION(sSelectorPeds, ePed2)
g_sSelectorUI.bSelection = TRUE
ELIF MAKE_SELECTOR_PED_SELECTION(sSelectorPeds, ePed3)
g_sSelectorUI.bSelection = TRUE
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
IF (g_sSelectorUI.bSelection)
g_sSelectorUI.bHideUiForSwitch = TRUE
HIDE_HUD_COMPONENT_THIS_FRAME(NEW_HUD_VEHICLE_NAME)
HIDE_HUD_COMPONENT_THIS_FRAME(NEW_HUD_AREA_NAME)
HIDE_HUD_COMPONENT_THIS_FRAME(NEW_HUD_DISTRICT_NAME)
HIDE_HUD_COMPONENT_THIS_FRAME(NEW_HUD_STREET_NAME)
ENDIF
// Let scripts know if the player just made a selection
RETURN (g_sSelectorUI.bSelection)
ENDFUNC
/// PURPOSE: Forces the player to be a specific character without scripts having to create a selector ped
/// NOTE: This only works with SELECTOR_PED_MICHAEL, SELECTOR_PED_TREVOR, and SELECTOR_PED_FRANKLIN
FUNC BOOL SET_CURRENT_SELECTOR_PED(SELECTOR_SLOTS_ENUM eSlot, BOOL bCleanupModel = TRUE)
// We are forcing a switch with this command so clear manual selection flag
g_sSelectorUI.bManualSelection = FALSE
// Player is dead
IF IS_PED_INJURED(PLAYER_PED_ID())
RETURN TRUE
ENDIF
// Grab the ped and model enums
enumCharacterList ePed = GET_PLAYER_PED_ENUM_FROM_SELECTOR_SLOT(eSlot)
MODEL_NAMES eModel = GET_PLAYER_PED_MODEL(ePed)
// Character is not a playable character
IF eModel = DUMMY_MODEL_FOR_SCRIPT
#IF IS_DEBUG_BUILD
SCRIPT_ASSERT("SET_CURRENT_SELECTOR_PED - Only works with SELECTOR_PED_MICHAEL, SELECTOR_PED_TREVOR, and SELECTOR_PED_FRANKLIN")
PRINTSTRING("\nSET_CURRENT_SELECTOR_PED - Only works with SELECTOR_PED_MICHAEL, SELECTOR_PED_TREVOR, and SELECTOR_PED_FRANKLIN")PRINTNL()
#ENDIF
RETURN TRUE
ENDIF
// Player is already this character
IF IS_PED_MODEL(PLAYER_PED_ID(), eModel)
RETURN TRUE
ENDIF
// Reques the ped model
REQUEST_MODEL(eModel)
// Model not loaded yet
IF NOT HAS_MODEL_LOADED(eModel)
RETURN FALSE
ENDIF
// Check if the player is in a vehicle
VEHICLE_INDEX veh
VEHICLE_SEAT seat
IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
veh = GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID())
IF PLAYER_PED_ID() = GET_PED_IN_VEHICLE_SEAT(veh, VS_DRIVER)
seat = VS_DRIVER
ELIF PLAYER_PED_ID() = GET_PED_IN_VEHICLE_SEAT(veh, VS_FRONT_RIGHT)
seat = VS_FRONT_RIGHT
ELIF PLAYER_PED_ID() = GET_PED_IN_VEHICLE_SEAT(veh, VS_BACK_LEFT)
seat = VS_BACK_LEFT
ELIF PLAYER_PED_ID() = GET_PED_IN_VEHICLE_SEAT(veh, VS_BACK_RIGHT)
seat = VS_BACK_RIGHT
ELSE
seat = VS_DRIVER
ENDIF
ELSE
veh = NULL
ENDIF
// Create the selector ped in the players place
IF DOES_ENTITY_EXIST(veh)
AND IS_VEHICLE_DRIVEABLE(veh)
CLEAR_PED_TASKS_IMMEDIATELY(PLAYER_PED_ID())// Gets them out of the vehicle seat
CREATE_PLAYER_PED_INSIDE_VEHICLE(g_sTempSelectorData.pedID[eSlot], ePed, veh, seat, bCleanupModel)
ELSE
VECTOR vCoords = GET_ENTITY_COORDS(PLAYER_PED_ID())
GET_GROUND_Z_FOR_3D_COORD(vCoords, vCoords.z)
CREATE_PLAYER_PED_ON_FOOT(g_sTempSelectorData.pedID[eSlot], ePed, vCoords, GET_ENTITY_HEADING(PLAYER_PED_ID()), bCleanupModel)
ENDIF
// Make the selection
//MAKE_SELECTOR_PED_SELECTION(g_sTempSelectorData, eSlot)
// Force the selection
g_sTempSelectorData.eNewSelectorPed = eSlot
g_sTempSelectorData.bInitialised = TRUE
// Take control
TAKE_CONTROL_OF_SELECTOR_PED(g_sTempSelectorData, FALSE)
// Show this on the UI
DISPLAY_SELECTOR_PED_AUTOSWITCH_UI(eSlot)
// Complete
RETURN TRUE
ENDFUNC
FUNC BOOL IS_CHARACTER_MODEL_CHECK_DONE()
RETURN g_bCharacterModelCheckDone
ENDFUNC
PROC SET_CHARACTER_MODEL_CHECK_DONE(BOOL bSet)
#IF IS_DEBUG_BUILD
IF (bSet != g_bCharacterModelCheckDone)
PRINTLN("g_bCharacterModelCheckDone changed to ", bSet)
ELSE
PRINTLN("g_bCharacterModelCheckDone already ", bSet)
ENDIF
DEBUG_PRINTCALLSTACK()
#ENDIF
g_bCharacterModelCheckDone = bSet
ENDPROC
PROC MAINTAIN_SP_CHARACTER_MODEL_CHECK()
IF NOT g_bCharacterModelCheckDone
CPRINTLN(DEBUG_INIT_SP, "Validating current player model as we start SP...")
#IF USE_FINAL_PRINTS
PRINTLN_FINAL("<2140379> Validating current player model as we start SP...")
#ENDIF
IF IS_PLAYER_PLAYING(PLAYER_ID())
// Run the check if we aren't transitioning, or we're transitioning out of SP.
IF NOT IS_TRANSITION_ACTIVE() // No transition out of MP in progress.
OR (GET_JOINING_GAMEMODE() != GAMEMODE_SP AND GET_JOINING_GAMEMODE() != GAMEMODE_EMPTY AND GET_CURRENT_GAMEMODE() != GAMEMODE_FM) // Current transition isn't in to SP.
IF NOT IS_PLAYER_SWITCH_IN_PROGRESS() //Some form of switch scene being processed.
AND GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(HASH("startup_positioning")) = 0 //Singleplayer character is being placed in the world.
MODEL_NAMES ePlayerModel = GET_PLAYER_MODEL()
CPRINTLN(DEBUG_INIT_SP, "The player model was set to hash ", ENUM_TO_INT(ePlayerModel))
#IF USE_FINAL_PRINTS
PRINTLN_FINAL("<2140379> The player model was set to hash ", ENUM_TO_INT(ePlayerModel))
#ENDIF
IF NOT IS_PLAYER_MODEL_PLAYABLE(ePlayerModel)
CPRINTLN(DEBUG_INIT_SP, "Found the player model set to an invalid hash.")
#IF USE_FINAL_PRINTS
PRINTLN_FINAL("<2140379> Found the player model set to an invalid hash.")
#ENDIF
enumCharacterList eSwapChar
IF IS_PLAYER_MODEL_PLAYABLE( GET_PLAYER_PED_MODEL(g_savedGlobals.sPlayerData.sInfo.eCurrentPed))
CPRINTLN(DEBUG_INIT_SP, "Swapping model back to current tracked player character.")
#IF USE_FINAL_PRINTS
PRINTLN_FINAL("<2140379> Swapping model back to current tracked player character.")
#ENDIF
eSwapChar = g_savedGlobals.sPlayerData.sInfo.eCurrentPed
ELIF IS_PLAYER_MODEL_PLAYABLE( GET_PLAYER_PED_MODEL(g_savedGlobals.sPlayerData.sInfo.eLastKnownPed) )
CPRINTLN(DEBUG_INIT_SP, "Swapping model back to the last known player character.")
#IF USE_FINAL_PRINTS
PRINTLN_FINAL("<2140379> Swapping model back to the last known player character.")
#ENDIF
eSwapChar = g_savedGlobals.sPlayerData.sInfo.eLastKnownPed
ELSE
CPRINTLN(DEBUG_INIT_SP, "Swapping model back to Franklin as a default.")
#IF USE_FINAL_PRINTS
PRINTLN_FINAL("<2140379> Swapping model back to Franklin as a default.")
#ENDIF
eSwapChar = CHAR_FRANKLIN
ENDIF
CPRINTLN(DEBUG_INIT_SP, "Selected character swap is ", GET_PLAYER_PED_STRING(eSwapChar))
#IF USE_FINAL_PRINTS
PRINTLN_FINAL("<2140379> Selected character swap is ", ENUM_TO_INT(eSwapChar))
#ENDIF
IF NOT SET_CURRENT_SELECTOR_PED(GET_SELECTOR_SLOT_FROM_PLAYER_PED_ENUM(eSwapChar))
CPRINTLN(DEBUG_INIT_SP, "Waiting for character swap to complete...")
#IF USE_FINAL_PRINTS
PRINTLN_FINAL("<2140379> Waiting for character swap to complete...")
#ENDIF
SET_CHARACTER_MODEL_CHECK_DONE(FALSE)
EXIT
ENDIF
CPRINTLN(DEBUG_INIT_SP, "Model swapped back to a valid character. Check finished.")
#IF USE_FINAL_PRINTS
PRINTLN_FINAL("<2140379> Model swapped back to a valid character. Check finished.")
#ENDIF
ELSE
SET_CHARACTER_MODEL_CHECK_DONE(TRUE)
CPRINTLN(DEBUG_INIT_SP, "The player character model is valid. Check finished.")
#IF USE_FINAL_PRINTS
PRINTLN_FINAL("<2140379> The player character model is valid. Check finished.")
#ENDIF
ENDIF
ELSE
SET_CHARACTER_MODEL_CHECK_DONE(FALSE)
CPRINTLN(DEBUG_INIT_SP, "Waiting for startup scripts and switch scenes to finish running...")
#IF USE_FINAL_PRINTS
PRINTLN_FINAL("<2140379> Waiting for startup scripts and switch scenes to finish running...")
#ENDIF
ENDIF
ELSE
SET_CHARACTER_MODEL_CHECK_DONE(FALSE)
CPRINTLN(DEBUG_INIT_SP, "Waiting for transition in to SP to finish...")
#IF USE_FINAL_PRINTS
PRINTLN_FINAL("<2140379> Waiting for transition in to SP to finish...")
#ENDIF
ENDIF
ELSE
SET_CHARACTER_MODEL_CHECK_DONE(FALSE)
CPRINTLN(DEBUG_INIT_SP, "Waiting for player to be alive...")
#IF USE_FINAL_PRINTS
PRINTLN_FINAL("<2140379> Waiting for player to be alive...")
#ENDIF
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Obtains the RGB values for the ps4 contoller light effect for chop.
PROC GET_CHOP_CONTROL_LIGHT_EFFECT_COLOUR(INT &R, INT &G, INT &B)
r = 255
g = 0
b = 0
ENDPROC