1100 lines
39 KiB
Python
Executable File
1100 lines
39 KiB
Python
Executable File
//╒═════════════════════════════════════════════════════════════════════════════╕
|
|
//│ Mission Repeat Controller │
|
|
//╞═════════════════════════════════════════════════════════════════════════════╡
|
|
//│ │
|
|
//│ AUTHOR: Ben Rollinson / Andrew Minghella │
|
|
//│ DATE: 13/09/11 │
|
|
//│ DESCRIPTION: A system used to trigger mission scripts │
|
|
//│ that the player has chosen to replay after │
|
|
//│ having already completed them. │
|
|
//│ │
|
|
//╘═════════════════════════════════════════════════════════════════════════════╛
|
|
|
|
USING "rage_builtins.sch"
|
|
USING "globals.sch"
|
|
USING "snapshot_private.sch"
|
|
USING "flow_processing_game.sch"
|
|
USING "mission_repeat_private.sch"
|
|
USING "savegame_private.sch"
|
|
USING "RC_launcher_public.sch"
|
|
USING "flow_processing_missions_game.sch"
|
|
|
|
USING "script_heist.sch"
|
|
USING "mission_repeat_public.sch"
|
|
|
|
ENUM RP_STATE
|
|
RP_SETUP,
|
|
RP_HEIST_PLANNING_BOARD,
|
|
RP_LAUNCH,
|
|
RP_RUNNING,
|
|
RP_PASSED,
|
|
RP_FAILED
|
|
ENDENUM
|
|
|
|
// repeat play variables
|
|
RP_STATE eRPState
|
|
RP_HEIST_STATE eRPHeistState
|
|
|
|
TEXT_LABEL_31 tScriptName
|
|
INT iTriggerCharBitset
|
|
INT iCandidateID = NO_CANDIDATE_ID
|
|
INT iHeistCrewUnlockBackup // Used for remembering which crew memebers had been unlocked before resetting the flow state.
|
|
|
|
// --------------------------functions ----------------------------------------------------------
|
|
/// PURPOSE:
|
|
/// Moves the player into position and loads the world in
|
|
/// PARAMS:
|
|
/// vPos - where we are moving the player
|
|
/// fHeading - heading the player should use
|
|
/// bRepopulate - do we want to repropulate the world here?
|
|
/// RETURNS:
|
|
/// TRUE if everything loaded ok
|
|
FUNC BOOL RepeatPlay_Warp_Player(VECTOR vPos, FLOAT fHeading, BOOL bRepopulate)
|
|
|
|
IF IS_PLAYER_PLAYING(PLAYER_ID())
|
|
// start the teleport
|
|
CPRINTLN(DEBUG_REPEAT, "RepeatPlay_Warp_Player started")
|
|
SET_GAME_PAUSED(FALSE)
|
|
|
|
// turn off emergency streaming (pausing game will ensure player doesnt fall through floor)
|
|
//SET_GAME_PAUSES_FOR_STREAMING(FALSE)
|
|
|
|
// move player now
|
|
CLEAR_AREA(vPos, 5.0, TRUE)
|
|
IF DOES_ENTITY_EXIST(PLAYER_PED_ID())
|
|
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
|
|
SET_ENTITY_COORDS(PLAYER_PED_ID(), vPos)
|
|
SET_ENTITY_HEADING(PLAYER_PED_ID(), fHeading)
|
|
SET_GAMEPLAY_CAM_RELATIVE_PITCH(0.0)
|
|
SET_GAMEPLAY_CAM_RELATIVE_HEADING(0.0)
|
|
ENDIF
|
|
ENDIF
|
|
NEW_LOAD_SCENE_START_SPHERE(vPos, 600)
|
|
WAIT(0) // wait a frame for the camera to catch up before pausing
|
|
|
|
// clear wanted level again (in case repeat play triggered in restricted area)
|
|
IF IS_PLAYER_PLAYING(PLAYER_ID())
|
|
CPRINTLN(DEBUG_REPEAT,"Repeat play clearing wanted level now (after warp).")
|
|
CLEAR_PLAYER_WANTED_LEVEL(PLAYER_ID())
|
|
ENDIF
|
|
|
|
// clear the area
|
|
CLEAR_AREA(vPos, 5000, TRUE, FALSE)
|
|
DELETE_VEHICLE_GEN_VEHICLES_IN_AREA(vPos, 5000)
|
|
CLEAR_AREA_OF_OBJECTS(vPos, 5000)
|
|
REMOVE_PARTICLE_FX_IN_RANGE(vPos, 5000)
|
|
REMOVE_DECALS_IN_RANGE(vPos, 5000)
|
|
CLEAR_ALL_MUST_LEAVE_AREA_VEHICLE_GEN_FLAGS()
|
|
RESET_VEHICLE_GEN_LOADED_CHECKS()
|
|
|
|
// start timer + pause game
|
|
SETTIMERA(0)
|
|
SET_GAME_PAUSED(TRUE)
|
|
|
|
// try to create the new load scene
|
|
IF NOT IS_NEW_LOAD_SCENE_ACTIVE()
|
|
WHILE NOT NEW_LOAD_SCENE_START_SPHERE(vPos, REPLAY_LOAD_SCENE_SIZE)
|
|
WAIT(0)
|
|
IF TIMERA() > 2000
|
|
CPRINTLN(DEBUG_REPEAT, "RepeatPlay_Warp_Player failed to create load scene- exit.")
|
|
//SET_GAME_PAUSES_FOR_STREAMING(TRUE) // allow emergency streaming again
|
|
SET_GAME_PAUSED(FALSE)
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDWHILE
|
|
ENDIF
|
|
|
|
// wait for scene to load
|
|
CPRINTLN(DEBUG_REPEAT, "REPLAY_WARP_PLAYER new load scene succesfully started.")
|
|
SETTIMERA(0)
|
|
WHILE NOT IS_NEW_LOAD_SCENE_LOADED()
|
|
WAIT(0)
|
|
CPRINTLN(DEBUG_REPEAT, "RepeatPlay_Warp_Player new load scene still loading: ", TIMERA())
|
|
// check for early out
|
|
IF TIMERA() > REPLAY_LOAD_SCENE_TIMEOUT
|
|
CPRINTLN(DEBUG_REPEAT, "RepeatPlay_Warp_Player took too long: early out")
|
|
SET_GAME_PAUSED(FALSE)
|
|
// get rid of the stream vol
|
|
IF IS_NEW_LOAD_SCENE_ACTIVE()
|
|
NEW_LOAD_SCENE_STOP()
|
|
ENDIF
|
|
//SET_GAME_PAUSES_FOR_STREAMING(TRUE) // allow emergency streaming again
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
// check for debug skip
|
|
#IF IS_DEBUG_BUILD
|
|
IF (IS_KEYBOARD_KEY_JUST_PRESSED(KEY_V))
|
|
CPRINTLN(DEBUG_REPLAY, "RepeatPlay_Warp_Player debug skipping streaming.")
|
|
SET_GAME_PAUSED(FALSE)
|
|
// get rid of the stream vol
|
|
IF IS_NEW_LOAD_SCENE_ACTIVE()
|
|
NEW_LOAD_SCENE_STOP()
|
|
ENDIF
|
|
//SET_GAME_PAUSES_FOR_STREAMING(TRUE) // allow emergency streaming again
|
|
RETURN FALSE
|
|
ENDIF
|
|
#ENDIF
|
|
ENDWHILE
|
|
CPRINTLN(DEBUG_REPEAT, "RepeatPlay_Warp_Player warp finished")
|
|
|
|
// post warp cleanup- then start repopulation
|
|
// clear and repopulate the area
|
|
IF DOES_ENTITY_EXIST(PLAYER_PED_ID())
|
|
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
|
|
|
|
// get rid of the stream vol
|
|
IF IS_NEW_LOAD_SCENE_ACTIVE()
|
|
NEW_LOAD_SCENE_STOP()
|
|
ENDIF
|
|
|
|
//SET_GAME_PAUSES_FOR_STREAMING(TRUE) // allow emergency streaming again
|
|
|
|
// need to unpause for repopulate stuff to work
|
|
SET_GAME_PAUSED(FALSE)
|
|
SETTIMERA(0)
|
|
|
|
// refill population
|
|
INSTANTLY_FILL_PED_POPULATION()
|
|
IF bRepopulate = TRUE
|
|
INSTANTLY_FILL_VEHICLE_POPULATION()
|
|
ELSE
|
|
// if not doing vehicle repop, set the early out
|
|
SETTIMERA(REPOP_EARLY_OUT - REPOP_MIN_WAIT)
|
|
ENDIF
|
|
POPULATE_NOW()
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// wait for repopulation to finish
|
|
WHILE (NOT HAS_INSTANT_FILL_VEHICLE_POPULATION_FINISHED()
|
|
OR NOT HAVE_ALL_VEHICLE_GENS_LOADED_NEAR_PLAYER()
|
|
OR TIMERA() < REPOP_MIN_WAIT)
|
|
AND TIMERA() < REPOP_EARLY_OUT
|
|
WAIT(0)
|
|
CPRINTLN(DEBUG_REPEAT, "RepeatPlay_Warp_Player waiting for vehicle repopulation.")
|
|
ENDWHILE
|
|
|
|
IF TIMERA() > REPOP_EARLY_OUT
|
|
IF bRepopulate = TRUE
|
|
CPRINTLN(DEBUG_REPEAT, "RepeatPlay_Warp_Player repopulation took too long, early out.")
|
|
ELSE
|
|
CPRINTLN(DEBUG_REPEAT, "RepeatPlay_Warp_Player skipping vehicle repopulation.")
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// reset camera behind player
|
|
SET_GAMEPLAY_CAM_RELATIVE_PITCH(0.0)
|
|
SET_GAMEPLAY_CAM_RELATIVE_HEADING(0.0)
|
|
|
|
// finished
|
|
CPRINTLN(DEBUG_REPLAY, "RepeatPlay_Warp_Player: repopulation finished")
|
|
SET_GAME_PAUSED(FALSE)
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
CPRINTLN(DEBUG_REPLAY, "RepeatPlay_Warp_Player: player not playing")
|
|
SET_GAME_PAUSED(FALSE)
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// (Un)Freezes the player
|
|
/// PARAMS:
|
|
/// bFreeze- are we freezing or unfreezing?
|
|
PROC RepeatPlay_Freeze_Player(BOOL bFreeze)
|
|
|
|
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
|
|
|
|
IF bFreeze = TRUE
|
|
// freeze
|
|
SET_BIT(g_iRepeatPlayBits, ENUM_TO_INT(RPB_FROZEN_PLAYER))
|
|
CPRINTLN(DEBUG_REPEAT, "Repeat Play is freezing the player.")
|
|
// disable player control
|
|
IF IS_PLAYER_PLAYING(PLAYER_ID())
|
|
SET_PLAYER_CONTROL(PLAYER_ID(), FALSE)
|
|
ENDIF
|
|
CLEAR_PED_TASKS(PLAYER_PED_ID())
|
|
IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
|
|
FREEZE_ENTITY_POSITION(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()), TRUE)
|
|
ELSE
|
|
IF NOT IS_PED_GETTING_INTO_A_VEHICLE(PLAYER_PED_ID())
|
|
IF IS_ENTITY_ATTACHED(PLAYER_PED_ID())
|
|
CPRINTLN(DEBUG_REPEAT, "Repeat Play is detaching entity.")
|
|
DETACH_ENTITY(PLAYER_PED_ID())
|
|
ENDIF
|
|
ENDIF
|
|
IF NOT IS_ENTITY_ATTACHED(PLAYER_PED_ID())
|
|
FREEZE_ENTITY_POSITION(PLAYER_PED_ID(), TRUE)
|
|
ENDIF
|
|
ENDIF
|
|
SET_ENTITY_INVINCIBLE(PLAYER_PED_ID(), TRUE)
|
|
SET_ENTITY_PROOFS(PLAYER_PED_ID(), TRUE, TRUE, TRUE, TRUE, TRUE)
|
|
ELSE
|
|
// unfreeze
|
|
IF IS_BIT_SET(g_iRepeatPlayBits, ENUM_TO_INT(RPB_FROZEN_PLAYER))
|
|
CPRINTLN(DEBUG_REPEAT, "Repeat Play is unfreezing the player.")
|
|
// disable player control
|
|
IF IS_PLAYER_PLAYING(PLAYER_ID())
|
|
SET_PLAYER_CONTROL(PLAYER_ID(), TRUE)
|
|
ENDIF
|
|
IF IS_ENTITY_ATTACHED(PLAYER_PED_ID()) // unfreeze player
|
|
FREEZE_ENTITY_POSITION(GET_ENTITY_ATTACHED_TO(PLAYER_PED_ID()), FALSE)
|
|
ELSE
|
|
FREEZE_ENTITY_POSITION(PLAYER_PED_ID(), FALSE)
|
|
ENDIF
|
|
IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
|
|
FREEZE_ENTITY_POSITION(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()), FALSE)
|
|
ENDIF
|
|
SET_ENTITY_INVINCIBLE(PLAYER_PED_ID(), FALSE)
|
|
SET_ENTITY_PROOFS(PLAYER_PED_ID(), FALSE, FALSE, FALSE, FALSE, FALSE)
|
|
CLEAR_BIT(g_iRepeatPlayBits, ENUM_TO_INT(RPB_FROZEN_PLAYER))
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Reactivates game flow and comm queues
|
|
PROC Exit_Repeat_Play(BOOL bFadeIn)
|
|
g_savedGlobals.sFlow.isGameflowActive = TRUE
|
|
g_bPauseCommsQueues = FALSE
|
|
CPRINTLN(DEBUG_REPEAT, "Unpaused Flow + communication queue.")
|
|
SET_GAME_PAUSED(FALSE)
|
|
|
|
IF bFadeIn = TRUE
|
|
DO_SCREEN_FADE_IN(DEFAULT_FADE_TIME)
|
|
ENDIF
|
|
|
|
// stop the player being invinvible
|
|
// this was set on by the repeat play menu
|
|
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
|
|
SET_ENTITY_INVINCIBLE(PLAYER_PED_ID(), FALSE)
|
|
ENDIF
|
|
|
|
// reset the bitset - we don't clear the bits after as they are used for putting the player back after things like the rollercoaster
|
|
CLEAR_BIT(g_iRepeatPlayBits, ENUM_TO_INT(RPB_ACTIVE))
|
|
CLEAR_BIT(g_iRepeatPlayBits, ENUM_TO_INT(RPB_PASSED))
|
|
CLEAR_BIT(g_iRepeatPlayBits, ENUM_TO_INT(RPB_FROZEN_PLAYER))
|
|
CLEAR_BIT(g_iRepeatPlayBits, ENUM_TO_INT(RPB_PAUSED_GAME))
|
|
|
|
SET_PLAYER_IS_REPEATING_A_MISSION(FALSE)
|
|
|
|
TERMINATE_THIS_THREAD()
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// This is called after repeat play is passed, or repeat play replay is rejected (or if player quits via pause menu)
|
|
/// Calls mission termination commands, loads the autosave and calls exit repeat play
|
|
PROC Repeat_Play_Completed()
|
|
|
|
CPRINTLN(DEBUG_REPEAT,"Mission repeat ended for mission script ", tScriptName)
|
|
|
|
// End of mission cleanup
|
|
IF g_RepeatPlayData.eMissionType = CP_GROUP_MISSIONS
|
|
MISSION_PROCESSING_MISSION_OVER(INT_TO_ENUM(SP_MISSIONS, g_RepeatPlayData.iMissionIndex))
|
|
//Inform the mission candidate system that the mission is over
|
|
Mission_Over(iCandidateID)
|
|
ELSE
|
|
// nothing needs to be done here as the RCs run as normal via world points and launchers
|
|
ENDIF
|
|
|
|
// Load the auto-save here
|
|
QUEUE_MISSION_REPEAT_LOAD()
|
|
Exit_Repeat_Play(FALSE)
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Returns the position we want to warp the player to for this story mission.
|
|
/// Uses static blip position for normal missions.
|
|
/// Uses custom vectors for moving prep missions.
|
|
/// RETURNS:
|
|
/// VECTOR position to warp the player to
|
|
FUNC VECTOR GET_STORY_MISSION_WARP_POS()
|
|
|
|
VECTOR vPos = <<0.0,0.0,0.0>>
|
|
|
|
SP_MISSIONS eMissionID = INT_TO_ENUM(SP_MISSIONS, g_RepeatPlayData.iMissionIndex)
|
|
|
|
SWITCH eMissionID
|
|
|
|
// moving prep missions
|
|
CASE SP_HEIST_AGENCY_PREP_1
|
|
vPos = <<354.3055, -1722.2062, 28.2590>>
|
|
BREAK
|
|
|
|
CASE SP_MISSION_FBI_4_PREP_1
|
|
vPos = <<1062.2830, -357.3208, 66.1474>>
|
|
BREAK
|
|
|
|
CASE SP_HEIST_JEWELRY_PREP_1B
|
|
g_iForcePrepMissionRoute = GET_RANDOM_INT_IN_RANGE(1,4)
|
|
SWITCH g_iForcePrepMissionRoute
|
|
CASE 1
|
|
vPos = <<-745.47900, -1118.11047, 9.67980>>
|
|
BREAK
|
|
CASE 2
|
|
vPos = <<895.8368, -788.0649, 41.9022>>
|
|
BREAK
|
|
CASE 3
|
|
vPos = <<-964.6421, -336.7097, 36.8155>>
|
|
BREAK
|
|
ENDSWITCH
|
|
BREAK
|
|
|
|
CASE SP_HEIST_JEWELRY_PREP_2A
|
|
g_iForcePrepMissionRoute = 1
|
|
vPos = <<1261.4415, 589.6306, 80.5991>>
|
|
BREAK
|
|
|
|
CASE SP_HEIST_RURAL_PREP_1
|
|
vPos = <<45.7300, 3064.2739, 39.9430>>
|
|
BREAK
|
|
|
|
CASE SP_HEIST_DOCKS_PREP_1
|
|
vPos = <<1219.1857, -2977.8999, 4.8653>>
|
|
BREAK
|
|
|
|
// other special cases
|
|
CASE SP_MISSION_CHINESE_1
|
|
vPos = <<1991.0757, 3054.2473, 46.2147>>
|
|
BREAK
|
|
|
|
// normal missions
|
|
DEFAULT
|
|
IF g_sMissionStaticData[g_RepeatPlayData.iMissionIndex].blip != STATIC_BLIP_NAME_DUMMY_FINAL
|
|
vPos = GET_STATIC_BLIP_POSITION(g_sMissionStaticData[g_RepeatPlayData.iMissionIndex].blip)
|
|
ENDIF
|
|
BREAK
|
|
ENDSWITCH
|
|
|
|
RETURN vPos
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Sets up the flow ready for the chosen repeat play mission
|
|
PROC Setup_Repeat_Play()
|
|
|
|
CPRINTLN(DEBUG_REPEAT,"Setup_Repeat_Play called")
|
|
|
|
// pause game
|
|
CPRINTLN(DEBUG_REPEAT, "Pausing game in mission repeat controller.")
|
|
SET_GAME_PAUSED(TRUE)
|
|
|
|
//Check the mission repeat index to trigger is valid.
|
|
IF g_RepeatPlayData.iMissionIndex < 0 OR g_RepeatPlayData.iMissionIndex >= ENUM_TO_INT(SP_MISSION_MAX)
|
|
SCRIPT_ASSERT("mission_repeat_controller.sc: The controller was asked to trigger a repeatable mission with an invalid index.")
|
|
Exit_Repeat_Play(TRUE)
|
|
ENDIF
|
|
|
|
// ------------Set initial mission details--------------------------
|
|
g_structRCMissionsStatic sRCMissionDetails
|
|
|
|
IF g_RepeatPlayData.eMissionType = CP_GROUP_RANDOMCHARS
|
|
g_bSceneAutoTrigger = TRUE // set scene auto trigger on for RCs
|
|
Retrieve_Random_Character_Static_Mission_Details(INT_TO_ENUM(g_eRC_MissionIDs ,g_RepeatPlayData.iMissionIndex), sRCMissionDetails)
|
|
ENDIF
|
|
|
|
// Some are different for story and RC missions
|
|
SWITCH g_RepeatPlayData.eMissionType
|
|
CASE CP_GROUP_MISSIONS
|
|
tScriptName = g_sMissionStaticData[g_RepeatPlayData.iMissionIndex].scriptName
|
|
iTriggerCharBitset = g_sMissionStaticData[g_RepeatPlayData.iMissionIndex].triggerCharBitset
|
|
BREAK
|
|
|
|
CASE CP_GROUP_RANDOMCHARS
|
|
tScriptName = sRCMissionDetails.rcScriptName
|
|
iTriggerCharBitset = sRCMissionDetails.rcPlayableChars
|
|
BREAK
|
|
|
|
DEFAULT
|
|
CPRINTLN(DEBUG_REPEAT,"Run_Mission_Repeat passed a mission type that isn't repeat playable: ", g_RepeatPlayData.eMissionType)
|
|
BREAK
|
|
ENDSWITCH
|
|
|
|
SET_PLAYER_IS_REPEATING_A_MISSION(TRUE)
|
|
|
|
// ------------------set up the player ready for the mission-------------------------
|
|
WHILE NOT IS_SCREEN_FADED_OUT()
|
|
IF NOT IS_SCREEN_FADING_OUT()
|
|
DO_SCREEN_FADE_OUT(500)
|
|
ENDIF
|
|
WAIT(0)
|
|
ENDWHILE
|
|
|
|
// Perform the repeat play autosave
|
|
Store_RepeatPlay_Snapshot()
|
|
|
|
// overwrite the vehicle's velocity- as we've already stored it
|
|
// and it is now frozen so velocity is 0
|
|
g_savedGlobals.sRepeatPlayData.mVehicleStruct.vVehicleVelocity = g_vRPVelocity
|
|
CPRINTLN(DEBUG_REPEAT, "Overwriting velocity as g_vRPVelocity x= ", g_vRPVelocity.x, " y= ", g_vRPVelocity.y, " z= ", g_vRPVelocity.z)
|
|
|
|
PERFORM_PRE_SAVEGAME_ROUTINE(FALSE, TRUE)
|
|
QUEUE_MISSION_REPEAT_SAVE()
|
|
|
|
WHILE GET_STATUS_OF_MISSION_REPEAT_SAVE() = SAVEGAME_OPERATION_IN_PROGRESS
|
|
WAIT(0)
|
|
CPRINTLN(DEBUG_REPEAT,"Waiting for repeat play to save the game.")
|
|
ENDWHILE
|
|
|
|
// Exit if we failed to save the game
|
|
IF GET_STATUS_OF_MISSION_REPEAT_SAVE() = SAVEGAME_OPERATION_FAILED
|
|
CPRINTLN(DEBUG_REPEAT,"Repeat play save failed. exit repeat play.")
|
|
Exit_Repeat_Play(TRUE)
|
|
EXIT
|
|
ELSE
|
|
CPRINTLN(DEBUG_REPEAT,"Repeat play save was successful.")
|
|
ENDIF
|
|
|
|
// stop player being on fire, ground him etc
|
|
VECTOR vPos
|
|
IF DOES_ENTITY_EXIST(PLAYER_PED_ID())
|
|
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
|
|
CPRINTLN(DEBUG_REPEAT,"Doing new safety checks: not injured.")
|
|
|
|
// get player out of car and ground him
|
|
CLEAR_PED_TASKS_IMMEDIATELY(PLAYER_PED_ID())
|
|
vPos = GET_ENTITY_COORDS(PLAYER_PED_ID())
|
|
GET_GROUND_Z_FOR_3D_COORD(vPos, vPos.z)
|
|
SET_ENTITY_COORDS(PLAYER_PED_ID(), vPos)
|
|
|
|
IF IS_ENTITY_ON_FIRE(PLAYER_PED_ID())
|
|
STOP_ENTITY_FIRE(PLAYER_PED_ID())
|
|
ENDIF
|
|
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
|
|
STOP_FIRE_IN_RANGE(vPos, 50.0)
|
|
ENDIF
|
|
CLEAR_AREA_OF_PROJECTILES(vPos, 50.0)
|
|
SET_ENTITY_HEALTH(PLAYER_PED_ID(),GET_PED_MAX_HEALTH(PLAYER_PED_ID())) //Always set the player to full health.
|
|
SET_CURRENT_PED_WEAPON(PLAYER_PED_ID(), WEAPONTYPE_UNARMED, TRUE)
|
|
ELSE
|
|
CPRINTLN(DEBUG_REPEAT,"Doing new safety checks: Player already injured.")
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// Repeat play is initialising, force clean-up any scripts we need to terminate
|
|
RepeatPlay_Freeze_Player(TRUE)
|
|
|
|
RUN_GENERAL_SCRIPT_CLEANUP()
|
|
|
|
// #1542560: Backup old crew unlock bitset before reset so we can use them on
|
|
// any heist planning board that supports them later.
|
|
iHeistCrewUnlockBackup = g_savedGlobals.sHeistData.iCrewUnlockedBitset
|
|
|
|
// set up building swaps, available characters etc
|
|
REPEAT_PLAY_UNLOCKING(g_RepeatPlayData.iMissionIndex, g_RepeatPlayData.eMissionType)
|
|
|
|
#if use_CLF_dlc
|
|
//always remove the spy vehicle for a repeat play
|
|
spy_vehicle_system_struct temp_spy_veh_system
|
|
spy_vehicle_remove_all_system_assets(temp_spy_veh_system)
|
|
#endif
|
|
|
|
IF g_RepeatPlayData.eMissionType = CP_GROUP_MISSIONS // (heists are in mission group at the moment for repeat play)
|
|
AND IS_BIT_SET(g_sMissionStaticData[g_RepeatPlayData.iMissionIndex].settingsBitset, MF_INDEX_IS_HEIST)
|
|
eRPState = RP_HEIST_PLANNING_BOARD // need to do planning board
|
|
ELSE
|
|
eRPState = RP_LAUNCH // no planning board needed, go to the mission
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Lets the player choose which crew / approach etc to use for this repeat play heist
|
|
PROC Do_Heist_Planning_Board()
|
|
CPRINTLN(DEBUG_REPEAT, "Do_Heist_Planning_Board called.")
|
|
|
|
// heist only variables
|
|
INT iHeist = GET_HEIST_FROM_MISSION_ID(INT_TO_ENUM(SP_MISSIONS, g_RepeatPlayData.iMissionIndex))
|
|
TEXT_LABEL_31 tHeistController = GET_HEIST_CONTROLLER_SCRIPT(INT_TO_ENUM(SP_MISSIONS, g_RepeatPlayData.iMissionIndex))
|
|
VECTOR vHeistPos = GET_HEIST_PLANNING_BOARD_LOCATION(iHeist)
|
|
|
|
//#1542560: Unlock previously unlocked heist crew members who are valid for this heist.
|
|
SWITCH iHeist
|
|
CASE HEIST_FINALE
|
|
CASE HEIST_AGENCY
|
|
IF IS_BIT_SET(iHeistCrewUnlockBackup, ENUM_TO_INT(CM_DRIVER_G_TALINA_UNLOCK))
|
|
SET_HEIST_CREW_MEMBER_UNLOCKED(CM_DRIVER_G_TALINA_UNLOCK)
|
|
ENDIF
|
|
FALLTHRU
|
|
CASE HEIST_RURAL_BANK
|
|
IF IS_BIT_SET(iHeistCrewUnlockBackup, ENUM_TO_INT(CM_GUNMAN_G_CHEF_UNLOCK))
|
|
SET_HEIST_CREW_MEMBER_UNLOCKED(CM_GUNMAN_G_CHEF_UNLOCK)
|
|
ENDIF
|
|
FALLTHRU
|
|
CASE HEIST_JEWEL
|
|
IF IS_BIT_SET(iHeistCrewUnlockBackup, ENUM_TO_INT(CM_GUNMAN_G_PACKIE_UNLOCK))
|
|
SET_HEIST_CREW_MEMBER_UNLOCKED(CM_GUNMAN_G_PACKIE_UNLOCK)
|
|
ENDIF
|
|
IF IS_BIT_SET(iHeistCrewUnlockBackup, ENUM_TO_INT(CM_HACKER_B_RICKIE_UNLOCK))
|
|
SET_HEIST_CREW_MEMBER_UNLOCKED(CM_HACKER_B_RICKIE_UNLOCK)
|
|
ENDIF
|
|
BREAK
|
|
ENDSWITCH
|
|
|
|
// load the heist controller
|
|
REQUEST_SCRIPT(tHeistController)
|
|
WHILE NOT (HAS_SCRIPT_LOADED(tHeistController))
|
|
CPRINTLN(DEBUG_REPEAT, "RepeatPlay: Waiting for script to load: ", tHeistController)
|
|
WAIT(0)
|
|
ENDWHILE
|
|
|
|
// Script has loaded, so launch it
|
|
START_NEW_SCRIPT(tHeistController, FRIEND_STACK_SIZE) //Fix for 1219287: This stack size must match the ones defined in Define_Restore_Launched_ScriptNames()
|
|
SET_SCRIPT_AS_NO_LONGER_NEEDED(tHeistController)
|
|
CPRINTLN(DEBUG_REPEAT, "RepeatPlay: script launched: ", tHeistController)
|
|
|
|
// Warp the player to the planning board
|
|
CPRINTLN(DEBUG_REPEAT, "iHeist = ", iHeist)
|
|
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
|
|
CPRINTLN(DEBUG_REPEAT, "RepeatPlay: warping player to heist board pos: ", vHeistPos)
|
|
RepeatPlay_Warp_Player(vHeistPos, GET_ENTITY_HEADING(PLAYER_PED_ID()), FALSE)
|
|
ENDIF
|
|
|
|
// set up any board display groups that should be on
|
|
SET_HEIST_BOARD_DISPLAY_GROUPS_ON(iHeist)
|
|
|
|
// any other special case setup
|
|
IF iHeist = HEIST_DOCKS
|
|
SET_BUILDING_STATE(BUILDINGNAME_ES_FLOYDS_APPARTMENT_SHIT, BUILDINGSTATE_DESTROYED)
|
|
SET_BUILDING_STATE(BUILDINGNAME_ES_FLOYDS_APPARTMENT_SHIT_SOFA, BUILDINGSTATE_DESTROYED)
|
|
|
|
ELIF iHeist = HEIST_AGENCY
|
|
SET_BUILDING_STATE(BUILDINGNAME_IPL_SWEATSHOP_WITH_INTERIOR, BUILDINGSTATE_DESTROYED)
|
|
ENDIF
|
|
|
|
// set flow flag to activate the planning board
|
|
REPEAT_PLAY_SET_HEIST_FLOW_FLAG(iHeist, RPH_START_BOARD_INTERACTIONS, TRUE)
|
|
|
|
// fade in when the board is ready to be displayed
|
|
WHILE g_bHeistBoardViewActive = FALSE
|
|
CPRINTLN(DEBUG_REPEAT, "Waiting for heist board to set up..")
|
|
WAIT(0)
|
|
ENDWHILE
|
|
RepeatPlay_Freeze_Player(FALSE) // un freeze + no longer invincible
|
|
|
|
// slight wait so we don't see stuff fade in
|
|
WAIT(500)
|
|
|
|
CPRINTLN(DEBUG_REPEAT, "Heist board has been setup, fading in.")
|
|
DO_SCREEN_FADE_IN(500)
|
|
|
|
// ---------------------------HEIST PLANNING BOARD FLOW-------------------------------------------------
|
|
eRPHeistState = RPHS_POI_OVERVIEW
|
|
|
|
WHILE eRPHeistState <> RPHS_FINISHED
|
|
WAIT(0)
|
|
|
|
SWITCH eRPHeistState
|
|
CASE RPHS_POI_OVERVIEW
|
|
eRPHeistState = REPEAT_PLAY_DO_BOARD_INTERACTION(iHeist, INTERACT_POI_OVERVIEW, REPEAT_PLAY_GET_HEIST_CHOICE_DISPLAY_GROUP(iHeist, TRUE), eRPHeistState)
|
|
BREAK
|
|
|
|
CASE RPHS_POI_OVERVIEW_DONE
|
|
CPRINTLN(DEBUG_REPEAT, "Point of interest overview done.")
|
|
WAIT(REPEAT_PLAY_GET_HEIST_CHOICE_DONE_WAIT(iHeist, eRPHeistState))
|
|
IF iHeist = HEIST_RURAL_BANK // bank heist doesn't have a gameplay choice
|
|
CPRINTLN(DEBUG_REPEAT, "Bank heist skipping gameplay choice.")
|
|
Set_Mission_Flow_Int_Value(FLOWINT_HEIST_CHOICE_RURAL, HEIST_CHOICE_RURAL_NO_TANK)
|
|
REPEAT_PLAY_SET_HEIST_FLOW_FLAG(iHeist, RPH_LOAD_EXIT_CUTSCENE, TRUE)
|
|
eRPHeistState = RPHS_CREW_CHOICE
|
|
ELSE
|
|
eRPHeistState = RPHS_GAMEPLAY_CHOICE
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE RPHS_GAMEPLAY_CHOICE
|
|
eRPHeistState = REPEAT_PLAY_DO_BOARD_INTERACTION(iHeist, INTERACT_GAMEPLAY_CHOICE, REPEAT_PLAY_GET_HEIST_CHOICE_DISPLAY_GROUP(iHeist, TRUE), eRPHeistState)
|
|
IF eRPHeistState <> RPHS_GAMEPLAY_CHOICE
|
|
REPEAT_PLAY_SET_HEIST_FLOW_FLAG(iHeist, RPH_LOAD_EXIT_CUTSCENE, TRUE)
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE RPHS_GAMEPLAY_CHOICE_DONE
|
|
CPRINTLN(DEBUG_REPEAT, "Gameplay choice done.")
|
|
WAIT(REPEAT_PLAY_GET_HEIST_CHOICE_DONE_WAIT(iHeist, eRPHeistState))
|
|
eRPHeistState = RPHS_CREW_CHOICE
|
|
BREAK
|
|
|
|
CASE RPHS_CREW_CHOICE
|
|
eRPHeistState = REPEAT_PLAY_DO_BOARD_INTERACTION(iHeist, INTERACT_CREW, REPEAT_PLAY_GET_HEIST_CHOICE_DISPLAY_GROUP(iHeist, FALSE), eRPHeistState)
|
|
BREAK
|
|
|
|
CASE RPHS_CREW_CHOICE_DONE
|
|
CPRINTLN(DEBUG_REPEAT, "Crew choice done.")
|
|
WAIT(REPEAT_PLAY_GET_HEIST_CHOICE_DONE_WAIT(iHeist, eRPHeistState))
|
|
REPEAT_PLAY_TOGGLE_BOARD_VIEWING(iHeist, FALSE)
|
|
eRPHeistState = RPHS_EXIT_CUTSCENE
|
|
BREAK
|
|
|
|
CASE RPHS_EXIT_CUTSCENE
|
|
|
|
CPRINTLN(DEBUG_REPEAT, "Waiting for heist board exit cut-scene to finish...")
|
|
WHILE NOT REPEAT_PLAY_HAS_HEIST_CUTSCENE_FINISHED(iHeist)
|
|
WAIT(0)
|
|
ENDWHILE
|
|
CPRINTLN(DEBUG_REPEAT, "Finished.")
|
|
|
|
DO_SCREEN_FADE_OUT(0)
|
|
|
|
CPRINTLN(DEBUG_REPEAT, "Waiting for heist board cut-scene to unload...")
|
|
WHILE IS_CUTSCENE_ACTIVE()
|
|
WAIT(0)
|
|
ENDWHILE
|
|
CPRINTLN(DEBUG_REPEAT, "Unloaded.")
|
|
eRPHeistState = RPHS_FINISHED
|
|
BREAK
|
|
|
|
DEFAULT
|
|
CPRINTLN(DEBUG_REPEAT, "Heist planning board in unknown state.")
|
|
BREAK
|
|
|
|
ENDSWITCH
|
|
ENDWHILE
|
|
CPRINTLN(DEBUG_REPEAT, "Heist planning board finished.")
|
|
//--------------------------------------------------------------------------------------------
|
|
|
|
// wait for the heist board to cleanup
|
|
CPRINTLN(DEBUG_REPEAT, "Waiting for heist board to cleanup.")
|
|
WHILE IS_CURRENTLY_ON_MISSION_TO_TYPE()
|
|
WAIT(0)
|
|
ENDWHILE
|
|
CPRINTLN(DEBUG_REPEAT, "Heist board has finished clean up.")
|
|
|
|
// any special case clean-up
|
|
IF iHeist = HEIST_AGENCY
|
|
// Switch to empty sweatshop interior
|
|
SET_BUILDING_STATE(BUILDINGNAME_IPL_SWEATSHOP_NO_INTERIOR, BUILDINGSTATE_DESTROYED)
|
|
SET_BUILDING_STATE(BUILDINGNAME_IPL_SWEATSHOP_WITH_INTERIOR, BUILDINGSTATE_CLEANUP)
|
|
SET_BUILDING_STATE(BUILDINGNAME_IPL_SWEATSHOP_LOD_DOOR, BUILDINGSTATE_DESTROYED)
|
|
SET_BUILDING_STATE(BUILDINGNAME_IPL_SWEATSHOP_BURNT, BUILDINGSTATE_NORMAL)
|
|
SET_BUILDING_STATE(BUILDINGNAME_IPL_SWEATSHOP_WINDOW_LIGHTS, BUILDINGSTATE_NORMAL)
|
|
|
|
ELIF iHeist = HEIST_DOCKS
|
|
SET_BUILDING_STATE(BUILDINGNAME_ES_FLOYDS_APPARTMENT_SHIT, BUILDINGSTATE_NORMAL)
|
|
SET_BUILDING_STATE(BUILDINGNAME_ES_FLOYDS_APPARTMENT_SHIT_SOFA, BUILDINGSTATE_NORMAL)
|
|
ENDIF
|
|
|
|
// do the actual heist mission
|
|
g_RepeatPlayData.iMissionIndex = REPEAT_PLAY_GET_SELECTED_HEIST_MISSION_ID(iHeist)
|
|
tScriptName = g_sMissionStaticData[g_RepeatPlayData.iMissionIndex].scriptName
|
|
iTriggerCharBitset = g_sMissionStaticData[g_RepeatPlayData.iMissionIndex].triggerCharBitset
|
|
|
|
RepeatPlay_Freeze_Player(TRUE) // re freeze + invincible
|
|
eRPState = RP_LAUNCH
|
|
ENDPROC
|
|
|
|
|
|
/// PURPOSE:
|
|
/// Launches the repeat play mission script
|
|
PROC Launch_Repeat_Play()
|
|
CPRINTLN(DEBUG_REPEAT, "Launch_Repeat_Play called.")
|
|
|
|
INT iHour, iMinute // used to set time of day to something suitable
|
|
|
|
// RC variables
|
|
g_structRCMissionsStatic sRCMissionDetails
|
|
|
|
// ----------------------load and launch the mission -------------------------------------
|
|
|
|
//Reset mission passed flag.
|
|
CLEAR_BIT(g_iRepeatPlayBits, ENUM_TO_INT(RPB_PASSED))
|
|
|
|
//Wait for the player character to be switched to the correct character for this mission.
|
|
REPEAT_PLAY_SWITCH_TO_SUITABLE_CHARACTER(iTriggerCharBitset)
|
|
|
|
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
|
|
|
|
//---------- warp the player into position + set time of day-------------
|
|
SWITCH g_RepeatPlayData.eMissionType
|
|
|
|
CASE CP_GROUP_MISSIONS
|
|
|
|
// warp
|
|
VECTOR vPos
|
|
vPos = GET_STORY_MISSION_WARP_POS()
|
|
IF NOT ARE_VECTORS_EQUAL(vPos, <<0.0,0.0,0.0>>)
|
|
CPRINTLN(DEBUG_REPEAT,"Moving player to blip pos")
|
|
RepeatPlay_Warp_Player(vPos, GET_ENTITY_HEADING(PLAYER_PED_ID()), TRUE)
|
|
CPRINTLN(DEBUG_REPEAT,"Moved player to blip pos")
|
|
ELSE
|
|
CPRINTLN(DEBUG_REPEAT,"Move to vector was 0,0,0. Leave player where he was.")
|
|
ENDIF
|
|
|
|
// set time to be suitable
|
|
SP_MISSIONS eMissionID
|
|
eMissionID = INT_TO_ENUM(SP_MISSIONS, g_RepeatPlayData.iMissionIndex)
|
|
|
|
IF (g_sMissionStaticData[eMissionID].startHour != NULL_HOUR) AND (g_sMissionStaticData[eMissionID].endHour != NULL_HOUR)
|
|
AND NOT IS_BIT_SET(g_sMissionStaticData[eMissionID].settingsBitset, MF_INDEX_MID_MISSION_TOD)
|
|
// ignore if the TOD skip is done mid mission
|
|
|
|
INT iCurrentHour
|
|
INT iStartHour
|
|
INT iEndHour
|
|
iCurrentHour = GET_TIMEOFDAY_HOUR(GET_CURRENT_TIMEOFDAY())
|
|
iStartHour = g_sMissionStaticData[eMissionID].startHour
|
|
iEndHour = g_sMissionStaticData[eMissionID].endHour
|
|
IF NOT IS_HOUR_BETWEEN_THESE_HOURS(iCurrentHour, iStartHour, iEndHour)
|
|
CPRINTLN(DEBUG_REPEAT, "Current hour is ", iCurrentHour, " which is not in the valid mission triggering hours of ", iStartHour, "->", iEndHour, ".")
|
|
CPRINTLN(DEBUG_REPEAT, "Overriding time hour to be ", iStartHour, ".")
|
|
SET_CLOCK_TIME(iStartHour, 00, 00)
|
|
ENDIF
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE CP_GROUP_RANDOMCHARS
|
|
|
|
g_eRC_MissionIDs eRCMissionID
|
|
|
|
// Warp
|
|
Retrieve_Random_Character_Static_Mission_Details(INT_TO_ENUM(g_eRC_MissionIDs ,g_RepeatPlayData.iMissionIndex), sRCMissionDetails)
|
|
CPRINTLN(DEBUG_REPEAT,"Moving player to blip pos")
|
|
|
|
// Get mission ID
|
|
eRCMissionID = Get_RC_MissionID_For_Script(tScriptName)
|
|
|
|
IF ARE_VECTORS_EQUAL(sRCMissionDetails.rcCoords, <<0,0,0>>)
|
|
|
|
IF eRCMissionID = RC_TONYA_3
|
|
OR eRCMissionID = RC_TONYA_4
|
|
sRCMissionDetails.rcCoords = <<-3.2349, -1469.9525, 29.5503>>
|
|
// Heading should be... 265.8950
|
|
ELSE
|
|
CERRORLN(DEBUG_REPEAT,"Launch_Repeat_Play: rcCoords are <<0,0,0 with no associated mission! Bug for Andy Minghella")
|
|
SCRIPT_ASSERT("Launch_Repeat_Play: rcCoords are <<0,0,0>> with no associated mission! Bug for Andy Minghella")
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// other special cases where we need to spawn player away from blip pos
|
|
IF eRCMissionID = RC_BARRY_1
|
|
OR eRCMissionID = RC_BARRY_2
|
|
sRCMissionDetails.rcCoords = <<188.51234, -954.81543, 29.09192>>
|
|
CPRINTLN(DEBUG_REPEAT,"Using special case pos for Barry 1/2 RC.")
|
|
ELIF eRCMissionID = RC_BARRY_3A
|
|
sRCMissionDetails.rcCoords = <<1205.7874, -1289.2284, 34.2264>>
|
|
ELIF eRCMissionID = RC_BARRY_3C
|
|
sRCMissionDetails.rcCoords = <<-447.0243, -1704.6481, 17.9004>>
|
|
ENDIF
|
|
|
|
RepeatPlay_Warp_Player(sRCMissionDetails.rcCoords, GET_ENTITY_HEADING(PLAYER_PED_ID()), TRUE)
|
|
CPRINTLN(DEBUG_REPEAT,"Moved player to blip pos")
|
|
|
|
// Time
|
|
IF sRCMissionDetails.rcStartTime != 0000 OR sRCMissionDetails.rcEndTime != 2359
|
|
iHour = (sRCMissionDetails.rcStartTime/100)
|
|
iMinute = (sRCMissionDetails.rcStartTime%100)
|
|
SET_CLOCK_TIME(iHour, iMinute, 0)
|
|
CPRINTLN(DEBUG_REPEAT,"REPEAT_PLAY_SET_SUITABLE_TIME_OF_DAY set time to : ", iHour, iMinute)
|
|
ENDIF
|
|
|
|
// Activate the RC so we can launch it
|
|
Activate_RC_Mission(eRCMissionID, FALSE)
|
|
|
|
// Special case for Tonya phone call missions
|
|
IF eRCMissionID = RC_TONYA_3
|
|
OR eRCMissionID = RC_TONYA_4
|
|
|
|
// Load script
|
|
REQUEST_SCRIPT("ambient_Tonya")
|
|
WHILE NOT HAS_SCRIPT_LOADED("ambient_Tonya")
|
|
REQUEST_SCRIPT("ambient_Tonya")
|
|
WAIT(0)
|
|
ENDWHILE
|
|
|
|
// Launch script
|
|
START_NEW_SCRIPT("ambient_Tonya", DEFAULT_STACK_SIZE)
|
|
SET_SCRIPT_AS_NO_LONGER_NEEDED("ambient_Tonya")
|
|
CPRINTLN(DEBUG_REPEAT, "Launched ambient script for Tonya 3 or 4.")
|
|
ELSE
|
|
CPRINTLN(DEBUG_REPEAT, "Reactivating all world brains.")
|
|
REACTIVATE_ALL_WORLD_BRAINS_THAT_ARE_WAITING_TILL_OUT_OF_RANGE()
|
|
ENDIF
|
|
|
|
g_RandomChars[eRCMissionID].rcLeaveAreaCheck = FALSE
|
|
g_bSceneAutoTrigger = TRUE //Flag launchers to setup their RC scene to automatically trigger.
|
|
|
|
//Delay until rc is flagged as running.
|
|
CPRINTLN(DEBUG_REPEAT, "Waiting for RC mission to trigger.")
|
|
WHILE NOT g_RandomChars[eRCMissionID].rcIsRunning
|
|
g_RandomChars[eRCMissionID].rcLeaveAreaCheck = FALSE
|
|
WAIT(0)
|
|
ENDWHILE
|
|
g_bSceneAutoTrigger = FALSE
|
|
BREAK
|
|
|
|
DEFAULT
|
|
CPRINTLN(DEBUG_REPEAT,"Launch_Repeat_Play passed a mission type that isn't repeat playable: ", g_RepeatPlayData.eMissionType)
|
|
BREAK
|
|
ENDSWITCH
|
|
ELSE
|
|
CERRORLN(DEBUG_REPEAT,"Launch_Repeat_Play: player is injured. Abort!. bug for Andy Minghella.")
|
|
SCRIPT_ASSERT("Launch_Repeat_Play: player is injured. Abort!. bug for Andy Minghella")
|
|
Exit_Repeat_Play(TRUE)
|
|
EXIT
|
|
ENDIF
|
|
|
|
RepeatPlay_Freeze_Player(FALSE) // un freeze + no longer invincible
|
|
eRPState = RP_RUNNING
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Waits for the repeat play thread to terminate
|
|
PROC Run_Repeat_Play()
|
|
CPRINTLN(DEBUG_REPEAT, "Run_Repeat_Play called.")
|
|
|
|
SWITCH g_RepeatPlayData.eMissionType
|
|
CASE CP_GROUP_MISSIONS
|
|
|
|
INT iCoreVarsArrayPos
|
|
iCoreVarsArrayPos = g_sMissionStaticData[g_RepeatPlayData.iMissionIndex].coreVariablesIndex
|
|
CPRINTLN(DEBUG_MISSION, "CoreVarsIndex in static data set to ", iCoreVarsArrayPos)
|
|
|
|
WHILE PERFORM_DO_MISSION_NOW(iCoreVarsArrayPos) = STAY_ON_THIS_COMMAND
|
|
WAIT(0)
|
|
// Story mission repeat play still running.
|
|
ENDWHILE
|
|
|
|
CPRINTLN(DEBUG_REPEAT, "Run_Repeat_Play story mission passed or failed +rejected.")
|
|
|
|
// handle 2 part mission
|
|
SP_MISSIONS eMissionID
|
|
eMissionID= INT_TO_ENUM(SP_MISSIONS, g_RepeatPlayData.iMissionIndex)
|
|
//Handle Finale A and B
|
|
IF eMissionID = SP_MISSION_FINALE_A
|
|
OR eMissionID = SP_MISSION_FINALE_B
|
|
IF IS_BIT_SET(g_iRepeatPlayBits, ENUM_TO_INT(RPB_PASSED))
|
|
//Wait until the Finale Credits is passed as well
|
|
CPRINTLN(DEBUG_REPEAT, "Run_Repeat_Play launching finale credits.")
|
|
|
|
// passed 2nd part, do credits
|
|
iCoreVarsArrayPos = g_sMissionStaticData[SP_MISSION_FINALE_CREDITS].coreVariablesIndex
|
|
|
|
WHILE PERFORM_DO_MISSION_NOW(iCoreVarsArrayPos) = STAY_ON_THIS_COMMAND
|
|
WAIT(0)
|
|
// Story mission repeat play still running
|
|
ENDWHILE
|
|
ENDIF
|
|
|
|
|
|
//Handle Finale C1
|
|
ELIF eMissionID = SP_MISSION_FINALE_C1
|
|
IF IS_BIT_SET(g_iRepeatPlayBits, ENUM_TO_INT(RPB_PASSED))
|
|
|
|
CPRINTLN(DEBUG_REPEAT, "Run_Repeat_Play launching finale c2.")
|
|
|
|
// passed 1st part, do 2nd part of mission
|
|
iCoreVarsArrayPos = g_sMissionStaticData[SP_MISSION_FINALE_C2].coreVariablesIndex
|
|
|
|
WHILE PERFORM_DO_MISSION_NOW(iCoreVarsArrayPos) = STAY_ON_THIS_COMMAND
|
|
WAIT(0)
|
|
// Story mission repeat play still running
|
|
ENDWHILE
|
|
|
|
//Wait until the Finale Credits is passed as well
|
|
CPRINTLN(DEBUG_REPEAT, "Run_Repeat_Play launching finale credits.")
|
|
|
|
// passed 2nd part, do credits
|
|
iCoreVarsArrayPos = g_sMissionStaticData[SP_MISSION_FINALE_CREDITS].coreVariablesIndex
|
|
|
|
WHILE PERFORM_DO_MISSION_NOW(iCoreVarsArrayPos) = STAY_ON_THIS_COMMAND
|
|
WAIT(0)
|
|
// Story mission repeat play still running
|
|
ENDWHILE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// if we're not staying on this command, repeat play was either passed or failed + rejected
|
|
IF IS_BIT_SET(g_iRepeatPlayBits, ENUM_TO_INT(RPB_PASSED))
|
|
eRPState = RP_PASSED
|
|
ELSE
|
|
eRPState = RP_FAILED
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE CP_GROUP_RANDOMCHARS
|
|
// wait for the mission thread to actually start
|
|
WHILE GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(GET_HASH_KEY(tScriptName)) =0
|
|
WAIT(0)
|
|
CPRINTLN(DEBUG_REPEAT, "Run_Repeat_Play waiting for mission thread to start.")
|
|
ENDWHILE
|
|
CPRINTLN(DEBUG_REPEAT, "Run_Repeat_Play mission thread started.")
|
|
|
|
//--------------------Wait for the mission script to terminate----------------------------
|
|
WHILE GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(GET_HASH_KEY(tScriptName)) >0
|
|
WAIT(0)
|
|
ENDWHILE
|
|
|
|
CPRINTLN(DEBUG_REPEAT, "Run_Repeat_Play mission thread terminated.")
|
|
|
|
/// ----------Pass / Fail-------------------------------
|
|
IF IS_BIT_SET(g_iRepeatPlayBits, ENUM_TO_INT(RPB_PASSED))
|
|
eRPState = RP_PASSED
|
|
ELSE
|
|
eRPState = RP_FAILED
|
|
ENDIF
|
|
BREAK
|
|
|
|
DEFAULT
|
|
CPRINTLN(DEBUG_REPEAT,"Run_Repeat_Play passed a mission type that isn't repeat playable: ", g_RepeatPlayData.eMissionType)
|
|
BREAK
|
|
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Waits for pass stats to display then calls repeat play completed
|
|
PROC Repeat_Play_Passed()
|
|
INT iEarlyExitTimer = 0
|
|
INT iEarlyOutLimit = 20000
|
|
CPRINTLN(DEBUG_REPEAT, "Repeat_Play_Passed called.")
|
|
|
|
BOOL bWaitForPassedScreen = TRUE
|
|
|
|
IF g_RepeatPlayData.eMissionType = CP_GROUP_MISSIONS
|
|
|
|
SP_MISSIONS eMissionID = INT_TO_ENUM(SP_MISSIONS, g_RepeatPlayData.iMissionIndex)
|
|
|
|
// Some missions do their passed screens during the mission.
|
|
IF eMissionID = SP_MISSION_FAMILY_3
|
|
OR eMissionID = SP_MISSION_FAMILY_5
|
|
OR eMissionID = SP_MISSION_FAMILY_6
|
|
OR eMissionID = SP_HEIST_FINALE_2A
|
|
OR eMissionID = SP_HEIST_FINALE_2B
|
|
//OR eMissionID = SP_MISSION_FINALE_C1 //C1 IS c2, c1 seamless passes into C2, fix for last comment on 1593783
|
|
OR eMissionID = SP_HEIST_JEWELRY_2
|
|
bWaitForPassedScreen = FALSE
|
|
CPRINTLN(DEBUG_REPEAT, "Repeat_Play_Passed: This mission does passed screen on mission: Don't wait for passed screen.")
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF bWaitForPassedScreen = TRUE
|
|
//Wait for the mission pass stats to start displaying
|
|
iEarlyExitTimer = GET_GAME_TIMER() + iEarlyOutLimit
|
|
WHILE g_bResultScreenDisplaying = FALSE
|
|
AND GET_GAME_TIMER() < iEarlyExitTimer
|
|
AND (NOT g_MissionStatSystemSuppressVisual)
|
|
WAIT(0)
|
|
CPRINTLN(DEBUG_REPEAT, "Repeat_Play_Passed: Waiting for stats to start displaying.")
|
|
ENDWHILE
|
|
|
|
//Wait for the mission pass stats to finish displaying
|
|
iEarlyExitTimer = GET_GAME_TIMER() + 30000
|
|
|
|
CPRINTLN(DEBUG_REPEAT, "Repeat_Play_Passed: Starting to wait for stats to finish displaying...")
|
|
WHILE (g_bResultScreenDisplaying OR g_bMissionStatSystemUploadPending)
|
|
AND GET_GAME_TIMER() < iEarlyExitTimer
|
|
WAIT(0)
|
|
ENDWHILE
|
|
CPRINTLN(DEBUG_REPEAT, "Repeat_Play_Passed: Stats finished displaying.")
|
|
ENDIF
|
|
|
|
// fade out and exit
|
|
WHILE NOT IS_SCREEN_FADED_OUT()
|
|
IF NOT IS_SCREEN_FADING_OUT()
|
|
DO_SCREEN_FADE_OUT(DEFAULT_FADE_TIME)
|
|
ENDIF
|
|
WAIT(0)
|
|
ENDWHILE
|
|
Repeat_Play_Completed()
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Handles setting up, accepting and rejecting replays
|
|
PROC Repeat_Play_Failed()
|
|
CPRINTLN(DEBUG_REPEAT, "Repeat_Play_Failed called.")
|
|
|
|
// End of mission cleanup
|
|
SWITCH g_RepeatPlayData.eMissionType
|
|
CASE CP_GROUP_MISSIONS
|
|
// Story missions only enter the failed state after replay rejection
|
|
// so can go stright to the exit
|
|
CPRINTLN(DEBUG_REPEAT,"Story Mission repeat rejected.")
|
|
Repeat_Play_Completed()
|
|
BREAK
|
|
|
|
CASE CP_GROUP_RANDOMCHARS
|
|
// RC replays should work ok since they don't rely on flow commands
|
|
WHILE IS_REPLAY_BEING_PROCESSED()
|
|
WAIT(0)
|
|
CPRINTLN(DEBUG_REPEAT,"Mission repeat RC waiting to be set up for a replay.")
|
|
ENDWHILE
|
|
|
|
// Handle accepting / rejecting of replay
|
|
IF IS_REPLAY_IN_PROGRESS()
|
|
CPRINTLN(DEBUG_REPEAT,"Mission repeat RC accepted.")
|
|
// replay accepted, wait for script to be running and go back into running state
|
|
WHILE GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(GET_HASH_KEY(tScriptName)) =0
|
|
WAIT(0)
|
|
CPRINTLN(DEBUG_REPEAT,"Waiting for RC replay to launch.")
|
|
ENDWHILE
|
|
eRPState = RP_RUNNING
|
|
ELSE
|
|
CPRINTLN(DEBUG_REPEAT,"Mission repeat RC rejected.")
|
|
Repeat_Play_Completed() // replay rejected, this repeat play is complete
|
|
ENDIF
|
|
BREAK
|
|
|
|
DEFAULT
|
|
CPRINTLN(DEBUG_REPEAT,"Repeat_Play_Failed passed a mission type that isn't repeat playable: ", g_RepeatPlayData.eMissionType)
|
|
Repeat_Play_Completed()
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
// ----------------Main Loop-------------------------------------------------------------
|
|
SCRIPT
|
|
CPRINTLN(DEBUG_REPEAT,"Starting mission repeat controller.")
|
|
|
|
// 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|FORCE_CLEANUP_FLAG_MAGDEMO))
|
|
CPRINTLN(DEBUG_REPEAT,"Mission_repeat_controller.sc has been forced to cleanup.")
|
|
|
|
IF GET_CAUSE_OF_MOST_RECENT_FORCE_CLEANUP() = FORCE_CLEANUP_FLAG_SP_TO_MP
|
|
CPRINTLN(DEBUG_REPEAT,"Mission_repeat_controller.sc has been forced to cleanup (SP to MP)")
|
|
SET_FRONTEND_ACTIVE(FALSE)
|
|
LOBBY_SET_AUTO_MULTIPLAYER(TRUE)
|
|
SHUTDOWN_SESSION_CLEARS_AUTO_MULTIPLAYER(FALSE)
|
|
QUEUE_MISSION_REPEAT_LOAD()
|
|
ENDIF
|
|
|
|
SET_PLAYER_IS_REPEATING_A_MISSION(FALSE)
|
|
|
|
TERMINATE_THIS_THREAD()
|
|
ENDIF
|
|
|
|
WHILE TRUE
|
|
IF IS_REPEAT_PLAY_ACTIVE()
|
|
|
|
SWITCH eRPState
|
|
|
|
CASE RP_SETUP
|
|
Setup_Repeat_Play()
|
|
BREAK
|
|
|
|
CASE RP_HEIST_PLANNING_BOARD
|
|
Do_Heist_Planning_Board()
|
|
BREAK
|
|
|
|
CASE RP_LAUNCH
|
|
Launch_Repeat_Play()
|
|
BREAK
|
|
|
|
CASE RP_RUNNING
|
|
Run_Repeat_Play()
|
|
BREAK
|
|
|
|
CASE RP_PASSED
|
|
Repeat_Play_Passed()
|
|
BREAK
|
|
|
|
CASE RP_FAILED
|
|
Repeat_Play_Failed()
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDIF
|
|
WAIT(0)
|
|
ENDWHILE
|
|
ENDSCRIPT
|