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

1717 lines
68 KiB
Python
Executable File

//////////////////////////////////////////////////////////////////////////////////////////
// //
// SCRIPT NAME : player_controller_b.sc //
// AUTHOR : Kenneth Ross & Alwyn Roberts //
// DESCRIPTION : Initialises the global data for each player character. //
// Keeps track of all the player data such as weapons, health, //
// armour, last time active, and last known coords. //
// //
//////////////////////////////////////////////////////////////////////////////////////////
USING "rage_builtins.sch"
USING "globals.sch"
USING "player_ped_public.sch"
USING "player_ped_scenes.sch"
USING "selector_public.sch"
USING "commands_camera.sch"
USING "mp_scaleform_functions.sch"
#IF IS_DEBUG_BUILD
USING "commands_debug.sch"
USING "player_controller_debug.sch"
#ENDIF
ENUM PLAYER_CONTROL_STAGE_ENUM
PC_STAGE_INIT = 0,
PC_STAGE_WAIT,
PC_STAGE_SWITCH,
PC_STAGE_END
ENDENUM
PLAYER_CONTROL_STAGE_ENUM eStage = PC_STAGE_INIT
//SELECTOR_SLOTS_ENUM eSelectorPed
//SELECTOR_CAM_STRUCT sSelectorCam
BOOL bMP_to_SP_switch, bDeleteCharStruct, bResetMichael1Assets
BOOL bRequestedPedModelsOnSelectorUI = FALSE
SCALEFORM_LOADING_ICON sDeleteCharStruct
PED_SCENE_STRUCT sSceneData // The struct used for the new scene system
#IF IS_DEBUG_BUILD
WIDGET_GROUP_ID wPlayerControllerWidget
BOOL bPerformDemo, bTestSelectedMissionSceneCoords, bGetAverageOfMissionArray, bBubblesortCharSwitchesByDist
INT iTempRecentlySelectedScene
BOOL bTest_Default_PedTo_Coord_Move
BOOL bSWITCH_FLAG_DESCENT_ONLY = FALSE
INT iTempSwitchFlags = 0
BOOL bUpdateLocations
//BOOL bGetVehDamage, bSetVehDamage
//VECTOR vSetVehDamage[4]
TEXT_WIDGET_ID wTestWidget
BOOL bRandomisePlayerVariations
BOOL bTestDefaultPedToCoordMove
PROC SETUP_PLAYER_CONTROL_DEBUG_WIDGETS()
wPlayerControllerWidget = START_WIDGET_GROUP("Player_Controller_B")
ADD_WIDGET_BOOL("Draw debug display", g_bDrawPlayerControlDebugDisplay)
ADD_WIDGET_BOOL("Draw Literal Scene String", g_bDrawLiteralSceneString)
ADD_WIDGET_BOOL("Set player clothes in cutscenes", g_bSetPlayerClothesInCutscenes)
ADD_WIDGET_BOOL("Set player weapons in cutscenes", g_bSetPlayerWeaponsInCutscenes)
ADD_WIDGET_BOOL("Update locations", bUpdateLocations)
// ADD_WIDGET_BOOL("Get Veh Damage", bGetVehDamage)
// ADD_WIDGET_BOOL("Set Veh Damage", bSetVehDamage)
// ADD_WIDGET_VECTOR_SLIDER("vVehDamage", vSetVehDamage, -1,1,0.0001)
ADD_WIDGET_BOOL("Debug print: Scene Schedule Info", g_bDebugPrint_SceneScheduleInfo)
// PED_REQUEST_SCENE_ENUM eScene
// START_NEW_WIDGET_COMBO()
// REPEAT (ENUM_TO_INT(NUM_OF_PED_REQUEST_SCENES)+2) eScene
// ADD_TO_WIDGET_COMBO(Get_String_From_Ped_Request_Scene_Enum(eScene))
// ENDREPEAT
// STOP_WIDGET_COMBO("Recent Location", iTempRecentlySelectedScene)
g_iSelectedDebugPlayerCharScene = GET_RANDOM_INT_IN_RANGE(0, ENUM_TO_INT(NUM_OF_PED_REQUEST_SCENES))
// START_NEW_WIDGET_COMBO()
// REPEAT NUM_OF_PED_REQUEST_SCENES eScene
// ADD_TO_WIDGET_COMBO(Get_String_From_Ped_Request_Scene_Enum(eScene))
// ENDREPEAT
// STOP_WIDGET_COMBO("Locations", g_iSelectedDebugPlayerCharScene)
ADD_WIDGET_INT_SLIDER("Location num", g_iSelectedDebugPlayerCharScene, 0, ENUM_TO_INT(NUM_OF_PED_REQUEST_SCENES)-1, 1)
wTestWidget = ADD_TEXT_WIDGET("Location name")
SET_CONTENTS_OF_TEXT_WIDGET(wTestWidget, Get_String_From_Ped_Request_Scene_Enum(INT_TO_ENUM(PED_REQUEST_SCENE_ENUM, g_iSelectedDebugPlayerCharScene)))
ADD_WIDGET_BOOL("Warp to selected location", g_bWarpDebugPlayerCharScene)
ADD_WIDGET_BOOL("bSWITCH_FLAG_descent_only", bSWITCH_FLAG_DESCENT_ONLY)
ADD_WIDGET_BOOL("Perform Scene Demo", bPerformDemo)
ADD_WIDGET_BOOL("Test Selected Mission Scene Coords", bTestSelectedMissionSceneCoords)
ADD_WIDGET_BOOL("Get Average Of Mission Array", bGetAverageOfMissionArray)
ADD_WIDGET_BOOL("Bubblesort Char Switches By Dist", bBubblesortCharSwitchesByDist)
ADD_WIDGET_BOOL("bTest_Default_PedTo_Coord_Move", bTest_Default_PedTo_Coord_Move)
ADD_WIDGET_BOOL("bTestDefaultPedToCoordMove", bTestDefaultPedToCoordMove)
STOP_WIDGET_GROUP()
ENDPROC
PROC MAINTAIN_PLAYER_CONTROL_DEBUG_WIDGETS()
IF bTestDefaultPedToCoordMove
AND NOT IS_PED_INJURED(PLAYER_PED_ID())
WIDGET_GROUP_ID wTestDefaultPedTo
VECTOR vTestDefaultPedToPoint = GET_ENTITY_COORDS(PLAYER_PED_ID())
VECTOR vTestDefaultPedToCoors1 = vTestDefaultPedToPoint - <<10.0, 10.0, 10.0>>
VECTOR vTestDefaultPedToCoors2 = vTestDefaultPedToPoint + <<10.0, 10.0, 10.0>>
FLOAT fTestDefaultPedToDistance = 5.0
SET_CURRENT_WIDGET_GROUP(wPlayerControllerWidget)
wTestDefaultPedTo = START_WIDGET_GROUP("wTestDefaultPedTo")
ADD_WIDGET_BOOL("bTestDefaultPedToCoordMove", bTestDefaultPedToCoordMove)
ADD_WIDGET_VECTOR_SLIDER("vTestDefaultPedToPoint", vTestDefaultPedToPoint, -3000, 3000, 0.1)
ADD_WIDGET_VECTOR_SLIDER("vTestDefaultPedToCoors1", vTestDefaultPedToCoors1, -3000, 3000, 0.1)
ADD_WIDGET_VECTOR_SLIDER("vTestDefaultPedToCoors2", vTestDefaultPedToCoors2, -3000, 3000, 0.1)
ADD_WIDGET_FLOAT_SLIDER("fTestDefaultPedToDistance", fTestDefaultPedToDistance, 0, 3000, 0.1)
STOP_WIDGET_GROUP()
CLEAR_CURRENT_WIDGET_GROUP(wPlayerControllerWidget)
SET_DEBUG_LINES_AND_SPHERES_DRAWING_ACTIVE(TRUE)
WHILE bTestDefaultPedToCoordMove
AND NOT IS_PED_INJURED(PLAYER_PED_ID())
SET_ENTITY_COORDS(PLAYER_PED_ID(), vTestDefaultPedToPoint)
DRAW_DEBUG_SPHERE(vTestDefaultPedToCoors1, 0.25, 255,000,255,255)
DRAW_DEBUG_SPHERE(vTestDefaultPedToCoors2, 0.25, 255,000,255,255)
IF IS_POINT_IN_ANGLED_AREA(vTestDefaultPedToPoint,
vTestDefaultPedToCoors1, vTestDefaultPedToCoors2,
fTestDefaultPedToDistance)
DRAW_DEBUG_SPHERE(vTestDefaultPedToPoint, 0.5, 255,255,000,255)
ELSE
DRAW_DEBUG_SPHERE(vTestDefaultPedToPoint, 0.5, 000,000,255,255)
ENDIF
// VECTOR vCreateCoords
// FLOAT fCreateHead
// enumBlockedPedCoordZone eZone
// Is_Ped_Last_Known_Coords_In_Blocked_Zone(vTestDefaultPedToPoint, vCreateCoords, fCreateHead, eZone)
WAIT(0)
ENDWHILE
OPEN_DEBUG_FILE()
SAVE_NEWLINE_TO_DEBUG_FILE()
SAVE_STRING_TO_DEBUG_FILE("//PRIVATE_Should_Default_PedTo_Coord_Move()")SAVE_NEWLINE_TO_DEBUG_FILE()
SAVE_STRING_TO_DEBUG_FILE(" IF IS_POINT_IN_ANGLED_AREA(vLastKnownCoords, ")SAVE_VECTOR_TO_DEBUG_FILE(vTestDefaultPedToCoors1)SAVE_STRING_TO_DEBUG_FILE(", ")SAVE_VECTOR_TO_DEBUG_FILE(vTestDefaultPedToCoors2)SAVE_STRING_TO_DEBUG_FILE(", ")SAVE_FLOAT_TO_DEBUG_FILE(fTestDefaultPedToDistance)SAVE_STRING_TO_DEBUG_FILE(")")SAVE_NEWLINE_TO_DEBUG_FILE()
SAVE_STRING_TO_DEBUG_FILE(" vCreateCoords = ")SAVE_VECTOR_TO_DEBUG_FILE(vTestDefaultPedToPoint)SAVE_NEWLINE_TO_DEBUG_FILE()
SAVE_STRING_TO_DEBUG_FILE(" fCreateHead = ")SAVE_VECTOR_TO_DEBUG_FILE(vTestDefaultPedToPoint)SAVE_NEWLINE_TO_DEBUG_FILE()
SAVE_STRING_TO_DEBUG_FILE(" RETURN TRUE")SAVE_NEWLINE_TO_DEBUG_FILE()
SAVE_NEWLINE_TO_DEBUG_FILE()
CLOSE_DEBUG_FILE()
DELETE_WIDGET_GROUP(wTestDefaultPedTo)
ENDIF
IF bRandomisePlayerVariations
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
SET_PED_RANDOM_COMPONENT_VARIATION(PLAYER_PED_ID())
ENDIF
bRandomisePlayerVariations = FALSE
ENDIF
IF bUpdateLocations
iTempRecentlySelectedScene = ENUM_TO_INT(g_eRecentlySelectedScene)
ENDIF
SET_CONTENTS_OF_TEXT_WIDGET(wTestWidget, Get_String_From_Ped_Request_Scene_Enum(INT_TO_ENUM(PED_REQUEST_SCENE_ENUM, g_iSelectedDebugPlayerCharScene)))
IF g_bWarpDebugPlayerCharScene
//for bug 884228
PED_SCENE_STRUCT sDebugSceneData
sDebugSceneData.sSelectorPeds.ePreviousSelectorPed = SELECTOR_PED_MICHAEL
sDebugSceneData.iStage = 0
sDebugSceneData.eScene = INT_TO_ENUM(PED_REQUEST_SCENE_ENUM, g_iSelectedDebugPlayerCharScene)
sDebugSceneData.sSelectorCam.bSplineCreated = FALSE
CLEAR_Pause_Outro_Count()
GET_PLAYER_CHAR_FOR_PED_REQUEST_SCENE(sDebugSceneData.eScene, sDebugSceneData.ePed)
IF (sDebugSceneData.ePed = CHAR_MULTIPLAYER)
IF (sDebugSceneData.eScene = PR_SCENE_FTa_FRANKLIN1a
// OR sDebugSceneData.eScene = PR_SCENE_FTa_FRANKLIN1b
OR sDebugSceneData.eScene = PR_SCENE_FTa_FRANKLIN1c
OR sDebugSceneData.eScene = PR_SCENE_FTa_FRANKLIN1d
OR sDebugSceneData.eScene = PR_SCENE_FTa_FRANKLIN1e)
SWITCH GET_CURRENT_PLAYER_PED_ENUM()
CASE CHAR_MICHAEL
IF GET_RANDOM_INT_IN_RANGE(0, 100) < 50
sDebugSceneData.ePed = CHAR_FRANKLIN
ELSE
sDebugSceneData.ePed = CHAR_TREVOR
ENDIF
BREAK
CASE CHAR_FRANKLIN
sDebugSceneData.ePed = CHAR_TREVOR
BREAK
CASE CHAR_TREVOR
sDebugSceneData.ePed = CHAR_FRANKLIN
BREAK
ENDSWITCH
ENDIF
ENDIF
FLOAT fScenePercent = -1
PED_REQUEST_SCENE_ENUM eDebugSelectedScene = PR_SCENE_INVALID
IF NOT GET_PLAYER_PED_POSITION_FOR_SCENE(sDebugSceneData.eScene, sDebugSceneData.vCreateCoords, sDebugSceneData.fCreateHead, sDebugSceneData.tCreateRoom)
enumCharacterList eCurrentPed = sDebugSceneData.ePed
PLAYER_TIMETABLE_SCENE_STRUCT sPassedScene
eDebugSelectedScene = sDebugSceneData.eScene
g_SavedGlobals.sPlayerSceneData.g_ePlayerLastScene[sDebugSceneData.ePed] = eDebugSelectedScene
IF IS_PED_THE_CURRENT_PLAYER_PED(sDebugSceneData.ePed)
SELECTOR_SLOTS_ENUM newSelectorPed
SWITCH sDebugSceneData.ePed
CASE CHAR_MICHAEL
IF GET_RANDOM_INT_IN_RANGE(0, 100) < 50
newSelectorPed = SELECTOR_PED_FRANKLIN
ELSE
newSelectorPed = SELECTOR_PED_TREVOR
ENDIF
BREAK
CASE CHAR_FRANKLIN
IF GET_RANDOM_INT_IN_RANGE(0, 100) < 50
newSelectorPed = SELECTOR_PED_MICHAEL
ELSE
newSelectorPed = SELECTOR_PED_TREVOR
ENDIF
BREAK
CASE CHAR_TREVOR
IF GET_RANDOM_INT_IN_RANGE(0, 100) < 50
newSelectorPed = SELECTOR_PED_MICHAEL
ELSE
newSelectorPed = SELECTOR_PED_FRANKLIN
ENDIF
BREAK
ENDSWITCH
WHILE NOT SET_CURRENT_SELECTOR_PED(newSelectorPed)
WAIT(0)
ENDWHILE
ENDIF
GET_PLAYER_PED_SCENE_FOR_CURRENT_TIME(sDebugSceneData.ePed, sDebugSceneData.eScene, fScenePercent, sDebugSceneData, sPassedScene)
sDebugSceneData.ePed = eCurrentPed
ENDIF
IF IS_PED_THE_CURRENT_PLAYER_PED(sDebugSceneData.ePed)
SELECTOR_SLOTS_ENUM newSelectorPed
SWITCH sDebugSceneData.ePed
CASE CHAR_MICHAEL
IF GET_RANDOM_INT_IN_RANGE(0, 100) < 50
newSelectorPed = SELECTOR_PED_FRANKLIN
ELSE
newSelectorPed = SELECTOR_PED_TREVOR
ENDIF
BREAK
CASE CHAR_FRANKLIN
IF GET_RANDOM_INT_IN_RANGE(0, 100) < 50
newSelectorPed = SELECTOR_PED_MICHAEL
ELSE
newSelectorPed = SELECTOR_PED_TREVOR
ENDIF
BREAK
CASE CHAR_TREVOR
IF GET_RANDOM_INT_IN_RANGE(0, 100) < 50
newSelectorPed = SELECTOR_PED_MICHAEL
ELSE
newSelectorPed = SELECTOR_PED_FRANKLIN
ENDIF
BREAK
ENDSWITCH
WHILE NOT SET_CURRENT_SELECTOR_PED(newSelectorPed)
WAIT(0)
ENDWHILE
ENDIF
SWITCH GET_CURRENT_PLAYER_PED_ENUM()
CASE CHAR_MICHAEL
Set_Mission_Flow_Flag_State(FLOWFLAG_PLAYER_PED_INTRODUCED_M, TRUE)
SET_PLAYER_PED_AVAILABLE(CHAR_MICHAEL, TRUE)
BREAK
CASE CHAR_FRANKLIN
Set_Mission_Flow_Flag_State(FLOWFLAG_PLAYER_PED_INTRODUCED_F, TRUE)
SET_PLAYER_PED_AVAILABLE(CHAR_FRANKLIN, TRUE)
BREAK
CASE CHAR_TREVOR
Set_Mission_Flow_Flag_State(FLOWFLAG_PLAYER_PED_INTRODUCED_T, TRUE)
SET_PLAYER_PED_AVAILABLE(CHAR_TREVOR, TRUE)
BREAK
ENDSWITCH
// // // #949607
SELECTOR_SLOTS_ENUM ePedSlot = GET_SELECTOR_SLOT_FROM_PLAYER_PED_ENUM(sDebugSceneData.ePed)
IF DOES_ENTITY_EXIST(sDebugSceneData.sSelectorPeds.pedID[ePedSlot])
CPRINTLN(DEBUG_SWITCH, "slot ", GET_PLAYER_PED_STRING(sDebugSceneData.ePed), " has ", "sDebugSceneData exists")
VECTOR vCreateCoords
FLOAT fCreateHead
TEXT_LABEL_31 tRoom
IF GET_PLAYER_PED_POSITION_FOR_SCENE(sDebugSceneData.eScene, vCreateCoords, fCreateHead, tRoom)
VECTOR vPedSlotCoord = GET_ENTITY_COORDS(sDebugSceneData.sSelectorPeds.pedID[ePedSlot], FALSE)
IF NOT ARE_VECTORS_ALMOST_EQUAL(vCreateCoords, vPedSlotCoord, 5.0)
CPRINTLN(DEBUG_SWITCH, " pedTo(", vPedSlotCoord, ") nowhere near vCreateCoords(", vCreateCoords, "): dist:", VDIST(vCreateCoords, vPedSlotCoord))
SET_ENTITY_COORDS(sDebugSceneData.sSelectorPeds.pedID[ePedSlot], vCreateCoords)
SET_ENTITY_HEADING(sDebugSceneData.sSelectorPeds.pedID[ePedSlot], fCreateHead)
ENDIF
ENDIF
ELSE
CPRINTLN(DEBUG_SWITCH, "slot ", GET_PLAYER_PED_STRING(sDebugSceneData.ePed), " has ", "sDebugSceneData DOESNT exist")
ENDIF
// // //
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
CLEAR_AREA(GET_ENTITY_COORDS(PLAYER_PED_ID()), 50.0, TRUE)
CLEAR_AREA_OF_VEHICLES(GET_ENTITY_COORDS(PLAYER_PED_ID()), 50.0)
ENDIF
// set switch flags if needed
IF bSWITCH_FLAG_DESCENT_ONLY
IF NOT IS_BITMASK_AS_ENUM_SET(iTempSwitchFlags, SWITCH_FLAG_DESCENT_ONLY)
SET_BITMASK_AS_ENUM(iTempSwitchFlags, SWITCH_FLAG_DESCENT_ONLY)
ENDIF
ELSE
IF IS_BITMASK_AS_ENUM_SET(iTempSwitchFlags, SWITCH_FLAG_DESCENT_ONLY)
CLEAR_BITMASK_AS_ENUM(iTempSwitchFlags, SWITCH_FLAG_DESCENT_ONLY)
ENDIF
ENDIF
//perform switch flag checks if needed
IF IS_BITMASK_AS_ENUM_SET(iTempSwitchFlags, SWITCH_FLAG_DESCENT_ONLY)
DO_SCREEN_FADE_OUT(0)
IF NOT IS_ENTITY_DEAD(PLAYER_PED_ID())
VECTOR vCreateCoords
FLOAT fCreateHead
TEXT_LABEL_31 tRoom
IF GET_PLAYER_PED_POSITION_FOR_SCENE(sDebugSceneData.eScene, vCreateCoords, fCreateHead, tRoom)
VECTOR vRespawnDescentCoords
vRespawnDescentCoords = GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(vCreateCoords, fCreateHead, <<0,0,5>>)
SET_ENTITY_COORDS(PLAYER_PED_ID(), vRespawnDescentCoords)
SET_ENTITY_SHOULD_FREEZE_WAITING_ON_COLLISION(PLAYER_PED_ID(), TRUE)
FREEZE_ENTITY_POSITION(PLAYER_PED_ID(), TRUE)
// load the stream vol
NEW_LOAD_SCENE_START_SPHERE(vCreateCoords, 150, NEWLOADSCENE_FLAG_REQUIRE_COLLISION)
INT iNewLoadSceneTimeout = 0
CPRINTLN(DEBUG_SWITCH, "<player_controller_b> wait for new load scene.")
WHILE NOT IS_NEW_LOAD_SCENE_LOADED()
AND (iNewLoadSceneTimeout < 350)
iNewLoadSceneTimeout++
WAIT(0)
ENDWHILE
CPRINTLN(DEBUG_SWITCH, "<player_controller_b> new load scene loaded [", iNewLoadSceneTimeout, "].")
ENDIF
ENDIF
ENDIF
BOOL bPerformingGenericPedScene = TRUE
WHILE IS_PLAYER_PLAYING(PLAYER_ID())
AND bPerformingGenericPedScene
IF NOT GENERIC_PED_SCENE(sDebugSceneData,
&SCENE_CUSTOM_SCRIPT_REQUEST,
&SCENE_CUSTOM_SCRIPT_SETUP, iTempSwitchFlags)
IF (eDebugSelectedScene <> PR_SCENE_INVALID)
#IF IS_DEBUG_BUILD
IF g_bDrawLiteralSceneString
STRING sScene
sScene = Get_String_From_Ped_Request_Scene_Enum(eDebugSelectedScene)
HUD_COLOURS eHudColour
eHudColour = HUD_COLOUR_BLUELIGHT
TEXT_LABEL_63 sLiteral
sLiteral = ("eDebugSelectedScene = \"")
sLiteral += GET_STRING_FROM_STRING(sScene,
GET_LENGTH_OF_LITERAL_STRING("PR_SCENE_"),
GET_LENGTH_OF_LITERAL_STRING(sScene))
sLiteral += ("\" , percent: ")
sLiteral += GET_STRING_FROM_FLOAT(fScenePercent)
SET_TEXT_SCALE(0.4, 0.4)
SET_TEXT_HUD_COLOUR(eHudColour, 127)
SET_TEXT_JUSTIFICATION(FONT_CENTRE)
SET_TEXT_OUTLINE()
DISPLAY_TEXT_WITH_LITERAL_STRING(0.5, 0.925 - 0.03 - 0.03, "STRING", sLiteral)
ENDIF
#ENDIF
ENDIF
iTempRecentlySelectedScene = ENUM_TO_INT(g_eRecentlySelectedScene)
ELSE
bPerformingGenericPedScene = FALSE
ENDIF
WAIT(0)
ENDWHILE
SWITCH GET_CURRENT_PLAYER_PED_ENUM()
CASE CHAR_MICHAEL
Set_Mission_Flow_Flag_State(FLOWFLAG_PLAYER_PED_INTRODUCED_M, TRUE)
SET_PLAYER_PED_AVAILABLE(CHAR_MICHAEL, TRUE)
BREAK
CASE CHAR_FRANKLIN
Set_Mission_Flow_Flag_State(FLOWFLAG_PLAYER_PED_INTRODUCED_F, TRUE)
SET_PLAYER_PED_AVAILABLE(CHAR_FRANKLIN, TRUE)
BREAK
CASE CHAR_TREVOR
Set_Mission_Flow_Flag_State(FLOWFLAG_PLAYER_PED_INTRODUCED_T, TRUE)
SET_PLAYER_PED_AVAILABLE(CHAR_TREVOR, TRUE)
BREAK
ENDSWITCH
g_bWarpDebugPlayerCharScene = FALSE
ENDIF
// IF bGetVehDamage
// VEHICLE_INDEX playerVehID = GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID())
// IF DOES_ENTITY_EXIST(playerVehID)
// VECTOR BoundingBoxMin, BoundingBoxMax
// GET_MODEL_DIMENSIONS(GET_ENTITY_MODEL(playerVehID), BoundingBoxMin, BoundingBoxMax)
//
// VECTOR vecFrontPos = <<0,BoundingBoxMax.y, 0>>
// VECTOR vecRearPos = <<0,-BoundingBoxMax.y, 0>>
// VECTOR vecLeftPos = <<BoundingBoxMax.x,0, 0>>
// VECTOR vecRightPos = <<-BoundingBoxMax.x,0, 0>>
//
// VECTOR vecFrontDeform = GET_VEHICLE_DEFORMATION_AT_POS(playerVehID, vecFrontPos)
// VECTOR vecRearDeform = GET_VEHICLE_DEFORMATION_AT_POS(playerVehID, vecRearPos)
// VECTOR vecLeftDeform = GET_VEHICLE_DEFORMATION_AT_POS(playerVehID, vecLeftPos)
// VECTOR vecRightDeform = GET_VEHICLE_DEFORMATION_AT_POS(playerVehID, vecRightPos)
//
// SAVE_STRING_TO_DEBUG_FILE("vecFrontDeform: ")SAVE_VECTOR_TO_DEBUG_FILE(vecFrontDeform)SAVE_NEWLINE_TO_DEBUG_FILE()
// SAVE_STRING_TO_DEBUG_FILE("vecRearDeform: ")SAVE_VECTOR_TO_DEBUG_FILE(vecRearDeform)SAVE_NEWLINE_TO_DEBUG_FILE()
// SAVE_STRING_TO_DEBUG_FILE("vecLeftDeform: ")SAVE_VECTOR_TO_DEBUG_FILE(vecLeftDeform)SAVE_NEWLINE_TO_DEBUG_FILE()
// SAVE_STRING_TO_DEBUG_FILE("vecRightDeform: ")SAVE_VECTOR_TO_DEBUG_FILE(vecRightDeform)SAVE_NEWLINE_TO_DEBUG_FILE()
// SAVE_NEWLINE_TO_DEBUG_FILE()
// ENDIF
//
// bGetVehDamage = FALSE
// ENDIF
// IF bSetVehDamage
// VEHICLE_INDEX playerVehID = GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID())
// IF DOES_ENTITY_EXIST(playerVehID)
// VECTOR BoundingBoxMin, BoundingBoxMax
// GET_MODEL_DIMENSIONS(GET_ENTITY_MODEL(playerVehID), BoundingBoxMin, BoundingBoxMax)
//
// VECTOR vecFrontPos = <<0,BoundingBoxMax.y, 0>>
// VECTOR vecRearPos = <<0,-BoundingBoxMax.y, 0>>
// VECTOR vecLeftPos = <<BoundingBoxMax.x,0, 0>>
// VECTOR vecRightPos = <<-BoundingBoxMax.x,0, 0>>
//
// SET_VEHICLE_DAMAGE(playerVehID, vecFrontPos, vSetVehDamage[0], VMAG(vSetVehDamage[0]), TRUE)
// ENDIF
//
// bSetVehDamage = FALSE
// ENDIF
IF bPerformDemo
PED_REQUEST_SCENE_ENUM sceneArray[NUM_OF_PED_REQUEST_SCENES]
INT iSceneWait[NUM_OF_PED_REQUEST_SCENES]
Perform_Switch_Demo(sceneArray, iSceneWait,
bPerformDemo, iTempRecentlySelectedScene)
bPerformDemo = FALSE
ENDIF
IF bTestSelectedMissionSceneCoords
PED_REQUEST_SCENE_ENUM eReqScene
REPEAT NUM_OF_PED_REQUEST_SCENES eReqScene
IF (eReqScene <> PR_SCENE_DEAD)
enumCharacterList ePed = NO_CHARACTER
GET_PLAYER_CHAR_FOR_PED_REQUEST_SCENE(eReqScene, ePed)
IF TestSelectedMissionSceneCoords(eReqScene)
CPRINTLN(DEBUG_SWITCH, "TestSelectedMissionSceneCoords(")
CPRINTLN(DEBUG_SWITCH, Get_String_From_Ped_Request_Scene_Enum(eReqScene))
CPRINTLN(DEBUG_SWITCH, "): TRUE")
ELSE
CPRINTLN(DEBUG_SWITCH, "TestSelectedMissionSceneCoords(")
CPRINTLN(DEBUG_SWITCH, Get_String_From_Ped_Request_Scene_Enum(eReqScene))
CPRINTLN(DEBUG_SWITCH, "): FALSE")
ENDIF
ENDIF
ENDREPEAT
bTestSelectedMissionSceneCoords = FALSE
ENDIF
IF bGetAverageOfMissionArray
Get_Average_Of_Mission_Array(wPlayerControllerWidget, bGetAverageOfMissionArray)
bGetAverageOfMissionArray = FALSE
ENDIF
IF bBubblesortCharSwitchesByDist
//create a list of scenes just for the current player char
enumCharacterList ePlayerPed = GET_CURRENT_PLAYER_PED_ENUM()
VECTOR vPlayerCoord = GET_ENTITY_COORDS(PLAYER_PED_ID())
PED_REQUEST_SCENE_ENUM sceneArray[NUM_OF_PED_REQUEST_SCENES], eScene
INT iSceneCount = 0
REPEAT COUNT_OF(sceneArray) eScene
VECTOR vLastKnownCoords = <<0,0,0>>
FLOAT fLastKnownHead = 0
IF (eScene <> PR_SCENE_DEAD)
AND NOT GetLastKnownPedInfoPostMission(eScene, vLastKnownCoords, fLastKnownHead)
IF NOT ARE_VECTORS_EQUAL(g_sPedSceneData[eScene].vCreateCoords, <<0,0,0>>)
enumCharacterList ePed = NO_CHARACTER
GET_PLAYER_CHAR_FOR_PED_REQUEST_SCENE(eScene, ePed)
IF ePed = ePlayerPed
sceneArray[iSceneCount] = eScene
iSceneCount++
ENDIF
ENDIF
ENDIF
ENDREPEAT
//sort that list
INT i, j
FOR i = 0 TO iSceneCount
FOR j = 0 TO iSceneCount-1
FLOAT jDjst = VDIST(vPlayerCoord, g_sPedSceneData[sceneArray[j]].vCreateCoords)
FLOAT jPlusDist = VDIST(vPlayerCoord, g_sPedSceneData[sceneArray[j+1]].vCreateCoords)
iF jPlusDist < jDjst
PED_REQUEST_SCENE_ENUM sceneTempj = sceneArray[j+1]
sceneArray[j+1] = sceneArray[j]
sceneArray[j] = sceneTempj
ENDIF
ENDFOR
i = i
ENDFOR
//output the list
REPEAT iSceneCount eScene
CPRINTLN(DEBUG_SWITCH, "sceneArray[")
CPRINTLN(DEBUG_SWITCH, Get_String_From_Ped_Request_Scene_Enum(sceneArray[eScene]))
CPRINTLN(DEBUG_SWITCH, "] = ")
CPRINTLN(DEBUG_SWITCH, VDIST(vPlayerCoord, g_sPedSceneData[sceneArray[eScene]].vCreateCoords))
CPRINTLN(DEBUG_SWITCH, "m")
ENDREPEAT
bBubblesortCharSwitchesByDist = FALSE
ENDIF
IF bTest_Default_PedTo_Coord_Move
INT iPlayerHashKey = GET_ROOM_KEY_FROM_ENTITY(PLAYER_PED_ID())
VECTOR VecCoords1 = <<428.292847,-996.683411,24.488642>>
VECTOR VecCoords2 = <<439.543823,-996.711365,28.103334>>
FLOAT AreaWidth = 8.687500
TEXT_WIDGET_ID tw_Text
SET_CURRENT_WIDGET_GROUP(wPlayerControllerWidget)
WIDGET_GROUP_ID wg_TestWidget = START_WIDGET_GROUP("bTest_Default_PedTo_Coord_Move")
ADD_WIDGET_BOOL("bTest_Default_PedTo_Coord_Move", bTest_Default_PedTo_Coord_Move)
tw_Text = ADD_TEXT_WIDGET("sPlayerRoomName")
ADD_WIDGET_VECTOR_SLIDER("VecCoords1", VecCoords1, -5000.0, 5000.0, 0.1)
ADD_WIDGET_VECTOR_SLIDER("VecCoords2", VecCoords2, -5000.0, 5000.0, 0.1)
ADD_WIDGET_FLOAT_SLIDER("AreaWidth", AreaWidth, 0.0, 100.0, 0.1)
STOP_WIDGET_GROUP()
CLEAR_CURRENT_WIDGET_GROUP(wPlayerControllerWidget)
TEXT_LABEL_31 sPlayerRoomName
WHILE bTest_Default_PedTo_Coord_Move
AND NOT IS_PED_INJURED(PLAYER_PED_ID())
VECTOR vPlayerCoord = GET_ENTITY_COORDS(PLAYER_PED_ID())
iPlayerHashKey = GET_ROOM_KEY_FROM_ENTITY(PLAYER_PED_ID())
sPlayerRoomName = DEBUG_get_string_room_hash_key(iPlayerHashKey)
SET_CONTENTS_OF_TEXT_WIDGET(tw_Text, sPlayerRoomName)
IF IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), VecCoords1, VecCoords2, AreaWidth)
CPRINTLN(DEBUG_SWITCH, "PRIVATE_Should_Default_PedTo_Coord_Move(\"", sPlayerRoomName, "\"): vLastKnownCoords ", vPlayerCoord, " inside zone")
ELSE
CPRINTLN(DEBUG_SWITCH, "PRIVATE_Should_Default_PedTo_Coord_Move(\"", sPlayerRoomName, "\"): vLastKnownCoords ", vPlayerCoord, " not inside zone...")
ENDIF
WAIT(0)
ENDWHILE
bTest_Default_PedTo_Coord_Move = FALSE
SAVE_NEWLINE_TO_DEBUG_FILE()
SAVE_STRING_TO_DEBUG_FILE(" CASE HASH(\"")
SAVE_STRING_TO_DEBUG_FILE(sPlayerRoomName)
SAVE_STRING_TO_DEBUG_FILE("\")) //")
SAVE_NEWLINE_TO_DEBUG_FILE()
SAVE_STRING_TO_DEBUG_FILE(" IF IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), ")
SAVE_VECTOR_TO_DEBUG_FILE(VecCoords1)
SAVE_STRING_TO_DEBUG_FILE(", ")
SAVE_VECTOR_TO_DEBUG_FILE(VecCoords2)
SAVE_STRING_TO_DEBUG_FILE(", ")
SAVE_FLOAT_TO_DEBUG_FILE(AreaWidth)
SAVE_STRING_TO_DEBUG_FILE(")")
SAVE_NEWLINE_TO_DEBUG_FILE()
SAVE_NEWLINE_TO_DEBUG_FILE()
DELETE_WIDGET_GROUP(wg_TestWidget)
ENDIF
ENDPROC
#ENDIF
// ===========================================================================================================
// Cleanup
// ===========================================================================================================
// PURPOSE: Ensures that the script gets a chance to cleanup under specific circumstances (ie: moving from SP to MP)
//
PROC Player_Controller_B_Cleanup()
IF (g_sPlayerPedRequest.eState = PR_STATE_PROCESSING)
CPRINTLN(DEBUG_SWITCH, "Player_Controller_B_Cleanup() g_sPlayerPedRequest.eState = PR_STATE_PROCESSING")
// CASSERTLN(DEBUG_SWITCH, "Player_Controller_B_Cleanup() eState = PR_STATE_PROCESSING")
ENDIF
IF g_sPlayerPedRequest.iStage <> 0
CPRINTLN(DEBUG_SWITCH, "Player_Controller_B_Cleanup() g_sPlayerPedRequest.iStage <> 0")
// CASSERTLN(DEBUG_SWITCH, "Player_Controller_B_Cleanup() iStage <> 0")
ENDIF
IF bRequestedPedModelsOnSelectorUI
CPRINTLN(DEBUG_SWITCH, "Player_Controller_B_Cleanup() - NOT g_sSelectorUI.bLoaded")
bRequestedPedModelsOnSelectorUI = FALSE
enumCharacterList ePed
REPEAT NUM_OF_PLAYABLE_PEDS ePed
IF NOT IS_PED_THE_CURRENT_PLAYER_PED(ePed)
MODEL_NAMES model = GET_PLAYER_PED_MODEL(ePed)
SET_MODEL_AS_NO_LONGER_NEEDED(model)
CPRINTLN(DEBUG_SWITCH, " model ", ePed, " no longer needed.")
ELSE
CPRINTLN(DEBUG_SWITCH, " model ", ePed, " current player ped.")
ENDIF
ENDREPEAT
ENDIF
TERMINATE_THIS_THREAD()
ENDPROC
/// PURPOSE: Checks if a request has been made to switch the player character
PROC CHECK_PLAYER_PED_REQUEST()
IF g_sPlayerPedRequest.eState = PR_STATE_PROCESSING
eStage = PC_STAGE_SWITCH
ENDIF
IF g_sSelectorUI.bLoaded
IF NOT bRequestedPedModelsOnSelectorUI
CPRINTLN(DEBUG_SWITCH, "CHECK_PLAYER_PED_REQUEST - g_sSelectorUI.bLoaded")
bRequestedPedModelsOnSelectorUI = TRUE
enumCharacterList ePed
REPEAT NUM_OF_PLAYABLE_PEDS ePed
IF NOT IS_PED_THE_CURRENT_PLAYER_PED(ePed)
MODEL_NAMES model = GET_PLAYER_PED_MODEL(ePed)
REQUEST_MODEL(model)
IF HAS_MODEL_LOADED(model)
CPRINTLN(DEBUG_SWITCH, " model ", ePed, " loaded.")
ELSE
CPRINTLN(DEBUG_SWITCH, " model ", ePed, " NOT loaded.")
bRequestedPedModelsOnSelectorUI = FALSE
ENDIF
ELSE
CPRINTLN(DEBUG_SWITCH, " model ", ePed, " current player ped.")
ENDIF
ENDREPEAT
ENDIF
ELSE
IF bRequestedPedModelsOnSelectorUI
CPRINTLN(DEBUG_SWITCH, "CHECK_PLAYER_PED_REQUEST - NOT g_sSelectorUI.bLoaded")
bRequestedPedModelsOnSelectorUI = FALSE
enumCharacterList ePed
REPEAT NUM_OF_PLAYABLE_PEDS ePed
IF NOT IS_PED_THE_CURRENT_PLAYER_PED(ePed)
MODEL_NAMES model = GET_PLAYER_PED_MODEL(ePed)
SET_MODEL_AS_NO_LONGER_NEEDED(model)
CPRINTLN(DEBUG_SWITCH, " model ", ePed, " no longer needed.")
ELSE
CPRINTLN(DEBUG_SWITCH, " model ", ePed, " current player ped.")
ENDIF
ENDREPEAT
ENDIF
ENDIF
ENDPROC
/// PURPOSE: Performs the player ped switch using the ped request data
PROC MAINTAIN_PLAYER_PED_REQUEST()
PED_SCENE_STRUCT sPedScene
//////////////////////////////////////////////////////////////////////////////////////////////////
/// Process the ped switch
SWITCH g_sPlayerPedRequest.eState
CASE PR_STATE_PROCESSING
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
PLAYER_TIMETABLE_SCENE_STRUCT sPassedScene
// // // // // // // // // // // // // //
// stage 0: initialise switch deets
//
IF (g_sPlayerPedRequest.iStage = 0)
// Fix for bug #107444 - Add a communication delay so the current character
// cannot contact you straight after you switch to the selected character.
enumCharacterList eCurrentPed
eCurrentPed = GET_CURRENT_PLAYER_PED_ENUM()
IF eCurrentPed <> NO_CHARACTER
ADD_COMMUNICATION_DELAY_FOR_CHARACTER(eCurrentPed)
ENDIF
CLEAR_Pause_Outro_Count()
// Set the global communication delay to a short timer when switching
ADD_GLOBAL_COMMUNICATION_DELAY(6000)
// Clear the savehouse vehicle spawn delay when switching
INT i
REPEAT NUM_OF_PLAYABLE_PEDS i
g_iCreatedPlayerVehicleCleanupTimer[i][0] = -1
g_iCreatedPlayerVehicleCleanupTimer[i][1] = -1
ENDREPEAT
sSceneData.sSelectorPeds = g_sPlayerPedRequest.sSelectorPeds
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_SWITCH, "<player_controller_b> global before sSelectorPeds.pedID [", NATIVE_TO_INT(g_sPlayerPedRequest.sSelectorPeds.pedID[SELECTOR_PED_MICHAEL]), ", ", NATIVE_TO_INT(g_sPlayerPedRequest.sSelectorPeds.pedID[SELECTOR_PED_FRANKLIN]), ", ", NATIVE_TO_INT(g_sPlayerPedRequest.sSelectorPeds.pedID[SELECTOR_PED_TREVOR]), "] //", GET_PLAYER_PED_STRING(g_sPlayerPedRequest.ePed))
#ENDIF
// Setup the scene data
sSceneData.iStage = 0
sSceneData.eScene = PR_SCENE_INVALID
sSceneData.ePed = g_sPlayerPedRequest.ePed
IF (sSceneData.ePed = CHAR_MULTIPLAYER)
sSceneData.ePed = GET_CURRENT_PLAYER_PED_ENUM()
ENDIF
IF (sSceneData.ePed = NO_CHARACTER)
sSceneData.ePed = GET_CURRENT_PLAYER_PED_ENUM()
ENDIF
SELECTOR_SLOTS_ENUM eSelectorChar
eSelectorChar = GET_SELECTOR_SLOT_FROM_PLAYER_PED_ENUM(g_sPlayerPedRequest.ePed)
sSceneData.sSelectorPeds.pedID[eSelectorChar] = g_sPlayerPedRequest.sSelectorPeds.pedID[eSelectorChar]
#IF IS_DEBUG_BUILD
BOOL bDebugPrint_SceneScheduleInfo
bDebugPrint_SceneScheduleInfo = g_bDebugPrint_SceneScheduleInfo
g_bDebugPrint_SceneScheduleInfo = TRUE
#ENDIF
FLOAT fScenePercent
IF GET_PLAYER_PED_SCENE_FOR_CURRENT_TIME(sSceneData.ePed, sSceneData.eScene, fScenePercent, sPedScene, sPassedScene, bMP_to_SP_switch)
AND (bMP_to_SP_switch OR NOT IS_CURRENTLY_ON_MISSION_TO_TYPE(MISSION_TYPE_SWITCH))
IF bMP_to_SP_switch
IF (sSceneData.eScene = PR_SCENE_Fa_PHONECALL_FAM3)
GetFranklinSceneForCurrentTime(sSceneData.eScene, fScenePercent, sPedScene, sPassedScene, bMP_to_SP_switch)
PRINTLN("force PR_SCENE_Fa_PHONECALL_FAM3 to be ", Get_String_From_Ped_Request_Scene_Enum(sSceneData.eScene))
ENDIF
//#1615356
IF (sSceneData.eScene = PR_SCENE_F_CS_CHECKSHOE)
INT iCLOCK_HOURS
iCLOCK_HOURS = GET_CLOCK_HOURS()
IF (iCLOCK_HOURS < 9 OR iCLOCK_HOURS >= 21) /* 09:00 - 20:59 */
PRINTLN("force PR_SCENE_F_CS_CHECKSHOE [", iCLOCK_HOURS, ":00] to be F_KUSH_DOC_b")
sSceneData.eScene = PR_SCENE_F_KUSH_DOC_b
ELSE
PRINTLN("force PR_SCENE_F_CS_CHECKSHOE [", iCLOCK_HOURS, ":00] to be F_KUSH_DOC_a")
sSceneData.eScene = PR_SCENE_F_KUSH_DOC_a
ENDIF
ELIF (sSceneData.eScene = PR_SCENE_F_CS_WIPEHANDS)
CPRINTLN(DEBUG_SWITCH, "force PR_SCENE_F_CS_WIPEHANDS to be F_KUSH_DOC_b")
sSceneData.eScene = PR_SCENE_F_KUSH_DOC_b
ELIF (sSceneData.eScene = PR_SCENE_F_CS_WIPERIGHT)
CPRINTLN(DEBUG_SWITCH, "force PR_SCENE_F_CS_WIPERIGHT to be F_KUSH_DOC_c")
sSceneData.eScene = PR_SCENE_F_KUSH_DOC_c
ENDIF
//#1615723
CLEAR_AREA_OF_VEHICLES(GET_ENTITY_COORDS(PLAYER_PED_ID(), FALSE), 150.0)
ENDIF
CPRINTLN(DEBUG_SWITCH, "<player_controller_b> GET_PLAYER_PED_SCENE_FOR_CURRENT_TIME[\"", Get_String_From_Ped_Request_Scene_Enum(sSceneData.eScene), "\"] fScenePercent:", fScenePercent, "%")
IF (sSceneData.eScene = PR_SCENE_M_DEFAULT)
OR (sSceneData.eScene = PR_SCENE_F_DEFAULT)
OR (sSceneData.eScene = PR_SCENE_T_DEFAULT)
IF IsCharPresentInWorld(sSceneData.ePed)
VECTOR vOldLastKnownCoords
vOldLastKnownCoords = g_savedGlobals.sPlayerData.sInfo.vLastKnownCoords[sSceneData.ePed]
STORE_PLAYER_PED_POSITION(g_sPlayerPedRequest.sSelectorPeds.pedID[sSceneData.ePed])
CPRINTLN(DEBUG_SWITCH, "ped[", GET_PLAYER_PED_STRING(sSceneData.ePed), "] in world - update coords from ", vOldLastKnownCoords.x, ", ", vOldLastKnownCoords.y, ", ", vOldLastKnownCoords.z, " to ", g_savedGlobals.sPlayerData.sInfo.vLastKnownCoords[sSceneData.ePed])
CPRINTLN(DEBUG_SWITCH, "(dist:", VDIST(g_savedGlobals.sPlayerData.sInfo.vLastKnownCoords[sSceneData.ePed], vOldLastKnownCoords), ")")
ENDIF
#IF IS_DEBUG_BUILD
IF IsCharPresentInWorld(sSceneData.ePed)
CPRINTLN(DEBUG_SWITCH, "ped[", GET_PLAYER_PED_STRING(sSceneData.ePed), "] in world, ")
ELSE
CPRINTLN(DEBUG_SWITCH, "ped[", GET_PLAYER_PED_STRING(sSceneData.ePed), "] NOT in world, ")
ENDIF
#ENDIF
IF Is_TIMEOFDAY_Valid(g_savedGlobals.sPlayerData.sInfo.sLastTimeActive[sSceneData.ePed])
INT iSeconds, iMinutes, iHours, iDays, iMonths, iYears
GET_DIFFERENCE_BETWEEN_NOW_AND_TIMEOFDAY(g_savedGlobals.sPlayerData.sInfo.sLastTimeActive[sSceneData.ePed],
iSeconds, iMinutes, iHours, iDays, iMonths, iYears)
IF NOT HasHourPassedSinceCharLastTimeActive(sSceneData.ePed)
CPRINTLN(DEBUG_SWITCH, "hour[", Get_String_From_TIMEOFDAY(g_savedGlobals.sPlayerData.sInfo.sLastTimeActive[sSceneData.ePed]), "] not passed[", iSeconds, "s ", iMinutes, "m ", iHours, "h ", iDays, "d ", iMonths+(iYears*12), "m], ")
IF NOT ARE_VECTORS_ALMOST_EQUAL(g_savedGlobals.sPlayerData.sInfo.vLastKnownCoords[sSceneData.ePed], <<0,0,0>>, 1.5)
CPRINTLN(DEBUG_SWITCH, "vectors[", g_savedGlobals.sPlayerData.sInfo.vLastKnownCoords[sSceneData.ePed], "] not almost zero")
ELSE
CPRINTLN(DEBUG_SWITCH, "vectors[", g_savedGlobals.sPlayerData.sInfo.vLastKnownCoords[sSceneData.ePed], "] almost zero")
ENDIF
ELSE
IF NOT ARE_VECTORS_ALMOST_EQUAL(g_savedGlobals.sPlayerData.sInfo.vLastKnownCoords[sSceneData.ePed], <<0,0,0>>, 1.5)
CPRINTLN(DEBUG_SWITCH, "hour[", Get_String_From_TIMEOFDAY(g_savedGlobals.sPlayerData.sInfo.sLastTimeActive[sSceneData.ePed]), "] passed[", iSeconds, "s ", iMinutes, "m ", iHours, "h ", iDays, "d ", iMonths+(iYears*12), "m], vectors[", g_savedGlobals.sPlayerData.sInfo.vLastKnownCoords[sSceneData.ePed], "] not almost zero")
ELSE
CPRINTLN(DEBUG_SWITCH, "hour[", Get_String_From_TIMEOFDAY(g_savedGlobals.sPlayerData.sInfo.sLastTimeActive[sSceneData.ePed]), "] passed[", iSeconds, "s ", iMinutes, "m ", iHours, "h ", iDays, "d ", iMonths+(iYears*12), "m], vectors[", g_savedGlobals.sPlayerData.sInfo.vLastKnownCoords[sSceneData.ePed], "] almost zero")
ENDIF
ENDIF
ELSE
IF NOT ARE_VECTORS_ALMOST_EQUAL(g_savedGlobals.sPlayerData.sInfo.vLastKnownCoords[sSceneData.ePed], <<0,0,0>>, 1.5)
CPRINTLN(DEBUG_SWITCH, "time[", Get_String_From_TIMEOFDAY(g_savedGlobals.sPlayerData.sInfo.sLastTimeActive[sSceneData.ePed]), "] not valid, vectors[", g_savedGlobals.sPlayerData.sInfo.vLastKnownCoords[sSceneData.ePed], "] not almost zero")
ELSE
CPRINTLN(DEBUG_SWITCH, "time[", Get_String_From_TIMEOFDAY(g_savedGlobals.sPlayerData.sInfo.sLastTimeActive[sSceneData.ePed]), "] not valid, vectors[", g_savedGlobals.sPlayerData.sInfo.vLastKnownCoords[sSceneData.ePed], "] almost zero")
ENDIF
ENDIF
ELSE
IF IsCharPresentInWorld(sSceneData.ePed)
//
ELSE
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_SWITCH, "char \"", GET_PLAYER_PED_STRING(sSceneData.ePed), "\" NOT in world, request model \"", GET_MODEL_NAME_FOR_DEBUG(GET_PLAYER_PED_MODEL(sPedScene.ePed)), "\"")
#ENDIF
REQUEST_PLAYER_PED_MODEL(sPedScene.ePed)
ENDIF
ENDIF
CPRINTLN(DEBUG_SWITCH, "<player_controller_b> g_sPlayerPedRequest.iStage = 1")
g_sPlayerPedRequest.iStage++
ELSE
// Unable to get a suitable scene so bail out
CASSERTLN(DEBUG_SWITCH, "Unable to get a suitable scene so bail out - ",
PICK_STRING(bMP_to_SP_switch, "[bMP_to_SP_switch, ", "[not bMP_to_SP_switch, "),
PICK_STRING(NOT IS_CURRENTLY_ON_MISSION_TO_TYPE(MISSION_TYPE_SWITCH), "not MISSION_TYPE_SWITCH, ", "MISSION_TYPE_SWITCH, "),
GET_PLAYER_PED_STRING(sSceneData.ePed), ", ", Get_String_From_Ped_Request_Scene_Enum(sSceneData.eScene), "]")
DO_SCREEN_FADE_IN(DEFAULT_FADE_TIME)
SET_PLAYER_CONTROL(PLAYER_ID(), TRUE)
RESTORE_PLAYER_PED_VARIATIONS(PLAYER_PED_ID())
if g_bLoadedClifford
// SET_FLOW_OUTFIT_REQUIREMENTSCLF(PLAYER_PED_ID())
else
SET_FLOW_OUTFIT_REQUIREMENTS(PLAYER_PED_ID(), FALSE)
endif
IF NOT IS_TRANSITION_ACTIVE() //Dont turn off my camera - Brenda
IF IS_PLAYER_SWITCH_IN_PROGRESS()
NET_NL()NET_PRINT("MAINTAIN_PLAYER_PED_REQUEST - STOP_PLAYER_SWITCH")
STOP_PLAYER_SWITCH()
ENDIF
ENDIF
g_sPlayerPedRequest.eState = PR_STATE_COMPLETE
ENDIF
#IF IS_DEBUG_BUILD
g_bDebugPrint_SceneScheduleInfo = bDebugPrint_SceneScheduleInfo
#ENDIF
ENDIF
// // // // // // // // // // // // // //
// stage 1: run this switch
//
IF (g_sPlayerPedRequest.iStage = 1)
INT iSwitchFlags
iSwitchFlags = 0
IF bMP_to_SP_switch
iSwitchFlags = ENUM_TO_INT(SWITCH_FLAG_SKIP_INTRO)
CDEBUG2LN(DEBUG_SWITCH, "disable frontend this frame...")
//#1317012
DISABLE_CONTROL_ACTION(FRONTEND_CONTROL, INPUT_FRONTEND_PAUSE)
DISABLE_FRONTEND_THIS_FRAME()
ENDIF
// #1273854 - Add loading spinner when going to SP from MP
IF bDeleteCharStruct
IF IS_TRANSITION_ACTIVE()
sDeleteCharStruct.sMainStringSlot = "HUD_INIT"
RUN_SCALEFORM_LOADING_ICON(sDeleteCharStruct, SHOULD_REFRESH_SCALEFORM_LOADING_ICON(sDeleteCharStruct))
ELSE
bDeleteCharStruct = FALSE
SET_LOADING_ICON_INACTIVE()
ENDIF
ENDIF
IF IS_PLAYER_SWITCH_IN_PROGRESS()
AND GET_PLAYER_SWITCH_TYPE() != SWITCH_TYPE_SHORT
AND GET_PLAYER_SWITCH_JUMP_CUT_INDEX() > 1
AND NOT g_bVehFreezingUnderSwitchControl
IF NOT IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID(), TRUE)
IF IS_ENTITY_ATTACHED(PLAYER_PED_ID())
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_SWITCH, "PLAYER_PED_ID() attached due to jacking vehicle #1827779")
#ENDIF
ELSE
FREEZE_ENTITY_POSITION(PLAYER_PED_ID(), TRUE)
ENDIF
ELSE
VEHICLE_INDEX vehToFreeze
vehToFreeze = GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID(), TRUE)
IF DOES_ENTITY_EXIST(vehToFreeze)
IF NOT IS_PLAYBACK_GOING_ON_FOR_VEHICLE(vehToFreeze)
IF IS_ENTITY_ATTACHED(vehToFreeze)
#IF IS_DEBUG_BUILD
CASSERTLN(DEBUG_SWITCH, "url:bugstar:1809477 - vehToFreeze attached at point two")
#ENDIF
ELSE
FREEZE_ENTITY_POSITION(vehToFreeze, TRUE)
//bug fix:2327388
SET_ENTITY_SHOULD_FREEZE_WAITING_ON_COLLISION(vehToFreeze,true)
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
IF PROCESS_PLAYER_PED_SCENE(sSceneData, iSwitchFlags)
IF bMP_to_SP_switch
bMP_to_SP_switch = FALSE
ResetLastKnownPedInfo(g_savedGlobals.sPlayerData.sInfo, SP_MISSION_NONE)
IF IsPlayerLastVehModelInvalid(CHAR_MICHAEL)
g_sPlayerLastVeh[CHAR_MICHAEL].model = DUMMY_MODEL_FOR_SCRIPT
g_vPlayerVeh[CHAR_MICHAEL] = null
g_ePlayerLastVehState[CHAR_MICHAEL] = PTVS_0_noVehicle
ENDIF
IF IsPlayerLastVehModelInvalid(CHAR_FRANKLIN)
g_sPlayerLastVeh[CHAR_FRANKLIN].model = DUMMY_MODEL_FOR_SCRIPT
g_vPlayerVeh[CHAR_FRANKLIN] = null
g_ePlayerLastVehState[CHAR_FRANKLIN] = PTVS_0_noVehicle
ENDIF
IF IsPlayerLastVehModelInvalid(CHAR_TREVOR)
g_sPlayerLastVeh[CHAR_TREVOR].model = DUMMY_MODEL_FOR_SCRIPT
g_vPlayerVeh[CHAR_TREVOR] = null
g_ePlayerLastVehState[CHAR_TREVOR] = PTVS_0_noVehicle
ENDIF
ENDIF
IF bDeleteCharStruct
bDeleteCharStruct = FALSE
SET_LOADING_ICON_INACTIVE()
DISABLE_CONTROL_ACTION(FRONTEND_CONTROL, INPUT_FRONTEND_PAUSE)
DISABLE_FRONTEND_THIS_FRAME()
SET_PLAYER_CONTROL(PLAYER_ID(), TRUE)
ENDIF
IF bResetMichael1Assets
RUN_RCI_MICHAEL1()
bResetMichael1Assets = FALSE
ENDIF
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_SWITCH, "<player_controller_b> global after sSelectorPeds.pedID [", NATIVE_TO_INT(g_sPlayerPedRequest.sSelectorPeds.pedID[SELECTOR_PED_MICHAEL]), ", ", NATIVE_TO_INT(g_sPlayerPedRequest.sSelectorPeds.pedID[SELECTOR_PED_FRANKLIN]), ", ", NATIVE_TO_INT(g_sPlayerPedRequest.sSelectorPeds.pedID[SELECTOR_PED_TREVOR]), "]")
#ENDIF
SELECTOR_SLOTS_ENUM eCurrentPlayerSelector
eCurrentPlayerSelector = GET_SELECTOR_SLOT_FROM_PLAYER_PED_ENUM(GET_CURRENT_PLAYER_PED_ENUM())
IF sSceneData.sSelectorPeds.eNewSelectorPed != NUMBER_OF_SELECTOR_PEDS
IF eCurrentPlayerSelector != sSceneData.sSelectorPeds.eNewSelectorPed
CPRINTLN(DEBUG_SWITCH, "<player_controller_b> FAILSAFE - force selector to take control post-switch eCurrentPlayerSelector: ", ENUM_TO_INT(eCurrentPlayerSelector), ", sSceneData.sSelectorPeds.eNewSelectorPed: ", ENUM_TO_INT(sSceneData.sSelectorPeds.eNewSelectorPed))
CWARNINGLN(DEBUG_SWITCH, "<player_controller_b> FAILSAFE - Running failsafe character swap.")
WHILE NOT TAKE_CONTROL_OF_SELECTOR_PED(sSceneData.sSelectorPeds)
WAIT(0)
ENDWHILE
CPRINTLN(DEBUG_SWITCH, "<player_controller_b> FAILSAFE - Player character swap completed.")
ENDIF
ENDIF
IF NOT IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID(), TRUE)
//
ELSE
VEHICLE_INDEX vehToFreeze
vehToFreeze = GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID(), TRUE)
IF DOES_ENTITY_EXIST(vehToFreeze)
IF IS_ENTITY_ATTACHED(vehToFreeze)
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_SWITCH, "url:bugstar:1809477 - Can't freeze vehicle, vehToFreeze attached at point three")
#ENDIF
ELSE
FREEZE_ENTITY_POSITION(vehToFreeze, FALSE)
ENDIF
ENDIF
ENDIF
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_SWITCH, "set char \"", GET_PLAYER_PED_STRING(sSceneData.ePed), "\" ped model \"", GET_MODEL_NAME_FOR_DEBUG(GET_PLAYER_PED_MODEL(sPedScene.ePed)), "\" as no longer needed")
#ENDIF
SET_PLAYER_PED_MODEL_AS_NO_LONGER_NEEDED(sPedScene.ePed)
//See bug 4119181 - we can drop in from failed MP transition after playing as animals in DM,
//Need to make sure this is reset
CPRINTLN(DEBUG_SWITCH,"<player_controller_b> Setting PLAYER_IS_IN_ANIMAL_FORM to FALSE as we're switching to ",GET_PLAYER_PED_STRING(sSceneData.ePed))
SET_PLAYER_IS_IN_ANIMAL_FORM(FALSE)
CPRINTLN(DEBUG_SWITCH, "<player_controller_b> g_sPlayerPedRequest.eState = PR_STATE_COMPLETE")
g_sPlayerPedRequest.eState = PR_STATE_COMPLETE
ENDIF
ENDIF
ENDIF
BREAK
// Process complete so finish up
CASE PR_STATE_COMPLETE
CPRINTLN(DEBUG_SWITCH, "<player_controller_b> eStage = PC_STAGE_WAIT")
IF g_eMissionRunningOnMPSwitchStart != SP_MISSION_NONE
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_SWITCH, "<SP-MP-MISSION> Clearing mission running on switch to MP flag. Was set to ", GET_SP_MISSION_DISPLAY_STRING_FROM_ID(g_eMissionRunningOnMPSwitchStart))
#ENDIF
enumCharacterList ePlayer
REPEAT NUM_OF_PLAYABLE_PEDS ePlayer
SP_MISSIONS eResetOutfitMPSwitchReturn
eResetOutfitMPSwitchReturn = SP_MISSION_NONE
IF RESET_PED_VARIATIONS_AFTER_MP_SWITCH_OUT_OF_MISSION(ePlayer, eResetOutfitMPSwitchReturn)
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_SWITCH, "reset ", GET_PLAYER_PED_STRING(ePlayer), " stored outfit - switched out of ", GET_SP_MISSION_DISPLAY_STRING_FROM_ID(eResetOutfitMPSwitchReturn))
#ENDIF
#IF NOT IS_DEBUG_BUILD
eResetOutfitMPSwitchReturn = SP_MISSION_NONE
#ENDIF
SETUP_DEFAULT_PLAYER_VARIATIONS(ePlayer)
ENDIF
ENDREPEAT
ENDIF
g_eMissionRunningOnMPSwitchStart = SP_MISSION_NONE
g_eRCMRunningOnMPSwitchStart = NO_RC_MISSION
IF g_bSPInitialisedThroughSwitch
//#1616806
enumCharacterList ePed
REPEAT NUM_OF_PLAYABLE_PEDS ePed
g_savedGlobals.sPlayerData.sInfo.vLastKnownCoords[ePed] = <<0,0,0>>
ENDREPEAT
g_bSPInitialisedThroughSwitch = FALSE
ENDIF
eStage = PC_STAGE_WAIT
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE: This proc gets called when the Player_Controller_Bscript starts up.
/// One of the main tasks is to set the player as one of the main chracters.
PROC INITIALISE_PLAYER_PED_STATE()
IF (GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(HASH("startup_positioning")) > 0)
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_SWITCH, "Player_controller_b - script \"startup_positioning\" is running.\n")
#ENDIF
EXIT
ENDIF
IF g_bRunMultiplayerOnStartup
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_SWITCH, "Player_controller_b - g_bRunMultiplayerOnStartup is TRUE.\n")
#ENDIF
EXIT
ENDIF
#IF IS_DEBUG_BUILD
SWITCH g_sPlayerPedRequest.eState
CASE PR_STATE_WAITING
CPRINTLN(DEBUG_SWITCH, "Player_controller_b - initial player ped state [ePed: ", GET_PLAYER_PED_STRING(g_sPlayerPedRequest.ePed), ", eState: PR_STATE_WAITING, iStage: ", g_sPlayerPedRequest.iStage, ", in progress: ", GET_STRING_FROM_BOOL(IS_PLAYER_SWITCH_IN_PROGRESS()), "]")
BREAK
CASE PR_STATE_PROCESSING
CPRINTLN(DEBUG_SWITCH, "Player_controller_b - initial player ped state [ePed: ", GET_PLAYER_PED_STRING(g_sPlayerPedRequest.ePed), ", eState: PR_STATE_PROCESSING, iStage: ", g_sPlayerPedRequest.iStage, ", in progress: ", GET_STRING_FROM_BOOL(IS_PLAYER_SWITCH_IN_PROGRESS()), "]")
BREAK
CASE PR_STATE_COMPLETE
CPRINTLN(DEBUG_SWITCH, "Player_controller_b - initial player ped state [ePed: ", GET_PLAYER_PED_STRING(g_sPlayerPedRequest.ePed), ", eState: PR_STATE_COMPLETE, iStage: ", g_sPlayerPedRequest.iStage, ", in progress: ", GET_STRING_FROM_BOOL(IS_PLAYER_SWITCH_IN_PROGRESS()), "]")
BREAK
DEFAULT
CPRINTLN(DEBUG_SWITCH, "Player_controller_b - initial player ped state [ePed: ", GET_PLAYER_PED_STRING(g_sPlayerPedRequest.ePed), ", eState: PR_STATE_", ENUM_TO_INT(g_sPlayerPedRequest.eState), "_unknown???, iStage: ", g_sPlayerPedRequest.iStage, ", in progress: ", GET_STRING_FROM_BOOL(IS_PLAYER_SWITCH_IN_PROGRESS()), "]")
BREAK
ENDSWITCH
#ENDIF
IF g_bHaveBeenInMultiplayer
AND NOT IS_REPEAT_PLAY_ACTIVE()
BOOL bBlockScenesForSPMission = FALSE
enumCharacterList eCharToSwitchTo
//Ensure switch scenes are blocked if we are switching from MP
//directly into an SP game with a DO_MISSION_NOW mission about to start.
IF NOT IS_BIT_SET(g_savedGlobals.sFlow.strandSavedVars[STRAND_PROLOGUE].savedBitflags, SAVED_BITS_STRAND_ACTIVATED)
#IF IS_DEBUG_BUILD
IF NOT GET_COMMANDLINE_PARAM_EXISTS("DisableSPStartFromMP")
#ENDIF
CPRINTLN(DEBUG_SWITCH, "INITIALISE_PLAYER_PED_STATE - Jumping in to an SP game in which the gameflow isn't initialised. Blocking switch scenes.")
bBlockScenesForSPMission = TRUE
eCharToSwitchTo = CHAR_MICHAEL
//Move the player somewhere near the start of the Prologue mission
//to aid streaming.
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
SET_ENTITY_COORDS(PLAYER_PED_ID(), <<5295.4702, -5207.4424, 81.7308>>)
ENDIF
#IF IS_DEBUG_BUILD
ENDIF
#ENDIF
ELSE
//If the SP flow is initialised but Prologue hasn't been completed then we can assume that Prologue
//is about to start, regardless of the strand sitting on the DO_MISSION_NOW command or not.
IF NOT GET_MISSION_COMPLETE_STATE(SP_MISSION_PROLOGUE)
CPRINTLN(DEBUG_SWITCH, "INITIALISE_PLAYER_PED_STATE - Jumping in to an SP game in which Prologue or CLF start isn't completed. Blocking switch scenes.")
bBlockScenesForSPMission = TRUE
eCharToSwitchTo = CHAR_MICHAEL
//Move the player somewhere near the start of the Prologue mission
//to aid streaming.
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
SET_ENTITY_COORDS(PLAYER_PED_ID(), <<5295.4702, -5207.4424, 81.7308>>)
ENDIF
ELSE
INT iStrandIndex
//Check to see if any strands are sitting on DO_MISSION_NOW flow commands that will autostart
REPEAT MAX_STRANDS iStrandIndex
IF NOT bBlockScenesForSPMission
INT iCommandPos = g_savedGlobals.sFlow.strandSavedVars[iStrandIndex].thisCommandPos
IF iCommandPos != ILLEGAL_ARRAY_POSITION
IF g_flowUnsaved.flowCommands[iCommandPos].command = FLOW_DO_MISSION_NOW
CPRINTLN(DEBUG_SWITCH, "INITIALISE_PLAYER_PED_STATE - Jumping in to an SP game with a mission that will autostart. Blocking switch scenes.")
bBlockScenesForSPMission = TRUE
//Figure out a valid character to switch to to start this mission.
SP_MISSIONS eMissionID = INT_TO_ENUM(SP_MISSIONS, g_flowUnsaved.coreVars[g_flowUnsaved.flowCommands[iCommandPos].index].iValue1)
IF IS_BIT_SET(g_sMissionStaticData[eMissionID].triggerCharBitset, ENUM_TO_INT(CHAR_MICHAEL))
CPRINTLN(DEBUG_SWITCH, "INITIALISE_PLAYER_PED_STATE - Switching character to Michael to start DO_MISSION_NOW mission ", GET_SP_MISSION_DISPLAY_STRING_FROM_ID(eMissionID), ".")
eCharToSwitchTo = CHAR_MICHAEL
ELIF IS_BIT_SET(g_sMissionStaticData[eMissionID].triggerCharBitset, ENUM_TO_INT(CHAR_FRANKLIN))
CPRINTLN(DEBUG_SWITCH, "INITIALISE_PLAYER_PED_STATE - Switching character to Franklin to start DO_MISSION_NOW mission ", GET_SP_MISSION_DISPLAY_STRING_FROM_ID(eMissionID), ".")
eCharToSwitchTo = CHAR_FRANKLIN
ELIF IS_BIT_SET(g_sMissionStaticData[eMissionID].triggerCharBitset, ENUM_TO_INT(CHAR_TREVOR))
CPRINTLN(DEBUG_SWITCH, "INITIALISE_PLAYER_PED_STATE - Switching character to Trevor to start DO_MISSION_NOW mission ", GET_SP_MISSION_DISPLAY_STRING_FROM_ID(eMissionID), ".")
eCharToSwitchTo = CHAR_TREVOR
#IF IS_DEBUG_BUILD
ELSE
CASSERTLN(DEBUG_SWITCH, "INITIALISE_PLAYER_PED_STATE: Could not find a valid triggering character for DO_MISSION_NOW mission.")
#ENDIF
ENDIF
//Move the player somewhere near the start of the mission
//to aid streaming.
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
SWITCH eMissionID
CASE SP_MISSION_PROLOGUE
SET_ENTITY_COORDS(PLAYER_PED_ID(), <<5295.4702, -5207.4424, 81.7308>>)
BREAK
CASE SP_MISSION_ARMENIAN_1
SET_ENTITY_COORDS(PLAYER_PED_ID(), <<-1890.6461, -598.3062, 10.8933>>)
BREAK
//Fix for 1625887. Ensure the player is near the timelapse position when jumping directly into
//the Jewel Store Job heist mission from an MP transition.
CASE SP_HEIST_JEWELRY_2
SET_ENTITY_COORDS(PLAYER_PED_ID(), <<702.9835, -984.5344, 23.0969>>)
BREAK
ENDSWITCH
ENDIF
ENDIF
ENDIF
ENDIF
ENDREPEAT
ENDIF
ENDIF
//If a mission is about to automatically start cancel the skycam transition back from MP
//so we can fade out and load straight into the mission intro.
IF bBlockScenesForSPMission
AND NOT IS_REPEAT_PLAY_ACTIVE()
CPRINTLN(DEBUG_SWITCH, "INITIALISE_PLAYER_PED_STATE - Switch scenes blocked as a singleplayer mission is about to automatically start.")
STOP_PLAYER_SWITCH()
CPRINTLN(DEBUG_SWITCH, "INITIALISE_PLAYER_PED_STATE - STOP_PLAYER_SWITCH.")
SET_SKYSWOOP_STAGE(SKYSWOOP_NONE)
TAKE_CONTROL_OF_TRANSITION(FALSE)
SET_SELECTOR_CAM_ACTIVE(FALSE)
SET_MINIMAP_IN_SPECTATOR_MODE(FALSE, NULL)
SET_PLAYER_CONTROL(PLAYER_ID(), FALSE)
SET_LOADING_ICON_INACTIVE()
//Switch to a character the mission can use.
IF GET_CURRENT_PLAYER_PED_ENUM() != eCharToSwitchTo
CPRINTLN(DEBUG_SWITCH, "INITIALISE_PLAYER_PED_STATE - Switching character to ", GET_PLAYER_PED_STRING(eCharToSwitchTo), " ahead of mission starting.")
WHILE NOT SET_CURRENT_SELECTOR_PED(GET_SELECTOR_SLOT_FROM_PLAYER_PED_ENUM(eCharToSwitchTo), TRUE)
WAIT(0)
ENDWHILE
ENDIF
// Delete any previously selected character so they aren't left loose in the world.
INT iSelectorPed
REPEAT NUMBER_OF_SELECTOR_PEDS iSelectorPed
IF GET_PLAYER_PED_ENUM_FROM_SELECTOR_SLOT(INT_TO_ENUM(SELECTOR_SLOTS_ENUM, iSelectorPed)) != eCharToSwitchTo
IF DOES_ENTITY_EXIST(g_sPlayerPedRequest.sSelectorPeds.pedID[iSelectorPed])
CPRINTLN(DEBUG_SWITCH, "INITIALISE_PLAYER_PED_STATE - Deleting global player ped ", GET_PLAYER_PED_STRING(GET_PLAYER_PED_ENUM_FROM_SELECTOR_SLOT(INT_TO_ENUM(SELECTOR_SLOTS_ENUM, iSelectorPed)))," as we transition into a mission as different character.")
SET_ENTITY_AS_MISSION_ENTITY(g_sPlayerPedRequest.sSelectorPeds.pedID[iSelectorPed], FALSE, TRUE)
DELETE_PED(g_sPlayerPedRequest.sSelectorPeds.pedID[iSelectorPed])
ENDIF
ENDIF
ENDREPEAT
// Freeze the player now as they are going to be left wherever the switch leaves them which
// may involve falling through the map.
FREEZE_ENTITY_POSITION(PLAYER_PED_ID(), TRUE)
bBlockScenesForSPMission = FALSE
g_sPlayerPedRequest.iStage = 0
g_sPlayerPedRequest.eState = PR_STATE_WAITING
eStage = PC_STAGE_WAIT
EXIT
#IF IS_DEBUG_BUILD
ELIF IS_REPEAT_PLAY_ACTIVE()
CPRINTLN(DEBUG_SWITCH, "INITIALISE_PLAYER_PED_STATE - Switch scenes blocked but skipped skycam cancel due to repeat play.")
#ENDIF
ENDIF
ENDIF
// If we are in the middle of switching then jump straight to the
// switch stage - this is most likely to happen when returning
// from MP
IF IS_PLAYER_SWITCH_IN_PROGRESS()
CPRINTLN(DEBUG_SWITCH, "Player_Controller_B - returning from MP")
// Fix for bug #170990 - Removing player control so we cannot activate sp script with invalid character
SET_PLAYER_CONTROL(PLAYER_ID(), FALSE)
// Fix for bug #1603098 - Freeze and revive the players when starting player_controller_b
IF NOT IS_ENTITY_DEAD(PLAYER_PED_ID())
IF NOT IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID(), TRUE)
FREEZE_ENTITY_POSITION(PLAYER_PED_ID(), TRUE)
ELSE
VEHICLE_INDEX vehToFreeze
vehToFreeze = GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID(), TRUE)
IF DOES_ENTITY_EXIST(vehToFreeze)
IF NOT IS_PLAYBACK_GOING_ON_FOR_VEHICLE(vehToFreeze)
FREEZE_ENTITY_POSITION(vehToFreeze, TRUE)
ENDIF
ENDIF
ENDIF
IF IS_PED_INJURED(PLAYER_PED_ID())
REVIVE_INJURED_PED(PLAYER_PED_ID())
ENDIF
ELSE
CASSERTLN(DEBUG_SWITCH, "trying to revive a dead player ped")
ENDIF
CPRINTLN(DEBUG_SWITCH, "<Player_Controller_B> Reset last known ped info.")
ResetLastKnownPedInfo(g_savedGlobals.sPlayerData.sInfo, SP_MISSION_NONE)
//#1615331
IF (g_eMissionRunningOnMPSwitchStart = SP_MISSION_MICHAEL_1)
//call this to enable/disable prologue 2D map, from blip_control_public.sch
SET_MINIMAP_IN_PROLOGUE_AND_HANDLE_STATIC_BLIPS(FALSE)
//clear the weather type from snow which was in the prologue area
SET_WEATHER_TYPE_NOW_PERSIST("EXTRASUNNY")
CLEAR_WEATHER_TYPE_PERSIST()
CLEAR_TIMECYCLE_MODIFIER()
DISABLE_MOON_CYCLE_OVERRIDE()
bResetMichael1Assets = TRUE
CPRINTLN(DEBUG_SWITCH, "<Player_Controller_B> cleanup Michael1 with RUN_RCI_MICHAEL1().")
ENDIF
REFRESH_SCALEFORM_LOADING_ICON(sDeleteCharStruct)
bDeleteCharStruct = TRUE
bMP_to_SP_switch = TRUE
BOOL bPlayerSelected = FALSE
INT iPlayerCharIndex
//Do we have any end-of-mission phonecalls queued.
//If so pick the character who can receive this call.
INT index
REPEAT g_savedGlobals.sCommsControlData.iNoQueuedCalls index
IF NOT bPlayerSelected
IF g_savedGlobals.sCommsControlData.sQueuedCalls[index].sCommData.ePriority = CPR_VERY_HIGH
IF IS_BIT_SET(g_savedGlobals.sCommsControlData.sQueuedCalls[index].sCommData.iPlayerCharBitset, ENUM_TO_INT(CHAR_MICHAEL))
CPRINTLN(DEBUG_SWITCH, "<Player_Controller_B> CHAR_MICHAEL for switch due to character having an end of mission call queued.")
g_sPlayerPedRequest.ePed = CHAR_MICHAEL
bPlayerSelected = TRUE
ELIF IS_BIT_SET(g_savedGlobals.sCommsControlData.sQueuedCalls[index].sCommData.iPlayerCharBitset, ENUM_TO_INT(CHAR_FRANKLIN))
CPRINTLN(DEBUG_SWITCH, "<Player_Controller_B> CHAR_FRANKLIN for switch due to character having an end of mission call queued.")
g_sPlayerPedRequest.ePed = CHAR_FRANKLIN
bPlayerSelected = TRUE
ELIF IS_BIT_SET(g_savedGlobals.sCommsControlData.sQueuedCalls[index].sCommData.iPlayerCharBitset, ENUM_TO_INT(CHAR_TREVOR))
CPRINTLN(DEBUG_SWITCH, "<Player_Controller_B> CHAR_TREVOR for switch due to character having an end of mission call queued.")
g_sPlayerPedRequest.ePed = CHAR_TREVOR
bPlayerSelected = TRUE
ENDIF
ENDIF
ENDIF
ENDREPEAT
//Did this switch start from in a SP mission?
IF NOT bPlayerSelected
IF g_eMissionRunningOnMPSwitchStart != SP_MISSION_NONE
//Try and pick a chaacter who can't have been involved in the mission that
//was switched out of.
REPEAT 3 iPlayerCharIndex
IF NOT bPlayerSelected
enumCharacterList ePlayer = INT_TO_ENUM(enumCharacterList, iPlayerCharIndex)
IF IS_PLAYER_PED_AVAILABLE(ePlayer)
IF NOT IS_BIT_SET(g_sMissionStaticData[g_eMissionRunningOnMPSwitchStart].triggerCharBitset, iPlayerCharIndex)
CPRINTLN(DEBUG_SWITCH, "<SP-MP-MISSION> Selected ", GET_PLAYER_PED_STRING(ePlayer), " for switch due to mission can't trigger condition.")
g_sPlayerPedRequest.ePed = ePlayer
bPlayerSelected = TRUE
ENDIF
ENDIF
ENDIF
ENDREPEAT
ENDIF
ENDIF
enumCharacterList eLastPlayer = GET_LAST_KNOWN_PLAYER_PED_ENUM()
IF (g_iGametimeMPSPTransition = -1)
CPRINTLN(DEBUG_SWITCH, "<SP-MP-MISSION> MP-SP Transition time is null.")
ELSE
IF (GET_GAME_TIMER() > (g_iGametimeMPSPTransition+120000))
CPRINTLN(DEBUG_SWITCH, "<SP-MP-MISSION> MP-SP transition time elapsed ", TO_FLOAT(GET_GAME_TIMER()-g_iGametimeMPSPTransition)/1000.0, "ms - outside of window, don't look for alternative.")
ELSE
CPRINTLN(DEBUG_SWITCH, "<SP-MP-MISSION> MP-SP Transition time elapsed ", TO_FLOAT(GET_GAME_TIMER()-g_iGametimeMPSPTransition)/1000.0, "ms - within window, seek an alternative to last known character.")
IF NOT bPlayerSelected
//Try and pick a character who we weren't just playing as so it doesn't
//appear that they have suddenly warped to a switch scene.
REPEAT 3 iPlayerCharIndex
IF NOT bPlayerSelected
enumCharacterList ePlayer = INT_TO_ENUM(enumCharacterList, iPlayerCharIndex)
IF IS_PLAYER_PED_AVAILABLE(ePlayer)
IF ePlayer != eLastPlayer
CPRINTLN(DEBUG_SWITCH, "<SP-MP-MISSION> Selected ", GET_PLAYER_PED_STRING(ePlayer), " for not being recent last player ped.")
g_sPlayerPedRequest.ePed = ePlayer
bPlayerSelected = TRUE
ENDIF
ENDIF
ENDIF
ENDREPEAT
ENDIF
ENDIF
ENDIF
IF NOT bPlayerSelected
IF NOT IS_PLAYER_PED_PLAYABLE(g_sPlayerPedRequest.ePed)
OR NOT IS_PLAYER_PED_AVAILABLE(g_sPlayerPedRequest.ePed)
//Only player available is the last known player. Just use them.
CPRINTLN(DEBUG_SWITCH, "<SP-MP-MISSION> Failed to find a good character to use. Defaulting to the last player: ", GET_PLAYER_PED_STRING(g_sPlayerPedRequest.ePed), ", ", GET_PLAYER_PED_STRING(eLastPlayer), ".")
g_sPlayerPedRequest.ePed = eLastPlayer
bPlayerSelected = TRUE
ENDIF
ENDIF
//IF NOT bPlayerSelected
//No swaps needed. Just run with the requested ped.
//ENDIF
IF (g_sPlayerPedRequest.eState <> PR_STATE_PROCESSING)
g_sPlayerPedRequest.iStage = 0
g_sPlayerPedRequest.eState = PR_STATE_PROCESSING
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_SWITCH, "INITIALISE_PLAYER_PED_STATE - Forcing character switch to (", GET_PLAYER_PED_STRING(g_sPlayerPedRequest.ePed), ")")
#ENDIF
ENDIF
//#1356702
DISABLE_CONTROL_ACTION(FRONTEND_CONTROL, INPUT_FRONTEND_PAUSE)
DISABLE_FRONTEND_THIS_FRAME()
//Fix for bug #1333467
SET_PLAYER_WANTED_LEVEL_NO_DROP(PLAYER_ID(), 0)
g_bSPInitialisedThroughSwitch = TRUE
CPRINTLN(DEBUG_SWITCH, "INITIALISE_PLAYER_PED_STATE - eStage = PC_STAGE_SWITCH //IS_PLAYER_SWITCH_IN_PROGRESS()")
eStage = PC_STAGE_SWITCH
ENDIF
IF NOT IS_PLAYER_PED_SWITCH_IN_PROGRESS()
// Jump to the wait stage so we can process any requests
IF (g_sPlayerPedRequest.eState = PR_STATE_COMPLETE)
CPRINTLN(DEBUG_SWITCH, "INITIALISE_PLAYER_PED_STATE - g_sPlayerPedRequest.eState = PR_STATE_COMPLETE")
g_sPlayerPedRequest.iStage = 0
g_sPlayerPedRequest.eState = PR_STATE_WAITING
ENDIF
IF (g_sPlayerPedRequest.eState <> PR_STATE_WAITING)
CPRINTLN(DEBUG_SWITCH, "INITIALISE_PLAYER_PED_STATE - g_sPlayerPedRequest.eState <> PR_STATE_WAITING")
CASSERTLN(DEBUG_SWITCH, "INITIALISE_PLAYER_PED_STATE - eState <> PR_STATE_WAITING")
g_sPlayerPedRequest.iStage = 0
g_sPlayerPedRequest.eState = PR_STATE_WAITING
ENDIF
CPRINTLN(DEBUG_SWITCH, "INITIALISE_PLAYER_PED_STATE - eStage = PC_STAGE_WAIT //NOT IS_PLAYER_PED_SWITCH_IN_PROGRESS()")
eStage = PC_STAGE_WAIT
ENDIF
IF (g_sPlayerPedRequest.iStage <> 0)
CPRINTLN(DEBUG_SWITCH, "INITIALISE_PLAYER_PED_STATE - g_sPlayerPedRequest.iStage = ", g_sPlayerPedRequest.iStage, " <> 0")
// CASSERTLN(DEBUG_SWITCH, "INITIALISE_PLAYER_PED_STATE - iStage <> 0")
g_sPlayerPedRequest.iStage = 0
ENDIF
IF (eStage = PC_STAGE_INIT)
CPRINTLN(DEBUG_SWITCH, "INITIALISE_PLAYER_PED_STATE - eStage = PC_STAGE_INIT //missed out of... something")
// Jump to the wait stage so we can process any requests
IF (g_sPlayerPedRequest.eState = PR_STATE_COMPLETE)
CPRINTLN(DEBUG_SWITCH, "INITIALISE_PLAYER_PED_STATE - g_sPlayerPedRequest.eState = PR_STATE_COMPLETE")
g_sPlayerPedRequest.iStage = 0
g_sPlayerPedRequest.eState = PR_STATE_WAITING
ENDIF
// Jump to the wait stage so we can process any requests
IF (g_sPlayerPedRequest.eState = PR_STATE_PROCESSING)
CPRINTLN(DEBUG_SWITCH, "INITIALISE_PLAYER_PED_STATE - g_sPlayerPedRequest.eState = PR_STATE_PROCESSING")
CPRINTLN(DEBUG_SWITCH, "INITIALISE_PLAYER_PED_STATE - Assuming dropping out of multiplayer without a skycam transition.")
INT iTimeout
IF (GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(HASH("maintransition")) > 0)
CPRINTLN(DEBUG_SWITCH, "INITIALISE_PLAYER_PED_STATE - Wait for \"maintransition\" to cleanup.")
iTimeout = GET_GAME_TIMER() + 10000
WHILE (GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(HASH("maintransition")) > 0)
AND GET_GAME_TIMER() < iTimeout
WAIT(0)
ENDWHILE
CPRINTLN(DEBUG_SWITCH, "INITIALISE_PLAYER_PED_STATE - Finised waiting ", GET_GAME_TIMER() - iTimeout, " ms for \"maintransition\" to cleanup.")
ENDIF
SET_MINIMAP_IN_SPECTATOR_MODE(FALSE, NULL)
SET_PLAYER_CONTROL(PLAYER_ID(), FALSE)
enumCharacterList ePlayer = GET_CURRENT_PLAYER_PED_ENUM()
CPRINTLN(DEBUG_SWITCH, "INITIALISE_PLAYER_PED_STATE - Starting to attempt to reposition player at nearest valid savehouse. Player char: ", GET_PLAYER_PED_STRING(ePlayer))
BOOL bPlayerRepositioned = FALSE
iTimeout = GET_GAME_TIMER() + 10000
WHILE NOT bPlayerRepositioned AND GET_GAME_TIMER() < iTimeout
IF NOT IS_ENTITY_DEAD(PLAYER_PED_ID())
IF IS_PLAYER_PED_PLAYABLE(ePlayer)
VECTOR vWarpPos = << -1234.70, -1135.56, 6.81 >>
FLOAT fWarpHeading = 135.0000
SAVEHOUSE_NAME_ENUM eSavehouse = GET_CLOSEST_SAVEHOUSE(GET_ENTITY_COORDS(PLAYER_PED_ID()), ePlayer, TRUE)
IF eSavehouse != NUMBER_OF_SAVEHOUSE_LOCATIONS
vWarpPos = g_sSavehouses[eSavehouse].vSpawnCoords
fWarpHeading = g_sSavehouses[eSavehouse].fSpawnHeading
ENDIF
DO_PLAYER_MAP_WARP_WITH_LOAD(vWarpPos, fWarpHeading, FALSE)
SET_GAMEPLAY_CAM_RELATIVE_HEADING()
SET_GAMEPLAY_CAM_RELATIVE_PITCH()
FREEZE_ENTITY_POSITION(PLAYER_PED_ID(), FALSE)
CLEAR_PED_TASKS(PLAYER_PED_ID())
SET_PLAYER_CONTROL(PLAYER_ID(), TRUE)
CPRINTLN(DEBUG_SWITCH, "INITIALISE_PLAYER_PED_STATE - repositioned Player char: ", GET_PLAYER_PED_STRING(ePlayer), " to safehouse ", Get_Savehouse_Respawn_Name(eSavehouse))
bPlayerRepositioned = TRUE
ELSE
CPRINTLN(DEBUG_SWITCH, "INITIALISE_PLAYER_PED_STATE - Waiting for player ped to be a SP char before repositioning.")
ePlayer = GET_CURRENT_PLAYER_PED_ENUM()
ENDIF
ELSE
CPRINTLN(DEBUG_SWITCH, "INITIALISE_PLAYER_PED_STATE - Waiting for player ped to not be dead before repositioning.")
ENDIF
WAIT(0)
IF NOT bPlayerRepositioned
ePlayer = GET_CURRENT_PLAYER_PED_ENUM()
ENDIF
ENDWHILE
IF NOT bPlayerRepositioned
AND NOT IS_ENTITY_DEAD(PLAYER_PED_ID())
SET_GAMEPLAY_CAM_RELATIVE_HEADING()
SET_GAMEPLAY_CAM_RELATIVE_PITCH()
FREEZE_ENTITY_POSITION(PLAYER_PED_ID(), FALSE)
CLEAR_PED_TASKS(PLAYER_PED_ID())
SET_PLAYER_CONTROL(PLAYER_ID(), TRUE)
CPRINTLN(DEBUG_SWITCH, "INITIALISE_PLAYER_PED_STATE - fallback reset Player char: ", GET_PLAYER_PED_STRING(ePlayer))
ENDIF
CPRINTLN(DEBUG_SWITCH, "INITIALISE_PLAYER_PED_STATE - Player positioning done in ", GET_GAME_TIMER() - iTimeout, " ms. Cleaning up transition and fading.")
SET_SKYSWOOP_STAGE(SKYSWOOP_NONE)
TAKE_CONTROL_OF_TRANSITION(FALSE)
SET_SELECTOR_CAM_ACTIVE(FALSE)
SET_LOADING_ICON_INACTIVE()
DO_SCREEN_FADE_IN(DEFAULT_FADE_TIME_LONG)
g_sPlayerPedRequest.iStage = 0
g_sPlayerPedRequest.eState = PR_STATE_WAITING
eStage = PC_STAGE_WAIT
ENDIF
IF (g_sPlayerPedRequest.eState <> PR_STATE_WAITING)
CPRINTLN(DEBUG_SWITCH, "INITIALISE_PLAYER_PED_STATE - g_sPlayerPedRequest.eState <> PR_STATE_WAITING")
// CASSERTLN(DEBUG_SWITCH, "INITIALISE_PLAYER_PED_STATE - eState <> PR_STATE_WAITING")
g_sPlayerPedRequest.iStage = 0
g_sPlayerPedRequest.eState = PR_STATE_WAITING
ENDIF
CPRINTLN(DEBUG_SWITCH, "INITIALISE_PLAYER_PED_STATE - eStage = PC_STAGE_WAIT //eStage = PC_STAGE_INIT")
eStage = PC_STAGE_WAIT
ENDIF
ENDPROC
SCRIPT
CPRINTLN(DEBUG_SWITCH, "Starting Player_Controller_B\n")
// This script needs to cleanup only when the game moves from SP to MP
IF (HAS_FORCE_CLEANUP_OCCURRED(FORCE_CLEANUP_FLAG_SP_TO_MP))
CPRINTLN(DEBUG_SWITCH, "...player_controller_b.sc has been forced to cleanup (SP to MP)")
Player_Controller_B_Cleanup()
ENDIF
// Setup some debug widgets
#IF IS_DEBUG_BUILD
SETUP_PLAYER_CONTROL_DEBUG_WIDGETS()
#ENDIF
g_bSPInitialisedThroughSwitch = FALSE
WHILE (TRUE)
IF NOT CAN_MISSION_TYPE_START_AGAINST_CURRENT_TYPE(MISSION_TYPE_STORY)
IF NOT (Is_Player_Timetable_Scene_In_Progress() OR IS_PLAYER_SWITCH_IN_PROGRESS() OR IS_PLAYER_PED_SWITCH_IN_PROGRESS())
CPRINTLN(DEBUG_SWITCH, "player_controller_b cleaning up as game is now on mission.")
IF (g_sPlayerPedRequest.eState = PR_STATE_PROCESSING)
CPRINTLN(DEBUG_SWITCH, "on mission: g_sPlayerPedRequest.eState = PR_STATE_PROCESSING")
// CASSERTLN(DEBUG_SWITCH, "on mission: eState = PR_STATE_PROCESSING")
ENDIF
IF g_sPlayerPedRequest.iStage <> 0
CPRINTLN(DEBUG_SWITCH, "on mission: g_sPlayerPedRequest.iStage <> 0")
// CASSERTLN(DEBUG_SWITCH, "on mission: iStage <> 0")
ENDIF
Player_Controller_B_Cleanup()
ENDIF
ENDIF
#IF IS_DEBUG_BUILD
MAINTAIN_PLAYER_CONTROL_DEBUG_WIDGETS()
#ENDIF
// Set any defaults and make sure we are a valid character
IF (eStage = PC_STAGE_INIT)
INITIALISE_PLAYER_PED_STATE()
ENDIF
// The main control logic takes place here
IF (eStage = PC_STAGE_WAIT)
CHECK_PLAYER_PED_REQUEST()
ENDIF
// Switching to another ped
IF (eStage = PC_STAGE_SWITCH)
MAINTAIN_PLAYER_PED_REQUEST()
ENDIF
IF (eStage = PC_STAGE_END)
// Perform any cleanup routines here
// - Save player data
ENDIF
WAIT(0)
ENDWHILE
ENDSCRIPT