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

3705 lines
120 KiB
Python
Executable File

//Compile out Title Update changes to header functions.
//Must be before includes.
//CONST_INT USE_TU_CHANGES 0 // Removed by Kenneth R.
USING "rage_builtins.sch"
USING "globals.sch"
USING "cutscene_public.sch"
USING "commands_cutscene.sch"
USING "commands_entity.sch"
USING "commands_script.sch"
USING "script_player.sch"
USING "randomChar_public.sch"
USING "script_ped.sch"
USING "dialogue_public.sch"
USING "comms_control_public.sch"
USING "RC_Helper_Functions.sch"
USING "CompletionPercentage_public.sch"
USING "replay_public.sch"
USING "locates_public.sch"
USING "initial_scenes_Barry.sch"
USING "script_drawing.sch"
USING "commands_recording.sch"
#IF IS_DEBUG_BUILD
USING "select_mission_stage.sch"
#ENDIF
// *****************************************************************************************
// *****************************************************************************************
// *****************************************************************************************
//
// MISSION NAME : Barry3C.sc
// AUTHOR : Tom Waters
// DESCRIPTION : Franklin collects an old banger for Barry.
//
// *****************************************************************************************
// *****************************************************************************************
// *****************************************************************************************
//*************************************************************************************************************************************************
// :ENUMS:
//*************************************************************************************************************************************************
// Mission stages
ENUM MISSION_STAGE
MS_STAGE_ENTER_STASH_CAR,
MS_STAGE_START_STASH_CAR,
MS_STAGE_CALL_BARRY,
MS_STAGE_FIND_TOWTRUCK,
MS_STAGE_TOW_VEHICLE,
MS_STAGE_RETURN_VEHICLE,
MS_STAGE_UNHOOK_VEHICLE,
MS_STAGE_LEAVE,
MS_STAGE_GET_TRUCK_BACK,
MS_STAGE_REATTACH_VEHICLE,
MS_STAGE_REDELIVER,
MS_STAGE_LOSE_WANTED,
MS_STAGE_DELIVERY_PHONE_CALL,
MS_STAGE_FAIL_FADE
ENDENUM
// Progression within a stage
ENUM STAGE_PROGRESS
SP_SETUP,
SP_RUNNING,
SP_CLEANUP
ENDENUM
// Trying to start the car event
ENUM START_CAR_EVENT
SCE_ASSETS,
SCE_WAIT_FOR_INPUT, // Used in ambient car staring
SCE_TRIGGER_ANIM,
SCE_IGNITION_SOUND,
SCE_WAIT_TO_REPEAT,
SCE_ANNOYED_HORN,
SCE_COMMENT,
SCE_EXIT_CAR,
SCE_END
ENDENUM
//*************************************************************************************************************************************************
// :STRUCTURES:
//*************************************************************************************************************************************************
// Objectives
STRUCT MISSION_OBJECTIVE
INT iDisplayMax
INT iDisplayCount
STRING sTextLabel
ENDSTRUCT
// Vehicles
STRUCT COLLECT_VEHICLE
VECTOR location
FLOAT heading
VEHICLE_INDEX vehicle
MODEL_NAMES modelName
BOOL bPlayerBeenInThis
ENDSTRUCT
//*************************************************************************************************************************************************
// :CONSTANTS:
//*************************************************************************************************************************************************
// Checkpoints
CONST_INT CP_START_TOW 1
CONST_INT CP_DELIVERY 2
CONST_INT CP_MISSION_COMPLETE 3 // SHITSKIP only - do not set CPs for this
// Distances
CONST_FLOAT ABANDON_DISTANCE 200.0
CONST_FLOAT WARNING_DISTANCE 85.0
CONST_FLOAT LEAVE_DISTANCE 150.0
// Helper truck stuff
CONST_FLOAT TRUCK_SPAWN_DISTANCE 100.0
CONST_FLOAT TRUCK_DESPAWN_DISTANCE 175.0
CONST_INT INITIAL_SCENE_TRUCK 6
CONST_INT NUM_HELPER_TRUCKS 8
// Delay Franklin's comments and Barry's helper call
CONST_INT PUSH_MUTTER_DELAY 8000
CONST_INT BARRY_CALL_DELAY 120000
CONST_INT TRUCK_MUTTER_DELAY 160000
// Objective constants
CONST_INT MO_B3CENTV 0 // Get in the ~b~stash car.~s~
CONST_INT MO_B3CDELV 1 // Go to Barry's ~y~apartment.~s~
CONST_INT MO_B3CWAN1 2 // Lose the cops.
CONST_INT MO_B3CNOGO 3 // Find a way to move the stash car.
CONST_INT MO_B3CREVRS 4 // Hook the ~b~stash car.~s~
CONST_INT MO_B3CLEAVE 5 // Leave the area
CONST_INT MO_B3CRTTT 6 // Get back in the ~b~tow truck.~s~
CONST_INT MO_B3CGBTB 7 // The ~b~stash car~s~ has broken loose, hook it with the tow truck.
CONST_INT MO_B3CRTCB 8 // Get back in the ~b~cargobob.~s~
CONST_INT NUM_MISSION_OBJECTIVES 9
// For readibility of anim dict string array
CONST_INT ANM_DICT 0
CONST_INT ANM_NAME 1
// Vehicle restriction
CONST_INT RESTRICTION_STASHVEH 0
//*************************************************************************************************************************************************
// :VARIABLES:
//*************************************************************************************************************************************************
// Launcher vars
g_structRCScriptArgs sRCLauncherDataLocal
SCENARIO_BLOCKING_INDEX mScenarioBlocker
#IF IS_DEBUG_BUILD
// STAGE SKIPPING/CHECKPOINT STUFF
// Mission specific z-skip enum
ENUM MISSION_SKIP_STAGE
MSS_RESTART,
MSS_IN_CAR,
MSS_CALL_SKIP,
MSS_TOWING,
MSS_WARP_NEAR_END,
MSS_DELIVERY,
MSS_MISSION_COMPLETE
ENDENUM
MISSION_SKIP_STAGE eTargetStage
CONST_INT MAX_SKIP_MENU_LENGTH 7
MissionStageMenuTextStruct mSkipMenu[MAX_SKIP_MENU_LENGTH]
WIDGET_GROUP_ID widgetGroup
BOOL bDebugCheatCarLocation = FALSE
BOOL bDebugCarStartSpew = FALSE
#ENDIF
// Conversation/objective text interrupt handling
RC_CONV_RESTORE_STATE stateRestoreConversation
TEXT_LABEL_23 tSavedConversationRoot
TEXT_LABEL_23 tSavedConversationLabel
// Mission progression
MISSION_STAGE mStage = MS_STAGE_ENTER_STASH_CAR // track what mission stage we are at
STAGE_PROGRESS sProgress = SP_SETUP // used to track what bit of the current mission stage we're at
// general utility blip
BLIP_INDEX biGotoBlip
// The vehicle
COLLECT_VEHICLE stStashCar
BOOL bStashCarOnRoofLastFrame = FALSE
BOOL bTowTruckOnRoofLastFrame = FALSE
BOOL bTruckStuckCheckActive = FALSE
BOOL bStashStuckCheckActive = FALSE
INT iStashCarStuckTimer
INT iTowTruckStuckTimer
OBJECT_INDEX oiStashBox
VECTOR vecStashOffset = << -0.10, -0.85, 0.23 >>
VECTOR vecStashRotate = << 8.0, 0.5, 0.0 >>
MODEL_NAMES mnStashBox = Prop_Weed_Tub_01
// Has stash car been hooked so far? (used for objective control)
BOOL bStashCarHasBeenHooked = FALSE
BOOL bStashCarHasComeUnhooked = FALSE
// Vehicle delivery destinations
VECTOR vecApartment
SCENARIO_BLOCKING_INDEX sbCarPark[2] // Scenario blocker to stop parking scenario
// Tow truck bits
VEHICLE_INDEX vehTowTruck
MODEL_NAMES truckSkipModel = TOWTRUCK
INT iTruckColourScheme // Truck colour scheme is saved for recreating truck in skips
COLLECT_VEHICLE stTruck[NUM_HELPER_TRUCKS] // Towtrucks that are spawned to help player
BOOL bPlayerInTruckLastFrame // Track player entering/exiting truck in some mission steps
// Player snapshot car
BOOL bSetupVehGen = FALSE
// general utility counter
INT iCount
// Conversation struct
structPedsForConversation mConversationStruct
// Tracking which conversations have triggered in the truck-hunting stage
BOOL bFranklinPushMuttered = FALSE // Has Franklin muttered about needing to move the broken down car
BOOL bBarryCalledAboutTruck = FALSE // Has Barry called player suggesting tow truck
BOOL bFranklinTruckMuttered = FALSE // Has Franklin muttered about needing to jack a truck
// Event tracking bools
BOOL bShowedRaiseLowerHelp = FALSE // Has tow truck help message been displayed?
BOOL bShowedDetachHelp = FALSE
// Timers
INT iCarEventsTimer
INT iCallDelayTimer
INT iHelpTimer
// Car starting
CONST_INT NUM_IGNITION_ATTEMPTS 4
START_CAR_EVENT sceProgress
INT iIgnitionAttempts
INT iIgnitionSoundID
BOOL bPlayerWantsOut
BOOL bPlayerInStashCar
STRING sIgnitionAnims = "rcm_barry3c"
SEQUENCE_INDEX seqCarStart
// Franklin unhook complaints
CONST_INT NUM_FRANKLIN_COMPLAINTS 4 // Number of different complaint comments we have
STAGE_PROGRESS spFranklinUnhook // State progression for start/wait for comment/idle
STRING sComplaintLabel[NUM_FRANKLIN_COMPLAINTS] // Complaint labels array
INT iComplaintCount // Which was the last comment we played (they cycle)
// Hook monitoring
BOOL bShouldPlayUnhookComment
// Store dropoff zone behind Barry's
VECTOR vecDropoff[2][2]
FLOAT fDropoffWidth[2]
// Has the delivery phone call been triggered
BOOL bDeliveryCallTriggered
// Objective struct
MISSION_OBJECTIVE moObjectives[NUM_MISSION_OBJECTIVES]
BOOL bObjectiveNeeded // Used when we have to delay objectives
// Failure reason
STRING sFailReason
// For new checkpoint method
VECTOR vecRespawnTruck
FLOAT fRespawnTruck
//*************************************************************************************************************************************************
// Objectives functions/procs
//*************************************************************************************************************************************************
/// PURPOSE:
/// Returns a completed struct that holds an objective's info
/// PARAMS:
/// stTextLabel - The name of the text label that will be displayed as God text
/// iDisMax - Maximum number of times it can display. Set to -1 for no limit.
FUNC MISSION_OBJECTIVE CREATE_MISSION_OBJECTIVE(STRING stTextLabel, INT iDisMax = 1)
MISSION_OBJECTIVE tmpMissionObj
tmpMissionObj.sTextLabel = stTextLabel
tmpMissionObj.iDisplayMax = iDisMax
tmpMissionObj.iDisplayCount = 0
RETURN tmpMissionObj
ENDFUNC
/// PURPOSE:
/// Display an objective, unless it has already been displayed as many times as allowed
/// PARAMS:
/// iObj - which objective to display (use the constants)
PROC DISPLAY_MISSION_OBJECTIVE(INT iObj)
IF moObjectives[iObj].iDisplayCount < moObjectives[iObj].iDisplayMax
OR moObjectives[iObj].iDisplayMax = -1
PRINT_NOW(moObjectives[iObj].sTextLabel, DEFAULT_GOD_TEXT_TIME, 1)
CHECK_CONVERSATION_AND_OBJECTIVE_TEXT_CONFLICT_NOW(stateRestoreConversation)
moObjectives[iObj].iDisplayCount++
ENDIF
ENDPROC
/// PURPOSE:
/// Test whether an objective will display
/// Saves having a seperate bool for blip updates, or lets you see whether you need to clear an objective
/// PARAMS:
/// iObj - which objective to check (use the constants)
/// RETURNS:
/// TRUE if the objective will display
FUNC BOOL MISSION_OBJECTIVE_WILL_DISPLAY(INT iObj)
IF moObjectives[iObj].iDisplayCount < moObjectives[iObj].iDisplayMax
OR moObjectives[iObj].iDisplayMax = -1
RETURN TRUE
ELSE
RETURN FALSE
ENDIF
ENDFUNC
/// PURPOSE:
/// Remove a specific objective that is being displayed
/// PARAMS:
/// iObj - which objective we are removing (use the constants)
PROC CLEAR_MISSION_OBJECTIVE(INT iObj)
CLEAR_THIS_PRINT(moObjectives[iObj].sTextLabel)
ENDPROC
/// PURPOSE:
/// Are any mission objectives currently on screen?
/// RETURNS:
/// True if there is currently an objective from this mission on screen
FUNC BOOL MISSION_OBJECTIVES_CURRENTLY_DISPLAYED()
FOR iCount = 0 TO NUM_MISSION_OBJECTIVES-1
IF IS_THIS_PRINT_BEING_DISPLAYED(moObjectives[iCount].sTextLabel)
RETURN TRUE
ENDIF
ENDFOR
// Didn't find an objective
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// Allows skip procs to reset objective counter
/// PARAMS:
/// iObj - which objective we're resetting
/// iNewCount - new iDisplayCount value
PROC MISSION_OBJECTIVE_RESET(INT iObj, INT iNewCount = 0)
moObjectives[iObj].iDisplayCount = iNewCount
ENDPROC
/// PURPOSE:
/// Allows skip procs to set an objective to act as if it has already displayed
/// PARAMS:
/// iObj - which objective we're altering
PROC MISSION_OBJECTIVE_EXPIRE(INT iObj)
IF moObjectives[iObj].iDisplayMax = -1
CPRINTLN(DEBUG_MISSION, "Trying to expire an objective that has unlimited repeats!")
ELSE
moObjectives[iObj].iDisplayCount = moObjectives[iObj].iDisplayMax
ENDIF
ENDPROC
/// PURPOSE:
/// Set up all the mission objectives
PROC STORE_MISSION_OBJECTIVE_DATA()
moObjectives[MO_B3CENTV] = CREATE_MISSION_OBJECTIVE("B3CENTV", 1) // Get in the ~b~stash car.~s~
moObjectives[MO_B3CDELV] = CREATE_MISSION_OBJECTIVE("B3CDELV", 1) // Go to Barry's ~y~apartment.~s~
moObjectives[MO_B3CWAN1] = CREATE_MISSION_OBJECTIVE("B3CWAN1", -1) // Lose the cops.
moObjectives[MO_B3CNOGO] = CREATE_MISSION_OBJECTIVE("B3CNOGO", 1) // Find a way to move the stash car.
moObjectives[MO_B3CREVRS] = CREATE_MISSION_OBJECTIVE("B3CREVRS", 1) // Hook the ~b~stash car.~s~
moObjectives[MO_B3CLEAVE] = CREATE_MISSION_OBJECTIVE("B3CLEAVE", 1) // Leave the area.
moObjectives[MO_B3CRTTT] = CREATE_MISSION_OBJECTIVE("B3CRTTT", 1) // Get back in the ~b~tow truck.~s~
moObjectives[MO_B3CGBTB] = CREATE_MISSION_OBJECTIVE("B3CGBTB", 1) // The ~b~stash car~s~ has broken loose, hook it with the tow truck.
moObjectives[MO_B3CRTCB] = CREATE_MISSION_OBJECTIVE("B3CRTCB", 1) // Get back in the ~b~cargobob.~s~
ENDPROC
/// PURPOSE:
/// Stores the labels for Franklin's complaint comments
PROC STORE_COMPLAINT_STRINGS()
sComplaintLabel[0] = "BAR3C_Z1"
sComplaintLabel[1] = "BAR3C_Z2"
sComplaintLabel[2] = "BAR3C_Z3"
sComplaintLabel[3] = "BAR3C_Z4"
ENDPROC
/// PURPOSE:
/// Toggle all the car mod shops in one go
/// PARAMS:
/// bToggleFlag - Pass TRUE to toggle off, FALSE to toggle back on
PROC TOGGLE_CAR_MOD_SHOPS_UNAVAILABLE(BOOL bToggleFlag)
SET_SHOP_IS_TEMPORARILY_UNAVAILABLE(CARMOD_SHOP_01_AP, bToggleFlag)
SET_SHOP_IS_TEMPORARILY_UNAVAILABLE(CARMOD_SHOP_05_ID2, bToggleFlag)
SET_SHOP_IS_TEMPORARILY_UNAVAILABLE(CARMOD_SHOP_06_BT1, bToggleFlag)
SET_SHOP_IS_TEMPORARILY_UNAVAILABLE(CARMOD_SHOP_07_CS1, bToggleFlag)
SET_SHOP_IS_TEMPORARILY_UNAVAILABLE(CARMOD_SHOP_08_CS6, bToggleFlag)
SET_SHOP_IS_TEMPORARILY_UNAVAILABLE(CARMOD_SHOP_SUPERMOD, bToggleFlag)
ENDPROC
//*************************************************************************************************************************************************
// Utility functions/procs
//*************************************************************************************************************************************************
/// PURPOSE:
/// Cleanup
/// PARAMS:
/// If bDeleteEntities is FALSE the entities will be released instead of deleted
PROC COLLECT_AREA_CLEANUP()
IF IS_ENTITY_ALIVE(stStashCar.vehicle)
SET_ENTITY_LOAD_COLLISION_FLAG(stStashCar.vehicle, FALSE)
ENDIF
SAFE_RELEASE_VEHICLE(vehTowTruck)
SAFE_RELEASE_VEHICLE(stStashCar.vehicle)
SET_VEHICLE_MODEL_IS_SUPPRESSED(TOWTRUCK, FALSE)
TOGGLE_CAR_MOD_SHOPS_UNAVAILABLE(FALSE)
RC_CleanupSceneEntities(sRCLauncherDataLocal)
ENDPROC
/// PURPOSE:
/// Tests whether player is currently using a cargobob despite Franklin's dubious flying ability and readily available towtrucks
/// Do not call this unless you have already checked IS_PLAYER_IN_TOWTRUCK or similar
/// RETURNS:
/// TRUE if we are on the path of wrongness
FUNC BOOL TOWTRUCK_IS_ACTUALLY_A_CARGOBOB()
MODEL_NAMES mTmp = GET_ENTITY_MODEL(vehTowTruck)
IF mTmp = CARGOBOB
OR mTmp = CARGOBOB2
OR mTmp = CARGOBOB3
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// Checks the stash car's roll to see if it's probably on its roof
/// RETURNS:
/// TRUE if reasonably sure the car is upside down
FUNC BOOL STASH_CAR_UPSIDE_DOWN()
IF IS_ENTITY_ALIVE(stStashCar.vehicle)
FLOAT fStashRoll = WRAP(GET_ENTITY_ROLL(stStashCar.vehicle), 0, 360)
IF fStashRoll > 150
AND fStashRoll < 210
// CPRINTLN(DEBUG_MISSION, "Clamped 0-360 stash car roll is ", fStashRoll)
RETURN TRUE
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// Check for either vehicle being destroyed or dead player
/// RETURNS:
/// TRUE if either vehicle exists but is dead or stuck
FUNC BOOL MISSION_FAIL_CHECKS()
// Is the player dead
IF NOT IS_ENTITY_ALIVE(PLAYER_PED_ID())
RETURN TRUE
ENDIF
// Check for stash car destruction if currently spawned
IF DOES_ENTITY_EXIST(stStashCar.vehicle)
// Basic trashed checks
IF IS_ENTITY_DEAD(stStashCar.vehicle)
sFailReason = "B3CVHDEST" // The stash car was wrecked
sProgress = SP_SETUP
mStage = MS_STAGE_FAIL_FADE
RETURN TRUE
// Keep track of vehicle on roof
ELIF bStashStuckCheckActive
// IF STASH_CAR_UPSIDE_DOWN()
IF IS_VEHICLE_STUCK_ON_ROOF(stStashCar.vehicle)
IF bStashCarOnRoofLastFrame
IF GET_GAME_TIMER() - iStashCarStuckTimer > ROOF_TIME
sFailReason = "B3CVHSTUCK" // The stash car is stuck
sProgress = SP_SETUP
mStage = MS_STAGE_FAIL_FADE
RETURN TRUE
ENDIF
ELSE
CPRINTLN(DEBUG_MISSION, "Stash car is now on roof!")
bStashCarOnRoofLastFrame = TRUE
iStashCarStuckTimer = GET_GAME_TIMER()
ENDIF
ELSE
#IF IS_DEBUG_BUILD
IF bStashCarOnRoofLastFrame
CPRINTLN(DEBUG_MISSION, "Stash car is no longer on roof")
ENDIF
#ENDIF
bStashCarOnRoofLastFrame = FALSE
ENDIF
ENDIF
ENDIF
// Check for tow truck destruction if currently spawned
IF DOES_ENTITY_EXIST(vehTowTruck)
// Basic trashed checks
IF IS_ENTITY_DEAD(vehTowTruck)
AND bDeliveryCallTriggered = FALSE // Tow truck fails temp. disabled after delivery
IF TOWTRUCK_IS_ACTUALLY_A_CARGOBOB()
sFailReason = "B3CCBDEST" // The cargobob was destroyed
ELSE
sFailReason = "B3CTWDEST" // The tow truck was destroyed
ENDIF
sProgress = SP_SETUP
mStage = MS_STAGE_FAIL_FADE
RETURN TRUE
// Keep track of vehicle on roof
ELIF bTruckStuckCheckActive
AND bDeliveryCallTriggered = FALSE // Tow truck fails temp. disabled after delivery
IF IS_VEHICLE_STUCK_ON_ROOF(vehTowTruck)
IF bTowTruckOnRoofLastFrame
IF GET_GAME_TIMER() - iTowTruckStuckTimer > ROOF_TIME
IF TOWTRUCK_IS_ACTUALLY_A_CARGOBOB()
sFailReason = "B3CCBSTUCK" // The cargobob got stuck
ELSE
sFailReason = "B3CTWSTUCK" // The tow truck got stuck
ENDIF
sProgress = SP_SETUP
mStage = MS_STAGE_FAIL_FADE
RETURN TRUE
ENDIF
ELSE
bTowTruckOnRoofLastFrame = TRUE
iTowTruckStuckTimer = GET_GAME_TIMER()
ENDIF
ELSE
bTowTruckOnRoofLastFrame = FALSE
ENDIF
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// Check whether the stash car is attached to the tow truck
/// RETURNS:
/// TRUE if currently attached
FUNC BOOL IS_STASH_CAR_HOOKED()
// THIS IS USED IN SKIPS, IT MUST CHECK ENTITIES!
// Check if player has hooked car
IF IS_ENTITY_ALIVE(vehTowTruck)
AND IS_ENTITY_ALIVE(stStashCar.vehicle)
IF TOWTRUCK_IS_ACTUALLY_A_CARGOBOB()
IF DOES_CARGOBOB_HAVE_PICK_UP_ROPE(vehTowTruck)
AND IS_VEHICLE_ATTACHED_TO_CARGOBOB(vehTowTruck, stStashCar.vehicle)
bStashCarHasBeenHooked = TRUE
RETURN TRUE
ENDIF
ELSE
IF IS_VEHICLE_ATTACHED_TO_TOW_TRUCK(vehTowTruck, stStashCar.vehicle)
bStashCarHasBeenHooked = TRUE
RETURN TRUE
ENDIF
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// Check if the player is in any valid tow truck (TOWTRUCK, TOWTRUCK2)
/// If the player changes trucks, this will update the entity to point at the current one
/// RETURNS:
/// TRUE if player is in any valid tow truck
FUNC BOOL IS_PLAYER_IN_TOWTRUCK()
// Is player in the currently preferred towtruck
IF DOES_ENTITY_EXIST(vehTowTruck)
AND IS_PED_IN_VEHICLE(PLAYER_PED_ID(), vehTowTruck)
RETURN TRUE
// Is player in some other vehicle
ELIF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
// Get player vehicle
VEHICLE_INDEX tmpVehicle
tmpVehicle = GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID())
IF IS_ENTITY_ALIVE(tmpVehicle)
// Is vehicle a valid towtruck or cargobob?
MODEL_NAMES mTmp = GET_ENTITY_MODEL(tmpVehicle)
IF mTmp = TOWTRUCK OR mTmp = TOWTRUCK2
OR mTmp = CARGOBOB OR mTmp = CARGOBOB2 OR mTmp = CARGOBOB3
CPRINTLN(DEBUG_MISSION, "IS_PLAYER_IN_TOWTRUCK grabbing a new vehicle")
BOOL bOneOfOurs = FALSE // Tracks if the vehicle is one of our helper trucks
#IF IS_DEBUG_BUILD
truckSkipModel = mTmp
iTruckColourScheme = GET_VEHICLE_COLOUR_COMBINATION(tmpVehicle)
#ENDIF
// Ditch the current towtruck
IF DOES_ENTITY_EXIST(vehTowTruck)
IF bTruckStuckCheckActive
REMOVE_VEHICLE_UPSIDEDOWN_CHECK(vehTowTruck)
bTruckStuckCheckActive = FALSE
ENDIF
SET_VEHICLE_AS_NO_LONGER_NEEDED(vehTowTruck)
ENDIF
// Check whether the entered vehicle is one of the helper trucks
FOR iCount = 0 TO NUM_HELPER_TRUCKS-1
IF IS_ENTITY_ALIVE(stTruck[iCount].vehicle)
AND IS_PED_IN_VEHICLE(PLAYER_PED_ID(), stTruck[iCount].vehicle)
bOneOfOurs = TRUE
stTruck[iCount].bPlayerBeenInThis = TRUE
ASSIGN_VEHICLE_INDEX(vehTowTruck, stTruck[iCount].vehicle)
CPRINTLN(DEBUG_MISSION, "IS_PLAYER_IN_TOWTRUCK grabbed helper truck ", iCount, " as the one true truck")
ENDIF
ENDFOR
// Make truck player is in our truck if it hasn't already been grabbed from the helper trucks
IF NOT bOneOfOurs
SET_ENTITY_AS_MISSION_ENTITY(tmpVehicle, TRUE, TRUE)
vehTowTruck = tmpVehicle
ENDIF
ADD_VEHICLE_UPSIDEDOWN_CHECK(vehTowTruck)
bTruckStuckCheckActive = TRUE
// make truck unhookable to prevent craziness
SET_VEHICLE_AUTOMATICALLY_ATTACHES(vehTowTruck, FALSE)
// Mark the comment as invalid or it will fire spuriously
bShouldPlayUnhookComment = FALSE
RETURN TRUE
ENDIF
ENDIF
ENDIF
// Player isn't in a towtruck then
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// Checks whether it's reasonably likely that the player's about to be in a towtruck
/// RETURNS:
/// TRUE if entering a towtruck or close to a spawn
FUNC BOOL PLAYER_ABOUT_TO_GET_IN_TOWTRUCK()
// Check if player is entering a tow truck
IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID(), TRUE)
VEHICLE_INDEX tmpVehicle
tmpVehicle = GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID(), TRUE)
IF GET_ENTITY_MODEL(tmpVehicle) = TOWTRUCK OR GET_ENTITY_MODEL(tmpVehicle) = TOWTRUCK2
RETURN TRUE
ENDIF
ENDIF
// Check if player is right on top of an active tow truck spawn
FOR iCount = 0 TO NUM_HELPER_TRUCKS-1
IF NOT stTruck[iCount].bPlayerBeenInThis
AND IS_ENTITY_IN_RANGE_COORDS(PLAYER_PED_ID(), stTruck[iCount].location, 8.0)
RETURN TRUE
ENDIF
ENDFOR
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// Prevents the stash car from being towed
/// PARAMS:
/// bShouldBeNobbled - TRUE makes the stash car untowable
PROC NOBBLE_TOWING(BOOL bShouldBeNobbled)
IF bShouldBeNobbled
CPRINTLN(DEBUG_MISSION, "NOBBLE_TOWING: Setting stash car as untowable")
SET_VEHICLE_AUTOMATICALLY_ATTACHES(stStashCar.vehicle, FALSE)
SET_VEHICLE_DISABLE_TOWING(stStashCar.vehicle, TRUE)
ELSE
CPRINTLN(DEBUG_MISSION, "NOBBLE_TOWING: Setting stash car back to towable")
SET_VEHICLE_AUTOMATICALLY_ATTACHES(stStashCar.vehicle, TRUE)
SET_VEHICLE_DISABLE_TOWING(stStashCar.vehicle, FALSE)
ENDIF
ENDPROC
/// PURPOSE:
/// Disables select inputs during the car ignition attempt event
PROC DISABLE_INPUTS_FOR_CAR_SEQUENCE()
// DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_EXIT)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_MOVE_LR)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_ATTACK)
ENDPROC
/// PURPOSE:
/// Set up vehicle gen
PROC CHECK_VEHGEN_CREATION()
IF NOT bSetupVehGen
SET_MISSION_START_VEHICLE_AS_VEHICLE_GEN(<<0,0,0>>, 0, FALSE)
bSetupVehGen = TRUE
ENDIF
ENDPROC
/// PURPOSE:
/// Debug proc for printing out enum stage
FUNC STRING PRINT_STARTUP_ENUM_NAME(START_CAR_EVENT eCarStart)
SWITCH eCarStart
CASE SCE_ASSETS RETURN "SCE_ASSETS"
CASE SCE_WAIT_FOR_INPUT RETURN "SCE_WAIT_FOR_INPUT"
CASE SCE_TRIGGER_ANIM RETURN "SCE_TRIGGER_ANIM"
CASE SCE_IGNITION_SOUND RETURN "SCE_IGNITION_SOUND"
CASE SCE_WAIT_TO_REPEAT RETURN "SCE_WAIT_TO_REPEAT"
CASE SCE_ANNOYED_HORN RETURN "SCE_ANNOYED_HORN"
CASE SCE_COMMENT RETURN "SCE_COMMENT"
CASE SCE_EXIT_CAR RETURN "SCE_EXIT_CAR"
CASE SCE_END RETURN "SCE_END"
ENDSWITCH
RETURN "***Unknown START_CAR_EVENT value for PRINT_STARTUP_ENUM_NAME***"
ENDFUNC
/// PURPOSE:
/// Monitor player in stash car so we can have pressing the accelerator try the starter.
/// OK to call this when player isn't in car but probably as well to avoid ijn mission stages where we wouldn't want it.
PROC STASH_CAR_STARTFAIL_HANDLER()
IF NOT bPlayerInStashCar
IF IS_PED_IN_VEHICLE(PLAYER_PED_ID(), stStashCar.vehicle)
CPRINTLN(DEBUG_MISSION, "STASH_CAR_STARTFAIL_HANDLER detecting player in car, disabling controls")
bPlayerInStashCar = TRUE
bPlayerWantsOut = FALSE
sceProgress = SCE_ASSETS
SET_PLAYER_CONTROL(PLAYER_ID(), FALSE, SPC_LEAVE_CAMERA_CONTROL_ON)
DISABLE_INPUTS_FOR_CAR_SEQUENCE() // For some reason there STILL seemed to be a window where tweaking the wheel was allowed?
ELIF IS_PED_IN_VEHICLE(PLAYER_PED_ID(), stStashCar.vehicle, TRUE)
DISABLE_INPUTS_FOR_CAR_SEQUENCE()
ENDIF
ELSE
DISABLE_INPUTS_FOR_CAR_SEQUENCE()
IF NOT IS_PED_IN_VEHICLE(PLAYER_PED_ID(), stStashCar.vehicle)
#IF IS_DEBUG_BUILD
IF bDebugCarStartSpew
CPRINTLN(DEBUG_MISSION, "Startfail spew: Ped not in vehicle in step ", PRINT_STARTUP_ENUM_NAME(sceProgress), ", setting bools FALSE")
ENDIF
#ENDIF
IF bPlayerInStashCar
SET_PLAYER_CONTROL(PLAYER_ID(), TRUE) // Script fix for B*1760196
ENDIF
bPlayerInStashCar = FALSE
bPlayerWantsOut = FALSE
ELSE
IF NOT bPlayerWantsOut
AND IS_DISABLED_CONTROL_JUST_PRESSED(PLAYER_CONTROL, INPUT_VEH_EXIT)
CPRINTLN(DEBUG_MISSION, "STASH_CAR_STARTFAIL_HANDLER - Player wants out! Current stage is ", PRINT_STARTUP_ENUM_NAME(sceProgress))
bPlayerWantsOut = TRUE
ENDIF
SWITCH sceProgress
CASE SCE_ASSETS
IF bPlayerWantsOut
CPRINTLN(DEBUG_MISSION, "STASH_CAR_STARTFAIL_HANDLER: SCE_ASSETS: Allowing vehicle exit")
sceProgress = SCE_EXIT_CAR
ELSE
// Check sounds and assets loaded...
REQUEST_ANIM_DICT(sIgnitionAnims)
IF REQUEST_SCRIPT_AUDIO_BANK("BARRY3C_IGNITION_FAIL")
AND HAS_ANIM_DICT_LOADED(sIgnitionAnims)
// Don't go on before player is in driver seat
IF GET_PED_IN_VEHICLE_SEAT(stStashCar.vehicle) = PLAYER_PED_ID()
CPRINTLN(DEBUG_MISSION, "STASH_CAR_STARTFAIL_HANDLER: SCE_ASSETS: Got assets, ready to detect input")
sceProgress = SCE_WAIT_FOR_INPUT
ENDIF
#IF IS_DEBUG_BUILD
ELSE
IF bDebugCarStartSpew
CPRINTLN(DEBUG_MISSION, "Startfail spew: SCE_ASSETS waiting on assets")
ENDIF
#ENDIF
ENDIF
ENDIF
BREAK
// Wait for input
CASE SCE_WAIT_FOR_INPUT
IF bPlayerWantsOut
CPRINTLN(DEBUG_MISSION, "STASH_CAR_STARTFAIL_HANDLER: SCE_WAIT_FOR_INPUT: Allowing vehicle exit")
sceProgress = SCE_EXIT_CAR
// Check for accelerator press
ELIF IS_DISABLED_CONTROL_JUST_PRESSED(PLAYER_CONTROL, INPUT_VEH_ACCELERATE)
CPRINTLN(DEBUG_MISSION, "STASH_CAR_STARTFAIL_HANDLER: SCE_WAIT_FOR_INPUT: Received input, start anim")
sceProgress = SCE_TRIGGER_ANIM
#IF IS_DEBUG_BUILD
ELSE
IF bDebugCarStartSpew
CPRINTLN(DEBUG_MISSION, "Startfail spew: SCE_WAIT_FOR_INPUT waiting for input")
ENDIF
#ENDIF
ENDIF
BREAK
CASE SCE_TRIGGER_ANIM
CPRINTLN(DEBUG_MISSION, "STASH_CAR_STARTFAIL_HANDLER: SCE_TRIGGER_ANIM: Triggering anim, going to SCE_IGNITION_SOUND")
// Special long attempt then go to annoyance reaction
OPEN_SEQUENCE_TASK(seqCarStart)
TASK_PLAY_ANIM(NULL, sIgnitionAnims, "franklinfailingtostartcar_enter", NORMAL_BLEND_IN, NORMAL_BLEND_OUT, 2000, AF_NOT_INTERRUPTABLE)
TASK_PLAY_ANIM(NULL, sIgnitionAnims, "franklinfailingtostartcar_loop", NORMAL_BLEND_IN, NORMAL_BLEND_OUT, 1500, AF_LOOPING|AF_NOT_INTERRUPTABLE)
TASK_PLAY_ANIM(NULL, sIgnitionAnims, "franklinfailingtostartcar_exit", NORMAL_BLEND_IN, NORMAL_BLEND_OUT, 766, AF_NOT_INTERRUPTABLE)
CLOSE_SEQUENCE_TASK(seqCarStart)
CLEAR_PED_TASKS(PLAYER_PED_ID())
TASK_PERFORM_SEQUENCE(PLAYER_PED_ID(), seqCarStart)
CLEAR_SEQUENCE_TASK(seqCarStart)
iCarEventsTimer = GET_GAME_TIMER() + 2000
sceProgress = SCE_IGNITION_SOUND
BREAK
CASE SCE_IGNITION_SOUND
IF GET_GAME_TIMER() > iCarEventsTimer
CPRINTLN(DEBUG_MISSION, "STASH_CAR_STARTFAIL_HANDLER: SCE_IGNITION_SOUND: Triggering sound, going to SCE_WAIT_TO_REPEAT")
PLAY_SOUND_FROM_ENTITY(iIgnitionSoundID, "IGNITION_FAIL", stStashCar.vehicle, "BARRY_03_SOUNDSET")
SET_VARIABLE_ON_SOUND(iIgnitionSoundID, "HOLD TIME", 1.5)
iCarEventsTimer = GET_GAME_TIMER() + 2400
sceProgress = SCE_WAIT_TO_REPEAT
#IF IS_DEBUG_BUILD
ELSE
IF bDebugCarStartSpew
CPRINTLN(DEBUG_MISSION, "Startfail spew: SCE_IGNITION_SOUND waiting for timer ", iCarEventsTimer-GET_GAME_TIMER())
ENDIF
#ENDIF
ENDIF
BREAK
CASE SCE_WAIT_TO_REPEAT
IF GET_GAME_TIMER() > iCarEventsTimer
IF bPlayerWantsOut
CPRINTLN(DEBUG_MISSION, "STASH_CAR_STARTFAIL_HANDLER: SCE_WAIT_TO_REPEAT: Going on to exit")
sceProgress = SCE_EXIT_CAR
ELSE
CPRINTLN(DEBUG_MISSION, "STASH_CAR_STARTFAIL_HANDLER: SCE_WAIT_TO_REPEAT: Going to wait for input")
sceProgress = SCE_WAIT_FOR_INPUT
ENDIF
#IF IS_DEBUG_BUILD
ELSE
IF bDebugCarStartSpew
CPRINTLN(DEBUG_MISSION, "Startfail spew: SCE_WAIT_TO_REPEAT waiting for timer ", iCarEventsTimer-GET_GAME_TIMER())
ENDIF
#ENDIF
ENDIF
BREAK
CASE SCE_EXIT_CAR
IF GET_GAME_TIMER() > iCarEventsTimer
AND NOT GET_IS_TASK_ACTIVE(PLAYER_PED_ID(), CODE_TASK_EXIT_VEHICLE)
CPRINTLN(DEBUG_MISSION, "STASH_CAR_STARTFAIL_HANDLER: SCE_EXIT_CAR: Exit the car")
CLEAR_PED_TASKS(PLAYER_PED_ID())
TASK_LEAVE_VEHICLE(PLAYER_PED_ID(), stStashCar.vehicle)
SET_PLAYER_CONTROL(PLAYER_ID(), TRUE)
#IF IS_DEBUG_BUILD
ELSE
IF bDebugCarStartSpew
CPRINTLN(DEBUG_MISSION, "Startfail spew: SCE_EXIT_CAR waiting for timer ", iCarEventsTimer-GET_GAME_TIMER())
ENDIF
#ENDIF
ENDIF
BREAK
ENDSWITCH
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Turns off engine and lights
PROC VEHICLE_SHUTDOWN(VEHICLE_INDEX viVehicle)
IF IS_ENTITY_ALIVE(viVehicle)
SET_VEHICLE_ENGINE_ON(viVehicle, FALSE, FALSE)
SET_VEHICLE_LIGHTS(viVehicle, FORCE_VEHICLE_LIGHTS_OFF)
ENDIF
ENDPROC
/// PURPOSE:
/// Trigger Franklin complaint conversations
PROC FRANKLIN_UNHOOK_COMPLAINT()
SWITCH spFranklinUnhook
CASE SP_SETUP
// Don't allow "tow" comment if we're in a cargobob
IF iComplaintCount = 3 AND TOWTRUCK_IS_ACTUALLY_A_CARGOBOB()
CPRINTLN(DEBUG_MISSION, "Franklin complaint is at 3 but we're in a cargobob - set back to 0")
iComplaintCount = 0
ENDIF
IF MISSION_OBJECTIVES_CURRENTLY_DISPLAYED()
// Play conversation with no subtitles
IF CREATE_CONVERSATION(mConversationStruct, "BAR3CAU", sComplaintLabel[iComplaintCount], CONV_PRIORITY_MEDIUM, DO_NOT_DISPLAY_SUBTITLES)
CPRINTLN(DEBUG_MISSION, "Franklin complaint ", sComplaintLabel[iComplaintCount])
spFranklinUnhook = SP_RUNNING
ENDIF
ELSE
// Play conversation with subtitles
IF CREATE_CONVERSATION(mConversationStruct, "BAR3CAU", sComplaintLabel[iComplaintCount], CONV_PRIORITY_MEDIUM)
CPRINTLN(DEBUG_MISSION, "Franklin complaint ", sComplaintLabel[iComplaintCount])
spFranklinUnhook = SP_RUNNING
ENDIF
ENDIF
BREAK
CASE SP_RUNNING
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
// Roll on the complaint counter
iComplaintCount++
CPRINTLN(DEBUG_MISSION, "Franklin complaint counter set to ", iComplaintCount)
IF iComplaintCount >= NUM_FRANKLIN_COMPLAINTS
iComplaintCount = 0
CPRINTLN(DEBUG_MISSION, " - and then reset to zero")
ENDIF
spFranklinUnhook = SP_CLEANUP
ENDIF
BREAK
CASE SP_CLEANUP
// Do nothing
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE:
/// Creates a filled in vehicle struct for a possible towtruck spawn
FUNC COLLECT_VEHICLE MAKE_TOWTRUCK_SPAWN(VECTOR vLoc, FLOAT fHead)
COLLECT_VEHICLE stTmp
stTmp.location = vLoc
stTmp.heading = fHead
stTmp.modelName = TOWTRUCK
stTmp.bPlayerBeenInThis = FALSE
RETURN stTmp
ENDFUNC
/// PURPOSE:
/// Controls spawning and despawning of helper towtrucks
PROC TRUCK_SPAWNER(BOOL bForceCleanup = FALSE)
IF bForceCleanup
// We've finished looking for trucks - force cleanup
FOR iCount = 0 TO NUM_HELPER_TRUCKS-1
SAFE_RELEASE_VEHICLE(stTruck[iCount].vehicle)
ENDFOR
ELSE
// Check whether any of the trucks need spawning or deleting
FOR iCount = 0 TO NUM_HELPER_TRUCKS-1
// Check whether truck exists
IF DOES_ENTITY_EXIST(stTruck[iCount].vehicle) // Must use this method - B*1128499
// See if the player is now too far away and this needs deleting
IF NOT IS_ENTITY_IN_RANGE_COORDS(PLAYER_PED_ID(), stTruck[iCount].location, TRUCK_DESPAWN_DISTANCE)
AND GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), stTruck[iCount].vehicle) > TRUCK_DESPAWN_DISTANCE // Need to use a command that has dead checks or you'll get an assert
SAFE_DELETE_VEHICLE(stTruck[iCount].vehicle)
ENDIF
ELSE
// If we have already been in this truck it won't spawn again - otherwise OK
IF NOT stTruck[iCount].bPlayerBeenInThis
AND IS_ENTITY_IN_RANGE_COORDS(PLAYER_PED_ID(), stTruck[iCount].location, TRUCK_SPAWN_DISTANCE)
stTruck[iCount].vehicle = CREATE_VEHICLE(TOWTRUCK, stTruck[iCount].location, stTruck[iCount].heading)
IF iCount = INITIAL_SCENE_TRUCK
SET_VEHICLE_COLOURS(stTruck[iCount].vehicle, 39, 43)
ELSE
SET_VEHICLE_COLOUR_COMBINATION(stTruck[iCount].vehicle, 0)
ENDIF
SET_VEHICLE_ON_GROUND_PROPERLY(stTruck[iCount].vehicle)
SET_VEHICLE_AUTOMATICALLY_ATTACHES(stTruck[iCount].vehicle, FALSE)
SET_VEHICLE_HAS_STRONG_AXLES(stTruck[iCount].vehicle, TRUE)
ENDIF
ENDIF
ENDFOR
ENDIF
ENDPROC
//*************************************************************************************************************************************************
//
// SKIP PROCS
//
//*************************************************************************************************************************************************
/// PURPOSE:
/// Clears any objective that are being displayed, clear help, stop conversations, kill phone calls
PROC SKIP_CLEAR_ALL_MISSION_OBJECTIVES()
CLEAR_PRINTS()
CLEAR_HELP(TRUE)
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
KILL_FACE_TO_FACE_CONVERSATION_DO_NOT_FINISH_LAST_LINE()
ENDIF
HANG_UP_AND_PUT_AWAY_PHONE()
ENDPROC
/// PURPOSE:
/// Clear wanted level when skipping
PROC SKIP_CLEAR_WANTED()
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
IF GET_PLAYER_WANTED_LEVEL(PLAYER_ID()) > 0
SET_PLAYER_WANTED_LEVEL(PLAYER_ID(), 0)
SET_PLAYER_WANTED_LEVEL_NOW(PLAYER_ID())
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Recreates the truck
PROC SKIP_RESPAWN_TRUCK(VECTOR vecRSLoc, FLOAT fRSHead, BOOL bInsertPlayer = TRUE)
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
IF bInsertPlayer
SET_ENTITY_COORDS(PLAYER_PED_ID(), vecRSLoc)
ENDIF
ENDIF
IF DOES_ENTITY_EXIST(vehTowTruck)
IF bTruckStuckCheckActive
REMOVE_VEHICLE_UPSIDEDOWN_CHECK(vehTowTruck)
bTruckStuckCheckActive = FALSE
ENDIF
SAFE_DELETE_VEHICLE(vehTowTruck)
ENDIF
REQUEST_MODEL(truckSkipModel)
WHILE NOT HAS_MODEL_LOADED(truckSkipModel)
WAIT(0)
ENDWHILE
vehTowTruck = CREATE_VEHICLE(truckSkipModel, vecRSLoc, fRSHead)
SET_MODEL_AS_NO_LONGER_NEEDED(truckSkipModel)
SET_VEHICLE_COLOUR_COMBINATION(vehTowTruck, iTruckColourScheme)
SET_VEHICLE_ON_GROUND_PROPERLY(vehTowTruck)
IF bInsertPlayer
SAFE_SET_PED_INTO_VEHICLE(PLAYER_PED_ID(), vehTowTruck)
ENDIF
SET_VEHICLE_CAN_LEAK_OIL(vehTowTruck, FALSE)
SET_VEHICLE_CAN_LEAK_PETROL(vehTowTruck, FALSE)
SET_VEHICLE_HAS_STRONG_AXLES(vehTowTruck, TRUE)
IF NOT IS_ENTITY_DEAD(vehTowTruck)
ADD_VEHICLE_UPSIDEDOWN_CHECK(vehTowTruck)
bTruckStuckCheckActive = TRUE
ENDIF
ENDPROC
/// PURPOSE:
/// Recreates the stash car
PROC SKIP_RESPAWN_STASH_CAR(VECTOR vecRSLoc, FLOAT fRSHead)
REQUEST_MODEL(stStashCar.modelName)
IF DOES_ENTITY_EXIST(stStashCar.vehicle)
IF bStashStuckCheckActive
REMOVE_VEHICLE_UPSIDEDOWN_CHECK(stStashCar.vehicle)
bStashStuckCheckActive = FALSE
ENDIF
ENDIF
WHILE NOT HAS_MODEL_LOADED(stStashCar.modelName)
CPRINTLN(DEBUG_MISSION, "Waiting to load stash car model...")
WAIT(0)
ENDWHILE
SAFE_DELETE_OBJECT(oiStashBox)
SAFE_DELETE_VEHICLE(stStashCar.vehicle)
stStashCar.vehicle = CREATE_VEHICLE(stStashCar.modelName, vecRSLoc, fRSHead)
SET_MODEL_AS_NO_LONGER_NEEDED(stStashCar.modelName)
SET_VEHICLE_ON_GROUND_PROPERLY(stStashCar.vehicle)
SET_VEHICLE_CAN_LEAK_OIL(stStashCar.vehicle, FALSE)
SET_VEHICLE_CAN_LEAK_PETROL(stStashCar.vehicle, FALSE)
SET_VEHICLE_COLOUR_COMBINATION(stStashCar.vehicle, 1)
SET_VEHICLE_UNDRIVEABLE(stStashCar.vehicle, TRUE)
SET_VEHICLE_HAS_STRONG_AXLES(stStashCar.vehicle, TRUE)
SET_ENTITY_LOAD_COLLISION_FLAG(stStashCar.vehicle, TRUE)
IF NOT IS_ENTITY_DEAD(stStashCar.vehicle)
ADD_VEHICLE_UPSIDEDOWN_CHECK(stStashCar.vehicle)
bStashStuckCheckActive = TRUE
ENDIF
oiStashBox = CREATE_OBJECT(mnStashBox, vecRSLoc+vecStashOffset)
ATTACH_ENTITY_TO_ENTITY(oiStashBox, stStashCar.vehicle, 0, vecStashOffset, vecStashRotate)
ENDPROC
#IF IS_DEBUG_BUILD
/// PURPOSE:
/// Restart the mission
PROC SKIP_TO_MS_INIT()
CPRINTLN(DEBUG_MISSION, "DEBUG SKIP ::: restart mission")
SET_VEHICLE_MODEL_IS_SUPPRESSED(TOWTRUCK, FALSE)
SKIP_CLEAR_ALL_MISSION_OBJECTIVES()
SKIP_CLEAR_WANTED()
SAFE_REMOVE_BLIP(biGotoBlip)
// Progression stuff
mStage = MS_STAGE_ENTER_STASH_CAR
sProgress = SP_SETUP
// Teleport player out of vehicle, recreate it
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
SET_ENTITY_COORDS(PLAYER_PED_ID(), stStashCar.location)
ENDIF
SKIP_RESPAWN_STASH_CAR(stStashCar.location, stStashCar.heading)
// Place player
CLEAR_AREA_OF_VEHICLES(<<-451.4656, -1702.8058, 17.8676>>, 7.0)
SET_ENTITY_COORDS(PLAYER_PED_ID(), <<-451.4656, -1702.8058, 17.8676>>)
SET_ENTITY_HEADING(PLAYER_PED_ID(), 117.2)
// Clear up towtruck(s)
IF DOES_ENTITY_EXIST(vehTowTruck)
SAFE_DELETE_VEHICLE(vehTowTruck)
ENDIF
FOR iCount = 0 TO NUM_HELPER_TRUCKS-1
IF DOES_ENTITY_EXIST(stTruck[iCount].vehicle)
SAFE_DELETE_VEHICLE(stTruck[iCount].vehicle)
ENDIF
stTruck[iCount].bPlayerBeenInThis = FALSE
ENDFOR
// Has stash car been hooked yet?
bStashCarHasBeenHooked = FALSE
// Reset Franklin's unhook complaints
spFranklinUnhook = SP_CLEANUP
iComplaintCount = 0
bFranklinPushMuttered = FALSE // Has Franklin muttered about needing to move the broken down car
bBarryCalledAboutTruck = FALSE // Has Barry called player suggesting tow truck
bFranklinTruckMuttered = FALSE // Has Franklin muttered about needing to jack a truck
bDeliveryCallTriggered = FALSE
MISSION_OBJECTIVE_RESET(MO_B3CENTV) // Get in the ~b~stash car.~s~
MISSION_OBJECTIVE_RESET(MO_B3CDELV) // Go to Barry's ~y~apartment.~s~
MISSION_OBJECTIVE_RESET(MO_B3CWAN1) // Lose the cops.
MISSION_OBJECTIVE_RESET(MO_B3CNOGO) // Find a way to move the stash car.
MISSION_OBJECTIVE_RESET(MO_B3CREVRS) // Hook the ~b~stash car.~s~
MISSION_OBJECTIVE_RESET(MO_B3CLEAVE) // Leave the area
MISSION_OBJECTIVE_RESET(MO_B3CRTTT) // Get back in the ~b~tow truck.~s~
MISSION_OBJECTIVE_RESET(MO_B3CGBTB) // The ~b~stash car~s~ has broken loose, hook it with the tow truck.
MISSION_OBJECTIVE_RESET(MO_B3CGBTB) // Rehook the ~b~stash car~s~.
ENDPROC
#ENDIF
/// PURPOSE:
/// Z-SKIP
/// Set player into car to start it up
PROC SKIP_TO_START_CAR(BOOL bIsACheckpoint = FALSE)
CPRINTLN(DEBUG_MISSION, "DEBUG SKIP ::: SKIP_TO_START_CAR")
IF bIsACheckPoint
START_REPLAY_SETUP(stStashCar.location, stStashCar.heading)
ENDIF
SET_VEHICLE_MODEL_IS_SUPPRESSED(TOWTRUCK, FALSE)
SKIP_CLEAR_ALL_MISSION_OBJECTIVES()
SKIP_CLEAR_WANTED()
SAFE_REMOVE_BLIP(biGotoBlip)
// Progression stuff
mStage = MS_STAGE_START_STASH_CAR
sProgress = SP_SETUP
// Has stash car been hooked yet?
bStashCarHasBeenHooked = FALSE
// Reset Franklin's unhook complaints
spFranklinUnhook = SP_CLEANUP
iComplaintCount = 0
bFranklinPushMuttered = FALSE // Has Franklin muttered about needing to move the broken down car
bBarryCalledAboutTruck = FALSE // Has Barry called player suggesting tow truck
bFranklinTruckMuttered = FALSE // Has Franklin muttered about needing to jack a truck
bDeliveryCallTriggered = FALSE
MISSION_OBJECTIVE_EXPIRE(MO_B3CENTV) // Get in the ~b~stash car.~s~
MISSION_OBJECTIVE_RESET(MO_B3CDELV) // Go to Barry's ~y~apartment.~s~
MISSION_OBJECTIVE_RESET(MO_B3CWAN1) // Lose the cops.
MISSION_OBJECTIVE_RESET(MO_B3CNOGO) // Find a way to move the stash car.
MISSION_OBJECTIVE_RESET(MO_B3CREVRS) // Hook the ~b~stash car.~s~
MISSION_OBJECTIVE_RESET(MO_B3CLEAVE) // Leave the area
MISSION_OBJECTIVE_RESET(MO_B3CRTTT) // Get back in the ~b~tow truck.~s~
MISSION_OBJECTIVE_RESET(MO_B3CGBTB) // The ~b~stash car~s~ has broken loose, hook it with the tow truck.
MISSION_OBJECTIVE_RESET(MO_B3CGBTB) // Rehook the ~b~stash car~s~.
// Clear up towtruck(s)
IF DOES_ENTITY_EXIST(vehTowTruck)
SAFE_DELETE_VEHICLE(vehTowTruck)
ENDIF
FOR iCount = 0 TO NUM_HELPER_TRUCKS-1
IF DOES_ENTITY_EXIST(stTruck[iCount].vehicle)
SAFE_DELETE_VEHICLE(stTruck[iCount].vehicle)
ENDIF
stTruck[iCount].bPlayerBeenInThis = FALSE
ENDFOR
// Replay or not?
IF bIsACheckPoint
IF NOT DOES_ENTITY_EXIST(stStashCar.vehicle) // On initial repeat play checkpoint, car will exist from initial scene
SKIP_RESPAWN_STASH_CAR(stStashCar.location, stStashCar.heading)
ENDIF
WHILE NOT HAS_ADDITIONAL_TEXT_LOADED(MISSION_TEXT_SLOT)
WAIT(0)
ENDWHILE
END_REPLAY_SETUP(stStashCar.vehicle, VS_DRIVER, FALSE)
ELSE
// Teleport player out of vehicle, recreate it
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
SET_ENTITY_COORDS(PLAYER_PED_ID(), stStashCar.location)
ENDIF
SKIP_RESPAWN_STASH_CAR(stStashCar.location, stStashCar.heading)
SET_PED_INTO_VEHICLE(PLAYER_PED_ID(), stStashCar.vehicle)
ENDIF
ENDPROC
#IF IS_DEBUG_BUILD
/// PURPOSE:
/// Z-SKIP
/// jump to point after the initial phone call to Barry
PROC SKIP_TO_AFTER_CALL()
CPRINTLN(DEBUG_MISSION, "DEBUG SKIP ::: skip to after phone call")
SET_VEHICLE_MODEL_IS_SUPPRESSED(TOWTRUCK, FALSE)
SKIP_CLEAR_ALL_MISSION_OBJECTIVES()
SKIP_CLEAR_WANTED()
SAFE_REMOVE_BLIP(biGotoBlip)
// Progression stuff
mStage = MS_STAGE_CALL_BARRY
sProgress = SP_CLEANUP
// Set player near car
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
SET_ENTITY_COORDS(PLAYER_PED_ID(), << -464.8707, -1710.4111, 17.6895 >>)
SET_ENTITY_HEADING(PLAYER_PED_ID(), 287.46)
ENDIF
// Remake the stash car (locked)
SKIP_RESPAWN_STASH_CAR(stStashCar.location, stStashCar.heading)
WAIT(0)
// Clear up towtruck(s)
IF DOES_ENTITY_EXIST(vehTowTruck)
SAFE_DELETE_VEHICLE(vehTowTruck)
ENDIF
FOR iCount = 0 TO NUM_HELPER_TRUCKS-1
IF DOES_ENTITY_EXIST(stTruck[iCount].vehicle)
SAFE_DELETE_VEHICLE(stTruck[iCount].vehicle)
ENDIF
stTruck[iCount].bPlayerBeenInThis = FALSE
ENDFOR
// Reset Franklin's unhook complaints
spFranklinUnhook = SP_CLEANUP
iComplaintCount = 0
bFranklinPushMuttered = FALSE // Has Franklin muttered about needing to move the broken down car
bBarryCalledAboutTruck = FALSE // Has Barry called player suggesting tow truck
bFranklinTruckMuttered = FALSE // Has Franklin muttered about needing to jack a truck
bDeliveryCallTriggered = FALSE
MISSION_OBJECTIVE_EXPIRE(MO_B3CENTV) // Get in the ~b~stash car.~s~
MISSION_OBJECTIVE_RESET(MO_B3CDELV) // Go to Barry's ~y~apartment.~s~
MISSION_OBJECTIVE_RESET(MO_B3CWAN1) // Lose the cops.
MISSION_OBJECTIVE_RESET(MO_B3CNOGO) // Find a way to move the stash car.
MISSION_OBJECTIVE_RESET(MO_B3CREVRS) // Hook the ~b~stash car.~s~
MISSION_OBJECTIVE_RESET(MO_B3CLEAVE) // Leave the area
MISSION_OBJECTIVE_RESET(MO_B3CRTTT) // Get back in the ~b~tow truck.~s~
MISSION_OBJECTIVE_RESET(MO_B3CGBTB) // The ~b~stash car~s~ has broken loose, hook it with the tow truck.
MISSION_OBJECTIVE_RESET(MO_B3CGBTB) // Rehook the ~b~stash car~s~.
// If we are checkpointing need to wait for text
WHILE NOT HAS_ADDITIONAL_TEXT_LOADED(MISSION_TEXT_SLOT)
WAIT(0)
ENDWHILE
ENDPROC
#ENDIF
/// PURPOSE:
/// Skip to start of towing section
PROC SKIP_START_TOWING_SECTION(BOOL bIsCheckPoint = FALSE)
CPRINTLN(DEBUG_MISSION, "DEBUG SKIP ::: skip to start of tow in barry3c")
// Need to determine the truck coordinates before we can do the load wait
IF bIsCheckPoint
IF IS_REPLAY_CHECKPOINT_VEHICLE_AVAILABLE()
truckSkipModel = GET_REPLAY_CHECKPOINT_VEHICLE_MODEL()
// Only towtrucks and cargobobs are valid for this checkpoint, so change invalid vehicle types to be TOWTRUCK
IF truckSkipModel <> TOWTRUCK2
AND truckSkipModel <> CARGOBOB
AND truckSkipModel <> CARGOBOB2
AND truckSkipModel <> CARGOBOB3
truckSkipModel = TOWTRUCK
ENDIF
ELSE
truckSkipModel = TOWTRUCK
ENDIF
START_REPLAY_SETUP(stStashCar.location, stStashCar.heading)
ENDIF
// Get spawn coordinates for truck
IF truckSkipModel = TOWTRUCK
CPRINTLN(DEBUG_MISSION, "Spawning truck at position for TOWTRUCK")
vecRespawnTruck = << -462.0807, -1711.6804, 17.6454 >>
fRespawnTruck = 277.92
ELIF truckSkipModel = TOWTRUCK2
CPRINTLN(DEBUG_MISSION, "Spawning truck at position for TOWTRUCK2")
vecRespawnTruck = << -463.5672, -1712.2842, 17.6392 >>
fRespawnTruck = 272.29
ELIF truckSkipModel = CARGOBOB OR truckSkipModel = CARGOBOB2 OR truckSkipModel = CARGOBOB3
CPRINTLN(DEBUG_MISSION, "Spawning cargobob at position for CARGOBOB")
vecRespawnTruck = <<-455.4628, -1712.2817, 17.6420>>
fRespawnTruck = 0.7
ENDIF
IF bIsCheckPoint
START_REPLAY_SETUP(vecRespawnTruck, fRespawnTruck)
ELSE
// If player is in the stash car get them out of it so it can be deleted
IF IS_PED_IN_VEHICLE(PLAYER_PED_ID(), stStashCar.vehicle)
SET_ENTITY_COORDS(PLAYER_PED_ID(), stStashCar.location)
ENDIF
ENDIF
SKIP_CLEAR_ALL_MISSION_OBJECTIVES()
SKIP_CLEAR_WANTED()
SAFE_REMOVE_BLIP(biGotoBlip)
// Progression stuff
mStage = MS_STAGE_RETURN_VEHICLE
sProgress = SP_SETUP
// Clear up towtruck(s)
FOR iCount = 0 TO NUM_HELPER_TRUCKS-1
SAFE_DELETE_VEHICLE(stTruck[iCount].vehicle)
ENDFOR
SET_VEHICLE_MODEL_IS_SUPPRESSED(TOWTRUCK, TRUE)
// Reset Franklin's unhook complaints
spFranklinUnhook = SP_CLEANUP
iComplaintCount = 0
bFranklinPushMuttered = TRUE // Has Franklin muttered about needing to move the broken down car
bBarryCalledAboutTruck = TRUE // Has Barry called player suggesting tow truck
bFranklinTruckMuttered = TRUE // Has Franklin muttered about needing to jack a truck
bDeliveryCallTriggered = FALSE
MISSION_OBJECTIVE_EXPIRE(MO_B3CENTV) // Get in the ~b~stash car.~s~
MISSION_OBJECTIVE_RESET(MO_B3CDELV) // Go to Barry's ~y~apartment.~s~
MISSION_OBJECTIVE_RESET(MO_B3CWAN1) // Lose the cops.
MISSION_OBJECTIVE_EXPIRE(MO_B3CNOGO) // Find a way to move the stash car.
MISSION_OBJECTIVE_EXPIRE(MO_B3CREVRS) // Hook the ~b~stash car.~s~
MISSION_OBJECTIVE_RESET(MO_B3CLEAVE) // Leave the area
MISSION_OBJECTIVE_RESET(MO_B3CRTTT) // Get back in the ~b~tow truck.~s~
MISSION_OBJECTIVE_RESET(MO_B3CRTCB) // Get back in the ~b~cargobob.~s~
MISSION_OBJECTIVE_RESET(MO_B3CGBTB) // The ~b~stash car~s~ has broken loose, hook it with the tow truck.
MISSION_OBJECTIVE_RESET(MO_B3CGBTB) // Rehook the ~b~stash car~s~.
// Remake the stash car
SKIP_RESPAWN_STASH_CAR(stStashCar.location, stStashCar.heading)
IF bIsCheckpoint
SKIP_RESPAWN_TRUCK(vecRespawnTruck, fRespawnTruck, FALSE)
// Reattach car to truck
IF IS_ENTITY_ALIVE(vehTowTruck)
AND truckSkipModel = TOWTRUCK
SET_VEHICLE_TOW_TRUCK_ARM_POSITION(vehTowTruck, 0.0)
ENDIF
WHILE NOT HAS_ADDITIONAL_TEXT_LOADED(MISSION_TEXT_SLOT)
WAIT(0)
ENDWHILE
END_REPLAY_SETUP(vehTowTruck, VS_DRIVER, FALSE)
ELSE
SKIP_RESPAWN_TRUCK(vecRespawnTruck, fRespawnTruck, TRUE)
// Reattach car to truck
IF IS_ENTITY_ALIVE(vehTowTruck)
AND truckSkipModel = TOWTRUCK
SET_VEHICLE_TOW_TRUCK_ARM_POSITION(vehTowTruck, 0.0)
ENDIF
ENDIF
// Wait until car is hooked - on checkpoints this check won't work before player is in truck and it's placed
IF truckSkipModel = TOWTRUCK OR truckSkipModel = TOWTRUCK2
WHILE NOT IS_STASH_CAR_HOOKED()
CPRINTLN(DEBUG_MISSION, "DEBUG SKIP::: Waiting until car is attached to truck...")
WAIT(0)
ENDWHILE
ENDIF
SET_REPLAY_MID_MISSION_STAGE_WITH_NAME(CP_START_TOW, "Start of towing stage")
ENDPROC
#IF IS_DEBUG_BUILD
/// PURPOSE:
/// DEBUG SKIP - Warp near to ending
PROC SKIP_WARP_NEAR_END()
CPRINTLN(DEBUG_MISSION, "DEBUG SKIP ::: warp near delivery location")
SKIP_CLEAR_ALL_MISSION_OBJECTIVES()
SKIP_CLEAR_WANTED()
SAFE_REMOVE_BLIP(biGotoBlip)
// Progression stuff
mStage = MS_STAGE_RETURN_VEHICLE
sProgress = SP_SETUP
// Clear up towtruck(s)
FOR iCount = 0 TO NUM_HELPER_TRUCKS-1
IF DOES_ENTITY_EXIST(stTruck[iCount].vehicle)
SAFE_DELETE_VEHICLE(stTruck[iCount].vehicle)
ENDIF
ENDFOR
SET_VEHICLE_MODEL_IS_SUPPRESSED(TOWTRUCK, TRUE)
// Teleport player out of vehicle, recreate it
IF truckSkipModel = TOWTRUCK
CPRINTLN(DEBUG_MISSION, "truckSkipModel = TOWTRUCK - respawning")
SKIP_RESPAWN_TRUCK(<< -1050.8541, -1267.1842, 5.2005 >>, 119.77)
ELIF truckSkipModel = TOWTRUCK2
CPRINTLN(DEBUG_MISSION, "truckSkipModel = TOWTRUCK2 - respawning")
SKIP_RESPAWN_TRUCK(<< -1049.7117, -1266.5262, 5.2119 >>, 120.05)
ELIF truckSkipModel = CARGOBOB OR truckSkipModel = CARGOBOB2 OR truckSkipModel = CARGOBOB3
CPRINTLN(DEBUG_MISSION, "truckSkipModel is a cargobob - respawning")
SKIP_RESPAWN_TRUCK(<<-1074.1339, -1250.2921, 4.5293>>, 199.5)
ELSE
CPRINTLN(DEBUG_MISSION, "truckSkipModel wasn't a known type - respawning a towtruck")
truckSkipModel = TOWTRUCK
SKIP_RESPAWN_TRUCK(<< -1050.8541, -1267.1842, 5.2005 >>, 119.77)
ENDIF
// Remake the stash car
SKIP_RESPAWN_STASH_CAR(<< -1045.25, -1263.94, 5.75 >>, 119.5)
WAIT(0)
// Reattach car to truck
IF truckSkipModel = TOWTRUCK
AND IS_ENTITY_ALIVE(vehTowTruck)
SET_VEHICLE_TOW_TRUCK_ARM_POSITION(vehTowTruck, 0.0)
ENDIF
// Reset Franklin's unhook complaints
spFranklinUnhook = SP_CLEANUP
iComplaintCount = 0
bFranklinPushMuttered = TRUE // Has Franklin muttered about needing to move the broken down car
bBarryCalledAboutTruck = TRUE // Has Barry called player suggesting tow truck
bFranklinTruckMuttered = TRUE // Has Franklin muttered about needing to jack a truck
bDeliveryCallTriggered = FALSE
MISSION_OBJECTIVE_EXPIRE(MO_B3CENTV) // Get in the ~b~stash car.~s~
MISSION_OBJECTIVE_EXPIRE(MO_B3CDELV) // Go to Barry's ~y~apartment.~s~
MISSION_OBJECTIVE_RESET(MO_B3CWAN1) // Lose the cops.
MISSION_OBJECTIVE_EXPIRE(MO_B3CNOGO) // Find a way to move the stash car.
MISSION_OBJECTIVE_EXPIRE(MO_B3CREVRS) // Hook the ~b~stash car.~s~
MISSION_OBJECTIVE_RESET(MO_B3CLEAVE) // Leave the area
MISSION_OBJECTIVE_RESET(MO_B3CRTTT) // Get back in the ~b~tow truck.~s~
MISSION_OBJECTIVE_RESET(MO_B3CRTCB) // Get back in the ~b~cargobob.~s~
MISSION_OBJECTIVE_RESET(MO_B3CGBTB) // The ~b~stash car~s~ has broken loose, hook it with the tow truck.
MISSION_OBJECTIVE_RESET(MO_B3CGBTB) // Rehook the ~b~stash car~s~.
// Wait until car is hooked
IF truckSkipModel = TOWTRUCK OR truckSkipModel = TOWTRUCK2
WHILE NOT IS_STASH_CAR_HOOKED()
CPRINTLN(DEBUG_MISSION, "DEBUG SKIP::: Waiting until car is attached to truck...")
WAIT(0)
ENDWHILE
ENDIF
ENDPROC
#ENDIF
/// PURPOSE:
/// DEBUG SKIP/CHECKPOINT - to leave the area stage
PROC SKIP_TRIGGER_DELIVERY(BOOL bIsACheckpoint = FALSE)
CPRINTLN(DEBUG_MISSION, "DEBUG SKIP ::: trigger delivery event")
IF bIsACheckpoint
IF IS_REPLAY_CHECKPOINT_VEHICLE_AVAILABLE()
truckSkipModel = GET_REPLAY_CHECKPOINT_VEHICLE_MODEL()
// Only towtrucks and cargobobs are valid for this checkpoint, so change vehicle types apart from TOWTRUCK2 to be TOWTRUCK
IF truckSkipModel <> TOWTRUCK2
AND truckSkipModel <> CARGOBOB
AND truckSkipModel <> CARGOBOB2
AND truckSkipModel <> CARGOBOB3
truckSkipModel = TOWTRUCK
ENDIF
ELSE
truckSkipModel = TOWTRUCK
ENDIF
IF truckSkipModel = TOWTRUCK OR truckSkipModel = TOWTRUCK2
START_REPLAY_SETUP(<<-1154.2244, -1234.3102, 5.7174>>, 12.45)
ELSE
// Cargobob on garage roof
START_REPLAY_SETUP(<<-1148.1831, -1227.0050, 8.4468>>, 19.2)
ENDIF
ENDIF
SKIP_CLEAR_ALL_MISSION_OBJECTIVES()
SKIP_CLEAR_WANTED()
SAFE_REMOVE_BLIP(biGotoBlip)
// Progression stuff
// Checkpoint won't replay the phonecall - but if the player has shitskipped they should get the call
IF bIsACheckpoint
AND NOT g_bShitskipAccepted
bDeliveryCallTriggered = TRUE // Skip phone call
mStage = MS_STAGE_LEAVE
ELSE
bDeliveryCallTriggered = FALSE
iCallDelayTimer = GET_GAME_TIMER() + 3000
mStage = MS_STAGE_DELIVERY_PHONE_CALL
ENDIF
sProgress = SP_SETUP
// Clear up towtruck(s)
FOR iCount = 0 TO NUM_HELPER_TRUCKS-1
IF DOES_ENTITY_EXIST(stTruck[iCount].vehicle)
SAFE_DELETE_VEHICLE(stTruck[iCount].vehicle)
ENDIF
ENDFOR
SET_VEHICLE_MODEL_IS_SUPPRESSED(TOWTRUCK, TRUE)
bFranklinPushMuttered = TRUE // Has Franklin muttered about needing to move the broken down car
bBarryCalledAboutTruck = TRUE // Has Barry called player suggesting tow truck
bFranklinTruckMuttered = TRUE // Has Franklin muttered about needing to jack a truck
MISSION_OBJECTIVE_EXPIRE(MO_B3CENTV) // Get in the ~b~stash car.~s~
MISSION_OBJECTIVE_EXPIRE(MO_B3CDELV) // Go to Barry's ~y~apartment.~s~
MISSION_OBJECTIVE_RESET(MO_B3CWAN1) // Lose the cops.
MISSION_OBJECTIVE_EXPIRE(MO_B3CNOGO) // Get the car to Barry's apartment.
MISSION_OBJECTIVE_EXPIRE(MO_B3CREVRS) // Hook the ~b~stash car~s~ with the tow truck.
MISSION_OBJECTIVE_RESET(MO_B3CLEAVE) // Leave the area
MISSION_OBJECTIVE_RESET(MO_B3CRTTT) // Get back in the ~b~tow truck.~s~
MISSION_OBJECTIVE_RESET(MO_B3CRTCB) // Get back in the ~b~cargobob.~s~
MISSION_OBJECTIVE_RESET(MO_B3CGBTB) // The ~b~stash car~s~ has broken loose, hook it with the tow truck.
MISSION_OBJECTIVE_RESET(MO_B3CGBTB) // Rehook the ~b~stash car~s~.
// Remake the stash car - not attatched to truck
SKIP_RESPAWN_STASH_CAR(<< -1151.36, -1243.57, 6.52 >>, 25.18)
IF bIsACheckpoint
// Teleport player out of vehicle, recreate it
IF truckSkipModel = TOWTRUCK OR truckSkipModel = TOWTRUCK2
SKIP_RESPAWN_TRUCK(<<-1154.2244, -1234.3102, 5.7174>>, 12.45, FALSE)
ELSE
// Cargobob on garage roof
SKIP_RESPAWN_TRUCK(<<-1148.1831, -1227.0050, 8.4468>>, 19.2, FALSE)
ENDIF
WHILE NOT HAS_ADDITIONAL_TEXT_LOADED(MISSION_TEXT_SLOT)
WAIT(0)
ENDWHILE
END_REPLAY_SETUP(vehTowTruck, VS_DRIVER, FALSE)
ELSE
// Teleport player out of vehicle, recreate it
IF truckSkipModel = TOWTRUCK OR truckSkipModel = TOWTRUCK2
SKIP_RESPAWN_TRUCK(<<-1154.2244, -1234.3102, 5.7174>>, 12.45)
ELSE
// Cargobob on garage roof
SKIP_RESPAWN_TRUCK(<<-1148.1831, -1227.0050, 8.4468>>, 19.2)
ENDIF
ENDIF
SET_REPLAY_MID_MISSION_STAGE_WITH_NAME(CP_DELIVERY, "Delivered vehicle", TRUE)
ENDPROC
/// PURPOSE:
/// DEBUG SKIP - Trigger the completion
PROC SKIP_MISSION_COMPLETE(BOOL bIsACheckpoint = FALSE)
CPRINTLN(DEBUG_MISSION, "DEBUG SKIP ::: Trigger mission complete")
IF bIsACheckpoint
IF IS_REPLAY_CHECKPOINT_VEHICLE_AVAILABLE()
truckSkipModel = GET_REPLAY_CHECKPOINT_VEHICLE_MODEL()
// Only towtrucks and cargobobs are valid for this checkpoint, so change vehicle types apart from TOWTRUCK2 to be TOWTRUCK
IF truckSkipModel <> TOWTRUCK2
AND truckSkipModel <> CARGOBOB
AND truckSkipModel <> CARGOBOB2
AND truckSkipModel <> CARGOBOB3
truckSkipModel = TOWTRUCK
ENDIF
ELSE
truckSkipModel = TOWTRUCK
ENDIF
// Start the load
IF truckSkipModel = TOWTRUCK OR truckSkipModel = TOWTRUCK2
START_REPLAY_SETUP(<< -1237.9617, -1035.1941, 7.2466 >>, 110.0)
ELSE
START_REPLAY_SETUP(<<-1074.1339, -1250.2921, 4.5293>>, 199.5)
ENDIF
ENDIF
SKIP_CLEAR_ALL_MISSION_OBJECTIVES()
SKIP_CLEAR_WANTED()
SAFE_REMOVE_BLIP(biGotoBlip)
// Progression stuff
mStage = MS_STAGE_LEAVE
sProgress = SP_SETUP
MISSION_OBJECTIVE_EXPIRE(MO_B3CENTV) // Get in the ~b~stash car.~s~
MISSION_OBJECTIVE_EXPIRE(MO_B3CDELV) // Go to Barry's ~y~apartment.~s~
MISSION_OBJECTIVE_EXPIRE(MO_B3CWAN1) // Lose the cops.
MISSION_OBJECTIVE_EXPIRE(MO_B3CNOGO) // Find a way to move the stash car.
MISSION_OBJECTIVE_EXPIRE(MO_B3CREVRS) // Hook the ~b~stash car~s~ with the tow truck.
MISSION_OBJECTIVE_EXPIRE(MO_B3CLEAVE) // Leave the area
MISSION_OBJECTIVE_EXPIRE(MO_B3CRTTT) // Get back in the ~b~tow truck.~s~
MISSION_OBJECTIVE_EXPIRE(MO_B3CRTCB) // Get back in the ~b~tow truck.~s~
MISSION_OBJECTIVE_EXPIRE(MO_B3CGBTB) // The ~b~stash car~s~ has broken loose, hook it with the tow truck.
MISSION_OBJECTIVE_EXPIRE(MO_B3CGBTB) // Rehook the ~b~stash car~s~.
// Remake the stash car - at drop-off location
SKIP_RESPAWN_STASH_CAR(<< -1151.36, -1243.57, 6.52 >>, 25.18)
IF bIsACheckpoint
// Spawn vehicle
IF truckSkipModel = TOWTRUCK OR truckSkipModel = TOWTRUCK2
SKIP_RESPAWN_TRUCK(<< -1237.9617, -1035.1941, 7.2466 >>, 110.0, FALSE)
ELSE
SKIP_RESPAWN_TRUCK(<<-1074.1339, -1250.2921, 4.5293>>, 199.5, FALSE)
ENDIF
WHILE NOT HAS_ADDITIONAL_TEXT_LOADED(MISSION_TEXT_SLOT)
WAIT(0)
ENDWHILE
END_REPLAY_SETUP(vehTowTruck, VS_DRIVER, FALSE)
ELSE
// Teleport player out of vehicle, recreate it
IF truckSkipModel = TOWTRUCK OR truckSkipModel = TOWTRUCK2
SKIP_RESPAWN_TRUCK(<< -1237.9617, -1035.1941, 7.2466 >>, 110.0)
ELSE
SKIP_RESPAWN_TRUCK(<<-1074.1339, -1250.2921, 4.5293>>, 199.5)
ENDIF
ENDIF
SAFE_FADE_SCREEN_IN_FROM_BLACK() // Screen needs to be fully faded back in before the mission complete GUI stuff will display
ENDPROC
#IF IS_DEBUG_BUILD
/// PURPOSE:
/// Debug skip forward
PROC SKIP_FORWARD()
RC_START_Z_SKIP()
SWITCH mStage
CASE MS_STAGE_ENTER_STASH_CAR
SKIP_TO_START_CAR()
BREAK
CASE MS_STAGE_START_STASH_CAR
CASE MS_STAGE_CALL_BARRY
CASE MS_STAGE_FIND_TOWTRUCK
CASE MS_STAGE_TOW_VEHICLE
SKIP_START_TOWING_SECTION()
BREAK
CASE MS_STAGE_RETURN_VEHICLE
CASE MS_STAGE_GET_TRUCK_BACK
CASE MS_STAGE_REATTACH_VEHICLE
// Check whether we're already close to end
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
IF GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), vecApartment) < 200
SKIP_TRIGGER_DELIVERY()
ELSE
SKIP_WARP_NEAR_END()
ENDIF
ENDIF
BREAK
CASE MS_STAGE_DELIVERY_PHONE_CALL
CASE MS_STAGE_LEAVE
SKIP_MISSION_COMPLETE()
BREAK
ENDSWITCH
RC_END_Z_SKIP()
ENDPROC
/// PURPOSE:
/// Skips backward
PROC SKIP_BACKWARD()
RC_START_Z_SKIP()
SWITCH mStage
CASE MS_STAGE_ENTER_STASH_CAR
CASE MS_STAGE_START_STASH_CAR
SKIP_TO_MS_INIT()
BREAK
CASE MS_STAGE_CALL_BARRY
CASE MS_STAGE_FIND_TOWTRUCK
CASE MS_STAGE_TOW_VEHICLE
SKIP_TO_START_CAR()
BREAK
CASE MS_STAGE_RETURN_VEHICLE
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
IF GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), stStashCar.location) < 10
SKIP_TO_START_CAR()
ELSE
SKIP_START_TOWING_SECTION()
ENDIF
ENDIF
BREAK
CASE MS_STAGE_GET_TRUCK_BACK
CASE MS_STAGE_REATTACH_VEHICLE
SKIP_START_TOWING_SECTION()
BREAK
CASE MS_STAGE_UNHOOK_VEHICLE
CASE MS_STAGE_DELIVERY_PHONE_CALL
SKIP_WARP_NEAR_END()
BREAK
CASE MS_STAGE_LEAVE
SKIP_TRIGGER_DELIVERY()
BREAK
ENDSWITCH
RC_END_Z_SKIP()
ENDPROC
/// PURPOSE:
/// Handle Z-skips and checkpoints
PROC DO_Z_SKIP(INT iZSkip)
RC_START_Z_SKIP()
eTargetStage = INT_TO_ENUM(MISSION_SKIP_STAGE, iZSkip)
// Checkpoints
IF eTargetStage = MSS_RESTART
SKIP_TO_MS_INIT()
ELIF eTargetStage = MSS_IN_CAR
SKIP_TO_START_CAR()
ELIF eTargetStage = MSS_CALL_SKIP
SKIP_TO_AFTER_CALL()
ELIF eTargetStage = MSS_TOWING
SKIP_START_TOWING_SECTION()
ELIF eTargetStage = MSS_WARP_NEAR_END
SKIP_WARP_NEAR_END()
ELIF eTargetStage = MSS_DELIVERY
SKIP_TRIGGER_DELIVERY()
ELIF eTargetStage = MSS_MISSION_COMPLETE
SKIP_MISSION_COMPLETE()
ENDIF
RC_END_Z_SKIP()
ENDPROC
#ENDIF
// ===========================================================================================================
// Termination
// ===========================================================================================================
// -----------------------------------------------------------------------------------------------------------
// Script Cleanup
// -----------------------------------------------------------------------------------------------------------
PROC Script_Cleanup()
// If the mission was triggered then additional mission cleanup will be required.
IF (Random_Character_Cleanup_If_Triggered())
CPRINTLN(DEBUG_MISSION, "...Random Character Script was triggered so additional cleanup required")
ENDIF
#IF IS_DEBUG_BUILD
// Widgets
IF DOES_WIDGET_GROUP_EXIST(widgetGroup)
DELETE_WIDGET_GROUP(widgetGroup)
ENDIF
#ENDIF
// Return wanted level to normal
SET_WANTED_LEVEL_MULTIPLIER(1.0)
RC_CleanupSceneEntities(sRCLauncherDataLocal)
REMOVE_SCENARIO_BLOCKING_AREA(mScenarioBlocker)
REMOVE_SCENARIO_BLOCKING_AREA(sbCarPark[0])
REMOVE_SCENARIO_BLOCKING_AREA(sbCarPark[1])
SET_GPS_DISABLED_ZONE(<< 0, 0, 0 >>, << 0, 0, 0 >>)
COLLECT_AREA_CLEANUP()
SET_INSTANCE_PRIORITY_HINT(INSTANCE_HINT_NONE)
TERMINATE_THIS_THREAD()
ENDPROC
// -----------------------------------------------------------------------------------------------------------
// Script Pass
// -----------------------------------------------------------------------------------------------------------
PROC Script_Passed()
Random_Character_Passed(CP_RAND_C_BAR3,FALSE)
Script_Cleanup()
ENDPROC
//*************************************************************************************************************************************************
//
// DATA SETUP
//
//*************************************************************************************************************************************************
/// PURPOSE:
/// Setup initial data and entity/variable states
PROC DATA_INIT()
// Note: This proc is called before the main loop, you must do dead checks!
SET_WANTED_LEVEL_MULTIPLIER(0.2) // Reduced from 0.5 - B*1164227
SET_GPS_DISABLED_ZONE(<< -1188.4091, -1233.0059, 0.0 >>, << -1165.7822, -1214.3778, 15.0 >>)
REQUEST_ADDITIONAL_TEXT("BARR3C", MISSION_TEXT_SLOT)
vecApartment = << -1152.4301, -1238.8237, 5.9752 >>
mScenarioBlocker = Barry3C_Scenario_Blocker()
sbCarPark[0] = ADD_SCENARIO_BLOCKING_AREA(<< -1156.9, -1274.0, 0.0 >>, << -1141.5, -1239.6, 8.0 >>)
sbCarPark[1] = ADD_SCENARIO_BLOCKING_AREA(<< -1177.0, -1292.0, 0.0 >>, << -1160.0, -1273.3, 8.0 >>)
// Stash vehicle info
stStashCar.modelName = EMPEROR2
stStashCar.location = << -468.90, -1713.06, 18.21 >>
stStashCar.heading = -76.20
// stTruck[0] = MAKE_TOWTRUCK_SPAWN(<< -587.61, -1637.06, 18.88 >>, 240.9)
stTruck[0] = MAKE_TOWTRUCK_SPAWN(<< -552.67, -1698.84, 18.16 >>, 205.7) // Made position more obvious - B*1165092
stTruck[1] = MAKE_TOWTRUCK_SPAWN(<< -317.14, -1540.72, 26.67 >>, 336.5)
stTruck[2] = MAKE_TOWTRUCK_SPAWN(<< -104.41, -1984.91, 17.02 >>, 171.6)
stTruck[3] = MAKE_TOWTRUCK_SPAWN(<< -586.69, -1774.59, 21.67 >>, 145.8)
stTruck[4] = MAKE_TOWTRUCK_SPAWN(<< -1207.90, -1334.87, 3.77 >>, 204.1)
stTruck[5] = MAKE_TOWTRUCK_SPAWN(<< -1253.67, -1210.30, 6.03 >>, 10.7)
stTruck[INITIAL_SCENE_TRUCK] = MAKE_TOWTRUCK_SPAWN(<< -426.56, -1717.89, 18.20 >>, 43.5) // HELPER TRUCK FROM INITIAL SCENE - BE CAREFUL IF YOU HAVE TO MESS WITH THIS!
stTruck[7] = MAKE_TOWTRUCK_SPAWN(<< 401.64, -1633.30, 28.29 >>, 231.5) // Towing compound
IF IS_ENTITY_ALIVE(stStashCar.vehicle)
SET_VEHICLE_CAN_LEAK_OIL(stStashCar.vehicle, FALSE)
SET_VEHICLE_CAN_LEAK_PETROL(stStashCar.vehicle, FALSE)
SET_VEHICLE_UNDRIVEABLE(stStashCar.vehicle, TRUE)
SET_VEHICLE_HAS_STRONG_AXLES(stStashCar.vehicle, TRUE)
ENDIF
REQUEST_MODEL(TOWTRUCK)
REQUEST_ANIM_DICT(sIgnitionAnims)
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
ADD_PED_FOR_DIALOGUE(mConversationStruct, 1, PLAYER_PED_ID(), "FRANKLIN")
ENDIF
ADD_PED_FOR_DIALOGUE(mConversationStruct, 3, NULL, "BARRY")
#IF IS_DEBUG_BUILD
mSkipMenu[0].sTxtLabel = "Restart"
mSkipMenu[1].sTxtLabel = "Trying to start car"
mSkipMenu[2].sTxtLabel = "Skip after initial phone call"
mSkipMenu[3].sTxtLabel = "Start towing section (CP1)"
mSkipMenu[4].sTxtLabel = "Warp near end"
mSkipMenu[5].sTxtLabel = "Delivered vehicle (CP2)"
mSkipMenu[6].sTxtLabel = "Mission Complete"
IF NOT DOES_WIDGET_GROUP_EXIST(widgetGroup)
widgetGroup = START_WIDGET_GROUP("Barry 3C")
ADD_WIDGET_BOOL("Cheat the car location for cargobob", bDebugCheatCarLocation)
ADD_WIDGET_BOOL("Toggle STASH_CAR_STARTFAIL_HANDLER debug spew", bDebugCarStartSpew)
ADD_WIDGET_VECTOR_SLIDER("Stash prop offset", vecStashOffset, -4.0, 4.0, 0.05)
ADD_WIDGET_VECTOR_SLIDER("Stash prop rotate", vecStashRotate, -180.0, 180.0, 0.5)
STOP_WIDGET_GROUP()
ENDIF
#ENDIF
// Init tow truck help
bShowedRaiseLowerHelp = FALSE
// Init objectives
STORE_MISSION_OBJECTIVE_DATA()
// Init fail reason
sFailReason = "DEFAULT"
// Setup Franklin's unhook complaint bits
iComplaintCount = 0
STORE_COMPLAINT_STRINGS()
spFranklinUnhook = SP_CLEANUP
// Store dropoff area
vecDropoff[0][0] = << -1161.11, -1217.32, 5.65 >>
vecDropoff[0][1] = << -1147.86, -1251.60, 10.01 >>
fDropoffWidth[0] = 10.5
vecDropoff[1][0] = << -1147.14, -1253.07, 5.65 >>
vecDropoff[1][1] = << -1161.97, -1216.69, 10.98 >>
fDropoffWidth[1] = 12.0
// Silently add Barry as contact in case we've launched from debug menu
ADD_CONTACT_TO_PHONEBOOK(CHAR_BARRY, FRANKLIN_BOOK, FALSE)
// Has the delivery call happened?
bDeliveryCallTriggered = FALSE
SET_GPS_DISABLED_ZONE(<< -1132.88, -1262.01, 0.0 >>, << -1102.43, -1196.58, 15.0 >>)
TOGGLE_CAR_MOD_SHOPS_UNAVAILABLE(TRUE)
ENDPROC
//*************************************************************************************************************************************************
//
// Mission stage procs
//
//*************************************************************************************************************************************************
/// PURPOSE:
/// MISSION STAGE PROC
/// Initial get into car step, check whether the player has arrived with a tow truck
PROC STAGE_ENTER_STASH_CAR()
SWITCH sProgress
CASE SP_SETUP
IF HAS_ADDITIONAL_TEXT_LOADED(MISSION_TEXT_SLOT)
// See if player is wise to what's up and has brought their own ride
IF IS_PLAYER_IN_TOWTRUCK()
CPRINTLN(DEBUG_MISSION, "Player has started mission in towtruck/cargobob")
CHECK_VEHGEN_CREATION()
// Franklin's comment
IF CREATE_CONVERSATION(mConversationStruct, "BAR3CAU", "BAR3C_C2", CONV_PRIORITY_MEDIUM)
// Have they hooked?
IF IS_STASH_CAR_HOOKED()
// Yes - deliver
INFORM_MISSION_STATS_SYSTEM_OF_TIME_WINDOW_OPEN(BA3C_DELIVERY_TIME)
MISSION_OBJECTIVE_EXPIRE(MO_B3CNOGO)
MISSION_OBJECTIVE_EXPIRE(MO_B3CREVRS)
mStage = MS_STAGE_RETURN_VEHICLE
sProgress = SP_SETUP
ELSE
// No - start towing
MISSION_OBJECTIVE_EXPIRE(MO_B3CNOGO)
mStage = MS_STAGE_TOW_VEHICLE
sProgress = SP_SETUP
ENDIF
ENDIF
ELSE
// Blip vehicle and advise player to enter it
biGotoBlip = CREATE_VEHICLE_BLIP(stStashCar.vehicle)
DISPLAY_MISSION_OBJECTIVE(MO_B3CENTV) // Get in the stash car
sProgress = SP_RUNNING
// Request audio bank now
REQUEST_SCRIPT_AUDIO_BANK("BARRY3C_IGNITION_FAIL")
ENDIF
ENDIF
BREAK
CASE SP_RUNNING
// Check for normal progression - player gets in car
IF IS_PED_IN_VEHICLE(PLAYER_PED_ID(), stStashCar.vehicle)
// Player in stash car
sProgress = SP_CLEANUP
// Check for player getting back into a tow truck after mission launch
ELIF IS_PLAYER_IN_TOWTRUCK()
CHECK_VEHGEN_CREATION()
// Franklin's comment
IF CREATE_CONVERSATION(mConversationStruct, "BAR3CAU", "BAR3C_C2", CONV_PRIORITY_MEDIUM)
// Have they hooked?
IF IS_STASH_CAR_HOOKED()
// Yes - deliver
INFORM_MISSION_STATS_SYSTEM_OF_TIME_WINDOW_OPEN(BA3C_DELIVERY_TIME)
MISSION_OBJECTIVE_EXPIRE(MO_B3CNOGO)
MISSION_OBJECTIVE_EXPIRE(MO_B3CREVRS)
mStage = MS_STAGE_RETURN_VEHICLE
sProgress = SP_SETUP
ELSE
// No - start towing
MISSION_OBJECTIVE_EXPIRE(MO_B3CNOGO)
mStage = MS_STAGE_TOW_VEHICLE
sProgress = SP_SETUP
ENDIF
ENDIF
ENDIF
BREAK
CASE SP_CLEANUP
CLEAR_PRINTS()
SAFE_REMOVE_BLIP(biGotoBlip)
mStage = MS_STAGE_START_STASH_CAR
sProgress = SP_SETUP
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE:
/// MISSION STAGE PROC
/// Handles the car not staring sequence
PROC STAGE_START_STASH_CAR()
SWITCH sProgress
CASE SP_SETUP
// Fade in in case we're on a replay
SAFE_FADE_SCREEN_IN_FROM_BLACK()
SET_PLAYER_CONTROL(PLAYER_ID(), FALSE, SPC_LEAVE_CAMERA_CONTROL_ON)
CPRINTLN(DEBUG_MISSION, "Text loaded...")
// Check for shady exactly-this-frame truck entry or other weirdness
IF IS_PLAYER_IN_TOWTRUCK()
CPRINTLN(DEBUG_MISSION, "STAGE_ENTER_STASH_CAR: SP_SETUP: Detected mission start from player hooking car, checking whether it's still attached...")
INFORM_MISSION_STATS_SYSTEM_OF_TIME_WINDOW_OPEN(BA3C_DELIVERY_TIME)
MISSION_OBJECTIVE_EXPIRE(MO_B3CNOGO)
MISSION_OBJECTIVE_EXPIRE(MO_B3CREVRS)
SET_VEHICLE_CAN_LEAK_OIL(stStashCar.vehicle, FALSE)
SET_VEHICLE_CAN_LEAK_PETROL(stStashCar.vehicle, FALSE)
IF IS_STASH_CAR_HOOKED()
// Player is in a truck and hooked up
CPRINTLN(DEBUG_MISSION, "STAGE_ENTER_STASH_CAR: SP_SETUP: ...car still hooked, going to MS_STAGE_RETURN_VEHICLE.")
sProgress = SP_SETUP
mStage = MS_STAGE_RETURN_VEHICLE
ELSE
// Player hooked car but it's already loose!
CPRINTLN(DEBUG_MISSION, "STAGE_ENTER_STASH_CAR: SP_SETUP: ...car already came unhooked, going to MS_STAGE_TOW_VEHICLE.")
sProgress = SP_SETUP
mStage = MS_STAGE_TOW_VEHICLE
ENDIF
ELSE
// Normal flow, player is currently in stash car
CPRINTLN(DEBUG_MISSION, "STAGE_ENTER_STASH_CAR: SP_SETUP: Mission start from player entering stash car, going to SP_RUNNING")
SET_VEHICLE_CAN_LEAK_OIL(stStashCar.vehicle, FALSE)
SET_VEHICLE_CAN_LEAK_PETROL(stStashCar.vehicle, FALSE)
bPlayerWantsOut = FALSE
sceProgress = SCE_ASSETS
sProgress = SP_RUNNING
ENDIF
BREAK
CASE SP_RUNNING
IF NOT bPlayerWantsOut
AND (sceProgress <> SCE_ASSETS) // Ignore exit attempts while we're still loading assets
AND (iIgnitionAttempts > 0 AND iIgnitionAttempts < NUM_IGNITION_ATTEMPTS) // Ignore exit attempts before they've tried engine once, and after the final attempt
AND IS_DISABLED_CONTROL_JUST_PRESSED(PLAYER_CONTROL, INPUT_VEH_EXIT)
CPRINTLN(DEBUG_MISSION, "Player wants out!")
bPlayerWantsOut = TRUE
ENDIF
SWITCH sceProgress
CASE SCE_ASSETS
// Check sounds and assets loaded...
IF REQUEST_SCRIPT_AUDIO_BANK("BARRY3C_IGNITION_FAIL")
AND HAS_ANIM_DICT_LOADED(sIgnitionAnims)
// Don't go on before player is in driver seat
IF GET_PED_IN_VEHICLE_SEAT(stStashCar.vehicle) = PLAYER_PED_ID()
CPRINTLN(DEBUG_MISSION, "STAGE_ENTER_STASH_CAR: SCE_ASSETS: Got assets, starting cutscene...")
IF NOT bStashStuckCheckActive
ADD_VEHICLE_UPSIDEDOWN_CHECK(stStashCar.vehicle)
bStashStuckCheckActive = TRUE
ENDIF
// Set up timer and go on to next step
iIgnitionAttempts = 0
iIgnitionSoundID = GET_SOUND_ID()
sceProgress = SCE_TRIGGER_ANIM
ENDIF
ENDIF
BREAK
CASE SCE_TRIGGER_ANIM
IF GET_PED_IN_VEHICLE_SEAT(stStashCar.vehicle) = PLAYER_PED_ID()
AND IS_PED_SITTING_IN_VEHICLE(PLAYER_PED_ID(), stStashCar.vehicle)
CPRINTLN(DEBUG_MISSION, "STAGE_ENTER_STASH_CAR: SCE_ASSETS: Triggering anim...")
IF iIgnitionAttempts = NUM_IGNITION_ATTEMPTS-1
// Special long attempt then go to annoyance reaction
OPEN_SEQUENCE_TASK(seqCarStart)
TASK_PLAY_ANIM(NULL, sIgnitionAnims, "franklinfailingtostartcar_enter", NORMAL_BLEND_IN, NORMAL_BLEND_OUT, 2000, AF_NOT_INTERRUPTABLE)
TASK_PLAY_ANIM(NULL, sIgnitionAnims, "franklinfailingtostartcar_loop", NORMAL_BLEND_IN, NORMAL_BLEND_OUT, 8000, AF_LOOPING|AF_NOT_INTERRUPTABLE)
TASK_PLAY_ANIM(NULL, sIgnitionAnims, "franklinfailingtostartcar_exit", NORMAL_BLEND_IN, NORMAL_BLEND_OUT, 766, AF_NOT_INTERRUPTABLE)
CLOSE_SEQUENCE_TASK(seqCarStart)
TASK_PERFORM_SEQUENCE(PLAYER_PED_ID(), seqCarStart)
CLEAR_SEQUENCE_TASK(seqCarStart)
iCarEventsTimer = GET_GAME_TIMER() + 2000
sceProgress = SCE_IGNITION_SOUND
ELIF iIgnitionAttempts = NUM_IGNITION_ATTEMPTS-2
IF CREATE_CONVERSATION(mConversationStruct, "BAR3CAU", "BAR3C_C1", CONV_PRIORITY_MEDIUM)
OPEN_SEQUENCE_TASK(seqCarStart)
TASK_PLAY_ANIM(NULL, sIgnitionAnims, "franklinfailingtostartcar_enter", NORMAL_BLEND_IN, NORMAL_BLEND_OUT, 2000, AF_NOT_INTERRUPTABLE)
TASK_PLAY_ANIM(NULL, sIgnitionAnims, "franklinfailingtostartcar_loop", NORMAL_BLEND_IN, NORMAL_BLEND_OUT, 1200+(iIgnitionAttempts*250), AF_LOOPING|AF_NOT_INTERRUPTABLE)
TASK_PLAY_ANIM(NULL, sIgnitionAnims, "franklinfailingtostartcar_exit", NORMAL_BLEND_IN, NORMAL_BLEND_OUT, 766, AF_NOT_INTERRUPTABLE)
CLOSE_SEQUENCE_TASK(seqCarStart)
TASK_PERFORM_SEQUENCE(PLAYER_PED_ID(), seqCarStart)
CLEAR_SEQUENCE_TASK(seqCarStart)
iCarEventsTimer = GET_GAME_TIMER() + 2000
sceProgress = SCE_IGNITION_SOUND
ENDIF
ELSE
OPEN_SEQUENCE_TASK(seqCarStart)
TASK_PLAY_ANIM(NULL, sIgnitionAnims, "franklinfailingtostartcar_enter", NORMAL_BLEND_IN, NORMAL_BLEND_OUT, 2000, AF_NOT_INTERRUPTABLE)
TASK_PLAY_ANIM(NULL, sIgnitionAnims, "franklinfailingtostartcar_loop", NORMAL_BLEND_IN, NORMAL_BLEND_OUT, 1200+(iIgnitionAttempts*250), AF_LOOPING|AF_NOT_INTERRUPTABLE)
TASK_PLAY_ANIM(NULL, sIgnitionAnims, "franklinfailingtostartcar_exit", NORMAL_BLEND_IN, NORMAL_BLEND_OUT, 766, AF_NOT_INTERRUPTABLE)
CLOSE_SEQUENCE_TASK(seqCarStart)
TASK_PERFORM_SEQUENCE(PLAYER_PED_ID(), seqCarStart)
CLEAR_SEQUENCE_TASK(seqCarStart)
iCarEventsTimer = GET_GAME_TIMER() + 2000
sceProgress = SCE_IGNITION_SOUND
ENDIF
ENDIF
BREAK
CASE SCE_IGNITION_SOUND
IF GET_GAME_TIMER() > iCarEventsTimer
IF iIgnitionAttempts = NUM_IGNITION_ATTEMPTS
PLAY_SOUND_FROM_ENTITY(iIgnitionSoundID, "IGNITION_FAIL", stStashCar.vehicle, "BARRY_03_SOUNDSET")
SET_VARIABLE_ON_SOUND(iIgnitionSoundID, "HOLD TIME", 3.0)
iCarEventsTimer = GET_GAME_TIMER() + 9100
ELSE
PLAY_SOUND_FROM_ENTITY(iIgnitionSoundID, "IGNITION_FAIL", stStashCar.vehicle, "BARRY_03_SOUNDSET")
SET_VARIABLE_ON_SOUND(iIgnitionSoundID, "HOLD TIME", (TO_FLOAT(1200+(iIgnitionAttempts*250))/1000.0))
iCarEventsTimer = GET_GAME_TIMER() + (iIgnitionAttempts*250) + 1200 + 766
ENDIF
sceProgress = SCE_WAIT_TO_REPEAT
ENDIF
BREAK
CASE SCE_WAIT_TO_REPEAT
IF GET_GAME_TIMER() > iCarEventsTimer
IF bPlayerWantsOut
sceProgress = SCE_COMMENT
ELSE
iIgnitionAttempts++
IF iIgnitionAttempts = NUM_IGNITION_ATTEMPTS
// We're done - annoyed gesture time
TASK_PLAY_ANIM(PLAYER_PED_ID(), sIgnitionAnims, "franklinfailingtostartcar_slamwheel", INSTANT_BLEND_IN, NORMAL_BLEND_OUT, 3300)
iCarEventsTimer = GET_GAME_TIMER() + 330
sceProgress = SCE_ANNOYED_HORN
ELSE
sceProgress = SCE_TRIGGER_ANIM
ENDIF
ENDIF
ENDIF
BREAK
CASE SCE_ANNOYED_HORN
IF GET_GAME_TIMER() > iCarEventsTimer
START_VEHICLE_HORN(stStashCar.vehicle, 500, GET_HASH_KEY("NORMAL"))
iCarEventsTimer = GET_GAME_TIMER() + 2000
sceProgress = SCE_END
ENDIF
BREAK
CASE SCE_COMMENT
// Comment if player exits car manually
IF IS_PED_SITTING_IN_VEHICLE(PLAYER_PED_ID(), stStashCar.vehicle)
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
CPRINTLN(DEBUG_MISSION, "STAGE_ENTER_STASH_CAR: SP_RUNNING: SCE_COMMENT: Player forcing exit, do shift it comment if not speaking")
IF CREATE_CONVERSATION(mConversationStruct, "BAR3CAU", "BAR3C_C2", CONV_PRIORITY_MEDIUM)
iCarEventsTimer = GET_GAME_TIMER()
sceProgress = SCE_EXIT_CAR
ENDIF
ELSE
iCarEventsTimer = GET_GAME_TIMER()
sceProgress = SCE_EXIT_CAR
ENDIF
ENDIF
BREAK
CASE SCE_EXIT_CAR
IF GET_GAME_TIMER() > iCarEventsTimer
CPRINTLN(DEBUG_MISSION, "STAGE_ENTER_STASH_CAR: SP_RUNNING: SCE_EXIT_CAR: Exit the car")
CLEAR_PED_TASKS(PLAYER_PED_ID())
TASK_LEAVE_VEHICLE(PLAYER_PED_ID(), stStashCar.vehicle)
SET_PLAYER_CONTROL(PLAYER_ID(), TRUE)
sceProgress = SCE_END
ENDIF
BREAK
CASE SCE_END
CPRINTLN(DEBUG_MISSION, "STAGE_ENTER_STASH_CAR: SP_RUNNING: SCE_END: Sequence over")
iCarEventsTimer = GET_GAME_TIMER()
SET_PLAYER_CONTROL(PLAYER_ID(), TRUE)
sProgress = SP_CLEANUP
BREAK
ENDSWITCH
BREAK
CASE SP_CLEANUP
// Delay phone call
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
AND GET_GAME_TIMER() - iCarEventsTimer > 2500
sProgress = SP_SETUP
mStage = MS_STAGE_CALL_BARRY
ENDIF
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE:
/// MISSION STAGE PROC
/// Franklin calls Barry to see what to do about the car
PROC STAGE_CALL_BARRY()
SWITCH sProgress
CASE SP_SETUP
// Init the car startfail handler
bPlayerInStashCar = FALSE
bPlayerWantsOut = FALSE
// Start phone call to Barry
IF PLAYER_CALL_CHAR_CELLPHONE(mConversationStruct, CHAR_BARRY, "BAR3CAU", "BAR3C_NG", CONV_PRIORITY_VERY_HIGH)
CPRINTLN(DEBUG_MISSION, "STAGE_CALL_BARRY: SP_SETUP: Phone call started")
sProgress = SP_RUNNING
ENDIF
BREAK
CASE SP_RUNNING
TRUCK_SPAWNER()
STASH_CAR_STARTFAIL_HANDLER()
// Check for ninja truck acquisition
IF IS_PLAYER_IN_TOWTRUCK()
CHECK_VEHGEN_CREATION()
IF IS_STASH_CAR_HOOKED()
// Expire redundant objectives
MISSION_OBJECTIVE_EXPIRE(MO_B3CNOGO) // Get the vehicle to Barry's apartment.
MISSION_OBJECTIVE_EXPIRE(MO_B3CREVRS) // Hook the stash car
IF GET_PLAYER_WANTED_LEVEL(PLAYER_ID()) < 1
// Go to main driving stage
CPRINTLN(DEBUG_MISSION, "STAGE_CALL_BARRY: SP_RUNNING: Player in truck with car hooked super fast, going to STAGE_RETURN_VEHICLE")
mStage = MS_STAGE_RETURN_VEHICLE
sProgress = SP_SETUP
ELSE
// Wanted!
CPRINTLN(DEBUG_MISSION, "STAGE_CALL_BARRY: SP_RUNNING: Player in truck with car hooked super fast but is wanted, going to STAGE_LOSE_WANTED")
mStage = MS_STAGE_LOSE_WANTED
sProgress = SP_SETUP
ENDIF
ELSE
//Go to tow stage
CPRINTLN(DEBUG_MISSION, "STAGE_CALL_BARRY: SP_RUNNING: Player in truck, still needs to hook car, go to STAGE_TOW_VEHICLE")
mStage = MS_STAGE_TOW_VEHICLE
sProgress = SP_SETUP
// Expire redundant objectives
MISSION_OBJECTIVE_EXPIRE(MO_B3CNOGO) // Get the vehicle to Barry's apartment.
ENDIF
ELIF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
sProgress = SP_CLEANUP
CPRINTLN(DEBUG_MISSION, "STAGE_CALL_BARRY: SP_RUNNING: Phone call completed, going to SP_CLEANUP to show objective after a delay")
ENDIF
BREAK
CASE SP_CLEANUP
IF NOT IS_PLAYER_IN_TOWTRUCK()
CPRINTLN(DEBUG_MISSION, "STAGE_CALL_BARRY: SP_CLEANUP: going on to find tow truck stage.")
STASH_CAR_STARTFAIL_HANDLER()
DISPLAY_MISSION_OBJECTIVE(MO_B3CNOGO) // Get the vehicle to Barry's apartment.
SAFE_REMOVE_BLIP(biGotoBlip)
biGotoBlip = CREATE_VEHICLE_BLIP(stStashCar.vehicle)
bBarryCalledAboutTruck = FALSE
iCallDelayTimer = GET_GAME_TIMER()
sProgress = SP_SETUP
mStage = MS_STAGE_FIND_TOWTRUCK
ELSE
//Go to tow stage
CPRINTLN(DEBUG_MISSION, "STAGE_CALL_BARRY: SP_RUNNING: Player in truck, still needs to hook car, go to STAGE_TOW_VEHICLE")
mStage = MS_STAGE_TOW_VEHICLE
sProgress = SP_SETUP
// Expire redundant objectives
MISSION_OBJECTIVE_EXPIRE(MO_B3CNOGO) // Get the vehicle to Barry's apartment.
ENDIF
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE:
/// MISSION STAGE PROC
/// Find a tow truck
PROC STAGE_FIND_TOWTRUCK()
SWITCH sProgress
// Setup - stay here until player finds a towtruck
CASE SP_SETUP
TRUCK_SPAWNER()
// Check for player in towtruck
IF IS_PLAYER_IN_TOWTRUCK()
// Let's start suppressing the towtruck model now
SET_VEHICLE_MODEL_IS_SUPPRESSED(TOWTRUCK, TRUE)
CHECK_VEHGEN_CREATION()
IF IS_STASH_CAR_HOOKED()
CPRINTLN(DEBUG_MISSION, "STAGE_FIND_TOWTRUCK: SP_SETUP: Player already in towtruck and hooked, going to MS_STAGE_RETURN_VEHICLE")
MISSION_OBJECTIVE_EXPIRE(MO_B3CREVRS)
SAFE_REMOVE_BLIP(biGotoBlip)
bPlayerInTruckLastFrame = TRUE
bBarryCalledAboutTruck = TRUE
mStage = MS_STAGE_RETURN_VEHICLE
sProgress = SP_SETUP
ELSE
CPRINTLN(DEBUG_MISSION, "STAGE_FIND_TOWTRUCK: SP_SETUP: Player got in towtruck, going to SP_RUNNING")
DISPLAY_MISSION_OBJECTIVE(MO_B3CREVRS)
SAFE_REMOVE_BLIP(biGotoBlip)
biGotoBlip = CREATE_VEHICLE_BLIP(stStashCar.vehicle)
bPlayerInTruckLastFrame = TRUE
bBarryCalledAboutTruck = TRUE
sProgress = SP_RUNNING
ENDIF
ELSE
STASH_CAR_STARTFAIL_HANDLER()
// Conversation triggering
// See if we should be triggering Franklin's first comment
IF NOT bFranklinPushMuttered
AND GET_GAME_TIMER() - iCallDelayTimer > PUSH_MUTTER_DELAY
IF CREATE_CONVERSATION(mConversationStruct, "BAR3CAU", "BAR3C_MUTT", CONV_PRIORITY_MEDIUM)
bFranklinPushMuttered = TRUE
ENDIF
// See if we should be triggering call from Barry
ELIF NOT bBarryCalledAboutTruck
AND GET_GAME_TIMER() - iCallDelayTimer > BARRY_CALL_DELAY
IF NOT PLAYER_ABOUT_TO_GET_IN_TOWTRUCK()
IF CHAR_CALL_PLAYER_CELLPHONE_FORCE_ANSWER(mConversationStruct, CHAR_BARRY, "BAR3CAU", "BAR3C_HC", CONV_PRIORITY_MEDIUM)
bBarryCalledAboutTruck = TRUE
ENDIF
ENDIF
// See if we should be triggering Franklin's second comment
ELIF NOT bFranklinTruckMuttered
AND GET_GAME_TIMER() - iCallDelayTimer > TRUCK_MUTTER_DELAY
IF CREATE_CONVERSATION(mConversationStruct, "BAR3CAU", "BAR3C_TOW", CONV_PRIORITY_MEDIUM)
bFranklinTruckMuttered = TRUE
ENDIF
ENDIF
ENDIF
BREAK
// Running - wait for player to reach stash car area
CASE SP_RUNNING
IF bPlayerInTruckLastFrame
// Player currently in truck
// Check for player getting out of the truck
IF NOT IS_PLAYER_IN_TOWTRUCK()
DISPLAY_MISSION_OBJECTIVE(MO_B3CRTTT) // Get back in the towtruck
SAFE_REMOVE_BLIP(biGotoBlip)
biGotoBlip = CREATE_VEHICLE_BLIP(vehTowTruck)
bPlayerInTruckLastFrame = FALSE
// Are they near the stash car yet?
ELIF IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), << -417.58, -1723.81, 15.42 >>, << -473.60, -1705.96, 26.95 >>, 49.0)
sProgress = SP_CLEANUP
// Is player in truck with car hooked - fringe case from mucking about
ELIF IS_STASH_CAR_HOOKED()
CPRINTLN(DEBUG_MISSION, "Stash car hooked in STAGE_FIND_TOWTRUCK without going through angled area - Player may have moved car away from start point or be in cargobob")
sProgress = SP_CLEANUP
ENDIF
// Player not in truck - Have they got back in?
ELIF IS_PLAYER_IN_TOWTRUCK()
CLEAR_MISSION_OBJECTIVE(MO_B3CRTTT)
SAFE_REMOVE_BLIP(biGotoBlip)
biGotoBlip = CREATE_VEHICLE_BLIP(stStashCar.vehicle)
bPlayerInTruckLastFrame = TRUE
ENDIF
STASH_CAR_STARTFAIL_HANDLER()
BREAK
CASE SP_CLEANUP
// Remove blip
CLEAR_PRINTS()
CLEAR_HELP(TRUE)
// Set substage here in case it need to be overridden
sProgress = SP_SETUP
// Change states
IF IS_PLAYER_IN_TOWTRUCK()
// Player in truck - check towing status - VERY unlikely to happen here but best to check
IF IS_STASH_CAR_HOOKED()
// Car is attached - go to main driving stage
INFORM_MISSION_STATS_SYSTEM_OF_TIME_WINDOW_OPEN(BA3C_DELIVERY_TIME)
SET_REPLAY_MID_MISSION_STAGE_WITH_NAME(CP_START_TOW, "Start of towing stage")
mStage = MS_STAGE_RETURN_VEHICLE
ELSE
// Go to intial towing stage
mStage = MS_STAGE_TOW_VEHICLE
ENDIF
bPlayerInTruckLastFrame = TRUE
ENDIF
STASH_CAR_STARTFAIL_HANDLER()
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE:
/// MISSION STAGE PROC
/// Get the tow truck attached to the stash car
PROC STAGE_TOW_VEHICLE()
STASH_CAR_STARTFAIL_HANDLER()
SWITCH sProgress
CASE SP_SETUP
SET_INSTANCE_PRIORITY_HINT(INSTANCE_HINT_DRIVING)
IF bPlayerInTruckLastFrame
// Player is in the truck
// Check whether player has got out of truck
IF NOT IS_PLAYER_IN_TOWTRUCK()
// Player not in truck
CPRINTLN(DEBUG_MISSION, "STAGE_TOW_VEHICLE: SP_SETUP: Player not in tow truck")
DISPLAY_MISSION_OBJECTIVE(MO_B3CRTTT) // Get back in the tow truck
SAFE_REMOVE_BLIP(biGotoBlip)
biGotoBlip = CREATE_VEHICLE_BLIP(vehTowTruck)
ELSE
// See if player has hooked car super fast
IF IS_STASH_CAR_HOOKED()
// Skip through to main driving stage
CPRINTLN(DEBUG_MISSION, "STAGE_TOW_VEHICLE: SP_SETUP: Player in tow truck with car hooked, going to MS_STAGE_RETURN_VEHICLE")
MISSION_OBJECTIVE_EXPIRE(MO_B3CREVRS) // Hook the stash car
bObjectiveNeeded = FALSE
INFORM_MISSION_STATS_SYSTEM_OF_TIME_WINDOW_OPEN(BA3C_DELIVERY_TIME)
SET_REPLAY_MID_MISSION_STAGE_WITH_NAME(CP_START_TOW, "Start of towing stage")
SAFE_REMOVE_BLIP(biGotoBlip)
mStage = MS_STAGE_RETURN_VEHICLE
sProgress = SP_SETUP
ELSE
// OK to go onto running step
CPRINTLN(DEBUG_MISSION, "STAGE_TOW_VEHICLE: SP_SETUP: Player in tow truck, going to SP_RUNNING")
IF GET_PROFILE_SETTING(PROFILE_DISPLAY_SUBTITLES) = 0
OR NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
DISPLAY_MISSION_OBJECTIVE(MO_B3CREVRS) // Hook the stash car
bObjectiveNeeded = FALSE
ELSE
bObjectiveNeeded = TRUE
ENDIF
IF NOT DOES_BLIP_EXIST(biGotoBlip)
biGotoBlip = CREATE_VEHICLE_BLIP(stStashCar.vehicle)
ENDIF
sProgress = SP_RUNNING
ENDIF
ENDIF
ELSE
// Player is on foot
// Check whether player is back in truck
IF IS_PLAYER_IN_TOWTRUCK()
IF NOT DOES_BLIP_EXIST(biGotoBlip)
biGotoBlip = CREATE_VEHICLE_BLIP(stStashCar.vehicle)
ENDIF
bPlayerInTruckLastFrame = TRUE
ENDIF
ENDIF
BREAK
CASE SP_RUNNING
// Display the current tow truck help message
IF NOT bShowedRaiseLowerHelp
AND IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), << -458.11, -1725.30, 17.67 >>, << -456.71, -1701.81, 22.0>>, 17.50)
AND NOT IS_STASH_CAR_HOOKED()
AND NOT TOWTRUCK_IS_ACTUALLY_A_CARGOBOB()
PRINT_HELP("B3CTTHB") // Raise/lower
bShowedRaiseLowerHelp = TRUE
ENDIF
// Check if player has hooked car
IF IS_STASH_CAR_HOOKED()
// Stash car hooked - change state
INFORM_MISSION_STATS_SYSTEM_OF_TIME_WINDOW_OPEN(BA3C_DELIVERY_TIME)
SET_REPLAY_MID_MISSION_STAGE_WITH_NAME(CP_START_TOW, "Start of towing stage")
sProgress = SP_CLEANUP
bShouldPlayUnhookComment = TRUE
// Check for player exiting towttruck
ELIF NOT IS_PLAYER_IN_TOWTRUCK()
// Set commment off, will be weird if player gets back in while car not attached
bShouldPlayUnhookComment = FALSE
// Player got out of truck, change states
sProgress = SP_CLEANUP
// As expected in this step - see if we need the hook objective
ELIF bObjectiveNeeded
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
DISPLAY_MISSION_OBJECTIVE(MO_B3CREVRS) // Hook the stash car
bObjectiveNeeded = FALSE
ENDIF
ENDIF
BREAK
CASE SP_CLEANUP
// Remove blip
SAFE_REMOVE_BLIP(biGotoBlip)
CLEAR_PRINTS()
CLEAR_HELP(TRUE)
// Set substage here in case it need to be overridden
sProgress = SP_SETUP
// Change states
IF IS_PLAYER_IN_TOWTRUCK()
// Car is attached - go to main driving stage
mStage = MS_STAGE_RETURN_VEHICLE
ELSE
// Player got out of truck
mStage = MS_STAGE_GET_TRUCK_BACK
ENDIF
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE:
/// MISSION STAGE PROC
/// Get vehicle to Barry if player has collected it
PROC STAGE_RETURN_VEHICLE()
VECTOR vTmpCar
STASH_CAR_STARTFAIL_HANDLER()
SWITCH sProgress
CASE SP_SETUP
CPRINTLN(DEBUG_MISSION, "STAGE_RETURN_VEHICLE: SP_SETUP")
SAFE_REMOVE_BLIP(biGotoBlip)
biGotoBlip = CREATE_COORD_BLIP(vecApartment)
SET_INSTANCE_PRIORITY_HINT(INSTANCE_HINT_DRIVING)
// Set comment playing bool if all is well
IF IS_STASH_CAR_HOOKED()
bShouldPlayUnhookComment = TRUE
ENDIF
// Check the player's not wanted before displaying objective
IF GET_PLAYER_WANTED_LEVEL(PLAYER_ID()) < 1
// Check whether there are subtitles that might block the objective
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
OR GET_PROFILE_SETTING(PROFILE_DISPLAY_SUBTITLES) = 0
DISPLAY_MISSION_OBJECTIVE(MO_B3CDELV) // Take the vehicle to Barry
bObjectiveNeeded = FALSE
ELSE
bObjectiveNeeded = TRUE
ENDIF
ENDIF
sProgress = SP_RUNNING
BREAK
CASE SP_RUNNING
// Update Franklin complaint conversation in case it's ongoing
FRANKLIN_UNHOOK_COMPLAINT()
// Detect player getting out of tow truck
IF NOT IS_PLAYER_IN_TOWTRUCK()
// Player not in vehicle - change states
sProgress = SP_CLEANUP
// Detect vehicle becoming detatched
ELIF NOT IS_STASH_CAR_HOOKED()
// Stash car unhooked
IF TOWTRUCK_IS_ACTUALLY_A_CARGOBOB()
IF IS_ENTITY_IN_ANGLED_AREA(stStashCar.vehicle, vecDropoff[1][0], vecDropoff[1][1], fDropoffWidth[1], FALSE, FALSE)
CPRINTLN(DEBUG_MISSION, "STAGE_RETURN_VEHICLE: SP_RUNNING: Car unhooked from cargobob, in delivery zone")
IF NOT IS_ENTITY_IN_AIR(stStashCar.vehicle)
CPRINTLN(DEBUG_MISSION, "STAGE_RETURN_VEHICLE: SP_RUNNING: Car not in air")
vTmpCar = GET_ENTITY_COORDS(stStashCar.vehicle)
IF vTmpCar.z < 6.7 // Have to check this in case being hitched on the edge of a roof counts as on ground
// Delivered. Probably with cargobob.
CPRINTLN(DEBUG_MISSION, "STAGE_RETURN_VEHICLE: SP_RUNNING: Car delivered")
SAFE_REMOVE_BLIP(biGotoBlip)
mStage = MS_STAGE_DELIVERY_PHONE_CALL
sProgress = SP_SETUP
ENDIF
ENDIF
ELSE
// - change states
sProgress = SP_CLEANUP
ENDIF
ELSE
// - change states
sProgress = SP_CLEANUP
ENDIF
// Check player isn't wanted
ELIF GET_PLAYER_WANTED_LEVEL(PLAYER_ID()) > 0
// Player wanted - change states
sProgress = SP_CLEANUP
ELIF IS_ENTITY_IN_ANGLED_AREA(stStashCar.vehicle, vecDropoff[0][0], vecDropoff[0][1], fDropoffWidth[0], TRUE)
// Go on to unhook stage and tell player to release vehicle
sProgress = SP_CLEANUP
ELIF bObjectiveNeeded
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
bObjectiveNeeded = FALSE
DISPLAY_MISSION_OBJECTIVE(MO_B3CDELV)
ENDIF
ENDIF
BREAK
CASE SP_CLEANUP
SAFE_REMOVE_BLIP(biGotoBlip)
CLEAR_PRINTS()
sProgress = SP_SETUP
// Change stage
IF NOT IS_PLAYER_IN_TOWTRUCK()
// Get the truck back
mStage = MS_STAGE_GET_TRUCK_BACK
ELIF NOT IS_STASH_CAR_HOOKED()
// Check whether we've delivered
IF TOWTRUCK_IS_ACTUALLY_A_CARGOBOB()
AND IS_ENTITY_IN_ANGLED_AREA(stStashCar.vehicle, vecDropoff[0][0], vecDropoff[0][1], fDropoffWidth[0], FALSE, FALSE)
CPRINTLN(DEBUG_MISSION, "STAGE_RETURN_VEHICLE: SP_RUNNING: Car unhooked, in the 2D area")
IF NOT IS_ENTITY_IN_AIR(stStashCar.vehicle)
CPRINTLN(DEBUG_MISSION, "STAGE_RETURN_VEHICLE: SP_RUNNING: Car not in the air")
vTmpCar = GET_ENTITY_COORDS(stStashCar.vehicle)
IF vTmpCar.z < 6.7 // Have to check this in case being hitched on the edge of a roof counts as on ground
// Delivered. Probably with cargobob.
mStage = MS_STAGE_DELIVERY_PHONE_CALL
ENDIF
ELSE
// Otherwise stay here until we're good
sProgress = SP_CLEANUP
ENDIF
ELSE
// Reattach car
mStage = MS_STAGE_REATTACH_VEHICLE
ENDIF
ELIF IS_ENTITY_IN_ANGLED_AREA(stStashCar.vehicle, vecDropoff[0][0], vecDropoff[0][1], fDropoffWidth[0], FALSE) //IS_ENTITY_IN_RANGE_COORDS(vehTowTruck, vecApartment, 10)
// Go on to car park drop-off stage
mStage = MS_STAGE_UNHOOK_VEHICLE
ELIF GET_PLAYER_WANTED_LEVEL(PLAYER_ID()) > 0
// Lose wanted
mStage = MS_STAGE_LOSE_WANTED
ENDIF
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE:
/// MISSION STAGE PROC
/// Tracks player getting back a tow truck if they abandon it en route to Barry
PROC STAGE_GET_TRUCK_BACK()
STASH_CAR_STARTFAIL_HANDLER()
SWITCH sProgress
CASE SP_SETUP
CPRINTLN(DEBUG_MISSION, "STAGE_GET_TRUCK_BACK: SP_SETUP")
// Blip truck
SAFE_REMOVE_BLIP(biGotoBlip)
IF IS_ENTITY_ALIVE(vehTowTruck)
biGotoBlip = CREATE_VEHICLE_BLIP(vehTowTruck)
SET_BLIP_ROUTE(biGotoBlip, TRUE)
IF GET_PROFILE_SETTING(PROFILE_DISPLAY_SUBTITLES) = 0
OR NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF TOWTRUCK_IS_ACTUALLY_A_CARGOBOB()
DISPLAY_MISSION_OBJECTIVE(MO_B3CRTCB) // Get back in the cargobob
bObjectiveNeeded = FALSE
ELSE
DISPLAY_MISSION_OBJECTIVE(MO_B3CRTTT) // Get back in the tow truck
bObjectiveNeeded = FALSE
ENDIF
ELSE
bObjectiveNeeded = TRUE
ENDIF
sProgress = SP_RUNNING
ELSE
CPRINTLN(DEBUG_MISSION, "STAGE_GET_TRUCK_BACK: Dead truck, dropping to STAGE_REDELIVER")
mStage = MS_STAGE_REDELIVER
ENDIF
BREAK
CASE SP_RUNNING
// Update Franklin complaint conversation in case it's ongoing
FRANKLIN_UNHOOK_COMPLAINT()
// Track player entering towtruck
IF IS_PLAYER_IN_TOWTRUCK()
// Player back in truck - change state
sProgress = SP_CLEANUP
// See if we need to drop to redeliver state due to dead truck
ELIF bDeliveryCallTriggered
AND NOT IS_ENTITY_ALIVE(vehTowTruck)
CPRINTLN(DEBUG_MISSION, "STAGE_GET_TRUCK_BACK: Dead truck, dropping to STAGE_REDELIVER")
SAFE_REMOVE_BLIP(biGotoBlip)
CLEAR_PRINTS()
mStage = MS_STAGE_REDELIVER
sProgress = SP_SETUP
// See if we need the objective
ELIF bObjectiveNeeded
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF TOWTRUCK_IS_ACTUALLY_A_CARGOBOB()
DISPLAY_MISSION_OBJECTIVE(MO_B3CRTCB) // Get back in the cargobob
bObjectiveNeeded = FALSE
ELSE
DISPLAY_MISSION_OBJECTIVE(MO_B3CRTTT) // Get back in the tow truck
bObjectiveNeeded = FALSE
ENDIF
ENDIF
ENDIF
BREAK
CASE SP_CLEANUP
CPRINTLN(DEBUG_MISSION, "STAGE_GET_TRUCK_BACK: SP_CLEANUP")
SAFE_REMOVE_BLIP(biGotoBlip)
CLEAR_PRINTS()
// Is player in truck?
IF IS_PLAYER_IN_TOWTRUCK()
// Check for whether the stash car is attached to the truck
IF IS_STASH_CAR_HOOKED()
// Car hooked - Go to main driving stage unless wanted
IF GET_PLAYER_WANTED_LEVEL(PLAYER_ID()) > 0
// Wanted!
mStage = MS_STAGE_LOSE_WANTED
ELSE
// Not wanted, check if they are in drop-off area
IF IS_ENTITY_IN_ANGLED_AREA(stStashCar.vehicle, vecDropoff[0][0], vecDropoff[0][1], fDropoffWidth[0])
mStage = MS_STAGE_UNHOOK_VEHICLE
ELSE
mStage = MS_STAGE_RETURN_VEHICLE
ENDIF
ENDIF
ELSE
// Car not hooked - get it back
mStage = MS_STAGE_REATTACH_VEHICLE
ENDIF
ENDIF
sProgress = SP_SETUP
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE:
/// MISSION STAGE PROC
/// Vehicle has become detatched before reaching destination
PROC STAGE_REATTACH_VEHICLE()
VECTOR vTmpCar
STASH_CAR_STARTFAIL_HANDLER()
SWITCH sProgress
CASE SP_SETUP
CPRINTLN(DEBUG_MISSION, "STAGE_REATTACH_VEHICLE: SP_SETUP")
IF NOT bStashCarHasComeUnhooked
CPRINTLN(DEBUG_MISSION, "Stash car just came unhooked! No stat check for you!")
bStashCarHasComeUnhooked = TRUE
ENDIF
// Update blip and objective
SAFE_REMOVE_BLIP(biGotoBlip)
// Check that the tow truck is alive in cae we are in post-delivery state
IF IS_ENTITY_ALIVE(vehTowTruck)
biGotoBlip = CREATE_VEHICLE_BLIP(stStashCar.vehicle)
SET_BLIP_ROUTE(biGotoBlip, TRUE)
IF bStashCarHasBeenHooked
DISPLAY_MISSION_OBJECTIVE(MO_B3CGBTB) // Reattach the stash car
ENDIF
// Initialise Franklin unhook conversation tracking
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
AND bShouldPlayUnhookComment
AND NOT IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_VEH_HEADLIGHT) // If key is still held down unhook was deliberate
spFranklinUnhook = SP_SETUP
ENDIF
sProgress = SP_RUNNING
ELSE
// Dead truck
CPRINTLN(DEBUG_MISSION, "STAGE_REATTACH_VEHICLE: Dead truck, dropping to STAGE_REDELIVER")
mStage = MS_STAGE_REDELIVER
ENDIF
BREAK
CASE SP_RUNNING
// Franklin complaint conversation
FRANKLIN_UNHOOK_COMPLAINT()
// See if we need to drop to redeliver state due to dead truck post delivery
IF bDeliveryCallTriggered
AND NOT IS_ENTITY_ALIVE(vehTowTruck)
CPRINTLN(DEBUG_MISSION, "STAGE_REATTACH_VEHICLE: Dead truck, dropping to STAGE_REDELIVER")
SAFE_REMOVE_BLIP(biGotoBlip)
CLEAR_PRINTS()
mStage = MS_STAGE_REDELIVER
sProgress = SP_SETUP
// Detect player getting out of tow truck
ELIF NOT IS_PLAYER_IN_TOWTRUCK()
// Player not in truck - change state
CPRINTLN(DEBUG_MISSION, "STAGE_REATTACH_VEHICLE: Not in truck, going to cleanup")
sProgress = SP_CLEANUP
// Detect reattaching car
ELIF IS_STASH_CAR_HOOKED()
// Got car back - change states
CPRINTLN(DEBUG_MISSION, "STAGE_REATTACH_VEHICLE: In truck and hooked up, going to cleanup")
sProgress = SP_CLEANUP
bShouldPlayUnhookComment = TRUE
// Detect cargobob/shunt delivery
ELIF IS_ENTITY_IN_ANGLED_AREA(stStashCar.vehicle, vecDropoff[0][0], vecDropoff[0][1], fDropoffWidth[0], FALSE, FALSE)
AND NOT IS_ENTITY_IN_AIR(stStashCar.vehicle)
vTmpCar = GET_ENTITY_COORDS(stStashCar.vehicle)
IF vTmpCar.z < 6.7 // Have to check this in case being hitched on the edge of a roof counts as on ground
CPRINTLN(DEBUG_MISSION, "STAGE_REATTACH_VEHICLE: Detatched truck is in delivery area - skipping directly to delivery call")
mStage = MS_STAGE_DELIVERY_PHONE_CALL
sProgress = SP_SETUP
ENDIF
ENDIF
BREAK
CASE SP_CLEANUP
SAFE_REMOVE_BLIP(biGotoBlip)
CLEAR_PRINTS()
// Check player is in truck
IF NOT IS_PLAYER_IN_TOWTRUCK()
// Get the truck back
CPRINTLN(DEBUG_MISSION, "STAGE_REATTACH_VEHICLE: SP_CLEANUP: Going to STAGE_GET_TRUCK_BACK")
mStage = MS_STAGE_GET_TRUCK_BACK
ELSE
// Player is in truck and must have car hitched
CPRINTLN(DEBUG_MISSION, "STAGE_REATTACH_VEHICLE: SP_CLEANUP: Going to STAGE_RETURN_VEHICLE")
mStage = MS_STAGE_RETURN_VEHICLE
ENDIF
sProgress = SP_SETUP
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE:
/// MISSION STAGE PROC
/// Waits for player to unhook the car in the destination car park
PROC STAGE_UNHOOK_VEHICLE()
STASH_CAR_STARTFAIL_HANDLER()
SWITCH sProgress
CASE SP_SETUP
CPRINTLN(DEBUG_MISSION, "STAGE_UNHOOK_VEHICLE: SP_SETUP")
// remove blip
SAFE_REMOVE_BLIP(biGotoBlip)
// Show unhook help
IF NOT bShowedDetachHelp
iHelpTimer = GET_GAME_TIMER()
ENDIF
sProgress = SP_RUNNING
BREAK
CASE SP_RUNNING
// Check if wanted
IF GET_PLAYER_WANTED_LEVEL(PLAYER_ID()) > 0
// Player wanted - change state
CPRINTLN(DEBUG_MISSION, "STAGE_UNHOOK_VEHICLE: SP_RUNNING: Player wanted, go to cleanup")
sProgress = SP_CLEANUP
// Check for player exiting towtruck prematurely
ELIF NOT IS_PED_IN_VEHICLE(PLAYER_PED_ID(), vehTowtruck)
// Player exited vehicle prematurely - change state
CPRINTLN(DEBUG_MISSION, "STAGE_UNHOOK_VEHICLE: SP_RUNNING: Player out of truck, go to cleanup")
sProgress = SP_CLEANUP
// Check if the towed car is attatched, and/or in the car park
ELIF IS_STASH_CAR_HOOKED()
// Still towing, do we need to update objectives?
IF IS_ENTITY_IN_ANGLED_AREA(stStashCar.vehicle, vecDropoff[0][0], vecDropoff[0][1], fDropoffWidth[0])
// Show unhook objective
SAFE_REMOVE_BLIP(biGotoBlip)
// Show unhook help
IF NOT bShowedDetachHelp
IF GET_GAME_TIMER() - iHelpTimer > 1000
PRINT_HELP("B3CTTHA", DEFAULT_HELP_TEXT_TIME+5000) // Press button to release towed thing - Increased time B*1342412
bShowedDetachHelp = TRUE
ENDIF
ENDIF
// Check whether player is dicking about removing vehicle again
ELIF NOT IS_ENTITY_IN_ANGLED_AREA(stStashCar.vehicle, vecDropoff[1][0], vecDropoff[1][1], fDropoffWidth[1])
CPRINTLN(DEBUG_MISSION, "STAGE_UNHOOK_VEHICLE: SP_RUNNING: Car towed out of delivery area, go to redeliver stage")
mStage = MS_STAGE_REDELIVER
sProgress = SP_SETUP
ENDIF
ELSE
// Vehicle is loose - need to check if we're complete or need to rehook
CPRINTLN(DEBUG_MISSION, "STAGE_UNHOOK_VEHICLE: SP_RUNNING: Vehicle loose, go to cleanup")
sProgress = SP_CLEANUP
ENDIF
BREAK
CASE SP_CLEANUP
// Get rid of the unhook objective if it's still on
CLEAR_PRINTS()
CLEAR_HELP(TRUE)
// Check if wanted
IF GET_PLAYER_WANTED_LEVEL(PLAYER_ID()) > 0
// Must lose cops to deliver
mStage = MS_STAGE_LOSE_WANTED
// Check for player exiting towtruck prematurely
ELIF NOT IS_PED_IN_VEHICLE(PLAYER_PED_ID(), vehTowtruck)
// Get back in truck
mStage = MS_STAGE_GET_TRUCK_BACK
// Check for towed car is attatched, and/or in the car park
ELIF NOT IS_VEHICLE_ATTACHED_TO_TOW_TRUCK(vehTowtruck, stStashCar.vehicle)
IF IS_ENTITY_IN_ANGLED_AREA(stStashCar.vehicle, vecDropoff[1][0], vecDropoff[1][1], fDropoffWidth[1])
// Car delivered
CPRINTLN(DEBUG_MISSION, "Closing the timer stat.")
INFORM_MISSION_STATS_SYSTEM_OF_TIME_WINDOW_CLOSED()
IF NOT bStashCarHasComeUnhooked
CPRINTLN(DEBUG_MISSION, "Setting BA3C_STASH_UNHOOKED stat")
INFORM_STAT_SYSTEM_OF_BOOL_STAT_HAPPENED(BA3C_STASH_UNHOOKED)
#IF IS_DEBUG_BUILD
ELSE
CPRINTLN(DEBUG_MISSION, "Not setting BA3C_STASH_UNHOOKED stat")
#ENDIF
ENDIF
// Make car unhookable
NOBBLE_TOWING(TRUE)
bPlayerInTruckLastFrame = TRUE
// Check whether the phone call has been triggered yet
IF bDeliveryCallTriggered
CPRINTLN(DEBUG_MISSION, "STAGE_UNHOOK_VEHICLE: SP_CLEANUP: Call was already triggered, going to STAGE_LEAVE")
mStage = MS_STAGE_LEAVE
ELSE
CPRINTLN(DEBUG_MISSION, "STAGE_UNHOOK_VEHICLE: SP_CLEANUP: Going to STAGE_DELIVERY_PHONE_CALL")
iCallDelayTimer = GET_GAME_TIMER() + 5000 // B*1415971 // B*1530401
mStage = MS_STAGE_DELIVERY_PHONE_CALL
ENDIF
ELSE
// Not in car park - reattach car
CPRINTLN(DEBUG_MISSION, "STAGE_UNHOOK_VEHICLE: SP_CLEANUP: Car's out of delivery zone, going to MS_STAGE_REATTACH_VEHICLE")
mStage = MS_STAGE_REATTACH_VEHICLE
ENDIF
ENDIF
sProgress = SP_SETUP
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE:
/// MISSION STAGE PROC
/// Franklin calls Barry to confirm delivery
PROC STAGE_DELIVERY_PHONE_CALL()
// Start phone call to Barry
// Go directly to leave area
IF GET_GAME_TIMER() > iCallDelayTimer
IF PLAYER_CALL_CHAR_CELLPHONE(mConversationStruct, CHAR_BARRY, "BAR3CAU", "BAR3C_P1", CONV_PRIORITY_VERY_HIGH)
CPRINTLN(DEBUG_MISSION, "STAGE_DELIVERY_PHONE_CALL: SP_SETUP: The call has started")
SET_REPLAY_MID_MISSION_STAGE_WITH_NAME(CP_DELIVERY, "Delivered vehicle", TRUE)
bDeliveryCallTriggered = TRUE
mStage = MS_STAGE_LEAVE
sProgress = SP_SETUP
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// MISSION STAGE PROC
/// Player must leave the area where they have dropped off the stash car.
PROC STAGE_LEAVE()
STASH_CAR_STARTFAIL_HANDLER()
SWITCH sProgress
CASE SP_SETUP
CPRINTLN(DEBUG_MISSION, "STAGE_LEAVE: SP_SETUP")
SAFE_REMOVE_BLIP(biGotoBlip)
// Leave the area
IF MISSION_OBJECTIVE_WILL_DISPLAY(MO_B3CLEAVE)
AND (NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED() OR GET_PROFILE_SETTING(PROFILE_DISPLAY_SUBTITLES) = 0)
DISPLAY_MISSION_OBJECTIVE(MO_B3CLEAVE) // Leave the area.
ENDIF
sProgress = SP_RUNNING
BREAK
CASE SP_RUNNING
// Check player isn't mucking about and dragging/shunting car off again
IF IS_ENTITY_IN_ANGLED_AREA(stStashCar.vehicle, vecDropoff[1][0], vecDropoff[1][1], fDropoffWidth[1])
// Car position OK - see if ready to pass mission
IF NOT IS_ENTITY_IN_RANGE_ENTITY(PLAYER_PED_ID(), stStashCar.vehicle, LEAVE_DISTANCE)
AND NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
// Player clear of drop-off area now, phone call complete
CPRINTLN(DEBUG_MISSION, "STAGE_LEAVE: SP_RUNNING: Player clear of drop-off area now, phone call complete, going to cleanup")
sProgress = SP_CLEANUP
// Check in case we still need to display objective
ELIF MISSION_OBJECTIVE_WILL_DISPLAY(MO_B3CLEAVE)
AND NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
DISPLAY_MISSION_OBJECTIVE(MO_B3CLEAVE) // Leave the area.
ENDIF
ELSE
// Player is messing about with car - go to another stage
CLEAR_PRINTS()
// Restore car's hookability
NOBBLE_TOWING(FALSE)
// Go to other stage
IF IS_PLAYER_IN_TOWTRUCK()
IF IS_STASH_CAR_HOOKED()
CPRINTLN(DEBUG_MISSION, "STAGE_LEAVE: Car out of position, player in truck with car attached, going to STAGE_RETURN_VEHICLE")
mStage = MS_STAGE_RETURN_VEHICLE
ELSE
CPRINTLN(DEBUG_MISSION, "STAGE_LEAVE: Car out of position, player in truck but car not attached, going to MS_STAGE_REATTACH_VEHICLE")
mStage = MS_STAGE_REATTACH_VEHICLE
ENDIF
ELIF IS_ENTITY_ALIVE(vehTowTruck)
CPRINTLN(DEBUG_MISSION, "STAGE_LEAVE: Car out of position, towtruck OK but player not in it, going to STAGE_GET_TRUCK_BACK")
mStage = MS_STAGE_GET_TRUCK_BACK
ELSE
CPRINTLN(DEBUG_MISSION, "STAGE_LEAVE: Car out of position, towtruck dead, going to STAGE_REDELIVER")
MISSION_OBJECTIVE_RESET(MO_B3CNOGO) // Find a way to move the stash car.
mStage = MS_STAGE_REDELIVER
ENDIF
sProgress = SP_SETUP
ENDIF
BREAK
CASE SP_CLEANUP
CPRINTLN(DEBUG_MISSION, "STAGE_LEAVE: SP_CLEANUP")
SAFE_DELETE_OBJECT(oiStashBox)
SAFE_DELETE_VEHICLE(stStashCar.vehicle)
Script_Passed()
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE:
///
PROC STAGE_REDELIVER()
STASH_CAR_STARTFAIL_HANDLER()
SWITCH sProgress
CASE SP_SETUP
CPRINTLN(DEBUG_MISSION, "STAGE_REDELIVER: SP_SETUP")
IF MISSION_OBJECTIVE_WILL_DISPLAY(MO_B3CNOGO)
AND (NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED() OR GET_PROFILE_SETTING(PROFILE_DISPLAY_SUBTITLES) = 0)
DISPLAY_MISSION_OBJECTIVE(MO_B3CNOGO) // Find a way to move the stash car.
ENDIF
MISSION_OBJECTIVE_RESET(MO_B3CLEAVE) // Leave the area.
sProgress = SP_RUNNING
TRUCK_SPAWNER()
BREAK
CASE SP_RUNNING
// Has player contrived the stash car back into the delivery zone?
IF IS_ENTITY_IN_ANGLED_AREA(stStashCar.vehicle, vecDropoff[0][0], vecDropoff[0][1], fDropoffWidth[0])
CPRINTLN(DEBUG_MISSION, "STAGE_REDELIVER: SP_RUNNING: stash car back in the delivery zone, going to cleanup")
sProgress = SP_CLEANUP
ELSE
// See if we still need the objective
IF MISSION_OBJECTIVE_WILL_DISPLAY(MO_B3CNOGO)
AND NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
DISPLAY_MISSION_OBJECTIVE(MO_B3CNOGO) // Find a way to move the stash car.
ENDIF
// Check for tow truck action
IF IS_PLAYER_IN_TOWTRUCK()
IF IS_STASH_CAR_HOOKED()
CPRINTLN(DEBUG_MISSION, "STAGE_REDELIVER: SP_RUNNING: Car hooked to truck, going to STAGE_RETURN_VEHICLE")
mStage = MS_STAGE_RETURN_VEHICLE
ELSE
CPRINTLN(DEBUG_MISSION, "STAGE_REDELIVER: SP_RUNNING: Player in a tow truck, going to STAGE_REATTACH_VEHICLE")
mStage = MS_STAGE_REATTACH_VEHICLE
ENDIF
sProgress = SP_SETUP
ELSE
TRUCK_SPAWNER()
ENDIF
ENDIF
BREAK
CASE SP_CLEANUP
// Redelivered
CPRINTLN(DEBUG_MISSION, "STAGE_REDELIVER: SP_CLEANUP")
mStage = MS_STAGE_LEAVE
sProgress = SP_SETUP
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE:
/// Lose wanted level before you can deliver
PROC STAGE_LOSE_WANTED()
STASH_CAR_STARTFAIL_HANDLER()
SWITCH sProgress
CASE SP_SETUP
CPRINTLN(DEBUG_MISSION, "STAGE_LOSE_WANTED: SP_SETUP")
SAFE_REMOVE_BLIP(biGotoBlip)
DISPLAY_MISSION_OBJECTIVE(MO_B3CWAN1) // Lose the cops.
sProgress = SP_RUNNING
BREAK
CASE SP_RUNNING
// Update Franklin complaint conversation in case it's ongoing
FRANKLIN_UNHOOK_COMPLAINT()
// Has player lost wanted level
IF GET_PLAYER_WANTED_LEVEL(PLAYER_ID()) < 1
CPRINTLN(DEBUG_MISSION, "STAGE_LOSE_WANTED: SP_RUNNING: Cleared wanted level, going to cleanup")
CLEAR_MISSION_OBJECTIVE(MO_B3CWAN1)
sProgress = SP_CLEANUP
// Detect player exiting tow truck
ELIF NOT IS_PLAYER_IN_TOWTRUCK()
// Player exited truck - change state
CPRINTLN(DEBUG_MISSION, "STAGE_LOSE_WANTED: SP_RUNNING: Player exited truck, going to cleanup")
sProgress = SP_CLEANUP
// Detect towed vehicle becoming detached
ELIF NOT IS_STASH_CAR_HOOKED()
// Truck is loose - change state
CPRINTLN(DEBUG_MISSION, "STAGE_LOSE_WANTED: SP_RUNNING: Towed vehicle not hooked, going to cleanup")
sProgress = SP_CLEANUP
ENDIF
BREAK
CASE SP_CLEANUP
CPRINTLN(DEBUG_MISSION, "STAGE_LOSE_WANTED: SP_CLEANUP")
CLEAR_PRINTS()
// Change state
IF NOT IS_PED_IN_VEHICLE(PLAYER_PED_ID(), vehTowTruck)
CPRINTLN(DEBUG_MISSION, "STAGE_LOSE_WANTED: SP_CLEANUP: Not in truck, going to STAGE_GET_TRUCK_BACK")
mStage = MS_STAGE_GET_TRUCK_BACK
ELSE
// Player in truck, see if the stash car is hooked
IF NOT IS_VEHICLE_ATTACHED_TO_TOW_TRUCK(vehTowTruck, stStashCar.vehicle)
CPRINTLN(DEBUG_MISSION, "STAGE_LOSE_WANTED: SP_CLEANUP: In truck, not hooked up, going to STAGE_REATTACH_VEHICLE")
mStage = MS_STAGE_REATTACH_VEHICLE
ELSE
CPRINTLN(DEBUG_MISSION, "STAGE_LOSE_WANTED: SP_CLEANUP: In truck and towing, going to STAGE_RETURN_VEHICLE")
mStage = MS_STAGE_RETURN_VEHICLE
ENDIF
ENDIF
sProgress = SP_SETUP
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE:
/// MISSION STAGE PROC
/// Handles stupid stuff happening during our wait to fail the mission
PROC STAGE_FAIL_FADE()
SWITCH sProgress
CASE SP_SETUP
CPRINTLN(DEBUG_MISSION, "STAGE_FAIL_FADE: SP_SETUP")
SAFE_REMOVE_BLIP(biGotoBlip)
IF IS_STRING_NULL_OR_EMPTY(sFailReason)
// Guard against null string case
SCRIPT_ASSERT("Reached STAGE_FAIL_FADE with NULL/empty fail reason string - Please add detailed repro steps when bugging this.")
sFailReason = "DEFAULT"
ENDIF
IF ARE_STRINGS_EQUAL(sFailReason, "DEFAULT")
// No fail reason
Random_Character_Failed()
ELSE
Random_Character_Failed_With_Reason(sFailReason)
ENDIF
sProgress = SP_RUNNING
BREAK
CASE SP_RUNNING
IF GET_MISSION_FLOW_SAFE_TO_CLEANUP()
// finished fading out
CPRINTLN(DEBUG_MISSION, "STAGE_FAIL_FADE: Cleanup")
// Remove player from stash vehicle, although this is a very unlikely case.
// Don't remove from tow truck - not really a problem letting them keep that.
// Detach truck from car in case player is about to get to keep the truck, otherwise it stuffs up the tow rope.
IF IS_ENTITY_ALIVE(stStashCar.vehicle)
AND IS_ENTITY_ALIVE(vehTowTruck)
AND IS_ENTITY_ATTACHED_TO_ENTITY(stStashCar.vehicle, vehTowTruck)
CPRINTLN(DEBUG_MISSION, "Unhooking car in cleanup")
DETACH_VEHICLE_FROM_ANY_TOW_TRUCK(stStashCar.vehicle)
ENDIF
// Not warping player - not that likely they failed in an unsafe location
COLLECT_AREA_CLEANUP()
Script_Cleanup()
ELSE
// not finished fading out
// you may want to handle dialogue etc here.
ENDIF
BREAK
ENDSWITCH
ENDPROC
// ===========================================================================================================
// DEBUG FUNCTIONS
// ===========================================================================================================
/// PURPOSE: Check for Forced Pass or Fail
PROC DEBUG_Check_Debug_Keys()
#IF IS_DEBUG_BUILD
INT iNewStage
// Check for Pass
IF (IS_KEYBOARD_KEY_JUST_PRESSED(KEY_S))
SKIP_CLEAR_ALL_MISSION_OBJECTIVES()
Script_Passed()
// Check for Fail
ELIF (IS_KEYBOARD_KEY_JUST_PRESSED(KEY_F))
SKIP_CLEAR_ALL_MISSION_OBJECTIVES()
mStage = MS_STAGE_FAIL_FADE
sProgress = SP_SETUP
// Check for skip forward
ELIF (IS_KEYBOARD_KEY_JUST_PRESSED(KEY_J))
SKIP_FORWARD()
ELIF (IS_KEYBOARD_KEY_JUST_PRESSED(KEY_P))
SKIP_BACKWARD()
ELIF LAUNCH_MISSION_STAGE_MENU(mSkipMenu, iNewStage)
DO_Z_SKIP(iNewStage)
ENDIF
IF bDebugCheatCarLocation
bDebugCheatCarLocation = FALSE
IF mStage = MS_STAGE_CALL_BARRY
OR mStage = MS_STAGE_FIND_TOWTRUCK
OR mStage = MS_STAGE_TOW_VEHICLE
CPRINTLN(DEBUG_MISSION, "CHEAT!!! Moved stash car!")
SET_ENTITY_COORDS(stStashCar.vehicle, <<-456.9121, -1710.0674, 17.7283>>)
SET_ENTITY_HEADING(stStashCar.vehicle, 272.5)
SET_VEHICLE_ON_GROUND_PROPERLY(stStashCar.vehicle)
ELSE
CPRINTLN(DEBUG_MISSION, "TRIED TO CHEAT CAR COORDS IN INVALID MISSION STAGE!")
ENDIF
ENDIF
#ENDIF
ENDPROC
// ===========================================================================================================
// Script Loop
// ===========================================================================================================
SCRIPT(g_structRCScriptArgs sRCLauncherDataIn)
sRCLauncherDataLocal = sRCLauncherDataIn
RC_TakeEntityOwnership(sRCLauncherDataLocal)
RC_CLEANUP_LAUNCHER()
SET_MISSION_FLAG(TRUE)
// Setup callback when player is killed, arrested or goes to multiplayer
IF (HAS_FORCE_CLEANUP_OCCURRED(DEFAULT_FORCE_CLEANUP_FLAGS|FORCE_CLEANUP_FLAG_DEBUG_MENU))
PRINT_LAUNCHER_DEBUG("Force cleanup [TERMINATING]")
Random_Character_Failed()
Script_Cleanup()
ENDIF
// Grab stash car
IF DOES_ENTITY_EXIST(sRCLauncherDataLocal.vehID[0])
CPRINTLN(DEBUG_MISSION, "Grabbing stash car from initial scene")
IF NOT IS_ENTITY_DEAD(sRCLauncherDataLocal.vehID[0])
SET_VEHICLE_AUTOMATICALLY_ATTACHES(sRCLauncherDataLocal.vehID[0],TRUE)
ASSIGN_VEHICLE_INDEX(stStashCar.vehicle, sRCLauncherDataLocal.vehID[0])
SET_ENTITY_LOAD_COLLISION_FLAG(stStashCar.vehicle, TRUE)
SET_VEHICLE_AS_RESTRICTED(stStashCar.vehicle, RESTRICTION_STASHVEH)
ENDIF
ENDIF
ASSIGN_OBJECT_INDEX(oiStashBox, sRCLauncherDataLocal.objID[0])
DATA_INIT()
// Grab truck from initial scene - after the vehicle structs are set up
IF DOES_ENTITY_EXIST(sRCLauncherDataLocal.vehID[1])
CPRINTLN(DEBUG_MISSION, "Grabbing start area tow truck from initial scene")
ASSIGN_VEHICLE_INDEX(stTruck[6].vehicle, sRCLauncherDataLocal.vehID[1])
ENDIF
// Check whether this is a replay
IF Is_Replay_In_Progress()
INT iReplayStage = GET_REPLAY_MID_MISSION_STAGE()
// Check for shit skip
IF g_bShitskipAccepted
iReplayStage++
ENDIF
// Individual skip procs handle START_REPLAY_SETUP - some stages need to handle vehicle positioning so the tow truck can attach
SWITCH iReplayStage
CASE 0
SKIP_TO_START_CAR(TRUE)
RC_END_Z_SKIP()
BREAK
CASE CP_START_TOW
SKIP_START_TOWING_SECTION(TRUE)
RC_END_Z_SKIP()
BREAK
CASE CP_DELIVERY
SKIP_TRIGGER_DELIVERY(TRUE)
RC_END_Z_SKIP()
BREAK
CASE CP_MISSION_COMPLETE
SKIP_MISSION_COMPLETE(TRUE)
RC_END_Z_SKIP()
BREAK
DEFAULT
SCRIPT_ASSERT("Replay in progress: Unknown checkpoint selected")
BREAK
ENDSWITCH
ELIF IS_REPEAT_PLAY_ACTIVE()
CPRINTLN(DEBUG_MISSION, "Barry3C - repeat play")
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
SET_ENTITY_HEADING(PLAYER_PED_ID(), 113.9)
SET_GAMEPLAY_CAM_RELATIVE_HEADING(0)
SET_GAMEPLAY_CAM_RELATIVE_PITCH(0)
ENDIF
RC_END_Z_SKIP()
ENDIF
// Loop within here until the mission passes or fails
WHILE(TRUE)
REPLAY_CHECK_FOR_EVENT_THIS_FRAME("SF_GRTD")
UPDATE_MISSION_NAME_DISPLAYING(sRCLauncherDataLocal.sIntroCutscene)
IF mStage = MS_STAGE_FAIL_FADE
STAGE_FAIL_FADE()
ELSE
IF NOT MISSION_FAIL_CHECKS()
// Check debug completion/failure
DEBUG_Check_Debug_Keys()
HANDLE_CONVERSATION_AND_OBJECTIVE_TEXT_CONFLICT(stateRestoreConversation, mConversationStruct, "BAR3CAU", tSavedConversationRoot, tSavedConversationLabel)
SWITCH mStage
CASE MS_STAGE_ENTER_STASH_CAR
STAGE_ENTER_STASH_CAR()
BREAK
CASE MS_STAGE_START_STASH_CAR
STAGE_START_STASH_CAR()
BREAK
CASE MS_STAGE_CALL_BARRY
STAGE_CALL_BARRY()
BREAK
CASE MS_STAGE_FIND_TOWTRUCK
STAGE_FIND_TOWTRUCK()
BREAK
CASE MS_STAGE_TOW_VEHICLE
STAGE_TOW_VEHICLE()
BREAK
CASE MS_STAGE_RETURN_VEHICLE
STAGE_RETURN_VEHICLE()
BREAK
CASE MS_STAGE_UNHOOK_VEHICLE
STAGE_UNHOOK_VEHICLE()
BREAK
CASE MS_STAGE_DELIVERY_PHONE_CALL
STAGE_DELIVERY_PHONE_CALL()
BREAK
CASE MS_STAGE_LEAVE
STAGE_LEAVE()
BREAK
CASE MS_STAGE_LOSE_WANTED
STAGE_LOSE_WANTED()
BREAK
CASE MS_STAGE_GET_TRUCK_BACK
STAGE_GET_TRUCK_BACK()
BREAK
CASE MS_STAGE_REATTACH_VEHICLE
STAGE_REATTACH_VEHICLE()
BREAK
CASE MS_STAGE_REDELIVER
STAGE_REDELIVER()
BREAK
ENDSWITCH
ENDIF
ENDIF
WAIT(0)
ENDWHILE
// Script should never reach here. Always terminate with cleanup function.
ENDSCRIPT