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

16198 lines
541 KiB
Python
Executable File

//|=======================================================================================|
//| Author: Lukasz Bogaj / Jim McMahon Date: 28/11/2011 |
//|=======================================================================================|
//| FAMILY3.sc |
//| MARRIAGE COUNSELLING |
//| |
//|=======================================================================================|
//Compile out Title Update changes to header functions.
//Must be before includes.
//CONST_INT USE_TU_CHANGES 0 // Removed by Kenneth R.
//|==================================== INCLUDE FILES ====================================|
USING "rage_builtins.sch"
USING "globals.sch"
//Commands headers
USING "commands_fire.sch"
USING "commands_script.sch"
USING "commands_pad.sch"
USING "commands_object.sch"
USING "commands_misc.sch"
USING "commands_player.sch"
USING "commands_streaming.sch"
USING "commands_camera.sch"
USING "Commands_clock.sch"
USING "Commands_interiors.sch"
USING "commands_cutscene.sch"
USING "commands_physics.sch"
USING "commands_entity.sch"
USING "commands_recording.sch"
//Script headers
USING "script_player.sch"
USING "script_blips.sch"
USING "script_ped.sch"
//Public headers
USING "dialogue_public.sch"
USING "cellphone_public.sch"
USING "locates_public.sch"
USING "chase_hint_cam.sch"
USING "flow_public_game.sch"
USING "flow_public_core_override.sch"
USING "stats_public.sch"
USING "replay_public.sch"
USING "cutscene_public.sch"
USING "mission_stat_public.sch"
USING "selector_public.sch"
USING "building_control_public.sch"
USING "clearMissionArea.sch"
USING "taxi_functions.sch"
USING "vehicle_gen_public.sch"
USING "carsteal_public.sch"
USING "flow_help_public.sch"
USING "respawn_location_private.sch"
USING "emergency_call.sch"
USING "buddy_head_track_public.sch"
USING "cellphone_public.sch"
//================================ UBER PLAYBACK CONSTANTS ===============================|
//Replace the default uber playback values stored in "traffic_default_values.sch"
//total should not exceed 225
CONST_INT TOTAL_NUMBER_OF_TRAFFIC_CARS 150
CONST_INT TOTAL_NUMBER_OF_PARKED_CARS 50
CONST_INT TOTAL_NUMBER_OF_SET_PIECE_CARS 25
//total should not exceed 12
CONST_INT MAX_NUMBER_OF_TRAFFIC_CARS_PLAYING_BACK 14
CONST_INT MAX_NUMBER_OF_SET_PIECE_CARS_PLAYING_BACK 21
//this should be fine
CONST_INT MAX_NUMBER_OF_PARKED_CARS_PLAYING_BACK 6
//============================== END UBER PLAYBACK CONSTANTS =============================|
USING "traffic.sch"
//Debug headers
#IF IS_DEBUG_BUILD
USING "script_debug.sch"
USING "select_mission_stage.sch"
#ENDIF
//===================================== ENUMS & STRUCTS ==================================|
/// PURPOSE: Specifies stages of the mission.
ENUM MISSION_STAGES
MISSION_STAGE_CUTSCENE_INTRO = 0, //Intro cutscene
MISSION_STAGE_CAR_CHASE = 1, //Michael and Franklin chase after tennis coach
MISSION_STAGE_CUTSCENE_BACK_OF_HOUSE = 2, //Cutscene taking place at the back of the house
MISSION_STAGE_PULL_HOUSE_DOWN = 3, //Michael and Franklin pull the house down
MISSION_STAGE_ESCAPE_GOONS = 4, //Michael and Franklin escape goons chasing them after pulling the house down
MISSION_STAGE_CUTSCENE_END = 5, //End cutscene
MISSION_STAGE_LEADOUT = 6, //Mission lead out, Michael is seen making a phone call to Lester after mission pass
#IF IS_DEBUG_BUILD
MISSION_STAGE_DEBUG_RECORD_CHASE = 7, //Debug stage to record the car chase
MISSION_STAGE_DEBUG_PLAYBACK_CHASE = 8, //Debug stage to playback car chase
#ENDIF
MISSION_STAGE_PASSED, //Mission passed
MISSION_STAGE_FAILED //Mission failed
ENDENUM
/// PURPOSE: Specifies mission fail reasons.
ENUM MISSION_FAILS
MISSION_FAIL_EMPTY = 0, //Generic fail
MISSION_FAIL_CAR_DESTROYED, //Mission car destroyed
MISSION_FAIL_CAR_STUCK, //Mission car stuck
MISSION_FAIL_MICHAEL_DEAD, //Michael killed
MISSION_FAIL_MICHAEL_LEFT_BEHIND, //Michael left behind
MISSION_FAIL_FRANKLIN_DEAD, //Franklin killed
MISSION_FAIL_FRANKLIN_LEFT_BEHIND, //Franklin left behind
MISSION_FAIL_COACH_DEAD, //Tennis coach killed
MISSION_FAIL_COACH_ATTACKED, //Tennis coach attacked
MISSION_FAIL_COACH_SPOOKED, //Tennis coach spooked
MISSION_FAIL_FORCE_FAIL, //Debug forced fail
MAX_MISSION_FAILS
ENDENUM
/// PURPOSE: Specifies mid-mission checkpoints for mission retry.
ENUM MID_MISSION_STAGES
MID_MISSION_STAGE_CAR_CHASE = 0, //Checkpoint at MISSION_STAGE_CAR_CHASE
MID_MISSION_STAGE_PULL_HOUSE_DOWN = 1, //Checkpoint at MISSION_STAGE_PULL_HOUSE_DOWN
MID_MISSION_STAGE_ESCAPE_GOONS = 2, //Checkpoint at MISSION_STAGE_ESCAPE_GOONS
MID_MISSION_STAGE_DRIVE_HOME = 3 //Checkpoint at MISSION_STAGE_DRIVE_HOME
ENDENUM
ENUM PED_STATES
PED_STATE_IDLE = 0,
PED_STATE_ON_FOOT,
PED_STATE_ENTERING_VEHICLE,
PED_STATE_SITTING_IN_VEHICLE_PASSENGER,
PED_STATE_SITTING_IN_VEHICLE_DRIVER,
PED_STATE_SHUFFLING_VEHICLE_SEATS,
PED_STATE_LOOKING_BEHIND_IN_VEHICLE,
PED_STATE_COMBAT_ON_FOOT,
PED_STATE_COMBAT_FROM_CAR_NO_SHOOTING,
PED_STATE_COMBAT_FROM_CAR_SHOOTING,
PED_STATE_DRIVE_FLEE_TARGETS,
PED_STATE_DRIVE_FLEE_COPS,
PED_STATE_DRIVE_TO_DESTINATION,
PED_STATE_FOLLOWING_PLAYER,
PED_STATE_WAITING_FOR_PLAYER,
PED_STATE_WAITING_FOR_TASK_AFTER_SWITCH
ENDENUM
ENUM FRANKLIN_CAR_ANIMATIONS
FCA_BRACE_START = 1,
FCA_BRACE_LOOP = 2,
FCA_BRACE_EXIT = 3,
FCA_BUMPS_LOOP = 4
ENDENUM
ENUM CHASE_FINISHED_REASONS
CHASE_FINISHED_TARGET_LOST = 0,
CHASE_FINISHED_END_REACHED = 1
ENDENUM
ENUM PED_CLEANUP_REASONS
PED_CLEANUP_NO_CLEANUP = 0,
PED_CLEANUP_LOST = 1,
PED_CLEANUP_KILLED_BY_MICHAEL = 2,
PED_CLEANUP_KILLED_BY_FRANKLIN = 3,
PED_CLEANUP_KILLED_BY_VEHICLE = 4,
PED_CLEANUP_KILLED_BY_PLAYER_AS_MICHAEL = 5,
PED_CLEANUP_KILLED_BY_PLAYER_AS_FRANKLIN = 6
ENDENUM
/// PURPOSE: Specifies details of mission peds.
STRUCT PED_STRUCT
PED_INDEX PedIndex //Ped Index
BLIP_INDEX BlipIndex //Ped's Blip Index
VECTOR vPosition //Ped's start location
FLOAT fHeading //Ped's start heading
MODEL_NAMES ModelName //Ped's model
INT iTimer //Ped's timer
INT iAgressiveTimer //Ped's timer to become aggressive
INT iConversationTimer //Ped's conversation timer
INT iConversationCounter //Ped's conversation counter
INT iProgress //Ped's progress
INT iCleanupAttempts
BOOL bHasTask
BOOL bCleanupConversationTriggered
FLOAT fDistanceToTarget
PED_STATES eState
PED_CLEANUP_REASONS eCleanupReason
#IF IS_DEBUG_BUILD
TEXT_LABEL_31 sDebugName
#ENDIF
ENDSTRUCT
/// PURPOSE: Specifies details of mission vehicles.
STRUCT VEH_STRUCT
VEHICLE_INDEX VehicleIndex //Vehicle index
BLIP_INDEX BlipIndex //Vehicle blip
VECTOR vPosition //Vehicle postion
FLOAT fHeading //Vehicle heading
MODEL_NAMES ModelName //Vehicle model
INT iProgress //Vehicle progress counter
INT iTimer //Vehicle timer
INT iRecordingNumber //Vehicle recording number
FLOAT fPlaybackSpeed //Vehicle recording playback speed
BOOL bAutoDrive //Vehicle using auto driving
BOOL bLOSFlag //Vehicle line of sight flag
INT iWarpTimer
VECTOR vWarpOffset
VECTOR vTargetPosition
FLOAT fTargetHeading
FLOAT fDistanceToTarget
#IF IS_DEBUG_BUILD
TEXT_LABEL_63 sDebugName
#ENDIF
ENDSTRUCT
STRUCT OBJECT_STRUCT
OBJECT_INDEX ObjectIndex //ObjectIndex
VECTOR vPosition //Object position
VECTOR vRotation //Object rotation
MODEL_NAMES ModelName //Object model name
ENDSTRUCT
/// PURPOSE: Contains player postion, heading and destination.
STRUCT LOCATION_STRUCT
BLIP_INDEX DestinationBlip
VECTOR vPosition
FLOAT fHeading
ENDSTRUCT
//|======================================= CONSTANTS =====================================|
//asset requirements
CONST_INT MAX_MODELS 8
CONST_INT MAX_CAR_RECORDINGS 6
CONST_INT MAX_ANIMATIONS 1
CONST_INT MAX_BUDDY_PED_HEALTH 400
TWEAK_FLOAT BLIP_SLIDE_AMOUNT 1.1 //1.0
TWEAK_FLOAT fForceConverge 0.5
TWEAK_FLOAT fSideForceValue 130.0
TWEAK_FLOAT fDownForceValue 450.0
TWEAK_FLOAT fFirstPersonFlashPhase1 0.900
TWEAK_FLOAT fFirstPersonFlashPhase2 0.500
TWEAK_FLOAT fFirstPersonFlashPhase3 0.900
TWEAK_INT iTennisCoachHintDuration 9500
TWEAK_INT iFirstPersonFlashTime 300
CONST_FLOAT CHASE_TARGET_LOST_DISTANCE 250.0
CONST_FLOAT ROPE_MAX_LEN 28.0
STRING ROPE_DATA_FILE = "ropeFamily3"
VECTOR vInteriorPosition = << -813.80, 179.23, 71.16 >> //room: V_Michael_G_Front
VECTOR vVanLocateSize = << 40.0, 40.0, 40.0 >> //<< 37.5, 37.5, 37.5 >>
VECTOR vUnderBalconyPosition = << -991.65, 645.38, 138.64 >>
VECTOR vMichaelsHousePosition = << -822.26, 182.90, 70.90 >>
VECTOR vTennisCoachHintPosition = << -977.222, 634.37, 156.00 >> //<< -1035.22, 653.37, 154.92 >>
VECTOR vBalconyHintPosition = << -1015.8, 656.4, 149.2 >>
STRING sVehicleRecordingsFile = "famthree"
#IF IS_DEBUG_BUILD
STRING sUberRecordingFile = "ft" //"fam3" //"famthree"
#ENDIF
VECTOR vRearLeftWheelOffset = << -0.875, -1.75, -0.475 >>
VECTOR vRearRightWheelOffset = << 0.875, -1.75, -0.475 >>
VECTOR vPTFXRotation = << 0.0, 0.0, 0.0 >>
VECTOR vForceBackOffset = << 0.0, -2.6, 0.20 >>
TEXT_LABEL sLabelGIT = "FAM3_GIT"
TEXT_LABEL sLabelDCAN = "FAM3_DCAN"
TEXT_LABEL sLabelDHOUSE = "FAM3_DHOUSE"
TEXT_LABEL sLabelGETBCK = "FAM3_GBIT"
TEXT_LABEL sLabelFLEAVE = "CMN_FLEAVE"
TEXT_LABEL sLabelMLEAVE = "CMN_MLEAVE"
TEXT_LABEL sLabelLWANTED = "LOSE_WANTED"
//|======================================= VARIABLES =====================================|
MISSION_STAGES eMissionStage = MISSION_STAGE_CUTSCENE_INTRO
MISSION_FAILS eMissionFail = MISSION_FAIL_EMPTY
CHASE_FINISHED_REASONS eChaseFinishReason = CHASE_FINISHED_TARGET_LOST
REL_GROUP_HASH rgEnemies
REL_GROUP_HASH rgTennisCoach
//mission peds
PED_STRUCT psFranklin
PED_STRUCT psMichael
PED_STRUCT psCoach
PED_STRUCT psVanDriver
//mission vehicles
VEH_STRUCT vsMichaelsEndCar
VEH_STRUCT vsPlayersCar
VEH_STRUCT vsCoachsCar
VEH_STRUCT vsVan
VEH_STRUCT vsCutsceneCar
OBJECT_STRUCT osRacket01
OBJECT_STRUCT osRacket02
OBJECT_STRUCT osCellphone
OBJECT_STRUCT osRopeDummy
OBJECT_STRUCT osRopeAnchor
OBJECT_STRUCT osRopeProp
OBJECT_STRUCT osBootCollision
OBJECT_STRUCT osBrokenPlantPot
//switch data
BOOL bAllowHotSwap
BOOL bHotSwapHinted
BOOL bHotSwapTriggered
INT iHotSwapHintTimer
SELECTOR_PED_STRUCT sSelectorPeds
SELECTOR_CAM_STRUCT sCamDetails
//locates header data
LOCATES_HEADER_DATA sLocatesData
CHASE_HINT_CAM_STRUCT localChaseHintCamStruct
//conversation struct
structPedsForConversation sFamily3Conversation
INT iRandomLinesTriggered
//progress counters and flags for loading, skipping and replays
INT iStageSetupProgress
INT iMissionStageProgress
BOOL bSkipFlag
BOOL bReplayFlag
BOOL bLoadingFlag
//asset request counters
INT iModelsRequested
INT iRecordingsRequested
INT iAnimationsRequested
//text printing
INT iTriggeredTextHashes[30]
INT iNumTextHashesStored
//scripted cutscene & rayfire
INT iSyncedSceneCoachID
INT iScriptedCameraProgress
CAMERA_INDEX ScriptedCamera
RAYFIRE_INDEX riHouseFallRayfire
RAYFIRE_INDEX riFrenchDoorRayfire
ROPE_INDEX Rope
BOOL bRopeAttached
BOOL bHousePullStarted
BOOL bHousePullCompleted
INT iRayfireMapObjectProgress
INT iRayfireSequenceProgress
FLOAT fRayfirePhase
BOOL bRayfirePrimed
BOOL bRayfireStarted
BOOL bRayfirePaused
BOOL bRayfireFinished
FLOAT fCameraShakeAmplitude
FLOAT fWheelspinValue
BOOL bPTFXStarted
PTFX_ID ptfxRearLeftWheel
PTFX_ID ptfxRearRightWheel
PTFX_ID ptfxDustCloud
INT iConversationProgress
INT iConversationIdleTimer
INT iGoonsChaseDelayTimer
INT iVehicleSwitchTimer
INT iVehicleImpactSoundTimer
BOOL bPhoneCallInterruptedByPlayer
BOOL bCustomRouteActive
BOOL bShouldUseDefaultRoute
BOOL bRunLocatesHeaderCheck
BOOL bDisplayDestinationBlip
BOOL bStartGoonTimerDelay
TEXT_LABEL_23 lConversationLabel = ""
TEXT_LABEL_23 lConversationRoot = ""
BOOL bConversationPaused
BOOL bCoachLostConversationStarted
BOOL bPlayerCrashedIntoVan
BOOL bChaseInProgress
BOOL bChaseFinished
BOOL bCoachVisible
BOOL bCoachSpotted
BOOL bMichaelStartedShouting
BOOL bSpotConversationFinished
BOOL bRecordingPlaybackStarted
BOOL bCutsceneSkipped
BOOL bCutsceneAssetsRequested
BOOL bTruckRepositionedForCutscene
BOOL bAllowConvsersationOutsideOfCar
BOOL bStopScriptedConversations
BOOL bStatConversationFinished
BOOL bVanDriverCrashSpeechTriggered
FLOAT fChaseDistanceFromPlayerToCoach
FLOAT fChaseSpeed = 0.65 //initialise to uber chase start speed value
FLOAT fChaseTime
BOOL bRandomConversationAllowed
FLOAT fClosestRoadNodeHeading
VECTOR vClosestRoadNode
VECTOR vPullStartVehiclePosition
//goons stage
INT iGoonsProgress
BOOL bGoonsAllowed
BOOL bGoonsAttacked
BOOL bGoonsChaseInProgress
BOOL bGoonsChaseFinished
BOOL bGoonsAggressive
BOOL bCombatAllowed
BOOL bPlayerFiredAsPassenger
BOOL bLoseWantedDisplayed
INT iGoonsChaseInitialTimer
BOOL bGoonsChaseInitialTimePassed
//kill counters
INT iPlayerMichaelKills
INT iPlayerFranklinKills
INT iBuddyMichaelKills
INT iBuddyFranklinKills
INT iPlayerShootingTimer
INT iDriveTaskDelayTimer
BOOL bDriveTaskDelayed
BOOL bShutVehicleBoot
BOOL bMusicEventMissionStartTriggered
BOOL bMusicEventHookedUpTriggered
BOOL bVehicleReversed
BOOL bChaseHintCamAllowed
BOOL bPlayerVehicleEntered
BOOL bBuddyPedCoverTaskCleared
BOOL bWantedLevelBlockedOnBuddyDrive
INT iApplyForceSide
INT iApplyForceTimer
FLOAT fMinX, fMinY, fMaxX, fMaxY
INT bGameplayHintTimer
INT iPhoneCallSceneID = -1
INT iNMBlockingObject01 = -1 //blocks the house debris with larger part of the deck
INT iNMBlockingObject02 = -1 //blocks the house debris with smaller part of the deck
INT iNMBlockingObject03 = -1 //blocks the house debris with the smallest part of the deck
INT iLeadOutTimer
INT iCutsceneCarLightsProgress
INT iCustomSwitchSoundID
INT iMichaelsVehicleExitDelay = 0
INT iFranklinsVehicleExitDelay = 250
INT iCameraTimer
INT iCameraProgress
INT iLeadOutLoadSceneTimer
BOOL bLeadoutConversationEnded
BOOL bFirstSwitchCompleted
BOOL bRunDirectSwitch
BOOL bPedsTaskedToLeaveAnyVehicle
BOOL bStopRandomChaseConversations
BOOL bStartPreloadingVanConversation
INT iMichaelEnemyKillConversations
INT iFranklinEnemyKillConversations
BOOL bResetFirstPersonCamera
BOOL bStopForcingThirdPersonCamera
BOOL bFirstPersonFlashPlayed
BOOL bTriggerSwitchFlash
INT iFirstPersonFlashTimer
INT iReplayCameraWarpTimer
//|========================================= ARRAYS ======================================|
BOOL FailFlags[MAX_MISSION_FAILS]
//asset arrays
MODEL_NAMES MissionModels[MAX_MODELS]
INT MissionRecordings[MAX_CAR_RECORDINGS]
STRING MissionAnimations[MAX_ANIMATIONS]
FLOAT fPlayerHeadings[8]
VECTOR vPlayerPositions[8]
VECTOR vEnemyCarsOffset[2]
VEH_STRUCT vsEnemyCars[2]
PED_STRUCT psEnemyGoonsCar0[2]
PED_STRUCT psEnemyGoonsCar1[2]
//|========================= MISCELLANEOUS PROCEDURES & FUNCTIONS ========================|
/// PURPOSE:
/// Resets all mission flags and progress counters to their default values.
PROC RESET_MISSION_FLAGS()
//reset setup progress to 1, so that iSetupProgress = 0 only runs once, on initial mission load.
iStageSetupProgress = 1
iMissionStageProgress = 0
psFranklin.iTimer = 0
psFranklin.iConversationTimer = 0
psFranklin.iConversationCounter = 0
psMichael.iConversationTimer = 0
psMichael.iConversationCounter = 0
iRandomLinesTriggered = 0
psFranklin.iProgress = 0
psFranklin.bHasTask = FALSE
psFranklin.eState = PED_STATE_IDLE
psCoach.iProgress = 0
vsVan.iProgress = 0
vsPlayersCar.iProgress = 0
vsPlayersCar.bAutoDrive = FALSE
bRandomConversationAllowed = FALSE
bPhoneCallInterruptedByPlayer = FALSE
bCustomRouteActive = FALSE
bShouldUseDefaultRoute = FALSE
bRunLocatesHeaderCheck = FALSE
bDisplayDestinationBlip = FALSE
fChaseSpeed = 0.65
fChaseTime = 0.0
bChaseInProgress = FALSE
bChaseFinished = FALSE
bCoachVisible = FALSE
bCoachSpotted = FALSE
bMichaelStartedShouting = FALSE
bSpotConversationFinished = FALSE
bRecordingPlaybackStarted = FALSE
iSyncedSceneCoachID = 0
iScriptedCameraProgress = 0
iRayfireMapObjectProgress = 0
iRayfireSequenceProgress = 0
fRayfirePhase = 0.0
bRayfireStarted = FALSE
bRayfirePaused = FALSE
bPTFXStarted = FALSE
fWheelspinValue = 0.0
fCameraShakeAmplitude = 0.0
bConversationPaused = FALSE
bPlayerCrashedIntoVan = FALSE
bCoachLostConversationStarted = FALSE
bCutsceneSkipped = FALSE
bCutsceneAssetsRequested = FALSE
bAllowConvsersationOutsideOfCar = FALSE
bStopScriptedConversations = FALSE
bStatConversationFinished = FALSE
bVanDriverCrashSpeechTriggered = FALSE
bHousePullStarted = FALSE
bHousePullCompleted = FALSE
iVehicleSwitchTimer = 0
iGoonsChaseDelayTimer = 0
iConversationProgress = 0
iConversationIdleTimer = 0
iVehicleImpactSoundTimer = 0
iGoonsProgress = 0
bGoonsAllowed = FALSE
bGoonsAttacked = FALSE
bGoonsChaseInProgress = FALSE
bGoonsChaseFinished = FALSE
bGoonsAggressive = FALSE
bCombatAllowed = FALSE
bPlayerFiredAsPassenger = FALSE
bLoseWantedDisplayed = FALSE
bTruckRepositionedForCutscene = FALSE
bStartGoonTimerDelay = FALSE
iPlayerShootingTimer = 0
sLabelDCAN = "FAM3_DCAN"
sLabelDHOUSE = "FAM3_DHOUSE"
sLabelGETBCK = "FAM3_GBIT"
sLabelFLEAVE = "CMN_FLEAVE"
sLabelMLEAVE = "CMN_MLEAVE"
sLabelLWANTED = "LOSE_WANTED"
eChaseFinishReason = CHASE_FINISHED_TARGET_LOST
bMusicEventHookedUpTriggered = FALSE
bMusicEventMissionStartTriggered= FALSE
bChaseHintCamAllowed = FALSE
bPlayerVehicleEntered = FALSE
iApplyForceSide = 1
iApplyForceTimer = 0
bAllowHotSwap = FALSE
bHotSwapHinted = FALSE
bHotSwapTriggered = FALSE
iHotSwapHintTimer = 0
bGameplayHintTimer = 0
iDriveTaskDelayTimer = 0
bDriveTaskDelayed = FALSE
bBuddyPedCoverTaskCleared = FALSE
bWantedLevelBlockedOnBuddyDrive = FALSE
iGoonsChaseInitialTimer = 0
bGoonsChaseInitialTimePassed = FALSE
bShutVehicleBoot = FALSE
iLeadOutTimer = 0
iCutsceneCarLightsProgress = 0
iCameraTimer = 0
iCameraProgress = 0
iLeadOutLoadSceneTimer = 0
bLeadoutConversationEnded = FALSE
bFirstSwitchCompleted = FALSE
bPedsTaskedToLeaveAnyVehicle = FALSE
bStopRandomChaseConversations = FALSE
bStartPreloadingVanConversation = FALSE
iMichaelEnemyKillConversations = 0
iFranklinEnemyKillConversations = 0
bResetFirstPersonCamera = FALSE
bStopForcingThirdPersonCamera = FALSE
bRunDirectSwitch = FALSE
bFirstPersonFlashPlayed = FALSE
iFirstPersonFlashTimer = 0
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Mission flags and progress counters are reset.")
#ENDIF
ENDPROC
/// PURPOSE:
/// Sets all fail flags to specified boolean value.
/// PARAMS:
/// bNewBool - Boolean value to set all flags to TRUE or FALSE.
PROC SET_FAIL_FLAGS(BOOL bNewBool)
INT i = 0
FOR i = 0 TO ( COUNT_OF(FailFlags) - 1 )
FailFlags[i] = bNewBool
ENDFOR
ENDPROC
PROC INITIALISE_UBER_ARRAY()
TrafficCarPos[0] = <<-867.2245, 209.0847, 73.3253>>
TrafficCarQuatX[0] = 0.0774
TrafficCarQuatY[0] = 0.0159
TrafficCarQuatZ[0] = 0.8993
TrafficCarQuatW[0] = -0.4302
TrafficCarRecording[0] = 4
TrafficCarStartime[0] = 2600.0
TrafficCarModel[0] = dilettante
TrafficCarPos[1] = <<-785.0840, 220.7164, 75.9672>>
TrafficCarQuatX[1] = 0.0123
TrafficCarQuatY[1] = 0.0143
TrafficCarQuatZ[1] = 0.7330
TrafficCarQuatW[1] = 0.6799
TrafficCarRecording[1] = 76
TrafficCarStartime[1] = 6170.0
TrafficCarModel[1] = Baller
TrafficCarPos[2] = <<-992.3110, 217.7745, 67.0249>>
TrafficCarQuatX[2] = 0.0234
TrafficCarQuatY[2] = 0.0272
TrafficCarQuatZ[2] = -0.1712
TrafficCarQuatW[2] = 0.9846
TrafficCarRecording[2] = 10
TrafficCarStartime[2] = 10475.0
TrafficCarModel[2] = jackal
TrafficCarPos[3] = <<-967.0320, 362.0272, 71.8551>>
TrafficCarQuatX[3] = -0.0168
TrafficCarQuatY[3] = -0.0225
TrafficCarQuatZ[3] = 0.7457
TrafficCarQuatW[3] = -0.6657
TrafficCarRecording[3] = 1
TrafficCarStartime[3] = 11425.0
TrafficCarModel[3] = voltic
TrafficCarPos[4] = <<-991.3395, 258.1681, 67.7794>>
TrafficCarQuatX[4] = -0.0273
TrafficCarQuatY[4] = 0.0303
TrafficCarQuatZ[4] = 0.7281
TrafficCarQuatW[4] = -0.6843
TrafficCarRecording[4] = 71
TrafficCarStartime[4] = 12480.0
TrafficCarModel[4] = Baller
TrafficCarPos[5] = <<-1069.2350, 209.9156, 61.2541>>
TrafficCarQuatX[5] = 0.0255
TrafficCarQuatY[5] = 0.0146
TrafficCarQuatZ[5] = 0.1780
TrafficCarQuatW[5] = 0.9836
TrafficCarRecording[5] = 7
TrafficCarStartime[5] = 13475.0
TrafficCarModel[5] = RapidGT
TrafficCarPos[6] = <<-1007.4832, 269.8612, 66.4751>>
TrafficCarQuatX[6] = -0.0376
TrafficCarQuatY[6] = -0.0134
TrafficCarQuatZ[6] = 0.7170
TrafficCarQuatW[6] = 0.6959
TrafficCarRecording[6] = 15
TrafficCarStartime[6] = 15000.0
TrafficCarModel[6] = rocoto
TrafficCarPos[7] = <<-1078.1970, 278.4990, 63.8791>>
TrafficCarQuatX[7] = 0.0064
TrafficCarQuatY[7] = -0.0266
TrafficCarQuatZ[7] = 0.3714
TrafficCarQuatW[7] = 0.9281
TrafficCarRecording[7] = 16
TrafficCarStartime[7] = 16225.0
TrafficCarModel[7] = Baller
TrafficCarPos[8] = <<-1064.9928, 270.3903, 63.4535>>
TrafficCarQuatX[8] = -0.0069
TrafficCarQuatY[8] = -0.0066
TrafficCarQuatZ[8] = 0.6859
TrafficCarQuatW[8] = 0.7276
TrafficCarRecording[8] = 18
TrafficCarStartime[8] = 17396.0
TrafficCarModel[8] = blista
TrafficCarPos[9] = <<-1084.0250, 290.5645, 63.6725>>
TrafficCarQuatX[9] = -0.0006
TrafficCarQuatY[9] = -0.0104
TrafficCarQuatZ[9] = 0.9994
TrafficCarQuatW[9] = 0.0340
TrafficCarRecording[9] = 19
TrafficCarStartime[9] = 18189.0
TrafficCarModel[9] = felon2
TrafficCarPos[10] = <<-1104.4526, 262.3094, 64.0965>>
TrafficCarQuatX[10] = -0.0328
TrafficCarQuatY[10] = 0.0305
TrafficCarQuatZ[10] = -0.7028
TrafficCarQuatW[10] = 0.7099
TrafficCarRecording[10] = 20
TrafficCarStartime[10] = 18960.0
TrafficCarModel[10] = rocoto
TrafficCarPos[11] = <<-1105.7966, 267.6655, 63.9132>>
TrafficCarQuatX[11] = -0.0315
TrafficCarQuatY[11] = 0.0297
TrafficCarQuatZ[11] = -0.6890
TrafficCarQuatW[11] = 0.7234
TrafficCarRecording[11] = 21
TrafficCarStartime[11] = 18990.0
TrafficCarModel[11] = prairie
TrafficCarPos[12] = <<-1118.2029, 260.7814, 64.8678>>
TrafficCarQuatX[12] = -0.0372
TrafficCarQuatY[12] = 0.0464
TrafficCarQuatZ[12] = -0.6148
TrafficCarQuatW[12] = 0.7865
TrafficCarRecording[12] = 22
TrafficCarStartime[12] = 19500.0
TrafficCarModel[12] = serrano
TrafficCarPos[13] = <<-1074.3485, 351.9871, 67.1602>>
TrafficCarQuatX[13] = 0.0396
TrafficCarQuatY[13] = -0.0133
TrafficCarQuatZ[13] = 0.0033
TrafficCarQuatW[13] = 0.9991
TrafficCarRecording[13] = 23
TrafficCarStartime[13] = 20950.0
TrafficCarModel[13] = dilettante
TrafficCarPos[14] = <<-1064.6390, 341.6877, 67.0819>>
TrafficCarQuatX[14] = 0.0006
TrafficCarQuatY[14] = -0.0231
TrafficCarQuatZ[14] = 0.6850
TrafficCarQuatW[14] = 0.7282
TrafficCarRecording[14] = 24
TrafficCarStartime[14] = 22890.0
TrafficCarModel[14] = rocoto
TrafficCarPos[15] = <<-1114.7520, 483.8648, 82.1372>>
TrafficCarQuatX[15] = -0.0001
TrafficCarQuatY[15] = -0.0011
TrafficCarQuatZ[15] = 0.9945
TrafficCarQuatW[15] = 0.1048
TrafficCarRecording[15] = 73
TrafficCarStartime[15] = 33000.0//32000.0 //32400.0
TrafficCarModel[15] = Baller
TrafficCarPos[16] = <<-1300.9729, 457.5321, 97.5162>>
TrafficCarQuatX[16] = -0.0343
TrafficCarQuatY[16] = 0.0347
TrafficCarQuatZ[16] = -0.6816
TrafficCarQuatW[16] = 0.7301
TrafficCarRecording[16] = 28
TrafficCarStartime[16] = 39850.0
TrafficCarModel[16] = felon
TrafficCarPos[17] = <<-1360.6454, 458.8226, 102.7037>>
TrafficCarQuatX[17] = 0.0295
TrafficCarQuatY[17] = -0.0343
TrafficCarQuatZ[17] = 0.7530
TrafficCarQuatW[17] = -0.6565
TrafficCarRecording[17] = 29
TrafficCarStartime[17] = 40850.0
TrafficCarModel[17] = cogcabrio
SetPieceCarPos[0] = <<-947.3407, 422.2456, 78.9748>>
SetPieceCarQuatX[0] = -0.0513
SetPieceCarQuatY[0] = -0.0036
SetPieceCarQuatZ[0] = 0.8378
SetPieceCarQuatW[0] = 0.5436
SetPieceCarRecording[0] = 2
SetPieceCarStartime[0] = 15000.0
SetPieceCarRecordingSpeed[0] = 0.8000
SetPieceCarModel[0] = Benson
SetPieceCarPos[1] = <<-1062.9193, 452.6988, 74.4478>>
SetPieceCarQuatX[1] = 0.0294
SetPieceCarQuatY[1] = -0.0410
SetPieceCarQuatZ[1] = 0.8439
SetPieceCarQuatW[1] = 0.5341
SetPieceCarRecording[1] = 70
SetPieceCarStartime[1] = 28912.0
SetPieceCarRecordingSpeed[1] = 1.0000
SetPieceCarModel[1] = cogcabrio
ENDPROC
PROC ADD_NAVMESH_BLOCKING_OBJECTS()
IF ( iNMBlockingObject01 = -1)
iNMBlockingObject01 = ADD_NAVMESH_BLOCKING_OBJECT(<< -1018.043, 642.159, 140.444 >>, << 18.0, 10.0, 4.0 >>, (-6.120 / 360.0) * 6.28)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Adding nav mesh blocking object iNMBlockingObject01.")
#ENDIF
ENDIF
IF ( iNMBlockingObject02 = -1)
iNMBlockingObject02 = ADD_NAVMESH_BLOCKING_OBJECT(<< -1032.143, 646.559, 140.444 >>, << 15.0, 9.0, 4.0 >>, (-27.0 / 360.0) * 6.28)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Adding nav mesh blocking object iNMBlockingObject02.")
#ENDIF
ENDIF
IF ( iNMBlockingObject03 = -1)
iNMBlockingObject03 = ADD_NAVMESH_BLOCKING_OBJECT(<< -1008.675, 641.048, 140.000 >>, << 5.0, 5.0, 4.0 >>, (-26.280 / 360.0) * 6.28)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Adding nav mesh blocking object iNMBlockingObject03.")
#ENDIF
ENDIF
ENDPROC
PROC REMOVE_NAVMESH_BLOCKING_OBJECTS()
IF ( iNMBlockingObject01 != -1)
REMOVE_NAVMESH_BLOCKING_OBJECT(iNMBlockingObject01)
iNMBlockingObject01 = -1
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Removing nav mesh blocking object iNMBlockingObject01.")
#ENDIF
ENDIF
IF ( iNMBlockingObject02 != -1)
REMOVE_NAVMESH_BLOCKING_OBJECT(iNMBlockingObject02)
iNMBlockingObject02 = -1
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Removing nav mesh blocking object iNMBlockingObject02.")
#ENDIF
ENDIF
IF ( iNMBlockingObject03 != -1)
REMOVE_NAVMESH_BLOCKING_OBJECT(iNMBlockingObject03)
iNMBlockingObject03 = -1
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Removing nav mesh blocking object iNMBlockingObject03.")
#ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Warps specified ped to new coordinates and sets specified ped's new heading.
/// PARAMS:
/// ped - PED_INDEX to warp.
/// vNewPosition - VECTOR coordinates specifying new ped's position.
/// fNewHeading - FLOAT specifying new ped's heading.
/// bKeepVehicle - Specifies if ped should keep vehicle they are currently in.
/// bResetGameplayCamera - Specifies if gameplay camera should be positioned behind player's back. Works only for PLAYER_PED_ID().
/// bLoadScene - Specifies if scene at new provided coordinates should be loaded. Works only for PLAYER_PED_ID().
PROC WARP_PED(PED_INDEX ped, VECTOR vNewPosition, FLOAT fNewHeading, BOOL bKeepVehicle, BOOL bResetGameplayCamera, BOOL bLoadScene)
IF NOT IS_PED_INJURED(ped)
IF ( bKeepVehicle = TRUE )
SET_PED_COORDS_KEEP_VEHICLE(ped, vNewPosition)
ELIF ( bKeepVehicle = FALSE )
SET_ENTITY_COORDS(ped, vNewPosition)
ENDIF
SET_ENTITY_HEADING(ped, fNewHeading)
IF ( ped = PLAYER_PED_ID())
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Warping player ped to coordinates ", vNewPosition, " and heading ", fNewHeading, ".")
#ENDIF
IF ( bResetGameplayCamera = TRUE)
SET_GAMEPLAY_CAM_RELATIVE_HEADING(0)
SET_GAMEPLAY_CAM_RELATIVE_PITCH(0)
ENDIF
IF ( bLoadScene = TRUE )
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Calling LOAD_SCENE() at coordinates ", vNewPosition, ". This might take a while to load.")
#ENDIF
LOAD_SCENE(vNewPosition)
ENDIF
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Returns PED_INDEX for specified player ped character from enumCharacterList.
/// PARAMS:
/// CHAR_TYPE - Character to get ped index for. For example CHAR_FRANKLIN, CHAR_TREVOR or CHAR_MICHAEL.
/// RETURNS:
/// PED_INDEX for the specified player ped character.
FUNC PED_INDEX GET_PED_INDEX(enumCharacterList CHAR_TYPE)
IF ( GET_CURRENT_PLAYER_PED_ENUM() = CHAR_TYPE )
RETURN PLAYER_PED_ID()
ELSE
RETURN sSelectorPeds.pedID[GET_SELECTOR_SLOT_FROM_PLAYER_PED_ENUM(CHAR_TYPE)]
ENDIF
ENDFUNC
PROC CALCULATE_VEHICLE_EXIT_DELAYS()
//return default values by default
iMichaelsVehicleExitDelay = 0
iFranklinsVehicleExitDelay = 250
IF NOT IS_PED_INJURED(GET_PED_INDEX(CHAR_MICHAEL))
AND NOT IS_PED_INJURED(GET_PED_INDEX(CHAR_FRANKLIN))
AND ARE_PEDS_IN_THE_SAME_VEHICLE(GET_PED_INDEX(CHAR_MICHAEL), GET_PED_INDEX(CHAR_FRANKLIN))
VEHICLE_INDEX VehicleIndex
VehicleIndex = GET_VEHICLE_PED_IS_USING(GET_PED_INDEX(CHAR_MICHAEL))
IF IS_PED_SITTING_IN_THIS_VEHICLE(GET_PED_INDEX(CHAR_MICHAEL), VehicleIndex)
AND IS_PED_SITTING_IN_THIS_VEHICLE(GET_PED_INDEX(CHAR_FRANKLIN), VehicleIndex)
SWITCH GET_PED_VEHICLE_SEAT(GET_PED_INDEX(CHAR_MICHAEL), VehicleIndex)
CASE VS_DRIVER
SWITCH GET_PED_VEHICLE_SEAT(GET_PED_INDEX(CHAR_FRANKLIN), VehicleIndex)
CASE VS_BACK_LEFT
iMichaelsVehicleExitDelay = 1250
iFranklinsVehicleExitDelay = 0
BREAK
DEFAULT
iMichaelsVehicleExitDelay = 0
iFranklinsVehicleExitDelay = 250
BREAK
ENDSWITCH
BREAK
CASE VS_BACK_LEFT
SWITCH GET_PED_VEHICLE_SEAT(GET_PED_INDEX(CHAR_FRANKLIN), VehicleIndex)
CASE VS_DRIVER
iMichaelsVehicleExitDelay = 0
iFranklinsVehicleExitDelay = 1250
BREAK
DEFAULT
iMichaelsVehicleExitDelay = 0
iFranklinsVehicleExitDelay = 250
BREAK
ENDSWITCH
BREAK
DEFAULT
iMichaelsVehicleExitDelay = 0
iFranklinsVehicleExitDelay = 250
BREAK
ENDSWITCH
ENDIF
ENDIF
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": iMichaelsVehicleExitDelay: ", iMichaelsVehicleExitDelay, ", iFranklinsVehicleExitDelay: ", iFranklinsVehicleExitDelay, ".")
#ENDIF
ENDPROC
PROC CALCULATE_PATH_NODES_AREA_FOR_POS(VECTOR vPosition)
IF ( vPosition.x < vMichaelsHousePosition.x )
fMinX = vPosition.x - 25.0
fMaxX = vMichaelsHousePosition.x + 25.0
ELIF ( vPosition.x > vMichaelsHousePosition.x )
fMinX = vMichaelsHousePosition.x - 25.0
fMaxX = vPosition.x + 25.0
ENDIF
IF ( vPosition.y < vMichaelsHousePosition.y )
fMinY = vPosition.y - 25.0
fMaxY = vMichaelsHousePosition.y + 25.0
ELIF ( vPosition.y > vMichaelsHousePosition.y )
fMinY = vMichaelsHousePosition.y - 25.0
fMaxY = vPosition.y + 25.0
ENDIF
ENDPROC
FUNC PED_INDEX GET_CLOSEST_PED_FROM_GROUP(PED_STRUCT &array[], INT &iOutIndex)
INT i = 0
INT iClosestIndex = -1
FLOAT fCurrentDistance = 0.0
FLOAT fShortestDistance = 500.0
FOR i = 0 TO (COUNT_OF(array) - 1)
IF DOES_ENTITY_EXIST(array[i].PedIndex)
IF NOT IS_ENTITY_DEAD(array[i].PedIndex)
fCurrentDistance = array[i].fDistanceToTarget
IF ( fCurrentDistance < fShortestDistance )
fShortestDistance = fCurrentDistance
iClosestIndex = i
ENDIF
ENDIF
ENDIF
ENDFOR
IF ( iClosestIndex = -1 )
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Could not find closest ped from specified ped group.")
#ENDIF
iOutIndex = iClosestIndex
RETURN NULL
ELSE
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Found closest ped ", array[iClosestIndex].sDebugName, " from ped group at distance ", array[iClosestIndex].fDistanceToTarget, " with index ", iClosestIndex, ".")
#ENDIF
iOutIndex = iClosestIndex
RETURN array[iClosestIndex].PedIndex
ENDIF
ENDFUNC
FUNC FLOAT GET_DISTANCE_TO_CLOSEST_PED_FROM_GROUPS(PED_STRUCT &array1[], PED_STRUCT &array2[])
INT i, k
GET_CLOSEST_PED_FROM_GROUP(array1, i)
GET_CLOSEST_PED_FROM_GROUP(array2, k)
IF ( i <> -1 AND k <> -1)
IF ( array1[i].fDistanceToTarget <= array2[k].fDistanceToTarget )
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Distance to closest ped ", array1[i].sDebugName, " is ", array1[i].fDistanceToTarget, ".")
#ENDIF
RETURN array1[i].fDistanceToTarget
ELSE
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Distance to closest ped ", array2[k].sDebugName, " is ", array2[k].fDistanceToTarget, ".")
#ENDIF
RETURN array2[k].fDistanceToTarget
ENDIF
ELSE
IF ( i <> -1 )
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Distance to closest ped ", array1[i].sDebugName, " is ", array1[i].fDistanceToTarget, ".")
#ENDIF
RETURN array1[i].fDistanceToTarget
ELIF ( k <> -1 )
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Distance to closest ped ", array2[k].sDebugName, " is ", array2[k].fDistanceToTarget, ".")
#ENDIF
RETURN array2[k].fDistanceToTarget
ENDIF
ENDIF
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Unable to return distance to closest ped from specified ped groups.")
#ENDIF
RETURN -1.0
ENDFUNC
FUNC VEHICLE_INDEX GET_CLOSEST_MISSION_VEHICLE_TO_ENTITY(ENTITY_INDEX EntityIndex, FLOAT fRadius, MODEL_NAMES ModelName)
VEHICLE_INDEX VehicleIndex
IF DOES_ENTITY_EXIST(EntityIndex)
VECTOR vPosition
vPosition = GET_ENTITY_COORDS(EntityIndex, FALSE)
VehicleIndex = GET_CLOSEST_VEHICLE(vPosition, fRadius, ModelName, VEHICLE_SEARCH_FLAG_RETURN_MISSION_VEHICLES |
VEHICLE_SEARCH_FLAG_RETURN_VEHICLES_CONTAINING_A_DEAD_OR_DYING_PED |
VEHICLE_SEARCH_FLAG_RETURN_VEHICLES_WITH_PEDS_ENTERING_OR_EXITING |
VEHICLE_SEARCH_FLAG_ALLOW_VEHICLE_OCCUPANTS_TO_BE_PERFORMING_A_SCRIPTED_TASK)
#IF IS_DEBUG_BUILD
IF DOES_ENTITY_EXIST(VehicleIndex)
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Found closest mission vehicle with model ", GET_MODEL_NAME_FOR_DEBUG(ModelName), " in radius ", fRadius, ".")
DRAW_DEBUG_LINE(GET_ENTITY_COORDS(EntityIndex, FALSE), GET_ENTITY_COORDS(VehicleIndex, FALSE), 255)
ELSE
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Not found any mission vehicles with model ", GET_MODEL_NAME_FOR_DEBUG(ModelName), " in radius ", fRadius, ".")
ENDIF
#ENDIF
ENDIF
RETURN VehicleIndex
ENDFUNC
FUNC BOOL IS_PED_SHOOTING_AT_ENTITY(PED_INDEX PedIndex, ENTITY_INDEX EntityIndex, BOOL bPlayerPed = FALSE, FLOAT fRadius = 7.5)
IF DOES_ENTITY_EXIST(PedIndex)
AND DOES_ENTITY_EXIST(EntityIndex)
IF NOT IS_ENTITY_DEAD(PedIndex)
AND NOT IS_ENTITY_DEAD(EntityIndex)
IF ( bPlayerPed = TRUE )
IF IS_BULLET_IN_AREA(GET_ENTITY_COORDS(EntityIndex), fRadius, bPlayerPed)
RETURN TRUE
ENDIF
ENDIF
IF HAS_ENTITY_BEEN_DAMAGED_BY_ENTITY(EntityIndex, PedIndex, FALSE)
IF HAS_ENTITY_BEEN_DAMAGED_BY_WEAPON(EntityIndex, WEAPONTYPE_INVALID, GENERALWEAPON_TYPE_ANYWEAPON)
RETURN TRUE
ENDIF
ENDIF
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
FUNC BOOL DOES_VEHICLE_HAVE_A_DRIVER(VEHICLE_INDEX VehicleIndex)
IF DOES_ENTITY_EXIST(VehicleIndex)
IF NOT IS_ENTITY_DEAD(VehicleIndex)
IF NOT IS_VEHICLE_SEAT_FREE(VehicleIndex, VS_DRIVER)
PED_INDEX DriverPedIndex
DriverPedIndex = GET_PED_IN_VEHICLE_SEAT(VehicleIndex, VS_DRIVER)
IF DOES_ENTITY_EXIST(DriverPedIndex)
IF NOT IS_ENTITY_DEAD(DriverPedIndex)
RETURN TRUE
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
FUNC PED_CLEANUP_REASONS GET_PED_CLEANUP_REASON(PED_STRUCT &ped)
IF DOES_ENTITY_EXIST(ped.PedIndex)
IF IS_ENTITY_DEAD(ped.PedIndex)
ENTITY_INDEX SourceOfDeathEntity
SourceOfDeathEntity = GET_PED_SOURCE_OF_DEATH(ped.PedIndex)
IF DOES_ENTITY_EXIST(SourceOfDeathEntity)
IF IS_ENTITY_A_PED(SourceOfDeathEntity)
PED_INDEX SourceOfDeathPed
SourceOfDeathPed = GET_PED_INDEX_FROM_ENTITY_INDEX(SourceOfDeathEntity)
IF ( SourceOfDeathPed = GET_PED_INDEX(CHAR_FRANKLIN) )
SWITCH GET_CURRENT_PLAYER_PED_ENUM()
CASE CHAR_MICHAEL
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Ped ", ped.sDebugName, " cleaned up with reason PED_CLEANUP_KILLED_BY_FRANKLIN.")
#ENDIF
RETURN PED_CLEANUP_KILLED_BY_FRANKLIN
BREAK
CASE CHAR_FRANKLIN
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Ped ", ped.sDebugName, " cleaned up with reason PED_CLEANUP_KILLED_BY_PLAYER_AS_FRANKLIN.")
#ENDIF
RETURN PED_CLEANUP_KILLED_BY_PLAYER_AS_FRANKLIN
BREAK
ENDSWITCH
ELIF ( SourceOfDeathPed = GET_PED_INDEX(CHAR_MICHAEL) )
SWITCH GET_CURRENT_PLAYER_PED_ENUM()
CASE CHAR_MICHAEL
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Ped ", ped.sDebugName, " cleaned up with reason PED_CLEANUP_KILLED_BY_PLAYER_AS_MICHAEL.")
#ENDIF
RETURN PED_CLEANUP_KILLED_BY_PLAYER_AS_MICHAEL
BREAK
CASE CHAR_FRANKLIN
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Ped ", ped.sDebugName, " cleaned up with reason PED_CLEANUP_KILLED_BY_MICHAEL.")
#ENDIF
RETURN PED_CLEANUP_KILLED_BY_MICHAEL
BREAK
ENDSWITCH
ELSE
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Ped ", ped.sDebugName, " cleaned up with reason PED_CLEANUP_LOST.")
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Ped ", ped.sDebugName, " source of death was a ped but not Franklin or Michael.")
#ENDIF
RETURN PED_CLEANUP_LOST
ENDIF
ELIF IS_ENTITY_A_VEHICLE(SourceOfDeathEntity)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Ped ", ped.sDebugName, " cleaned up with reason PED_CLEANUP_KILLED_BY_VEHICLE.")
#ENDIF
RETURN PED_CLEANUP_KILLED_BY_VEHICLE
ELSE
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Ped ", ped.sDebugName, " cleaned up with reason PED_CLEANUP_LOST.")
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Ped ", ped.sDebugName, " source of death was not a ped or vehicle.")
#ENDIF
RETURN PED_CLEANUP_LOST
ENDIF
ELSE
ped.iCleanupAttempts++
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Ped ", ped.sDebugName, " source of death does not exist.")
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Ped ", ped.sDebugName, " had ", ped.iCleanupAttempts, " cleanup attempts .")
#ENDIF
IF ( ped.iCleanupAttempts = 10 )
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Ped ", ped.sDebugName, " cleaned up with reason PED_CLEANUP_LOST due to cleanup attempts running out.")
#ENDIF
RETURN PED_CLEANUP_LOST
ENDIF
ENDIF
ENDIF
ENDIF
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Ped ", ped.sDebugName, " cleaned up with reason PED_CLEANUP_NO_CLEANUP.")
#ENDIF
RETURN PED_CLEANUP_NO_CLEANUP
ENDFUNC
PROC UPDATE_PLAYER_AND_BUDDY_KILL_COUNTERS(PED_CLEANUP_REASONS eCleanupReason, INT &iPlayerKillsAsMichael, INT &iPlayerKillsAsFranklin,
INT &iBuddyKillsAsMichael, INT &iBuddyKillsAsFranklin)
SWITCH eCleanupReason
CASE PED_CLEANUP_KILLED_BY_PLAYER_AS_MICHAEL
iPlayerKillsAsMichael++
INFORM_MISSION_STATS_OF_INCREMENT(FAM3_KILLS) //increment mission stat for kills
IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
INFORM_MISSION_STATS_OF_INCREMENT(FAM3_VEHICLE_KILLS) //increment mission stat for from vehicle kills
ENDIF
BREAK
CASE PED_CLEANUP_KILLED_BY_PLAYER_AS_FRANKLIN
iPlayerKillsAsFranklin++
INFORM_MISSION_STATS_OF_INCREMENT(FAM3_KILLS) //increment mission stat
IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
INFORM_MISSION_STATS_OF_INCREMENT(FAM3_VEHICLE_KILLS) //increment mission stat for from vehicle kills
ENDIF
BREAK
CASE PED_CLEANUP_KILLED_BY_MICHAEL
iBuddyKillsAsMichael++
BREAK
CASE PED_CLEANUP_KILLED_BY_FRANKLIN
iBuddyKillsAsFranklin++
BREAK
ENDSWITCH
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": *********************** UPDATE_PLAYER_AND_BUDDY_KILL_COUNTERS *************************")
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Player kills as Michael: ", iPlayerKillsAsMichael, ". Player kills as Franklin: ", iPlayerKillsAsFranklin, ".")
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Buddy kills as Michael: ", iBuddyKillsAsMichael, ". Buddy kills as Franklin: ", iBuddyKillsAsFranklin, ".")
PRINTLN(GET_THIS_SCRIPT_NAME(), ": ***************************************************************************************")
#ENDIF
ENDPROC
PROC SET_MISSION_PED_PROPERTIES(PED_INDEX PedIndex, REL_GROUP_HASH relGroupHash, BOOL bCanFlyThroughWindscreen, BOOL bKeepRelGroupOnCleanup,
BOOL bCanBeTargetted, BOOL bIsEnemy)
IF DOES_ENTITY_EXIST(PedIndex)
IF NOT IS_PED_INJURED(PedIndex)
SET_PED_INFINITE_AMMO(PedIndex, FALSE)
SET_PED_AS_ENEMY(PedIndex, bIsEnemy)
SET_PED_CAN_BE_TARGETTED(PedIndex, bCanBeTargetted)
SET_PED_RELATIONSHIP_GROUP_HASH(PedIndex, relGroupHash)
SET_PED_CONFIG_FLAG(PedIndex, PCF_WillFlyThroughWindscreen, bCanFlyThroughWindscreen)
SET_PED_CONFIG_FLAG(PedIndex, PCF_KeepRelationshipGroupAfterCleanUp, bKeepRelGroupOnCleanup)
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(PedIndex, TRUE)
ENDIF
ENDIF
ENDPROC
FUNC BOOL IS_ENTITY_PLAYING_LOOK_BEHIND_ANIM(ENTITY_INDEX EntityIndex)
IF DOES_ENTITY_EXIST(EntityIndex)
IF NOT IS_ENTITY_DEAD(EntityIndex)
IF IS_ENTITY_PLAYING_ANIM(EntityIndex, "missfam3", "incar_lookbehind_enter_driver")
OR IS_ENTITY_PLAYING_ANIM(EntityIndex, "missfam3", "incar_lookbehind_idle_driver")
OR IS_ENTITY_PLAYING_ANIM(EntityIndex, "missfam3", "incar_lookbehind_exit_driver")
OR IS_ENTITY_PLAYING_ANIM(EntityIndex, "missfam3", "incar_lookbehind_enter_passenger")
OR IS_ENTITY_PLAYING_ANIM(EntityIndex, "missfam3", "incar_lookbehind_idle_passenger")
OR IS_ENTITY_PLAYING_ANIM(EntityIndex, "missfam3", "incar_lookbehind_exit_passenger")
RETURN TRUE
ENDIF
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
PROC TASK_PLAY_LOOK_BEHIND_ANIM(PED_INDEX PedIndex, VEHICLE_SEAT eSeat, INT iTime = -1, ANIMATION_FLAGS Animflags = AF_DEFAULT)
IF DOES_ENTITY_EXIST(PedIndex)
IF NOT IS_ENTITY_DEAD(PedIndex)
STRING sEnterAnim
STRING sLoopAnim
STRING sExitAnim
SEQUENCE_INDEX SequenceIndex
SWITCH eSeat
CASE VS_DRIVER
CASE VS_BACK_LEFT
sEnterAnim = "incar_lookbehind_enter_driver"
sLoopAnim = "incar_lookbehind_idle_driver"
sExitAnim = "incar_lookbehind_exit_driver"
BREAK
CASE VS_FRONT_RIGHT
CASE VS_BACK_RIGHT
sEnterAnim = "incar_lookbehind_enter_passenger"
sLoopAnim = "incar_lookbehind_idle_passenger"
sExitAnim = "incar_lookbehind_exit_passenger"
BREAK
ENDSWITCH
CLEAR_SEQUENCE_TASK(SequenceIndex)
OPEN_SEQUENCE_TASK(SequenceIndex)
TASK_PLAY_ANIM(NULL, "missfam3", sEnterAnim, SLOW_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_UPPERBODY | Animflags)
TASK_PLAY_ANIM(NULL, "missfam3", sLoopAnim, NORMAL_BLEND_IN, NORMAL_BLEND_OUT, iTime, AF_UPPERBODY | Animflags | AF_LOOPING)
TASK_PLAY_ANIM(NULL, "missfam3", sExitAnim, NORMAL_BLEND_IN, SLOW_BLEND_OUT, -1, AF_UPPERBODY | Animflags)
CLOSE_SEQUENCE_TASK(SequenceIndex)
TASK_PERFORM_SEQUENCE(PedIndex, SequenceIndex)
CLEAR_SEQUENCE_TASK(SequenceIndex)
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Creates a ped or player ped to be used by player and returns TRUE if such pad was created successfully.
/// PARAMS:
/// psPed - PED_STRUCT containg ped details, like PED_INDEX, blip, coordinates, heading, model etc.
/// bPlayerPed - Boolean indicating if a player ped or NPC ped should be created.
/// relGroupHash - Relationship group hash for the created ped.
/// bCreateBlip - Boolean indicating if a blip for this ped should be created.
/// eCharacter - Enum specifying character from story characters list. Use NO_CHARACTER for characters not stored in that list and provide a MODEL_NAMES in PED_STRUCT.
/// bCanFlyThroughWindscreen - Sets if ped can fly through windscreen when car crashes.
/// bCanBeTargetted - Sets if ped can be targetted by player.
/// bIsEnemy - Sets if ped is considered an enemy.
/// VehicleIndex - Specify a vehicle index if ped should be created inside a vehicle. IF not use NULL.
/// eVehicleSeat - Vehicle seat enum for peds created in vehicles.
/// RETURNS:
/// TRUE if ped was created successfully, FALSE if otherwise.
FUNC BOOL HAS_MISSION_PED_BEEN_CREATED(PED_STRUCT &psPed, BOOL bPlayerPed, REL_GROUP_HASH relGroupHash, BOOL bCreateBlip, enumCharacterList eCharacter,
BOOL bCanFlyThroughWindscreen = FALSE, BOOL bCanBeTargetted = FALSE, BOOL bIsEnemy = FALSE, VEHICLE_INDEX VehicleIndex = NULL,
VEHICLE_SEAT eVehicleSeat = VS_DRIVER, BOOL bKeepRelGroupOnCleanup = TRUE #IF IS_DEBUG_BUILD, STRING sDebugName = NULL #ENDIF)
IF ( bPlayerPed = FALSE ) //create non player ped
IF NOT DOES_ENTITY_EXIST(psPed.PedIndex)
REQUEST_MODEL(psPed.ModelName)
IF HAS_MODEL_LOADED(psPed.ModelName)
IF ( VehicleIndex = NULL ) //create ped outside of vehicle
IF ( eCharacter = NO_CHARACTER ) //use MODEL_NAMES stored in the PED_STRUCT if no character was specified
psPed.PedIndex = CREATE_PED(PEDTYPE_MISSION, psPed.ModelName, psPed.vPosition, psPed.fHeading)
SET_MODEL_AS_NO_LONGER_NEEDED(psPed.ModelName)
ELSE //use character name to define the ped MODEL_NAMES
IF CREATE_NPC_PED_ON_FOOT(psPed.PedIndex, eCharacter, psPed.vPosition, psPed.fHeading)
SET_MODEL_AS_NO_LONGER_NEEDED(psPed.ModelName)
ENDIF
ENDIF
IF NOT IS_PED_INJURED(psPed.PedIndex)
SET_MISSION_PED_PROPERTIES(psPed.PedIndex, relGroupHash, bCanFlyThroughWindscreen, bKeepRelGroupOnCleanup,
bCanBeTargetted, bIsEnemy)
IF ( bCreateBlip = TRUE )
psPed.BlipIndex = CREATE_BLIP_FOR_ENTITY(psPed.PedIndex, FALSE)
ENDIF
ENDIF
#IF IS_DEBUG_BUILD
IF NOT Is_String_Null_Or_Empty(sDebugName)
SET_PED_NAME_DEBUG(psPed.PedIndex, sDebugName)
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Created mission ped ", sDebugName, " with model ", GET_MODEL_NAME_FOR_DEBUG(psPed.ModelName), " at coordinates ", psPed.vPosition, ".")
ELSE
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Created mission ped with model ", GET_MODEL_NAME_FOR_DEBUG(psPed.ModelName), " at coordinates ", psPed.vPosition, ".")
ENDIF
#ENDIF
RETURN TRUE
ELIF ( VehicleIndex != NULL ) //create ped in a vehicle
IF IS_VEHICLE_DRIVEABLE(VehicleIndex)
IF ( eCharacter = NO_CHARACTER ) //use MODEL_NAMES stored in the PED_STRUCT
psPed.PedIndex = CREATE_PED_INSIDE_VEHICLE(VehicleIndex, PEDTYPE_MISSION, psPed.ModelName, eVehicleSeat)
SET_MODEL_AS_NO_LONGER_NEEDED(psPed.ModelName)
ELSE //use character name to define the ped MODEL_NAMES
IF CREATE_NPC_PED_INSIDE_VEHICLE(psPed.PedIndex, eCharacter, VehicleIndex, eVehicleSeat)
SET_MODEL_AS_NO_LONGER_NEEDED(psPed.ModelName)
ENDIF
ENDIF
IF NOT IS_PED_INJURED(psPed.PedIndex)
SET_MISSION_PED_PROPERTIES(psPed.PedIndex, relGroupHash, bCanFlyThroughWindscreen, bKeepRelGroupOnCleanup,
bCanBeTargetted, bIsEnemy)
IF ( bCreateBlip = TRUE )
psPed.BlipIndex = CREATE_BLIP_FOR_ENTITY(psPed.PedIndex, FALSE)
ENDIF
ENDIF
#IF IS_DEBUG_BUILD
IF NOT Is_String_Null_Or_Empty(sDebugName)
SET_PED_NAME_DEBUG(psPed.PedIndex, sDebugName)
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Created mission ped ", sDebugName, " with model ", GET_MODEL_NAME_FOR_DEBUG(psPed.ModelName), " in vehicle.")
ELSE
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Created mission ped with model ", GET_MODEL_NAME_FOR_DEBUG(psPed.ModelName), " in vehicle.")
ENDIF
#ENDIF
RETURN TRUE
ENDIF
ENDIF
ENDIF
ELSE
//if the ped already exists return true
RETURN TRUE
ENDIF
ELIF ( bPlayerPed = TRUE ) //create player ped, for example a ped that player can hotswap to and take control of
IF NOT DOES_ENTITY_EXIST(psPed.PedIndex)
IF ( VehicleIndex = NULL ) //create player ped outside of vehicle
IF CREATE_PLAYER_PED_ON_FOOT(psPed.PedIndex, eCharacter, psPed.vPosition, psPed.fHeading, TRUE)
SET_MISSION_PED_PROPERTIES(psPed.PedIndex, relGroupHash, bCanFlyThroughWindscreen, bKeepRelGroupOnCleanup,
bCanBeTargetted, bIsEnemy)
IF ( bCreateBlip = TRUE )
psPed.BlipIndex = CREATE_BLIP_FOR_ENTITY(psPed.PedIndex, FALSE)
ENDIF
#IF IS_DEBUG_BUILD
IF NOT Is_String_Null_Or_Empty(sDebugName)
SET_PED_NAME_DEBUG(psPed.PedIndex, sDebugName)
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Created player ped ", sDebugName, " with model ", GET_MODEL_NAME_FOR_DEBUG(psPed.ModelName), " at coordinates ", psPed.vPosition, ".")
ELSE
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Created player ped with model ", GET_MODEL_NAME_FOR_DEBUG(psPed.ModelName), " at coordinates ", psPed.vPosition, ".")
ENDIF
#ENDIF
RETURN TRUE
ENDIF
ELIF ( VehicleIndex != NULL ) //create player ped in a vehicle
IF IS_VEHICLE_DRIVEABLE(VehicleIndex)
IF CREATE_PLAYER_PED_INSIDE_VEHICLE(psPed.PedIndex, eCharacter, VehicleIndex, eVehicleSeat, TRUE)
SET_MISSION_PED_PROPERTIES(psPed.PedIndex, relGroupHash, bCanFlyThroughWindscreen, bKeepRelGroupOnCleanup,
bCanBeTargetted, bIsEnemy)
IF ( bCreateBlip = TRUE )
psPed.BlipIndex = CREATE_BLIP_FOR_ENTITY(psPed.PedIndex, FALSE)
ENDIF
#IF IS_DEBUG_BUILD
IF NOT Is_String_Null_Or_Empty(sDebugName)
SET_PED_NAME_DEBUG(psPed.PedIndex, sDebugName)
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Created player ped ", sDebugName, " in vehicle with model ", GET_MODEL_NAME_FOR_DEBUG(psPed.ModelName), ".")
ELSE
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Created player ped in vehicle with model ", GET_MODEL_NAME_FOR_DEBUG(psPed.ModelName), ".")
ENDIF
#ENDIF
RETURN TRUE
ENDIF
ENDIF
ENDIF
ELSE
//if the ped already exists, return true
RETURN TRUE
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
PROC SET_MISSION_VEHICLE_PROPERTIES(VEH_STRUCT &vsVehicle, BOOL bMissionCritical = TRUE, INT iColourCombination = -1, INT iColour1 = -1,
INT iColour2 = -1, INT iColour3 = 0, INT iColour4 = 0 #IF IS_DEBUG_BUILD, STRING sDebugName = NULL #ENDIF)
IF DOES_ENTITY_EXIST(vsVehicle.VehicleIndex)
IF NOT IS_ENTITY_DEAD(vsVehicle.VehicleIndex)
//make sure doors are unlocked
SET_VEHICLE_DOORS_LOCKED(vsVehicle.VehicleIndex, VEHICLELOCK_UNLOCKED)
SET_VEHICLE_HAS_STRONG_AXLES(vsVehicle.VehicleIndex, bMissionCritical)
//limit damage that can be done to the vehicle
SET_VEHICLE_CAN_LEAK_OIL(vsVehicle.VehicleIndex, NOT bMissionCritical)
SET_VEHICLE_CAN_LEAK_PETROL(vsVehicle.VehicleIndex, NOT bMissionCritical)
//make the vehicle not attach to tow truck if mission critical
SET_VEHICLE_AUTOMATICALLY_ATTACHES(vsVehicle.VehicleIndex, NOT bMissionCritical)
IF IS_THIS_MODEL_A_CAR(vsVehicle.ModelName)
SET_DOOR_ALLOWED_TO_BE_BROKEN_OFF(vsVehicle.VehicleIndex, SC_DOOR_FRONT_LEFT, NOT bMissionCritical)
SET_DOOR_ALLOWED_TO_BE_BROKEN_OFF(vsVehicle.VehicleIndex, SC_DOOR_FRONT_RIGHT, NOT bMissionCritical)
SET_VEHICLE_TYRES_CAN_BURST(vsVehicle.VehicleIndex, NOT bMissionCritical)
ENDIF
//set vehicle colours, if they are provided
IF ( iColour1 != -1)
AND ( iColour2 != -1 )
SET_VEHICLE_COLOURS(vsVehicle.VehicleIndex, iColour1, iColour2)
ENDIF
//set vehicle colour combination, if it is provided
IF ( iColourCombination != -1 )
SET_VEHICLE_COLOUR_COMBINATION(vsVehicle.VehicleIndex, iColourCombination)
ENDIF
SET_VEHICLE_EXTRA_COLOURS(vsVehicle.VehicleIndex, iColour3, iColour4)
#IF IS_DEBUG_BUILD
IF NOT Is_String_Null_Or_Empty(sDebugName)
SET_VEHICLE_NAME_DEBUG(vsVehicle.VehicleIndex, sDebugName)
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Set mission vehicle properties for vehicle ", sDebugName, " with model ", GET_MODEL_NAME_FOR_DEBUG(vsVehicle.ModelName), ".")
ELSE
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Set mission vehicle properties for vehicle with model ", GET_MODEL_NAME_FOR_DEBUG(vsVehicle.ModelName), ".")
ENDIF
#ENDIF
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Creates vehicle to be used on a mission by player and returns TRUE if such vehicle was created successfully.
/// PARAMS:
/// vsVehicle - VEH_STRUCT containing model, position and heading of the vehicle.
/// bPlayerVehicle - If set to TRUE will create player specific vehicles using CREATE_PLAYER_VEHICLE()
/// bCarStealVehicle - If set to TRUE will create car steal strand vehicle with a specific command. Works when bPlayerVehicle is FALSE.
/// eCharacter - Character enum indicating which character specific vehicle to create.
/// bMissionCritical - Sets the vehicle to be unable to leak oil/petrol and break off doors. Set to TRUE to stop these damage types to vehicle.
/// iColourCombination - Colour combination of the vehicle.
/// iColour1 - Colour 1 of the vehicle.
/// iColour2 - Colour 2 of the vehicle.
/// RETURNS:
/// TRUE if vehicle was created, FALSE if otherwise.
FUNC BOOL HAS_MISSION_VEHICLE_BEEN_CREATED(VEH_STRUCT &vsVehicle, BOOL bPlayerVehicle = FALSE, BOOL bCarStealVehicle = FALSE, enumCharacterList eCharacter = CHAR_MICHAEL,
BOOL bMissionCritical = TRUE, INT iColourCombination = -1, INT iColour1 = -1, INT iColour2 = -1,
INT iColour3 = 0, INT iColour4 = 0 #IF IS_DEBUG_BUILD, STRING sDebugName = NULL #ENDIF)
//create any vehicle that can be used on a mission by player
IF ( bPlayerVehicle = FALSE )
IF NOT DOES_ENTITY_EXIST(vsVehicle.VehicleIndex)
REQUEST_MODEL(vsVehicle.ModelName)
IF HAS_MODEL_LOADED(vsVehicle.ModelName)
IF( bCarStealVehicle = TRUE )
vsVehicle.VehicleIndex = CREATE_CAR_STEAL_STRAND_CAR(vsVehicle.ModelName, vsVehicle.vPosition, vsVehicle.fHeading)
SET_MODEL_AS_NO_LONGER_NEEDED(vsVehicle.ModelName)
ELSE
IF ( eCharacter = NO_CHARACTER )
vsVehicle.VehicleIndex = CREATE_VEHICLE(vsVehicle.ModelName, vsVehicle.vPosition, vsVehicle.fHeading)
SET_MODEL_AS_NO_LONGER_NEEDED(vsVehicle.ModelName)
ELSE //create npc vehicle based on the character enum specified
IF CREATE_NPC_VEHICLE(vsVehicle.VehicleIndex, eCharacter, vsVehicle.vPosition, vsVehicle.fHeading)
SET_MODEL_AS_NO_LONGER_NEEDED(vsVehicle.ModelName)
ENDIF
ENDIF
ENDIF
IF IS_VEHICLE_DRIVEABLE(vsVehicle.VehicleIndex)
//set vehicle colours, if they are provided
IF ( iColour1 != -1)
AND ( iColour2 != -1 )
SET_VEHICLE_COLOURS(vsVehicle.VehicleIndex, iColour1, iColour2)
ENDIF
//set vehicle colour combination, if it is provided
IF ( iColourCombination != -1 )
SET_VEHICLE_COLOUR_COMBINATION(vsVehicle.VehicleIndex, iColourCombination)
ENDIF
SET_VEHICLE_EXTRA_COLOURS(vsVehicle.VehicleIndex, iColour3, iColour4)
SET_VEHICLE_HAS_STRONG_AXLES(vsVehicle.VehicleIndex, bMissionCritical)
//limit damage that can be done to the vehicle
SET_VEHICLE_CAN_LEAK_OIL(vsVehicle.VehicleIndex, NOT bMissionCritical)
SET_VEHICLE_CAN_LEAK_PETROL(vsVehicle.VehicleIndex, NOT bMissionCritical)
//make the vehicle not attach to tow truck if mission critical
SET_VEHICLE_AUTOMATICALLY_ATTACHES(vsVehicle.VehicleIndex, NOT bMissionCritical)
IF IS_THIS_MODEL_A_CAR(vsVehicle.ModelName)
SET_DOOR_ALLOWED_TO_BE_BROKEN_OFF(vsVehicle.VehicleIndex, SC_DOOR_FRONT_LEFT, NOT bMissionCritical)
SET_DOOR_ALLOWED_TO_BE_BROKEN_OFF(vsVehicle.VehicleIndex, SC_DOOR_FRONT_RIGHT, NOT bMissionCritical)
SET_VEHICLE_TYRES_CAN_BURST(vsVehicle.VehicleIndex, NOT bMissionCritical)
ENDIF
SET_VEHICLE_ON_GROUND_PROPERLY(vsVehicle.VehicleIndex)
ENDIF
#IF IS_DEBUG_BUILD
IF NOT Is_String_Null_Or_Empty(sDebugName)
SET_VEHICLE_NAME_DEBUG(vsVehicle.VehicleIndex, sDebugName)
IF ( bCarStealVehicle = TRUE )
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Created car steal strand vehicle ", sDebugName, " with model ", GET_MODEL_NAME_FOR_DEBUG(vsVehicle.ModelName), " at coordinates ", vsVehicle.vPosition, " and heading ", vsVehicle.fHeading, ".")
ELSE
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Created vehicle ", sDebugName, " with model ", GET_MODEL_NAME_FOR_DEBUG(vsVehicle.ModelName), " at coordinates ", vsVehicle.vPosition, " and heading ", vsVehicle.fHeading, ".")
ENDIF
ELSE
IF ( bCarStealVehicle = TRUE )
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Created car steal strand vehicle with model ", GET_MODEL_NAME_FOR_DEBUG(vsVehicle.ModelName), " at coordinates ", vsVehicle.vPosition, " and heading ", vsVehicle.fHeading, ".")
ELSE
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Created vehicle with model ", GET_MODEL_NAME_FOR_DEBUG(vsVehicle.ModelName), " at coordinates ", vsVehicle.vPosition, " and heading ", vsVehicle.fHeading, ".")
ENDIF
ENDIF
#ENDIF
RETURN TRUE
ENDIF
ELSE //if the vehicle exists, return true
RETURN TRUE
ENDIF
//create player specific vehicle
ELIF ( bPlayerVehicle = TRUE )
IF NOT DOES_ENTITY_EXIST(vsVehicle.VehicleIndex)
//call the player vehicle creation until it returns true
IF CREATE_PLAYER_VEHICLE(vsVehicle.VehicleIndex, eCharacter, vsVehicle.vPosition, vsVehicle.fHeading, TRUE)
SET_VEHICLE_HAS_STRONG_AXLES(vsVehicle.VehicleIndex, bMissionCritical)
//limit damage that can be done to the vehicle
SET_VEHICLE_CAN_LEAK_OIL(vsVehicle.VehicleIndex, NOT bMissionCritical)
SET_VEHICLE_CAN_LEAK_PETROL(vsVehicle.VehicleIndex, NOT bMissionCritical)
//make the vehicle not attach to tow truck if mission critical
SET_VEHICLE_AUTOMATICALLY_ATTACHES(vsVehicle.VehicleIndex, NOT bMissionCritical)
IF IS_THIS_MODEL_A_CAR(vsVehicle.ModelName)
SET_DOOR_ALLOWED_TO_BE_BROKEN_OFF(vsVehicle.VehicleIndex, SC_DOOR_FRONT_LEFT, NOT bMissionCritical)
SET_DOOR_ALLOWED_TO_BE_BROKEN_OFF(vsVehicle.VehicleIndex, SC_DOOR_FRONT_RIGHT, NOT bMissionCritical)
SET_VEHICLE_TYRES_CAN_BURST(vsVehicle.VehicleIndex, NOT bMissionCritical)
ENDIF
#IF IS_DEBUG_BUILD
IF NOT Is_String_Null_Or_Empty(sDebugName)
SET_VEHICLE_NAME_DEBUG(vsVehicle.VehicleIndex, sDebugName)
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Created player vehicle ", sDebugName, " with model ", GET_MODEL_NAME_FOR_DEBUG(vsVehicle.ModelName), " at coordinates ", vsVehicle.vPosition, " and heading ", vsVehicle.fHeading, ".")
ELSE
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Created player vehicle with model ", GET_MODEL_NAME_FOR_DEBUG(vsVehicle.ModelName), " at coordinates ", vsVehicle.vPosition, " and heading ", vsVehicle.fHeading, ".")
ENDIF
#ENDIF
RETURN TRUE
ENDIF
ELSE //if the vehicle exists, return true
RETURN TRUE
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
FUNC BOOL IS_PLAYER_IN_CONTROL_OF_VEHICLE(VEHICLE_INDEX VehicleIndex)
INT iLeftStickX, iLeftStickY, iRightStickX, iRightStickY
IF IS_VEHICLE_DRIVEABLE(VehicleIndex)
IF IS_PED_IN_VEHICLE(PLAYER_PED_ID(), VehicleIndex)
GET_CONTROL_VALUE_OF_ANALOGUE_STICKS(iLeftStickX, iLeftStickY, iRightStickX, iRightStickY)
IF (iLeftStickX < -20 OR iLeftStickX > 20)
OR (iLeftStickY < -20 OR iLeftStickY > 20)
OR IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_VEH_ACCELERATE)
OR IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_VEH_BRAKE)
OR IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_VEH_HANDBRAKE)
OR IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_VEH_EXIT)
OR IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_VEH_HEADLIGHT)
OR IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_VEH_HORN)
CLEAR_PED_TASKS(PLAYER_PED_ID())
RETURN TRUE
ENDIF
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// Creates an object and returns TRUE if such object was created successfully.
/// PARAMS:
/// osObject - OBJECT_STRUCT containing model, position and rotation of the object.
/// bFreezeObject - Specify if this object's position should be frozen.
/// RETURNS:
/// TRUE if object was created, FALSE if otherwise.
FUNC BOOL HAS_MISSION_OBJECT_BEEN_CREATED(OBJECT_STRUCT &osObject, BOOL bFreezeObject = FALSE)
IF NOT DOES_ENTITY_EXIST(osObject.ObjectIndex)
REQUEST_MODEL(osObject.ModelName)
IF HAS_MODEL_LOADED(osObject.ModelName)
osObject.ObjectIndex = CREATE_OBJECT(osObject.ModelName, osObject.vPosition)
SET_ENTITY_COORDS_NO_OFFSET(osObject.ObjectIndex, osObject.vPosition)
SET_ENTITY_ROTATION(osObject.ObjectIndex, osObject.vRotation)
FREEZE_ENTITY_POSITION(osObject.ObjectIndex, bFreezeObject)
SET_ENTITY_INVINCIBLE(osObject.ObjectIndex, TRUE)
SET_MODEL_AS_NO_LONGER_NEEDED(osObject.ModelName)
ENDIF
ENDIF
IF DOES_ENTITY_EXIST(osObject.ObjectIndex)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Created object with model ", GET_MODEL_NAME_FOR_DEBUG(osObject.ModelName), " at coordinates ", osObject.vPosition, ".")
#ENDIF
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// Performs a screen fade in with a wait for a specified time.
/// PARAMS:
/// iTime - Duration of the fade in miliseconds.
PROC DO_SAFE_SCREEN_FADE_IN(INT iTime)
IF NOT IS_SCREEN_FADED_IN()
DO_SCREEN_FADE_IN(iTime)
WHILE NOT IS_SCREEN_FADED_IN()
WAIT(0)
ENDWHILE
ENDIF
ENDPROC
/// PURPOSE:
/// Performs a screen fade out with a wait for a specified time.
/// PARAMS:
/// iTime - Duration of the fade in miliseconds.
PROC DO_SAFE_SCREEN_FADE_OUT(INT iTime)
IF NOT IS_SCREEN_FADED_OUT()
DO_SCREEN_FADE_OUT(iTime)
WHILE NOT IS_SCREEN_FADED_OUT()
WAIT(0)
ENDWHILE
ENDIF
ENDPROC
/// PURPOSE:
/// Stops an active mocap cutscene and waits until it has finished.
PROC DO_SAFE_STOP_CUTSCENE()
IF IS_CUTSCENE_PLAYING()
SET_CUTSCENE_FADE_VALUES(FALSE, FALSE, FALSE, FALSE)
STOP_CUTSCENE(TRUE)
SET_SCRIPTS_SAFE_FOR_CUTSCENE(FALSE) //needs to be called to make sure all scripted systems work correctly when cutscene is skipped
ENDIF
WHILE NOT HAS_CUTSCENE_FINISHED()
WAIT(0)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Waiting for the cutscene to finish.")
#ENDIF
ENDWHILE
ENDPROC
/// PURPOSE:
/// Checks if the specified mocap cutscene has loaded.
/// Removes any other loaded mocap cutscene and requests the specified cutscene until it is loaded.
/// PARAMS:
/// sSceneName - Mocap cutscene name to check for being loaded.
/// CutsceneSection - Cutscene section specifying at what section to start the cutscene. Use CS_SECTION_1 to play from start.
/// RETURNS:
/// TRUE if the specified cutscene has loaded, FALSE if otherwise.
FUNC BOOL HAS_REQUESTED_CUTSCENE_LOADED(STRING sSceneName, CUTSCENE_SECTION CutsceneSection = CS_SECTION_1)
//check if the specified cutscene has loaded first
IF HAS_THIS_CUTSCENE_LOADED_WITH_FAILSAFE(sSceneName)
RETURN TRUE
ELSE
//if the expected reuqested cutscene has not loaded, but there already is a loaded cutscene
//then remove it and keep requesting specified mocap cutscene
IF HAS_CUTSCENE_LOADED_WITH_FAILSAFE()
REMOVE_CUTSCENE()
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": HAS_REQUESTED_CUTSCENE_LOADED() Removing cutscene from memory, because cutscene ", sSceneName, " was expected to be loaded.")
#ENDIF
ENDIF
IF ( CutsceneSection = CS_SECTION_1)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Cutscene ", sSceneName, " is loading.")
#ENDIF
//if the cutscene is not loaded, keep requesting it
REQUEST_CUTSCENE(sSceneName)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Requesting ", sSceneName, ".")
#ENDIF
ELSE
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Cutscene ", sSceneName, " is loading with playback list.")
#ENDIF
//if the cutscene is not loaded, keep requesting it
REQUEST_CUTSCENE_WITH_PLAYBACK_LIST(sSceneName, CutsceneSection)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Requesting ", sSceneName, " cutscene with playback list.")
#ENDIF
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
FUNC BOOL IS_VEHICLE_REVERSING(VEHICLE_INDEX VehicleIndex)
IF DOES_ENTITY_EXIST(VehicleIndex)
IF IS_VEHICLE_DRIVEABLE(VehicleIndex)
VECTOR vVelocity = GET_ENTITY_SPEED_VECTOR(VehicleIndex, TRUE)
IF ( vVelocity.y < -1.0 )
RETURN TRUE
ENDIF
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
FUNC BOOL IS_THIS_CONVERSATION_PLAYING(STRING sRoot)
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
TEXT_LABEL txtRoot = GET_CURRENTLY_PLAYING_STANDARD_CONVERSATION_ROOT()
IF ARE_STRINGS_EQUAL(sRoot, txtRoot)
RETURN TRUE
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
PROC REMOVE_LABEL_ARRAY_SPACES()
INT iArrayLength = COUNT_OF(iTriggeredTextHashes)
INT i = 0
REPEAT (iArrayLength - 1) i
IF iTriggeredTextHashes[i] = 0
IF iTriggeredTextHashes[i+1] != 0
iTriggeredTextHashes[i] = iTriggeredTextHashes[i+1]
iTriggeredTextHashes[i+1] = 0
ENDIF
ENDIF
ENDREPEAT
ENDPROC
FUNC INT GET_LABEL_INDEX(INT iLabelHash)
INT i = 0
REPEAT iNumTextHashesStored i
IF iTriggeredTextHashes[i] = iLabelHash
RETURN i
ENDIF
ENDREPEAT
RETURN -1
ENDFUNC
FUNC BOOL HAS_LABEL_BEEN_TRIGGERED(STRING strLabel)
INT iHash = GET_HASH_KEY(strLabel)
IF GET_LABEL_INDEX(iHash) != -1
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
PROC SET_LABEL_AS_TRIGGERED(STRING strLabel, BOOL bTrigger)
INT iHash = GET_HASH_KEY(strLabel)
IF bTrigger
IF NOT HAS_LABEL_BEEN_TRIGGERED(strLabel)
INT iArraySize = COUNT_OF(iTriggeredTextHashes)
IF iNumTextHashesStored < iArraySize
iTriggeredTextHashes[iNumTextHashesStored] = iHash
iNumTextHashesStored++
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": SET_LABEL_AS_TRIGGERED(): ", strLabel, " TRUE.")
PRINTLN(GET_THIS_SCRIPT_NAME(), ": SET_LABEL_AS_TRIGGERED(): ", iNumTextHashesStored, "/", COUNT_OF(iTriggeredTextHashes), ".")
#ENDIF
ELSE
#IF IS_DEBUG_BUILD
SCRIPT_ASSERT("SET_LABEL_AS_TRIGGERED: Label array is full.")
#ENDIF
ENDIF
ENDIF
ELSE
INT iIndex = GET_LABEL_INDEX(iHash)
IF iIndex != -1
iTriggeredTextHashes[iIndex] = 0
REMOVE_LABEL_ARRAY_SPACES()
iNumTextHashesStored--
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": SET_LABEL_AS_TRIGGERED(): ", strLabel, " FALSE.")
PRINTLN(GET_THIS_SCRIPT_NAME(), ": SET_LABEL_AS_TRIGGERED(): ", iNumTextHashesStored, "/", COUNT_OF(iTriggeredTextHashes), ".")
#ENDIF
ENDIF
ENDIF
ENDPROC
PROC CLEAR_TRIGGERED_LABELS()
INT iArraySize = COUNT_OF(iTriggeredTextHashes)
INT i = 0
REPEAT iArraySize i
iTriggeredTextHashes[i] = 0
ENDREPEAT
iNumTextHashesStored = 0
ENDPROC
PROC UPDATE_TRIGGERED_LABEL(TEXT_LABEL &sLabel)
IF NOT IS_STRING_NULL_OR_EMPTY(sLabel) //if the label is not empty, which means not yet printed by locates header
IF NOT HAS_LABEL_BEEN_TRIGGERED(sLabel) //if it was not set as triggered by script
IF IS_THIS_PRINT_BEING_DISPLAYED(sLabel) //if the label was displayed on screen
SET_LABEL_AS_TRIGGERED(sLabel, TRUE) //mark it as triggered
ENDIF
ELSE //if the label was set as triggered by script,
//which means it was printed by locates header
IF NOT IS_THIS_PRINT_BEING_DISPLAYED(sLabel) //but is not currently being printed, cleared off screen or timed out
sLabel = "" //mark is as empty
ENDIF
ENDIF
ENDIF
ENDPROC
PROC PRINT_GOD_TEXT_ADVANCED(STRING sLabel, INT iDuration = DEFAULT_GOD_TEXT_TIME, BOOL bOnce = TRUE)
IF NOT HAS_LABEL_BEEN_TRIGGERED(sLabel)
PRINT(sLabel, iDuration, 1)
SET_LABEL_AS_TRIGGERED(sLabel, bOnce)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Printing god text ", sLabel, ".")
#ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Returns the next mission stage after the specified mission stage.
/// PARAMS:
/// eStage - Mission stage to get the next mission stage.
/// RETURNS:
/// Mission stage that is next after the specified mission stage.
FUNC MISSION_STAGES GET_NEXT_MISSION_STAGE(MISSION_STAGES eStage)
IF eStage = MISSION_STAGE_CUTSCENE_END
RETURN MISSION_STAGE_CUTSCENE_END
ENDIF
MISSION_STAGES eNextStage
INT iNextStage = ENUM_TO_INT(eStage) + 1
eNextStage = INT_TO_ENUM(MISSION_STAGES, iNextStage)
RETURN eNextStage
ENDFUNC
/// PURPOSE:
/// Check is the specified time has passed using specified timer.
/// PARAMS:
/// iTimeAmount - Time to check.
/// iTimer - Timer to use.
/// RETURNS:
/// True is the specified amount of time has passed for the specified timer.
FUNC BOOL HAS_TIME_PASSED(INT iTimeAmount, INT iTimer)
INT iCurrentTime
INT iTimeDifference
iCurrentTime = GET_GAME_TIMER()
iTimeDifference = iCurrentTime - iTimeAmount
IF iTimeDifference > iTimer
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
PROC CLEANUP_RAYFIRE_MAP_OBJECT(BOOL bSendToStart = TRUE, BOOL bWaitForPlayerToLeaveArea = FALSE)
IF ( bSendToStart = TRUE ) //send to start_state by setting state to starting state
SET_BUILDING_STATE(BUILDINGNAME_RF_STILT_HOUSE, BUILDINGSTATE_NORMAL, bWaitForPlayerToLeaveArea)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Setting BUILDINGNAME_RF_STILT_HOUSE to BUILDINGSTATE_NORMAL.")
#ENDIF
ELSE
SET_BUILDING_STATE(BUILDINGNAME_RF_STILT_HOUSE, BUILDINGSTATE_DESTROYED, bWaitForPlayerToLeaveArea)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Setting BUILDINGNAME_RF_STILT_HOUSE to BUILDINGSTATE_DESTROYED.")
#ENDIF
ENDIF
ENDPROC
PROC CLEANUP_PED(PED_STRUCT &ped, BOOL bDelete = FALSE, BOOL bDeathOnly = TRUE, BOOL bKeepTask = TRUE)
IF ( bDelete = FALSE )
IF DOES_ENTITY_EXIST(ped.PedIndex)
IF ( bDeathOnly = TRUE )
IF IS_PED_INJURED(ped.PedIndex)
IF IS_ENTITY_DEAD(ped.PedIndex)
REMOVE_PED_DEFENSIVE_AREA(ped.PedIndex)
ENDIF
SET_PED_AS_NO_LONGER_NEEDED(ped.PedIndex)
IF DOES_BLIP_EXIST(ped.BlipIndex)
REMOVE_BLIP(ped.BlipIndex)
ENDIF
ENDIF
ELIF ( bDeathOnly = FALSE )
IF NOT IS_PED_INJURED(ped.PedIndex)
IF NOT IS_PED_INJURED(ped.PedIndex)
IF IS_PED_GROUP_MEMBER(ped.PedIndex, PLAYER_GROUP_ID())
REMOVE_PED_FROM_GROUP(ped.PedIndex)
ENDIF
ENDIF
SET_PED_KEEP_TASK(ped.PedIndex, bKeepTask)
SET_PED_AS_NO_LONGER_NEEDED(ped.PedIndex)
IF DOES_BLIP_EXIST(ped.BlipIndex)
REMOVE_BLIP(ped.BlipIndex)
ENDIF
ENDIF
ENDIF
ENDIF
ELIF ( bDelete = TRUE )
IF DOES_ENTITY_EXIST(ped.PedIndex)
IF NOT IS_PED_INJURED(ped.PedIndex)
IF IS_PED_GROUP_MEMBER(ped.PedIndex, PLAYER_GROUP_ID())
REMOVE_PED_FROM_GROUP(ped.PedIndex)
ENDIF
ENDIF
IF NOT IS_PED_INJURED(ped.PedIndex)
REMOVE_PED_DEFENSIVE_AREA(ped.PedIndex)
ENDIF
DELETE_PED(ped.PedIndex)
ENDIF
IF DOES_BLIP_EXIST(ped.BlipIndex)
REMOVE_BLIP(ped.BlipIndex)
ENDIF
ped.iTimer = 0
ped.iConversationTimer = 0
ped.iConversationCounter = 0
ped.iAgressiveTimer = 0
ped.iProgress = 0
ped.iCleanupAttempts = 0
ped.fDistanceToTarget = 0.0
ped.bHasTask = FALSE
ped.bCleanupConversationTriggered = FALSE
ped.eCleanupReason = PED_CLEANUP_NO_CLEANUP
ENDIF
ENDPROC
PROC CLEANUP_PED_GROUP(PED_STRUCT &array[], BOOL bDelete = FALSE, BOOL bDeathOnly = TRUE, BOOL bKeepTask = TRUE)
INT i = 0
FOR i = 0 TO ( COUNT_OF(array) - 1 )
CLEANUP_PED(array[i], bDelete, bDeathOnly, bKeepTask)
ENDFOR
ENDPROC
PROC CLEANUP_VEHICLE(VEH_STRUCT &vehicle, BOOL bDelete = FALSE, BOOL bDeathOnly = TRUE)
IF ( bDelete = FALSE )
IF DOES_ENTITY_EXIST(vehicle.VehicleIndex)
IF ( bDeathOnly = TRUE )
IF NOT IS_VEHICLE_DRIVEABLE(vehicle.VehicleIndex)
OR IS_ENTITY_DEAD(vehicle.VehicleIndex)
REMOVE_VEHICLE_STUCK_CHECK(vehicle.VehicleIndex)
REMOVE_VEHICLE_UPSIDEDOWN_CHECK(vehicle.VehicleIndex)
REMOVE_ENTITY_FROM_AUDIO_MIX_GROUP(vehicle.VehicleIndex)
SET_VEHICLE_AS_NO_LONGER_NEEDED(vehicle.VehicleIndex)
ENDIF
IF DOES_BLIP_EXIST(vehicle.BlipIndex)
REMOVE_BLIP(vehicle.BlipIndex)
ENDIF
ELIF ( bDeathOnly = FALSE )
IF NOT IS_ENTITY_DEAD(vehicle.VehicleIndex)
REMOVE_VEHICLE_STUCK_CHECK(vehicle.VehicleIndex)
REMOVE_VEHICLE_UPSIDEDOWN_CHECK(vehicle.VehicleIndex)
REMOVE_ENTITY_FROM_AUDIO_MIX_GROUP(vehicle.VehicleIndex)
SET_VEHICLE_AS_NO_LONGER_NEEDED(vehicle.VehicleIndex)
ENDIF
IF DOES_BLIP_EXIST(vehicle.BlipIndex)
REMOVE_BLIP(vehicle.BlipIndex)
ENDIF
ENDIF
ENDIF
ELIF ( bDelete = TRUE )
IF DOES_ENTITY_EXIST(vehicle.VehicleIndex)
IF IS_ENTITY_A_MISSION_ENTITY(vehicle.VehicleIndex)
IF IS_ENTITY_DEAD(vehicle.VehicleIndex)
OR NOT IS_ENTITY_DEAD(vehicle.VehicleIndex)
REMOVE_VEHICLE_STUCK_CHECK(vehicle.VehicleIndex)
REMOVE_VEHICLE_UPSIDEDOWN_CHECK(vehicle.VehicleIndex)
REMOVE_ENTITY_FROM_AUDIO_MIX_GROUP(vehicle.VehicleIndex)
DELETE_VEHICLE(vehicle.VehicleIndex)
ENDIF
ENDIF
ENDIF
IF DOES_BLIP_EXIST(vehicle.BlipIndex)
REMOVE_BLIP(vehicle.BlipIndex)
ENDIF
vehicle.iProgress = 0
vehicle.bAutoDrive = FALSE
vehicle.bLOSFlag = FALSE
vehicle.iWarpTimer = 0
vehicle.vTargetPosition = << 0.0, 0.0, 0.0 >>
vehicle.fTargetHeading = 0.0
vehicle.fDistanceToTarget = 0.0
ENDIF
ENDPROC
PROC CLEANUP_VEHICLE_GROUP(VEH_STRUCT &vsArray[], BOOL bDelete = FALSE, BOOL bDeathOnly = TRUE)
INT i = 0
FOR i = 0 TO ( COUNT_OF(vsArray) - 1 )
CLEANUP_VEHICLE(vsArray[i], bDelete, bDeathOnly)
ENDFOR
ENDPROC
FUNC PED_INDEX CREATE_ENEMY_PED_IN_VEHICLE(VEHICLE_INDEX VehicleIndex, MODEL_NAMES ModelName, VEHICLE_SEAT eVehicleSeat, INT iHealth = 200,
WEAPON_TYPE eWeaponType = WEAPONTYPE_UNARMED #IF IS_DEBUG_BUILD, STRING sDebugName = NULL #ENDIF)
IF IS_VEHICLE_DRIVEABLE(VehicleIndex)
PED_INDEX PedIndex = CREATE_PED_INSIDE_VEHICLE(VehicleIndex, PEDTYPE_MISSION, ModelName, eVehicleSeat)
SET_PED_MAX_HEALTH(PedIndex, iHealth)
SET_ENTITY_HEALTH(PedIndex, iHealth)
SET_PED_DIES_WHEN_INJURED(PedIndex, TRUE)
GIVE_WEAPON_TO_PED(PedIndex, eWeaponType, INFINITE_AMMO, FALSE)
SET_PED_INFINITE_AMMO(PedIndex, TRUE, eWeaponType)
SET_PED_RELATIONSHIP_GROUP_HASH(PedIndex, rgEnemies)
SET_PED_AS_ENEMY(PedIndex, TRUE)
SET_PED_TARGET_LOSS_RESPONSE(PedIndex, TLR_NEVER_LOSE_TARGET)
SET_PED_FLEE_ATTRIBUTES(PedIndex, FA_NEVER_FLEE, TRUE)
SET_PED_COMBAT_ATTRIBUTES(PedIndex, CA_ALWAYS_FLEE, FALSE)
SET_PED_COMBAT_ATTRIBUTES(PedIndex, CA_ALWAYS_FIGHT, TRUE)
SET_PED_CONFIG_FLAG(PedIndex, PCF_DisableHurt, TRUE)
SET_PED_CONFIG_FLAG(PedIndex, PCF_RunFromFiresAndExplosions, FALSE)
SET_PED_CONFIG_FLAG(PedIndex, PCF_KeepRelationshipGroupAfterCleanUp, TRUE)
SET_PED_CONFIG_FLAG(PedIndex, PCF_AllowToBeTargetedInAVehicle, TRUE)
SET_ENTITY_IS_TARGET_PRIORITY(PedIndex, TRUE)
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(PedIndex, TRUE)
#IF IS_DEBUG_BUILD
IF NOT Is_String_Null_Or_Empty(sDebugName)
SET_PED_NAME_DEBUG(PedIndex, sDebugName)
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Created enemy ped in vehicle with debug name ", sDebugName, ".")
ELSE
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Created enemy ped in vehicle.")
ENDIF
#ENDIF
RETURN PedIndex
ENDIF
RETURN NULL
ENDFUNC
/// PURPOSE:
/// Checks if specified ped is using petrol can weapon to pour petrol at or around the specified entity.
/// PARAMS:
/// PedIndex - Ped to check for petrol can usage.
/// EntityIndex - Entity to check for petrol being used against.
/// fRadius - Radius to check around the specified entity.
/// RETURNS:
/// TRUE if specified ped is using petrol can to pour petrol around specified entity in the specified radius. FALSE if otherwise.
FUNC BOOL IS_PED_USING_PETROL_CAN_AT_ENTITY(PED_INDEX PedIndex, ENTITY_INDEX EntityIndex, FLOAT fRadius = 2.5
#IF IS_DEBUG_BUILD, BOOL bDrawDebugSphere = TRUE, INT iRed = 0, INT iGreen = 255, INT iBlue = 0,
INT iAlpha = 128 #ENDIF)
IF NOT IS_PED_INJURED(PedIndex)
IF DOES_ENTITY_EXIST(EntityIndex)
IF NOT IS_ENTITY_DEAD(EntityIndex)
WEAPON_TYPE PedCurrentWeaponType
IF GET_CURRENT_PED_WEAPON(PedIndex, PedCurrentWeaponType) //check if ped has petrol can equipped first
IF ( PedCurrentWeaponType = WEAPONTYPE_PETROLCAN )
VECTOR vEntityPosition = GET_ENTITY_COORDS(EntityIndex)
FLOAT fGroundZ
IF GET_GROUND_Z_FOR_3D_COORD(vEntityPosition, fGroundZ)
vEntityPosition.Z = fGroundZ
ENDIF
//draw debug sphere to visualise the check area, this will only draw when petrol can is equipped by ped
#IF IS_DEBUG_BUILD
IF ( bDrawDebugSphere = TRUE )
DRAW_DEBUG_SPHERE(vEntityPosition, fRadius, iRed, iGreen, iBlue, iAlpha)
ENDIF
#ENDIF
//check if ped is using petrol can and if any petrol decals are the entity
IF IS_PED_SHOOTING(PedIndex)
AND GET_IS_PETROL_DECAL_IN_RANGE(vEntityPosition, fRadius)
RETURN TRUE
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
FUNC BOOL IS_PED_DRIVING_VEHICLE(PED_INDEX PedIndex, VEHICLE_INDEX VehicleIndex)
IF DOES_ENTITY_EXIST(PedIndex)
AND NOT IS_ENTITY_DEAD(PedIndex)
IF DOES_ENTITY_EXIST(VehicleIndex)
AND NOT IS_ENTITY_DEAD(VehicleIndex)
IF IS_PED_SITTING_IN_VEHICLE(PedIndex, VehicleIndex)
IF NOT IS_VEHICLE_STOPPED(VehicleIndex)
RETURN TRUE
ENDIF
ENDIF
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
PROC MAKE_PED_FLEE_PED(PED_INDEX PedIndex, PED_INDEX PedIndexToFleeFrom, FLOAT fSafeDistance, INT iTime)
IF NOT IS_PED_INJURED(PedIndexToFleeFrom)
IF DOES_ENTITY_EXIST(PedIndex)
IF NOT IS_PED_INJURED(PedIndex)
CLEAR_PED_TASKS(PedIndex)
SET_PED_FLEE_ATTRIBUTES(PedIndex, FA_CAN_SCREAM, TRUE)
TASK_SMART_FLEE_PED(PedIndex, PedIndexToFleeFrom, fSafeDistance, iTime)
SET_PED_KEEP_TASK(PedIndex, TRUE)
ENDIF
ENDIF
ENDIF
ENDPROC
PROC START_VEHICLE_RECORDING_PLAYBACK_FOR_VEHICLE(VEH_STRUCT vsCar, STRING sFileName, FLOAT fPlaybackSpeed, BOOL bPaused = FALSE,
FLOAT fTime = 0.0, BOOL bSkipToVehiclePosition = FALSE, BOOL bUseFlags = FALSE,
INT iFlags = SWITCH_ON_PLAYER_VEHICLE_IMPACT)
IF IS_VEHICLE_DRIVEABLE(vsCar.VehicleIndex)
IF NOT IS_PLAYBACK_GOING_ON_FOR_VEHICLE(vsCar.VehicleIndex)
IF HAS_VEHICLE_RECORDING_BEEN_LOADED(vsCar.iRecordingNumber, sFileName)
IF ( bUseFlags = FALSE )
START_PLAYBACK_RECORDED_VEHICLE(vsCar.VehicleIndex, vsCar.iRecordingNumber, sFileName)
ELIF ( bUseFlags = TRUE )
START_PLAYBACK_RECORDED_VEHICLE_WITH_FLAGS(vsCar.VehicleIndex, vsCar.iRecordingNumber, sFileName, iFlags)
ENDIF
IF ( fTime > 0.0 )
SKIP_TIME_IN_PLAYBACK_RECORDED_VEHICLE(vsCar.VehicleIndex, fTime)
ELIF ( bSkipToVehiclePosition = TRUE )
SKIP_TIME_IN_PLAYBACK_RECORDED_VEHICLE(vsCar.VehicleIndex, GET_CLOSEST_TIME_POSITION_IN_RECORDING_TO_POINT(GET_ENTITY_COORDS(vsCar.VehicleIndex), vsCar.iRecordingNumber, sFileName, 16))
ENDIF
SET_PLAYBACK_SPEED(vsCar.VehicleIndex, fPlaybackSpeed)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Vehicle recording ", sFileName, " number ", vsCar.iRecordingNumber, " for vehicle ",
GET_MODEL_NAME_FOR_DEBUG(vsCar.ModelName), " started with playback speed ", fPlaybackSpeed, "and time ", fTime, ".")
#ENDIF
IF ( bPaused = TRUE )
PAUSE_PLAYBACK_RECORDED_VEHICLE(vsCar.VehicleIndex)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Vehicle recording ", sFileName, " number ", vsCar.iRecordingNumber, " for vehicle ", GET_MODEL_NAME_FOR_DEBUG(vsCar.ModelName), " paused.")
#ENDIF
ENDIF
ELSE
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Vehicle recording number ", vsCar.iRecordingNumber, " for vehicle ", GET_MODEL_NAME_FOR_DEBUG(vsCar.ModelName), " is not loaded.")
#ENDIF
ENDIF
ENDIF
ENDIF
ENDPROC
//Author: Ross Wallace
//PURPOSE: Returns the percentage progress of a car recording...
FUNC FLOAT GET_VEHICLE_RECORDING_PLAYBACK_PERCENTAGE(VEHICLE_INDEX VehicleIndex #IF IS_DEBUG_BUILD, BOOL bPrintOutput = FALSE #ENDIF)
IF DOES_ENTITY_EXIST(VehicleIndex)
AND IS_VEHICLE_DRIVEABLE(VehicleIndex)
IF IS_PLAYBACK_GOING_ON_FOR_VEHICLE(VehicleIndex)
RECORDING_ID RecordingID = GET_CURRENT_PLAYBACK_FOR_VEHICLE(VehicleIndex)
#IF IS_DEBUG_BUILD
INT iPercentage = ROUND( 100.0 * ( GET_TIME_POSITION_IN_RECORDING(VehicleIndex) / GET_TOTAL_DURATION_OF_VEHICLE_RECORDING_ID(RecordingID) ) )
TEXT_LABEL_63 debugName = GET_VEHICLE_RECORDING_NAME(RecordingID)
debugName += ":"
debugName += iPercentage
SET_VEHICLE_NAME_DEBUG(VehicleIndex, debugName)
#ENDIF
#IF IS_DEBUG_BUILD
IF ( bPrintOutput = TRUE )
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Recording ", GET_VEHICLE_RECORDING_NAME(RecordingID), " time is ", GET_TIME_POSITION_IN_RECORDING(VehicleIndex), ".")
ENDIF
#ENDIF
RETURN ( 100.0 * ( GET_TIME_POSITION_IN_RECORDING(VehicleIndex) / GET_TOTAL_DURATION_OF_VEHICLE_RECORDING_ID(RecordingID) ) )
ELSE
#IF IS_DEBUG_BUILD
IF ( bPrintOutput = TRUE )
PRINTLN(GET_THIS_SCRIPT_NAME(), ": GET_VEHICLE_RECORDING_PLAYBACK_PERCENTAGE: Playback not going on for vehicle.")
ENDIF
#ENDIF
ENDIF
ELSE
#IF IS_DEBUG_BUILD
IF ( bPrintOutput = TRUE )
PRINTLN(GET_THIS_SCRIPT_NAME(), ": GET_VEHICLE_RECORDING_PLAYBACK_PERCENTAGE: Vehicle does not exist or is not driveable.")
ENDIF
#ENDIF
ENDIF
RETURN -1.0
ENDFUNC
//|======================= END MISCELLANEOUS PROCEDURES & FUNCTIONS ======================|
//|=================================== MATH FUNCTIONS ====================================|
/// PURPOSE:
/// Returns the lowest int value from two specified int values.
/// PARAMS:
/// iValueA - First int value.
/// iValueB - Second int value.
/// RETURNS:
/// Lowest int value of the two.
FUNC INT GET_MINIMUM_INT(INT iValueA, INT iValueB)
IF (iValueA = iValueB)
RETURN iValueA
ELIF (iValueA > iValueB)
RETURN iValueB
ELIF (iValueA < iValueB)
RETURN iValueA
ENDIF
RETURN iValueA
ENDFUNC
//|================================= END MATH FUNCTIONS ==================================|
//|======================= DEBUG VARIABLES, PROCEDURES & FUNCTIONS =======================|
#IF IS_DEBUG_BUILD
//mission skip menu and widget variables
MissionStageMenuTextStruct SkipMenu[9]
INT iReturnStage = 0
BOOL bStageResetFlag
BOOL bCoachStartToggle = FALSE
BOOL bCoachStopToggle = FALSE
BOOL bPrintDebugOutput = FALSE
VECTOR vRopeTruckAttachmentOffset
BOOL bDrawDebugLinesAndSpheres
BOOL bDrawDebugStates
BOOL bToggleVehicleExtra
//debug widgets variables
WIDGET_GROUP_ID Family3Widgets
/// PURPOSE:
/// Returns string name of the specified mission stage.
/// PARAMS:
/// eStage - Mission stage to get string name for.
/// RETURNS:
/// String name of the specified mission stage.
FUNC STRING GET_MISSION_STAGE_NAME_FOR_DEBUG(MISSION_STAGES eStage)
SWITCH eStage
CASE MISSION_STAGE_CUTSCENE_INTRO
RETURN "MISSION_STAGE_CUTSCENE_INTRO"
BREAK
CASE MISSION_STAGE_CAR_CHASE
RETURN "MISSION_STAGE_CAR_CHASE"
BREAK
CASE MISSION_STAGE_CUTSCENE_BACK_OF_HOUSE
RETURN "MISSION_STAGE_CUTSCENE_BACK_OF_HOUSE"
BREAK
CASE MISSION_STAGE_PULL_HOUSE_DOWN
RETURN "MISSION_STAGE_PULL_HOUSE_DOWN"
BREAK
CASE MISSION_STAGE_ESCAPE_GOONS
RETURN "MISSION_STAGE_ESCAPE_GOONS"
BREAK
CASE MISSION_STAGE_CUTSCENE_END
RETURN "MISSION_STAGE_CUTSCENE_END"
BREAK
CASE MISSION_STAGE_LEADOUT
RETURN "MISSION_STAGE_LEADOUT"
BREAK
CASE MISSION_STAGE_DEBUG_RECORD_CHASE
RETURN "MISSION_STAGE_DEBUG_RECORD_CHASE"
BREAK
CASE MISSION_STAGE_DEBUG_PLAYBACK_CHASE
RETURN "MISSION_STAGE_DEBUG_PLAYBACK_CHASE"
BREAK
ENDSWITCH
RETURN "INCORRECT_MISSION_STAGE"
ENDFUNC
FUNC STRING GET_MISSION_FAIL_NAME_FOR_DEBUG(MISSION_FAILS eFailReason)
SWITCH eFailReason
CASE MISSION_FAIL_CAR_DESTROYED
RETURN "MISSION_FAIL_CAR_DESTROYED"
BREAK
CASE MISSION_FAIL_CAR_STUCK
RETURN "MISSION_FAIL_CAR_STUCK"
BREAK
CASE MISSION_FAIL_MICHAEL_DEAD
RETURN "MISSION_FAIL_MICHAEL_DEAD"
BREAK
CASE MISSION_FAIL_MICHAEL_LEFT_BEHIND
RETURN "MISSION_FAIL_MICHAEL_LEFT_BEHIND"
BREAK
CASE MISSION_FAIL_FRANKLIN_DEAD
RETURN "MISSION_FAIL_FRANKLIN_DEAD"
BREAK
CASE MISSION_FAIL_FRANKLIN_LEFT_BEHIND
RETURN "MISSION_FAIL_FRANKLIN_LEFT_BEHIND"
BREAK
CASE MISSION_FAIL_COACH_ATTACKED
RETURN "MISSION_FAIL_COACH_ATTACKED"
BREAK
CASE MISSION_FAIL_COACH_DEAD
RETURN "MISSION_FAIL_COACH_DEAD"
BREAK
CASE MISSION_FAIL_COACH_SPOOKED
RETURN "MISSION_FAIL_COACH_SPOOKED"
BREAK
CASE MISSION_FAIL_FORCE_FAIL
RETURN "MISSION_FAIL_FORCE_FAIL"
BREAK
ENDSWITCH
RETURN "INCORRECT_MISSION_FAIL"
ENDFUNC
FUNC STRING GET_PED_STATE_NAME_FOR_DEBUG(PED_STATES eState)
SWITCH eState
CASE PED_STATE_IDLE
RETURN "PED_STATE_IDLE"
BREAK
CASE PED_STATE_ON_FOOT
RETURN "PED_STATE_ON_FOOT"
BREAK
CASE PED_STATE_COMBAT_ON_FOOT
RETURN "PED_STATE_COMBAT_ON_FOOT"
BREAK
CASE PED_STATE_COMBAT_FROM_CAR_NO_SHOOTING
RETURN "PED_STATE_COMBAT_FROM_CAR_NO_SHOOTING"
BREAK
CASE PED_STATE_COMBAT_FROM_CAR_SHOOTING
RETURN "PED_STATE_COMBAT_FROM_CAR_SHOOTING"
BREAK
CASE PED_STATE_ENTERING_VEHICLE
RETURN "PED_STATE_ENTERING_VEHICLE"
BREAK
CASE PED_STATE_SITTING_IN_VEHICLE_PASSENGER
RETURN "PED_STATE_SITTING_IN_VEHICLE_PASSENGER"
BREAK
CASE PED_STATE_SITTING_IN_VEHICLE_DRIVER
RETURN "PED_STATE_SITTING_IN_VEHICLE_DRIVER"
BREAK
CASE PED_STATE_SHUFFLING_VEHICLE_SEATS
RETURN "PED_STATE_SHUFFLING_VEHICLE_SEATS"
BREAK
CASE PED_STATE_LOOKING_BEHIND_IN_VEHICLE
RETURN "PED_STATE_LOOKING_BEHIND_IN_VEHICLE"
BREAK
CASE PED_STATE_DRIVE_FLEE_TARGETS
RETURN "PED_STATE_DRIVE_FLEE_TARGETS"
BREAK
CASE PED_STATE_DRIVE_FLEE_COPS
RETURN "PED_STATE_DRIVE_FLEE_COPS"
BREAK
CASE PED_STATE_DRIVE_TO_DESTINATION
RETURN "PED_STATE_DRIVE_TO_DESTINATION"
BREAK
CASE PED_STATE_FOLLOWING_PLAYER
RETURN "PED_STATE_FOLLOWING_PLAYER"
BREAK
CASE PED_STATE_WAITING_FOR_PLAYER
RETURN "PED_STATE_WAITING_FOR_PLAYER"
BREAK
CASE PED_STATE_WAITING_FOR_TASK_AFTER_SWITCH
RETURN "PED_STATE_WAITING_FOR_TASK_AFTER_SWITCH"
BREAK
DEFAULT
RETURN "INVALID_PED_STATE"
BREAK
ENDSWITCH
RETURN "INVALID_PED_STATE"
ENDFUNC
PROC CREATE_DEBUG_WIDGETS()
Family3Widgets = START_WIDGET_GROUP("Mission: Family3")
ADD_WIDGET_BOOL("Print debug output", bPrintDebugOutput)
ADD_WIDGET_BOOL("bAllowHotSwap", bAllowHotSwap)
ADD_WIDGET_BOOL("bToggleVehicleExtra", bToggleVehicleExtra)
START_WIDGET_GROUP("Camera Hints")
ADD_WIDGET_VECTOR_SLIDER("vTennisCoachHintPosition", vTennisCoachHintPosition, -2000.0, 2000.0, 1.0)
ADD_WIDGET_VECTOR_SLIDER("vTennisCoachHintPosition", vTennisCoachHintPosition, -2000.0, 2000.0, 1.0)
STOP_WIDGET_GROUP()
START_WIDGET_GROUP("House Pull")
ADD_WIDGET_VECTOR_SLIDER("Rope Truck Attachment Offset", vRopeTruckAttachmentOffset, -10.0, 10.0, 0.1)
ADD_WIDGET_FLOAT_READ_ONLY("Rayfire phase", fRayfirePhase)
ADD_WIDGET_FLOAT_SLIDER("fForceConverge", fForceConverge, 0.0, 1.0, 0.01)
ADD_WIDGET_FLOAT_SLIDER("fSideForceValue", fSideForceValue, -500.0, 500.0, 1.0)
ADD_WIDGET_FLOAT_SLIDER("fDownForceValue", fDownForceValue, -500.0, 500.0, 1.0)
ADD_WIDGET_VECTOR_SLIDER("Force Back Offset", vForceBackOffset, -10.0, 10.0, 0.1)
STOP_WIDGET_GROUP()
START_WIDGET_GROUP("Goons chase")
ADD_WIDGET_BOOL("bGoonsAllowed", bGoonsAllowed)
ADD_WIDGET_FLOAT_SLIDER("BLIP_SLIDE_AMOUNT", BLIP_SLIDE_AMOUNT, 0.0, 256.0, 1.0)
ADD_WIDGET_VECTOR_SLIDER("vEnemyCarsOffset[0]", vEnemyCarsOffset[0], -10.0, 10.0, 0.1)
ADD_WIDGET_VECTOR_SLIDER("vEnemyCarsOffset[1]", vEnemyCarsOffset[1], -10.0, 10.0, 0.1)
STOP_WIDGET_GROUP()
START_WIDGET_GROUP("Uber car chase")
ADD_WIDGET_BOOL("Start coach playback", bCoachStartToggle)
ADD_WIDGET_BOOL("Stop coach playback", bCoachStopToggle)
STOP_WIDGET_GROUP()
ADD_WIDGET_INT_SLIDER("iFirstPersonFlashTime", iFirstPersonFlashTime, 0, 5000, 100)
ADD_WIDGET_FLOAT_SLIDER("fFirstPersonFlashPhase1", fFirstPersonFlashPhase1, 0.0, 1.0, 0.01)
ADD_WIDGET_FLOAT_SLIDER("fFirstPersonFlashPhase2", fFirstPersonFlashPhase2, 0.0, 1.0, 0.01)
ADD_WIDGET_FLOAT_SLIDER("fFirstPersonFlashPhase3", fFirstPersonFlashPhase3, 0.0, 1.0, 0.01)
STOP_WIDGET_GROUP()
SET_UBER_PARENT_WIDGET_GROUP(Family3Widgets)
SET_LOCATES_HEADER_WIDGET_GROUP(Family3Widgets)
ENDPROC
PROC DELETE_DEBUG_WIDGETS()
IF DOES_WIDGET_GROUP_EXIST(Family3Widgets)
DELETE_WIDGET_GROUP(Family3Widgets)
ENDIF
ENDPROC
PROC RUN_DEBUG_WIDGETS(MISSION_STAGES eStage)
IF ( bDrawDebugStates = TRUE )
DRAW_DEBUG_SPHERE(vTennisCoachHintPosition, 0.1, 255, 0, 0)
DRAW_DEBUG_SPHERE(vBalconyHintPosition, 0.1, 0, 0, 255)
ENDIF
SWITCH eStage
CASE MISSION_STAGE_DEBUG_RECORD_CHASE
CASE MISSION_STAGE_DEBUG_PLAYBACK_CHASE
IF ( bCoachStartToggle = TRUE )
START_VEHICLE_RECORDING_PLAYBACK_FOR_VEHICLE(vsCoachsCar, sVehicleRecordingsFile, 1.0)
SET_ENTITY_COLLISION(vsCoachsCar.VehicleIndex, FALSE)
bCoachStartToggle = FALSE
ENDIF
IF ( bCoachStopToggle = TRUE )
STOP_PLAYBACK_RECORDED_VEHICLE(vsCoachsCar.VehicleIndex)
SET_ENTITY_COLLISION(vsCoachsCar.VehicleIndex, TRUE)
bCoachStopToggle = FALSE
ENDIF
BREAK
ENDSWITCH
IF ( bToggleVehicleExtra = TRUE )
IF DOES_ENTITY_EXIST(vsPlayersCar.VehicleIndex)
IF NOT IS_ENTITY_DEAD(vsPlayersCar.VehicleIndex)
IF IS_VEHICLE_EXTRA_TURNED_ON(vsPlayersCar.VehicleIndex, 5)
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Vehicle extra 5 is ON.")
SET_VEHICLE_EXTRA(vsPlayersCar.VehicleIndex, 5, TRUE)
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Switching vehicle extra OFF.")
ELSE
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Vehicle extra 5 is OFF.")
SET_VEHICLE_EXTRA(vsPlayersCar.VehicleIndex, 5, FALSE)
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Switching vehicle extra ON.")
ENDIF
ENDIF
ENDIF
bToggleVehicleExtra = FALSE
ENDIF
ENDPROC
/// PURPOSE:
/// Creates debug mission stage menu.
PROC CREATE_DEBUG_MISSION_STAGE_MENU()
SkipMenu[0].sTxtLabel = "CUT - INTRO - FAMILY_3_INT"
SkipMenu[1].sTxtLabel = "CAR CHASE"
SkipMenu[2].sTxtLabel = "CUT - BALCONY - FAM_3_MCS_1"
SkipMenu[3].sTxtLabel = "PULL HOUSE DOWN"
SkipMenu[4].sTxtLabel = "ESCAPE GOONS"
SkipMenu[5].sTxtLabel = "CUT - END - FAMILY_3_EXT"
SkipMenu[6].sTxtLabel = "LEADOUT"
SkipMenu[7].sTxtLabel = "DEBUG - RECORD CHASE"
SkipMenu[8].sTxtLabel = "DEBUG - PLAYBACK CHASE"
ENDPROC
/// PURPOSE:
/// Checks if any of the debug pass or fail keys has been pressed to force mission end.
/// PARAMS:
/// eStage - Mission stage variable
/// eFailReason - Mission fail variable.
PROC RUN_DEBUG_PASS_AND_FAIL_CHECK(MISSION_STAGES &eStage, MISSION_FAILS &eFailReason)
IF IS_KEYBOARD_KEY_PRESSED (KEY_S)
eStage = MISSION_STAGE_PASSED
ENDIF
IF IS_KEYBOARD_KEY_PRESSED (KEY_F)
eStage = MISSION_STAGE_FAILED
eFailReason = MISSION_FAIL_FORCE_FAIL
ENDIF
ENDPROC
PROC RUN_MISSION_STAGE_CLEANUP_FOR_DEBUG()
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Starting mission stage cleanup.")
KILL_PHONE_CONVERSATION()
HANG_UP_AND_PUT_AWAY_PHONE(TRUE)
KILL_ANY_CONVERSATION()
KILL_FACE_TO_FACE_CONVERSATION_DO_NOT_FINISH_LAST_LINE()
REMOVE_CUTSCENE()
WAIT(0)
STOP_STREAM()
TRIGGER_MUSIC_EVENT("FAM3_MISSION_FAIL")
CANCEL_MUSIC_EVENT("FAM3_HOUSE_COLLAPSE")
STOP_AUDIO_SCENES()
//remove mission peds
SWITCH GET_CURRENT_PLAYER_PED_ENUM()
CASE CHAR_MICHAEL
CLEANUP_PED(psFranklin, TRUE)
BREAK
CASE CHAR_FRANKLIN
CLEANUP_PED(psMichael, TRUE)
BREAK
ENDSWITCH
CLEANUP_PED(psCoach, TRUE)
CLEANUP_PED(psVanDriver, TRUE)
CLEANUP_PED_GROUP(psEnemyGoonsCar0, TRUE)
CLEANUP_PED_GROUP(psEnemyGoonsCar1, TRUE)
CLEANUP_VEHICLE(vsVan, TRUE)
CLEANUP_VEHICLE(vsPlayersCar, TRUE)
CLEANUP_VEHICLE(vsCoachsCar, TRUE)
CLEANUP_VEHICLE(vsCutsceneCar, TRUE)
CLEANUP_VEHICLE_GROUP(vsEnemyCars, TRUE)
CLEANUP_UBER_PLAYBACK(TRUE)
//clear locates header data
CLEAR_MISSION_LOCATION_TEXT_AND_BLIPS(sLocatesData)
CLEAR_TRIGGERED_LABELS()
KILL_CHASE_HINT_CAM(localChaseHintCamStruct)
IF DOES_CAM_EXIST(ScriptedCamera)
SET_CAM_ACTIVE(ScriptedCamera, FALSE)
RENDER_SCRIPT_CAMS(FALSE, FALSE)
DESTROY_CAM(ScriptedCamera)
DISPLAY_RADAR(TRUE)
DISPLAY_HUD(TRUE)
ENDIF
DESTROY_ALL_CAMS()
STOP_GAMEPLAY_HINT()
STOP_GAMEPLAY_CAM_SHAKING()
//remove particle fx attached to player's truck
IF DOES_PARTICLE_FX_LOOPED_EXIST(ptfxRearLeftWheel)
REMOVE_PARTICLE_FX(ptfxRearLeftWheel)
ENDIF
IF DOES_PARTICLE_FX_LOOPED_EXIST(ptfxRearRightWheel)
REMOVE_PARTICLE_FX(ptfxRearRightWheel)
ENDIF
IF DOES_PARTICLE_FX_LOOPED_EXIST(ptfxDustCloud)
REMOVE_PARTICLE_FX(ptfxDustCloud)
ENDIF
REMOVE_PTFX_ASSET()
IF DOES_ROPE_EXIST(Rope)
AND DOES_ENTITY_EXIST(osRopeAnchor.ObjectIndex)
DETACH_ROPE_FROM_ENTITY(Rope, osRopeAnchor.ObjectIndex)
DELETE_ROPE(Rope)
DELETE_OBJECT(osRopeAnchor.ObjectIndex)
ROPE_UNLOAD_TEXTURES()
bRopeAttached = FALSE
ENDIF
IF DOES_ENTITY_EXIST(osRacket01.ObjectIndex)
DELETE_OBJECT(osRacket01.ObjectIndex)
ENDIF
IF DOES_ENTITY_EXIST(osRacket02.ObjectIndex)
DELETE_OBJECT(osRacket02.ObjectIndex)
ENDIF
IF DOES_ENTITY_EXIST(osRopeDummy.ObjectIndex)
DELETE_OBJECT(osRopeDummy.ObjectIndex)
ENDIF
IF DOES_ENTITY_EXIST(osRopeProp.ObjectIndex)
DELETE_OBJECT(osRopeProp.ObjectIndex)
ENDIF
IF DOES_ENTITY_EXIST(osBootCollision.ObjectIndex)
DELETE_OBJECT(osBootCollision.ObjectIndex)
ENDIF
IF DOES_ENTITY_EXIST(osCellphone.ObjectIndex)
DELETE_OBJECT(osCellphone.ObjectIndex)
ENDIF
IF DOES_ENTITY_EXIST(osBrokenPlantPot.ObjectIndex)
DELETE_OBJECT(osBrokenPlantPot.ObjectIndex)
ENDIF
REMOVE_ANIM_DICT("missfam3")
REMOVE_ANIM_DICT("switch@michael@bench")
REMOVE_VEHICLE_ASSET(BISON2)
SET_NO_LOADING_SCREEN(FALSE)
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Finished mission stage cleanup.")
ENDPROC
/// PURPOSE:
/// Controls running the debug mission stage menu.
/// PARAMS:
/// iSelectedStage - Variable that stores int value returned from the debug mission stage menu.
/// eStage - Mission stage variable.
/// bSkipActive - Skip flag.
PROC RUN_DEBUG_MISSION_STAGE_MENU(INT &iSelectedStage, MISSION_STAGES &eStage, BOOL &bSkipActive, BOOL &bResetStage)
IF LAUNCH_MISSION_STAGE_MENU(SkipMenu, iSelectedStage, ENUM_TO_INT(eStage), FALSE, "FAMILY 3")
DO_SAFE_SCREEN_FADE_OUT(DEFAULT_FADE_TIME)
DO_SAFE_STOP_CUTSCENE()
CLEAR_PRINTS()
CLEAR_HELP()
CLEAR_PED_TASKS_IMMEDIATELY(PLAYER_PED_ID())
RUN_MISSION_STAGE_CLEANUP_FOR_DEBUG()
eStage = INT_TO_ENUM(MISSION_STAGES, iSelectedStage)
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Current mission stage changed to ", GET_MISSION_STAGE_NAME_FOR_DEBUG(eStage), " via mission stage menu.")
//reset the debug stage reset flag
bResetStage = FALSE
bSkipActive = TRUE
RESET_MISSION_FLAGS()
ENDIF
ENDPROC
PROC RUN_DEBUG_SKIPS(MISSION_STAGES &eStage, BOOL &bSkipActive, BOOL &bResetStage)
INT iCurrentStage = ENUM_TO_INT(eStage)
IF IS_KEYBOARD_KEY_JUST_PRESSED(KEY_J)
IF eStage <> MISSION_STAGE_CUTSCENE_END
DO_SAFE_SCREEN_FADE_OUT(DEFAULT_FADE_TIME)
DO_SAFE_STOP_CUTSCENE()
CLEAR_PRINTS()
CLEAR_HELP()
CLEAR_PED_TASKS_IMMEDIATELY(PLAYER_PED_ID())
RUN_MISSION_STAGE_CLEANUP_FOR_DEBUG()
iCurrentStage++
eStage = INT_TO_ENUM(MISSION_STAGES, iCurrentStage)
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Current mission stage changed to ", GET_MISSION_STAGE_NAME_FOR_DEBUG(eStage), " via J skip.")
//reset the debug stage reset flag
bResetStage = FALSE
bSkipActive = TRUE
RESET_MISSION_FLAGS()
ENDIF
ELIF IS_KEYBOARD_KEY_JUST_PRESSED(KEY_P)
IF eStage <> MISSION_STAGE_CUTSCENE_INTRO
DO_SAFE_SCREEN_FADE_OUT(DEFAULT_FADE_TIME)
DO_SAFE_STOP_CUTSCENE()
CLEAR_PRINTS()
CLEAR_HELP()
CLEAR_PED_TASKS_IMMEDIATELY(PLAYER_PED_ID())
RUN_MISSION_STAGE_CLEANUP_FOR_DEBUG()
IF ( bResetStage = FALSE )
iCurrentStage--
eStage = INT_TO_ENUM(MISSION_STAGES, iCurrentStage)
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Current mission stage changed to ", GET_MISSION_STAGE_NAME_FOR_DEBUG(eStage), " via P skip.")
ELIF ( bResetStage = TRUE )
eStage = INT_TO_ENUM(MISSION_STAGES, iCurrentStage)
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Current mission stage ", GET_MISSION_STAGE_NAME_FOR_DEBUG(eStage), " reset via P skip.")
ENDIF
//reset the debug stage reset flag
bResetStage = FALSE
bSkipActive = TRUE
RESET_MISSION_FLAGS()
ENDIF
ENDIF
ENDPROC
PROC RUN_DEBUG_INFORMATION_DISPLAY()
IF IS_KEYBOARD_KEY_JUST_PRESSED(KEY_NUMPAD4)
IF ( bDrawDebugLinesAndSpheres = FALSE)
SET_DEBUG_LINES_AND_SPHERES_DRAWING_ACTIVE(TRUE)
bDrawDebugLinesAndSpheres = TRUE
ELSE
SET_DEBUG_LINES_AND_SPHERES_DRAWING_ACTIVE(FALSE)
bDrawDebugLinesAndSpheres = FALSE
ENDIF
ENDIF
IF IS_KEYBOARD_KEY_JUST_PRESSED(KEY_NUMPAD5)
IF ( bDrawDebugStates = FALSE)
bDrawDebugStates = TRUE
ELSE
bDrawDebugStates = FALSE
ENDIF
ENDIF
ENDPROC
#ENDIF
//|===================== END DEBUG VARIABLES, PROCEDURES & FUNCTIONS =====================|
//|======================= ASSET REQUESTING PROCEDURES & FUNCTIONS =======================|
/// PURPOSE:
/// Adds a model to model request array.
/// PARAMS:
/// ModelName - Model name being requested.
/// array - MODEL_NAMES array to add the requested model name to.
/// iArrayLength - Maximum length of the array.
/// iModelsAlreadyRequested - Number of models already requested in this array.
PROC ADD_MODEL_REQUEST_TO_ARRAY(MODEL_NAMES ModelName, MODEL_NAMES &array[], INT iArrayLength, INT &iModelsAlreadyRequested)
INT i = 0
BOOL bModelAlreadyRequested = FALSE
IF ( iModelsAlreadyRequested >= 0 )
IF ( iModelsAlreadyRequested <= ( iArrayLength - 1 ) )
//loop through the array (from 0 to number of models already requested)
//to see if the array already contains the model name being requested
//modify the boolean flag if the model was found in array, otherwise leave the flag unchanged
FOR i = 0 TO ( iModelsAlreadyRequested )
IF ( array[i] = ModelName )
bModelAlreadyRequested = TRUE
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Requested model ", GET_MODEL_NAME_FOR_DEBUG(ModelName), " is already in model array.")
#ENDIF
ENDIF
ENDFOR
IF ( bModelAlreadyRequested = FALSE )
REQUEST_MODEL(ModelName)
//iModelsAlreadyRequested will be the model array index of the model being requested
array[iModelsAlreadyRequested] = ModelName
iModelsAlreadyRequested++
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Requested model ", GET_MODEL_NAME_FOR_DEBUG(ModelName), " and added to model array.")
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Number of models requested: ", iModelsAlreadyRequested, ".")
#ENDIF
ENDIF
ELSE
SCRIPT_ASSERT("Number of requested models is greater than the length of the model array.")
ENDIF
ELSE
SCRIPT_ASSERT("Number of requested models is less than 0.")
ENDIF
ENDPROC
/// PURPOSE:
/// Checks if all requested models from model array are loaded into memory.
/// PARAMS:
/// array - MODEL_NAMES array holding the models.
/// iModelsAlreadyRequested - Number of already requested models. Should be greated than 0, since 0 means no models have been requested.
/// RETURNS:
/// TRUE if all models from model array are loaded into memory. FALSE if otherwise.
FUNC BOOL ARE_REQUESTED_MODELS_LOADED(MODEL_NAMES &array[], INT &iModelsAlreadyRequested)
INT i = 0
IF ( iModelsAlreadyRequested > 0 )
FOR i = 0 TO ( iModelsAlreadyRequested - 1 )
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Model in array[", i, "]: ", GET_MODEL_NAME_FOR_DEBUG(array[i]), ".")
#ENDIF
IF NOT HAS_MODEL_LOADED(array[i])
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Model ", GET_MODEL_NAME_FOR_DEBUG(array[i]), " is loading.")
#ENDIF
//if the model is not loaded keep requesting it
REQUEST_MODEL(array[i])
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Requesting model ", GET_MODEL_NAME_FOR_DEBUG(array[i]), ".")
#ENDIF
RETURN FALSE
ENDIF
ENDFOR
ENDIF
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Models from model array loaded. Number of models loaded: ", iModelsAlreadyRequested, ".")
#ENDIF
RETURN TRUE
ENDFUNC
/// PURPOSE:
/// Cleans model array from requested models.
/// PARAMS:
/// array - MODEL_NAMES array.
/// iModelsAlreadyRequested - Number of already requested models. Should be greated than 0, since 0 means no models have been requested.
PROC CLEANUP_MODEL_ARRAY(MODEL_NAMES &array[], INT &iModelsAlreadyRequested)
INT i = 0
IF ( iModelsAlreadyRequested > 0 )
FOR i = 0 TO ( iModelsAlreadyRequested - 1 )
IF array[i] <> DUMMY_MODEL_FOR_SCRIPT
SET_MODEL_AS_NO_LONGER_NEEDED(array[i])
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Model ", GET_MODEL_NAME_FOR_DEBUG(array[i]), " cleaned up from model array by setting it as no longer needed.")
#ENDIF
array[i] = DUMMY_MODEL_FOR_SCRIPT
ENDIF
ENDFOR
ENDIF
iModelsAlreadyRequested = 0
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Model array cleaned up. Number of requested models set to 0.")
#ENDIF
ENDPROC
/// PURPOSE:
/// Checks if two strings are equal.
/// PARAMS:
/// sString1 - First string.
/// sString2 - Second string.
/// RETURNS:
/// TRUE if strings are equal, FALSE if otherwise or if any of the strings is empty or NULL.
FUNC BOOL IS_STRING_EQUAL_TO_STRING(STRING sString1, STRING sString2)
IF NOT Is_String_Null_Or_Empty(sString1)
AND NOT Is_String_Null_Or_Empty(sString2)
RETURN ARE_STRINGS_EQUAL(sString1, sString2)
ELSE
RETURN FALSE
ENDIF
ENDFUNC
/// PURPOSE:
/// Adds animation dictionary to animation request array.
/// PARAMS:
/// sAnimName - Name of the animation dictionary to request.
/// array - STRING array containing requested animations.
/// iArrayLength - Maximum length of the array
/// iAnimationsAlreadyRequested - Number of animations already requested in this array.
PROC ADD_ANIMATION_REQUEST_TO_ARRAY(STRING sAnimName, STRING &array[], INT iArrayLength, INT &iAnimationsAlreadyRequested)
INT i = 0
BOOL bAnimationRequested
IF ( iAnimationsAlreadyRequested >= 0 )
IF ( iAnimationsAlreadyRequested <= (iArrayLength - 1 ) )
FOR i = 0 TO ( iAnimationsAlreadyRequested )
IF IS_STRING_EQUAL_TO_STRING(sAnimName, array[i])
bAnimationRequested = TRUE
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Requested animation ", sAnimName, " is already in animation array.")
#ENDIF
ENDIF
ENDFOR
IF ( bAnimationRequested = FALSE )
REQUEST_ANIM_DICT(sAnimName)
array[iAnimationsAlreadyRequested] = sAnimName
iAnimationsAlreadyRequested++
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Requested animation ", sAnimName, " and added to animation array.")
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Number of animations requested: ", iAnimationsAlreadyRequested, ".")
#ENDIF
ENDIF
ELSE
SCRIPT_ASSERT("Number of requested animations is greater than the length of the animation array.")
ENDIF
ELSE
SCRIPT_ASSERT("Number of requested animations is less than 0.")
ENDIF
ENDPROC
/// PURPOSE:
/// Checks if all requested animations are loaded into memory.
/// PARAMS:
/// array - STRING array containing requested animations.
/// iAnimationsAlreadyRequested - Number of animations already requested in this array.
/// RETURNS:
/// TRUE if all requested animations from animation array are loaded into memory. FALSE if otherwise.
FUNC BOOL ARE_REQUESTED_ANIMATIONS_LOADED(STRING &array[], INT &iAnimationsAlreadyRequested)
INT i = 0
IF ( iAnimationsAlreadyRequested > 0 )
FOR i = 0 TO ( iAnimationsAlreadyRequested - 1 )
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Animation dictionary in array[", i, "]: ", array[i], ".")
#ENDIF
IF NOT HAS_ANIM_DICT_LOADED(array[i])
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Animation dictionary ", array[i], " is loading.")
#ENDIF
//if the animation dictionary is not loaded keep requesting it
REQUEST_ANIM_DICT(array[i])
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Requesting animation dictionary ", array[i], ".")
#ENDIF
RETURN FALSE
ENDIF
ENDFOR
ENDIF
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Animations from animation array loaded. Number of animations loaded: ", iAnimationsAlreadyRequested, ".")
#ENDIF
RETURN TRUE
ENDFUNC
/// PURPOSE:
/// Cleans animation array from requested animations.
/// PARAMS:
/// array - STRING array of animations to clean.
/// iAnimationsAlreadyRequested - Number of animations already requested in this array.
PROC CLEANUP_ANIMATION_ARRAY(STRING &array[], INT &iAnimationsAlreadyRequested)
INT i = 0
STRING sNull = NULL
IF ( iAnimationsAlreadyRequested > 0 )
FOR i = 0 TO ( iAnimationsAlreadyRequested - 1 )
//brute force remove animation dictionary from memory
REMOVE_ANIM_DICT(array[i])
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Animation dictionary ", array[i], " removed from memory and cleaned up from animation array.")
#ENDIF
array[i] = sNull
ENDFOR
ENDIF
iAnimationsAlreadyRequested = 0
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Animation array cleaned up. Number of requested animations set to 0.")
#ENDIF
ENDPROC
/// PURPOSE:
/// Adds a car recording number to recording request array.
/// PARAMS:
/// iRecording - Recording number being requested.
/// sFile - Name of the file containing the car recording.
/// array - INT arry to add the requested recording number to.
/// iArrayLength - Maximum length of the array
/// iRecordingsAlreadyRequested - Number of recordings already requested in this array.
PROC ADD_CARREC_REQUEST_TO_ARRAY(INT iRecording, STRING sFile, INT &array[], INT iArrayLength, INT &iRecordingsAlreadyRequested)
INT i = 0
BOOL bRecordingRequested = FALSE
IF ( iRecordingsAlreadyRequested >= 0 )
IF ( iRecordingsAlreadyRequested <= ( iArrayLength - 1 ) )
FOR i = 0 TO ( iRecordingsAlreadyRequested )
IF array[i] = iRecording
bRecordingRequested = TRUE
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Requested car recording ", iRecording, " is already in recording array.")
#ENDIF
ENDIF
ENDFOR
IF ( bRecordingRequested = FALSE )
REQUEST_VEHICLE_RECORDING(iRecording, sFile)
array[iRecordingsAlreadyRequested] = iRecording
iRecordingsAlreadyRequested++
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Requested car recording ", iRecording, " and added to recording array.")
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Number of car recordings requested: ", iRecordingsAlreadyRequested, ".")
#ENDIF
ENDIF
ELSE
SCRIPT_ASSERT("Number of requested recordings is greater than the length of the recording array.")
ENDIF
ELSE
SCRIPT_ASSERT("Number of requested recordings is less than 0.")
ENDIF
ENDPROC
/// PURPOSE:
/// Checks if all requested car recordings are loaded into memory.
/// PARAMS:
/// sFile - File name of the car recording file.
/// array - INT array holding the recording numbers.
/// iRecordingsAlreadyRequested - Number of already requested recordings. Should be greated than 0, since 0 means no recordings have been requested.
/// RETURNS:
/// TRUE if all recordings from recording array are loaded into memory. FALSE if otherwise.
FUNC BOOL ARE_REQUESTED_CARRECS_LOADED(STRING sFile, INT &array[], INT &iRecordingsAlreadyRequested)
INT i = 0
IF ( iRecordingsAlreadyRequested > 0 )
FOR i = 0 TO ( iRecordingsAlreadyRequested - 1 )
IF NOT HAS_VEHICLE_RECORDING_BEEN_LOADED(array[i], sFile)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Car recording ", array[i], " is loading.")
#ENDIF
//if the vehicle recording is not loaded keep requesting it
REQUEST_VEHICLE_RECORDING(array[i], sFile)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Requesting vehicle recording ", array[i], ".")
#ENDIF
RETURN FALSE
ENDIF
ENDFOR
ENDIF
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Car recordings from recording array loaded. Number of car recordings loaded: ", iRecordingsAlreadyRequested, ".")
#ENDIF
RETURN TRUE
ENDFUNC
/// PURPOSE:
/// Cleans recording array from requested recordings.
/// PARAMS:
/// sFile - File name of the car recording file.
/// array - INT array holding the recording numbers.
/// iRecordingsAlreadyRequested - Number of already requested recordings. Should be greated than 0, since 0 means no recordings have been requested.
PROC CLEANUP_CARREC_ARRAY(STRING sFile, INT &array[], INT &iRecordingsAlreadyRequested)
INT i = 0
IF ( iRecordingsAlreadyRequested > 0 )
FOR i = 0 TO ( iRecordingsAlreadyRequested - 1 )
IF HAS_VEHICLE_RECORDING_BEEN_LOADED(array[i], sFile)
REMOVE_VEHICLE_RECORDING(array[i], sFile)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Car recording ", array[i], " cleaned up from recording array.")
#ENDIF
array[i] = 0
ENDIF
ENDFOR
ENDIF
iRecordingsAlreadyRequested = 0
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Recording array cleaned up. Number of requested car recordings set to 0.")
#ENDIF
ENDPROC
//|===================== END ASSET REQUESTING PROCEDURES & FUNCTIONS =====================|
PROC GO_TO_PED_STATE(PED_STRUCT &psPed, PED_STATES eState)
psPed.bHasTask = FALSE
psPed.eState = eState
#IF IS_DEBUG_BUILD
IF NOT IS_STRING_NULL_OR_EMPTY(psPed.sDebugName)
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Sending ped with debug name ", psPed.sDebugName, " to state ", GET_PED_STATE_NAME_FOR_DEBUG(eState), ".")
ENDIF
#ENDIF
ENDPROC
FUNC BOOL IS_PED_IN_PED_STATE(PED_STRUCT &psPed, PED_STATES ePedState)
IF DOES_ENTITY_EXIST(psPed.PedIndex)
IF NOT IS_PED_INJURED(psPed.PedIndex)
IF ( psPed.eState = ePedState )
RETURN TRUE
ENDIF
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
//|========================== MISSION STAGE LOADINGS PROCEDURES ==========================|
/// PURPOSE:
/// Checks for various mission fail conditions. Redirects mission flow to MISSION_STAGE_FAILED when one of fail conditions is true.
/// PARAMS:
/// eStage - Mission stage variable.
/// eFail - Mission fail reason.
PROC RUN_FAIL_CHECKS(MISSION_STAGES &eStage, MISSION_FAILS &eFail)
IF eStage <> MISSION_STAGE_PASSED
AND eStage <> MISSION_STAGE_FAILED
IF NOT IS_CUTSCENE_PLAYING()
//check pickup, the mission car
IF DOES_ENTITY_EXIST(vsPlayersCar.VehicleIndex)
IF ( FailFlags[MISSION_FAIL_CAR_STUCK] = TRUE )
IF IS_VEHICLE_PERMANENTLY_STUCK(vsPlayersCar.VehicleIndex)
eFail = MISSION_FAIL_CAR_STUCK
eStage = MISSION_STAGE_FAILED
ENDIF
ENDIF
IF ( FailFlags[MISSION_FAIL_CAR_DESTROYED] = TRUE )
IF NOT IS_VEHICLE_DRIVEABLE(vsPlayersCar.VehicleIndex, TRUE)
OR ( HAS_ENTITY_BEEN_DAMAGED_BY_ENTITY(vsPlayersCar.VehicleIndex, PLAYER_PED_ID()) AND HAS_ENTITY_BEEN_DAMAGED_BY_WEAPON(vsPlayersCar.VehicleIndex, WEAPONTYPE_MOLOTOV) )
eFail = MISSION_FAIL_CAR_DESTROYED
eStage = MISSION_STAGE_FAILED
ENDIF
ENDIF
ENDIF
//check Franklin
IF DOES_ENTITY_EXIST(GET_PED_INDEX(CHAR_FRANKLIN))
IF ( FailFlags[MISSION_FAIL_FRANKLIN_DEAD] = TRUE )
IF IS_PED_INJURED(GET_PED_INDEX(CHAR_FRANKLIN))
eFail = MISSION_FAIL_FRANKLIN_DEAD
eStage = MISSION_STAGE_FAILED
ENDIF
ENDIF
IF ( FailFlags[MISSION_FAIL_FRANKLIN_LEFT_BEHIND] = TRUE )
IF NOT IS_PED_INJURED(GET_PED_INDEX(CHAR_FRANKLIN))
IF GET_DISTANCE_BETWEEN_PEDS(PLAYER_PED_ID(), GET_PED_INDEX(CHAR_FRANKLIN)) > ABANDON_BUDDY_FAIL_RANGE
eFail = MISSION_FAIL_FRANKLIN_LEFT_BEHIND
eStage = MISSION_STAGE_FAILED
ENDIF
ENDIF
ENDIF
ENDIF
//check Michael
IF DOES_ENTITY_EXIST(GET_PED_INDEX(CHAR_MICHAEL))
IF ( FailFlags[MISSION_FAIL_MICHAEL_DEAD] = TRUE )
IF IS_PED_INJURED(GET_PED_INDEX(CHAR_MICHAEL))
eFail = MISSION_FAIL_MICHAEL_DEAD
eStage = MISSION_STAGE_FAILED
ENDIF
ENDIF
IF ( FailFlags[MISSION_FAIL_MICHAEL_LEFT_BEHIND] = TRUE )
IF NOT IS_PED_INJURED(GET_PED_INDEX(CHAR_MICHAEL))
IF GET_DISTANCE_BETWEEN_PEDS(PLAYER_PED_ID(), GET_PED_INDEX(CHAR_MICHAEL)) > ABANDON_BUDDY_FAIL_RANGE
eFail = MISSION_FAIL_MICHAEL_LEFT_BEHIND
eStage = MISSION_STAGE_FAILED
ENDIF
ENDIF
ENDIF
ENDIF
//check tennis coach
IF DOES_ENTITY_EXIST(psCoach.PedIndex)
IF ( FailFlags[MISSION_FAIL_COACH_DEAD] = TRUE )
IF IS_PED_INJURED(psCoach.PedIndex)
eFail = MISSION_FAIL_COACH_DEAD
eStage = MISSION_STAGE_FAILED
ENDIF
ENDIF
IF ( FailFlags[MISSION_FAIL_COACH_ATTACKED] = TRUE )
IF NOT IS_PED_INJURED(psCoach.PedIndex)
IF HAS_ENTITY_BEEN_DAMAGED_BY_ENTITY(psCoach.PedIndex, PLAYER_PED_ID(), TRUE)
OR (IS_VEHICLE_DRIVEABLE(vsPlayersCar.VehicleIndex) AND HAS_ENTITY_BEEN_DAMAGED_BY_ENTITY(psCoach.PedIndex, vsPlayersCar.VehicleIndex))
OR IS_PED_USING_PETROL_CAN_AT_ENTITY(PLAYER_PED_ID(), psCoach.PedIndex, 3.0)
MAKE_PED_FLEE_PED(psCoach.PedIndex, PLAYER_PED_ID(), 300, -1)
eFail = MISSION_FAIL_COACH_ATTACKED
eStage = MISSION_STAGE_FAILED
ENDIF
ENDIF
ENDIF
IF ( FailFlags[MISSION_FAIL_COACH_SPOOKED] = TRUE )
IF NOT IS_PED_INJURED(psCoach.PedIndex)
IF ( IS_ENTITY_AT_COORD(psCoach.PedIndex, <<-1024.919800,661.292053,159.575302>>, << 10.25, 8.0, 4.75 >>)
AND IS_ENTITY_AT_COORD(PLAYER_PED_ID(), <<-1024.919800,661.292053,159.575302>>, << 10.25, 8.0, 4.75 >>) )
OR HAS_PED_RECEIVED_EVENT(psCoach.PedIndex, EVENT_SWITCH_2_NM_TASK)
OR HAS_PED_RECEIVED_EVENT(psCoach.PedIndex, EVENT_EXPLOSION)
OR HAS_PED_RECEIVED_EVENT(psCoach.PedIndex, EVENT_SHOCKING_EXPLOSION)
OR IS_PED_SHOOTING_AT_ENTITY(PLAYER_PED_ID(), psCoach.PedIndex, TRUE, 5.0)
MAKE_PED_FLEE_PED(psCoach.PedIndex, PLAYER_PED_ID(), 300, -1)
eFail = MISSION_FAIL_COACH_SPOOKED
eStage = MISSION_STAGE_FAILED
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Sets mission as failed and provides mission flow with reason to print on screen.
/// PARAMS:
/// eFailReason - One of MISSION_FAILS values.
PROC SET_MISSION_FAILED_WITH_REASON(MISSION_FAILS &eFailReason)
SWITCH eFailReason
//Player's car is destroyed
CASE MISSION_FAIL_CAR_DESTROYED
MISSION_FLOW_MISSION_FAILED_WITH_REASON("FAM3_TDEST")
BREAK
//Player's is undrivable
CASE MISSION_FAIL_CAR_STUCK
MISSION_FLOW_MISSION_FAILED_WITH_REASON("FAM3_TUND")
BREAK
//Michael is dead
CASE MISSION_FAIL_MICHAEL_DEAD
MISSION_FLOW_MISSION_FAILED_WITH_REASON("CMN_MDIED")
BREAK
//Michael is left behind
CASE MISSION_FAIL_MICHAEL_LEFT_BEHIND
MISSION_FLOW_MISSION_FAILED_WITH_REASON("CMN_MLEFT")
BREAK
//Franklin is dead
CASE MISSION_FAIL_FRANKLIN_DEAD
MISSION_FLOW_MISSION_FAILED_WITH_REASON("CMN_FDIED")
BREAK
//Franklin is left behind
CASE MISSION_FAIL_FRANKLIN_LEFT_BEHIND
MISSION_FLOW_MISSION_FAILED_WITH_REASON("CMN_FLEFT")
BREAK
//Tennis coach is dead
CASE MISSION_FAIL_COACH_DEAD
MISSION_FLOW_MISSION_FAILED_WITH_REASON("FAM3_CDEAD")
BREAK
//Tennis coach attacked
CASE MISSION_FAIL_COACH_ATTACKED
MISSION_FLOW_MISSION_FAILED_WITH_REASON("FAM3_CATTA")
BREAK
//Tennis coach spooked
CASE MISSION_FAIL_COACH_SPOOKED
MISSION_FLOW_MISSION_FAILED_WITH_REASON("FAM3_CSPOOK")
BREAK
//Generic fail
//Debug forced fail
CASE MISSION_FAIL_EMPTY
CASE MISSION_FAIL_FORCE_FAIL
MISSION_FLOW_MISSION_FAILED_WITH_REASON("FAM3_FAIL")
BREAK
ENDSWITCH
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Mission failed with reason ", GET_MISSION_FAIL_NAME_FOR_DEBUG(eFailReason), ".")
#ENDIF
ENDPROC
/// PURPOSE:
/// Sets mission stage enum for replay.
/// PARAMS:
/// eStage - Mission stage enum variable.
/// iValue - Mid-mission replay value returned by the script when replaying the mission.
PROC SET_MISSION_STAGE_FOR_REPLAY(MISSION_STAGES &eStage, INT iValue)
IF iValue = ENUM_TO_INT(MID_MISSION_STAGE_CAR_CHASE)
eStage = MISSION_STAGE_CAR_CHASE
ELIF iValue = ENUM_TO_INT(MID_MISSION_STAGE_PULL_HOUSE_DOWN)
eStage = MISSION_STAGE_PULL_HOUSE_DOWN
ELIF iValue = ENUM_TO_INT(MID_MISSION_STAGE_ESCAPE_GOONS)
eStage = MISSION_STAGE_ESCAPE_GOONS
ENDIF
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Mission is being replayed at stage ", GET_MISSION_STAGE_NAME_FOR_DEBUG(eStage), ".")
#ENDIF
ENDPROC
/// PURPOSE:
/// Handles cleaning up when mission ends.
PROC MISSION_CLEANUP()
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Starting mission cleanup.")
DELETE_DEBUG_WIDGETS()
#ENDIF
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF IS_SCREEN_FADED_OUT()
KILL_FACE_TO_FACE_CONVERSATION_DO_NOT_FINISH_LAST_LINE()
ELSE
KILL_FACE_TO_FACE_CONVERSATION()
ENDIF
KILL_ANY_CONVERSATION()
ENDIF
IF IS_ANY_TEXT_BEING_DISPLAYED(sLocatesData, IAT_IGNORE_GOD_TEXT_IF_SUBTITLES_OFF)
CLEAR_PRINTS()
ENDIF
IF IS_HELP_MESSAGE_BEING_DISPLAYED()
CLEAR_HELP()
ENDIF
CLEANUP_MODEL_ARRAY(MissionModels, iModelsRequested)
CLEANUP_CARREC_ARRAY(sVehicleRecordingsFile, MissionRecordings, iRecordingsRequested)
CLEANUP_ANIMATION_ARRAY(MissionAnimations, iAnimationsRequested)
CLEAR_MISSION_LOCATION_TEXT_AND_BLIPS(sLocatesData)
CLEANUP_UBER_PLAYBACK()
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
CLEAR_PED_TASKS(PLAYER_PED_ID())
SET_PED_CONFIG_FLAG(PLAYER_PED_ID(), PCF_WillFlyThroughWindscreen, TRUE)
ENDIF
//remove mission peds
SWITCH GET_CURRENT_PLAYER_PED_ENUM()
CASE CHAR_MICHAEL
IF DOES_ENTITY_EXIST(psFranklin.PedIndex)
IF NOT IS_PED_INJURED(psFranklin.PedIndex)
IF IS_PED_IN_COMBAT(psFranklin.PedIndex)
SET_PED_KEEP_TASK(psFranklin.PedIndex, TRUE)
ELSE
CLEAR_PED_TASKS(psFranklin.PedIndex)
ENDIF
IF IS_PED_GROUP_MEMBER(psFranklin.PedIndex, PLAYER_GROUP_ID())
REMOVE_PED_FROM_GROUP(psFranklin.PedIndex)
ENDIF
ENDIF
IF NOT IS_SCREEN_FADED_OUT()
SET_PED_AS_NO_LONGER_NEEDED(psFranklin.PedIndex)
ELSE
DELETE_PED(psFranklin.PedIndex)
ENDIF
ENDIF
BREAK
CASE CHAR_FRANKLIN
IF DOES_ENTITY_EXIST(psMichael.PedIndex)
IF NOT IS_PED_INJURED(psMichael.PedIndex)
IF IS_PED_IN_COMBAT(psMichael.PedIndex)
SET_PED_KEEP_TASK(psMichael.PedIndex, TRUE)
ELSE
CLEAR_PED_TASKS(psMichael.PedIndex)
ENDIF
IF IS_PED_GROUP_MEMBER(psMichael.PedIndex, PLAYER_GROUP_ID())
REMOVE_PED_FROM_GROUP(psMichael.PedIndex)
ENDIF
ENDIF
IF NOT IS_SCREEN_FADED_OUT()
SET_PED_AS_NO_LONGER_NEEDED(psMichael.PedIndex)
ELSE
DELETE_PED(psMichael.PedIndex)
ENDIF
ENDIF
BREAK
ENDSWITCH
IF DOES_ENTITY_EXIST(psCoach.PedIndex)
IF NOT IS_PED_INJURED(psCoach.PedIndex)
CLEAR_PED_TASKS(psCoach.PedIndex)
ENDIF
IF NOT IS_SCREEN_FADED_OUT()
SET_PED_AS_NO_LONGER_NEEDED(psCoach.PedIndex)
ELSE
DELETE_PED(psCoach.PedIndex)
ENDIF
ENDIF
IF DOES_ENTITY_EXIST(psVanDriver.PedIndex)
IF NOT IS_PED_INJURED(psVanDriver.PedIndex)
CLEAR_PED_TASKS(psVanDriver.PedIndex)
SET_PED_AS_NO_LONGER_NEEDED(psVanDriver.PedIndex)
ENDIF
ENDIF
//remove mission vehicles
IF DOES_ENTITY_EXIST(vsPlayersCar.VehicleIndex)
IF IS_VEHICLE_DRIVEABLE(vsPlayersCar.VehicleIndex)
SET_VEHICLE_AUTOMATICALLY_ATTACHES(vsPlayersCar.VehicleIndex, TRUE)
SET_VEHICLE_STRONG(vsPlayersCar.VehicleIndex, FALSE)
SET_VEHICLE_CAN_SAVE_IN_GARAGE(vsPlayersCar.VehicleIndex, TRUE)
SET_VEHICLE_AS_NO_LONGER_NEEDED(vsPlayersCar.VehicleIndex)
ENDIF
ENDIF
CLEANUP_VEHICLE(vsVan, FALSE, FALSE)
CLEANUP_VEHICLE(vsCoachsCar, FALSE, FALSE)
CLEANUP_VEHICLE(vsCutsceneCar, FALSE, FALSE)
//remove blips
IF DOES_BLIP_EXIST(vsPlayersCar.BlipIndex)
REMOVE_BLIP(vsPlayersCar.BlipIndex)
ENDIF
IF DOES_BLIP_EXIST(vsCoachsCar.BlipIndex)
REMOVE_BLIP(vsCoachsCar.BlipIndex)
ENDIF
CLEANUP_PED_GROUP(psEnemyGoonsCar0, FALSE, FALSE, TRUE)
CLEANUP_PED_GROUP(psEnemyGoonsCar1, FALSE, FALSE, TRUE)
CLEANUP_VEHICLE_GROUP(vsEnemyCars, FALSE, FALSE)
//remove relationship groups
REMOVE_RELATIONSHIP_GROUP(rgEnemies)
//remove rope an anchor
IF DOES_ROPE_EXIST(Rope)
AND DOES_ENTITY_EXIST(osRopeAnchor.ObjectIndex)
DETACH_ROPE_FROM_ENTITY(Rope, osRopeAnchor.ObjectIndex)
DELETE_ROPE(Rope)
DELETE_OBJECT(osRopeAnchor.ObjectIndex)
ROPE_UNLOAD_TEXTURES()
bRopeAttached = FALSE
ENDIF
IF DOES_ENTITY_EXIST(osRopeDummy.ObjectIndex)
DELETE_OBJECT(osRopeDummy.ObjectIndex)
ENDIF
IF DOES_ENTITY_EXIST(osRopeProp.ObjectIndex)
DELETE_OBJECT(osRopeProp.ObjectIndex)
ENDIF
IF DOES_ENTITY_EXIST(osBootCollision.ObjectIndex)
DELETE_OBJECT(osBootCollision.ObjectIndex)
ENDIF
IF DOES_ENTITY_EXIST(osCellphone.ObjectIndex)
DELETE_OBJECT(osCellphone.ObjectIndex)
ENDIF
IF DOES_ENTITY_EXIST(osBrokenPlantPot.ObjectIndex)
SET_OBJECT_AS_NO_LONGER_NEEDED(osBrokenPlantPot.ObjectIndex)
ENDIF
//remove particle fx attached to player's truck
IF DOES_PARTICLE_FX_LOOPED_EXIST(ptfxRearLeftWheel)
REMOVE_PARTICLE_FX(ptfxRearLeftWheel)
ENDIF
IF DOES_PARTICLE_FX_LOOPED_EXIST(ptfxRearRightWheel)
REMOVE_PARTICLE_FX(ptfxRearRightWheel)
ENDIF
IF DOES_PARTICLE_FX_LOOPED_EXIST(ptfxDustCloud)
REMOVE_PARTICLE_FX(ptfxDustCloud)
ENDIF
REMOVE_PTFX_ASSET()
REMOVE_ANIM_DICT("missfam3")
REMOVE_ANIM_DICT("switch@michael@bench")
//disable mission vehicle models suppressing
SET_VEHICLE_MODEL_IS_SUPPRESSED(TAILGATER, FALSE) //Michael's car
SET_VEHICLE_MODEL_IS_SUPPRESSED(BISON2, FALSE) //player's car during mission
SET_VEHICLE_MODEL_IS_SUPPRESSED(BISON, FALSE) //car that looks the same like mission car
SET_VEHICLE_MODEL_IS_SUPPRESSED(BISON3, FALSE) //car that looks the same like mission car
SET_VEHICLE_MODEL_IS_SUPPRESSED(SADLER, FALSE) //car that looks the same like mission car
SET_VEHICLE_MODEL_IS_SUPPRESSED(BLISTA, FALSE) //tennis coach's car
SET_VEHICLE_MODEL_IS_SUPPRESSED(BALLER, FALSE) //enemy car
//disable mission ped models suppressing
SET_PED_MODEL_IS_SUPPRESSED(G_M_Y_POLOGOON_01, FALSE)
REMOVE_VEHICLE_ASSET(BISON2)
//enable the car gen on mission cleanup
DISABLE_VEHICLE_GEN_ON_MISSION(FALSE)
SET_VEHICLE_GEN_AVAILABLE(VEHGEN_MICHAEL_SAVEHOUSE, TRUE)
SET_MAX_WANTED_LEVEL(5)
SET_CREATE_RANDOM_COPS(TRUE)
SET_WANTED_LEVEL_MULTIPLIER(1.0)
SET_PED_POPULATION_BUDGET(3)
SET_VEHICLE_POPULATION_BUDGET(3)
SET_GPS_DISABLED_ZONE(<< 0.0, 0.0, 0.0 >>, << 0.0, 0.0, 0.0 >>)
DISABLE_CELLPHONE(FALSE)
DISABLE_TAXI_HAILING(FALSE)
//enable fire dept and ambulance dept
ENABLE_DISPATCH_SERVICE(DT_FIRE_DEPARTMENT, TRUE)
ENABLE_DISPATCH_SERVICE(DT_AMBULANCE_DEPARTMENT, TRUE)
STOP_GAMEPLAY_CAM_SHAKING()
STOP_STREAM()
STOP_AUDIO_SCENES()
CANCEL_MUSIC_EVENT("FAM3_HOUSE_COLLAPSE")
TRIGGER_MUSIC_EVENT("FAM3_MISSION_FAIL")
SET_PLAYER_CAN_CHANGE_CLOTHES_ON_MISSION(TRUE)
SET_PLAYER_PED_DATA_IN_CUTSCENES(TRUE, TRUE)
SET_PLAYER_PED_CAN_ENTER_SAVEHOUSE(CHAR_FRANKLIN, SAVEHOUSE_MICHAEL_BH, FALSE)
RELEASE_SUPPRESSED_EMERGENCY_CALLS()
IF IS_DOOR_REGISTERED_WITH_SYSTEM(ENUM_TO_INT(DOORHASH_M_MANSION_G1))
DOOR_SYSTEM_SET_OPEN_RATIO(ENUM_TO_INT(DOORHASH_M_MANSION_G1), 0.0, FALSE, FALSE)
DOOR_SYSTEM_SET_DOOR_STATE(ENUM_TO_INT(DOORHASH_M_MANSION_G1), DOORSTATE_UNLOCKED, FALSE, TRUE)
ENDIF
LOCK_AUTOMATIC_DOOR_OPEN(AUTODOOR_MICHAEL_MANSION_GATE, FALSE)
//CASCADE_SHADOWS_INIT_SESSION()
SET_INSTANCE_PRIORITY_HINT(INSTANCE_HINT_NONE)
STOP_GAMEPLAY_HINT()
KILL_CHASE_HINT_CAM(localChaseHintCamStruct)
REMOVE_NAVMESH_BLOCKING_OBJECTS()
SET_NO_LOADING_SCREEN(FALSE)
#IF IS_DEBUG_BUILD
SET_DEBUG_LINES_AND_SPHERES_DRAWING_ACTIVE(FALSE)
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Finished mission cleanup.")
#ENDIF
ENDPROC
/// PURPOSE:
/// Populates structs and arrays with data such as vectors, model names etc for a specified mission stage.
/// PARAMS:
/// eStage - Mission stage to initialise arrays for.
PROC INITIALISE_ARRAYS_FOR_MISSION_STAGE(MISSION_STAGES eStage)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Initialising arrays for ", GET_MISSION_STAGE_NAME_FOR_DEBUG(eStage), ".")
#ENDIF
SWITCH eStage
CASE MISSION_STAGE_CUTSCENE_INTRO
psMichael.vPosition = <<-813.8015, 179.2288, 71.1592>>
psMichael.fHeading = 294.8454
psMichael.ModelName = GET_PLAYER_PED_MODEL(CHAR_MICHAEL)
vsPlayersCar.vPosition = << -827.1151, 176.4370, 69.9585 >>
vsPlayersCar.fHeading = 148.7250
vsPlayersCar.ModelName = BISON2
psFranklin.vPosition = <<-813.8015, 179.2288, 71.1592>>
psFranklin.fHeading = 294.8454
psFranklin.ModelName = GET_PLAYER_PED_MODEL(CHAR_FRANKLIN)
vsCoachsCar.vPosition = <<-826.2942, 158.1811, 68.3918>>
vsCoachsCar.fHeading = 84.0848
vsCoachsCar.ModelName = BLISTA
vsCoachsCar.iRecordingNumber = 53
psCoach.vPosition = << -856.0540, 149.5746, 62.2112 >>
psCoach.fHeading = 3.1630
psCoach.ModelName = GET_NPC_PED_MODEL(CHAR_TENNIS_COACH)
osRacket01.vPosition = <<-818.0380, 179.2600, 71.2520>>
osRacket01.vRotation = <<-20.5200, -74.0200, 14.3000>>
osRacket01.ModelName = PROP_TENNIS_RACK_01
osRacket02.vPosition = <<-818.1280, 179.1527, 71.2620>>
osRacket02.vRotation = <<-39.2400, -75.9600, 16.2000>>
osRacket02.ModelName = PROP_TENNIS_RACK_01B
osBrokenPlantPot.vPosition = <<-819.6521, 176.6348, 70.7600>>
osBrokenPlantPot.vRotation = <<6.1200, 0.0000, -68.4000>>
osBrokenPlantPot.ModelName = PROP_WINDOWBOX_BROKEN
BREAK
CASE MISSION_STAGE_CAR_CHASE
psMichael.vPosition = <<-824.3681, 176.9837, 70.1645>>//<< -825.9493, 175.4956, 69.8794 >>
psMichael.fHeading = 135.3757//148.9250
psMichael.ModelName = GET_PLAYER_PED_MODEL(CHAR_MICHAEL)
vsPlayersCar.vPosition = << -827.1151, 176.4370, 69.9585 >>
vsPlayersCar.fHeading = 148.7250
vsPlayersCar.ModelName = BISON2
psFranklin.vPosition = << -828.5035, 177.0551, 69.9812 >>
psFranklin.fHeading = 159.2800
psFranklin.ModelName = GET_PLAYER_PED_MODEL(CHAR_FRANKLIN)
vsCoachsCar.vPosition = <<-826.2942, 158.1811, 68.3918>>
vsCoachsCar.fHeading = 84.0848
vsCoachsCar.ModelName = BLISTA
vsCoachsCar.iRecordingNumber = 53
psCoach.vPosition = << -856.0540, 149.5746, 62.2112 >>
psCoach.fHeading = 3.1630
psCoach.ModelName = GET_NPC_PED_MODEL(CHAR_TENNIS_COACH)
vsVan.vPosition = << -1386.9448, 456.5691, 104.2549 >>
vsVan.fHeading = 28.1851
vsVan.ModelName = JOURNEY
vsVan.iRecordingNumber = 51
psVanDriver.ModelName = A_M_M_BEVHILLS_01
osRacket01.vPosition = <<-818.0380, 179.2600, 71.2520>>
osRacket01.vRotation = <<-20.5200, -74.0200, 14.3000>>
osRacket01.ModelName = PROP_TENNIS_RACK_01
osRacket02.vPosition = <<-818.1280, 179.1527, 71.2620>>
osRacket02.vRotation = <<-39.2400, -75.9600, 16.2000>>
osRacket02.ModelName = PROP_TENNIS_RACK_01
osBrokenPlantPot.vPosition = <<-819.6521, 176.6348, 70.7600>>
osBrokenPlantPot.vRotation = <<6.1200, 0.0000, -68.4000>>
osBrokenPlantPot.ModelName = PROP_WINDOWBOX_BROKEN
BREAK
CASE MISSION_STAGE_CUTSCENE_BACK_OF_HOUSE
psMichael.vPosition = << -993.4860, 647.2808, 138.8108 >>
psMichael.fHeading = 274.6140
psMichael.ModelName = GET_PLAYER_PED_MODEL(CHAR_MICHAEL)
vsPlayersCar.vPosition = << -992.1501, 645.7378, 138.7702 >>
vsPlayersCar.fHeading = 282.1990
vsPlayersCar.ModelName = BISON2
psFranklin.vPosition = << -991.8490, 643.7483, 138.6733 >>
psFranklin.fHeading = 332.4843
psFranklin.ModelName = GET_PLAYER_PED_MODEL(CHAR_FRANKLIN)
vsCoachsCar.vPosition = <<-1007.2410, 708.9224, 161.0334>>
vsCoachsCar.fHeading = 358.5527
vsCoachsCar.ModelName = BLISTA
psCoach.vPosition = << -1026.9159, 653.8083, 155.0754 >>
psCoach.fHeading = 196.6071
psCoach.ModelName = GET_NPC_PED_MODEL(CHAR_TENNIS_COACH)
osRopeAnchor.vPosition = <<-1017.8320, 660.5620, 147.1470>>
osRopeAnchor.vRotation = <<15.0000, 15.0000, -0.0000>>
osRopeAnchor.ModelName = PROP_LD_ROPE_T
osRopeDummy.vPosition = <<-1006.0800, 652.8800, 143.6200>>
osRopeDummy.vRotation = <<0.0000, 15.0100, -32.4000>>
osRopeDummy.ModelName = PROP_LD_DUMMY_ROPE
osRopeProp.vPosition = <<-1018.2600, 660.6490, 147.2000>>
osRopeProp.vRotation = <<0.0000, 5.0000, -25.5600>>
osRopeProp.ModelName = PROP_ROPE_FAMILY_3
osBootCollision.vPosition = <<-995.2775, 645.0095, 139.6500>>
osBootCollision.vRotation = <<-90.0000, 0.0000, 102.0000>>
osBootCollision.ModelName = PROP_TAIL_GATE_COL
BREAK
CASE MISSION_STAGE_PULL_HOUSE_DOWN
psMichael.vPosition = << -993.4773, 647.6854, 138.7637 >>
psMichael.fHeading = 255.1397
psMichael.ModelName = GET_PLAYER_PED_MODEL(CHAR_MICHAEL)
vsPlayersCar.vPosition = << -992.1501, 645.7378, 138.7702 >>
vsPlayersCar.fHeading = 282.1990
vsPlayersCar.ModelName = BISON2
psFranklin.vPosition = << -992.5433, 643.7088, 138.7174 >>
psFranklin.fHeading = 86.0291
psFranklin.ModelName = GET_PLAYER_PED_MODEL(CHAR_FRANKLIN)
vsCoachsCar.vPosition = <<-1007.2410, 708.9224, 161.0334>>
vsCoachsCar.fHeading = 358.5527
vsCoachsCar.ModelName = BLISTA
psCoach.vPosition = << -1014.6680, 654.4220, 155.3056 >>
psCoach.fHeading = 252.4493
psCoach.ModelName = GET_NPC_PED_MODEL(CHAR_TENNIS_COACH)
osRopeAnchor.vPosition = <<-1017.8320, 660.5620, 147.1470>>
osRopeAnchor.vRotation = <<15.0000, 15.0000, -0.0000>>
osRopeAnchor.ModelName = PROP_LD_ROPE_T
osRopeDummy.vPosition = <<-1006.0800, 652.8800, 143.6200>>
osRopeDummy.vRotation = <<0.0000, 15.0100, -32.4000>>
osRopeDummy.ModelName = PROP_LD_DUMMY_ROPE
osRopeProp.vPosition = <<-1018.2600, 660.6490, 147.2000>>
osRopeProp.vRotation = <<0.0000, 5.0000, -25.5600>>
osRopeProp.ModelName = PROP_ROPE_FAMILY_3
osBootCollision.vPosition = <<-995.2775, 645.0095, 139.6500>>
osBootCollision.vRotation = <<-90.0000, 0.0000, 102.0000>>
osBootCollision.ModelName = PROP_TAIL_GATE_COL
BREAK
CASE MISSION_STAGE_ESCAPE_GOONS
psMichael.vPosition = << -993.4773, 647.6854, 138.7637 >>
psMichael.fHeading = 255.1397
psMichael.ModelName = GET_PLAYER_PED_MODEL(CHAR_MICHAEL)
vsPlayersCar.vPosition = << -977.7563, 646.6259, 137.9191 >>
vsPlayersCar.fHeading = 280.3406
vsPlayersCar.ModelName = BISON2
psFranklin.vPosition = << -992.5433, 643.7088, 138.7174 >>
psFranklin.fHeading = 86.0291
psFranklin.ModelName = GET_PLAYER_PED_MODEL(CHAR_FRANKLIN)
vsCoachsCar.vPosition = << -1008.7057, 710.1682, 161.5234 >>
vsCoachsCar.fHeading = 347.3929
vsCoachsCar.ModelName = BLISTA
psCoach.vPosition = << -1020.19, 698.98, 160.9 >>
psCoach.fHeading = 76.31
psCoach.ModelName = GET_NPC_PED_MODEL(CHAR_TENNIS_COACH)
BREAK
CASE MISSION_STAGE_CUTSCENE_END
psMichael.vPosition = << -816.3374, 160.8270, 70.0828 >>
psMichael.fHeading = 293.3672
psMichael.ModelName = GET_PLAYER_PED_MODEL(CHAR_MICHAEL)
vsPlayersCar.vPosition = <<-822.9047, 182.4500, 70.8286>> //<< -815.4899, 159.4702, 70.1270 >>
vsPlayersCar.fHeading = 305.1158 //293.2592
vsPlayersCar.ModelName = BISON2
psFranklin.vPosition = << -815.2599, 157.9198, 70.0847 >>
psFranklin.fHeading = 300.3756
psFranklin.ModelName = GET_PLAYER_PED_MODEL(CHAR_FRANKLIN)
vsCutsceneCar.vPosition = <<-777.6288, 161.9553, 66.4745>>
vsCutsceneCar.fHeading = 359.0025
vsCutsceneCar.ModelName = BALLER
BREAK
CASE MISSION_STAGE_LEADOUT
psMichael.vPosition = <<-95.550, -415.100, 35.6750>>
psMichael.fHeading = 133.000
psMichael.ModelName = GET_PLAYER_PED_MODEL(CHAR_MICHAEL)
vsMichaelsEndCar.vPosition = <<-155.8183, -423.4282, 32.8517>>
vsMichaelsEndCar.fHeading = 342.5681
vsMichaelsEndCar.ModelName = GET_PLAYER_VEH_MODEL(CHAR_MICHAEL)
osCellphone.vPosition = <<-95.550, -415.100, 35.6750>>
osCellphone.vRotation = << 0.0, 0.0, 0.0 >>
osCellphone.ModelName = Prop_phone_ING
BREAK
//debug stages
#IF IS_DEBUG_BUILD
CASE MISSION_STAGE_DEBUG_RECORD_CHASE
CASE MISSION_STAGE_DEBUG_PLAYBACK_CHASE
psMichael.vPosition = << -821.6009, 177.3395, 70.4432 >>
psMichael.fHeading = 100.3065
psMichael.ModelName = GET_PLAYER_PED_MODEL(CHAR_MICHAEL)
vsCoachsCar.vPosition = << -857.9623, 149.2353, 61.8515 >>
vsCoachsCar.fHeading = 346.0251
vsCoachsCar.ModelName = BLISTA
vsCoachsCar.iRecordingNumber = 53
BREAK
#ENDIF
ENDSWITCH
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Finished initialising arrays for ", GET_MISSION_STAGE_NAME_FOR_DEBUG(eStage), ".")
#ENDIF
ENDPROC
PROC BUILD_REQUEST_BANK_FOR_MISSION_STAGE(MISSION_STAGES eStage)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Building request bank for ", GET_MISSION_STAGE_NAME_FOR_DEBUG(eStage), ".")
#ENDIF
SWITCH eStage
CASE MISSION_STAGE_CUTSCENE_INTRO
//don't request anything here
BREAK
CASE MISSION_STAGE_CAR_CHASE
IF NOT DOES_ENTITY_EXIST(vsPlayersCar.VehicleIndex)
ADD_MODEL_REQUEST_TO_ARRAY(vsPlayersCar.ModelName, MissionModels, MAX_MODELS, iModelsRequested)
ENDIF
IF GET_CURRENT_PLAYER_PED_ENUM() = CHAR_MICHAEL
IF NOT DOES_ENTITY_EXIST(psFranklin.PedIndex)
ADD_MODEL_REQUEST_TO_ARRAY(psFranklin.ModelName, MissionModels, MAX_MODELS, iModelsRequested)
ENDIF
ELIF GET_CURRENT_PLAYER_PED_ENUM() = CHAR_FRANKLIN
IF NOT DOES_ENTITY_EXIST(psMichael.PedIndex)
ADD_MODEL_REQUEST_TO_ARRAY(psMichael.ModelName, MissionModels, MAX_MODELS, iModelsRequested)
ENDIF
ENDIF
IF NOT DOES_ENTITY_EXIST(vsCoachsCar.VehicleIndex)
ADD_MODEL_REQUEST_TO_ARRAY(vsCoachsCar.ModelName, MissionModels, MAX_MODELS, iModelsRequested)
ENDIF
IF NOT DOES_ENTITY_EXIST(psCoach.PedIndex)
ADD_MODEL_REQUEST_TO_ARRAY(psCoach.ModelName, MissionModels, MAX_MODELS, iModelsRequested)
ENDIF
ADD_CARREC_REQUEST_TO_ARRAY(vsCoachsCar.iRecordingNumber, sVehicleRecordingsFile, MissionRecordings, MAX_CAR_RECORDINGS, iRecordingsRequested)
BREAK
CASE MISSION_STAGE_CUTSCENE_BACK_OF_HOUSE
IF NOT DOES_ENTITY_EXIST(vsPlayersCar.VehicleIndex)
ADD_MODEL_REQUEST_TO_ARRAY(vsPlayersCar.ModelName, MissionModels, MAX_MODELS, iModelsRequested)
ENDIF
IF GET_CURRENT_PLAYER_PED_ENUM() = CHAR_MICHAEL
IF NOT DOES_ENTITY_EXIST(psFranklin.PedIndex)
ADD_MODEL_REQUEST_TO_ARRAY(psFranklin.ModelName, MissionModels, MAX_MODELS, iModelsRequested)
ENDIF
ELIF GET_CURRENT_PLAYER_PED_ENUM() = CHAR_FRANKLIN
IF NOT DOES_ENTITY_EXIST(psMichael.PedIndex)
ADD_MODEL_REQUEST_TO_ARRAY(psMichael.ModelName, MissionModels, MAX_MODELS, iModelsRequested)
ENDIF
ENDIF
IF NOT DOES_ENTITY_EXIST(psCoach.PedIndex)
ADD_MODEL_REQUEST_TO_ARRAY(psCoach.ModelName, MissionModels, MAX_MODELS, iModelsRequested)
ENDIF
IF NOT DOES_ENTITY_EXIST(osRopeAnchor.ObjectIndex)
ADD_MODEL_REQUEST_TO_ARRAY(osRopeAnchor.ModelName, MissionModels, MAX_MODELS, iModelsRequested)
ENDIF
ADD_ANIMATION_REQUEST_TO_ARRAY("missfam3", MissionAnimations, MAX_ANIMATIONS, iAnimationsRequested)
BREAK
CASE MISSION_STAGE_PULL_HOUSE_DOWN
IF NOT DOES_ENTITY_EXIST(vsPlayersCar.VehicleIndex)
ADD_MODEL_REQUEST_TO_ARRAY(vsPlayersCar.ModelName, MissionModels, MAX_MODELS, iModelsRequested)
ENDIF
IF GET_CURRENT_PLAYER_PED_ENUM() = CHAR_MICHAEL
IF NOT DOES_ENTITY_EXIST(psFranklin.PedIndex)
ADD_MODEL_REQUEST_TO_ARRAY(psFranklin.ModelName, MissionModels, MAX_MODELS, iModelsRequested)
ENDIF
ELIF GET_CURRENT_PLAYER_PED_ENUM() = CHAR_FRANKLIN
IF NOT DOES_ENTITY_EXIST(psMichael.PedIndex)
ADD_MODEL_REQUEST_TO_ARRAY(psMichael.ModelName, MissionModels, MAX_MODELS, iModelsRequested)
ENDIF
ENDIF
IF NOT DOES_ENTITY_EXIST(psCoach.PedIndex)
ADD_MODEL_REQUEST_TO_ARRAY(psCoach.ModelName, MissionModels, MAX_MODELS, iModelsRequested)
ENDIF
IF NOT DOES_ENTITY_EXIST(osRopeAnchor.ObjectIndex)
ADD_MODEL_REQUEST_TO_ARRAY(osRopeAnchor.ModelName, MissionModels, MAX_MODELS, iModelsRequested)
ENDIF
IF NOT DOES_ENTITY_EXIST(osRopeProp.ObjectIndex)
ADD_MODEL_REQUEST_TO_ARRAY(osRopeProp.ModelName, MissionModels, MAX_MODELS, iModelsRequested)
ENDIF
IF NOT DOES_ENTITY_EXIST(osBootCollision.ObjectIndex)
ADD_MODEL_REQUEST_TO_ARRAY(osBootCollision.ModelName, MissionModels, MAX_MODELS, iModelsRequested)
ENDIF
ADD_ANIMATION_REQUEST_TO_ARRAY("missfam3", MissionAnimations, MAX_ANIMATIONS, iAnimationsRequested)
BREAK
CASE MISSION_STAGE_CUTSCENE_END
IF NOT DOES_ENTITY_EXIST(vsPlayersCar.VehicleIndex)
ADD_MODEL_REQUEST_TO_ARRAY(vsPlayersCar.ModelName, MissionModels, MAX_MODELS, iModelsRequested)
ENDIF
IF GET_CURRENT_PLAYER_PED_ENUM() = CHAR_MICHAEL
IF NOT DOES_ENTITY_EXIST(psFranklin.PedIndex)
ADD_MODEL_REQUEST_TO_ARRAY(psFranklin.ModelName, MissionModels, MAX_MODELS, iModelsRequested)
ENDIF
ELIF GET_CURRENT_PLAYER_PED_ENUM() = CHAR_FRANKLIN
IF NOT DOES_ENTITY_EXIST(psMichael.PedIndex)
ADD_MODEL_REQUEST_TO_ARRAY(psMichael.ModelName, MissionModels, MAX_MODELS, iModelsRequested)
ENDIF
ENDIF
BREAK
CASE MISSION_STAGE_LEADOUT
//
BREAK
//debug stages
#IF IS_DEBUG_BUILD
CASE MISSION_STAGE_DEBUG_RECORD_CHASE
CASE MISSION_STAGE_DEBUG_PLAYBACK_CHASE
IF NOT DOES_ENTITY_EXIST(vsCoachsCar.VehicleIndex)
ADD_MODEL_REQUEST_TO_ARRAY(vsCoachsCar.ModelName, MissionModels, MAX_MODELS, iModelsRequested)
ENDIF
ADD_CARREC_REQUEST_TO_ARRAY(vsCoachsCar.iRecordingNumber, sVehicleRecordingsFile, MissionRecordings, MAX_CAR_RECORDINGS, iRecordingsRequested)
BREAK
#ENDIF
ENDSWITCH
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Finished building request bank for ", GET_MISSION_STAGE_NAME_FOR_DEBUG(eStage), ".")
#ENDIF
ENDPROC
PROC UPDATE_THIRD_PERSON_RUN_TO_VEHICLE_CAMERA()
IF ( bStopForcingThirdPersonCamera = FALSE )
IF GET_CAM_VIEW_MODE_FOR_CONTEXT(CAM_VIEW_MODE_CONTEXT_IN_VEHICLE) = CAM_VIEW_MODE_THIRD_PERSON
OR GET_CAM_VIEW_MODE_FOR_CONTEXT(CAM_VIEW_MODE_CONTEXT_IN_VEHICLE) = CAM_VIEW_MODE_THIRD_PERSON_NEAR
OR GET_CAM_VIEW_MODE_FOR_CONTEXT(CAM_VIEW_MODE_CONTEXT_IN_VEHICLE) = CAM_VIEW_MODE_THIRD_PERSON_MEDIUM
OR GET_CAM_VIEW_MODE_FOR_CONTEXT(CAM_VIEW_MODE_CONTEXT_IN_VEHICLE) = CAM_VIEW_MODE_THIRD_PERSON_FAR
IF GET_CAM_VIEW_MODE_FOR_CONTEXT(CAM_VIEW_MODE_CONTEXT_ON_FOOT) = CAM_VIEW_MODE_FIRST_PERSON
IF NOT IS_PED_SITTING_IN_THIS_VEHICLE(PLAYER_PED_ID(), vsPlayersCar.VehicleIndex)
DISABLE_ON_FOOT_FIRST_PERSON_VIEW_THIS_UPDATE()
ELSE
bStopForcingThirdPersonCamera = TRUE
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": UPDATE_THIRD_PERSON_RUN_TO_VEHICLE_CAMERA() - Stopping forcing third person camera due to player sitting in vehicle.")
#ENDIF
ENDIF
ELSE
bStopForcingThirdPersonCamera = TRUE
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": UPDATE_THIRD_PERSON_RUN_TO_VEHICLE_CAMERA() - Stopping forcing third person camera due to view cam mode selected.")
#ENDIF
ENDIF
ELIF GET_CAM_VIEW_MODE_FOR_CONTEXT(CAM_VIEW_MODE_CONTEXT_IN_VEHICLE) = CAM_VIEW_MODE_FIRST_PERSON
IF NOT IS_PED_IN_THIS_VEHICLE(PLAYER_PED_ID(), vsPlayersCar.VehicleIndex, TRUE)
DISABLE_ON_FOOT_FIRST_PERSON_VIEW_THIS_UPDATE()
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": UPDATE_THIRD_PERSON_RUN_TO_VEHICLE_CAMERA() - Disabling on foot first person camera. Player not in vehicle.")
#ENDIF
ELSE
DISABLE_ON_FOOT_FIRST_PERSON_VIEW_THIS_UPDATE()
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": UPDATE_THIRD_PERSON_RUN_TO_VEHICLE_CAMERA() - Disabling on foot first person camera. Player in vehicle or getting into vehicle.")
#ENDIF
IF ( bFirstPersonFlashPlayed = FALSE )
IF iFirstPersonFlashTimer = 0
IF GET_CAM_VIEW_MODE_FOR_CONTEXT(CAM_VIEW_MODE_CONTEXT_ON_FOOT) = CAM_VIEW_MODE_FIRST_PERSON
ANIMPOSTFX_PLAY(PICK_STRING(bTriggerSwitchFlash, "CamPushInMichael", "CamPushInNeutral"), 0, FALSE)
PLAY_SOUND_FRONTEND(-1, "1st_Person_Transition", "PLAYER_SWITCH_CUSTOM_SOUNDSET")
iFirstPersonFlashTimer = GET_GAME_TIMER()
ELSE
DISABLE_CINEMATIC_BONNET_CAMERA_THIS_UPDATE()
IF IS_PED_SITTING_IN_THIS_VEHICLE(PLAYER_PED_ID(), vsPlayersCar.VehicleIndex)
ANIMPOSTFX_PLAY(PICK_STRING(bTriggerSwitchFlash, "CamPushInMichael", "CamPushInNeutral"), 0, FALSE)
PLAY_SOUND_FRONTEND(-1, "1st_Person_Transition", "PLAYER_SWITCH_CUSTOM_SOUNDSET")
iFirstPersonFlashTimer = GET_GAME_TIMER()
ENDIF
ENDIF
ELSE
IF GET_CAM_VIEW_MODE_FOR_CONTEXT(CAM_VIEW_MODE_CONTEXT_ON_FOOT) != CAM_VIEW_MODE_FIRST_PERSON
DISABLE_CINEMATIC_BONNET_CAMERA_THIS_UPDATE()
ENDIF
IF HAS_TIME_PASSED(iFirstPersonFlashTime, iFirstPersonFlashTimer)
bFirstPersonFlashPlayed = TRUE
ENDIF
ENDIF
ELSE
bStopForcingThirdPersonCamera = TRUE
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": UPDATE_THIRD_PERSON_RUN_TO_VEHICLE_CAMERA() - Stopping forcing third person camera due to player being in vehicle.")
#ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDPROC
FUNC BOOL IS_MISSION_STAGE_LOADED(MISSION_STAGES eStage, INT &iSetupProgress, BOOL &bStageLoaded, BOOL &bStageSkippedTo, BOOL &bStageReplayed)
//handle initial mission setup
//only run this IF block once, when the mission first loads
IF ( iSetupProgress = 0 )
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Starting initial mission loading.")
#ENDIF
//clear the screen of any text displayed before mission started
CLEAR_PRINTS()
CLEAR_HELP()
//load the mission text
REQUEST_ADDITIONAL_TEXT("FAM3", MISSION_TEXT_SLOT)
REQUEST_ADDITIONAL_TEXT("FAM3AUD", MISSION_DIALOGUE_TEXT_SLOT)
WHILE NOT HAS_ADDITIONAL_TEXT_LOADED(MISSION_TEXT_SLOT)
OR NOT HAS_ADDITIONAL_TEXT_LOADED(MISSION_DIALOGUE_TEXT_SLOT)
WAIT(0)
ENDWHILE
REGISTER_SCRIPT_WITH_AUDIO(TRUE)
//suppress vehicle models used in mission
SET_VEHICLE_MODEL_IS_SUPPRESSED(TAILGATER, TRUE) //Michael's car
SET_VEHICLE_MODEL_IS_SUPPRESSED(BISON2, TRUE)
SET_VEHICLE_MODEL_IS_SUPPRESSED(BISON, TRUE) //car that looks the same like mission car
SET_VEHICLE_MODEL_IS_SUPPRESSED(BISON3, TRUE) //car that looks the same like mission car
SET_VEHICLE_MODEL_IS_SUPPRESSED(SADLER, TRUE) //car that looks the same like mission car
SET_VEHICLE_MODEL_IS_SUPPRESSED(BLISTA, TRUE) //tennis coach's car
SET_VEHICLE_MODEL_IS_SUPPRESSED(BALLER, TRUE) //enemy car
//suppress ped models used in mission
SET_PED_MODEL_IS_SUPPRESSED(G_M_Y_POLOGOON_01, TRUE)
//block car generator for player ped vehicle, it will be created in mission script
DISABLE_VEHICLE_GEN_ON_MISSION(TRUE)
DELETE_VEHICLE_GEN_VEHICLE(VEHGEN_MICHAEL_SAVEHOUSE)
//setup relationship groups
ADD_RELATIONSHIP_GROUP("ENEMIES", rgEnemies)
ADD_RELATIONSHIP_GROUP("TENNISCOACH", rgTennisCoach)
SET_RELATIONSHIP_BETWEEN_GROUPS(ACQUAINTANCE_TYPE_PED_HATE, RELGROUPHASH_PLAYER, rgEnemies)
SET_RELATIONSHIP_BETWEEN_GROUPS(ACQUAINTANCE_TYPE_PED_HATE, rgEnemies, RELGROUPHASH_PLAYER)
SET_RELATIONSHIP_BETWEEN_GROUPS(ACQUAINTANCE_TYPE_PED_LIKE, RELGROUPHASH_PLAYER, RELGROUPHASH_PLAYER)
SET_RELATIONSHIP_BETWEEN_GROUPS(ACQUAINTANCE_TYPE_PED_LIKE, rgEnemies, rgEnemies)
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
SET_PED_CONFIG_FLAG(PLAYER_PED_ID(), PCF_WillFlyThroughWindscreen, FALSE)
ENDIF
iCustomSwitchSoundID = GET_SOUND_ID()
SET_PLAYER_PED_DATA_IN_CUTSCENES(FALSE, TRUE)
SET_PLAYER_PED_CAN_ENTER_SAVEHOUSE(CHAR_FRANKLIN, SAVEHOUSE_MICHAEL_BH, TRUE)
#IF IS_DEBUG_BUILD
SET_DEBUG_LINES_AND_SPHERES_DRAWING_ACTIVE(FALSE)
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Finished initial mission loading.")
#ENDIF
iSetupProgress++
ENDIF
//run this each time new mission stage needs to be loaded
IF ( iSetupProgress = 1 )
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Started mission stage loading for ", GET_MISSION_STAGE_NAME_FOR_DEBUG(eStage), ".")
#ENDIF
bStageLoaded = FALSE
//initialise arrays for peds, vehicles and objects
INITIALISE_ARRAYS_FOR_MISSION_STAGE(eStage)
//cleanup the asset arrays so that they are ready to be populated with assets needed for the stage being loaded
CLEANUP_MODEL_ARRAY(MissionModels, iModelsRequested)
CLEANUP_ANIMATION_ARRAY(MissionAnimations, iAnimationsRequested)
CLEANUP_CARREC_ARRAY(sVehicleRecordingsFile, MissionRecordings, iRecordingsRequested)
//clear triggered text labels
CLEAR_TRIGGERED_LABELS()
iSetupProgress++
ENDIF
//handle player positioning when current stage is being skipped to or played normally
//fade in the screen if it was faded out due to skipping
IF ( iSetupProgress = 2 )
//stage was skipped to or is being replayed
IF ( bStageSkippedTo = TRUE OR bStageReplayed = TRUE )
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Warping player ped to new position for mission stage being loaded due to skipping or replay.")
#ENDIF
SWITCH GET_CURRENT_PLAYER_PED_ENUM()
CASE CHAR_MICHAEL
WARP_PED(PLAYER_PED_ID(), psMichael.vPosition, psMichael.fHeading, FALSE, TRUE, FALSE)
BREAK
CASE CHAR_FRANKLIN
WARP_PED(PLAYER_PED_ID(), psFranklin.vPosition, psFranklin.fHeading, FALSE, TRUE, FALSE)
BREAK
ENDSWITCH
IF ( eStage = MISSION_STAGE_CUTSCENE_INTRO )
WHILE NOT IS_INTERIOR_READY(GET_INTERIOR_AT_COORDS(vInteriorPosition))
PIN_INTERIOR_IN_MEMORY(GET_INTERIOR_AT_COORDS(vInteriorPosition))
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Pinning interior at coordinates ", vInteriorPosition, " in memory.")
#ENDIF
WAIT(0)
ENDWHILE
ENDIF
IF NOT IS_ENTITY_DEAD(PLAYER_PED_ID())
CLEAR_PED_WETNESS(PLAYER_PED_ID())
CLEAR_PED_DECORATIONS(PLAYER_PED_ID())
CLEAR_PED_BLOOD_DAMAGE(PLAYER_PED_ID())
RESET_PED_VISIBLE_DAMAGE(PLAYER_PED_ID())
RESTORE_PLAYER_PED_TATTOOS(PLAYER_PED_ID())
SET_PED_STEALTH_MOVEMENT(PLAYER_PED_ID(), FALSE)
SET_PED_USING_ACTION_MODE(PLAYER_PED_ID(), FALSE)
CLEAR_AREA(GET_ENTITY_COORDS(PLAYER_PED_ID()), 1000.0, TRUE)
REMOVE_DECALS_IN_RANGE(GET_ENTITY_COORDS(PLAYER_PED_ID()), 1000.0)
REMOVE_PARTICLE_FX_IN_RANGE(GET_ENTITY_COORDS(PLAYER_PED_ID()), 1000.0)
SET_CURRENT_PED_WEAPON(PLAYER_PED_ID(), WEAPONTYPE_UNARMED, TRUE)
SET_ENTITY_HEALTH(PLAYER_PED_ID(), GET_PED_MAX_HEALTH(PLAYER_PED_ID()))
ENDIF
IF IS_PLAYER_PLAYING(PLAYER_ID())
SET_PLAYER_CONTROL(PLAYER_ID(), FALSE)
SET_PLAYER_WANTED_LEVEL(PLAYER_ID(), 0)
SET_PLAYER_WANTED_LEVEL_NOW(PLAYER_ID())
ENDIF
//flags to reset on skips and retry
bVehicleReversed = FALSE
ENDIF
IF ( bStageReplayed = TRUE )
IF ( GET_CURRENT_PLAYER_PED_ENUM() = CHAR_MICHAEL )
START_REPLAY_SETUP(psMichael.vPosition, psMichael.fHeading)
ELIF ( GET_CURRENT_PLAYER_PED_ENUM() = CHAR_FRANKLIN )
START_REPLAY_SETUP(psFranklin.vPosition, psFranklin.fHeading)
ENDIF
ENDIF
//request assets needed for current stage
BUILD_REQUEST_BANK_FOR_MISSION_STAGE(eStage)
iSetupProgress++
ENDIF
//handle loading of mission models that have been requested in the previous stage in BUILD_REQUEST_BANK_FOR_MISSION_STAGE()
//handle loading of mission animations that been requested in the previous stage in BUILD_REQUEST_BANK_FOR_MISSION_STAGE()
IF ( iSetupProgress = 3 )
IF ARE_REQUESTED_MODELS_LOADED(MissionModels, iModelsRequested)
IF ARE_REQUESTED_ANIMATIONS_LOADED(MissionAnimations, iAnimationsRequested)
IF ARE_REQUESTED_CARRECS_LOADED(sVehicleRecordingsFile, MissionRecordings, iRecordingsRequested)
iSetupProgress++
ENDIF
ENDIF
ENDIF
ENDIF
//handle the state of rayfire objects for the stilt house on replays and skips
IF ( iSetupProgress = 4 )
//stage was skipped to or is being replayed
IF ( bStageSkippedTo = TRUE )
OR ( bStageReplayed = TRUE )
RAYFIRE_INDEX riTest = GET_RAYFIRE_MAP_OBJECT(<<-1020.50, 663.41, 154.75>>, 50, "DES_StiltHouse")
IF NOT DOES_RAYFIRE_MAP_OBJECT_EXIST(riTest) //rayfire map object does not exist
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Rayfire map object DES_StiltHouse does not exist.")
#ENDIF
SWITCH eStage
CASE MISSION_STAGE_CUTSCENE_INTRO
CASE MISSION_STAGE_CAR_CHASE
CASE MISSION_STAGE_CUTSCENE_BACK_OF_HOUSE
CASE MISSION_STAGE_PULL_HOUSE_DOWN
SET_BUILDING_STATE(BUILDINGNAME_RF_STILT_HOUSE, BUILDINGSTATE_NORMAL)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Setting BUILDINGNAME_RF_STILT_HOUSE to BUILDINGSTATE_NORMAL.")
#ENDIF
BREAK
CASE MISSION_STAGE_ESCAPE_GOONS
CASE MISSION_STAGE_CUTSCENE_END
CASE MISSION_STAGE_LEADOUT
SET_BUILDING_STATE(BUILDINGNAME_RF_STILT_HOUSE, BUILDINGSTATE_DESTROYED)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Setting BUILDINGNAME_RF_STILT_HOUSE to BUILDINGSTATE_DESTROYED.")
#ENDIF
BREAK
ENDSWITCH
iSetupProgress++
ELSE //rayfire map object exists
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Rayfire map object DES_StiltHouse exists.")
#ENDIF
SWITCH eStage
CASE MISSION_STAGE_CUTSCENE_BACK_OF_HOUSE
CASE MISSION_STAGE_PULL_HOUSE_DOWN
IF ( GET_STATE_OF_RAYFIRE_MAP_OBJECT(riTest) <> RFMO_STATE_START ) //rayfire not in start state
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Waiting for rayfire map object state to be RFMO_STATE_START.")
#ENDIF
IF ( GET_STATE_OF_RAYFIRE_MAP_OBJECT(riTest) <> RFMO_STATE_STARTING ) //rayfire not in starting state
AND ( GET_STATE_OF_RAYFIRE_MAP_OBJECT(riTest) <> RFMO_STATE_SYNC_STARTING ) //and not in sync_starting state
SET_STATE_OF_RAYFIRE_MAP_OBJECT(riTest, RFMO_STATE_STARTING) //set it to starting state then
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Setting rayfire map object DES_StiltHouse to state to RFMO_STATE_STARTING.")
#ENDIF
ENDIF
ELIF ( GET_STATE_OF_RAYFIRE_MAP_OBJECT(riTest) = RFMO_STATE_START )
iSetupProgress++
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Rayfire map object DES_StiltHouse is in state to RFMO_STATE_START.")
#ENDIF
ENDIF
BREAK
CASE MISSION_STAGE_ESCAPE_GOONS
IF ( GET_STATE_OF_RAYFIRE_MAP_OBJECT(riTest) <> RFMO_STATE_END ) //rayfire not in end state
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Waiting for rayfire map object state to be RFMO_STATE_END.")
#ENDIF
IF ( GET_STATE_OF_RAYFIRE_MAP_OBJECT(riTest) <> RFMO_STATE_ENDING ) //rayfire not in ending state
AND ( GET_STATE_OF_RAYFIRE_MAP_OBJECT(riTest) <> RFMO_STATE_SYNC_ENDING ) //and not in sync_ending state
SET_STATE_OF_RAYFIRE_MAP_OBJECT(riTest, RFMO_STATE_ENDING) //set it to ending then
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Rayfire map object state set to RFMO_STATE_ENDING.")
#ENDIF
ENDIF
ELIF ( GET_STATE_OF_RAYFIRE_MAP_OBJECT(riTest) = RFMO_STATE_END )
iSetupProgress++
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Rayfire map object DES_StiltHouse is in state to RFMO_STATE_END.")
#ENDIF
ENDIF
BREAK
ENDSWITCH
ENDIF
ELSE //stage not being skipped to or replayed
iSetupProgress++
ENDIF
ENDIF
//handle creating vehicles/peds and setting up fail flags
//run this each time new mission stage needs to be loaded
//THIS SETUP SECTION ASSUMES THAT ALL REQUIRED ASSETS HAVE BEEN ALREADY LOADED TO MEMORY IN PREVIOUS SETUP SECTIONS
IF ( iSetupProgress = 5 )
SET_FAIL_FLAGS(FALSE)
SWITCH eStage
CASE MISSION_STAGE_CUTSCENE_INTRO
IF IS_REPEAT_PLAY_ACTIVE() //create mission vehicles on mission repeat play only
IF HAS_MISSION_VEHICLE_BEEN_CREATED(vsPlayersCar, FALSE, FALSE, NO_CHARACTER, TRUE, -1, 132, 0)
IF HAS_MISSION_VEHICLE_BEEN_CREATED(vsCoachsCar, FALSE, FALSE, NO_CHARACTER, TRUE, -1, 43, 43)
SET_VEHICLE_AS_RESTRICTED(vsPlayersCar.VehicleIndex, 0)
IF IS_VEHICLE_DRIVEABLE(vsPlayersCar.VehicleIndex)
IF NOT IS_VEHICLE_EXTRA_TURNED_ON(vsPlayersCar.VehicleIndex, 5)
SET_VEHICLE_EXTRA(vsPlayersCar.VehicleIndex, 5, FALSE)
ENDIF
SET_VEHICLE_STRONG(vsPlayersCar.VehicleIndex, TRUE)
SET_VEHICLE_CAN_SAVE_IN_GARAGE(vsPlayersCar.VehicleIndex, FALSE)
ENDIF
iSetupProgress++
ENDIF
ENDIF
ELSE //move on if not repeat play
iSetupProgress++
ENDIF
BREAK
CASE MISSION_STAGE_CAR_CHASE
FailFlags[MISSION_FAIL_CAR_STUCK] = TRUE
FailFlags[MISSION_FAIL_CAR_DESTROYED] = TRUE
FailFlags[MISSION_FAIL_COACH_DEAD] = TRUE
FailFlags[MISSION_FAIL_COACH_ATTACKED] = TRUE
FailFlags[MISSION_FAIL_FRANKLIN_DEAD] = TRUE
FailFlags[MISSION_FAIL_FRANKLIN_LEFT_BEHIND] = TRUE
IF HAS_MISSION_OBJECT_BEEN_CREATED(osRacket01, TRUE)
AND HAS_MISSION_OBJECT_BEEN_CREATED(osRacket02, TRUE)
IF NOT DOES_ENTITY_EXIST(osBrokenPlantPot.ObjectIndex)
IF GET_PLAYER_CHARACTER_AT_MISSION_START() = CHAR_MICHAEL
IF HAS_MISSION_OBJECT_BEEN_CREATED(osBrokenPlantPot, TRUE)
ENDIF
ENDIF
ENDIF
//fix for B*1897723 - set the bedroom door rayfire to start state to hide double door issue
riFrenchDoorRayfire = GET_RAYFIRE_MAP_OBJECT(<< -817.1669, 178.0146, 75.7095>>, 3.0, "des_frenchdoor")
IF DOES_RAYFIRE_MAP_OBJECT_EXIST(riFrenchDoorRayfire)
SET_STATE_OF_RAYFIRE_MAP_OBJECT(riFrenchDoorRayfire, RFMO_STATE_STARTING)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Setting rayfire map object des_frenchdoor to start state.")
#ENDIF
ENDIF
IF HAS_MISSION_VEHICLE_BEEN_CREATED(vsPlayersCar, FALSE, FALSE, NO_CHARACTER, TRUE, -1, 132, 0)
SET_VEHICLE_AS_RESTRICTED(vsPlayersCar.VehicleIndex, 0)
IF IS_VEHICLE_DRIVEABLE(vsPlayersCar.VehicleIndex)
IF NOT IS_VEHICLE_EXTRA_TURNED_ON(vsPlayersCar.VehicleIndex, 5)
SET_VEHICLE_EXTRA(vsPlayersCar.VehicleIndex, 5, FALSE)
ENDIF
SET_VEHICLE_STRONG(vsPlayersCar.VehicleIndex, TRUE)
SET_VEHICLE_CAN_SAVE_IN_GARAGE(vsPlayersCar.VehicleIndex, FALSE)
ENDIF
IF HAS_MISSION_VEHICLE_BEEN_CREATED(vsCoachsCar, FALSE, FALSE, NO_CHARACTER, TRUE, -1, 43, 43)
IF HAS_MISSION_PED_BEEN_CREATED(psCoach, FALSE, rgTennisCoach, FALSE, NO_CHARACTER, FALSE, FALSE, FALSE, vsCoachsCar.VehicleIndex)
IF NOT IS_PED_INJURED(psCoach.PedIndex)
SET_PED_COMPONENT_VARIATION(psCoach.PedIndex, PED_COMP_TORSO, 1, 0)
SET_PED_COMPONENT_VARIATION(psCoach.PedIndex, PED_COMP_LEG, 1, 0)
ENDIF
OBJECT_INDEX FlowerObjectIndex
FlowerObjectIndex = GET_CLOSEST_OBJECT_OF_TYPE(<< -818.88, 177.91, 76.63 >>, 0.75, PROP_WINDOWBOX_B, FALSE)
IF DOES_ENTITY_EXIST(FlowerObjectIndex)
IF NOT IS_ENTITY_DEAD(FlowerObjectIndex)
SET_ENTITY_VISIBLE(FlowerObjectIndex, FALSE)
SET_ENTITY_COLLISION(FlowerObjectIndex, FALSE)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Hiding world prop object PROP_WINDOWBOX_B.")
#ENDIF
ENDIF
ENDIF
INFORM_MISSION_STATS_OF_SPEED_WATCH_ENTITY(vsPlayersCar.VehicleIndex)
INFORM_MISSION_STATS_OF_DAMAGE_WATCH_ENTITY(vsPlayersCar.VehicleIndex) //track damage during car chase
SWITCH GET_CURRENT_PLAYER_PED_ENUM()
CASE CHAR_MICHAEL
IF HAS_MISSION_PED_BEEN_CREATED(psFranklin, TRUE, RELGROUPHASH_PLAYER, FALSE, CHAR_FRANKLIN)
IF NOT IS_PED_INJURED(psFranklin.PedIndex) AND HAVE_ALL_STREAMING_REQUESTS_COMPLETED(psFranklin.PedIndex)
sSelectorPeds.pedID[SELECTOR_PED_FRANKLIN] = psFranklin.PedIndex
iSetupProgress++
ENDIF
ENDIF
BREAK
CASE CHAR_FRANKLIN
IF HAS_MISSION_PED_BEEN_CREATED(psMichael, TRUE, RELGROUPHASH_PLAYER, FALSE, CHAR_MICHAEL)
IF NOT IS_PED_INJURED(psMichael.PedIndex) AND HAVE_ALL_STREAMING_REQUESTS_COMPLETED(psMichael.PedIndex)
sSelectorPeds.pedID[SELECTOR_PED_MICHAEL] = psMichael.PedIndex
iSetupProgress++
ENDIF
ENDIF
BREAK
ENDSWITCH
ENDIF
ENDIF
ENDIF
ENDIF
BREAK
CASE MISSION_STAGE_CUTSCENE_BACK_OF_HOUSE
FailFlags[MISSION_FAIL_CAR_STUCK] = TRUE
FailFlags[MISSION_FAIL_CAR_DESTROYED] = TRUE
FailFlags[MISSION_FAIL_COACH_DEAD] = TRUE
FailFlags[MISSION_FAIL_COACH_SPOOKED] = TRUE
FailFlags[MISSION_FAIL_COACH_ATTACKED] = TRUE
FailFlags[MISSION_FAIL_FRANKLIN_DEAD] = TRUE
FailFlags[MISSION_FAIL_FRANKLIN_LEFT_BEHIND] = TRUE
IF HAS_MISSION_VEHICLE_BEEN_CREATED(vsPlayersCar, FALSE, FALSE, NO_CHARACTER, TRUE, -1, 132, 0)
SET_VEHICLE_AS_RESTRICTED(vsPlayersCar.VehicleIndex, 0)
IF IS_VEHICLE_DRIVEABLE(vsPlayersCar.VehicleIndex)
IF NOT IS_VEHICLE_EXTRA_TURNED_ON(vsPlayersCar.VehicleIndex, 5)
SET_VEHICLE_EXTRA(vsPlayersCar.VehicleIndex, 5, FALSE)
ENDIF
SET_VEHICLE_STRONG(vsPlayersCar.VehicleIndex, TRUE)
SET_VEHICLE_CAN_SAVE_IN_GARAGE(vsPlayersCar.VehicleIndex, FALSE)
ENDIF
IF HAS_MISSION_PED_BEEN_CREATED(psCoach, FALSE, rgTennisCoach, FALSE, CHAR_TENNIS_COACH)
IF HAS_MISSION_OBJECT_BEEN_CREATED(osRopeAnchor, TRUE)
IF DOES_ENTITY_EXIST(osRopeAnchor.ObjectIndex)
IF NOT IS_ENTITY_DEAD(osRopeAnchor.ObjectIndex)
SET_ENTITY_VISIBLE(osRopeAnchor.ObjectIndex, FALSE)
ENDIF
ENDIF
INFORM_MISSION_STATS_OF_SPEED_WATCH_ENTITY(vsPlayersCar.VehicleIndex)
INFORM_MISSION_STATS_OF_DAMAGE_WATCH_ENTITY(NULL) //stop tracking damage
IF NOT IS_PED_INJURED(psCoach.PedIndex)
SET_PED_COMPONENT_VARIATION(psCoach.PedIndex, PED_COMP_TORSO, 1, 0)
SET_PED_COMPONENT_VARIATION(psCoach.PedIndex, PED_COMP_LEG, 1, 0)
ENDIF
SWITCH GET_CURRENT_PLAYER_PED_ENUM()
CASE CHAR_MICHAEL
IF HAS_MISSION_PED_BEEN_CREATED(psFranklin, TRUE, RELGROUPHASH_PLAYER, FALSE, CHAR_FRANKLIN, FALSE, FALSE, FALSE, vsPlayersCar.VehicleIndex, VS_FRONT_RIGHT)
IF NOT IS_PED_INJURED(psFranklin.PedIndex) AND HAVE_ALL_STREAMING_REQUESTS_COMPLETED(psFranklin.PedIndex)
sSelectorPeds.pedID[SELECTOR_PED_FRANKLIN] = psFranklin.PedIndex
iSetupProgress++
ENDIF
ENDIF
BREAK
CASE CHAR_FRANKLIN
IF HAS_MISSION_PED_BEEN_CREATED(psMichael, TRUE, RELGROUPHASH_PLAYER, FALSE, CHAR_MICHAEL, FALSE, FALSE, FALSE, vsPlayersCar.VehicleIndex, VS_DRIVER)
IF NOT IS_PED_INJURED(psMichael.PedIndex) AND HAVE_ALL_STREAMING_REQUESTS_COMPLETED(psMichael.PedIndex)
sSelectorPeds.pedID[SELECTOR_PED_MICHAEL] = psMichael.PedIndex
IF NOT IS_PED_IN_VEHICLE(PLAYER_PED_ID(), vsPlayersCar.VehicleIndex)
SET_PED_INTO_VEHICLE(PLAYER_PED_ID(), vsPlayersCar.VehicleIndex, VS_FRONT_RIGHT)
ENDIF
iSetupProgress++
ENDIF
ENDIF
BREAK
ENDSWITCH
ENDIF
ENDIF
ENDIF
BREAK
CASE MISSION_STAGE_PULL_HOUSE_DOWN
FailFlags[MISSION_FAIL_CAR_STUCK] = FALSE //don't fail for truck getting stuck when pulling
FailFlags[MISSION_FAIL_CAR_DESTROYED] = TRUE
FailFlags[MISSION_FAIL_COACH_DEAD] = TRUE
FailFlags[MISSION_FAIL_COACH_SPOOKED] = TRUE
FailFlags[MISSION_FAIL_COACH_ATTACKED] = TRUE
FailFlags[MISSION_FAIL_FRANKLIN_DEAD] = TRUE
FailFlags[MISSION_FAIL_FRANKLIN_LEFT_BEHIND] = TRUE
IF HAS_MISSION_VEHICLE_BEEN_CREATED(vsPlayersCar, FALSE, FALSE, NO_CHARACTER, TRUE, -1, 132, 0)
SET_VEHICLE_AS_RESTRICTED(vsPlayersCar.VehicleIndex, 0)
IF IS_VEHICLE_DRIVEABLE(vsPlayersCar.VehicleIndex)
IF NOT IS_VEHICLE_EXTRA_TURNED_ON(vsPlayersCar.VehicleIndex, 5)
SET_VEHICLE_EXTRA(vsPlayersCar.VehicleIndex, 5, FALSE)
ENDIF
SET_VEHICLE_STRONG(vsPlayersCar.VehicleIndex, TRUE)
SET_VEHICLE_CAN_SAVE_IN_GARAGE(vsPlayersCar.VehicleIndex, FALSE)
ENDIF
IF HAS_MISSION_PED_BEEN_CREATED(psCoach, FALSE, rgTennisCoach, FALSE, CHAR_TENNIS_COACH)
IF HAS_MISSION_OBJECT_BEEN_CREATED(osRopeAnchor, TRUE)
AND HAS_MISSION_OBJECT_BEEN_CREATED(osRopeDummy, TRUE)
AND HAS_MISSION_OBJECT_BEEN_CREATED(osRopeProp, TRUE)
IF DOES_ENTITY_EXIST(osRopeAnchor.ObjectIndex)
IF NOT IS_ENTITY_DEAD(osRopeAnchor.ObjectIndex)
SET_ENTITY_VISIBLE(osRopeAnchor.ObjectIndex, FALSE)
ENDIF
ENDIF
IF DOES_ENTITY_EXIST(osRopeDummy.ObjectIndex)
IF NOT IS_ENTITY_DEAD(osRopeDummy.ObjectIndex)
SET_ENTITY_NO_COLLISION_ENTITY(osRopeDummy.ObjectIndex, vsPlayersCar.VehicleIndex, FALSE)
SET_CAN_CLIMB_ON_ENTITY(osRopeDummy.ObjectIndex, FALSE)
SET_CAN_AUTO_VAULT_ON_ENTITY(osRopeDummy.ObjectIndex, FALSE)
ENDIF
ENDIF
IF DOES_ENTITY_EXIST(osRopeProp.ObjectIndex)
IF NOT IS_ENTITY_DEAD(osRopeProp.ObjectIndex)
SET_CAN_CLIMB_ON_ENTITY(osRopeProp.ObjectIndex, FALSE)
SET_CAN_AUTO_VAULT_ON_ENTITY(osRopeProp.ObjectIndex, FALSE)
ENDIF
ENDIF
INFORM_MISSION_STATS_OF_SPEED_WATCH_ENTITY(vsPlayersCar.VehicleIndex)
IF NOT IS_PED_INJURED(psCoach.PedIndex)
SET_PED_COMPONENT_VARIATION(psCoach.PedIndex, PED_COMP_TORSO, 1, 0)
SET_PED_COMPONENT_VARIATION(psCoach.PedIndex, PED_COMP_LEG, 1, 0)
ENDIF
SWITCH GET_CURRENT_PLAYER_PED_ENUM()
CASE CHAR_MICHAEL
IF HAS_MISSION_PED_BEEN_CREATED(psFranklin, TRUE, RELGROUPHASH_PLAYER, FALSE, CHAR_FRANKLIN, FALSE, FALSE, FALSE, vsPlayersCar.VehicleIndex, VS_FRONT_RIGHT)
IF NOT IS_PED_INJURED(psFranklin.PedIndex) AND HAVE_ALL_STREAMING_REQUESTS_COMPLETED(psFranklin.PedIndex)
sSelectorPeds.pedID[SELECTOR_PED_FRANKLIN] = psFranklin.PedIndex
iSetupProgress++
ENDIF
ENDIF
BREAK
CASE CHAR_FRANKLIN
IF HAS_MISSION_PED_BEEN_CREATED(psMichael, TRUE, RELGROUPHASH_PLAYER, FALSE, CHAR_MICHAEL)
IF NOT IS_PED_INJURED(psMichael.PedIndex) AND HAVE_ALL_STREAMING_REQUESTS_COMPLETED(psMichael.PedIndex)
sSelectorPeds.pedID[SELECTOR_PED_MICHAEL] = psMichael.PedIndex
IF NOT IS_PED_IN_VEHICLE(PLAYER_PED_ID(), vsPlayersCar.VehicleIndex)
SET_PED_INTO_VEHICLE(PLAYER_PED_ID(), vsPlayersCar.VehicleIndex, VS_FRONT_RIGHT)
ENDIF
iSetupProgress++
ENDIF
ENDIF
BREAK
ENDSWITCH
ENDIF
ENDIF
ENDIF
BREAK
CASE MISSION_STAGE_ESCAPE_GOONS
FailFlags[MISSION_FAIL_MICHAEL_DEAD] = TRUE
FailFlags[MISSION_FAIL_FRANKLIN_DEAD] = TRUE
FailFlags[MISSION_FAIL_MICHAEL_LEFT_BEHIND] = TRUE
FailFlags[MISSION_FAIL_FRANKLIN_LEFT_BEHIND] = TRUE
IF HAS_MISSION_VEHICLE_BEEN_CREATED(vsPlayersCar, FALSE, FALSE, NO_CHARACTER, TRUE, -1, 132, 0)
SET_VEHICLE_AS_RESTRICTED(vsPlayersCar.VehicleIndex, 0)
IF IS_VEHICLE_DRIVEABLE(vsPlayersCar.VehicleIndex)
REQUEST_VEHICLE_HIGH_DETAIL_MODEL(vsPlayersCar.VehicleIndex)
IF NOT IS_VEHICLE_EXTRA_TURNED_ON(vsPlayersCar.VehicleIndex, 5)
SET_VEHICLE_EXTRA(vsPlayersCar.VehicleIndex, 5, FALSE)
ENDIF
SET_VEHICLE_STRONG(vsPlayersCar.VehicleIndex, FALSE)
SET_VEHICLE_CAN_SAVE_IN_GARAGE(vsPlayersCar.VehicleIndex, FALSE)
ENDIF
//IF NOT DOES_PARTICLE_FX_LOOPED_EXIST(ptfxDustCloud) //make sure dust particles are created
REQUEST_PTFX_ASSET()
// IF HAS_PTFX_ASSET_LOADED()
// #IF IS_DEBUG_BUILD
// PRINTLN(GET_THIS_SCRIPT_NAME(), ": Starting particle fx ent_ray_fam3_dust_settle.")
// #ENDIF
// ptfxDustCloud = START_PARTICLE_FX_LOOPED_AT_COORD("ent_ray_fam3_dust_settle", << -1016.0, 642.0, 141.0 >>, << 0.0, 0.0, 0.0 >>)
// ENDIF
//ELSE
//reset kill counters
iPlayerMichaelKills = 0
iPlayerFranklinKills = 0
iBuddyMichaelKills = 0
iBuddyFranklinKills = 0
bVehicleReversed = FALSE
INFORM_MISSION_STATS_OF_SPEED_WATCH_ENTITY(vsPlayersCar.VehicleIndex)
SWITCH GET_CURRENT_PLAYER_PED_ENUM()
CASE CHAR_MICHAEL
IF HAS_MISSION_PED_BEEN_CREATED(psFranklin, TRUE, RELGROUPHASH_PLAYER, FALSE, CHAR_FRANKLIN, FALSE, FALSE, FALSE, vsPlayersCar.VehicleIndex, VS_FRONT_RIGHT)
IF NOT IS_PED_INJURED(psFranklin.PedIndex) AND HAVE_ALL_STREAMING_REQUESTS_COMPLETED(psFranklin.PedIndex)
sSelectorPeds.pedID[SELECTOR_PED_FRANKLIN] = psFranklin.PedIndex
iSetupProgress++
ENDIF
ENDIF
BREAK
CASE CHAR_FRANKLIN
IF HAS_MISSION_PED_BEEN_CREATED(psMichael, TRUE, RELGROUPHASH_PLAYER, FALSE, CHAR_MICHAEL, FALSE, FALSE, FALSE, vsPlayersCar.VehicleIndex, VS_DRIVER)
IF NOT IS_PED_INJURED(psMichael.PedIndex) AND HAVE_ALL_STREAMING_REQUESTS_COMPLETED(psMichael.PedIndex)
sSelectorPeds.pedID[SELECTOR_PED_MICHAEL] = psMichael.PedIndex
IF NOT IS_PED_IN_VEHICLE(PLAYER_PED_ID(), vsPlayersCar.VehicleIndex)
SET_PED_INTO_VEHICLE(PLAYER_PED_ID(), vsPlayersCar.VehicleIndex, VS_FRONT_RIGHT)
ENDIF
iSetupProgress++
ENDIF
ENDIF
BREAK
ENDSWITCH
//ENDIF
ENDIF
BREAK
CASE MISSION_STAGE_CUTSCENE_END
IF HAS_MISSION_VEHICLE_BEEN_CREATED(vsPlayersCar, FALSE, FALSE, NO_CHARACTER, TRUE, -1, 132, 0)
AND HAS_MISSION_VEHICLE_BEEN_CREATED(vsCutsceneCar, FALSE, FALSE, NO_CHARACTER, TRUE, -1, 0, 0, 3, 0 #IF IS_DEBUG_BUILD, "MadrazosCar" #ENDIF)
IF IS_VEHICLE_DRIVEABLE(vsCutsceneCar.VehicleIndex)
SET_ENTITY_INVINCIBLE(vsCutsceneCar.VehicleIndex, TRUE)
ENDIF
SET_VEHICLE_AS_RESTRICTED(vsPlayersCar.VehicleIndex, 0)
INFORM_MISSION_STATS_OF_SPEED_WATCH_ENTITY(vsPlayersCar.VehicleIndex)
IF IS_VEHICLE_DRIVEABLE(vsPlayersCar.VehicleIndex)
IF NOT IS_VEHICLE_EXTRA_TURNED_ON(vsPlayersCar.VehicleIndex, 5)
SET_VEHICLE_EXTRA(vsPlayersCar.VehicleIndex, 5, FALSE)
ENDIF
SET_VEHICLE_STRONG(vsPlayersCar.VehicleIndex, FALSE)
SET_VEHICLE_CAN_SAVE_IN_GARAGE(vsPlayersCar.VehicleIndex, FALSE)
ENDIF
SWITCH GET_CURRENT_PLAYER_PED_ENUM()
CASE CHAR_MICHAEL
IF HAS_MISSION_PED_BEEN_CREATED(psFranklin, TRUE, RELGROUPHASH_PLAYER, FALSE, CHAR_FRANKLIN, FALSE, FALSE, FALSE, vsPlayersCar.VehicleIndex, VS_FRONT_RIGHT)
IF NOT IS_PED_INJURED(psFranklin.PedIndex) AND HAVE_ALL_STREAMING_REQUESTS_COMPLETED(psFranklin.PedIndex)
sSelectorPeds.pedID[SELECTOR_PED_FRANKLIN] = psFranklin.PedIndex
iSetupProgress++
ENDIF
ENDIF
BREAK
CASE CHAR_FRANKLIN
IF HAS_MISSION_PED_BEEN_CREATED(psMichael, TRUE, RELGROUPHASH_PLAYER, FALSE, CHAR_MICHAEL, FALSE, FALSE, FALSE, vsPlayersCar.VehicleIndex, VS_DRIVER)
IF NOT IS_PED_INJURED(psMichael.PedIndex) AND HAVE_ALL_STREAMING_REQUESTS_COMPLETED(psMichael.PedIndex)
sSelectorPeds.pedID[SELECTOR_PED_MICHAEL] = psMichael.PedIndex
iSetupProgress++
ENDIF
ENDIF
BREAK
ENDSWITCH
ENDIF
BREAK
CASE MISSION_STAGE_LEADOUT
IF NOT DOES_ENTITY_EXIST(vsMichaelsEndCar.VehicleIndex)
IF IS_VEHICLE_GEN_AVAILABLE(VEHGEN_MISSION_VEH)
AND DOES_ENTITY_EXIST(GET_VEHICLE_GEN_VEHICLE_INDEX(VEHGEN_MISSION_VEH))
AND IS_VEHICLE_DRIVEABLE(GET_VEHICLE_GEN_VEHICLE_INDEX(VEHGEN_MISSION_VEH))
AND GET_PLAYER_CHARACTER_AT_MISSION_START() = CHAR_MICHAEL
VEHICLE_INDEX VehGenVehicleIndex
VehGenVehicleIndex = GET_VEHICLE_GEN_VEHICLE_INDEX(VEHGEN_MISSION_VEH)
IF DOES_ENTITY_EXIST(VehGenVehicleIndex)
IF NOT IS_ENTITY_DEAD(VehGenVehicleIndex)
IF NOT IS_ENTITY_A_MISSION_ENTITY(VehGenVehicleIndex)
OR NOT DOES_ENTITY_BELONG_TO_THIS_SCRIPT(VehGenVehicleIndex)
SET_ENTITY_AS_MISSION_ENTITY(VehGenVehicleIndex, TRUE, TRUE)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Setting Michael's mission start vehicle as mission entity.")
#ENDIF
ENDIF
vsMichaelsEndCar.VehicleIndex = VehGenVehicleIndex
SET_ENTITY_COORDS(vsMichaelsEndCar.VehicleIndex, vsMichaelsEndCar.vPosition)
SET_ENTITY_HEADING(vsMichaelsEndCar.VehicleIndex, vsMichaelsEndCar.fHeading)
SET_VEHICLE_ON_GROUND_PROPERLY(vsMichaelsEndCar.VehicleIndex)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Moving Michael's mission start vehicle gen to position ",vsMichaelsEndCar.vPosition, " and heading ", vsMichaelsEndCar.fHeading, " and making a mission entity.")
#ENDIF
ENDIF
ENDIF
ELSE
DELETE_ALL_SCRIPT_CREATED_PLAYER_VEHICLES(CHAR_MICHAEL)
IF HAS_MISSION_VEHICLE_BEEN_CREATED(vsMichaelsEndCar, TRUE, FALSE, CHAR_MICHAEL, TRUE)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Creating default Michael's car due to mission vehicle gen for Michael not being available or dead.")
#ENDIF
ENDIF
ENDIF
ELSE
SWITCH GET_CURRENT_PLAYER_PED_ENUM()
CASE CHAR_MICHAEL
iSetupProgress++
BREAK
CASE CHAR_FRANKLIN
IF HAS_MISSION_PED_BEEN_CREATED(psMichael, TRUE, RELGROUPHASH_PLAYER, FALSE, CHAR_MICHAEL, FALSE, FALSE, FALSE, vsPlayersCar.VehicleIndex, VS_DRIVER)
IF NOT IS_PED_INJURED(psMichael.PedIndex) AND HAVE_ALL_STREAMING_REQUESTS_COMPLETED(psMichael.PedIndex)
sSelectorPeds.pedID[SELECTOR_PED_MICHAEL] = psMichael.PedIndex
iSetupProgress++
ENDIF
ENDIF
BREAK
ENDSWITCH
ENDIF
BREAK
//debug stages
#IF IS_DEBUG_BUILD
CASE MISSION_STAGE_DEBUG_RECORD_CHASE
CASE MISSION_STAGE_DEBUG_PLAYBACK_CHASE
IF HAS_MISSION_VEHICLE_BEEN_CREATED(vsCoachsCar, FALSE, FALSE, NO_CHARACTER, TRUE, -1, 43, 43)
iSetupProgress++
ENDIF
BREAK
#ENDIF
DEFAULT
iSetupProgress++
BREAK
ENDSWITCH
ENDIF
IF ( iSetupProgress = 6 )
IF ( bStageSkippedTo = TRUE OR bStageReplayed = TRUE ) //handle switching on skips and replay
SWITCH eStage
CASE MISSION_STAGE_CUTSCENE_INTRO
//don't force switch here
BREAK
CASE MISSION_STAGE_CAR_CHASE
CASE MISSION_STAGE_CUTSCENE_BACK_OF_HOUSE
CASE MISSION_STAGE_PULL_HOUSE_DOWN
CASE MISSION_STAGE_ESCAPE_GOONS
CASE MISSION_STAGE_LEADOUT
IF MAKE_SELECTOR_PED_SELECTION(sSelectorPeds, SELECTOR_PED_MICHAEL)
TAKE_CONTROL_OF_SELECTOR_PED(sSelectorPeds)
psFranklin.PedIndex = sSelectorPeds.pedID[SELECTOR_PED_FRANKLIN]
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Performing script controlled hotswap to Michael for mission stage being loaded.")
#ENDIF
ENDIF
BREAK
CASE MISSION_STAGE_CUTSCENE_END
//don't force switch here
BREAK
ENDSWITCH
ENDIF
LOCK_AUTOMATIC_DOOR_OPEN(AUTODOOR_MICHAEL_MANSION_GATE, FALSE)
SWITCH eStage //handle garage and gate door
CASE MISSION_STAGE_CUTSCENE_INTRO
CASE MISSION_STAGE_ESCAPE_GOONS
CASE MISSION_STAGE_CUTSCENE_END
IF IS_DOOR_REGISTERED_WITH_SYSTEM(ENUM_TO_INT(DOORHASH_M_MANSION_G1))
DOOR_SYSTEM_SET_OPEN_RATIO(ENUM_TO_INT(DOORHASH_M_MANSION_G1), 0.0, FALSE, FALSE)
DOOR_SYSTEM_SET_DOOR_STATE(ENUM_TO_INT(DOORHASH_M_MANSION_G1), DOORSTATE_LOCKED, FALSE, TRUE)
ENDIF
BREAK
CASE MISSION_STAGE_CAR_CHASE
LOCK_AUTOMATIC_DOOR_OPEN(AUTODOOR_MICHAEL_MANSION_GATE, TRUE)
IF IS_DOOR_REGISTERED_WITH_SYSTEM(ENUM_TO_INT(DOORHASH_M_MANSION_G1))
DOOR_SYSTEM_SET_OPEN_RATIO(ENUM_TO_INT(DOORHASH_M_MANSION_G1), 0.0, FALSE, FALSE)
DOOR_SYSTEM_SET_DOOR_STATE(ENUM_TO_INT(DOORHASH_M_MANSION_G1), DOORSTATE_UNLOCKED, FALSE, TRUE)
ENDIF
BREAK
DEFAULT
IF IS_DOOR_REGISTERED_WITH_SYSTEM(ENUM_TO_INT(DOORHASH_M_MANSION_G1))
DOOR_SYSTEM_SET_OPEN_RATIO(ENUM_TO_INT(DOORHASH_M_MANSION_G1), 0.0, FALSE, FALSE)
DOOR_SYSTEM_SET_DOOR_STATE(ENUM_TO_INT(DOORHASH_M_MANSION_G1), DOORSTATE_UNLOCKED, FALSE, TRUE)
ENDIF
BREAK
ENDSWITCH
iSetupProgress++
ENDIF
//handle adding mission peds for dialogue, cellphone and taxi hailing depending on mission stage
IF ( iSetupProgress = 7 )
REMOVE_PED_FOR_DIALOGUE(sFamily3Conversation, 0) //Michael
REMOVE_PED_FOR_DIALOGUE(sFamily3Conversation, 1) //Franklin
REMOVE_PED_FOR_DIALOGUE(sFamily3Conversation, 3) //Tennis coach
REMOVE_PED_FOR_DIALOGUE(sFamily3Conversation, 4) //Natalia
REMOVE_PED_FOR_DIALOGUE(sFamily3Conversation, 5) //Van Driver
REMOVE_PED_FOR_DIALOGUE(sFamily3Conversation, 6) //Lester
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
ADD_PED_FOR_DIALOGUE(sFamily3Conversation, 0, PLAYER_PED_ID(), "MICHAEL")
ENDIF
SWITCH eStage
CASE MISSION_STAGE_CAR_CHASE
IF NOT IS_PED_INJURED(psFranklin.PedIndex)
ADD_PED_FOR_DIALOGUE(sFamily3Conversation, 1, psFranklin.PedIndex, "FRANKLIN")
ENDIF
IF NOT IS_PED_INJURED(psCoach.PedIndex)
ADD_PED_FOR_DIALOGUE(sFamily3Conversation, 3, psCoach.PedIndex, "TENNISCOACH")
ENDIF
DISABLE_CELLPHONE(FALSE)
DISABLE_TAXI_HAILING(TRUE)
SUPPRESS_EMERGENCY_CALLS()
BREAK
CASE MISSION_STAGE_CUTSCENE_BACK_OF_HOUSE
CASE MISSION_STAGE_PULL_HOUSE_DOWN
IF NOT IS_PED_INJURED(psFranklin.PedIndex)
ADD_PED_FOR_DIALOGUE(sFamily3Conversation, 1, psFranklin.PedIndex, "FRANKLIN")
ENDIF
IF NOT IS_PED_INJURED(psCoach.PedIndex)
ADD_PED_FOR_DIALOGUE(sFamily3Conversation, 3, psCoach.PedIndex, "TENNISCOACH")
ENDIF
DISABLE_CELLPHONE(TRUE)
DISABLE_TAXI_HAILING(TRUE)
SUPPRESS_EMERGENCY_CALLS()
BREAK
CASE MISSION_STAGE_ESCAPE_GOONS
IF NOT IS_PED_INJURED(psFranklin.PedIndex)
ADD_PED_FOR_DIALOGUE(sFamily3Conversation, 1, psFranklin.PedIndex, "FRANKLIN")
ENDIF
IF DOES_ENTITY_EXIST(psCoach.PedIndex)
IF NOT IS_PED_INJURED(psCoach.PedIndex)
ADD_PED_FOR_DIALOGUE(sFamily3Conversation, 3, psCoach.PedIndex, "TENNISCOACH")
ENDIF
ELSE
ADD_PED_FOR_DIALOGUE(sFamily3Conversation, 3, NULL, "TENNISCOACH")
ENDIF
ADD_PED_FOR_DIALOGUE(sFamily3Conversation, 4, NULL, "NATHALIA")
DISABLE_CELLPHONE(FALSE)
DISABLE_TAXI_HAILING(TRUE)
SUPPRESS_EMERGENCY_CALLS()
BREAK
CASE MISSION_STAGE_CUTSCENE_END
DISABLE_CELLPHONE(FALSE)
DISABLE_TAXI_HAILING(FALSE)
RELEASE_SUPPRESSED_EMERGENCY_CALLS()
BREAK
CASE MISSION_STAGE_LEADOUT
ADD_PED_FOR_DIALOGUE(sFamily3Conversation, 6, NULL, "LESTER")
DISABLE_CELLPHONE(FALSE)
DISABLE_TAXI_HAILING(FALSE)
RELEASE_SUPPRESSED_EMERGENCY_CALLS()
BREAK
ENDSWITCH
iSetupProgress++
ENDIF
//handle ped and vehicle density and budget
IF ( iSetupProgress = 8 )
SET_MAX_WANTED_LEVEL(5)
SET_CREATE_RANDOM_COPS(TRUE)
SET_WANTED_LEVEL_MULTIPLIER(1.0)
ENABLE_DISPATCH_SERVICE(DT_FIRE_DEPARTMENT, TRUE)
ENABLE_DISPATCH_SERVICE(DT_AMBULANCE_DEPARTMENT, TRUE)
SET_ALL_SHOPS_TEMPORARILY_UNAVAILABLE(FALSE)
//CASCADE_SHADOWS_INIT_SESSION()
SET_INSTANCE_PRIORITY_HINT(INSTANCE_HINT_NONE)
REMOVE_NAVMESH_BLOCKING_OBJECTS()
SWITCH eStage
CASE MISSION_STAGE_CUTSCENE_INTRO
//turn ambient peds off
SET_PED_POPULATION_BUDGET(0)
SET_VEHICLE_POPULATION_BUDGET(0)
SET_PLAYER_CAN_CHANGE_CLOTHES_ON_MISSION(TRUE)
BREAK
CASE MISSION_STAGE_CAR_CHASE
//turn ambient peds on
SET_PED_POPULATION_BUDGET(3)
SET_VEHICLE_POPULATION_BUDGET(3)
SET_PLAYER_CAN_CHANGE_CLOTHES_ON_MISSION(TRUE)
SET_ALL_SHOPS_TEMPORARILY_UNAVAILABLE(TRUE)
SET_INSTANCE_PRIORITY_HINT(INSTANCE_HINT_DRIVING)
BREAK
CASE MISSION_STAGE_CUTSCENE_BACK_OF_HOUSE
CASE MISSION_STAGE_PULL_HOUSE_DOWN
//turn ambient peds off
SET_PED_POPULATION_BUDGET(0)
SET_VEHICLE_POPULATION_BUDGET(0)
SET_MAX_WANTED_LEVEL(0)
SET_CREATE_RANDOM_COPS(FALSE)
SET_WANTED_LEVEL_MULTIPLIER(0.0)
ENABLE_DISPATCH_SERVICE(DT_FIRE_DEPARTMENT, FALSE)
ENABLE_DISPATCH_SERVICE(DT_AMBULANCE_DEPARTMENT, FALSE)
SET_PLAYER_CAN_CHANGE_CLOTHES_ON_MISSION(TRUE)
BREAK
CASE MISSION_STAGE_ESCAPE_GOONS
//turn ambient peds on with lower density
SET_PED_POPULATION_BUDGET(3)
SET_VEHICLE_POPULATION_BUDGET(3)
//wanted level
SET_MAX_WANTED_LEVEL(0)
SET_CREATE_RANDOM_COPS(FALSE)
SET_WANTED_LEVEL_MULTIPLIER(0.0)
SET_PLAYER_CAN_CHANGE_CLOTHES_ON_MISSION(FALSE)
SET_ALL_SHOPS_TEMPORARILY_UNAVAILABLE(TRUE)
SET_INSTANCE_PRIORITY_HINT(INSTANCE_HINT_DRIVING)
ADD_NAVMESH_BLOCKING_OBJECTS()
BREAK
CASE MISSION_STAGE_CUTSCENE_END
CASE MISSION_STAGE_LEADOUT
//turn ambient peds on
SET_PED_POPULATION_BUDGET(3)
SET_VEHICLE_POPULATION_BUDGET(3)
IF IS_PLAYER_PLAYING(PLAYER_ID())
SET_PLAYER_WANTED_LEVEL(PLAYER_ID(), 0)
SET_PLAYER_WANTED_LEVEL_NOW(PLAYER_ID())
ENDIF
SET_PLAYER_CAN_CHANGE_CLOTHES_ON_MISSION(TRUE)
BREAK
ENDSWITCH
iSetupProgress++
ENDIF
IF ( iSetupProgress = 9 )
//stage was skipped to or is being replayed
IF ( bStageSkippedTo = TRUE OR bStageReplayed = TRUE )
SWITCH eStage
CASE MISSION_STAGE_CAR_CHASE
REQUEST_VEHICLE_ASSET(vsPlayersCar.ModelName, ENUM_TO_INT(VRF_REQUEST_ENTRY_ANIMS))
IF HAS_VEHICLE_ASSET_LOADED(vsPlayersCar.ModelName)
iSetupProgress++
ENDIF
BREAK
CASE MISSION_STAGE_PULL_HOUSE_DOWN
IF ( bRopeAttached = FALSE )
IF NOT DOES_ROPE_EXIST(Rope)
ROPE_LOAD_TEXTURES()
IF ROPE_ARE_TEXTURES_LOADED()
Rope = ADD_ROPE(<<-1017.9850, 660.4285, 147.4662>>, <<0.0, 0.0, 0.0>>, ROPE_MAX_LEN, PHYSICS_ROPE_DEFAULT, -1, 0.5, 0.5, FALSE, TRUE)
LOAD_ROPE_DATA( Rope, ROPE_DATA_FILE )
ENDIF
ENDIF
IF DOES_ENTITY_EXIST(osRopeAnchor.ObjectIndex)
AND DOES_ROPE_EXIST(rope)
IF DOES_ENTITY_HAVE_PHYSICS(osRopeAnchor.ObjectIndex)
IF IS_VEHICLE_DRIVEABLE(vsPlayersCar.VehicleIndex)
ATTACH_ENTITIES_TO_ROPE(Rope, osRopeAnchor.ObjectIndex, vsPlayersCar.VehicleIndex, osRopeAnchor.vPosition, GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(vsPlayersCar.VehicleIndex, << 0.0, -2.1, 0.6 >>), 35.0, 0, 0)
bRopeAttached = TRUE
ENDIF
ENDIF
ENDIF
ELSE
IF IS_VEHICLE_DRIVEABLE(vsPlayersCar.VehicleIndex)
SET_VEHICLE_DOOR_OPEN(vsPlayersCar.VehicleIndex, SC_DOOR_BOOT, FALSE, TRUE)
ENDIF
iSetupProgress++
ENDIF
BREAK
DEFAULT
iSetupProgress++
BREAK
ENDSWITCH
ELSE
iSetupProgress++
ENDIF
ENDIF
//handle player positioning when current stage is being skipped to or played normally
//fade in the screen if it was faded out due to skipping
IF ( iSetupProgress = 10 )
//stage was skipped to or is being replayed
IF ( bStageSkippedTo = TRUE OR bStageReplayed = TRUE )
IF ( bStageReplayed = TRUE )
END_REPLAY_SETUP(NULL, DEFAULT, FALSE)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Calling END_REPLAY_SETUP().")
#ENDIF
ELSE
NEW_LOAD_SCENE_START_SPHERE(GET_ENTITY_COORDS(PLAYER_PED_ID()), 100.0)
#IF IS_DEBUG_BUILD
VECTOR vNewLoadScenePosition = GET_ENTITY_COORDS(PLAYER_PED_ID())
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Calling NEW_LOAD_SCENE_START_SPHERE() at coordinates ", vNewLoadScenePosition, " for mission replay or stage skip. This might take a while to load.")
#ENDIF
INT iLoadSceneTimer = GET_GAME_TIMER() + 15000
WHILE IS_NEW_LOAD_SCENE_ACTIVE()
AND NOT IS_NEW_LOAD_SCENE_LOADED()
AND GET_GAME_TIMER() < iLoadSceneTimer
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Load scene timer: ", iLoadSceneTimer - GET_GAME_TIMER(), ".")
#ENDIF
WAIT(0)
ENDWHILE
NEW_LOAD_SCENE_STOP()
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Calling NEW_LOAD_SCENE_STOP().")
#ENDIF
ENDIF
//WAIT(1000) //add wait to hide any load scene freezes
//reset objective text labels for skips and retry
sLabelGIT = "FAM3_GIT"
//put player in car when required during the skip
SWITCH eStage
CASE MISSION_STAGE_CUTSCENE_BACK_OF_HOUSE
CASE MISSION_STAGE_ESCAPE_GOONS
CASE MISSION_STAGE_CUTSCENE_END
IF IS_VEHICLE_DRIVEABLE(vsPlayersCar.VehicleIndex)
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
SET_PED_INTO_VEHICLE(PLAYER_PED_ID(), vsPlayersCar.VehicleIndex, VS_DRIVER)
SET_VEHICLE_ON_GROUND_PROPERLY(vsPlayersCar.VehicleIndex)
SET_VEHICLE_ENGINE_ON(vsPlayersCar.VehicleIndex, TRUE, TRUE)
ENDIF
ENDIF
BREAK
ENDSWITCH
IF ( eStage = MISSION_STAGE_CAR_CHASE )
OR ( eStage = MISSION_STAGE_PULL_HOUSE_DOWN )
WAIT(500)
IF ( eStage = MISSION_STAGE_CAR_CHASE )
UPDATE_THIRD_PERSON_RUN_TO_VEHICLE_CAMERA()
ENDIF
ENDIF
SET_GAMEPLAY_CAM_RELATIVE_PITCH(0)
SET_GAMEPLAY_CAM_RELATIVE_HEADING(0)
//handle music for skips/retry/replay of mission stages
SWITCH eStage
CASE MISSION_STAGE_CAR_CHASE
TRIGGER_MUSIC_EVENT("FAM3_CHASE_RESTART")
BREAK
CASE MISSION_STAGE_CUTSCENE_BACK_OF_HOUSE
TRIGGER_MUSIC_EVENT("FAM3_HOUSE_RESTART")
BREAK
CASE MISSION_STAGE_PULL_HOUSE_DOWN
TRIGGER_MUSIC_EVENT("FAM3_PULL_RESTART")
BREAK
CASE MISSION_STAGE_ESCAPE_GOONS
TRIGGER_MUSIC_EVENT("FAM3_MEX_RESTART")
BREAK
ENDSWITCH
//handle fade in for each mission stage
//some stages start with or require a fade out
SWITCH eStage
CASE MISSION_STAGE_CUTSCENE_INTRO
CASE MISSION_STAGE_CAR_CHASE
CASE MISSION_STAGE_CUTSCENE_BACK_OF_HOUSE
CASE MISSION_STAGE_CUTSCENE_END
CASE MISSION_STAGE_LEADOUT
//do not fade in, mission stage will handle a fade in from fade out
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Halting loading screen fade in for skip to a mission stage that will fade the screen in.")
#ENDIF
BREAK
DEFAULT
//fade in
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Calling a loading screen fade in.")
#ENDIF
IF IS_SCREEN_FADED_OUT()
DO_SAFE_SCREEN_FADE_IN(DEFAULT_FADE_TIME)
ENDIF
BREAK
ENDSWITCH
ENDIF
iSetupProgress++
ENDIF
//handle setting of mid-mission replay/retry checkpoints
IF ( iSetupProgress = 11 )
SWITCH eStage
CASE MISSION_STAGE_CAR_CHASE
SET_REPLAY_MID_MISSION_STAGE_WITH_NAME(ENUM_TO_INT(MID_MISSION_STAGE_CAR_CHASE), "CAR CHASE", FALSE)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Setting replay mid-mission checkpoint to ", ENUM_TO_INT(MID_MISSION_STAGE_CAR_CHASE), " for stage ", GET_MISSION_STAGE_NAME_FOR_DEBUG(eStage), ".")
#ENDIF
BREAK
CASE MISSION_STAGE_PULL_HOUSE_DOWN
SET_REPLAY_MID_MISSION_STAGE_WITH_NAME(ENUM_TO_INT(MID_MISSION_STAGE_PULL_HOUSE_DOWN), "PULL HOUSE DOWN", FALSE)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Setting replay mid-mission checkpoint to ", ENUM_TO_INT(MID_MISSION_STAGE_PULL_HOUSE_DOWN), " for stage ", GET_MISSION_STAGE_NAME_FOR_DEBUG(eStage), ".")
#ENDIF
BREAK
CASE MISSION_STAGE_ESCAPE_GOONS
SET_REPLAY_MID_MISSION_STAGE_WITH_NAME(ENUM_TO_INT(MID_MISSION_STAGE_ESCAPE_GOONS), "ESCAPE GOONS", TRUE)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Setting replay mid-mission checkpoint to ", ENUM_TO_INT(MID_MISSION_STAGE_ESCAPE_GOONS), " for stage ", GET_MISSION_STAGE_NAME_FOR_DEBUG(eStage), ".")
#ENDIF
BREAK
ENDSWITCH
iSetupProgress++
ENDIF
//print the message only once per mission stage
//handle fades
IF ( iSetupProgress = 12 )
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Finished mission stage loading for ", GET_MISSION_STAGE_NAME_FOR_DEBUG(eStage), ".")
#ENDIF
//reset the stage reset flag
#IF IS_DEBUG_BUILD
bStageResetFlag = FALSE
#ENDIF
bStageLoaded = TRUE
bStageReplayed = FALSE
bStageSkippedTo = FALSE
SET_PLAYER_CONTROL(PLAYER_ID(), TRUE)
iSetupProgress++
ENDIF
IF ( iSetupProgress = 13 )
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
PROC SET_PED_PROPERTIES_AFTER_HOTSWAP(PED_STRUCT &ped, PED_INDEX PedIndex, BOOL bCreateBlip, REL_GROUP_HASH relGroupHash)
IF NOT IS_PED_INJURED(PedIndex)
ped.PedIndex = PedIndex
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(PedIndex, TRUE)
SET_PED_CAN_BE_TARGETTED(PedIndex, FALSE)
SET_PED_AS_ENEMY(PedIndex, FALSE)
SET_PED_RELATIONSHIP_GROUP_HASH(PedIndex, relGroupHash)
SET_RAGDOLL_BLOCKING_FLAGS(PedIndex, RBF_BULLET_IMPACT)
SET_RAGDOLL_BLOCKING_FLAGS(PedIndex, RBF_PLAYER_IMPACT)
SET_PED_SUFFERS_CRITICAL_HITS(PedIndex, FALSE)
SET_PED_HIGHLY_PERCEPTIVE(PedIndex, TRUE)
SET_PED_CONFIG_FLAG(PedIndex, PCF_DisableHurt, TRUE)
SET_PED_CONFIG_FLAG(PedIndex, PCF_DisablePanicInVehicle, TRUE)
SET_PED_CONFIG_FLAG(PedIndex, PCF_WillFlyThroughWindscreen, FALSE)
SET_PED_CONFIG_FLAG(PedIndex, PCF_OnlyAttackLawIfPlayerIsWanted, TRUE)
SET_COMBAT_FLOAT(PedIndex, CCF_TIME_TO_INVALIDATE_INJURED_TARGET, 1.0)
SET_PED_COMBAT_ATTRIBUTES(PedIndex, CA_ALWAYS_EQUIP_BEST_WEAPON, FALSE)
SET_PED_COMBAT_ATTRIBUTES(PedIndex, CA_CAN_FIGHT_ARMED_PEDS_WHEN_NOT_ARMED, TRUE)
SET_PED_MAX_HEALTH_WITH_SCALE(PedIndex, MAX_BUDDY_PED_HEALTH)
IF GET_BEST_PED_WEAPON(PedIndex) = WEAPONTYPE_UNARMED
GIVE_WEAPON_TO_PED(PedIndex, WEAPONTYPE_PISTOL, GET_MAX_AMMO_IN_CLIP(PedIndex, WEAPONTYPE_PISTOL) * 2, FALSE, FALSE)
ENDIF
ADD_ENTITY_TO_AUDIO_MIX_GROUP(PedIndex, "FAMILY_3_BUDDY_GROUP")
IF ( bCreateBlip = TRUE )
IF NOT DOES_BLIP_EXIST(ped.BlipIndex)
ped.BlipIndex = CREATE_BLIP_FOR_ENTITY(PedIndex, FALSE)
ENDIF
ENDIF
ENDIF
ENDPROC
FUNC BOOL RUN_SHORT_RANGE_OR_DIRECT_SWITCH(SELECTOR_CAM_STRUCT &sCamStruct, BOOL bDirectSwitch)
IF ( bDirectSwitch = FALSE ) //run default short range switch
IF RUN_SWITCH_CAM_FROM_PLAYER_TO_PED_SHORT_RANGE(sCamStruct)
IF sCamStruct.bOKToSwitchPed = TRUE
RETURN TRUE
ENDIF
ENDIF
ELSE //don't run the default short range switch, just move on to take control of selector ped directly
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
PROC RUN_HOTSWAP()
IF NOT sCamDetails.bRun
IF UPDATE_SELECTOR_HUD(sSelectorPeds)
IF NOT HAS_SELECTOR_PED_BEEN_SELECTED(sSelectorPeds, SELECTOR_PED_MULTIPLAYER)
IF HAS_SOUND_FINISHED(iCustomSwitchSoundID)
PLAY_SOUND_FRONTEND(iCustomSwitchSoundID, "All", "SHORT_PLAYER_SWITCH_SOUND_SET")
ENDIF
IF ( bFirstSwitchCompleted = FALSE )
ADD_AMMO_TO_PED(GET_PED_INDEX(CHAR_FRANKLIN), WEAPONTYPE_PISTOL,
GET_MAX_AMMO_IN_CLIP(GET_PED_INDEX(CHAR_FRANKLIN), WEAPONTYPE_PISTOL) * 5)
bFirstSwitchCompleted = TRUE
ENDIF
sCamDetails.pedTo = sSelectorPeds.pedID[sSelectorPeds.eNewSelectorPed]
sCamDetails.bRun = TRUE
bRunDirectSwitch = FALSE
//decide which switch to run here and then stick to it until switch is over
IF NOT IS_PED_INJURED(GET_PED_INDEX(CHAR_MICHAEL))
AND NOT IS_PED_INJURED(GET_PED_INDEX(CHAR_FRANKLIN))
IF IS_PED_IN_ANY_VEHICLE(GET_PED_INDEX(CHAR_MICHAEL))
OR IS_PED_IN_ANY_VEHICLE(GET_PED_INDEX(CHAR_FRANKLIN))
IF GET_CAM_VIEW_MODE_FOR_CONTEXT(CAM_VIEW_MODE_CONTEXT_IN_VEHICLE) = CAM_VIEW_MODE_FIRST_PERSON
bRunDirectSwitch = TRUE //disable short range switch and cut straight to the other ped
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ELSE
IF RUN_SHORT_RANGE_OR_DIRECT_SWITCH(sCamDetails, bRunDirectSwitch)
IF NOT sCamDetails.bPedSwitched
IF TAKE_CONTROL_OF_SELECTOR_PED(sSelectorPeds, TRUE, TRUE)
//clear locates header blips and god text when switching
CLEAR_MISSION_LOCATION_TEXT_AND_BLIPS(sLocatesData)
SWITCH GET_CURRENT_PLAYER_PED_ENUM()
CASE CHAR_MICHAEL //player hot swapped to Michael
//remove blip for the ped that is now current player ped
IF DOES_BLIP_EXIST(psMichael.BlipIndex)
REMOVE_BLIP(psMichael.BlipIndex)
ENDIF
SET_PED_PROPERTIES_AFTER_HOTSWAP(psFranklin, sSelectorPeds.pedID[sSelectorPeds.ePreviousSelectorPed], FALSE, RELGROUPHASH_PLAYER)
FailFlags[MISSION_FAIL_MICHAEL_DEAD] = FALSE
FailFlags[MISSION_FAIL_MICHAEL_LEFT_BEHIND] = FALSE
FailFlags[MISSION_FAIL_FRANKLIN_DEAD] = TRUE
FailFlags[MISSION_FAIL_FRANKLIN_LEFT_BEHIND] = TRUE
GO_TO_PED_STATE(psFranklin, PED_STATE_WAITING_FOR_TASK_AFTER_SWITCH)
IF ( bRunDirectSwitch = TRUE )
ANIMPOSTFX_PLAY("SwitchSceneMichael", 0, FALSE)
ENDIF
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Player switched to Michael.")
#ENDIF
BREAK
CASE CHAR_FRANKLIN //player hot swapped to Franklin
//remove blip for the ped that is now current player ped
IF DOES_BLIP_EXIST(psFranklin.BlipIndex)
REMOVE_BLIP(psFranklin.BlipIndex)
ENDIF
SET_PED_PROPERTIES_AFTER_HOTSWAP(psMichael, sSelectorPeds.pedID[sSelectorPeds.ePreviousSelectorPed], FALSE, RELGROUPHASH_PLAYER)
FailFlags[MISSION_FAIL_MICHAEL_DEAD] = TRUE
FailFlags[MISSION_FAIL_MICHAEL_LEFT_BEHIND] = TRUE
FailFlags[MISSION_FAIL_FRANKLIN_DEAD] = FALSE
FailFlags[MISSION_FAIL_FRANKLIN_LEFT_BEHIND] = FALSE
GO_TO_PED_STATE(psFranklin, PED_STATE_WAITING_FOR_TASK_AFTER_SWITCH)
IF ( bRunDirectSwitch = TRUE )
ANIMPOSTFX_PLAY("SwitchSceneFranklin", 0, FALSE)
ENDIF
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Player switched to Franklin.")
#ENDIF
BREAK
ENDSWITCH
IF NOT HAS_SOUND_FINISHED(iCustomSwitchSoundID)
STOP_SOUND(iCustomSwitchSoundID)
ENDIF
REMOVE_ENTITY_FROM_AUDIO_MIX_GROUP(PLAYER_PED_ID())
REGISTER_PED_TO_ACTIVATE_AUTOMATIC_DOOR(AUTODOOR_MICHAEL_MANSION_GATE, PLAYER_PED_ID()) //register current player with mansion gate
//this breaks on repeat play for some reason
INFORM_MISSION_STATS_OF_INCREMENT(FAM3_SWITCHES) //increments switch stat
SET_SELECTOR_PED_HINT(sSelectorPeds, SELECTOR_PED_MICHAEL, FALSE)
SET_SELECTOR_PED_HINT(sSelectorPeds, SELECTOR_PED_FRANKLIN, FALSE)
iPlayerShootingTimer = GET_GAME_TIMER() //reset shooting timer
bHotSwapTriggered = TRUE //flag that switch happened
sCamDetails.bPedSwitched = TRUE
IF ( bRunDirectSwitch = TRUE ) //running a direct cut other selector ped
sCamDetails.bRun = FALSE //reset these flags for 1st person vehicle switch
sCamDetails.bPedSwitched = FALSE //as we no longer run short range switch function
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDPROC
//|======================== END MISSION STAGE LOADINGS PROCEDURES ========================|
//|=============================== MISSION STAGES FUNCTIONS ==============================|
FUNC BOOL IS_MISSION_STAGE_CUTSCENE_INTRO_COMPLETED(INT &iStageProgress)
SWITCH iStageProgress
CASE 0
IF ( GET_CURRENT_PLAYER_PED_ENUM() = CHAR_MICHAEL )
IF HAS_REQUESTED_CUTSCENE_LOADED("family_3_int")
REGISTER_ENTITY_FOR_CUTSCENE(psFranklin.PedIndex, "Franklin", CU_CREATE_AND_ANIMATE_NEW_SCRIPT_ENTITY, GET_PLAYER_PED_MODEL(CHAR_FRANKLIN))
IF DOES_ENTITY_EXIST(g_sTriggerSceneAssets.object[0])
IF NOT IS_ENTITY_DEAD(g_sTriggerSceneAssets.object[0])
SET_ENTITY_AS_MISSION_ENTITY(g_sTriggerSceneAssets.object[0], TRUE, TRUE)
osRacket01.ObjectIndex = g_sTriggerSceneAssets.object[0]
REGISTER_ENTITY_FOR_CUTSCENE(osRacket01.ObjectIndex, "Racket_1", CU_ANIMATE_EXISTING_SCRIPT_ENTITY, osRacket01.ModelName)
ENDIF
ELSE
REGISTER_ENTITY_FOR_CUTSCENE(osRacket01.ObjectIndex, "Racket_1", CU_CREATE_AND_ANIMATE_NEW_SCRIPT_ENTITY, osRacket01.ModelName)
ENDIF
IF DOES_ENTITY_EXIST(g_sTriggerSceneAssets.object[1])
IF NOT IS_ENTITY_DEAD(g_sTriggerSceneAssets.object[1])
SET_ENTITY_AS_MISSION_ENTITY(g_sTriggerSceneAssets.object[1], TRUE, TRUE)
osRacket02.ObjectIndex = g_sTriggerSceneAssets.object[1]
REGISTER_ENTITY_FOR_CUTSCENE(osRacket02.ObjectIndex, "Racket_2", CU_ANIMATE_EXISTING_SCRIPT_ENTITY, osRacket02.ModelName)
ENDIF
ELSE
REGISTER_ENTITY_FOR_CUTSCENE(osRacket02.ObjectIndex, "Racket_2", CU_CREATE_AND_ANIMATE_NEW_SCRIPT_ENTITY, osRacket02.ModelName)
ENDIF
SET_SCRIPTS_SAFE_FOR_CUTSCENE(TRUE)
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
REMOVE_PED_HELMET(PLAYER_PED_ID(), TRUE)
ENDIF
CLEAR_HELP()
CLEAR_PRINTS()
START_CUTSCENE(CUTSCENE_SUPPRESS_FP_TRANSITION_FLASH)
REPLAY_START_EVENT(REPLAY_IMPORTANCE_HIGHEST)
iStageProgress++
ELSE
IF CAN_REQUEST_ASSETS_FOR_CUTSCENE_ENTITY()
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
SET_CUTSCENE_PED_COMPONENT_VARIATION_FROM_PED("Michael", PLAYER_PED_ID()) //Michael's variations
ENDIF
SET_CUTSCENE_PED_OUTFIT("Franklin", PLAYER_ONE, OUTFIT_P1_GREEN_SHIRT_JEANS) //Franklin's variations
SET_CUTSCENE_PED_COMPONENT_VARIATION("Amanda", PED_COMP_HAIR, 1, 0) //Amanda's variations
SET_CUTSCENE_PED_COMPONENT_VARIATION("Amanda", PED_COMP_TORSO, 2, 0)
SET_CUTSCENE_PED_COMPONENT_VARIATION("Amanda", PED_COMP_LEG, 2, 0)
SET_CUTSCENE_PED_COMPONENT_VARIATION("Amanda", PED_COMP_DECL, 1, 0)
SET_CUTSCENE_PED_COMPONENT_VARIATION("TennisCoach", PED_COMP_TORSO, 1, 0) //Tennis coach variations
SET_CUTSCENE_PED_COMPONENT_VARIATION("TennisCoach", PED_COMP_LEG, 1, 0)
ENDIF
ENDIF
ELIF ( GET_CURRENT_PLAYER_PED_ENUM() = CHAR_FRANKLIN )
IF HAS_REQUESTED_CUTSCENE_LOADED("family_3_int", CS_SECTION_4 | CS_SECTION_5)
REGISTER_ENTITY_FOR_CUTSCENE(psMichael.PedIndex, "Michael", CU_CREATE_AND_ANIMATE_NEW_SCRIPT_ENTITY, GET_PLAYER_PED_MODEL(CHAR_MICHAEL))
IF DOES_ENTITY_EXIST(g_sTriggerSceneAssets.object[0])
IF NOT IS_ENTITY_DEAD(g_sTriggerSceneAssets.object[0])
SET_ENTITY_AS_MISSION_ENTITY(g_sTriggerSceneAssets.object[0], TRUE, TRUE)
osRacket01.ObjectIndex = g_sTriggerSceneAssets.object[0]
REGISTER_ENTITY_FOR_CUTSCENE(osRacket01.ObjectIndex, "Racket_1", CU_ANIMATE_EXISTING_SCRIPT_ENTITY, osRacket01.ModelName)
ENDIF
ELSE
REGISTER_ENTITY_FOR_CUTSCENE(osRacket01.ObjectIndex, "Racket_1", CU_CREATE_AND_ANIMATE_NEW_SCRIPT_ENTITY, osRacket01.ModelName)
ENDIF
IF DOES_ENTITY_EXIST(g_sTriggerSceneAssets.object[1])
IF NOT IS_ENTITY_DEAD(g_sTriggerSceneAssets.object[1])
SET_ENTITY_AS_MISSION_ENTITY(g_sTriggerSceneAssets.object[1], TRUE, TRUE)
osRacket02.ObjectIndex = g_sTriggerSceneAssets.object[1]
REGISTER_ENTITY_FOR_CUTSCENE(osRacket02.ObjectIndex, "Racket_2", CU_ANIMATE_EXISTING_SCRIPT_ENTITY, osRacket02.ModelName)
ENDIF
ELSE
REGISTER_ENTITY_FOR_CUTSCENE(osRacket02.ObjectIndex, "Racket_2", CU_CREATE_AND_ANIMATE_NEW_SCRIPT_ENTITY, osRacket02.ModelName)
ENDIF
SET_SCRIPTS_SAFE_FOR_CUTSCENE(TRUE)
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
REMOVE_PED_HELMET(PLAYER_PED_ID(), TRUE)
ENDIF
CLEAR_HELP()
CLEAR_PRINTS()
START_CUTSCENE(CUTSCENE_SUPPRESS_FP_TRANSITION_FLASH)
iStageProgress++
ELSE
IF CAN_REQUEST_ASSETS_FOR_CUTSCENE_ENTITY()
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
SET_CUTSCENE_PED_COMPONENT_VARIATION_FROM_PED("Franklin", PLAYER_PED_ID()) //Franklin's variations
ENDIF
SET_CUTSCENE_PED_OUTFIT("Michael", PLAYER_ZERO, OUTFIT_P0_POLOSHIRT_JEANS_1) //Michael's variations
SET_CUTSCENE_PED_COMPONENT_VARIATION("Amanda", PED_COMP_HAIR, 1, 0) //Amanda's variations
SET_CUTSCENE_PED_COMPONENT_VARIATION("Amanda", PED_COMP_TORSO, 2, 0)
SET_CUTSCENE_PED_COMPONENT_VARIATION("Amanda", PED_COMP_LEG, 2, 0)
SET_CUTSCENE_PED_COMPONENT_VARIATION("Amanda", PED_COMP_DECL, 1, 0)
ENDIF
ENDIF
ENDIF
BREAK
CASE 1 //fade screen in if screen was faded out due to shit skip or debug skip
IF IS_CUTSCENE_PLAYING()
DELETE_VEHICLE_GEN_VEHICLE(VEHGEN_MISSION_VEH)
IF IS_REPLAY_START_VEHICLE_AVAILABLE()
AND DOES_ENTITY_EXIST(GET_PLAYERS_LAST_VEHICLE())
IF ( GET_MISSION_START_VEHICLE_INDEX() = GET_PLAYERS_LAST_VEHICLE() )
IF NOT IS_ENTITY_DEAD(GET_PLAYERS_LAST_VEHICLE())
AND IS_VEHICLE_DRIVEABLE(GET_PLAYERS_LAST_VEHICLE(), TRUE)
AND NOT IS_THIS_MODEL_A_HELI(GET_ENTITY_MODEL(GET_PLAYERS_LAST_VEHICLE()))
AND NOT IS_THIS_MODEL_A_PLANE(GET_ENTITY_MODEL(GET_PLAYERS_LAST_VEHICLE()))
SET_ENTITY_COORDS(GET_PLAYERS_LAST_VEHICLE(), << -867.9103, 158.2215, 63.9014 >>)
SET_ENTITY_HEADING(GET_PLAYERS_LAST_VEHICLE(), 174.2918)
SET_VEHICLE_DOORS_SHUT(GET_PLAYERS_LAST_VEHICLE())
SET_VEHICLE_ON_GROUND_PROPERLY(GET_PLAYERS_LAST_VEHICLE())
SET_VEHICLE_ENGINE_ON(GET_PLAYERS_LAST_VEHICLE(), FALSE, TRUE)
SET_MISSION_START_VEHICLE_AS_VEHICLE_GEN(<< -867.9103, 158.2215, 63.9014 >>, 174.2918)
CLEAR_MUST_LEAVE_AREA_VEHICLE_GEN_FLAG(VEHGEN_MISSION_VEH)
ENDIF
ENDIF
ENDIF
CLEAR_AREA(psMichael.vPosition, 5000.0, TRUE)
LOCK_AUTOMATIC_DOOR_OPEN(AUTODOOR_MICHAEL_MANSION_GATE, TRUE)
IF IS_SCREEN_FADED_OUT()
DO_SCREEN_FADE_IN(DEFAULT_FADE_TIME)
ENDIF
bTriggerSwitchFlash = FALSE
bTruckRepositionedForCutscene = FALSE
iStageProgress++
ENDIF
BREAK
CASE 2
UPDATE_THIRD_PERSON_RUN_TO_VEHICLE_CAMERA()
IF IS_CUTSCENE_PLAYING()
IF ( GET_CUTSCENE_TIME() > 40000.0 )
IF ( bMusicEventMissionStartTriggered = FALSE )
IF TRIGGER_MUSIC_EVENT("FAM3_MISSION_START")
bMusicEventMissionStartTriggered = TRUE
ENDIF
ENDIF
ENDIF
ENDIF
IF NOT DOES_ENTITY_EXIST(osBrokenPlantPot.ObjectIndex)
IF GET_CURRENT_PLAYER_PED_ENUM() = CHAR_MICHAEL
REQUEST_MODEL(osBrokenPlantPot.ModelName)
IF HAS_MODEL_LOADED(osBrokenPlantPot.ModelName)
IF GET_CUTSCENE_TIME() > 54000
IF HAS_MISSION_OBJECT_BEEN_CREATED(osBrokenPlantPot, TRUE)
SET_MODEL_AS_NO_LONGER_NEEDED(osBrokenPlantPot.ModelName)
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
IF NOT DOES_ENTITY_EXIST(osRacket01.ObjectIndex)
IF DOES_CUTSCENE_ENTITY_EXIST("Racket_1")
IF DOES_ENTITY_EXIST(GET_ENTITY_INDEX_OF_REGISTERED_ENTITY("Racket_1"))
osRacket01.ObjectIndex = GET_OBJECT_INDEX_FROM_ENTITY_INDEX(GET_ENTITY_INDEX_OF_REGISTERED_ENTITY("Racket_1"))
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Created object Racket_1 in the cutscene.")
#ENDIF
ENDIF
ENDIF
ENDIF
IF NOT DOES_ENTITY_EXIST(osRacket02.ObjectIndex)
IF DOES_CUTSCENE_ENTITY_EXIST("Racket_2")
IF DOES_ENTITY_EXIST(GET_ENTITY_INDEX_OF_REGISTERED_ENTITY("Racket_2"))
osRacket02.ObjectIndex = GET_OBJECT_INDEX_FROM_ENTITY_INDEX(GET_ENTITY_INDEX_OF_REGISTERED_ENTITY("Racket_2"))
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Created object Racket_2 in the cutscene.")
#ENDIF
ENDIF
ENDIF
ENDIF
//create player peds by extracting them from mocap cutscene
IF ( GET_CURRENT_PLAYER_PED_ENUM() = CHAR_MICHAEL )
IF NOT DOES_ENTITY_EXIST(psFranklin.PedIndex)
IF DOES_CUTSCENE_ENTITY_EXIST("Franklin")
IF DOES_ENTITY_EXIST(GET_ENTITY_INDEX_OF_REGISTERED_ENTITY("Franklin"))
psFranklin.PedIndex = GET_PED_INDEX_FROM_ENTITY_INDEX(GET_ENTITY_INDEX_OF_REGISTERED_ENTITY("Franklin"))
SET_MISSION_PED_PROPERTIES(psFranklin.PedIndex, RELGROUPHASH_PLAYER, FALSE, TRUE, FALSE, FALSE)
sSelectorPeds.pedID[SELECTOR_PED_FRANKLIN] = psFranklin.PedIndex
SET_RAGDOLL_BLOCKING_FLAGS(psFranklin.PedIndex, RBF_PLAYER_IMPACT)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Set up properites for mission player ped Franklin created in the intro cutscene.")
#ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
IF ( GET_CURRENT_PLAYER_PED_ENUM() = CHAR_FRANKLIN )
IF NOT DOES_ENTITY_EXIST(psMichael.PedIndex)
IF DOES_CUTSCENE_ENTITY_EXIST("Michael")
IF DOES_ENTITY_EXIST(GET_ENTITY_INDEX_OF_REGISTERED_ENTITY("Michael"))
psMichael.PedIndex = GET_PED_INDEX_FROM_ENTITY_INDEX(GET_ENTITY_INDEX_OF_REGISTERED_ENTITY("Michael"))
SET_MISSION_PED_PROPERTIES(psMichael.PedIndex, RELGROUPHASH_PLAYER, FALSE, TRUE, FALSE, FALSE)
sSelectorPeds.pedID[SELECTOR_PED_MICHAEL] = psMichael.PedIndex
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Set up properites for mission player ped Michael created in the intro cutscene.")
#ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
//create vehicles during mocap cutscene or grab them from pre-mission trigger scene
IF IS_CUTSCENE_PLAYING()
//truck
IF NOT DOES_ENTITY_EXIST(vsPlayersCar.VehicleIndex)
IF DOES_ENTITY_EXIST(g_sTriggerSceneAssets.veh[0])
IF IS_VEHICLE_DRIVEABLE(g_sTriggerSceneAssets.veh[0], TRUE)
SET_ENTITY_AS_MISSION_ENTITY(g_sTriggerSceneAssets.veh[0], TRUE, TRUE)
vsPlayersCar.VehicleIndex = g_sTriggerSceneAssets.veh[0]
SET_MISSION_VEHICLE_PROPERTIES(vsPlayersCar, TRUE, -1, 132, 0, 0, 0 #IF IS_DEBUG_BUILD, "TS_Truck" #ENDIF)
IF GET_CURRENT_PLAYER_PED_ENUM() = CHAR_MICHAEL
//SET_VEHICLE_FIXED(vsPlayersCar.VehicleIndex)
IF DOES_ENTITY_EXIST(vsPlayersCar.VehicleIndex) AND NOT IS_ENTITY_DEAD(vsPlayersCar.VehicleIndex)
SET_ENTITY_HEALTH(vsPlayersCar.VehicleIndex, GET_ENTITY_HEALTH(vsPlayersCar.VehicleIndex) + 1000)
SET_VEHICLE_ENGINE_HEALTH(vsPlayersCar.VehicleIndex, GET_VEHICLE_ENGINE_HEALTH(vsPlayersCar.VehicleIndex) + 1000)
SET_VEHICLE_PETROL_TANK_HEALTH(vsPlayersCar.VehicleIndex, GET_VEHICLE_PETROL_TANK_HEALTH(vsPlayersCar.VehicleIndex) + 1000)
STOP_FIRE_IN_RANGE(GET_ENTITY_COORDS(vsPlayersCar.VehicleIndex), 2.5)
IF IS_VEHICLE_TYRE_BURST(vsPlayersCar.VehicleIndex, SC_WHEEL_CAR_FRONT_LEFT)
SET_VEHICLE_TYRE_FIXED(vsPlayersCar.VehicleIndex, SC_WHEEL_CAR_FRONT_LEFT)
ENDIF
IF IS_VEHICLE_TYRE_BURST(vsPlayersCar.VehicleIndex, SC_WHEEL_CAR_FRONT_RIGHT)
SET_VEHICLE_TYRE_FIXED(vsPlayersCar.VehicleIndex, SC_WHEEL_CAR_FRONT_RIGHT)
ENDIF
IF IS_VEHICLE_TYRE_BURST(vsPlayersCar.VehicleIndex, SC_WHEEL_CAR_REAR_LEFT)
SET_VEHICLE_TYRE_FIXED(vsPlayersCar.VehicleIndex, SC_WHEEL_CAR_REAR_LEFT)
ENDIF
IF IS_VEHICLE_TYRE_BURST(vsPlayersCar.VehicleIndex, SC_WHEEL_CAR_REAR_RIGHT)
SET_VEHICLE_TYRE_FIXED(vsPlayersCar.VehicleIndex, SC_WHEEL_CAR_REAR_RIGHT)
ENDIF
IF NOT IS_VEHICLE_EXTRA_TURNED_ON(vsPlayersCar.VehicleIndex, 5)
SET_VEHICLE_EXTRA(vsPlayersCar.VehicleIndex, 5, FALSE)
ENDIF
SET_ENTITY_COORDS(vsPlayersCar.VehicleIndex, vsPlayersCar.vPosition) //reposition truck when playing as Michael
SET_ENTITY_HEADING(vsPlayersCar.VehicleIndex, vsPlayersCar.fHeading) //reposition truck later when playing as Franklin
SET_VEHICLE_ON_GROUND_PROPERLY(vsPlayersCar.VehicleIndex)
bTruckRepositionedForCutscene = TRUE
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Repositioned truck for cutscene. Player is CHAR_MICHAEL.")
#ENDIF
ENDIF
ENDIF
ELSE
SET_ENTITY_AS_MISSION_ENTITY(g_sTriggerSceneAssets.veh[0], TRUE, TRUE)
DELETE_VEHICLE(g_sTriggerSceneAssets.veh[0])
CLEAR_AREA(vsPlayersCar.vPosition, 5.0, TRUE)
ENDIF
ELSE
IF ( GET_CUTSCENE_TIME() > 8000 )
IF HAS_MISSION_VEHICLE_BEEN_CREATED(vsPlayersCar, FALSE, FALSE, NO_CHARACTER, TRUE, -1, 132, 0, 0, 0 #IF IS_DEBUG_BUILD, "M_Truck" #ENDIF)
SET_VEHICLE_EXTRA(vsPlayersCar.VehicleIndex, 5, FALSE)
ENDIF
ENDIF
ENDIF
ELSE
IF ( bTruckRepositionedForCutscene = FALSE )
IF GET_CURRENT_PLAYER_PED_ENUM() = CHAR_FRANKLIN
IF ( GET_CUTSCENE_TIME() > 60500.0 )
IF DOES_ENTITY_EXIST(vsPlayersCar.VehicleIndex) AND NOT IS_ENTITY_DEAD(vsPlayersCar.VehicleIndex)
SET_ENTITY_HEALTH(vsPlayersCar.VehicleIndex, GET_ENTITY_HEALTH(vsPlayersCar.VehicleIndex) + 1000)
SET_VEHICLE_ENGINE_HEALTH(vsPlayersCar.VehicleIndex, GET_VEHICLE_ENGINE_HEALTH(vsPlayersCar.VehicleIndex) + 1000)
SET_VEHICLE_PETROL_TANK_HEALTH(vsPlayersCar.VehicleIndex, GET_VEHICLE_PETROL_TANK_HEALTH(vsPlayersCar.VehicleIndex) + 1000)
STOP_FIRE_IN_RANGE(GET_ENTITY_COORDS(vsPlayersCar.VehicleIndex), 2.5)
IF IS_VEHICLE_TYRE_BURST(vsPlayersCar.VehicleIndex, SC_WHEEL_CAR_FRONT_LEFT)
SET_VEHICLE_TYRE_FIXED(vsPlayersCar.VehicleIndex, SC_WHEEL_CAR_FRONT_LEFT)
ENDIF
IF IS_VEHICLE_TYRE_BURST(vsPlayersCar.VehicleIndex, SC_WHEEL_CAR_FRONT_RIGHT)
SET_VEHICLE_TYRE_FIXED(vsPlayersCar.VehicleIndex, SC_WHEEL_CAR_FRONT_RIGHT)
ENDIF
IF IS_VEHICLE_TYRE_BURST(vsPlayersCar.VehicleIndex, SC_WHEEL_CAR_REAR_LEFT)
SET_VEHICLE_TYRE_FIXED(vsPlayersCar.VehicleIndex, SC_WHEEL_CAR_REAR_LEFT)
ENDIF
IF IS_VEHICLE_TYRE_BURST(vsPlayersCar.VehicleIndex, SC_WHEEL_CAR_REAR_RIGHT)
SET_VEHICLE_TYRE_FIXED(vsPlayersCar.VehicleIndex, SC_WHEEL_CAR_REAR_RIGHT)
ENDIF
IF NOT IS_VEHICLE_EXTRA_TURNED_ON(vsPlayersCar.VehicleIndex, 5)
SET_VEHICLE_EXTRA(vsPlayersCar.VehicleIndex, 5, FALSE)
ENDIF
SET_ENTITY_COORDS(vsPlayersCar.VehicleIndex, vsPlayersCar.vPosition) //reposition truck later when playing as Franklin
SET_ENTITY_HEADING(vsPlayersCar.VehicleIndex, vsPlayersCar.fHeading)
SET_VEHICLE_ON_GROUND_PROPERLY(vsPlayersCar.VehicleIndex)
bTruckRepositionedForCutscene = TRUE
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Repositioned truck for cutscene. Player is CHAR_FRANKLIN.")
#ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
IF NOT IS_ENTITY_DEAD(vsPlayersCar.VehicleIndex)
REQUEST_VEHICLE_HIGH_DETAIL_MODEL(vsPlayersCar.VehicleIndex)
ENDIF
ENDIF
//Tennis Coach's car
IF NOT DOES_ENTITY_EXIST(vsCoachsCar.VehicleIndex)
IF DOES_ENTITY_EXIST(g_sTriggerSceneAssets.veh[1])
IF IS_VEHICLE_DRIVEABLE(g_sTriggerSceneAssets.veh[1])
SET_ENTITY_AS_MISSION_ENTITY(g_sTriggerSceneAssets.veh[1], TRUE, TRUE)
SET_VEHICLE_FIXED(g_sTriggerSceneAssets.veh[1])
vsCoachsCar.VehicleIndex = g_sTriggerSceneAssets.veh[1]
SET_MISSION_VEHICLE_PROPERTIES(vsCoachsCar, TRUE, -1, 43, 43, 0, 0 #IF IS_DEBUG_BUILD, "TS_Coachs_Car" #ENDIF)
SET_ENTITY_COORDS(vsCoachsCar.VehicleIndex, vsCoachsCar.vPosition)
SET_ENTITY_HEADING(vsCoachsCar.VehicleIndex, vsCoachsCar.fHeading)
SET_VEHICLE_ON_GROUND_PROPERLY(vsCoachsCar.VehicleIndex)
ELSE
SET_ENTITY_AS_MISSION_ENTITY(g_sTriggerSceneAssets.veh[1], TRUE, TRUE)
DELETE_VEHICLE(g_sTriggerSceneAssets.veh[1])
CLEAR_AREA(vsCoachsCar.vPosition, 5.0, TRUE)
ENDIF
ELSE
IF ( GET_CUTSCENE_TIME() > 8000 )
HAS_MISSION_VEHICLE_BEEN_CREATED(vsCoachsCar, FALSE, FALSE, NO_CHARACTER, TRUE, -1, 43, 43, 0, 0 #IF IS_DEBUG_BUILD, "M_Coachs_Car" #ENDIF)
ENDIF
ENDIF
ENDIF
ENDIF
IF NOT DOES_ENTITY_EXIST(psCoach.PedIndex)
IF DOES_ENTITY_EXIST(g_sTriggerSceneAssets.ped[0])
SET_ENTITY_AS_MISSION_ENTITY(g_sTriggerSceneAssets.ped[0], TRUE, TRUE)
psCoach.PedIndex = g_sTriggerSceneAssets.ped[0]
SET_MISSION_PED_PROPERTIES(psCoach.PedIndex, rgTennisCoach, FALSE, TRUE, FALSE, FALSE)
IF DOES_ENTITY_EXIST(vsCoachsCar.VehicleIndex)
IF NOT IS_ENTITY_DEAD(vsCoachsCar.VehicleIndex)
CLEAR_PED_TASKS(psCoach.PedIndex)
SET_ENTITY_VISIBLE(psCoach.PedIndex, TRUE)
IF NOT IS_PED_IN_VEHICLE(psCoach.PedIndex, vsCoachsCar.VehicleIndex)
SET_PED_INTO_VEHICLE(psCoach.PedIndex, vsCoachsCar.VehicleIndex, VS_DRIVER)
ENDIF
ENDIF
ENDIF
#IF IS_DEBUG_BUILD
SET_PED_NAME_DEBUG(psCoach.PedIndex, "TS_TennisCoach")
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Grabbing Tennis Coach ped from trigger scene script.")
#ENDIF
ELSE
IF DOES_ENTITY_EXIST(vsCoachsCar.VehicleIndex)
IF HAS_MISSION_PED_BEEN_CREATED(psCoach, FALSE, rgTennisCoach, FALSE, NO_CHARACTER, FALSE, FALSE, FALSE, vsCoachsCar.VehicleIndex)
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(psCoach.PedIndex, TRUE)
ENDIF
ENDIF
ENDIF
ENDIF
IF CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY("Michael")
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY() returned true for Michael.")
#ENDIF
//hot swap to Michael if not currently controlling Michael
IF ( GET_CURRENT_PLAYER_PED_ENUM() <> CHAR_MICHAEL )
IF MAKE_SELECTOR_PED_SELECTION(sSelectorPeds, SELECTOR_PED_MICHAEL)
TAKE_CONTROL_OF_SELECTOR_PED(sSelectorPeds, TRUE, TRUE)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Taking control of player ped Michael when CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY() returned true for Michael.")
#ENDIF
IF GET_CAM_VIEW_MODE_FOR_CONTEXT(CAM_VIEW_MODE_CONTEXT_ON_FOOT) = CAM_VIEW_MODE_FIRST_PERSON
OR GET_CAM_VIEW_MODE_FOR_CONTEXT(CAM_VIEW_MODE_CONTEXT_IN_VEHICLE) = CAM_VIEW_MODE_FIRST_PERSON
bTriggerSwitchFlash = TRUE //trigger switch flash later, after the cutscene
ELSE
ANIMPOSTFX_PLAY("SwitchSceneMichael", 0, FALSE)
PLAY_SOUND_FRONTEND(-1, "Hit_1", "LONG_PLAYER_SWITCH_SOUNDS")
ENDIF
IF DOES_ENTITY_EXIST(GET_PED_INDEX(CHAR_FRANKLIN))
psFranklin.PedIndex = GET_PED_INDEX(CHAR_FRANKLIN)
SET_MISSION_PED_PROPERTIES(psFranklin.PedIndex, RELGROUPHASH_PLAYER, FALSE, TRUE, FALSE, FALSE)
sSelectorPeds.pedID[SELECTOR_PED_FRANKLIN] = psFranklin.PedIndex
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Set up properites for mission player ped Franklin for hot swap during intro cutscene when CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY() returned true for Michael.")
#ENDIF
ENDIF
ENDIF
ENDIF
IF ( bCutsceneSkipped = FALSE )
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
SET_PED_STEALTH_MOVEMENT(PLAYER_PED_ID(), FALSE)
WARP_PED(PLAYER_PED_ID(), <<-824.3681, 176.9837, 70.1645>>, 135.3757, FALSE, FALSE, FALSE)
IF IS_VEHICLE_DRIVEABLE(vsPlayersCar.VehicleIndex)
TASK_ENTER_VEHICLE(PLAYER_PED_ID(), vsPlayersCar.VehicleIndex, DEFAULT_TIME_BEFORE_WARP, VS_DRIVER, PEDMOVE_RUN, ECF_USE_LEFT_ENTRY | ECF_RESUME_IF_INTERRUPTED)
FORCE_PED_MOTION_STATE(PLAYER_PED_ID(), MS_ON_FOOT_RUN, FALSE, FAUS_CUTSCENE_EXIT)
ENDIF
ENDIF
ENDIF
ENDIF
IF CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY("Franklin")
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY() returned true for Franklin.")
#ENDIF
REPLAY_STOP_EVENT()
IF ( bCutsceneSkipped = FALSE )
IF NOT IS_PED_INJURED(psFranklin.PedIndex)
SET_RAGDOLL_BLOCKING_FLAGS(psFranklin.PedIndex, RBF_PLAYER_IMPACT)
SET_PED_STEALTH_MOVEMENT(psFranklin.PedIndex, FALSE)
WARP_PED(psFranklin.PedIndex, << -828.5035, 177.0551, 69.9812 >>, 159.2800, FALSE, FALSE, FALSE)
IF IS_VEHICLE_DRIVEABLE(vsPlayersCar.VehicleIndex)
TASK_ENTER_VEHICLE(psFranklin.PedIndex, vsPlayersCar.VehicleIndex, DEFAULT_TIME_BEFORE_WARP, VS_FRONT_RIGHT, PEDMOVE_RUN, ECF_USE_RIGHT_ENTRY | ECF_RESUME_IF_INTERRUPTED)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Giving Franklin ped task to enter vehicle when CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY() returned true for Franklin.")
#ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
IF CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY("Racket_1")
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY() returned true for Racket_1.")
#ENDIF
IF DOES_ENTITY_EXIST(osRacket01.ObjectIndex)
IF NOT IS_ENTITY_DEAD(osRacket01.ObjectIndex)
SET_ENTITY_COORDS_NO_OFFSET(osRacket01.ObjectIndex, osRacket01.vPosition)
SET_ENTITY_ROTATION(osRacket01.ObjectIndex, osRacket01.vRotation)
FREEZE_ENTITY_POSITION(osRacket01.ObjectIndex, TRUE)
ENDIF
ENDIF
ENDIF
IF CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY("Racket_2")
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY() returned true for Racket_2.")
#ENDIF
IF DOES_ENTITY_EXIST(osRacket02.ObjectIndex)
IF NOT IS_ENTITY_DEAD(osRacket02.ObjectIndex)
SET_ENTITY_COORDS_NO_OFFSET(osRacket02.ObjectIndex, osRacket02.vPosition)
SET_ENTITY_ROTATION(osRacket02.ObjectIndex, osRacket02.vRotation)
FREEZE_ENTITY_POSITION(osRacket02.ObjectIndex, TRUE)
ENDIF
ENDIF
ENDIF
IF HAS_CUTSCENE_FINISHED()
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Intro cutscene has finished.")
#ENDIF
IF HAS_MISSION_VEHICLE_BEEN_CREATED(vsPlayersCar, FALSE, FALSE, NO_CHARACTER, TRUE, -1, 132, 0, 0, 0 #IF IS_DEBUG_BUILD, "M_Truck" #ENDIF)
AND HAS_MISSION_VEHICLE_BEEN_CREATED(vsCoachsCar, FALSE, FALSE, NO_CHARACTER, TRUE, -1, 43, 43, 0, 0 #IF IS_DEBUG_BUILD, "M_Coachs_Car" #ENDIF)
AND HAS_VEHICLE_ASSET_LOADED(vsPlayersCar.ModelName)
AND DOES_ENTITY_EXIST(psCoach.PedIndex)
AND HAS_VEHICLE_RECORDING_BEEN_LOADED(vsCoachsCar.iRecordingNumber, sVehicleRecordingsFile)
AND DOES_ENTITY_EXIST(GET_PED_INDEX(CHAR_FRANKLIN))
AND ( GET_CURRENT_PLAYER_PED_ENUM() = CHAR_MICHAEL )
IF ( bCutsceneSkipped = TRUE )
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Repositioning peds and giving new tasks due to into cutscene skip.")
#ENDIF
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
SET_PED_STEALTH_MOVEMENT(PLAYER_PED_ID(), FALSE)
WARP_PED(PLAYER_PED_ID(), <<-824.3681, 176.9837, 70.1645>>, 135.3757, FALSE, FALSE, FALSE)
IF IS_VEHICLE_DRIVEABLE(vsPlayersCar.VehicleIndex)
TASK_ENTER_VEHICLE(PLAYER_PED_ID(), vsPlayersCar.VehicleIndex, DEFAULT_TIME_BEFORE_WARP, VS_DRIVER, PEDMOVE_RUN, ECF_USE_LEFT_ENTRY | ECF_RESUME_IF_INTERRUPTED)
FORCE_PED_MOTION_STATE(PLAYER_PED_ID(), MS_ON_FOOT_RUN)
ENDIF
ENDIF
IF NOT IS_PED_INJURED(psFranklin.PedIndex)
SET_PED_STEALTH_MOVEMENT(psFranklin.PedIndex, FALSE)
WARP_PED(psFranklin.PedIndex, << -828.5035, 177.0551, 69.9812 >>, 159.2800, FALSE, FALSE, FALSE)
IF IS_VEHICLE_DRIVEABLE(vsPlayersCar.VehicleIndex)
TASK_ENTER_VEHICLE(psFranklin.PedIndex, vsPlayersCar.VehicleIndex, DEFAULT_TIME_BEFORE_WARP, VS_FRONT_RIGHT, PEDMOVE_RUN, ECF_USE_RIGHT_ENTRY | ECF_RESUME_IF_INTERRUPTED)
ENDIF
ENDIF
SET_GAMEPLAY_CAM_RELATIVE_PITCH(0)
SET_GAMEPLAY_CAM_RELATIVE_HEADING(0)
WAIT(150)
UPDATE_THIRD_PERSON_RUN_TO_VEHICLE_CAMERA()
ENDIF
//close front doors at 0.0 open ratio
IF IS_DOOR_REGISTERED_WITH_SYSTEM(ENUM_TO_INT(DOORHASH_M_MANSION_F_L))
DOOR_SYSTEM_SET_OPEN_RATIO(ENUM_TO_INT(DOORHASH_M_MANSION_F_L), 0.0, FALSE, FALSE)
DOOR_SYSTEM_SET_DOOR_STATE(ENUM_TO_INT(DOORHASH_M_MANSION_F_L), DOORSTATE_FORCE_UNLOCKED_THIS_FRAME, FALSE, TRUE)
ENDIF
IF IS_DOOR_REGISTERED_WITH_SYSTEM(ENUM_TO_INT(DOORHASH_M_MANSION_F_R))
DOOR_SYSTEM_SET_OPEN_RATIO(ENUM_TO_INT(DOORHASH_M_MANSION_F_R), 0.0, FALSE, FALSE)
DOOR_SYSTEM_SET_DOOR_STATE(ENUM_TO_INT(DOORHASH_M_MANSION_F_R), DOORSTATE_FORCE_UNLOCKED_THIS_FRAME, FALSE, TRUE)
ENDIF
OBJECT_INDEX FlowerObjectIndex
FlowerObjectIndex = GET_CLOSEST_OBJECT_OF_TYPE(<< -818.88, 177.91, 76.63 >>, 0.75, PROP_WINDOWBOX_B, FALSE)
IF DOES_ENTITY_EXIST(FlowerObjectIndex)
IF NOT IS_ENTITY_DEAD(FlowerObjectIndex)
SET_ENTITY_VISIBLE(FlowerObjectIndex, FALSE)
SET_ENTITY_COLLISION(FlowerObjectIndex, FALSE)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Hiding world prop object PROP_WINDOWBOX_B.")
#ENDIF
ENDIF
ENDIF
//start uber recording playback when the cutscene ends
IF IS_VEHICLE_DRIVEABLE(vsCoachsCar.VehicleIndex)
SET_ENTITY_ONLY_DAMAGED_BY_PLAYER(vsCoachsCar.VehicleIndex, TRUE)
ENDIF
IF NOT IS_PED_INJURED(psCoach.PedIndex)
SET_ENTITY_ONLY_DAMAGED_BY_PLAYER(psCoach.PedIndex, TRUE)
SET_PED_CONFIG_FLAG(psCoach.PedIndex, PCF_WillFlyThroughWindscreen, FALSE)
SET_PED_CONFIG_FLAG(psCoach.PedIndex, PCF_GetOutBurningVehicle, FALSE)
SET_PED_CONFIG_FLAG(psCoach.PedIndex, PCF_GetOutUndriveableVehicle, FALSE)
ENDIF
INITIALISE_UBER_PLAYBACK(sVehicleRecordingsFile, vsCoachsCar.iRecordingNumber)
INITIALISE_UBER_ARRAY()
CREATE_ALL_WAITING_UBER_CARS()
#IF IS_DEBUG_BUILD
bTrafficDebugOn = TRUE
#ENDIF
fUberPlaybackDensitySwitchOffRange = 200.0
bPlayTrafficRecordingEvenIfPlayerIsAheadOfChase = TRUE
IF IS_VEHICLE_DRIVEABLE(vsCoachsCar.VehicleIndex)
START_VEHICLE_RECORDING_PLAYBACK_FOR_VEHICLE(vsCoachsCar, sVehicleRecordingsFile, fChaseSpeed, FALSE, 1500.0)
FORCE_PLAYBACK_RECORDED_VEHICLE_UPDATE(vsCoachsCar.VehicleIndex)
ENDIF
IF IS_VEHICLE_DRIVEABLE(vsPlayersCar.VehicleIndex)
SET_VEHICLE_CAN_SAVE_IN_GARAGE(vsPlayersCar.VehicleIndex, FALSE)
IF NOT IS_VEHICLE_EXTRA_TURNED_ON(vsPlayersCar.VehicleIndex, 5)
SET_VEHICLE_EXTRA(vsPlayersCar.VehicleIndex, 5, FALSE)
ENDIF
ENDIF
SET_VEHICLE_AS_RESTRICTED(vsPlayersCar.VehicleIndex, 0)
UPDATE_UBER_PLAYBACK(vsCoachsCar.VehicleIndex, 1.0)
IF IS_INTERIOR_READY(GET_INTERIOR_AT_COORDS(vInteriorPosition))
UNPIN_INTERIOR(GET_INTERIOR_AT_COORDS(vInteriorPosition))
ENDIF
SET_SCRIPTS_SAFE_FOR_CUTSCENE(FALSE)
IF ( bMusicEventMissionStartTriggered = FALSE )
IF TRIGGER_MUSIC_EVENT("FAM3_MISSION_START")
bMusicEventMissionStartTriggered = TRUE
ENDIF
ENDIF
STORE_PLAYER_PED_VARIATIONS(PLAYER_PED_ID(), TRUE)
STORE_PLAYER_PED_VARIATIONS(psFranklin.PedIndex, TRUE)
MISSION_FLOW_RELEASE_TRIGGER_SCENE_ASSETS(SP_MISSION_FAMILY_3)
IF IS_SCREEN_FADED_OUT()
DO_SCREEN_FADE_IN(DEFAULT_FADE_TIME)
ENDIF
RETURN TRUE
ELSE //if not all entities exits, make sure player peds are created in script if the cutscene did not create them
SWITCH GET_CURRENT_PLAYER_PED_ENUM()
CASE CHAR_MICHAEL
IF NOT DOES_ENTITY_EXIST(GET_PED_INDEX(CHAR_FRANKLIN))
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Creating Franklin ped when cutscene has finished.")
#ENDIF
IF HAS_MISSION_PED_BEEN_CREATED(psFranklin, TRUE, RELGROUPHASH_PLAYER, FALSE, CHAR_FRANKLIN)
SET_MISSION_PED_PROPERTIES(psFranklin.PedIndex, RELGROUPHASH_PLAYER, FALSE, TRUE, FALSE, FALSE)
sSelectorPeds.pedID[SELECTOR_PED_FRANKLIN] = psFranklin.PedIndex
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Set up properites for mission player ped Franklin created when intro cutscene has finished.")
#ENDIF
ENDIF
ENDIF
BREAK
CASE CHAR_FRANKLIN
IF NOT DOES_ENTITY_EXIST(GET_PED_INDEX(CHAR_MICHAEL))
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Creating Michael ped when cutscene has finished.")
#ENDIF
IF HAS_MISSION_PED_BEEN_CREATED(psMichael, TRUE, RELGROUPHASH_PLAYER, FALSE, CHAR_MICHAEL)
SET_MISSION_PED_PROPERTIES(psMichael.PedIndex, RELGROUPHASH_PLAYER, FALSE, TRUE, FALSE, FALSE)
sSelectorPeds.pedID[SELECTOR_PED_MICHAEL] = psMichael.PedIndex
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Set up properites for mission player ped Michael created when intro cutscene has finished.")
#ENDIF
ENDIF
ENDIF
BREAK
ENDSWITCH
//tennis coach
IF NOT DOES_ENTITY_EXIST(psCoach.PedIndex)
IF DOES_ENTITY_EXIST(vsCoachsCar.VehicleIndex)
IF HAS_MISSION_PED_BEEN_CREATED(psCoach, FALSE, rgTennisCoach, FALSE, NO_CHARACTER, FALSE, FALSE, FALSE, vsCoachsCar.VehicleIndex)
SET_PED_COMPONENT_VARIATION(psCoach.PedIndex, PED_COMP_TORSO, 1, 0)
SET_PED_COMPONENT_VARIATION(psCoach.PedIndex, PED_COMP_LEG, 1, 0)
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(psCoach.PedIndex, TRUE)
ENDIF
ENDIF
ENDIF
ENDIF
ELSE
//if cutscene is skipped, fade out and remain cutscene on faded out screen
IF ( bCutsceneSkipped = FALSE )
IF WAS_CUTSCENE_SKIPPED()
SET_CUTSCENE_FADE_VALUES(FALSE, FALSE, FALSE, FALSE)
bCutsceneSkipped = TRUE
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Intro mocap cutscene was skipped by the player.")
#ENDIF
ENDIF
ENDIF
ENDIF
//request assets for player vehicle
REQUEST_VEHICLE_ASSET(vsPlayersCar.ModelName, ENUM_TO_INT(VRF_REQUEST_ENTRY_ANIMS))
//request assets for uber recording
REQUEST_VEHICLE_RECORDING(vsCoachsCar.iRecordingNumber, sVehicleRecordingsFile)
BREAK
ENDSWITCH
RETURN FALSE
ENDFUNC
PROC RUN_RUBBER_BAND_BETWEEN_VEHICLES(VEHICLE_INDEX VehicleIndex, VEHICLE_INDEX VehicleIndexTarget, FLOAT &fPlaybackSpeed, FLOAT fOptimalDistance, FLOAT fMinSpeed = 0.5, FLOAT fMaxSpeed = 1.5)
FLOAT fSpeed
IF IS_VEHICLE_DRIVEABLE(VehicleIndex)
AND IS_VEHICLE_DRIVEABLE(VehicleIndexTarget)
IF IS_PLAYBACK_GOING_ON_FOR_VEHICLE(VehicleIndexTarget)
fSpeed = fOptimalDistance / GET_DISTANCE_BETWEEN_ENTITIES(VehicleIndex, VehicleIndexTarget)
IF ( fSpeed >= fMaxSpeed )
fSpeed = fMaxSpeed
ENDIF
IF ( fSpeed < fMinSpeed )
fSpeed = fMinSpeed
ENDIF
SET_PLAYBACK_SPEED(VehicleIndexTarget, fSpeed)
fPlaybackSpeed = fSpeed
ENDIF
ENDIF
ENDPROC
PROC CONVERGE_VALUE(FLOAT &val, FLOAT fDesiredVal, FLOAT fAmountToConverge, BOOL bAdjustForFramerate = FALSE)
IF val != fDesiredVal
FLOAT fConvergeAmountThisFrame = fAmountToConverge
IF bAdjustForFramerate
fConvergeAmountThisFrame = 0.0 +@ (fAmountToConverge * 30.0)
ENDIF
IF val - fDesiredVal > fConvergeAmountThisFrame
val -= fConvergeAmountThisFrame
ELIF val - fDesiredVal < -fConvergeAmountThisFrame
val += fConvergeAmountThisFrame
ELSE
val = fDesiredVal
ENDIF
ENDIF
ENDPROC
PROC RUBBER_BAND_PLAYBACK_SPEED_FOR_TRIGGER_VEHICLE(VEHICLE_INDEX TriggerVehicleIndex, VEHICLE_INDEX VehicleIndex,
FLOAT &fCurrentPlaybackSpeed, FLOAT &fCurrentPlaybackTime
#IF IS_DEBUG_BUILD, BOOL bPrintOutput = FALSE, STRING sTriggerVehicleDebugName = NULL,
STRING sVehicleDebugName = NULL #ENDIF)
IF IS_VEHICLE_DRIVEABLE(TriggerVehicleIndex)
AND IS_VEHICLE_DRIVEABLE(VehicleIndex)
VECTOR vTriggerVehiclePosition = GET_ENTITY_COORDS(TriggerVehicleIndex)
VECTOR vVehiclePosition = GET_ENTITY_COORDS(VehicleIndex)
FLOAT fDistance = GET_DISTANCE_BETWEEN_COORDS(vTriggerVehiclePosition, vVehiclePosition)
FLOAT fCloseDistance = 15.0
FLOAT fIdealDistance = 30.0
FLOAT fMaxDistance = 45.0
FLOAT fSuperMaxDistance = 75.0
FLOAT fDesiredPlaybackSpeed = 1.0
FLOAT fPlaybackTime
IF IS_PLAYBACK_GOING_ON_FOR_VEHICLE(TriggerVehicleIndex)
fPlaybackTime = GET_TIME_POSITION_IN_RECORDING(TriggerVehicleIndex)
fCurrentPlaybackTime = fPlaybackTime
ENDIF
VECTOR vOffset = GET_OFFSET_FROM_ENTITY_GIVEN_WORLD_COORDS(TriggerVehicleIndex, vVehiclePosition)
IF ( vOffset.y > 1.0 ) //trigger vehicle is behind the vehicle, need to increase recording playback speed
#IF IS_DEBUG_BUILD
IF ( bPrintOutput = TRUE )
PRINTLN(GET_THIS_SCRIPT_NAME(), ": ", sTriggerVehicleDebugName, " vehicle is behind ", sVehicleDebugName, " vehicle.")
ENDIF
#ENDIF
IF ( fDistance > fSuperMaxDistance )
fDesiredPlaybackSpeed = 5.0
ELIF ( fDistance > fMaxDistance )
fDesiredPlaybackSpeed = 4.0
ELIF ( fDistance > fIdealDistance )
fDesiredPlaybackSpeed = 3.0
ELSE
fDesiredPlaybackSpeed = 2.5
ENDIF
ELSE //trigger vehicle is front of the vehicle, lower recording playback speed when needed
#IF IS_DEBUG_BUILD
IF ( bPrintOutput = TRUE )
PRINTLN(GET_THIS_SCRIPT_NAME(), ": ", sTriggerVehicleDebugName, " vehicle is in front of ", sVehicleDebugName, " vehicle.")
ENDIF
#ENDIF
IF ( fDistance > fSuperMaxDistance )
fDesiredPlaybackSpeed = 0.6
ELIF ( fDistance > fMaxDistance )
fDesiredPlaybackSpeed = 1.05
ELIF ( fDistance > fIdealDistance )
fDesiredPlaybackSpeed = 1.225
ELIF ( fDistance > fCloseDistance )
fDesiredPlaybackSpeed = 1.385
ELSE
fDesiredPlaybackSpeed = 1.45
ENDIF
ENDIF
IF ( fPlaybackTime < 26000.0 ) //when the player is going through the park, increase the playback speed
IF IS_ENTITY_AT_COORD(VehicleIndex, << -948.42, 399.24, 76.69 >>, << 118.0, 112.0, 16.0 >>)
OR IS_ENTITY_IN_ANGLED_AREA(VehicleIndex, << -1002.70, 306.26, 65.30 >>, << -886.05, 263.07, 89.96 >>, 32.0)
//check speed difference between trigger vehicle and player vehicle
FLOAT fSpeedDifference = GET_ENTITY_SPEED(TriggerVehicleIndex) - GET_ENTITY_SPEED(VehicleIndex)
FLOAT fExtraBoost
//if the trigger vehicle is slower then add extra boost
IF fSpeedDifference < 0.0
fExtraBoost = 0.125
ENDIF
fDesiredPlaybackSpeed = 1.275 + fExtraBoost
ELSE
IF ( fPlaybackTime > 19000.0 )
fDesiredPlaybackSpeed = fDesiredPlaybackSpeed + 0.3
ENDIF
ENDIF
ENDIF
IF ( fPlaybackTime > 27000.0 ) //when the coach is on the road up the hill after making the turn left
fDesiredPlaybackSpeed = fDesiredPlaybackSpeed + 0.35
ENDIF
CONVERGE_VALUE(fCurrentPlaybackSpeed, fDesiredPlaybackSpeed, 0.01, TRUE)
#IF IS_DEBUG_BUILD
IF ( bDrawDebugLinesAndSpheres = TRUE )
DRAW_DEBUG_TEXT_ABOVE_ENTITY(TriggerVehicleIndex, GET_STRING_FROM_FLOAT(fPlaybackTime), 1.5)
DRAW_DEBUG_TEXT_ABOVE_ENTITY(TriggerVehicleIndex, GET_STRING_FROM_FLOAT(fDistance), 2.5)
DRAW_DEBUG_TEXT_ABOVE_ENTITY(TriggerVehicleIndex, GET_STRING_FROM_FLOAT(fCurrentPlaybackSpeed), 3.5)
ENDIF
#ENDIF
ENDIF
ENDPROC
PROC MANAGE_SET_PIECE_VAN(INT &iProgress)
FLOAT fPlaybackTime
FLOAT fVanPlaybackSpeed
//check for player horn and van driver horn
IF ( bVanDriverCrashSpeechTriggered = FALSE )
IF DOES_ENTITY_EXIST(vsVan.VehicleIndex)
AND DOES_ENTITY_EXIST(psVanDriver.PedIndex)
IF IS_VEHICLE_DRIVEABLE(vsVan.VehicleIndex)
AND IS_VEHICLE_DRIVEABLE(vsPlayersCar.VehicleIndex)
IF IS_PLAYBACK_GOING_ON_FOR_VEHICLE(vsVan.VehicleIndex)
OR IS_PLAYBACK_USING_AI_GOING_ON_FOR_VEHICLE(vsVan.VehicleIndex)
IF IS_ENTITY_AT_ENTITY(vsPlayersCar.VehicleIndex, vsVan.VehicleIndex, vVanLocateSize)
IF IS_PLAYER_PLAYING(PLAYER_ID())
IF IS_PLAYER_PRESSING_HORN(PLAYER_ID())
//play ped ambient speech on player using the horn
IF NOT IS_PED_INJURED(psVanDriver.PedIndex)
IF NOT IS_AMBIENT_SPEECH_PLAYING(psVanDriver.PedIndex)
PLAY_PED_AMBIENT_SPEECH(psVanDriver.PedIndex, "GENERIC_INSULT_HIGH", SPEECH_PARAMS_FORCE)
ENDIF
//also start a horn
START_VEHICLE_HORN(vsVan.VehicleIndex, 3000)
bVanDriverCrashSpeechTriggered = TRUE
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
#IF IS_DEBUG_BUILD
IF ( bDrawDebugLinesAndSpheres = TRUE )
DRAW_DEBUG_TEXT_ABOVE_ENTITY(vsVan.VehicleIndex, GET_STRING_FROM_INT(vsVan.iProgress), 1.75)
DRAW_DEBUG_TEXT_ABOVE_ENTITY(vsVan.VehicleIndex, GET_STRING_FROM_INT(psVanDriver.iProgress), 1.5)
ENDIF
#ENDIF
SWITCH iProgress
CASE 0 //request the models and vehicle recording, create vehicle and driver
IF ( bChaseInProgress = TRUE )
REQUEST_MODEL(vsVan.ModelName)
REQUEST_MODEL(psVanDriver.ModelName)
REQUEST_VEHICLE_RECORDING(vsVan.iRecordingNumber, sVehicleRecordingsFile)
IF HAS_MODEL_LOADED(vsVan.ModelName)
AND HAS_MODEL_LOADED(psVanDriver.ModelName)
AND HAS_VEHICLE_RECORDING_BEEN_LOADED(vsVan.iRecordingNumber, sVehicleRecordingsFile)
IF HAS_MISSION_VEHICLE_BEEN_CREATED(vsVan, FALSE, FALSE, NO_CHARACTER, FALSE, -1, 62, 131)
IF HAS_MISSION_PED_BEEN_CREATED(psVanDriver, FALSE, rgEnemies, FALSE, NO_CHARACTER, TRUE, TRUE, FALSE, vsVan.VehicleIndex, VS_DRIVER, FALSE)
IF NOT IS_PED_INJURED(psVanDriver.PedIndex)
SET_PED_COMBAT_ATTRIBUTES(psVanDriver.PedIndex, CA_CAN_TAUNT_IN_VEHICLE, TRUE)
//ADD_PED_FOR_DIALOGUE(sFamily3Conversation, 5, psVanDriver.PedIndex, "FAM3DRIVER")
ENDIF
SET_MODEL_AS_NO_LONGER_NEEDED(vsVan.ModelName)
SET_MODEL_AS_NO_LONGER_NEEDED(psVanDriver.ModelName)
iProgress++
ENDIF
ENDIF
ENDIF
ENDIF
BREAK
CASE 1 //wait until it is time to start playback of vehicle recording, then start the playback
IF ( bChaseInProgress = TRUE )
IF IS_ENTITY_AT_COORD(vsPlayersCar.VehicleIndex, << -1355.5088, 469.1981, 102.2932 >>, << 200, 200, 200 >>)
IF IS_VEHICLE_DRIVEABLE(vsCoachsCar.VehicleIndex)
IF IS_PLAYBACK_GOING_ON_FOR_VEHICLE(vsCoachsCar.VehicleIndex)
IF GET_TIME_POSITION_IN_RECORDING(vsCoachsCar.VehicleIndex) >= 45750.0
IF NOT IS_PED_INJURED(psVanDriver.PedIndex)
AND IS_VEHICLE_DRIVEABLE(vsVan.VehicleIndex)
START_VEHICLE_RECORDING_PLAYBACK_FOR_VEHICLE(vsVan, sVehicleRecordingsFile, 1.1, FALSE, 800.0, FALSE, TRUE)
START_AUDIO_SCENE("FAMILY_3_RV_BLOCKS_ROAD")
ADD_ENTITY_TO_AUDIO_MIX_GROUP(vsVan.VehicleIndex, "FAMILY_3_RV")
psVanDriver.iProgress = 0
iProgress++
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ELSE
IF DOES_ENTITY_EXIST(psVanDriver.PedIndex)
SET_PED_AS_NO_LONGER_NEEDED(psVanDriver.PedIndex)
ENDIF
IF DOES_ENTITY_EXIST(vsVan.VehicleIndex)
SET_VEHICLE_AS_NO_LONGER_NEEDED(vsVan.VehicleIndex)
ENDIF
iProgress++
ENDIF
BREAK
CASE 2 //keep updating the van recording playback based on the distance from the player car
IF IS_VEHICLE_DRIVEABLE(vsVan.VehicleIndex)
AND NOT IS_PED_INJURED(psVanDriver.PedIndex)
SWITCH psVanDriver.iProgress
CASE 0 //recording playback
IF IS_PLAYBACK_GOING_ON_FOR_VEHICLE(vsVan.VehicleIndex)
fPlaybackTime = GET_TIME_POSITION_IN_RECORDING(vsVan.VehicleIndex)
#IF IS_DEBUG_BUILD
IF ( bDrawDebugLinesAndSpheres = TRUE )
DRAW_DEBUG_TEXT_ABOVE_ENTITY(vsVan.VehicleIndex, GET_STRING_FROM_FLOAT(fPlaybackTime), 1.25)
ENDIF
#ENDIF
//check collision with player's truck
IF IS_ENTITY_TOUCHING_ENTITY(vsVan.VehicleIndex, vsPlayersCar.VehicleIndex)
REPLAY_RECORD_BACK_FOR_TIME(3, 0, REPLAY_IMPORTANCE_HIGH)
STOP_PLAYBACK_RECORDED_VEHICLE(vsVan.VehicleIndex)
START_PLAYBACK_RECORDED_VEHICLE_USING_AI(vsVan.VehicleIndex, vsVan.iRecordingNumber, sVehicleRecordingsFile, 5, DRIVINGMODE_STOPFORCARS)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Set piece van is now playing vehicle recording using AI due to collision with player vehicle.")
#ENDIF
psVanDriver.iProgress = 1
ENDIF
//check when to stop rubber banding
IF ( fPlaybackTime < 8510.0)
RUN_RUBBER_BAND_BETWEEN_VEHICLES(vsPlayersCar.VehicleIndex, vsVan.VehicleIndex, fVanPlaybackSpeed, 50.0, 1.05, 1.55)
ENDIF
//check when to switch to recording playback using AI
IF ( fPlaybackTime > 10085.0 )
STOP_PLAYBACK_RECORDED_VEHICLE(vsVan.VehicleIndex)
START_PLAYBACK_RECORDED_VEHICLE_USING_AI(vsVan.VehicleIndex, vsVan.iRecordingNumber, sVehicleRecordingsFile, 5, DRIVINGMODE_AVOIDCARS)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Set piece van is now playing vehicle recording using AI due to reaching recording playback target time.")
#ENDIF
psVanDriver.iProgress = 1
ENDIF
ENDIF
BREAK
CASE 1 //recording playback using AI, no player vehicle collision
IF NOT IS_PLAYBACK_USING_AI_GOING_ON_FOR_VEHICLE(vsVan.VehicleIndex)
TASK_VEHICLE_DRIVE_WANDER(psVanDriver.PedIndex, vsVan.VehicleIndex, 15.0, DRIVINGMODE_AVOIDCARS)
psVanDriver.iProgress = 2
ENDIF
BREAK
CASE 2
IF NOT IS_ENTITY_AT_ENTITY(PLAYER_PED_ID(), vsVan.VehicleIndex, vVanLocateSize)
STOP_AUDIO_SCENE("FAMILY_3_RV_BLOCKS_ROAD")
IF IS_VEHICLE_DRIVEABLE(vsVan.VehicleIndex)
SET_VEHICLE_AS_NO_LONGER_NEEDED(vsVan.VehicleIndex)
ENDIF
IF NOT IS_PED_INJURED(psVanDriver.PedIndex)
SET_PED_AS_NO_LONGER_NEEDED(psVanDriver.PedIndex)
ENDIF
REMOVE_VEHICLE_RECORDING(vsVan.iRecordingNumber, sVehicleRecordingsFile)
ENDIF
BREAK
ENDSWITCH
ENDIF
BREAK
ENDSWITCH
ENDPROC
FUNC BOOL IS_CHASE_REMINDER_NEEDED(FLOAT fChaseDistance, FLOAT fWarningDistance)
IF ( fChaseDistance > fWarningDistance)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": IS_CHASE_REMINDER_NEEDED() returning TRUE.")
#ENDIF
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
PROC MANAGE_CONVERSATIONS_DURING_CHASE(STRING sMainConversationRootLabel)
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
AND NOT IS_PED_INJURED(psFranklin.PedIndex)
AND IS_VEHICLE_DRIVEABLE(vsPlayersCar.VehicleIndex)
IF ( bChaseInProgress = TRUE )
IF ( bRandomConversationAllowed = FALSE )
//handle "FAM3_WARN" conversation when tennis coach is about to get away
IF IS_CHASE_REMINDER_NEEDED(fChaseDistanceFromPlayerToCoach, 175.0)
IF ( bConversationPaused = FALSE )
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
lConversationLabel = GET_STANDARD_CONVERSATION_LABEL_FOR_FUTURE_RESUMPTION()
KILL_FACE_TO_FACE_CONVERSATION_DO_NOT_FINISH_LAST_LINE()
ENDIF
IF NOT IS_ANY_TEXT_BEING_DISPLAYED(sLocatesData)
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_WARN", CONV_PRIORITY_VERY_HIGH)
bConversationPaused = TRUE
ENDIF
ENDIF
ENDIF
ELSE
IF NOT HAS_LABEL_BEEN_TRIGGERED(sMainConversationRootLabel)
IF IS_PED_SITTING_IN_VEHICLE(psFranklin.PedIndex, vsPlayersCar.VehicleIndex)
AND IS_PED_SITTING_IN_VEHICLE(PLAYER_PED_ID(), vsPlayersCar.VehicleIndex)
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF NOT IS_ANY_TEXT_BEING_DISPLAYED(sLocatesData, IAT_IGNORE_GOD_TEXT_IF_SUBTITLES_OFF)
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", sMainConversationRootLabel, CONV_PRIORITY_MEDIUM)
bAllowConvsersationOutsideOfCar = FALSE
SET_LABEL_AS_TRIGGERED(sMainConversationRootLabel, TRUE)
ENDIF
ENDIF
ENDIF
ENDIF
ELSE
IF ( bConversationPaused = TRUE )
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF CREATE_CONVERSATION_FROM_SPECIFIC_LINE(sFamily3Conversation, "FAM3AUD", sMainConversationRootLabel, lConversationLabel, CONV_PRIORITY_MEDIUM)
bConversationPaused = FALSE
ENDIF
ENDIF
ELIF ( bConversationPaused = FALSE )
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
psFranklin.iConversationTimer = GET_GAME_TIMER() //reset Franklin's timer for random dialogue
bRandomConversationAllowed = TRUE
ENDIF
ENDIF
ENDIF
ENDIF
ELSE //allow random conversations
//Franklin sees tennis coach seen turing left or right (is player is trying to cut through the park)
IF NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_LEFT")
AND NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_RIGHT")
IF ( fChaseTime > 30725.0 AND fChaseTime < 33500.0)
IF IS_PED_SITTING_IN_VEHICLE(psFranklin.PedIndex, vsPlayersCar.VehicleIndex)
AND IS_PED_SITTING_IN_VEHICLE(PLAYER_PED_ID(), vsPlayersCar.VehicleIndex)
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF NOT IS_ANY_TEXT_BEING_DISPLAYED(sLocatesData, IAT_IGNORE_GOD_TEXT_IF_SUBTITLES_OFF)
IF ( bCoachVisible = TRUE )
IF ( fChaseDistanceFromPlayerToCoach < 75.0 )
IF IS_ENTITY_IN_ANGLED_AREA(vsPlayersCar.VehicleIndex, <<-1076.606445,431.189056,63.721909>>, <<-1077.557373,345.405121,78.379799>>, 24.0)
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_LEFT", CONV_PRIORITY_MEDIUM)
SET_LABEL_AS_TRIGGERED("FAM3_LEFT", TRUE)
psFranklin.iConversationTimer = GET_GAME_TIMER()
ENDIF
ELIF IS_ENTITY_IN_ANGLED_AREA(vsPlayersCar.VehicleIndex, <<-1019.407349,397.151489,62.308754>>, <<-1064.459839,394.310486,79.967346>>, 24.0)
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_RIGHT", CONV_PRIORITY_MEDIUM)
SET_LABEL_AS_TRIGGERED("FAM3_RIGHT", TRUE)
psFranklin.iConversationTimer = GET_GAME_TIMER()
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
IF bStopRandomChaseConversations = FALSE
IF IS_PED_SITTING_IN_THIS_VEHICLE(PLAYER_PED_ID(), vsPlayersCar.VehicleIndex)
IF IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<-1288.665894,459.231873,94.684250>>, <<-1392.720093,466.896729,113.118851>>, 32.0)
IF DOES_ENTITY_EXIST(vsVan.VehicleIndex) AND NOT IS_ENTITY_DEAD(vsVan.VehicleIndex)
IF IS_PLAYBACK_GOING_ON_FOR_VEHICLE(vsVan.VehicleIndex) AND NOT IS_PLAYBACK_USING_AI_GOING_ON_FOR_VEHICLE(vsVan.VehicleIndex)
IF GET_TIME_POSITION_IN_RECORDING(vsVan.VehicleIndex) < 8350.0
KILL_FACE_TO_FACE_CONVERSATION()
bStopRandomChaseConversations = TRUE
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
IF bStopRandomChaseConversations = FALSE
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF NOT IS_ANY_TEXT_BEING_DISPLAYED(sLocatesData, IAT_IGNORE_GOD_TEXT_IF_SUBTITLES_OFF)
IF HAS_TIME_PASSED(10000, psFranklin.iConversationTimer)
IF IS_PED_SITTING_IN_VEHICLE(psFranklin.PedIndex, vsPlayersCar.VehicleIndex)
AND IS_PED_SITTING_IN_VEHICLE(PLAYER_PED_ID(), vsPlayersCar.VehicleIndex)
//player far, coach is getting away
IF fChaseDistanceFromPlayerToCoach > 185.0
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_WARN", CONV_PRIORITY_MEDIUM)
psFranklin.iConversationTimer = GET_GAME_TIMER()
ENDIF
ELIF fChaseDistanceFromPlayerToCoach > 150.0
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_LOSE", CONV_PRIORITY_MEDIUM)
psFranklin.iConversationTimer = GET_GAME_TIMER()
ENDIF
//player close to coach
ELIF fChaseDistanceFromPlayerToCoach < 75.0
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_SEE", CONV_PRIORITY_MEDIUM)
psFranklin.iConversationTimer = GET_GAME_TIMER()
ENDIF
ELSE
IF ( bCoachVisible = TRUE )
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_AHEAD", CONV_PRIORITY_MEDIUM)
psFranklin.iConversationTimer = GET_GAME_TIMER()
ENDIF
ELIF ( bCoachVisible = FALSE )
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_LOSE", CONV_PRIORITY_MEDIUM)
psFranklin.iConversationTimer = GET_GAME_TIMER()
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
IF bStopRandomChaseConversations = TRUE
IF bStartPreloadingVanConversation = FALSE
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
PRELOAD_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_VAN", CONV_PRIORITY_MEDIUM)
bStartPreloadingVanConversation = TRUE
ENDIF
ENDIF
ENDIF
ENDIF
ELSE
IF ( bChaseFinished = TRUE )
//play van blocking the road conversations
IF eChaseFinishReason = CHASE_FINISHED_END_REACHED
IF NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_VAN")
AND NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_LOST")
IF DOES_ENTITY_EXIST(vsVan.VehicleIndex)
IF NOT IS_ENTITY_DEAD(vsVan.VehicleIndex)
IF IS_ENTITY_AT_ENTITY(vsPlayersCar.VehicleIndex, vsVan.VehicleIndex, vVanLocateSize)
//check if the blocking van is actually still blocking the road in the recording
//and not driving forward using recording playback with AI
IF IS_PLAYBACK_GOING_ON_FOR_VEHICLE(vsVan.VehicleIndex)
AND NOT IS_PLAYBACK_USING_AI_GOING_ON_FOR_VEHICLE(vsVan.VehicleIndex)
//IF ( GET_VEHICLE_RECORDING_PLAYBACK_PERCENTAGE(vsVan.VehicleIndex #IF IS_DEBUG_BUILD, bPrintDebugOutput #ENDIF) < 59.25 )
IF GET_TIME_POSITION_IN_RECORDING(vsVan.VehicleIndex) < 8350.0
IF IS_PED_SITTING_IN_VEHICLE(psFranklin.PedIndex, vsPlayersCar.VehicleIndex)
AND IS_PED_SITTING_IN_VEHICLE(PLAYER_PED_ID(), vsPlayersCar.VehicleIndex)
IF bStartPreloadingVanConversation = FALSE
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF NOT IS_ANY_TEXT_BEING_DISPLAYED(sLocatesData, IAT_IGNORE_GOD_TEXT_IF_SUBTITLES_OFF)
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_VAN", CONV_PRIORITY_MEDIUM)
bRandomConversationAllowed = FALSE
SET_LABEL_AS_TRIGGERED("FAM3_VAN", TRUE)
ENDIF
ENDIF
ELSE
KILL_FACE_TO_FACE_CONVERSATION_DO_NOT_FINISH_LAST_LINE()
ENDIF
ELSE
BEGIN_PRELOADED_CONVERSATION()
bRandomConversationAllowed = FALSE
SET_LABEL_AS_TRIGGERED("FAM3_VAN", TRUE)
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
//play van collision conversation
IF eChaseFinishReason = CHASE_FINISHED_END_REACHED
IF NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_VANM2")
AND NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_LOST")
IF ( bPlayerCrashedIntoVan = FALSE )
IF DOES_ENTITY_EXIST(vsVan.VehicleIndex)
AND DOES_ENTITY_EXIST(psVanDriver.PedIndex)
IF IS_VEHICLE_DRIVEABLE(vsVan.VehicleIndex)
AND NOT IS_PED_INJURED(psVanDriver.PedIndex)
IF IS_ENTITY_TOUCHING_ENTITY(vsVan.VehicleIndex, vsPlayersCar.VehicleIndex)
//disable phone conversation immediately upon collision
IF IS_PHONE_ONSCREEN()
HANG_UP_AND_PUT_AWAY_PHONE(TRUE)
ENDIF
IF ( bVanDriverCrashSpeechTriggered = FALSE )
//play ped ambient speech and use vehicle horn on player crashing
IF NOT IS_PED_INJURED(psVanDriver.PedIndex)
PLAY_PED_AMBIENT_SPEECH(psVanDriver.PedIndex, "GENERIC_CURSE_HIGH", SPEECH_PARAMS_FORCE)
//also start a horn
START_VEHICLE_HORN(vsVan.VehicleIndex, 5000)
bVanDriverCrashSpeechTriggered = TRUE
ENDIF
ENDIF
IF ( bConversationPaused = FALSE )
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
//IF ( bAllowConvsersationOutsideOfCar = FALSE )
//lConversationLabel = GET_STANDARD_CONVERSATION_LABEL_FOR_FUTURE_RESUMPTION()
//KILL_FACE_TO_FACE_CONVERSATION_DO_NOT_FINISH_LAST_LINE()
//ELSE
KILL_FACE_TO_FACE_CONVERSATION_DO_NOT_FINISH_LAST_LINE()
bAllowConvsersationOutsideOfCar = FALSE
//ENDIF
ENDIF
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_VANM2", CONV_PRIORITY_HIGH)
bPlayerCrashedIntoVan = TRUE
SET_LABEL_AS_TRIGGERED("FAM3_VANM2", TRUE)
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
//play 'I think we lost him' conversation
IF NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_LOST")
IF ( bStartPreloadingVanConversation = TRUE )
IF NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_VAN")
KILL_FACE_TO_FACE_CONVERSATION()
ENDIF
ENDIF
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF NOT IS_ANY_TEXT_BEING_DISPLAYED(sLocatesData, IAT_IGNORE_GOD_TEXT_IF_SUBTITLES_OFF)
IF IS_PED_SITTING_IN_VEHICLE(psFranklin.PedIndex, vsPlayersCar.VehicleIndex)
AND IS_PED_SITTING_IN_VEHICLE(PLAYER_PED_ID(), vsPlayersCar.VehicleIndex)
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_LOST", CONV_PRIORITY_VERY_HIGH)
REPLAY_RECORD_BACK_FOR_TIME(3.0, 3.0)
SET_LABEL_AS_TRIGGERED("FAM3_LOST", TRUE)
psFranklin.iConversationTimer = GET_GAME_TIMER()
ENDIF
ENDIF
ENDIF
ENDIF
ELSE
//player gets close to the canyon turn
IF NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_TURN")
IF DOES_BLIP_EXIST(sLocatesData.LocationBlip)
IF IS_ENTITY_AT_COORD(vsPlayersCar.VehicleIndex, <<-1195.872559,706.979980,149.748108>>, <<34.0,34.0,7.0>>)
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF NOT IS_ANY_TEXT_BEING_DISPLAYED(sLocatesData, IAT_IGNORE_GOD_TEXT_IF_SUBTITLES_OFF)
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_TURN", CONV_PRIORITY_MEDIUM)
SET_LABEL_AS_TRIGGERED("FAM3_LOOK", TRUE) //make sure the "FAM3_LOOK" random dialogue does not play anymore
SET_LABEL_AS_TRIGGERED("FAM3_TURN", TRUE)
ENDIF
ENDIF
ELSE
KILL_FACE_TO_FACE_CONVERSATION()
ENDIF
ENDIF
ENDIF
ENDIF
//player drives onto canynon road
IF NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_FIND")
IF DOES_BLIP_EXIST(sLocatesData.LocationBlip)
IF IS_ENTITY_AT_COORD(vsPlayersCar.VehicleIndex, <<-1183.073120,704.413208,150.805725>>, <<16.0, 16.0, 7.0>>)
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF NOT IS_ANY_TEXT_BEING_DISPLAYED(sLocatesData, IAT_IGNORE_GOD_TEXT_IF_SUBTITLES_OFF)
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_FIND", CONV_PRIORITY_MEDIUM)
SET_LABEL_AS_TRIGGERED("FAM3_LOOK", TRUE) //make sure the "FAM3_LOOK" random dialogue does not play anymore
SET_LABEL_AS_TRIGGERED("FAM3_TURN", TRUE) //make sure the "FAM3_TURN" random dialogue does not play anymore
SET_LABEL_AS_TRIGGERED("FAM3_FIND", TRUE)
ENDIF
ENDIF
ELSE
KILL_FACE_TO_FACE_CONVERSATION()
ENDIF
ENDIF
ENDIF
ENDIF
IF NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_CAR")
IF HAS_LABEL_BEEN_TRIGGERED("FAM3_FIND")
IF DOES_BLIP_EXIST(sLocatesData.LocationBlip)
IF ( bCoachVisible = TRUE )
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF NOT IS_ANY_TEXT_BEING_DISPLAYED(sLocatesData, IAT_IGNORE_GOD_TEXT_IF_SUBTITLES_OFF)
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_CAR", CONV_PRIORITY_MEDIUM)
SET_LABEL_AS_TRIGGERED("FAM3_CAR", TRUE)
ENDIF
ENDIF
ELSE
KILL_FACE_TO_FACE_CONVERSATION()
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
//Michael's random dialogue for looking out for coach as player drives to the canyon
IF NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_LOOK")
IF ( eChaseFinishReason = CHASE_FINISHED_END_REACHED )
IF DOES_BLIP_EXIST(sLocatesData.LocationBlip) //locates blip has to exists
IF HAS_LABEL_BEEN_TRIGGERED(sLabelDCAN) OR IS_STRING_NULL_OR_EMPTY(sLabelDCAN) //and objective was displayed
IF HAS_TIME_PASSED(8000, psFranklin.iConversationTimer) //use Franklin's timer to trigger random dialogue
IF GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), vUnderBalconyPosition) < 425.0
IF NOT IS_VEHICLE_STOPPED(vsPlayersCar.VehicleIndex)
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF NOT IS_ANY_TEXT_BEING_DISPLAYED(sLocatesData, IAT_IGNORE_GOD_TEXT_IF_SUBTITLES_OFF)
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_LOOK", CONV_PRIORITY_MEDIUM)
iRandomLinesTriggered++
psFranklin.iConversationTimer = GET_GAME_TIMER()
ENDIF
IF ( iRandomLinesTriggered = 1 )
SET_LABEL_AS_TRIGGERED("FAM3_LOOK", TRUE) //just play one variation of these lines
ENDIF
ELSE
IF NOT IS_AMBIENT_SPEECH_PLAYING(PLAYER_PED_ID())
PLAY_PED_AMBIENT_SPEECH_WITH_VOICE(PLAYER_PED_ID(), "FAM3_AIAA", "MICHAEL", SPEECH_PARAMS_FORCE_NORMAL)
SET_LABEL_AS_TRIGGERED("FAM3_LOOK", TRUE)
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
//Michael and Franklin spot the tennis coach
IF NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_SPOT")
IF DOES_BLIP_EXIST(sLocatesData.LocationBlip)
IF ( bCoachSpotted = TRUE )
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF NOT IS_ANY_TEXT_BEING_DISPLAYED(sLocatesData, IAT_IGNORE_GOD_TEXT_IF_SUBTITLES_OFF)
//IF PLAY_SINGLE_LINE_FROM_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_SPOT", "FAM3_SPOT_1", CONV_PRIORITY_MEDIUM)
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_SPOT", CONV_PRIORITY_MEDIUM)
SET_LABEL_AS_TRIGGERED("FAM3_SPOT", TRUE)
ENDIF
ENDIF
ELSE
KILL_FACE_TO_FACE_CONVERSATION()
ENDIF
ELSE
IF ( bMichaelStartedShouting = TRUE )
SET_LABEL_AS_TRIGGERED("FAM3_SPOT", TRUE)
ENDIF
ENDIF
ENDIF
ELSE
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
bSpotConversationFinished = TRUE
ENDIF
ENDIF
//Michael shouts from the car to the tennis coach on the balcony
IF NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_BALC")
IF DOES_BLIP_EXIST(sLocatesData.LocationBlip)
IF ( bMichaelStartedShouting = TRUE )
IF IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(), "missfam3", "shout_out_window_michael")
AND GET_ENTITY_ANIM_CURRENT_TIME(PLAYER_PED_ID(), "missfam3", "shout_out_window_michael") > 0.05
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF NOT IS_ANY_TEXT_BEING_DISPLAYED(sLocatesData, IAT_IGNORE_GOD_TEXT_IF_SUBTITLES_OFF)
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_BALC", CONV_PRIORITY_MEDIUM)
SET_LABEL_AS_TRIGGERED("FAM3_BALC", TRUE)
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
//Michael's random line after the mini cutscene with coach on balcony
IF NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_BALCR")
IF HAS_LABEL_BEEN_TRIGGERED("FAM3_BALC") //play if after the preceding conversation
IF DOES_BLIP_EXIST(sLocatesData.LocationBlip)
IF ( bMichaelStartedShouting = TRUE AND bRecordingPlaybackStarted = TRUE )
IF NOT IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(), "missfam3", "shout_out_window_michael")
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF NOT IS_ANY_TEXT_BEING_DISPLAYED(sLocatesData, IAT_IGNORE_GOD_TEXT_IF_SUBTITLES_OFF)
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_BALCR", CONV_PRIORITY_MEDIUM)
SET_LABEL_AS_TRIGGERED("FAM3_BALCR", TRUE)
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
IF eChaseFinishReason = CHASE_FINISHED_TARGET_LOST
IF HAS_LABEL_BEEN_TRIGGERED(sMainConversationRootLabel)
IF NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_MST2")
AND NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_FST2")
IF DOES_BLIP_EXIST(sLocatesData.LocationBlip)
IF NOT IS_ANY_TEXT_BEING_DISPLAYED(sLocatesData, IAT_IGNORE_GOD_TEXT_IF_SUBTITLES_OFF)
IF ARE_STRINGS_EQUAL(sMainConversationRootLabel, "FAM3_MST1")
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_MST2", CONV_PRIORITY_MEDIUM)
SET_LABEL_AS_TRIGGERED("FAM3_MST2", TRUE)
ENDIF
ENDIF
IF ARE_STRINGS_EQUAL(sMainConversationRootLabel, "FAM3_FST1")
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_FST2", CONV_PRIORITY_MEDIUM)
SET_LABEL_AS_TRIGGERED("FAM3_FST2", TRUE)
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDPROC
PROC MANAGE_TENNIS_COACH_IN_CHASE(INT &iProgress)
SEQUENCE_INDEX PedSequence
SWITCH iProgress
CASE 0
IF IS_VEHICLE_DRIVEABLE(vsCoachsCar.VehicleIndex) //start uber recording playback if it is not going on
IF NOT IS_PLAYBACK_GOING_ON_FOR_VEHICLE(vsCoachsCar.VehicleIndex) //after intro cutscene or stage replay
SET_ENTITY_ONLY_DAMAGED_BY_PLAYER(vsCoachsCar.VehicleIndex, TRUE)
IF NOT IS_PED_INJURED(psCoach.PedIndex)
SET_ENTITY_VISIBLE(psCoach.PedIndex, TRUE)
SET_ENTITY_ONLY_DAMAGED_BY_PLAYER(psCoach.PedIndex, TRUE)
SET_PED_CONFIG_FLAG(psCoach.PedIndex, PCF_WillFlyThroughWindscreen, FALSE)
SET_PED_CONFIG_FLAG(psCoach.PedIndex, PCF_GetOutBurningVehicle, FALSE)
SET_PED_CONFIG_FLAG(psCoach.PedIndex, PCF_GetOutUndriveableVehicle, FALSE)
ENDIF
INITIALISE_UBER_PLAYBACK(sVehicleRecordingsFile, vsCoachsCar.iRecordingNumber)
INITIALISE_UBER_ARRAY()
CREATE_ALL_WAITING_UBER_CARS()
#IF IS_DEBUG_BUILD
bTrafficDebugOn = TRUE
#ENDIF
fUberPlaybackDensitySwitchOffRange = 200.0
bPlayTrafficRecordingEvenIfPlayerIsAheadOfChase = TRUE
START_VEHICLE_RECORDING_PLAYBACK_FOR_VEHICLE(vsCoachsCar, sVehicleRecordingsFile, fChaseSpeed, FALSE, 1500.0)
FORCE_PLAYBACK_RECORDED_VEHICLE_UPDATE(vsCoachsCar.VehicleIndex)
UPDATE_UBER_PLAYBACK(vsCoachsCar.VehicleIndex, 1.0)
ENDIF
ADD_ENTITY_TO_AUDIO_MIX_GROUP(vsCoachsCar.VehicleIndex, "FAMILY_3_TENNIS_COACH_GROUP")
ENDIF
TRIGGER_MUSIC_EVENT("FAM3_CHASE_START")
bChaseInProgress = TRUE
iProgress++
BREAK
CASE 1 //if the player reaches the van blocking the way, end the uber chase and speed up the coach
IF ( bChaseInProgress = TRUE )
IF IS_VEHICLE_DRIVEABLE(vsPlayersCar.VehicleIndex)
AND IS_VEHICLE_DRIVEABLE(vsCoachsCar.VehicleIndex)
RUBBER_BAND_PLAYBACK_SPEED_FOR_TRIGGER_VEHICLE(vsCoachsCar.VehicleIndex, vsPlayersCar.VehicleIndex,
fChaseSpeed, fChaseTime
#IF IS_DEBUG_BUILD, FALSE, "Coach", "Player" #ENDIF)
CREATE_ALL_WAITING_UBER_CARS()
UPDATE_UBER_PLAYBACK(vsCoachsCar.VehicleIndex, fChaseSpeed)
//uber playback flags
allow_veh_to_stop_on_PLAYER_impact = TRUE //switches set piece vehicles to playback using ai on player impact
ENDIF
ELSE
CLEANUP_UBER_PLAYBACK()
IF IS_VEHICLE_DRIVEABLE(vsCoachsCar.VehicleIndex)
IF IS_PLAYBACK_GOING_ON_FOR_VEHICLE(vsCoachsCar.VehicleIndex)
SET_PLAYBACK_SPEED(vsCoachsCar.VehicleIndex, 1.4)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Setting playback speed to 1.4 on cleanup_uber_playback.")
#ENDIF
ENDIF
SET_ENTITY_INVINCIBLE(vsCoachsCar.VehicleIndex, TRUE)
SET_ENTITY_ONLY_DAMAGED_BY_PLAYER(vsCoachsCar.VehicleIndex, TRUE)
SET_ENTITY_COLLISION(vsCoachsCar.VehicleIndex, FALSE)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Setting coach's car invincible, only damaged by player and no collision flag on cleanup_uber_playback.")
#ENDIF
ENDIF
IF NOT IS_PED_INJURED(psCoach.PedIndex)
SET_ENTITY_INVINCIBLE(psCoach.PedIndex, TRUE)
SET_ENTITY_ONLY_DAMAGED_BY_PLAYER(psCoach.PedIndex, TRUE)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Setting coach invincible, only damaged by player on cleanup_uber_playback.")
#ENDIF
ENDIF
iProgress++
ENDIF
BREAK
CASE 2 //after the chase has finished and coach's blip is off, make him drive super fast to the end of his recording
IF ( bChaseFinished = TRUE )
IF NOT DOES_BLIP_EXIST(vsCoachsCar.BlipIndex)
IF IS_VEHICLE_DRIVEABLE(vsCoachsCar.VehicleIndex)
IF IS_PLAYBACK_GOING_ON_FOR_VEHICLE(vsCoachsCar.VehicleIndex)
SET_PLAYBACK_SPEED(vsCoachsCar.VehicleIndex, 2.0)
SET_ENTITY_INVINCIBLE(vsCoachsCar.VehicleIndex, TRUE)
SET_ENTITY_ONLY_DAMAGED_BY_PLAYER(vsCoachsCar.VehicleIndex, TRUE)
SET_ENTITY_COLLISION(vsCoachsCar.VehicleIndex, FALSE)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Setting coach's car invincible, only damaged by player and no collision flag when chase is ended.")
#ENDIF
ENDIF
REMOVE_ENTITY_FROM_AUDIO_MIX_GROUP(vsCoachsCar.VehicleIndex)
ENDIF
IF NOT IS_PED_INJURED(psCoach.PedIndex)
SET_ENTITY_INVINCIBLE(psCoach.PedIndex, TRUE)
SET_ENTITY_ONLY_DAMAGED_BY_PLAYER(psCoach.PedIndex, TRUE)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Setting coach invincible, only damaged by player when chase is ended.")
#ENDIF
ENDIF
//request the IPL for balcony
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Requesting IPL DES_StiltHouse_imapstart.")
#ENDIF
REQUEST_IPL("DES_StiltHouse_imapstart")
iProgress++
ENDIF
ENDIF
BREAK
CASE 3 //when coach's car ends vehicle recording, coach needs to be warped to the balcony at the back of the house
IF IS_VEHICLE_DRIVEABLE(vsCoachsCar.VehicleIndex)
REQUEST_ANIM_DICT("missfam3")
IF NOT IS_PLAYBACK_GOING_ON_FOR_VEHICLE(vsCoachsCar.VehicleIndex)
//check if map section for balcony is loaded
IF IS_IPL_ACTIVE("DES_StiltHouse_imapstart")
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": IPL DES_StiltHouse_imapstart is active.")
#ENDIF
IF NOT IS_PED_INJURED(psCoach.PedIndex)
WARP_PED(psCoach.PedIndex, << -1034.6083, 653.9794, 155.0754 >>, 90.0561, FALSE, FALSE, FALSE)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Warping coach to the balcony.")
#ENDIF
SET_ENTITY_VISIBLE(psCoach.PedIndex, TRUE)
SET_ENTITY_INVINCIBLE(psCoach.PedIndex, FALSE)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Calling SET_ENTITY_INVINCIBLE(FALSE) for tennis coach.")
#ENDIF
SET_ENTITY_COLLISION(psCoach.PedIndex, TRUE)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Calling SET_ENTITY_COLLISION(TRUE) for tennis coach.")
#ENDIF
CLEAR_PED_TASKS(psCoach.PedIndex)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Calling CLEAR_PED_TASKS() for tennis coach.")
#ENDIF
SET_ENTITY_LOAD_COLLISION_FLAG(psCoach.PedIndex, TRUE)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Calling SET_ENTITY_LOAD_COLLISION_FLAG(TRUE) for tennis coach.")
#ENDIF
//SET_ENTITY_LOD_DIST(psCoach.PedIndex, 125)
SET_PED_LOD_MULTIPLIER(psCoach.PedIndex, 5.0)
SET_PED_COMPONENT_VARIATION(psCoach.PedIndex, PED_COMP_TORSO, 1, 0)
SET_PED_COMPONENT_VARIATION(psCoach.PedIndex, PED_COMP_LEG, 1, 0)
IF HAS_ANIM_DICT_LOADED("missfam3")
TASK_PLAY_ANIM_ADVANCED(psCoach.PedIndex, "missfam3", "coach_idle", << -1034.630, 654.114, 156.080 >>,
<< 0.0, 0.0, 85.0 >>, INSTANT_BLEND_IN, SLOW_BLEND_OUT, -1, AF_EXTRACT_INITIAL_OFFSET | AF_LOOPING | AF_OVERRIDE_PHYSICS)
ENDIF
ENDIF
IF IS_VEHICLE_DRIVEABLE(vsCoachsCar.VehicleIndex)
SET_ENTITY_INVINCIBLE(vsCoachsCar.VehicleIndex, FALSE)
SET_ENTITY_COLLISION(vsCoachsCar.VehicleIndex, TRUE)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Setting coach's car to not be invincible and have collision.")
#ENDIF
SET_VEHICLE_ENGINE_ON(vsCoachsCar.VehicleIndex, FALSE, TRUE)
SET_VEHICLE_LIGHTS(vsCoachsCar.VehicleIndex, FORCE_VEHICLE_LIGHTS_ON)
//SET_ENTITY_COORDS(vsCoachsCar.VehicleIndex, <<-1007.2410, 708.9224, 161.0334>>) //old position
//SET_ENTITY_HEADING(vsCoachsCar.VehicleIndex, 358.5527)
SET_ENTITY_COORDS(vsCoachsCar.VehicleIndex, <<-1069.1571, 672.9374, 141.3214>>)
SET_ENTITY_HEADING(vsCoachsCar.VehicleIndex, 275.7670)
SET_VEHICLE_ON_GROUND_PROPERLY(vsCoachsCar.VehicleIndex)
//SET_VEHICLE_DOORS_LOCKED(vsCoachsCar.VehicleIndex, VEHICLELOCK_LOCKED)
SET_VEHICLE_DOOR_OPEN(vsCoachsCar.VehicleIndex, SC_DOOR_FRONT_LEFT, FALSE, TRUE)
SET_VEHICLE_DOOR_OPEN(vsCoachsCar.VehicleIndex, SC_DOOR_FRONT_LEFT, TRUE)
SET_VEHICLE_IS_CONSIDERED_BY_PLAYER(vsCoachsCar.VehicleIndex, FALSE)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Repositioning coach's car.")
#ENDIF
ENDIF
FailFlags[MISSION_FAIL_COACH_DEAD] = TRUE
FailFlags[MISSION_FAIL_COACH_ATTACKED] = TRUE
FailFlags[MISSION_FAIL_COACH_SPOOKED] = TRUE
iProgress++
ENDIF
ENDIF
ENDIF
BREAK
CASE 4
//run a check for coach falling under the balcony
#IF IS_DEBUG_BUILD
VECTOR vCurrentCoachPosition
vCurrentCoachPosition = GET_ENTITY_COORDS(psCoach.PedIndex)
IF ( vCurrentCoachPosition.z < 155.0 ) //compare with warp coords << -1034.6083, 653.9794, 155.0754 >>
SCRIPT_ASSERT("Tennis coach ped is falling down.")
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Tennis coach ped is falling down.")
ENDIF
#ENDIF
IF ( bCoachSpotted = TRUE )
IF HAS_ANIM_DICT_LOADED("missfam3")
IF NOT IS_PED_INJURED(psCoach.PedIndex)
FREEZE_ENTITY_POSITION(psCoach.PedIndex, FALSE)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Calling FREEZE_ENTITY_POSITION(FALSE) for tennis coach.")
#ENDIF
TASK_PLAY_ANIM(psCoach.PedIndex, "missfam3", "coach_idle", SLOW_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_LOOPING)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Coach playing coach_idle animation on balcony.")
#ENDIF
iProgress++
ENDIF
ENDIF
ENDIF
BREAK
CASE 5 //coach's anim shout_out_window_coach is started in main mission stage function, check here for when it ends
IF ( bCoachSpotted = TRUE )
IF ( bMichaelStartedShouting = TRUE )
IF NOT IS_PED_INJURED(psCoach.PedIndex)
IF NOT IS_ENTITY_PLAYING_ANIM(psCoach.PedIndex, "missfam3", "shout_out_window_coach")
OPEN_SEQUENCE_TASK(PedSequence)
TASK_GO_STRAIGHT_TO_COORD(NULL, << -1026.9159, 653.8083, 155.0754 >>, PEDMOVE_WALK, -1, 196.607)
TASK_PLAY_ANIM(NULL, "missfam3", "coach_idle", NORMAL_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_LOOPING)
CLOSE_SEQUENCE_TASK(PedSequence)
TASK_PERFORM_SEQUENCE(psCoach.PedIndex, PedSequence)
CLEAR_SEQUENCE_TASK(PedSequence)
iProgress++
ENDIF
ENDIF
ENDIF
ENDIF
BREAK
ENDSWITCH
ENDPROC
PROC CHECK_LINE_OF_SIGHT_BETWEEN_ENTITIES(ENTITY_INDEX EntityIndex1, ENTITY_INDEX EntityIndex2, BOOL &bLOSFlag, INT &iTimer, INT iTime)
IF DOES_ENTITY_EXIST(EntityIndex1)
AND DOES_ENTITY_EXIST(EntityIndex2)
IF NOT IS_ENTITY_DEAD(EntityIndex1)
AND NOT IS_ENTITY_DEAD(EntityIndex2)
IF HAS_TIME_PASSED(iTime, iTimer)
bLOSFlag = HAS_ENTITY_CLEAR_LOS_TO_ENTITY(EntityIndex1, EntityIndex2)
iTimer = GET_GAME_TIMER()
ENDIF
ELSE
bLOSFlag = FALSE
ENDIF
ELSE
bLOSFlag = FALSE
ENDIF
ENDPROC
FUNC BOOL IS_MISSION_STAGE_CAR_CHASE_COMPLETED(INT &iStageProgress)
SET_BIT(sLocatesData.iLocatesBitSet, BS_DONT_DO_J_SKIP)
fChaseDistanceFromPlayerToCoach = GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), psCoach.PedIndex)
MANAGE_SET_PIECE_VAN(vsVan.iProgress)
MANAGE_TENNIS_COACH_IN_CHASE(psCoach.iProgress)
CHECK_LINE_OF_SIGHT_BETWEEN_ENTITIES(vsPlayersCar.VehicleIndex, vsCoachsCar.VehicleIndex, bCoachVisible, psCoach.iTimer, 1000)
UPDATE_CHASE_BLIP(vsCoachsCar.BlipIndex, vsCoachsCar.VehicleIndex, CHASE_TARGET_LOST_DISTANCE, 0.7, bChaseFinished)
SWITCH GET_PLAYER_CHARACTER_AT_MISSION_START()
CASE CHAR_MICHAEL
MANAGE_CONVERSATIONS_DURING_CHASE("FAM3_MST1")
BREAK
CASE CHAR_FRANKLIN
MANAGE_CONVERSATIONS_DURING_CHASE("FAM3_FST1")
BREAK
ENDSWITCH
UPDATE_TRIGGERED_LABEL(sLabelDCAN)
UPDATE_TRIGGERED_LABEL(sLabelGETBCK)
IF ( bShouldUseDefaultRoute = FALSE )
IF ( bCustomRouteActive = FALSE )
IF DOES_BLIP_EXIST(sLocatesData.LocationBlip)
SET_GPS_DISABLED_ZONE(<< -742.680298 - 48.0, 539.209961 - 48.0, 115.340584 - 18.0>>,
<< -742.680298 + 48.0, 539.209961 + 48.0, 115.340584 + 18.0>>)
bCustomRouteActive = TRUE
ENDIF
ELSE
IF NOT DOES_BLIP_EXIST(sLocatesData.LocationBlip)
SET_GPS_DISABLED_ZONE(<< 0.0, 0.0, 0.0 >>, << 0.0, 0.0, 0.0 >>)
bCustomRouteActive = FALSE
ENDIF
IF DOES_BLIP_EXIST(sLocatesData.LocationBlip)
IF IS_ENTITY_AT_COORD(PLAYER_PED_ID(), <<-742.680298,539.209961,115.340584>>, << 48.0, 48.0, 18.0 >>)
OR IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), << -1184.89, 709.60, 132.38 >>, << -1133.41, 679.84, 161.10 >>, 36.0)
OR IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), << -1062.28, 662.22, 125.02 >>, << -1138.02, 681.84, 161.37 >>, 36.0)
OR IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), << -1065.68, 661.26, 121.10 >>, << -976.84, 641.13, 153.91 >>, 36.0)
OR IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), << -894.49, 655.77, 113.47 >>, << -985.13, 640.53, 154.35 >>, 36.0)
OR IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), << -898.85, 657.44, 113.60 >>, << -823.46, 645.49, 144.01 >>, 36.0)
OR IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), << -770.93, 551.06, 101.91 >>, << -827.24, 649.55, 144.36 >>, 36.0)
OR IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), << -770.974, 557.36, 102.67 >>, << -700.16, 501.75, 124.60 >>, 36.0)
SET_GPS_DISABLED_ZONE(<< 0.0, 0.0, 0.0 >>, << 0.0, 0.0, 0.0 >>)
bShouldUseDefaultRoute = TRUE
ENDIF
ENDIF
ENDIF
ENDIF
SWITCH iStageProgress
CASE 0
IF IS_VEHICLE_DRIVEABLE(vsPlayersCar.VehicleIndex)
IF NOT IS_PED_INJURED(psFranklin.PedIndex)
IF NOT IS_PED_IN_VEHICLE(psFranklin.PedIndex, vsPlayersCar.VehicleIndex)
AND NOT IS_PED_GETTING_INTO_A_VEHICLE(psFranklin.PedIndex)
IF ( GET_SCRIPT_TASK_STATUS(psFranklin.PedIndex, SCRIPT_TASK_ENTER_VEHICLE) <> PERFORMING_TASK )
TASK_ENTER_VEHICLE(psFranklin.PedIndex, vsPlayersCar.VehicleIndex, DEFAULT_TIME_BEFORE_WARP, VS_FRONT_RIGHT, PEDMOVE_RUN, ECF_USE_RIGHT_ENTRY | ECF_RESUME_IF_INTERRUPTED)
ENDIF
ENDIF
SET_PED_CONFIG_FLAG(psFranklin.PedIndex, PCF_GetOutUndriveableVehicle, FALSE)
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(psFranklin.PedIndex, TRUE)
ENDIF
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
IF NOT IS_PED_IN_VEHICLE(PLAYER_PED_ID(), vsPlayersCar.VehicleIndex)
AND NOT IS_PED_GETTING_INTO_A_VEHICLE(PLAYER_PED_ID())
IF ( GET_SCRIPT_TASK_STATUS(PLAYER_PED_ID(), SCRIPT_TASK_ENTER_VEHICLE) <> PERFORMING_TASK )
WARP_PED(PLAYER_PED_ID(), psMichael.vPosition, psMichael.fHeading, FALSE, FALSE, FALSE)
FORCE_PED_MOTION_STATE(PLAYER_PED_ID(), MS_ON_FOOT_RUN, FALSE)
TASK_ENTER_VEHICLE(PLAYER_PED_ID(), vsPlayersCar.VehicleIndex, DEFAULT_TIME_BEFORE_WARP, VS_DRIVER, PEDMOVE_RUN, ECF_USE_LEFT_ENTRY | ECF_RESUME_IF_INTERRUPTED)
ENDIF
ENDIF
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(psFranklin.PedIndex, TRUE)
ENDIF
ENDIF
IF IS_SCREEN_FADED_OUT()
WAIT(150)
DO_SCREEN_FADE_IN(DEFAULT_FADE_TIME)
ENDIF
REPLAY_RECORD_BACK_FOR_TIME(0.0, 7.0, REPLAY_IMPORTANCE_HIGHEST)
iStageProgress++
BREAK
CASE 1 //player chases after tennis coach
#IF IS_DEBUG_BUILD
IF ( bDrawDebugStates = TRUE )
DRAW_DEBUG_TEXT_ABOVE_ENTITY(PLAYER_PED_ID(), GET_STRING_FROM_FLOAT(fChaseDistanceFromPlayerToCoach), 1.25)
DRAW_DEBUG_TEXT_ABOVE_ENTITY(vsPlayersCar.VehicleIndex, PICK_STRING(bCoachVisible, "TRUE", "FALSE"), 1.5)
ENDIF
#ENDIF
HANDLE_BUDDY_HEAD_TRACK_WHILE_ENTERING_VEHICLE()
//handle player's truck blip
IF IS_VEHICLE_DRIVEABLE(vsPlayersCar.VehicleIndex)
IF IS_PED_IN_VEHICLE(PLAYER_PED_ID(), vsPlayersCar.VehicleIndex)//player is in the truck
//remove player's car blip
IF DOES_BLIP_EXIST(vsPlayersCar.BlipIndex)
IF IS_THIS_PRINT_BEING_DISPLAYED("FAM3_GIT")
OR IS_THIS_PRINT_BEING_DISPLAYED("FAM3_GBIT")
CLEAR_PRINTS()
ENDIF
REMOVE_BLIP(vsPlayersCar.BlipIndex)
ENDIF
IF ( bPlayerVehicleEntered = FALSE )
IF NOT IS_AUDIO_SCENE_ACTIVE("FAMILY_3_FOLLOW_THE_COACH")
START_AUDIO_SCENE("FAMILY_3_FOLLOW_THE_COACH")
ENDIF
bPlayerVehicleEntered = TRUE
ENDIF
IF ( bChaseFinished = FALSE )
IF IS_VEHICLE_DRIVEABLE(vsCoachsCar.VehicleIndex)
IF NOT DOES_BLIP_EXIST(vsCoachsCar.BlipIndex)
vsCoachsCar.BlipIndex = CREATE_BLIP_FOR_VEHICLE(vsCoachsCar.VehicleIndex, TRUE)
ENDIF
IF DOES_BLIP_EXIST(vsCoachsCar.BlipIndex)
IF NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_FTC")
CLEAR_PRINTS()
PRINT_GOD_TEXT_ADVANCED("FAM3_FTC", DEFAULT_GOD_TEXT_TIME, TRUE)
ENDIF
ENDIF
ENDIF
ENDIF
ELSE //player is not in the truck
//display blip for player car and display objective to get in
IF NOT DOES_BLIP_EXIST(vsPlayersCar.BlipIndex)
vsPlayersCar.BlipIndex = CREATE_BLIP_FOR_VEHICLE(vsPlayersCar.VehicleIndex)
ENDIF
IF DOES_BLIP_EXIST(vsPlayersCar.BlipIndex)
//display initial objective to get in for the first time
IF NOT HAS_LABEL_BEEN_TRIGGERED(sLabelGIT)
IF ( bPlayerVehicleEntered = FALSE )
CLEAR_PRINTS()
PRINT_GOD_TEXT_ADVANCED(sLabelGIT, DEFAULT_GOD_TEXT_TIME, TRUE)
ENDIF
ELSE
//display objective for getting back in after the initial get in objective was printed
IF NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_GBIT")
IF ( bPlayerVehicleEntered = TRUE )
CLEAR_PRINTS()
PRINT_GOD_TEXT_ADVANCED("FAM3_GBIT", DEFAULT_GOD_TEXT_TIME, TRUE)
ENDIF
ENDIF
ENDIF
ENDIF
IF DOES_BLIP_EXIST(vsCoachsCar.BlipIndex)
REMOVE_BLIP(vsCoachsCar.BlipIndex)
ENDIF
ENDIF
ENDIF
IF ( bChaseInProgress = TRUE )
IF ( bChaseHintCamAllowed = FALSE )
IF ( fChaseTime >= 7500.0 )
bChaseHintCamAllowed = TRUE
ENDIF
ENDIF
//handle blips and god text depending on player being in the truck or not
IF IS_VEHICLE_DRIVEABLE(vsPlayersCar.VehicleIndex)
IF IS_PED_IN_VEHICLE(PLAYER_PED_ID(), vsPlayersCar.VehicleIndex)//player is in the truck
IF ( bChaseHintCamAllowed = TRUE )
CONTROL_VEHICLE_CHASE_HINT_CAM_IN_VEHICLE(localChaseHintCamStruct, vsCoachsCar.VehicleIndex, PICK_STRING(ShouldDisplayChaseHelpText(), "FAM3_HCAM", ""))
ENDIF
IF IS_GAMEPLAY_HINT_ACTIVE()
IF NOT IS_AUDIO_SCENE_ACTIVE("FAMILY_3_FOCUS_ON_COACH")
START_AUDIO_SCENE("FAMILY_3_FOCUS_ON_COACH")
ENDIF
ELSE
IF IS_AUDIO_SCENE_ACTIVE("FAMILY_3_FOCUS_ON_COACH")
STOP_AUDIO_SCENE("FAMILY_3_FOCUS_ON_COACH")
ENDIF
ENDIF
ELSE //player is not in the truck
//clear help message
IF HAS_LABEL_BEEN_TRIGGERED("FAM3_HCAM")
IF IS_THIS_HELP_MESSAGE_BEING_DISPLAYED("FAM3_HCAM")
CLEAR_HELP()
ENDIF
ENDIF
ENDIF
ENDIF
//check for chase finish
IF ( bChaseFinished = FALSE )
//player gets close to the van blocking the way, van can be dead or alive, player might shoot it up
IF DOES_ENTITY_EXIST(vsVan.VehicleIndex)
IF NOT IS_ENTITY_DEAD(vsVan.VehicleIndex)
IF IS_ENTITY_AT_ENTITY(vsPlayersCar.VehicleIndex, vsVan.VehicleIndex, vVanLocateSize)
KILL_CHASE_HINT_CAM(localChaseHintCamStruct)
IF IS_AUDIO_SCENE_ACTIVE("FAMILY_3_FOCUS_ON_COACH")
STOP_AUDIO_SCENE("FAMILY_3_FOCUS_ON_COACH")
ENDIF
bChaseInProgress = FALSE
bChaseFinished = TRUE
eChaseFinishReason = CHASE_FINISHED_END_REACHED
IF IS_THIS_PRINT_BEING_DISPLAYED("FAM3_FTC")
CLEAR_PRINTS()
ENDIF
//set the mission to be reset to the start when P-skip occurs from this point
#IF IS_DEBUG_BUILD
bStageResetFlag = TRUE
#ENDIF
ENDIF
ENDIF
ENDIF
//if player somehow destroyed the van, or the van does not exist as expected, do a locate check along the chase route
//use a locate check, should be more reliable than entity check as the van and driver might be dead
IF IS_ENTITY_IN_ANGLED_AREA(vsPlayersCar.VehicleIndex, <<-1381.268311,474.786530,103.054825>>, <<-1390.820190,457.381134,110.486206>>, 8.0)
KILL_CHASE_HINT_CAM(localChaseHintCamStruct)
IF IS_AUDIO_SCENE_ACTIVE("FAMILY_3_FOCUS_ON_COACH")
STOP_AUDIO_SCENE("FAMILY_3_FOCUS_ON_COACH")
ENDIF
bChaseInProgress = FALSE
bChaseFinished = TRUE
eChaseFinishReason = CHASE_FINISHED_END_REACHED
IF IS_THIS_PRINT_BEING_DISPLAYED("FAM3_FTC")
CLEAR_PRINTS()
ENDIF
//if player is making a phone call after destroying the van
//and entering the end of chase locate
IF IS_PHONE_ONSCREEN()
HANG_UP_AND_PUT_AWAY_PHONE(TRUE)
ENDIF
//set the mission to be reset to the start when P-skip occurs from this point
#IF IS_DEBUG_BUILD
bStageResetFlag = TRUE
#ENDIF
ENDIF
IF fChaseDistanceFromPlayerToCoach > CHASE_TARGET_LOST_DISTANCE
IF DOES_BLIP_EXIST(vsCoachsCar.BlipIndex)
REMOVE_BLIP(vsCoachsCar.BlipIndex)
ENDIF
KILL_CHASE_HINT_CAM(localChaseHintCamStruct)
IF IS_AUDIO_SCENE_ACTIVE("FAMILY_3_FOCUS_ON_COACH")
STOP_AUDIO_SCENE("FAMILY_3_FOCUS_ON_COACH")
ENDIF
bChaseInProgress = FALSE
bChaseFinished = TRUE
eChaseFinishReason = CHASE_FINISHED_TARGET_LOST
IF IS_THIS_PRINT_BEING_DISPLAYED("FAM3_FTC")
CLEAR_PRINTS()
ENDIF
//set the mission to be reset to the start when P-skip occurs from this point
#IF IS_DEBUG_BUILD
bStageResetFlag = TRUE
#ENDIF
ENDIF
ENDIF
ELSE
IF ( bChaseFinished = TRUE )
IF IS_AUDIO_SCENE_ACTIVE("FAMILY_3_FOLLOW_THE_COACH")
STOP_AUDIO_SCENE("FAMILY_3_FOLLOW_THE_COACH")
ENDIF
IF NOT IS_AUDIO_SCENE_ACTIVE("FAMILY_3_FIND_THE_COACH")
START_AUDIO_SCENE("FAMILY_3_FIND_THE_COACH")
ENDIF
SWITCH eChaseFinishReason
CASE CHASE_FINISHED_END_REACHED
BREAK
CASE CHASE_FINISHED_TARGET_LOST
BREAK
ENDSWITCH
IF HAS_LABEL_BEEN_TRIGGERED("FAM3_LOST") //if the conversation "FAM3_LOST" managed to be created and played
//remove coach's red blip when Michael and Franklin mention they lost him
IF DOES_BLIP_EXIST(vsCoachsCar.BlipIndex)
REMOVE_BLIP(vsCoachsCar.BlipIndex)
ENDIF
//when the "FAM3_LOST" conversation is playing
IF IS_THIS_CONVERSATION_PLAYING("FAM3_LOST")
bCoachLostConversationStarted = TRUE //mark the conversation FAM3_LOST as triggered and started playing
//when second line of that conversation triggers, create a blip for destination
IF ( GET_CURRENT_SCRIPTED_CONVERSATION_LINE() = 1 )
IF NOT DOES_BLIP_EXIST(sLocatesData.LocationBlip)
IF IS_VEHICLE_DRIVEABLE(vsPlayersCar.VehicleIndex)
IF IS_PED_SITTING_IN_VEHICLE(PLAYER_PED_ID(), vsPlayersCar.VehicleIndex)
IF NOT IS_PLAYER_WANTED_LEVEL_GREATER(PLAYER_ID(), 0)
//sLocatesData.LocationBlip = CREATE_BLIP_FOR_COORD(<<-991.654724,645.382141,140.642548>>, TRUE)
bDisplayDestinationBlip = TRUE
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ELSE //conversation FAM3_LOST not playing, could be due to being finished or still building
IF ( bCoachLostConversationStarted = TRUE ) //only move on if FAM3_LOST started playing and finished
//move on once the coach lost conversation is over
iStageProgress++
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
IF ( bDisplayDestinationBlip = TRUE )
IS_PLAYER_AT_LOCATION_WITH_BUDDY_IN_VEHICLE(sLocatesData, vUnderBalconyPosition, <<4.0, 8.0, LOCATE_SIZE_HEIGHT>>, TRUE, psFranklin.PedIndex,
vsPlayersCar.VehicleIndex, sLabelDCAN, "CMN_FLEAVE", "", sLabelGETBCK,FALSE, TRUE)
ENDIF
BREAK
CASE 2 //player drives to the canyon destination
//make sure shout anim for Michael is loaded
REQUEST_ANIM_DICT("missfam3")
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
IF IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(), "missfam3", "shout_out_window_michael")
OR GET_SCRIPT_TASK_STATUS(PLAYER_PED_ID(), SCRIPT_TASK_VEHICLE_MISSION) = PERFORMING_TASK
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_EXIT)
ENDIF
ENDIF
IF ( bCoachSpotted = FALSE )
IF DOES_BLIP_EXIST(sLocatesData.LocationBlip)
AND IS_PED_SITTING_IN_THIS_VEHICLE(PLAYER_PED_ID(), vsPlayersCar.VehicleIndex)
AND IS_PED_SITTING_IN_THIS_VEHICLE(psFranklin.PedIndex, vsPlayersCar.VehicleIndex)
AND IS_ENTITY_IN_ANGLED_AREA(vsPlayersCar.VehicleIndex, <<-1116.003296,693.004333,140.496552>>, <<-1040.929321,667.397583,157.254593>>, 36.000000)
//hacky fix for B*1407985 & B*1513220
IF NOT IS_ENTITY_AT_COORD(vsPlayersCar.VehicleIndex, <<-1054.042480,681.179077,152.773621>>,<<20.000000,16.000000,12.000000>>)
DISABLE_CELLPHONE(TRUE)
SETTIMERA(0)
SET_GAMEPLAY_COORD_HINT(vTennisCoachHintPosition, -1, iTennisCoachHintDuration, DEFAULT_INTERP_OUT_TIME, HINTTYPE_FAMILY3_COACH_ON_BALCONY_VEHICLE_HINT_HELPER)
TASK_VEHICLE_MISSION_COORS_TARGET(PLAYER_PED_ID(), vsPlayersCar.VehicleIndex, <<-991.654724,645.382141,140.642548>>,
MISSION_GOTO, 6.0, DF_SteerAroundStationaryCars, 1.0, 2.0, FALSE)
ENDIF
TRIGGER_MUSIC_EVENT("FAM3_BALCONY")
bCoachSpotted = TRUE
ELSE
IF NOT DOES_BLIP_EXIST(sLocatesData.LocationBlip)
AND IS_PLAYER_WANTED_LEVEL_GREATER(PLAYER_ID(), 0)
AND IS_PED_SITTING_IN_THIS_VEHICLE(PLAYER_PED_ID(), vsPlayersCar.VehicleIndex)
AND IS_PED_SITTING_IN_THIS_VEHICLE(psFranklin.PedIndex, vsPlayersCar.VehicleIndex)
AND IS_ENTITY_IN_ANGLED_AREA(vsPlayersCar.VehicleIndex, <<-1116.003296,693.004333,140.496552>>, <<-1040.929321,667.397583,157.254593>>, 36.000000)
TRIGGER_MUSIC_EVENT("FAM3_BALCONY")
bCoachSpotted = TRUE
ENDIF
ENDIF
ELIF ( bCoachSpotted = TRUE )
IF ( bMichaelStartedShouting = FALSE )
IF IS_PLAYER_WANTED_LEVEL_GREATER(PLAYER_ID(), 0)
SET_PLAYER_WANTED_LEVEL(PLAYER_ID(), 0)
SET_PLAYER_WANTED_LEVEL_NOW(PLAYER_ID())
ENDIF
IF DOES_BLIP_EXIST(sLocatesData.LocationBlip)
AND IS_PED_SITTING_IN_THIS_VEHICLE(PLAYER_PED_ID(), vsPlayersCar.VehicleIndex)
AND IS_PED_SITTING_IN_THIS_VEHICLE(psFranklin.PedIndex, vsPlayersCar.VehicleIndex)
IF HAS_LABEL_BEEN_TRIGGERED("FAM3_SPOT")
IF ( bSpotConversationFinished = TRUE )
REMOVE_VEHICLE_WINDOW(vsPlayersCar.VehicleIndex, SC_WINDOW_FRONT_LEFT)
TASK_PLAY_ANIM(PLAYER_PED_ID(), "missfam3", "shout_out_window_michael", SLOW_BLEND_IN, SLOW_BLEND_OUT,
-1, AF_UPPERBODY | AF_SECONDARY)
TASK_PLAY_ANIM(psFranklin.PedIndex, "missfam3", "shout_out_window_franklin", SLOW_BLEND_IN, WALK_BLEND_OUT,
-1, AF_UPPERBODY | AF_SECONDARY)
TASK_PLAY_ANIM_ADVANCED(psCoach.PedIndex, "missfam3", "shout_out_window_coach",
<< -1034.630, 654.114, 156.080 >>, << 0.0, 0.0, 85.0 >>,
SLOW_BLEND_IN, SLOW_BLEND_OUT, -1,
AF_EXTRACT_INITIAL_OFFSET | AF_OVERRIDE_PHYSICS | AF_NOT_INTERRUPTABLE)
TASK_LOOK_AT_ENTITY(psCoach.PedIndex, PLAYER_PED_ID(), INFINITE_TASK_TIME)
REPLAY_RECORD_BACK_FOR_TIME(7.0, 7.0, REPLAY_IMPORTANCE_HIGHEST)
bMichaelStartedShouting = TRUE
ENDIF
ENDIF
ENDIF
ELIF ( bMichaelStartedShouting = TRUE )
IF HAS_LABEL_BEEN_TRIGGERED("FAM3_BALC")
IF ( bRecordingPlaybackStarted = FALSE )
IF IS_THIS_CONVERSATION_PLAYING("FAM3_BALC") //when the "FAM3_BALC" conversation is playing
IF DOES_BLIP_EXIST(sLocatesData.LocationBlip)
AND IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(), "missfam3", "shout_out_window_michael")
IF ( GET_CURRENT_SCRIPTED_CONVERSATION_LINE() >= 0 )
OR IS_ENTITY_IN_ANGLED_AREA(vsPlayersCar.VehicleIndex, <<-1116.163086,681.841125,135.569122>>,
<<-1066.322632,665.023315,149.062729>>, 24.0)
IF IS_AUDIO_SCENE_ACTIVE("FAMILY_3_FIND_THE_COACH")
STOP_AUDIO_SCENE("FAMILY_3_FIND_THE_COACH")
ENDIF
IF NOT IS_AUDIO_SCENE_ACTIVE("FAMILY_3_ARRIVE_AT_HOUSE")
START_AUDIO_SCENE("FAMILY_3_ARRIVE_AT_HOUSE")
ENDIF
bRecordingPlaybackStarted = TRUE
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
IF IS_GAMEPLAY_HINT_ACTIVE()
IF IS_PLAYER_WANTED_LEVEL_GREATER(PLAYER_ID(), 0)
SET_PLAYER_WANTED_LEVEL(PLAYER_ID(), 0)
SET_PLAYER_WANTED_LEVEL_NOW(PLAYER_ID())
ENDIF
IF ( TIMERA() > iTennisCoachHintDuration)
OR ( IS_ENTITY_PLAYING_ANIM(psCoach.PedIndex, "missfam3", "shout_out_window_coach") AND GET_ENTITY_ANIM_CURRENT_TIME(psCoach.PedIndex, "missfam3", "shout_out_window_coach") > 0.8 )
OR ( HAS_LABEL_BEEN_TRIGGERED("FAM3_BALC") AND NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED() )
OR IS_ENTITY_IN_ANGLED_AREA(vsPlayersCar.VehicleIndex, <<-1056.988770,652.465698,140.027237>>, <<-1047.219238,668.414063,153.151367>>, 16.0)
DISABLE_CELLPHONE(FALSE)
//clear Michael's tasks
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
IF IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(), "missfam3", "shout_out_window_michael")
CLEAR_PED_SECONDARY_TASK(PLAYER_PED_ID())
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Stopping Michael's animation shout_out_window_michael.")
#ENDIF
ENDIF
ENDIF
//clear Franklin's tasks
IF NOT IS_PED_INJURED(psFranklin.PedIndex)
IF IS_ENTITY_PLAYING_ANIM(psFranklin.PedIndex, "missfam3", "shout_out_window_franklin")
CLEAR_PED_SECONDARY_TASK(psFranklin.PedIndex)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Stopping Franklin's animation shout_out_window_franklin.")
#ENDIF
ENDIF
ENDIF
STOP_GAMEPLAY_HINT()
CLEAR_PED_TASKS(PLAYER_PED_ID())
SET_PLAYER_CONTROL(PLAYER_ID(), TRUE)
IF IS_AUDIO_SCENE_ACTIVE("FAMILY_3_ARRIVE_AT_HOUSE")
STOP_AUDIO_SCENE("FAMILY_3_ARRIVE_AT_HOUSE")
ENDIF
IF IS_AUDIO_SCENE_ACTIVE("FAMILY_3_FIND_THE_COACH")
STOP_AUDIO_SCENE("FAMILY_3_FIND_THE_COACH")
ENDIF
IF NOT IS_AUDIO_SCENE_ACTIVE("FAMILY_3_DRIVE_IN_TO_POSITION")
START_AUDIO_SCENE("FAMILY_3_DRIVE_IN_TO_POSITION")
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
IF DOES_BLIP_EXIST(vsPlayersCar.BlipIndex) //remove player's car blip if it exists, locates header will handle it now
IF GET_BLIP_FROM_ENTITY(vsPlayersCar.VehicleIndex) = vsPlayersCar.BlipIndex
REMOVE_BLIP(vsPlayersCar.BlipIndex)
ENDIF
ENDIF
//check for when player arrives at the back of the house locate
IF IS_PLAYER_AT_LOCATION_WITH_BUDDY_IN_VEHICLE(sLocatesData, vUnderBalconyPosition, <<4.0, 8.0, LOCATE_SIZE_HEIGHT>>, TRUE, psFranklin.PedIndex,
vsPlayersCar.VehicleIndex, sLabelDCAN, "CMN_FLEAVE", "", sLabelGETBCK,FALSE, TRUE)
IF IS_VEHICLE_DRIVEABLE(vsPlayersCar.VehicleIndex)
IF IS_VEHICLE_ON_ALL_WHEELS(vsPlayersCar.VehicleIndex)
IF DOES_CAM_EXIST(ScriptedCamera)
SET_CAM_ACTIVE(ScriptedCamera, FALSE)
RENDER_SCRIPT_CAMS(FALSE, FALSE)
DESTROY_CAM(ScriptedCamera)
ENDIF
//clear Michael's tasks if he is still playing the shout animation
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
IF IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(), "missfam3", "shout_out_window_michael")
CLEAR_PED_SECONDARY_TASK(PLAYER_PED_ID())
ENDIF
ENDIF
//clear Franklin's tasks if he is still playing the shout animation
IF NOT IS_PED_INJURED(psFranklin.PedIndex)
IF IS_ENTITY_PLAYING_ANIM(psFranklin.PedIndex, "missfam3", "shout_out_window_franklin")
CLEAR_PED_SECONDARY_TASK(psFranklin.PedIndex)
ENDIF
ENDIF
//clear coach's tasks if he is still playing the shout animation
IF NOT IS_PED_INJURED(psCoach.PedIndex)
IF IS_ENTITY_PLAYING_ANIM(psCoach.PedIndex, "missfam3", "shout_out_window_coach")
CLEAR_PED_TASKS(psCoach.PedIndex)
ENDIF
TASK_CLEAR_LOOK_AT(psCoach.PedIndex)
ENDIF
IF DOES_ENTITY_EXIST(osRacket01.ObjectIndex)
DELETE_OBJECT(osRacket01.ObjectIndex)
ENDIF
IF DOES_ENTITY_EXIST(osRacket02.ObjectIndex)
DELETE_OBJECT(osRacket02.ObjectIndex)
ENDIF
IF DOES_ENTITY_EXIST(osBrokenPlantPot.ObjectIndex)
DELETE_OBJECT(osBrokenPlantPot.ObjectIndex)
ENDIF
CLEANUP_VEHICLE(vsCoachsCar, TRUE) //remove coach's car
KILL_ANY_CONVERSATION()
KILL_FACE_TO_FACE_CONVERSATION() //kill conversations and let last line play out
SETTIMERA(0) //start backup timer in case the conversations are busted by streaming
iStageProgress++
ENDIF
ENDIF
ENDIF
IF IS_PLAYER_BROWSING_ITEMS_IN_ANY_SHOP()
OR IS_PLAYER_CHANGING_CLOTHES() //check if player changed clothes before cutscene
IF HAS_THIS_CUTSCENE_LOADED("fam_3_mcs_1")
OR HAS_CUTSCENE_LOADED()
OR IS_CUTSCENE_ACTIVE()
REMOVE_CUTSCENE() //remove cutscene from memory if player changed clothes
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Player browsing items in a shop or changing clothes. Removing cutscene.")
#ENDIF
ENDIF
ELSE
IF GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), vUnderBalconyPosition) < DEFAULT_CUTSCENE_LOAD_DIST
REQUEST_CUTSCENE("fam_3_mcs_1") //request cutscene and variations
IF CAN_REQUEST_ASSETS_FOR_CUTSCENE_ENTITY()
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
SET_CUTSCENE_PED_COMPONENT_VARIATION_FROM_PED("Michael", PLAYER_PED_ID())
ENDIF
IF NOT IS_PED_INJURED(psFranklin.PedIndex)
SET_CUTSCENE_PED_COMPONENT_VARIATION_FROM_PED("Franklin", psFranklin.PedIndex)
ENDIF
SET_CUTSCENE_PED_COMPONENT_VARIATION("TennisCoach", PED_COMP_TORSO, 1, 0)
SET_CUTSCENE_PED_COMPONENT_VARIATION("TennisCoach", PED_COMP_LEG, 1, 0)
ENDIF
ELSE
IF HAS_THIS_CUTSCENE_LOADED("fam_3_mcs_1")
OR HAS_CUTSCENE_LOADED()
OR IS_CUTSCENE_ACTIVE()
REMOVE_CUTSCENE()
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Player too far away from destination to keep cutscene in memory. Removing cutscene.")
#ENDIF
ENDIF
ENDIF
ENDIF
//disable player climbing onto the balcony
IF IS_ENTITY_AT_COORD(PLAYER_PED_ID(), <<-1036.479858,671.642395,155.457687>>, << 4.0, 7.0, 4.5>>)
OR IS_ENTITY_AT_COORD(PLAYER_PED_ID(), <<-1006.946838,667.282104,154.917389>>, << 5.0, 8.0, 4.5 >>)
SET_PED_RESET_FLAG(PLAYER_PED_ID(), PRF_DisablePlayerAutoVaulting, TRUE)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_JUMP)
ENDIF
BREAK
CASE 3
IF BRING_VEHICLE_TO_HALT_AND_DISABLE_VEH_CONTROLS(vsPlayersCar.VehicleIndex, 3.0)
IF NOT IS_SCRIPTED_CONVERSATION_ONGOING() //check if scripted conversations are not ongoing using native command
OR NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED() //check if any conversations are not ongoing using script command
OR ( TIMERA() > 5000 ) //check backup timer in case the conversations are busted by streaming
CLEANUP_PED(psVanDriver, TRUE)
CLEANUP_VEHICLE(vsVan, TRUE)
REMOVE_VEHICLE_RECORDING(vsVan.iRecordingNumber, sVehicleRecordingsFile)
STOP_AUDIO_SCENE("FAMILY_3_FIND_THE_COACH")
STOP_AUDIO_SCENE("FAMILY_3_ARRIVE_AT_HOUSE")
STOP_AUDIO_SCENE("FAMILY_3_DRIVE_IN_TO_POSITION")
STOP_GAMEPLAY_HINT()
REPLAY_RECORD_BACK_FOR_TIME(7.0, 0.0, REPLAY_IMPORTANCE_HIGHEST)
RETURN TRUE
ENDIF
ENDIF
BREAK
ENDSWITCH
RETURN FALSE
ENDFUNC
FUNC BOOL IS_MISSION_STAGE_CUTSCENE_BACK_OF_HOUSE_COMPLETED(INT &iStageProgress)
SWITCH iStageProgress
CASE 0 //register peds for cutscene and start the cutscene when loaded
IF HAS_REQUESTED_CUTSCENE_LOADED("fam_3_mcs_1")
IF IS_VEHICLE_DRIVEABLE(vsPlayersCar.VehicleIndex)
IF IS_VEHICLE_DOOR_DAMAGED(vsPlayersCar.VehicleIndex, SC_DOOR_FRONT_LEFT)
SET_VEHICLE_DOOR_CONTROL(vsPlayersCar.VehicleIndex, SC_DOOR_FRONT_LEFT, DT_DOOR_INTACT, 0.0)
ENDIF
IF IS_VEHICLE_DOOR_DAMAGED(vsPlayersCar.VehicleIndex, SC_DOOR_FRONT_RIGHT)
SET_VEHICLE_DOOR_CONTROL(vsPlayersCar.VehicleIndex, SC_DOOR_FRONT_RIGHT, DT_DOOR_INTACT, 0.0)
ENDIF
REGISTER_ENTITY_FOR_CUTSCENE(vsPlayersCar.VehicleIndex, "Fam3_tow_truck", CU_ANIMATE_EXISTING_SCRIPT_ENTITY, BISON2)
SET_VEHICLE_ENGINE_ON(vsPlayersCar.VehicleIndex, TRUE, TRUE)
ENDIF
IF NOT IS_PED_INJURED(psFranklin.PedIndex)
REGISTER_ENTITY_FOR_CUTSCENE(psFranklin.PedIndex, "Franklin", CU_ANIMATE_EXISTING_SCRIPT_ENTITY, GET_PLAYER_PED_MODEL(CHAR_FRANKLIN))
ENDIF
IF NOT IS_PED_INJURED(psCoach.PedIndex)
REGISTER_ENTITY_FOR_CUTSCENE(psCoach.PedIndex, "TennisCoach", CU_ANIMATE_EXISTING_SCRIPT_ENTITY, CS_TENNISCOACH)
ENDIF
SET_SCRIPTS_SAFE_FOR_CUTSCENE(TRUE)
CLEAR_HELP()
CLEAR_PRINTS()
START_CUTSCENE(CUTSCENE_SUPPRESS_FP_TRANSITION_FLASH)
REPLAY_START_EVENT(REPLAY_IMPORTANCE_HIGHEST)
//CASCADE_SHADOWS_SET_CASCADE_BOUNDS_SCALE(0.3)
iStageProgress++
ELSE
IF CAN_REQUEST_ASSETS_FOR_CUTSCENE_ENTITY()
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
SET_CUTSCENE_PED_COMPONENT_VARIATION_FROM_PED("Michael", PLAYER_PED_ID())
ENDIF
IF NOT IS_PED_INJURED(psFranklin.PedIndex)
SET_CUTSCENE_PED_COMPONENT_VARIATION_FROM_PED("Franklin", psFranklin.PedIndex)
ENDIF
SET_CUTSCENE_PED_COMPONENT_VARIATION("TennisCoach", PED_COMP_TORSO, 1, 0)
SET_CUTSCENE_PED_COMPONENT_VARIATION("TennisCoach", PED_COMP_LEG, 1, 0)
ENDIF
ENDIF
BREAK
CASE 1 //fade screen in if screen was faded out due to shit skip or debug skip
IF IS_CUTSCENE_PLAYING()
TRIGGER_MUSIC_EVENT("FAM3_ARRIVE_HOUSE")
STOP_GAMEPLAY_HINT(TRUE)
CLEAR_AREA(psMichael.vPosition, 100.0, TRUE)
CLEAR_AREA_OF_VEHICLES(psMichael.vPosition, 100.0)
IF IS_SCREEN_FADED_OUT()
DO_SCREEN_FADE_IN(DEFAULT_FADE_TIME)
ENDIF
iStageProgress++
ENDIF
BREAK
CASE 2
ROPE_LOAD_TEXTURES()
REQUEST_ANIM_DICT("missfam3")
REQUEST_MODEL(osRopeProp.ModelName)
REQUEST_MODEL(osRopeDummy.ModelName)
REQUEST_MODEL(osBootCollision.ModelName)
DISABLE_ON_FOOT_FIRST_PERSON_VIEW_THIS_UPDATE()
IF CAN_SET_EXIT_STATE_FOR_CAMERA()
STOP_GAMEPLAY_HINT()
SET_GAMEPLAY_CAM_RELATIVE_PITCH(0)
SET_GAMEPLAY_CAM_RELATIVE_HEADING(0)
ENDIF
IF CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY("Michael")
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY() returned true for Michael.")
#ENDIF
IF ( bCutsceneSkipped = FALSE )
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
IF HAS_ANIM_DICT_LOADED("missfam3")
TASK_PLAY_ANIM_ADVANCED(PLAYER_PED_ID(), "missfam3", "argument_outro_michael",
<< -993.200, 646.188, 139.520 >>, << 0.0, 0.0, -93.24 >>,
INSTANT_BLEND_IN, SLOW_BLEND_OUT, -1,
AF_EXTRACT_INITIAL_OFFSET | AF_USE_KINEMATIC_PHYSICS | AF_HOLD_LAST_FRAME | AF_TAG_SYNC_OUT)
FORCE_PED_AI_AND_ANIMATION_UPDATE(PLAYER_PED_ID(), TRUE)
ENDIF
ENDIF
ENDIF
ENDIF
IF CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY("Franklin")
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY() returned true for Franklin.")
#ENDIF
IF ( bCutsceneSkipped = FALSE )
IF NOT IS_PED_INJURED(psFranklin.PedIndex)
IF IS_VEHICLE_DRIVEABLE(vsPlayersCar.VehicleIndex)
SET_PED_INTO_VEHICLE(psFranklin.PedIndex, vsPlayersCar.VehicleIndex, VS_FRONT_RIGHT)
ENDIF
ENDIF
ENDIF
ENDIF
IF CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY("Fam3_tow_truck")
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY() returned true for Fam3_tow_truck.")
#ENDIF
IF ( bCutsceneSkipped = FALSE )
IF IS_VEHICLE_DRIVEABLE(vsPlayersCar.VehicleIndex)
SET_VEHICLE_DOOR_OPEN(vsPlayersCar.VehicleIndex, SC_DOOR_BOOT, FALSE, TRUE)
ENDIF
ENDIF
ENDIF
IF CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY("TennisCoach")
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY() returned true for TennisCoach.")
#ENDIF
IF NOT IS_PED_INJURED(psCoach.PedIndex)
TASK_PLAY_ANIM(psCoach.PedIndex, "missfam3", "coach_idle", SLOW_BLEND_IN, SLOW_BLEND_OUT, -1, AF_LOOPING)
ENDIF
ENDIF
IF NOT DOES_ENTITY_EXIST(osRopeDummy.ObjectIndex)
IF HAS_MISSION_OBJECT_BEEN_CREATED(osRopeDummy, TRUE)
SET_ENTITY_COLLISION(osRopeDummy.ObjectIndex, TRUE)
SET_ENTITY_NO_COLLISION_ENTITY(osRopeDummy.ObjectIndex, PLAYER_PED_ID(), FALSE)
SET_ENTITY_NO_COLLISION_ENTITY(vsPlayersCar.VehicleIndex, osRopeDummy.ObjectIndex, FALSE)
SET_CAN_CLIMB_ON_ENTITY(osRopeDummy.ObjectIndex, FALSE)
SET_CAN_AUTO_VAULT_ON_ENTITY(osRopeDummy.ObjectIndex, FALSE)
ENDIF
ENDIF
IF ( bMusicEventHookedUpTriggered = FALSE )
IF GET_CUTSCENE_TIME() > 39500
IF TRIGGER_MUSIC_EVENT("FAM3_HOOKED_UP")
bMusicEventHookedUpTriggered = TRUE
ENDIF
ENDIF
ENDIF
IF ( bRopeAttached = FALSE )
IF ( bCutsceneSkipped = FALSE )
IF GET_CUTSCENE_TIME() > 58000.0
IF NOT DOES_ENTITY_EXIST(osRopeProp.ObjectIndex)
IF HAS_MISSION_OBJECT_BEEN_CREATED(osRopeProp, TRUE)
SET_CAN_CLIMB_ON_ENTITY(osRopeProp.ObjectIndex, FALSE)
SET_CAN_AUTO_VAULT_ON_ENTITY(osRopeProp.ObjectIndex, FALSE)
ENDIF
ENDIF
IF NOT DOES_ROPE_EXIST(Rope)
ROPE_LOAD_TEXTURES()
IF ROPE_ARE_TEXTURES_LOADED()
Rope = ADD_ROPE(<<-1017.9850, 660.4285, 147.4662>>, <<0.0, 0.0, 0.0>>, ROPE_MAX_LEN, PHYSICS_ROPE_DEFAULT, -1, 0.5, 0.5, FALSE, TRUE)
LOAD_ROPE_DATA(Rope, ROPE_DATA_FILE )
ENDIF
ENDIF
IF DOES_ENTITY_EXIST(osRopeAnchor.ObjectIndex)
AND DOES_ROPE_EXIST(rope)
IF DOES_ENTITY_HAVE_PHYSICS(osRopeAnchor.ObjectIndex)
IF IS_VEHICLE_DRIVEABLE(vsPlayersCar.VehicleIndex)
SET_VEHICLE_DOORS_SHUT(vsPlayersCar.VehicleIndex, TRUE)
ATTACH_ENTITIES_TO_ROPE(Rope, osRopeAnchor.ObjectIndex, vsPlayersCar.VehicleIndex, osRopeAnchor.vPosition, GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(vsPlayersCar.VehicleIndex, << 0.0, -2.1, 0.6 >>), 35.0, 0, 0)
bRopeAttached = TRUE
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
IF HAS_CUTSCENE_FINISHED()
SET_PLAYER_CONTROL(PLAYER_ID(), TRUE)
SET_SCRIPTS_SAFE_FOR_CUTSCENE(FALSE)
IF ( bCutsceneSkipped = TRUE ) //cutscene was skipped
IF ROPE_ARE_TEXTURES_LOADED()
AND HAS_ANIM_DICT_LOADED("missfam3")
AND HAS_MODEL_LOADED(osRopeDummy.ModelName)
IF IS_VEHICLE_DRIVEABLE(vsPlayersCar.VehicleIndex)
SET_VEHICLE_DOORS_SHUT(vsPlayersCar.VehicleIndex, TRUE)
SET_VEHICLE_DOOR_OPEN(vsPlayersCar.VehicleIndex, SC_DOOR_BOOT)
SET_VEHICLE_ON_GROUND_PROPERLY(vsPlayersCar.VehicleIndex)
ENDIF
IF ( bRopeAttached = FALSE )
IF NOT DOES_ENTITY_EXIST(osRopeProp.ObjectIndex)
IF HAS_MISSION_OBJECT_BEEN_CREATED(osRopeProp, TRUE)
SET_CAN_CLIMB_ON_ENTITY(osRopeProp.ObjectIndex, FALSE)
SET_CAN_AUTO_VAULT_ON_ENTITY(osRopeProp.ObjectIndex, FALSE)
ENDIF
ENDIF
IF NOT DOES_ROPE_EXIST(Rope)
IF ROPE_ARE_TEXTURES_LOADED()
Rope = ADD_ROPE(<<-1017.9850, 660.4285, 147.4662>>, <<0.0, 0.0, 0.0>>, ROPE_MAX_LEN, PHYSICS_ROPE_DEFAULT, -1, 0.5, 0.5, FALSE, TRUE)
LOAD_ROPE_DATA(Rope, ROPE_DATA_FILE)
ENDIF
ENDIF
IF DOES_ENTITY_EXIST(osRopeAnchor.ObjectIndex)
AND DOES_ROPE_EXIST(rope)
IF DOES_ENTITY_HAVE_PHYSICS(osRopeAnchor.ObjectIndex)
IF IS_VEHICLE_DRIVEABLE(vsPlayersCar.VehicleIndex)
ATTACH_ENTITIES_TO_ROPE(Rope, osRopeAnchor.ObjectIndex, vsPlayersCar.VehicleIndex, osRopeAnchor.vPosition, GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(vsPlayersCar.VehicleIndex, << 0.0, -2.1, 0.6 >>), 35.0, 0, 0)
bRopeAttached = TRUE
ENDIF
ENDIF
ENDIF
ENDIF
IF NOT DOES_ENTITY_EXIST(osRopeDummy.ObjectIndex)
IF HAS_MISSION_OBJECT_BEEN_CREATED(osRopeDummy, TRUE)
SET_ENTITY_COLLISION(osRopeDummy.ObjectIndex, TRUE)
SET_ENTITY_NO_COLLISION_ENTITY(osRopeDummy.ObjectIndex, PLAYER_PED_ID(), FALSE)
SET_ENTITY_NO_COLLISION_ENTITY(vsPlayersCar.VehicleIndex, osRopeDummy.ObjectIndex, FALSE)
SET_CAN_CLIMB_ON_ENTITY(osRopeDummy.ObjectIndex, FALSE)
SET_CAN_AUTO_VAULT_ON_ENTITY(osRopeDummy.ObjectIndex, FALSE)
ENDIF
ENDIF
WAIT(1000)
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
IF HAS_ANIM_DICT_LOADED("missfam3")
TASK_PLAY_ANIM_ADVANCED(PLAYER_PED_ID(), "missfam3", "argument_outro_michael",
<< -993.200, 646.188, 139.520 >>, << 0.0, 0.0, -93.240 >>,
INSTANT_BLEND_IN, SLOW_BLEND_OUT, -1,
AF_EXTRACT_INITIAL_OFFSET | AF_USE_KINEMATIC_PHYSICS | AF_HOLD_LAST_FRAME | AF_TAG_SYNC_OUT)
FORCE_PED_AI_AND_ANIMATION_UPDATE(PLAYER_PED_ID(), TRUE)
ENDIF
ENDIF
IF NOT IS_PED_INJURED(psFranklin.PedIndex)
IF IS_VEHICLE_DRIVEABLE(vsPlayersCar.VehicleIndex)
IF NOT IS_PED_IN_VEHICLE(psFranklin.PedIndex, vsPlayersCar.VehicleIndex)
SET_PED_INTO_VEHICLE(psFranklin.PedIndex, vsPlayersCar.VehicleIndex, VS_FRONT_RIGHT)
ENDIF
ENDIF
ENDIF
STOP_GAMEPLAY_HINT(TRUE)
SET_GAMEPLAY_CAM_RELATIVE_PITCH(0)
SET_GAMEPLAY_CAM_RELATIVE_HEADING(0)
IF IS_SCREEN_FADED_OUT()
DO_SCREEN_FADE_IN(DEFAULT_FADE_TIME)
ENDIF
iStageProgress++
ENDIF
ELSE //cutscene not skipped
IF IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(), "missfam3", "argument_outro_michael")
iStageProgress++
ENDIF
ENDIF
ELSE
//if cutscene is skipped, fade out and remain cutscene on faded out screen
IF ( bCutsceneSkipped = FALSE )
IF WAS_CUTSCENE_SKIPPED()
SET_CUTSCENE_FADE_VALUES(FALSE, FALSE, FALSE, FALSE)
bCutsceneSkipped = TRUE
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Mocap cutscene was skipped by the player.")
#ENDIF
ENDIF
ENDIF
ENDIF
BREAK
CASE 3
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
IF IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(), "missfam3", "argument_outro_michael")
DISABLE_ON_FOOT_FIRST_PERSON_VIEW_THIS_UPDATE()
DISABLE_CONTROL_ACTION(CAMERA_CONTROL, INPUT_NEXT_CAMERA)
IF NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_HKD")
IF CREATE_CONVERSATION_FROM_SPECIFIC_LINE(sFamily3Conversation, "FAM3AUD", "FAM3_HKD", "FAM3_HKD_3", CONV_PRIORITY_MEDIUM)
SET_LABEL_AS_TRIGGERED("FAM3_HKD", TRUE)
ENDIF
ENDIF
IF GET_ENTITY_ANIM_CURRENT_TIME(PLAYER_PED_ID(), "missfam3", "argument_outro_michael") >= 0.95
CLEAR_PED_TASKS(PLAYER_PED_ID())
SET_PED_STEALTH_MOVEMENT(PLAYER_PED_ID(), FALSE)
SET_PED_USING_ACTION_MODE(PLAYER_PED_ID(), FALSE)
FORCE_PED_MOTION_STATE(PLAYER_PED_ID(), MS_ON_FOOT_WALK, FALSE, FAUS_DEFAULT)
SIMULATE_PLAYER_INPUT_GAIT(PLAYER_ID(), PEDMOVE_WALK, 500)
ELIF GET_ENTITY_ANIM_CURRENT_TIME(PLAYER_PED_ID(), "missfam3", "argument_outro_michael") >= fFirstPersonFlashPhase1
IF GET_CAM_VIEW_MODE_FOR_CONTEXT(CAM_VIEW_MODE_CONTEXT_ON_FOOT) = CAM_VIEW_MODE_FIRST_PERSON
IF ( bFirstPersonFlashPlayed = FALSE )
ANIMPOSTFX_PLAY("CamPushInNeutral", 0, FALSE)
PLAY_SOUND_FRONTEND(-1, "1st_Person_Transition", "PLAYER_SWITCH_CUSTOM_SOUNDSET")
bFirstPersonFlashPlayed = TRUE
ENDIF
ENDIF
ENDIF
ELSE
IF DOES_ENTITY_EXIST(osRopeDummy.ObjectIndex)
IF NOT IS_ENTITY_DEAD(osRopeDummy.ObjectIndex)
IF IS_VEHICLE_DRIVEABLE(vsPlayersCar.VehicleIndex)
SET_ENTITY_COLLISION(osRopeDummy.ObjectIndex, TRUE)
SET_ENTITY_NO_COLLISION_ENTITY(osRopeDummy.ObjectIndex, PLAYER_PED_ID(), TRUE)
SET_ENTITY_NO_COLLISION_ENTITY(vsPlayersCar.VehicleIndex, osRopeDummy.ObjectIndex, FALSE)
ENDIF
ENDIF
ENDIF
IF NOT DOES_ENTITY_EXIST(osBootCollision.ObjectIndex)
IF HAS_MISSION_OBJECT_BEEN_CREATED(osBootCollision, TRUE)
SET_ENTITY_COLLISION(osBootCollision.ObjectIndex, TRUE)
SET_ENTITY_NO_COLLISION_ENTITY(osBootCollision.ObjectIndex, vsPlayersCar.VehicleIndex, FALSE)
ENDIF
ENDIF
//fix for B*2028269 - force the player to look at the truck on cut to first person on foot
IF GET_CAM_VIEW_MODE_FOR_CONTEXT(CAM_VIEW_MODE_CONTEXT_ON_FOOT) = CAM_VIEW_MODE_FIRST_PERSON
SET_ENTITY_HEADING(PLAYER_PED_ID(), 247.8959)
SET_GAMEPLAY_CAM_RELATIVE_PITCH(-15.0)
SET_GAMEPLAY_CAM_RELATIVE_HEADING(0.0)
//ANIMPOSTFX_PLAY("SwitchSceneMichael", 0, FALSE)
ENDIF
SET_MODEL_AS_NO_LONGER_NEEDED(osRopeDummy.ModelName)
TRIGGER_MUSIC_EVENT("FAM3_TRUCK_PULL")
REPLAY_STOP_EVENT()
RETURN TRUE
ENDIF
ENDIF
BREAK
ENDSWITCH
RETURN FALSE
ENDFUNC
PROC MANAGE_TENNIS_COACH_DURING_PULL_HOUSE_DOWN()
IF DOES_ENTITY_EXIST(psCoach.PedIndex)
IF NOT IS_ENTITY_DEAD(psCoach.PedIndex)
SWITCH psCoach.iProgress
CASE 0
IF NOT IS_ENTITY_PLAYING_ANIM(psCoach.PedIndex, "missfam3", "coach_idle")
TASK_PLAY_ANIM(psCoach.PedIndex, "missfam3", "coach_idle", INSTANT_BLEND_IN, INSTANT_BLEND_OUT, -1, AF_LOOPING)
ENDIF
//PLAY_PED_AMBIENT_SPEECH_WITH_VOICE(psCoach.PedIndex, "FAM3_AAAA", "TENNISCOACH", SPEECH_PARAMS_FORCE_PRELOAD_ONLY_SHOUTED)
psCoach.iProgress++
BREAK
CASE 1
IF ( bRayfireStarted = TRUE )
IF NOT IS_SYNCHRONIZED_SCENE_RUNNING(iSyncedSceneCoachID)
CLEAR_PED_TASKS(psCoach.PedIndex)
iSyncedSceneCoachID = CREATE_SYNCHRONIZED_SCENE(<< -1014.525, 654.250, 156.175 >>, << 0.000, 0.000, -103.320 >>)
TASK_SYNCHRONIZED_SCENE(psCoach.PedIndex, iSyncedSceneCoachID, "missfam3", "argument_outro_coach", INSTANT_BLEND_IN, INSTANT_BLEND_OUT)
SET_SYNCHRONIZED_SCENE_PHASE(iSyncedSceneCoachID, 0.6125)
ENDIF
psCoach.iProgress++
ENDIF
BREAK
CASE 2
IF IS_SYNCHRONIZED_SCENE_RUNNING(iSyncedSceneCoachID)
/*
IF NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_AAAA_1")
//IF NOT IS_AMBIENT_SPEECH_PLAYING(psCoach.PedIndex)
//PLAY_PED_AMBIENT_SPEECH_WITH_VOICE(psCoach.PedIndex, "FAM3_AAAA", "TENNISCOACH", SPEECH_PARAMS_FORCE_FRONTEND)
PLAY_PRELOADED_SPEECH(psCoach.PedIndex)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Trying to play ped ambient speech FAM3_AAAA.")
#ENDIF
//ELSE
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Playing ped ambient speech FAM3_AAAA.")
#ENDIF
SET_LABEL_AS_TRIGGERED("FAM3_AAAA_1", TRUE)
//ENDIF
ENDIF
*/
IF ( GET_SYNCHRONIZED_SCENE_PHASE(iSyncedSceneCoachID) > 0.95 )
STOP_SYNCHRONIZED_ENTITY_ANIM(psCoach.PedIndex, INSTANT_BLEND_OUT, TRUE)
CLEAR_PED_TASKS(psCoach.PedIndex)
WARP_PED(psCoach.PedIndex, <<-1021.5886, 663.7698, 155.2747>>, 178.5320, FALSE, FALSE, FALSE)
//PLAY_PED_AMBIENT_SPEECH_WITH_VOICE(psCoach.PedIndex, "FAM3_AAAA", "TENNISCOACH", SPEECH_PARAMS_FORCE_PRELOAD_ONLY_SHOUTED)
psCoach.iProgress++
ENDIF
ENDIF
BREAK
CASE 3
IF ( iRayfireSequenceProgress >= 2 )
IF NOT IS_SYNCHRONIZED_SCENE_RUNNING(iSyncedSceneCoachID)
CLEAR_PED_TASKS(psCoach.PedIndex)
iSyncedSceneCoachID = CREATE_SYNCHRONIZED_SCENE(<< -1034.000, 662.100, 156.100 >>, << 0.000, 0.000, -165.960 >>)
TASK_SYNCHRONIZED_SCENE(psCoach.PedIndex, iSyncedSceneCoachID, "missfam3", "argument_outro_coach", INSTANT_BLEND_IN, INSTANT_BLEND_OUT)
SET_SYNCHRONIZED_SCENE_PHASE(iSyncedSceneCoachID, 0.830)
psCoach.iProgress++
ENDIF
ENDIF
BREAK
CASE 4
IF NOT IS_PED_INJURED(psCoach.PedIndex)
IF IS_SYNCHRONIZED_SCENE_RUNNING(iSyncedSceneCoachID)
/*
IF NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_AAAA_2")
IF NOT IS_AMBIENT_SPEECH_PLAYING(psCoach.PedIndex)
//PLAY_PED_AMBIENT_SPEECH_WITH_VOICE(psCoach.PedIndex, "FAM3_AAAA", "TENNISCOACH", SPEECH_PARAMS_FORCE_FRONTEND)
PLAY_PRELOADED_SPEECH(psCoach.PedIndex)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Trying to play ped ambient speech FAM3_AAAA.")
#ENDIF
ELSE
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Playing ped ambient speech FAM3_AAAA.")
#ENDIF
SET_LABEL_AS_TRIGGERED("FAM3_AAAA_2", TRUE)
ENDIF
ENDIF
*/
IF ( GET_SYNCHRONIZED_SCENE_PHASE(iSyncedSceneCoachID) > 0.98 )
STOP_SYNCHRONIZED_ENTITY_ANIM(psCoach.PedIndex, INSTANT_BLEND_OUT, TRUE)
CLEAR_PED_TASKS(psCoach.PedIndex)
DELETE_PED(psCoach.PedIndex)
psCoach.iProgress++
ENDIF
ENDIF
ENDIF
BREAK
ENDSWITCH
ENDIF
ENDIF
ENDPROC
PROC MANAGE_PLAYERS_VEHICLE_IN_RAYFIRE_SEQUENCE(INT &iProgress)
SWITCH iProgress
CASE 0
IF ( bHousePullCompleted = TRUE )
BRING_VEHICLE_TO_HALT_AND_DISABLE_VEH_CONTROLS(vsPlayersCar.VehicleIndex, 3.0, 3)
IF ( iRayfireMapObjectProgress = 8 )
IF IS_VEHICLE_DRIVEABLE(vsPlayersCar.VehicleIndex)
TASK_PLAY_LOOK_BEHIND_ANIM(PLAYER_PED_ID(), VS_DRIVER, 5000)
TASK_PLAY_LOOK_BEHIND_ANIM(psFranklin.PedIndex, VS_FRONT_RIGHT, 6000)
iProgress++
ENDIF
ENDIF
ENDIF
BREAK
ENDSWITCH
ENDPROC
PROC MANAGE_RAYFIRE_MAP_OBJECT(INT &iProgress, BOOL &bStarted, BOOL &bPaused, BOOL &bPrimed, BOOL &bFinished, FLOAT &fPhase)
IF DOES_RAYFIRE_MAP_OBJECT_EXIST(riHouseFallRayfire)
IF ( GET_STATE_OF_RAYFIRE_MAP_OBJECT(riHouseFallRayfire) = RFMO_STATE_ANIMATING )
fPhase = GET_RAYFIRE_MAP_OBJECT_ANIM_PHASE(riHouseFallRayfire)
ENDIF
ENDIF
SWITCH iProgress
CASE 0 //priming rayfire map object until it is primed
riHouseFallRayfire = GET_RAYFIRE_MAP_OBJECT(<<-1020.50, 663.41, 154.75>>, 50, "DES_StiltHouse")
IF DOES_RAYFIRE_MAP_OBJECT_EXIST(riHouseFallRayfire)
IF ( GET_STATE_OF_RAYFIRE_MAP_OBJECT(riHouseFallRayfire) <> RFMO_STATE_PRIMED ) //rayfire not primed
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Waiting for rayfire map object state to be RFMO_STATE_PRIMED.")
#ENDIF
IF ( GET_STATE_OF_RAYFIRE_MAP_OBJECT(riHouseFallRayfire) <> RFMO_STATE_PRIMING ) //rayfire not priming
SET_STATE_OF_RAYFIRE_MAP_OBJECT(riHouseFallRayfire, RFMO_STATE_PRIMING) //prime the rayfire
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Rayfire map object state set to RFMO_STATE_PRIMING.")
#ENDIF
ENDIF
ELIF ( GET_STATE_OF_RAYFIRE_MAP_OBJECT(riHouseFallRayfire) = RFMO_STATE_PRIMED ) //rayfire is primed, move on
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Rayfire map object state is RFMO_STATE_PRIMED.")
#ENDIF
bPrimed = TRUE
iProgress++
ENDIF
ENDIF
BREAK
CASE 1 //rayfire map object primed, start the animation
IF DOES_RAYFIRE_MAP_OBJECT_EXIST(riHouseFallRayfire)
IF GET_STATE_OF_RAYFIRE_MAP_OBJECT(riHouseFallRayfire) = RFMO_STATE_PRIMED
IF ( bStarted = TRUE )
SET_STATE_OF_RAYFIRE_MAP_OBJECT(riHouseFallRayfire, RFMO_STATE_START_ANIM)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Rayfire map object state set to RFMO_STATE_START_ANIM.")
#ENDIF
iProgress++
ENDIF
ENDIF
ENDIF
BREAK
CASE 2 //rayfire started animating, set the first pause at 0.120 of animation phase
IF DOES_RAYFIRE_MAP_OBJECT_EXIST(riHouseFallRayfire)
IF ( GET_STATE_OF_RAYFIRE_MAP_OBJECT(riHouseFallRayfire) = RFMO_STATE_ANIMATING )
IF ( bPaused = FALSE )
IF ( GET_RAYFIRE_MAP_OBJECT_ANIM_PHASE(riHouseFallRayfire) > 0.1475 )//0.120 )
SET_STATE_OF_RAYFIRE_MAP_OBJECT(riHouseFallRayfire, RFMO_STATE_PAUSE)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Rayfire map object state set to RFMO_STATE_PAUSE.")
#ENDIF
bPaused = TRUE
SETTIMERB(0)
iProgress++
ENDIF
ENDIF
ENDIF
ENDIF
BREAK
CASE 3 //first pause in progress, wait until pause flag is set to false
IF DOES_RAYFIRE_MAP_OBJECT_EXIST(riHouseFallRayfire)
IF ( bPaused = FALSE )
IF ( GET_STATE_OF_RAYFIRE_MAP_OBJECT(riHouseFallRayfire) = RFMO_STATE_PAUSE )
SET_STATE_OF_RAYFIRE_MAP_OBJECT(riHouseFallRayfire, RFMO_STATE_RESUME)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Rayfire map object state set to RFMO_STATE_RESUME.")
#ENDIF
iProgress++
ENDIF
ENDIF
ENDIF
BREAK
CASE 4 //rayfire resumed animating after first pause, set the second pause at 0.350 of animation phase
IF DOES_RAYFIRE_MAP_OBJECT_EXIST(riHouseFallRayfire)
IF ( GET_STATE_OF_RAYFIRE_MAP_OBJECT(riHouseFallRayfire) = RFMO_STATE_ANIMATING )
IF ( bPaused = FALSE )
IF ( GET_RAYFIRE_MAP_OBJECT_ANIM_PHASE(riHouseFallRayfire) >= 0.433 ) //0.350 )
SET_STATE_OF_RAYFIRE_MAP_OBJECT(riHouseFallRayfire, RFMO_STATE_PAUSE)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Rayfire map object state set to RFMO_STATE_PAUSE.")
#ENDIF
bPaused = TRUE
SETTIMERB(0)
iProgress++
ENDIF
ENDIF
ENDIF
ENDIF
BREAK
CASE 5 //second pause in progress, wait until pause flag is set to false
IF DOES_RAYFIRE_MAP_OBJECT_EXIST(riHouseFallRayfire)
IF ( bPaused = FALSE )
IF ( GET_STATE_OF_RAYFIRE_MAP_OBJECT(riHouseFallRayfire) = RFMO_STATE_PAUSE )
SET_STATE_OF_RAYFIRE_MAP_OBJECT(riHouseFallRayfire, RFMO_STATE_RESUME)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Rayfire map object state set to RFMO_STATE_RESUME.")
#ENDIF
iProgress++
ENDIF
ENDIF
ENDIF
BREAK
CASE 6 //set the ending state of rayfire map object when specific phase is reached or when rayfire cutscene is skipped
//keep requesting ptfx assets, this should be in memory already since it was needed for wheel spin dirt
REQUEST_PTFX_ASSET()
IF DOES_RAYFIRE_MAP_OBJECT_EXIST(riHouseFallRayfire)
IF ( GET_STATE_OF_RAYFIRE_MAP_OBJECT(riHouseFallRayfire) = RFMO_STATE_ANIMATING )
IF ( GET_RAYFIRE_MAP_OBJECT_ANIM_PHASE(riHouseFallRayfire) > 0.875 )
OR ( bCutsceneSkipped = TRUE )
IF ( bCutsceneSkipped = TRUE )
SET_STATE_OF_RAYFIRE_MAP_OBJECT(riHouseFallRayfire, RFMO_STATE_ENDING)
ENDIF
IF NOT DOES_PARTICLE_FX_LOOPED_EXIST(ptfxDustCloud)
IF HAS_PTFX_ASSET_LOADED()
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Starting particle fx ent_ray_fam3_dust_settle.")
#ENDIF
ptfxDustCloud = START_PARTICLE_FX_LOOPED_AT_COORD("ent_ray_fam3_dust_settle", << -1016.0, 642.0, 141.0 >>, << 0.0, 0.0, 0.0 >>)
ENDIF
ENDIF
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Rayfire map object state set to RFMO_STATE_ENDING.")
#ENDIF
iProgress++
ENDIF
ENDIF
ENDIF
BREAK
CASE 7 //check if end state was reached
IF DOES_RAYFIRE_MAP_OBJECT_EXIST(riHouseFallRayfire)
IF ( GET_STATE_OF_RAYFIRE_MAP_OBJECT(riHouseFallRayfire) = RFMO_STATE_END )
bFinished = TRUE
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Rayfire map object state is RFMO_STATE_END.")
#ENDIF
PLAY_SOUND_FROM_COORD(-1, "FAMILY3_POST_DEBRIS_MASTER", << -1016.0, 642.0, 141.0 >>)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Playing sound FAMILY3_POST_DEBRIS_MASTER.")
#ENDIF
iProgress++
ENDIF
ENDIF
BREAK
CASE 8
//rayfire map object can only be in end state at this point
BREAK
ENDSWITCH
ENDPROC
PROC UPDATE_FORCES(VEHICLE_INDEX VehicleIndex)
IF DOES_ENTITY_EXIST(VehicleIndex)
IF NOT IS_ENTITY_DEAD(VehicleIndex)
IF IS_ENTITY_UPRIGHT(VehicleIndex) AND IS_VEHICLE_ON_ALL_WHEELS(VehicleIndex)
VECTOR vForce
FLOAT fForceModifier = 0.0 +@ (fForceConverge * 30.0)//CLAMP(0.0 +@ (fForceConverge * 30.0), 0.0, 1.0)
INT iTurnValue = ROUND(GET_CONTROL_NORMAL(PLAYER_CONTROL, INPUT_VEH_MOVE_LR) * 255.0)
INT iAccelerateValue = ROUND(GET_CONTROL_NORMAL(PLAYER_CONTROL, INPUT_VEH_ACCELERATE) * 255.0)
IF IS_DISABLED_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_VEH_BRAKE)
OR IS_DISABLED_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_VEH_HANDBRAKE)
OR IS_DISABLED_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_VEH_DUCK)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_ACCELERATE)
iAccelerateValue = 0
ENDIF
#IF IS_DEBUG_BUILD
IF ( bDrawDebugLinesAndSpheres = TRUE )
DRAW_DEBUG_TEXT_ABOVE_ENTITY(VehicleIndex, GET_STRING_FROM_FLOAT(fForceModifier), 1.5)
DRAW_DEBUG_TEXT_ABOVE_ENTITY(vsPlayersCar.VehicleIndex, GET_STRING_FROM_FLOAT(GET_ENTITY_HEADING(vsPlayersCar.VehicleIndex)), 1.25)
DRAW_DEBUG_SPHERE(GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(VehicleIndex, vForceBackOffset), 0.3, 0, 0, 255)
ENDIF
#ENDIF
IF ( iAccelerateValue >= 250 )
IF GET_ENTITY_HEADING(VehicleIndex) >= 287.0
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Heading more than 290.")
#ENDIF
vForce = << - ABSF(fSideForceValue * fForceModifier), 0.0, 0.0 >>
APPLY_FORCE_TO_ENTITY(VehicleIndex, APPLY_TYPE_IMPULSE, vForce, vForceBackOffset, 0, TRUE, TRUE, FALSE)
iApplyForceTimer = 0
ENDIF
IF ( iTurnValue >=225 )
IF GET_ENTITY_HEADING(VehicleIndex) > 265.0
vForce = << - ABSF(fSideForceValue * fForceModifier), 0.0, 0.0 >>
APPLY_FORCE_TO_ENTITY(VehicleIndex, APPLY_TYPE_IMPULSE, vForce, vForceBackOffset, 0, TRUE, TRUE, FALSE)
iApplyForceTimer = 0
ENDIF
ELIF ( iTurnValue <= -225 )
IF GET_ENTITY_HEADING(VehicleIndex) < 285.0
vForce = << ABSF(fSideForceValue * fForceModifier), 0.0, 0.0 >>
APPLY_FORCE_TO_ENTITY(VehicleIndex, APPLY_TYPE_IMPULSE, vForce, vForceBackOffset, 0, TRUE, TRUE, FALSE)
iApplyForceTimer = 0
ENDIF
ENDIF
IF ( iTurnValue = 0)
IF ( iApplyForceTimer = 0 )
iApplyForceTimer = GET_GAME_TIMER()
SWITCH GET_RANDOM_INT_IN_RANGE(0, 2)
CASE 0
iApplyForceSide = 1
BREAK
CASE 1
iApplyForceSide = -1
BREAK
ENDSWITCH
ELSE
IF GET_GAME_TIMER() - iApplyForceTimer < 1000
vForce = << ABSF(fSideForceValue * fForceModifier) * iApplyForceSide, 0.0, 0.0 >>
APPLY_FORCE_TO_ENTITY(VehicleIndex, APPLY_TYPE_IMPULSE, vForce, vForceBackOffset, 0, TRUE, TRUE, FALSE)
iApplyForceTimer = 0
ENDIF
ENDIF
ENDIF
vForce = << 0.0, 0.0, - ABSF(fDownForceValue * fForceModifier) >>
APPLY_FORCE_TO_ENTITY(VehicleIndex, APPLY_TYPE_IMPULSE, vForce, vForceBackOffset, 0, TRUE, TRUE, FALSE)
ELSE
iApplyForceTimer = 0
ENDIF
ENDIF
ENDIF
ENDIF
ENDPROC
FUNC BOOL IS_PULL_COMPLETED(BOOL &bPullInProgress, FLOAT fBurnoutTime, VECTOR vPullStartPosition, FLOAT fPullDistance)
VECTOR vPlayerCarPosition = GET_ENTITY_COORDS(vsPlayersCar.VehicleIndex)
INT iAccelerateValue = ROUND(GET_CONTROL_NORMAL(PLAYER_CONTROL, INPUT_VEH_ACCELERATE) * 255.0)
FLOAT fDistanceFromStart = GET_DISTANCE_BETWEEN_COORDS(<< vPullStartPosition.X, vPullStartPosition.Y, vPlayerCarPosition.Z >>, vPlayerCarPosition)
IF IS_DISABLED_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_VEH_BRAKE)
OR IS_DISABLED_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_VEH_HANDBRAKE)
OR IS_DISABLED_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_VEH_DUCK)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_ACCELERATE)
iAccelerateValue = 0
ENDIF
#IF IS_DEBUG_BUILD
IF ( bDrawDebugLinesAndSpheres = TRUE )
DRAW_DEBUG_TEXT_ABOVE_ENTITY(vsPlayersCar.VehicleIndex, GET_STRING_FROM_FLOAT(fDistanceFromStart), 0.5)
ENDIF
#ENDIF
IF IS_VEHICLE_DRIVEABLE(vsPlayersCar.VehicleIndex)
IF ( IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_VEH_ACCELERATE) AND iAccelerateValue <> 0 )
OR ( iAccelerateValue >= 250 )
IF IS_THIS_HELP_MESSAGE_BEING_DISPLAYED("FAM3_HPULL")
CLEAR_HELP()
ENDIF
IF ( bPullInProgress = FALSE )
SETTIMERA(0) //used to shake the pad
SHAKE_GAMEPLAY_CAM("SKY_DIVING_SHAKE", 0.0)
bPullInProgress = TRUE
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Player started pulling.")
#ENDIF
ENDIF
ELSE
IF NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_HPULL")
IF NOT IS_HELP_MESSAGE_BEING_DISPLAYED()
PRINT_HELP_FOREVER("FAM3_HPULL")
SET_LABEL_AS_TRIGGERED("FAM3_HPULL", TRUE)
ENDIF
ENDIF
IF ( bPullInProgress = TRUE )
bPullInProgress = FALSE
IF ( bPTFXStarted = TRUE )
IF DOES_PARTICLE_FX_LOOPED_EXIST(ptfxRearLeftWheel)
SET_PARTICLE_FX_LOOPED_EVOLUTION(ptfxRearLeftWheel, "wheelspin", fWheelspinValue)
STOP_PARTICLE_FX_LOOPED(ptfxRearLeftWheel)
ENDIF
IF DOES_PARTICLE_FX_LOOPED_EXIST(ptfxRearRightWheel)
SET_PARTICLE_FX_LOOPED_EVOLUTION(ptfxRearRightWheel, "wheelspin", fWheelspinValue)
STOP_PARTICLE_FX_LOOPED(ptfxRearRightWheel)
ENDIF
bPTFXStarted = FALSE
ENDIF
STOP_GAMEPLAY_CAM_SHAKING()
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Player stopped pulling.")
#ENDIF
ENDIF
ENDIF
IF ( bPullInProgress = TRUE )
//temporary shake value, this needs a proper value setting
SET_CONTROL_SHAKE(PLAYER_CONTROL, 100, GET_MINIMUM_INT(FLOOR(TO_FLOAT(TIMERA()) / 12.5), 255))
IF ( bPTFXStarted = FALSE )
IF HAS_PTFX_ASSET_LOADED()
IF NOT DOES_PARTICLE_FX_LOOPED_EXIST(ptfxRearLeftWheel)
AND NOT DOES_PARTICLE_FX_LOOPED_EXIST(ptfxRearRightWheel)
ptfxRearLeftWheel = START_PARTICLE_FX_LOOPED_ON_ENTITY("scr_fam3_wheelspin_dirt", vsPlayersCar.VehicleIndex, vRearLeftWheelOffset, vPTFXRotation)
ptfxRearRightWheel = START_PARTICLE_FX_LOOPED_ON_ENTITY("scr_fam3_wheelspin_dirt", vsPlayersCar.VehicleIndex, vRearRightWheelOffset, vPTFXRotation)
bPTFXStarted = TRUE
//play rope straining sound
PLAY_SOUND_FROM_ENTITY(-1, "FAMILY3_CABLE_STRAIN_MASTER", vsPlayersCar.VehicleIndex)
ENDIF
ENDIF
ELIF ( bPTFXStarted = TRUE )
IF DOES_PARTICLE_FX_LOOPED_EXIST(ptfxRearLeftWheel)
AND DOES_PARTICLE_FX_LOOPED_EXIST(ptfxRearRightWheel)
SET_PARTICLE_FX_LOOPED_EVOLUTION(ptfxRearLeftWheel, "wheelspin", fWheelspinValue)
SET_PARTICLE_FX_LOOPED_EVOLUTION(ptfxRearRightWheel, "wheelspin", fWheelspinValue)
ENDIF
ENDIF
#IF IS_DEBUG_BUILD
IF ( bPrintDebugOutput = TRUE )
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Pulling time is ", TIMERA())
ENDIF
#ENDIF
ENDIF
IF ( bPullInProgress = TRUE )
IF ( TIMERA() > fBurnoutTime )
SET_VEHICLE_BURNOUT(vsPlayersCar.VehicleIndex, FALSE)
ENDIF
IF ( TIMERA() > fBurnoutTime AND fDistanceFromStart > fPullDistance )
OR ( fDistanceFromStart > fPullDistance * 2 )
OR ( TIMERA() > fBurnoutTime + 1500)
SET_VEHICLE_BURNOUT(vsPlayersCar.VehicleIndex, FALSE)
SET_VEHICLE_FORWARD_SPEED(vsPlayersCar.VehicleIndex, 2.0)
IF DOES_PARTICLE_FX_LOOPED_EXIST(ptfxRearLeftWheel)
AND DOES_PARTICLE_FX_LOOPED_EXIST(ptfxRearRightWheel)
fWheelspinValue = 0.0
SET_PARTICLE_FX_LOOPED_EVOLUTION(ptfxRearLeftWheel, "wheelspin", fWheelspinValue)
SET_PARTICLE_FX_LOOPED_EVOLUTION(ptfxRearRightWheel, "wheelspin", fWheelspinValue)
STOP_PARTICLE_FX_LOOPED(ptfxRearLeftWheel)
STOP_PARTICLE_FX_LOOPED(ptfxRearRightWheel)
bPTFXStarted = FALSE
ENDIF
bPullInProgress = FALSE
RETURN TRUE
ENDIF
ENDIF
//update camera shake values and ptfx evolution
IF ( bPullInProgress = TRUE )
fCameraShakeAmplitude = CLAMP(fCameraShakeAmplitude +@0.2, 0.0, 0.3)
fWheelspinValue = CLAMP(fWheelspinValue +@0.25, 0.0, 1.0)
ELIF ( bPullInProgress = FALSE )
fCameraShakeAmplitude = CLAMP(fCameraShakeAmplitude -@0.4, 0.0, 0.3)
fWheelspinValue = 0.0
ENDIF
SET_AUDIO_SCENE_VARIABLE("FAMILY_3_PULL_DOWN_HOUSE_SCENE", "apply", fWheelspinValue)
#IF IS_DEBUG_BUILD
DRAW_DEBUG_SPHERE(<< vPullStartPosition.X, vPullStartPosition.Y, vPlayerCarPosition.Z >>, 0.2, 0, 0, 255)
#ENDIF
ENDIF
RETURN FALSE
ENDFUNC
PROC MANAGE_CAMERA_IN_RAYFIRE_SEQUENCE(INT &iProgress)
SWITCH iProgress
CASE 0
IF ( bHousePullCompleted = TRUE )
IF ( fRayfirePhase >= 0.560 )
IF NOT DOES_CAM_EXIST(ScriptedCamera)
ScriptedCamera = CREATE_CAMERA(CAMTYPE_SCRIPTED, TRUE)
SET_CAM_PARAMS(ScriptedCamera, <<-1009.953247,633.596191,140.483414>>,<<22.945997,-0.125925,21.448517>>,43.510220)
SET_CAM_PARAMS(ScriptedCamera, <<-1010.459290,633.923157,140.598160>>,<<13.298273,-0.125925,21.364548>>,43.510220, 5000,
GRAPH_TYPE_LINEAR, GRAPH_TYPE_LINEAR)
SHAKE_CAM(ScriptedCamera, "MEDIUM_EXPLOSION_SHAKE", 0.1)
STOP_GAMEPLAY_HINT(TRUE)
SET_GAMEPLAY_CAM_RELATIVE_PITCH(0)
SET_GAMEPLAY_CAM_RELATIVE_HEADING(0)
DISPLAY_HUD(FALSE)
DISPLAY_RADAR(FALSE)
RENDER_SCRIPT_CAMS(TRUE, FALSE)
iProgress++
ENDIF
ENDIF
ENDIF
BREAK
CASE 1
IF DOES_ROPE_EXIST(Rope)
AND DOES_ENTITY_EXIST(osRopeAnchor.ObjectIndex)
DETACH_ROPE_FROM_ENTITY(Rope, osRopeAnchor.ObjectIndex)
DETACH_ROPE_FROM_ENTITY(Rope, vsPlayersCar.VehicleIndex)
DELETE_OBJECT(osRopeAnchor.ObjectIndex)
DELETE_ROPE(Rope)
ROPE_UNLOAD_TEXTURES()
bRopeAttached = FALSE
ENDIF
IF DOES_ENTITY_EXIST(osRopeProp.ObjectIndex)
DELETE_OBJECT(osRopeProp.ObjectIndex)
ENDIF
IF ( fRayfirePhase >= 0.683 )
IF DOES_CAM_EXIST(ScriptedCamera)
SET_CAM_PARAMS(ScriptedCamera, <<-1009.381226,658.445251,152.820923>>,<<-39.496250,-0.125924,138.363358>>,43.510220)
SET_CAM_PARAMS(ScriptedCamera, <<-1010.491943,655.028503,150.779419>>,<<-30.668579,-0.125923,143.799835>>,43.510220, 4000,
GRAPH_TYPE_LINEAR, GRAPH_TYPE_LINEAR)
SHAKE_CAM(ScriptedCamera, "HAND_SHAKE", 0.25)
STOP_GAMEPLAY_HINT(TRUE)
SET_GAMEPLAY_CAM_RELATIVE_PITCH(0)
SET_GAMEPLAY_CAM_RELATIVE_HEADING(0)
iProgress++
ENDIF
ENDIF
BREAK
CASE 2
IF ( fRayfirePhase >= 0.730 )//0.771 )
IF DOES_CAM_EXIST(ScriptedCamera)
SET_CAM_PARAMS(ScriptedCamera, <<-1029.067017,622.262329,125.477417>>,<<45.378109,-0.125924,1.607233>>,50.256042)
SET_CAM_PARAMS(ScriptedCamera, <<-1029.405396,621.632324,126.455505>>,<<40.449352,-0.078049,1.812782>>,50.256042, 5000,
GRAPH_TYPE_LINEAR, GRAPH_TYPE_LINEAR)
SHAKE_CAM(ScriptedCamera, "HAND_SHAKE", 0.25)
STOP_GAMEPLAY_HINT(TRUE)
SET_GAMEPLAY_CAM_RELATIVE_PITCH(0)
SET_GAMEPLAY_CAM_RELATIVE_HEADING(0)
iProgress++
ENDIF
ENDIF
BREAK
CASE 3
IF ( iRayfireMapObjectProgress = 8 ) //rayfire map object is in end state at this point in progress
SET_CAM_PARAMS(ScriptedCamera, <<-1013.909851,632.159729,140.131577>>,<<22.288286,-0.125923,0.959580>>,50.256042)
SET_CAM_PARAMS(ScriptedCamera, <<-1014.135071,633.341919,140.977386>>,<<20.564297,-0.125923,1.779718>>,50.256042, 9000,
GRAPH_TYPE_LINEAR, GRAPH_TYPE_LINEAR)
SHAKE_CAM(ScriptedCamera, "HAND_SHAKE", 0.25)
STOP_GAMEPLAY_HINT(TRUE)
SET_GAMEPLAY_CAM_RELATIVE_PITCH(0)
SET_GAMEPLAY_CAM_RELATIVE_HEADING(0)
psMichael.iTimer = GET_GAME_TIMER()
IF IS_VEHICLE_DRIVEABLE(vsPlayersCar.VehicleIndex)
bShutVehicleBoot = TRUE
SET_VEHICLE_DOORS_SHUT(vsPlayersCar.VehicleIndex, TRUE)
SET_ENTITY_COORDS(vsPlayersCar.VehicleIndex, <<-994.4631, 643.6545, 138.8214>>)
SET_ENTITY_HEADING(vsPlayersCar.VehicleIndex, 277.0580)
SET_VEHICLE_ON_GROUND_PROPERLY(vsPlayersCar.VehicleIndex)
ENDIF
iProgress++
ENDIF
BREAK
CASE 4
IF HAS_TIME_PASSED(5500, psMichael.iTimer)
IF DOES_CAM_EXIST(ScriptedCamera)
SET_CAM_PARAMS(ScriptedCamera,<<-991.098938,642.266174,140.002777>>,<<15.862850,-0.000000,67.177223>>,50.000000)
SHAKE_CAM(ScriptedCamera, "HAND_SHAKE", 0.25)
STOP_GAMEPLAY_HINT(TRUE)
psMichael.iTimer = GET_GAME_TIMER()
iProgress++
ENDIF
ENDIF
BREAK
CASE 5
IF HAS_TIME_PASSED(500, psMichael.iTimer)
IF DOES_CAM_EXIST(ScriptedCamera)
DISPLAY_HUD(TRUE)
DISPLAY_RADAR(TRUE)
STOP_RENDERING_SCRIPT_CAMS_USING_CATCH_UP()
DISABLE_FIRST_PERSON_FLASH_EFFECT_THIS_UPDATE()
DESTROY_CAM(ScriptedCamera)
DESTROY_ALL_CAMS()
ENDIF
iProgress++
ENDIF
BREAK
ENDSWITCH
ENDPROC
FUNC BOOL IS_RAYFIRE_SEQUENCE_AND_CUTSCENE_COMPLETED(INT &iProgress)
IF ( bHousePullCompleted = FALSE )
UPDATE_FORCES(vsPlayersCar.VehicleIndex)
ENDIF
REPLAY_DISABLE_CAMERA_MOVEMENT_THIS_FRAME()
SWITCH iProgress
CASE 0
bRandomConversationAllowed = TRUE
LOAD_STREAM("FAMILY3_DECK_PULL_01_MASTER")
SET_VEHICLE_BURNOUT(vsPlayersCar.VehicleIndex, TRUE)
vPullStartVehiclePosition = vsPlayersCar.vPosition
IF IS_PULL_COMPLETED(bHousePullStarted, 3500, vPullStartVehiclePosition, 0.75)
AND LOAD_STREAM("FAMILY3_DECK_PULL_01_MASTER")
IF ( iRayfireMapObjectProgress = 1 ) //rayfire map object primed
CLEAR_HELP()
START_AUDIO_SCENE("FAMILY_3_RAYFIRE")
PLAY_STREAM_FROM_POSITION(<< -1020.98, 657.72, 154.51 >>)
SHAKE_GAMEPLAY_CAM("SMALL_EXPLOSION_SHAKE", 0.25)
SET_LABEL_AS_TRIGGERED("FAM3_HPULL", FALSE)
REPLAY_START_EVENT(REPLAY_IMPORTANCE_HIGHEST)
bRayfireStarted = TRUE
iProgress++
ENDIF
ENDIF
BREAK
CASE 1
IF ( bRayfireStarted )
IF ( bRayfirePaused = FALSE )
bRandomConversationAllowed = FALSE
SET_VEHICLE_BURNOUT(vsPlayersCar.VehicleIndex, TRUE)
vPullStartVehiclePosition = GET_ENTITY_COORDS(vsPlayersCar.VehicleIndex)
ELIF ( bRayfirePaused = TRUE )
bRandomConversationAllowed = TRUE
LOAD_STREAM("FAMILY3_DECK_PULL_02_MASTER")
IF IS_AUDIO_SCENE_ACTIVE("FAMILY_3_RAYFIRE")
STOP_AUDIO_SCENE("FAMILY_3_RAYFIRE")
ENDIF
SET_VEHICLE_BURNOUT(vsPlayersCar.VehicleIndex, TRUE)
IF IS_PULL_COMPLETED(bHousePullStarted, 4000, vPullStartVehiclePosition, 0.75)
AND LOAD_STREAM("FAMILY3_DECK_PULL_02_MASTER")
CLEAR_HELP()
START_AUDIO_SCENE("FAMILY_3_RAYFIRE")
PLAY_STREAM_FROM_POSITION(<< -1020.98, 657.72, 154.51 >>)
SHAKE_GAMEPLAY_CAM("MEDIUM_EXPLOSION_SHAKE", 0.15)
SET_LABEL_AS_TRIGGERED("FAM3_HPULL", FALSE)
bRayfirePaused = FALSE
iProgress++
ENDIF
ENDIF
ENDIF
BREAK
CASE 2
IF ( bRayfireStarted )
IF ( bRayfirePaused = FALSE )
bRandomConversationAllowed = FALSE
SET_VEHICLE_BURNOUT(vsPlayersCar.VehicleIndex, TRUE)
vPullStartVehiclePosition = GET_ENTITY_COORDS(vsPlayersCar.VehicleIndex)
ELIF ( bRayfirePaused = TRUE )
SET_VEHICLE_BURNOUT(vsPlayersCar.VehicleIndex, TRUE)
bRandomConversationAllowed = TRUE
LOAD_STREAM("FAMILY3_DECK_PULL_03_MASTER")
PREPARE_MUSIC_EVENT("FAM3_HOUSE_COLLAPSE")
IF IS_AUDIO_SCENE_ACTIVE("FAMILY_3_RAYFIRE")
STOP_AUDIO_SCENE("FAMILY_3_RAYFIRE")
ENDIF
IF IS_PULL_COMPLETED(bHousePullStarted, 4500, vPullStartVehiclePosition, 0.75)
AND LOAD_STREAM("FAMILY3_DECK_PULL_03_MASTER")
AND PREPARE_MUSIC_EVENT("FAM3_HOUSE_COLLAPSE")
//Start the multihead screen fade
SET_MULTIHEAD_SAFE(TRUE,FALSE)
CLEAR_HELP()
SET_VEHICLE_RADIO_ENABLED(vsPlayersCar.VehicleIndex, FALSE)
START_AUDIO_SCENE("FAMILY_3_RAYFIRE")
TRIGGER_MUSIC_EVENT("FAM3_HOUSE_COLLAPSE")
PLAY_STREAM_FROM_POSITION(<< -1020.98, 657.72, 154.51 >>)
SHAKE_GAMEPLAY_CAM("MEDIUM_EXPLOSION_SHAKE", 0.25)
REPLAY_RECORD_BACK_FOR_TIME(3, 0, REPLAY_IMPORTANCE_HIGH)
bRayfirePaused = FALSE
bHousePullStarted = FALSE
bHousePullCompleted = TRUE
iProgress++
ENDIF
ENDIF
ENDIF
BREAK
CASE 3 //rayfire cutscene
IF ( bRayfireStarted )
IF ( bRayfirePaused = FALSE )
bRandomConversationAllowed = FALSE
IF ( iRayfireMapObjectProgress = 8 ) //rayfire map object is in end state at this point in progress
bRandomConversationAllowed = TRUE
IF NOT DOES_CAM_EXIST(ScriptedCamera)
IF IS_AUDIO_SCENE_ACTIVE("FAMILY_3_RAYFIRE")
STOP_AUDIO_SCENE("FAMILY_3_RAYFIRE")
ENDIF
IF ( bCutsceneSkipped = TRUE )
DO_SAFE_SCREEN_FADE_IN(DEFAULT_FADE_TIME)
ENDIF
//Stop the multihead screen fade
SET_MULTIHEAD_SAFE(FALSE,FALSE)
SET_PLAYER_CONTROL(PLAYER_ID(), TRUE)
REPLAY_STOP_EVENT()
RETURN TRUE
ENDIF
ELSE
IF ( bCutsceneSkipped = FALSE )
IF DOES_CAM_EXIST(ScriptedCamera)
IF IS_CUTSCENE_SKIP_BUTTON_JUST_PRESSED()
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Rayfire cutscene is being skipped by the player.")
#ENDIF
DO_SAFE_SCREEN_FADE_OUT(DEFAULT_FADE_TIME)
IF ( iRayfireMapObjectProgress < 6 )
iRayfireMapObjectProgress = 6 //send the rayfire map object to the progress case that ends it
ENDIF
IF DOES_ROPE_EXIST(Rope)
AND DOES_ENTITY_EXIST(osRopeAnchor.ObjectIndex)
DETACH_ROPE_FROM_ENTITY(Rope, osRopeAnchor.ObjectIndex)
DETACH_ROPE_FROM_ENTITY(Rope, vsPlayersCar.VehicleIndex)
DELETE_OBJECT(osRopeAnchor.ObjectIndex)
DELETE_ROPE(Rope)
ROPE_UNLOAD_TEXTURES()
bRopeAttached = FALSE
ENDIF
IF DOES_ENTITY_EXIST(osRopeProp.ObjectIndex)
DELETE_OBJECT(osRopeProp.ObjectIndex)
ENDIF
IF IS_VEHICLE_DRIVEABLE(vsPlayersCar.VehicleIndex)
bShutVehicleBoot = TRUE
SET_VEHICLE_DOORS_SHUT(vsPlayersCar.VehicleIndex, TRUE)
SET_ENTITY_COORDS(vsPlayersCar.VehicleIndex, <<-994.4631, 643.6545, 138.8214>>)
SET_ENTITY_HEADING(vsPlayersCar.VehicleIndex, 277.0580)
SET_VEHICLE_ON_GROUND_PROPERLY(vsPlayersCar.VehicleIndex)
ENDIF
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
CLEAR_PED_TASKS(PLAYER_PED_ID())
ENDIF
IF NOT IS_PED_INJURED(psFranklin.PedIndex)
CLEAR_PED_TASKS(psFranklin.PedIndex)
ENDIF
//Stop the multihead screen fade
SET_MULTIHEAD_SAFE(FALSE,FALSE)
//destroy scripted camera due to rayfire cutscene skip
IF DOES_CAM_EXIST(ScriptedCamera)
STOP_GAMEPLAY_HINT(TRUE)
SET_GAMEPLAY_CAM_RELATIVE_PITCH(0)
SET_GAMEPLAY_CAM_RELATIVE_HEADING(0)
RENDER_SCRIPT_CAMS(FALSE, FALSE)
DESTROY_CAM(ScriptedCamera)
DESTROY_ALL_CAMS()
DISPLAY_HUD(TRUE)
DISPLAY_RADAR(TRUE)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Destroy scripted camera due to rayfire cutscene skip.")
#ENDIF
ENDIF
STOP_STREAM()
bCutsceneSkipped = TRUE
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
BREAK
ENDSWITCH
RETURN FALSE
ENDFUNC
PROC MANAGE_CONVERSATIONS_DURING_PULL_HOUSE_DOWN(BOOL bConversationAllowed, BOOL bPlayerPulling, INT iRayfireProgress, INT &iIdleTimer, INT &iPullTimer)
IF NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_PULLS")
IF IS_PED_SITTING_IN_THIS_VEHICLE(PLAYER_PED_ID(), vsPlayersCar.VehicleIndex)
AND IS_PED_SITTING_IN_THIS_VEHICLE(psFranklin.PedIndex, vsPlayersCar.VehicleIndex)
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF NOT IS_ANY_TEXT_BEING_DISPLAYED(sLocatesData, IAT_IGNORE_GOD_TEXT_IF_SUBTITLES_OFF)
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_PULLS", CONV_PRIORITY_MEDIUM)
SET_LABEL_AS_TRIGGERED("FAM3_PULLS", TRUE)
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
IF ( bConversationAllowed = TRUE )
SWITCH iRayfireProgress
CASE 1
IF ( bRayfirePaused = TRUE)
IF NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_PULLC1")
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_PULLC1", CONV_PRIORITY_MEDIUM)
SET_LABEL_AS_TRIGGERED("FAM3_PULLC1", TRUE)
iIdleTimer = GET_GAME_TIMER()
iPullTimer = GET_GAME_TIMER()
ENDIF
ENDIF
ENDIF
BREAK
CASE 2
IF ( bRayfirePaused = TRUE)
IF NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_PULLC2")
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_PULLC2", CONV_PRIORITY_MEDIUM)
SET_LABEL_AS_TRIGGERED("FAM3_PULLC2", TRUE)
iIdleTimer = GET_GAME_TIMER()
iPullTimer = GET_GAME_TIMER()
ENDIF
ENDIF
ENDIF
BREAK
ENDSWITCH
IF ( bPlayerPulling = FALSE )
IF HAS_TIME_PASSED(8000, iIdleTimer)
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF NOT IS_ANY_TEXT_BEING_DISPLAYED(sLocatesData, IAT_IGNORE_GOD_TEXT_IF_SUBTITLES_OFF)
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_PULLI", CONV_PRIORITY_MEDIUM)
iIdleTimer = GET_GAME_TIMER()
ENDIF
ENDIF
ELSE
IF IS_THIS_CONVERSATION_PLAYING("FAM3_PULLS")
iIdleTimer = GET_GAME_TIMER()
ENDIF
ENDIF
ENDIF
iPullTimer = GET_GAME_TIMER()
ELSE
iIdleTimer = GET_GAME_TIMER()
IF HAS_TIME_PASSED(3000, iPullTimer)
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF NOT IS_ANY_TEXT_BEING_DISPLAYED(sLocatesData, IAT_IGNORE_GOD_TEXT_IF_SUBTITLES_OFF)
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_PULLE", CONV_PRIORITY_MEDIUM)
iPullTimer = GET_GAME_TIMER()
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ELSE
iIdleTimer = GET_GAME_TIMER()
iPullTimer = GET_GAME_TIMER()
ENDIF
IF ( bHousePullCompleted = TRUE )
IF NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_PULLC3")
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_PULLC3", CONV_PRIORITY_MEDIUM)
SET_LABEL_AS_TRIGGERED("FAM3_PULLC3", TRUE)
ENDIF
ENDIF
ENDIF
IF ( bConversationAllowed = TRUE )
IF NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_DOWN")
AND NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_DOWNA")
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF ( iRayfireMapObjectProgress = 8 )
SWITCH GET_PLAYER_CHARACTER_AT_MISSION_START()
CASE CHAR_MICHAEL //FAM3_DOWN
IF CREATE_CONVERSATION_FROM_SPECIFIC_LINE(sFamily3Conversation, "FAM3AUD", "FAM3_DOWN", "FAM3_DOWN_1", CONV_PRIORITY_MEDIUM)
SET_LABEL_AS_TRIGGERED("FAM3_DOWN", TRUE)
ENDIF
BREAK
CASE CHAR_FRANKLIN //FAM3_DOWNA
IF CREATE_CONVERSATION_FROM_SPECIFIC_LINE(sFamily3Conversation, "FAM3AUD", "FAM3_DOWNA", "FAM3_DOWNA_1", CONV_PRIORITY_MEDIUM)
SET_LABEL_AS_TRIGGERED("FAM3_DOWNA", TRUE)
ENDIF
BREAK
ENDSWITCH
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDPROC
PROC MANAGE_FRANKLIN_IN_VEHICLE(PED_INDEX PedIndex, VEHICLE_INDEX VehicleIndex, PED_STRUCT &ped, BOOL bPullInProgress)
IF DOES_ENTITY_EXIST(PedIndex)
AND NOT IS_ENTITY_DEAD(PedIndex)
IF DOES_ENTITY_EXIST(VehicleIndex)
AND NOT IS_ENTITY_DEAD(VehicleIndex)
#IF IS_DEBUG_BUILD
IF ( bDrawDebugStates = TRUE )
DRAW_DEBUG_TEXT_ABOVE_ENTITY(PedIndex, GET_STRING_FROM_INT(ped.iProgress), 0.0)
ENDIF
#ENDIF
SWITCH ped.iProgress
CASE 0
IF IS_PED_IN_VEHICLE(PedIndex, VehicleIndex)
AND IS_PED_IN_VEHICLE(PLAYER_PED_ID(), VehicleIndex)
REQUEST_ANIM_DICT("missfam3")
IF HAS_ANIM_DICT_LOADED("missfam3")
SEQUENCE_INDEX SequenceIndex
OPEN_SEQUENCE_TASK(SequenceIndex)
TASK_PLAY_ANIM(NULL, "missfam3", "react_incar_brace_enter_f", SLOW_BLEND_IN, INSTANT_BLEND_OUT, -1, AF_UPPERBODY)
TASK_PLAY_ANIM(NULL, "missfam3", "react_incar_brace_loop_f", INSTANT_BLEND_IN, SLOW_BLEND_OUT, -1, AF_UPPERBODY | AF_LOOPING)
CLOSE_SEQUENCE_TASK(SequenceIndex)
TASK_PERFORM_SEQUENCE(PedIndex, SequenceIndex)
CLEAR_SEQUENCE_TASK(SequenceIndex)
ped.bHasTask = FALSE
ped.iProgress = 1
ENDIF
ENDIF
BREAK
CASE 1 //brace loop
IF ( ped.bHasTask = FALSE )
IF NOT IS_ENTITY_PLAYING_ANIM(PedIndex, "missfam3", "react_incar_brace_loop_f")
AND GET_SCRIPT_TASK_STATUS(PedIndex, SCRIPT_TASK_PERFORM_SEQUENCE) != PERFORMING_TASK
TASK_PLAY_ANIM(PedIndex, "missfam3", "react_incar_brace_loop_f", SLOW_BLEND_IN, SLOW_BLEND_OUT, -1, AF_UPPERBODY | AF_LOOPING)
ENDIF
ped.bHasTask = TRUE
ENDIF
IF ( bPullInProgress = TRUE )
ped.bHasTask = FALSE
ped.iProgress = 2
ELSE
IF ( iRayfireSequenceProgress >= 3)
ped.bHasTask = FALSE
ped.iProgress = 4
ENDIF
ENDIF
BREAK
CASE 2 //bump loop
IF ( ped.bHasTask = FALSE )
IF NOT IS_ENTITY_PLAYING_ANIM(PedIndex, "missfam3", "react_incar_bumps_loop_f")
TASK_PLAY_ANIM(PedIndex, "missfam3", "react_incar_bumps_loop_f", SLOW_BLEND_IN, SLOW_BLEND_OUT, -1, AF_UPPERBODY | AF_LOOPING)
ENDIF
ped.iTimer = GET_GAME_TIMER() + GET_RANDOM_INT_IN_RANGE(2000, 3000)
ped.bHasTask = TRUE
ENDIF
IF ( bPullInProgress = TRUE )
IF GET_GAME_TIMER() - ped.iTimer > 0
ped.bHasTask = FALSE
ped.iProgress = 3
ENDIF
ELSE
ped.bHasTask = FALSE
ped.iProgress = 1
ENDIF
BREAK
CASE 3
IF ( ped.bHasTask = FALSE )
TASK_PLAY_ANIM(PedIndex, "missfam3", "incar_lookbehind_idle_passenger", SLOW_BLEND_IN, SLOW_BLEND_OUT, -1, AF_UPPERBODY | AF_LOOPING)
ped.iTimer = GET_GAME_TIMER() + GET_RANDOM_INT_IN_RANGE(1000, 1750)
ped.bHasTask = TRUE
ENDIF
IF ( ped.bHasTask = TRUE )
IF GET_GAME_TIMER() - ped.iTimer > 0
IF IS_ENTITY_PLAYING_ANIM(PedIndex, "missfam3", "incar_lookbehind_idle_passenger")
IF ( bPullInProgress = TRUE )
ped.bHasTask = FALSE
ped.iProgress = 2
ELSE
ped.bHasTask = FALSE
ped.iProgress = 1
ENDIF
ENDIF
ENDIF
ENDIF
BREAK
CASE 4 //end brace pose
IF ( ped.bHasTask = FALSE )
IF NOT IS_ENTITY_PLAYING_ANIM(PedIndex, "missfam3", "react_incar_brace_exit_f")
TASK_PLAY_ANIM(PedIndex, "missfam3", "react_incar_brace_exit_f", SLOW_BLEND_IN, SLOW_BLEND_OUT, -1, AF_UPPERBODY)
ENDIF
ped.bHasTask = TRUE
ENDIF
IF ( bHousePullCompleted = TRUE )
ped.bHasTask = FALSE
ped.iProgress++
ENDIF
BREAK
CASE 5
IF ( ped.bHasTask = FALSE )
TASK_PLAY_LOOK_BEHIND_ANIM(PLAYER_PED_ID(), VS_DRIVER, 10000)
TASK_PLAY_LOOK_BEHIND_ANIM(psFranklin.PedIndex, VS_FRONT_RIGHT, 10500)
ped.bHasTask = TRUE
ENDIF
BREAK
ENDSWITCH
ENDIF
ENDIF
ENDPROC
PROC MANAGE_HINT_CAMERA(VECTOR vHintCoordinate)
IF IS_CONTROL_JUST_PRESSED(PLAYER_CONTROL, INPUT_LOOK_LR)
OR IS_CONTROL_JUST_PRESSED(PLAYER_CONTROL, INPUT_LOOK_UP)
IF IS_GAMEPLAY_HINT_ACTIVE()
bGameplayHintTimer = GET_GAME_TIMER()
STOP_GAMEPLAY_HINT()
ENDIF
ELSE
IF NOT IS_GAMEPLAY_HINT_ACTIVE()
IF ( bGameplayHintTimer != 0 )
IF HAS_TIME_PASSED(1000, bGameplayHintTimer)
SET_GAMEPLAY_COORD_HINT(vHintCoordinate, -1, 8000, DEFAULT_INTERP_OUT_TIME, HINTTYPE_FAMILY3_HOUSE_VEHICLE)
ENDIF
ENDIF
ENDIF
ENDIF
ENDPROC
PROC DISABLE_CINEMATIC_BONNET_CAMERA_FOR_LOOK_BEHIND_ANIMATION()
DISABLE_FIRST_PERSON_FLASH_EFFECT_THIS_UPDATE()
IF IS_PED_SITTING_IN_THIS_VEHICLE(PLAYER_PED_ID(), vsPlayersCar.VehicleIndex)
IF IS_ENTITY_PLAYING_LOOK_BEHIND_ANIM(PLAYER_PED_ID())
DISABLE_CONTROL_ACTION(CAMERA_CONTROL, INPUT_NEXT_CAMERA)
IF ( bResetFirstPersonCamera = TRUE )
IF GET_CAM_VIEW_MODE_FOR_CONTEXT(CAM_VIEW_MODE_CONTEXT_IN_VEHICLE) = CAM_VIEW_MODE_FIRST_PERSON
SET_GAMEPLAY_CAM_RELATIVE_PITCH()
SET_GAMEPLAY_CAM_RELATIVE_HEADING()
ENDIF
bResetFirstPersonCamera = FALSE
ENDIF
IF GET_CAM_VIEW_MODE_FOR_CONTEXT(CAM_VIEW_MODE_CONTEXT_IN_VEHICLE) = CAM_VIEW_MODE_FIRST_PERSON
IF ( bFirstPersonFlashPlayed = FALSE )
DISABLE_CINEMATIC_BONNET_CAMERA_THIS_UPDATE()
DISABLE_FIRST_PERSON_FLASH_EFFECT_THIS_UPDATE()
IF IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(), "missfam3", "incar_lookbehind_exit_driver")
IF GET_ENTITY_ANIM_CURRENT_TIME(PLAYER_PED_ID(), "missfam3", "incar_lookbehind_exit_driver") >= fFirstPersonFlashPhase2
IF iFirstPersonFlashTimer = 0
ANIMPOSTFX_PLAY("CamPushInNeutral", 0, FALSE)
PLAY_SOUND_FRONTEND(-1, "1st_Person_Transition", "PLAYER_SWITCH_CUSTOM_SOUNDSET")
iFirstPersonFlashTimer = GET_GAME_TIMER()
ELSE
IF HAS_TIME_PASSED(iFirstPersonFlashTime, iFirstPersonFlashTimer)
bResetFirstPersonCamera = TRUE
bFirstPersonFlashPlayed = TRUE
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDPROC
FUNC BOOL IS_MISSION_STAGE_PULL_HOUSE_DOWN_COMPLETED(INT &iStageProgress)
SET_BIT(sLocatesData.iLocatesBitSet, BS_DONT_DO_J_SKIP)
REQUEST_SCRIPT_AUDIO_BANK("FAMILY3_1")
MANAGE_TENNIS_COACH_DURING_PULL_HOUSE_DOWN()
MANAGE_FRANKLIN_IN_VEHICLE(psFranklin.PedIndex, vsPlayersCar.VehicleIndex, psFranklin, bHousePullStarted)
MANAGE_RAYFIRE_MAP_OBJECT(iRayfireMapObjectProgress, bRayfireStarted, bRayfirePaused, bRayfirePrimed, bRayfireFinished, fRayfirePhase)
MANAGE_CONVERSATIONS_DURING_PULL_HOUSE_DOWN(bRandomConversationAllowed, bHousePullStarted, iRayfireSequenceProgress,
iConversationIdleTimer, psFranklin.iConversationTimer)
DISABLE_CINEMATIC_BONNET_CAMERA_FOR_LOOK_BEHIND_ANIMATION()
IF IS_PED_SITTING_IN_THIS_VEHICLE(PLAYER_PED_ID(), vsPlayersCar.VehicleIndex)
DISABLE_SELECTOR_THIS_FRAME()
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_EXIT) //block most of the vehicle inputs
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_BRAKE)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_HANDBRAKE)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_DUCK)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_AIM)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_ATTACK)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_ATTACK2)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_SELECT_WEAPON)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_SELECT_NEXT_WEAPON)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_SELECT_PREV_WEAPON)
ENDIF
IF ( bShutVehicleBoot = FALSE )
IF DOES_ENTITY_EXIST(vsPlayersCar.VehicleIndex)
IF NOT IS_ENTITY_DEAD(vsPlayersCar.VehicleIndex)
SET_VEHICLE_DOOR_CONTROL(vsPlayersCar.VehicleIndex, SC_DOOR_BOOT, DT_DOOR_INTACT, 1.0) //keep boot door open
ENDIF
ENDIF
ENDIF
SWITCH iStageProgress
CASE 0
IF NOT IS_PED_INJURED(psFranklin.PedIndex)
AND IS_VEHICLE_DRIVEABLE(vsPlayersCar.VehicleIndex)
IF NOT IS_PED_IN_VEHICLE(psFranklin.PedIndex, vsPlayersCar.VehicleIndex)
TASK_ENTER_VEHICLE(psFranklin.PedIndex, vsPlayersCar.VehicleIndex, DEFAULT_TIME_BEFORE_WARP, VS_FRONT_RIGHT, PEDMOVE_WALK)
ENDIF
ENDIF
IF ( bRopeAttached = FALSE )
IF NOT DOES_ROPE_EXIST(Rope)
ROPE_LOAD_TEXTURES()
IF ROPE_ARE_TEXTURES_LOADED()
Rope = ADD_ROPE(<<-1017.9850, 660.4285, 147.4662>>, <<0.0, 0.0, 0.0>>, ROPE_MAX_LEN, PHYSICS_ROPE_DEFAULT, -1, 0.5, 0.5, FALSE, TRUE)
LOAD_ROPE_DATA( Rope, ROPE_DATA_FILE )
ENDIF
ENDIF
IF DOES_ENTITY_EXIST(osRopeAnchor.ObjectIndex)
AND DOES_ENTITY_EXIST(osRopeProp.ObjectIndex)
AND DOES_ROPE_EXIST(rope)
IF DOES_ENTITY_HAVE_PHYSICS(osRopeAnchor.ObjectIndex)
IF IS_VEHICLE_DRIVEABLE(vsPlayersCar.VehicleIndex)
ATTACH_ENTITIES_TO_ROPE(Rope, osRopeAnchor.ObjectIndex, vsPlayersCar.VehicleIndex, osRopeAnchor.vPosition, GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(vsPlayersCar.VehicleIndex, << 0.0, -2.1, 0.6 >>), 35.0, 0, 0)
bRopeAttached = TRUE
ENDIF
ENDIF
ENDIF
ENDIF
IF NOT DOES_ENTITY_EXIST(osBootCollision.ObjectIndex)
IF HAS_MISSION_OBJECT_BEEN_CREATED(osBootCollision, TRUE)
SET_ENTITY_COLLISION(osBootCollision.ObjectIndex, TRUE)
SET_ENTITY_NO_COLLISION_ENTITY(osBootCollision.ObjectIndex, vsPlayersCar.VehicleIndex, FALSE)
ENDIF
ENDIF
iStageProgress++
BREAK
CASE 1
DISABLE_CINEMATIC_BONNET_CAMERA_THIS_UPDATE() //fixes a pop between first person and gameplay hint when player enters the car
IF NOT IS_PED_INJURED(psFranklin.PedIndex)
AND NOT IS_PED_INJURED(PLAYER_PED_ID())
AND IS_VEHICLE_DRIVEABLE(vsPlayersCar.VehicleIndex)
IF IS_PED_IN_VEHICLE(PLAYER_PED_ID(), vsPlayersCar.VehicleIndex, TRUE)
SET_GAMEPLAY_COORD_HINT(vBalconyHintPosition, -1, 8000, DEFAULT_INTERP_OUT_TIME, HINTTYPE_FAMILY3_HOUSE_VEHICLE)
ENDIF
IF IS_PED_IN_VEHICLE(PLAYER_PED_ID(), vsPlayersCar.VehicleIndex)
IF DOES_BLIP_EXIST(vsPlayersCar.BlipIndex)
REMOVE_BLIP(vsPlayersCar.BlipIndex)
CLEAR_PRINTS()
ENDIF
ELSE
IF NOT DOES_BLIP_EXIST(vsPlayersCar.BlipIndex)
vsPlayersCar.BlipIndex = CREATE_BLIP_FOR_VEHICLE(vsPlayersCar.VehicleIndex)
ENDIF
IF NOT HAS_LABEL_BEEN_TRIGGERED(sLabelGIT) OR NOT IS_STRING_NULL_OR_EMPTY(sLabelGIT)
IF DOES_BLIP_EXIST(vsPlayersCar.BlipIndex)
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF NOT IS_ANY_TEXT_BEING_DISPLAYED(sLocatesData)
PRINT_GOD_TEXT_ADVANCED(sLabelGIT, DEFAULT_GOD_TEXT_TIME, TRUE)
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
IF IS_PED_SITTING_IN_VEHICLE(psFranklin.PedIndex, vsPlayersCar.VehicleIndex)
AND IS_PED_SITTING_IN_VEHICLE(PLAYER_PED_ID(), vsPlayersCar.VehicleIndex)
REPLAY_RECORD_BACK_FOR_TIME(5.0, 5.0, REPLAY_IMPORTANCE_HIGHEST)
IF DOES_ENTITY_EXIST(osRopeDummy.ObjectIndex)
DELETE_OBJECT(osRopeDummy.ObjectIndex)
ENDIF
IF DOES_ENTITY_EXIST(osBootCollision.ObjectIndex)
DELETE_OBJECT(osBootCollision.ObjectIndex)
ENDIF
SET_VEHICLE_BURNOUT(vsPlayersCar.VehicleIndex, TRUE)
CLEAR_AREA_OF_PEDS(psMichael.vPosition, 100.0)
CLEAR_AREA_OF_VEHICLES(psMichael.vPosition, 100.0)
START_AUDIO_SCENE("FAMILY_3_PULL_DOWN_HOUSE_SCENE")
iStageProgress++
ENDIF
ENDIF
BREAK
CASE 2
IF ( bCutsceneSkipped = FALSE )
//MANAGE_HINT_CAMERA(vBalconyHintPosition)
MANAGE_CAMERA_IN_RAYFIRE_SEQUENCE(iScriptedCameraProgress)
MANAGE_PLAYERS_VEHICLE_IN_RAYFIRE_SEQUENCE(vsPlayersCar.iProgress)
ENDIF
REQUEST_PTFX_ASSET()
REQUEST_ANIM_DICT("missfam3")
IF IS_RAYFIRE_SEQUENCE_AND_CUTSCENE_COMPLETED(iRayfireSequenceProgress)
IF IS_VEHICLE_DRIVEABLE(vsPlayersCar.VehicleIndex)
SET_VEHICLE_RADIO_ENABLED(vsPlayersCar.VehicleIndex, TRUE)
SET_VEHICLE_BURNOUT(vsPlayersCar.VehicleIndex, FALSE)
REMOVE_ENTITY_FROM_AUDIO_MIX_GROUP(vsPlayersCar.VehicleIndex)
ENDIF
STOP_AUDIO_SCENE("FAMILY_3_RAYFIRE")
STOP_AUDIO_SCENE("FAMILY_3_PULL_DOWN_HOUSE_SCENE")
STOP_GAMEPLAY_HINT()
RETURN TRUE
ENDIF
BREAK
ENDSWITCH
RETURN FALSE
ENDFUNC
FUNC BOOL IS_MISSION_STAGE_CUTSCENE_END_COMPLETED(INT &iStageProgress)
SWITCH iStageProgress
CASE 0
IF HAS_REQUESTED_CUTSCENE_LOADED("family_3_ext")
SWITCH GET_CURRENT_PLAYER_PED_ENUM()
CASE CHAR_MICHAEL
IF NOT IS_PED_INJURED(GET_PED_INDEX(CHAR_FRANKLIN))
REGISTER_ENTITY_FOR_CUTSCENE(GET_PED_INDEX(CHAR_FRANKLIN), "Franklin", CU_ANIMATE_EXISTING_SCRIPT_ENTITY, GET_PLAYER_PED_MODEL(CHAR_FRANKLIN))
ENDIF
BREAK
CASE CHAR_FRANKLIN
IF NOT IS_PED_INJURED(GET_PED_INDEX(CHAR_MICHAEL))
REGISTER_ENTITY_FOR_CUTSCENE(GET_PED_INDEX(CHAR_MICHAEL), "Michael", CU_ANIMATE_EXISTING_SCRIPT_ENTITY, GET_PLAYER_PED_MODEL(CHAR_MICHAEL))
ENDIF
BREAK
ENDSWITCH
IF DOES_ENTITY_EXIST(vsCutsceneCar.VehicleIndex)
IF NOT IS_ENTITY_DEAD(vsCutsceneCar.VehicleIndex)
SET_ENTITY_INVINCIBLE(vsCutsceneCar.VehicleIndex, TRUE)
//SET_VEHICLE_ENGINE_ON(vsCutsceneCar.VehicleIndex, TRUE, TRUE)
//SET_VEHICLE_LIGHTS(vsCutsceneCar.VehicleIndex, SET_VEHICLE_LIGHTS_ON)
REGISTER_ENTITY_FOR_CUTSCENE(vsCutsceneCar.VehicleIndex, "Madrazos_Car", CU_ANIMATE_AND_DELETE_EXISTING_SCRIPT_ENTITY, BALLER)
ENDIF
ENDIF
SET_SCRIPTS_SAFE_FOR_CUTSCENE(TRUE)
IF NOT IS_PED_INJURED(GET_PED_INDEX(CHAR_MICHAEL))
REMOVE_PED_HELMET(GET_PED_INDEX(CHAR_MICHAEL), TRUE)
ENDIF
IF NOT IS_PED_INJURED(GET_PED_INDEX(CHAR_FRANKLIN))
REMOVE_PED_HELMET(GET_PED_INDEX(CHAR_FRANKLIN), TRUE)
ENDIF
CLEAR_HELP()
CLEAR_PRINTS()
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
KILL_FACE_TO_FACE_CONVERSATION_DO_NOT_FINISH_LAST_LINE()
ENDIF
STOP_AUDIO_SCENES() //stop all audio scenes
TRIGGER_MUSIC_EVENT("FAM3_END") //stop all music playing
START_CUTSCENE()
REPLAY_START_EVENT(REPLAY_IMPORTANCE_HIGHEST)
SET_CUTSCENE_FADE_VALUES(FALSE, FALSE, TRUE, FALSE) //make sure cutscene ends with a fade
iStageProgress++
ELSE
IF CAN_REQUEST_ASSETS_FOR_CUTSCENE_ENTITY()
IF NOT IS_PED_INJURED(GET_PED_INDEX(CHAR_MICHAEL))
SET_CUTSCENE_PED_COMPONENT_VARIATION_FROM_PED("Michael", GET_PED_INDEX(CHAR_MICHAEL)) //Michael's variations
ENDIF
IF NOT IS_PED_INJURED(GET_PED_INDEX(CHAR_FRANKLIN))
SET_CUTSCENE_PED_COMPONENT_VARIATION_FROM_PED("Franklin", GET_PED_INDEX(CHAR_FRANKLIN)) //Franklin's variations
ENDIF
bCutsceneAssetsRequested = TRUE
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Setting cutscene ped components for cutscene ped Michael and Franklin from peds during stage ", GET_MISSION_STAGE_NAME_FOR_DEBUG(eMissionStage), ".")
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Setting bCutsceneAssetsRequested to ", bCutsceneAssetsRequested, ".")
#ENDIF
ENDIF
ENDIF
BREAK
CASE 1 //fade screen in if screen was faded out due to shit skip or debug skip
IF IS_CUTSCENE_PLAYING()
VEHICLE_INDEX LastPlayerVehicleIndex
LastPlayerVehicleIndex = GET_PLAYERS_LAST_VEHICLE()
IF DOES_ENTITY_EXIST(LastPlayerVehicleIndex)
IF NOT IS_ENTITY_DEAD(LastPlayerVehicleIndex)
//if last player vehicle is parked in the gate area or driveway where the cutscene car would drive
IF IS_ENTITY_AT_COORD(LastPlayerVehicleIndex, <<-846.192993,159.141159,66.499069>>, <<10.0,4.0,4.0>>)
OR IS_ENTITY_IN_ANGLED_AREA(LastPlayerVehicleIndex, <<-835.589661,158.536118,65.894333>>, <<-827.645386,177.585007,73.087891>>, 8.0)
IF NOT IS_ENTITY_A_MISSION_ENTITY(LastPlayerVehicleIndex)
SET_ENTITY_AS_MISSION_ENTITY(LastPlayerVehicleIndex)
ENDIF
STOP_VEHICLE_FIRE(LastPlayerVehicleIndex)
IF IS_VEHICLE_GEN_AVAILABLE(VEHGEN_MISSION_VEH)
AND DOES_ENTITY_EXIST(GET_VEHICLE_GEN_VEHICLE_INDEX(VEHGEN_MISSION_VEH))
//reposition last player vehicle to the other side of the driveway
SET_ENTITY_COORDS(LastPlayerVehicleIndex, <<-821.2841, 157.5416, 69.2754>>)
SET_ENTITY_HEADING(LastPlayerVehicleIndex, 95.1204)
ELSE
//reposition last player vehicle across the street
SET_ENTITY_COORDS(LastPlayerVehicleIndex, << -867.9103, 158.2215, 63.9014 >>)
SET_ENTITY_HEADING(LastPlayerVehicleIndex, 174.2918)
ENDIF
SET_VEHICLE_ON_GROUND_PROPERLY(LastPlayerVehicleIndex)
SET_VEHICLE_DOORS_SHUT(LastPlayerVehicleIndex, TRUE)
SET_VEHICLE_ENGINE_ON(LastPlayerVehicleIndex, FALSE, TRUE)
ENDIF
//if last player vehicle is close to the house blip
IF GET_DISTANCE_BETWEEN_COORDS(vMichaelsHousePosition, GET_ENTITY_COORDS(LastPlayerVehicleIndex)) < 15.0
IF NOT IS_ENTITY_A_MISSION_ENTITY(LastPlayerVehicleIndex)
SET_ENTITY_AS_MISSION_ENTITY(LastPlayerVehicleIndex)
ENDIF
STOP_VEHICLE_FIRE(LastPlayerVehicleIndex)
//repostion last player vehicle into the end locate
//so that it can be seen in the end cutscene
SET_ENTITY_COORDS(LastPlayerVehicleIndex, vsPlayersCar.vPosition)
SET_ENTITY_HEADING(LastPlayerVehicleIndex, PICK_FLOAT(bVehicleReversed, 126.8534, vsPlayersCar.fHeading))
SET_VEHICLE_ON_GROUND_PROPERLY(LastPlayerVehicleIndex)
SET_VEHICLE_DOORS_SHUT(LastPlayerVehicleIndex, TRUE)
SET_VEHICLE_ENGINE_ON(LastPlayerVehicleIndex, FALSE, TRUE)
SET_ENTITY_LOD_DIST(LastPlayerVehicleIndex, 50)
SET_VEHICLE_LOD_MULTIPLIER(LastPlayerVehicleIndex, 2.0)
//if last player vehicle does not fit into the end locate and could collide with cutscene vehicle
IF DOES_VEHICLE_OVERLAP_ANGLED_AREA(LastPlayerVehicleIndex, <<-824.815613,185.378525,69.954208>>,
<<-820.613281,179.789505,73.639229>>, 7.5)
IF IS_VEHICLE_GEN_AVAILABLE(VEHGEN_MISSION_VEH)
AND DOES_ENTITY_EXIST(GET_VEHICLE_GEN_VEHICLE_INDEX(VEHGEN_MISSION_VEH))
//reposition last player vehicle to the other side of the driveway
SET_ENTITY_COORDS(LastPlayerVehicleIndex, <<-821.2841, 157.5416, 69.2754>>)
SET_ENTITY_HEADING(LastPlayerVehicleIndex, 95.1204)
ELSE
//reposition last player vehicle across the street
SET_ENTITY_COORDS(LastPlayerVehicleIndex, << -867.9103, 158.2215, 63.9014 >>)
SET_ENTITY_HEADING(LastPlayerVehicleIndex, 174.2918)
ENDIF
SET_VEHICLE_ON_GROUND_PROPERLY(LastPlayerVehicleIndex)
SET_VEHICLE_DOORS_SHUT(LastPlayerVehicleIndex, TRUE)
SET_VEHICLE_ENGINE_ON(LastPlayerVehicleIndex, FALSE, TRUE)
ENDIF
ENDIF
ENDIF
IF ( LastPlayerVehicleIndex != vsPlayersCar.VehicleIndex )
SET_VEHICLE_AS_NO_LONGER_NEEDED(vsPlayersCar.VehicleIndex)
ENDIF
ENDIF
//remove blood damage decals, see TODO B*1492682
IF NOT IS_PED_INJURED(GET_PED_INDEX(CHAR_MICHAEL))
CLEAR_PED_BLOOD_DAMAGE(GET_PED_INDEX(CHAR_MICHAEL))
RESET_PED_VISIBLE_DAMAGE(GET_PED_INDEX(CHAR_MICHAEL))
ENDIF
IF NOT IS_PED_INJURED(GET_PED_INDEX(CHAR_FRANKLIN))
CLEAR_PED_BLOOD_DAMAGE(GET_PED_INDEX(CHAR_FRANKLIN))
RESET_PED_VISIBLE_DAMAGE(GET_PED_INDEX(CHAR_FRANKLIN))
ENDIF
CLEAR_AREA_OF_PEDS(vMichaelsHousePosition, 1000.0)
CLEAR_AREA_OF_COPS(vMichaelsHousePosition, 1000.0)
CLEAR_AREA_OF_VEHICLES(vMichaelsHousePosition, 1000.0)
CLEAR_AREA_OF_PROJECTILES(vMichaelsHousePosition, 1000.0, TRUE)
//shut the mansion front doors, they can be seen open sometimes, see B*1470757
IF IS_DOOR_REGISTERED_WITH_SYSTEM(ENUM_TO_INT(DOORHASH_M_MANSION_F_L))
DOOR_SYSTEM_SET_OPEN_RATIO(ENUM_TO_INT(DOORHASH_M_MANSION_F_L), 0.0, FALSE, FALSE)
DOOR_SYSTEM_SET_DOOR_STATE(ENUM_TO_INT(DOORHASH_M_MANSION_F_L), DOORSTATE_FORCE_UNLOCKED_THIS_FRAME, FALSE, TRUE)
ENDIF
IF IS_DOOR_REGISTERED_WITH_SYSTEM(ENUM_TO_INT(DOORHASH_M_MANSION_F_R))
DOOR_SYSTEM_SET_OPEN_RATIO(ENUM_TO_INT(DOORHASH_M_MANSION_F_R), 0.0, FALSE, FALSE)
DOOR_SYSTEM_SET_DOOR_STATE(ENUM_TO_INT(DOORHASH_M_MANSION_F_R), DOORSTATE_FORCE_UNLOCKED_THIS_FRAME, FALSE, TRUE)
ENDIF
SET_NO_LOADING_SCREEN(TRUE)
IF IS_SCREEN_FADED_OUT()
DO_SCREEN_FADE_IN(DEFAULT_FADE_TIME)
ENDIF
iStageProgress++
ENDIF
BREAK
CASE 2
VEHICLE_INDEX LastPlayerVehicleIndex
LastPlayerVehicleIndex = GET_PLAYERS_LAST_VEHICLE()
IF DOES_ENTITY_EXIST(LastPlayerVehicleIndex)
//IF ( LastPlayerVehicleIndex != vsPlayersCar.VehicleIndex )
IF IS_ENTITY_A_MISSION_ENTITY(LastPlayerVehicleIndex)
SET_VEHICLE_AS_NO_LONGER_NEEDED(LastPlayerVehicleIndex)
ENDIF
//ENDIF
ENDIF
IF IS_CUTSCENE_PLAYING()
SWITCH iCutsceneCarLightsProgress
CASE 0 //cutscene car turns up in the cutscene
IF GET_CUTSCENE_TIME() > 14500.0
IF IS_VEHICLE_DRIVEABLE(vsCutsceneCar.VehicleIndex)
SET_VEHICLE_ENGINE_ON(vsCutsceneCar.VehicleIndex, TRUE, TRUE)
SET_VEHICLE_LIGHTS(vsCutsceneCar.VehicleIndex, SET_VEHICLE_LIGHTS_ON)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Turning cutscene car baller lights on.")
#ENDIF
iCutsceneCarLightsProgress++
ENDIF
ENDIF
BREAK
CASE 1 //driver gets out
IF GET_CUTSCENE_TIME() > 19200.0
IF IS_VEHICLE_DRIVEABLE(vsCutsceneCar.VehicleIndex)
SET_VEHICLE_ENGINE_ON(vsCutsceneCar.VehicleIndex, FALSE, FALSE)
SET_VEHICLE_LIGHTS(vsCutsceneCar.VehicleIndex, SET_VEHICLE_LIGHTS_OFF)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Turning cutscene car baller lights off.")
#ENDIF
iCutsceneCarLightsProgress++
ENDIF
ENDIF
BREAK
CASE 2
IF GET_CUTSCENE_TIME() > 127760.0
IF IS_VEHICLE_DRIVEABLE(vsCutsceneCar.VehicleIndex)
SET_VEHICLE_ENGINE_ON(vsCutsceneCar.VehicleIndex, TRUE, TRUE)
SET_VEHICLE_LIGHTS(vsCutsceneCar.VehicleIndex, SET_VEHICLE_LIGHTS_ON)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Turning cutscene car baller lights on.")
#ENDIF
iCutsceneCarLightsProgress++
ENDIF
ENDIF
BREAK
CASE 3
IF GET_CUTSCENE_TIME() > 131850.0
IF IS_VEHICLE_DRIVEABLE(vsCutsceneCar.VehicleIndex)
SET_VEHICLE_LIGHTS(vsCutsceneCar.VehicleIndex, SET_VEHICLE_LIGHTS_OFF)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Turning cutscene car baller lights off.")
#ENDIF
iCutsceneCarLightsProgress++
ENDIF
ENDIF
BREAK
ENDSWITCH
ENDIF
IF CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY("Michael")
//hot swap to Michael if not currently controlling Michael
IF ( GET_CURRENT_PLAYER_PED_ENUM() <> CHAR_MICHAEL )
IF MAKE_SELECTOR_PED_SELECTION(sSelectorPeds, SELECTOR_PED_MICHAEL)
TAKE_CONTROL_OF_SELECTOR_PED(sSelectorPeds, TRUE, TRUE)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Taking control of player ped Michael when CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY() returned true for Michael.")
#ENDIF
ENDIF
ENDIF
ENDIF
IF CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY("Madrazos_Car")
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY() returned true for Madrazos_Car.")
#ENDIF
CLEANUP_VEHICLE(vsCutsceneCar, TRUE)
ENDIF
IF HAS_CUTSCENE_FINISHED()
REPLAY_STOP_EVENT()
IF IS_DOOR_REGISTERED_WITH_SYSTEM(ENUM_TO_INT(DOORHASH_M_MANSION_G1))
DOOR_SYSTEM_SET_OPEN_RATIO(ENUM_TO_INT(DOORHASH_M_MANSION_G1), 0.0, FALSE, FALSE)
DOOR_SYSTEM_SET_DOOR_STATE(ENUM_TO_INT(DOORHASH_M_MANSION_G1), DOORSTATE_UNLOCKED, FALSE, TRUE)
ENDIF
SET_PLAYER_CONTROL(PLAYER_ID(), TRUE)
SET_GAMEPLAY_CAM_RELATIVE_PITCH(0)
SET_GAMEPLAY_CAM_RELATIVE_HEADING(0)
SET_SCRIPTS_SAFE_FOR_CUTSCENE(FALSE)
//move player's mission start car to Franklin's safe house if mission started by Franklin
IF GET_PLAYER_CHARACTER_AT_MISSION_START() = CHAR_FRANKLIN
VEHICLE_INDEX VehGenVehicleIndex
VehGenVehicleIndex = GET_VEHICLE_GEN_VEHICLE_INDEX(VEHGEN_MISSION_VEH)
IF DOES_ENTITY_EXIST(VehGenVehicleIndex)
IF NOT IS_ENTITY_DEAD(VehGenVehicleIndex)
STORE_VEH_DATA_FROM_VEH(GET_PED_INDEX(CHAR_FRANKLIN), VehGenVehicleIndex, //make the vehicle gen vehicle Franklin's last known vehicle
g_sPlayerLastVeh[SELECTOR_PED_FRANKLIN],
g_vPlayerLastVehCoord[SELECTOR_PED_FRANKLIN],
g_fPlayerLastVehHead[SELECTOR_PED_FRANKLIN],
g_ePlayerLastVehState[SELECTOR_PED_FRANKLIN],
g_ePlayerLastVehGen[SELECTOR_PED_FRANKLIN])
SET_MISSION_VEHICLE_GEN_VEHICLE(VehGenVehicleIndex, << -25.02, -1467.7142, 29.7815>>, 275.6534) //move Franklin's start car to area in Franklin's safe house
CLEAR_AREA(<< -867.91, 158.22, 63.90 >>, 5.0, TRUE) //clear area where the car was parked for the mission
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Setting Franklin's mission start vehicle as vehicle gen in position << -25.02, -1467.7142, 29.7815>> and heading 275.6534.")
#ENDIF
ENDIF
ENDIF
ENDIF
IF DOES_ENTITY_EXIST(GET_PED_INDEX(CHAR_FRANKLIN))
psFranklin.PedIndex = GET_PED_INDEX(CHAR_FRANKLIN)
sSelectorPeds.pedID[SELECTOR_PED_FRANKLIN] = psFranklin.PedIndex
DELETE_PED(psFranklin.PedIndex)
ENDIF
CLEANUP_VEHICLE(vsCutsceneCar, TRUE)
iStageProgress++
ELSE
#IF IS_DEBUG_BUILD
IF IS_CUTSCENE_SKIP_BUTTON_JUST_PRESSED_WITH_DELAY()
STOP_CUTSCENE()
ENDIF
#ENDIF
ENDIF
BREAK
CASE 3
TRIGGER_MISSION_STATS_UI(TRUE, TRUE)
iStageProgress++
BREAK
CASE 4
IF ( g_bResultScreenDisplaying = TRUE )
iStageProgress++
ENDIF
BREAK
CASE 5
IF NOT IS_REPEAT_PLAY_ACTIVE()
RETURN TRUE
ELSE
IF ( g_bResultScreenDisplaying = FALSE )
RETURN TRUE
ENDIF
ENDIF
BREAK
ENDSWITCH
RETURN FALSE
ENDFUNC
FUNC BOOL IS_MISSION_STAGE_LEADOUT_COMPLETED(INT &iStageProgress)
SWITCH iStageProgress
CASE 0
WARP_PED(PLAYER_PED_ID(), psMichael.vPosition, psMichael.fHeading, FALSE, TRUE, FALSE)
IF NOT IS_ENTITY_DEAD(PLAYER_PED_ID())
CLEAR_PED_WETNESS(PLAYER_PED_ID())
CLEAR_PED_DECORATIONS(PLAYER_PED_ID())
CLEAR_PED_BLOOD_DAMAGE(PLAYER_PED_ID())
RESET_PED_VISIBLE_DAMAGE(PLAYER_PED_ID())
RESTORE_PLAYER_PED_TATTOOS(PLAYER_PED_ID())
SET_PED_STEALTH_MOVEMENT(PLAYER_PED_ID(), FALSE)
SET_PED_USING_ACTION_MODE(PLAYER_PED_ID(), FALSE)
CLEAR_AREA(GET_ENTITY_COORDS(PLAYER_PED_ID()), 1000.0, TRUE)
REMOVE_DECALS_IN_RANGE(GET_ENTITY_COORDS(PLAYER_PED_ID()), 1000.0)
REMOVE_PARTICLE_FX_IN_RANGE(GET_ENTITY_COORDS(PLAYER_PED_ID()), 1000.0)
SET_CURRENT_PED_WEAPON(PLAYER_PED_ID(), WEAPONTYPE_UNARMED, TRUE)
SET_ENTITY_HEALTH(PLAYER_PED_ID(), GET_PED_MAX_HEALTH(PLAYER_PED_ID()))
ENDIF
SET_PLAYER_CONTROL(PLAYER_ID(), FALSE)
SET_WEATHER_TYPE_NOW("CLOUDS")
ADVANCE_CLOCK_TIME_TO(11, 0, 0)
iLeadOutLoadSceneTimer = GET_GAME_TIMER()
iStageProgress++
BREAK
CASE 1
IF NOT IS_NEW_LOAD_SCENE_ACTIVE()
NEW_LOAD_SCENE_START(<< -97.12, -410.58, 35.89 >>, << 0.31, -0.9, 0.5 >>, 500.0)
iLeadOutLoadSceneTimer = GET_GAME_TIMER()
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Calling NEW_LOAD_SCENE_START().")
#ENDIF
ENDIF
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Leadout load scene timer: ", GET_GAME_TIMER() - iLeadOutLoadSceneTimer, ".")
#ENDIF
IF IS_NEW_LOAD_SCENE_LOADED()
OR HAS_TIME_PASSED(10000, iLeadOutLoadSceneTimer)
#IF IS_DEBUG_BUILD
IF HAS_TIME_PASSED(10000, iLeadOutLoadSceneTimer)
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Calling NEW_LOAD_SCENE_STOP() due to iLoadSceneTimer timeout.")
ELSE
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Calling NEW_LOAD_SCENE_STOP() due to IS_NEW_LOAD_SCENE_LOADED() returning TRUE.")
ENDIF
#ENDIF
NEW_LOAD_SCENE_STOP()
iLeadOutTimer = 0
iStageProgress++
ENDIF
BREAK
CASE 2
REQUEST_MODEL(osCellphone.ModelName)
REQUEST_ANIM_DICT("switch@michael@bench")
IF HAS_MODEL_LOADED(osCellphone.ModelName)
AND HAS_ANIM_DICT_LOADED("switch@michael@bench")
IF ( g_bResultScreenDisplaying = FALSE )
IF ( iLeadOutTimer = 0 )
iLeadOutTimer = GET_GAME_TIMER()
ENDIF
IF iLeadOutTimer != 0 AND HAS_TIME_PASSED(1000, iLeadOutTimer)
IF NOT IS_SYNCHRONIZED_SCENE_RUNNING(iPhoneCallSceneID)
iPhoneCallSceneID = CREATE_SYNCHRONIZED_SCENE(<< -95.550, -415.100, 35.6750 >>, << 0.0, 0.0, 133.0 >>)
SET_SYNCHRONIZED_SCENE_LOOPED(iPhoneCallSceneID, TRUE)
IF HAS_MISSION_OBJECT_BEEN_CREATED(osCellphone, FALSE)
SET_OBJECT_TINT_INDEX(osCellphone.ObjectIndex, GET_PHONE_SURROUND_TINT_FOR_SP_PLAYER_CHARACTER(GET_CURRENT_PLAYER_PED_ENUM()))
ATTACH_ENTITY_TO_ENTITY(osCellphone.ObjectIndex, PLAYER_PED_ID(), GET_PED_BONE_INDEX(PLAYER_PED_ID(), BONETAG_PH_R_HAND),
<< 0.0, 0.0, 0.0 >>, << 0.0, 0.0, 0.0 >>)
ENDIF
TASK_SYNCHRONIZED_SCENE(PLAYER_PED_ID(), iPhoneCallSceneID, "switch@michael@bench", "bench_on_phone_idle_listen",
INSTANT_BLEND_IN, WALK_BLEND_OUT, SYNCED_SCENE_USE_PHYSICS)
FORCE_PED_AI_AND_ANIMATION_UPDATE(PLAYER_PED_ID(), TRUE)
SET_MODEL_AS_NO_LONGER_NEEDED(osCellphone.ModelName)
SET_PLAYER_CONTROL(PLAYER_ID(), FALSE, SPC_LEAVE_CAMERA_CONTROL_ON)
DISPLAY_HUD(FALSE)
DISPLAY_RADAR(FALSE)
DISABLE_CELLPHONE(TRUE)
DESTROY_ALL_CAMS()
ScriptedCamera = CREATE_CAMERA(CAMTYPE_SCRIPTED, TRUE)
SET_CAM_PARAMS(ScriptedCamera, <<-90.226990,-417.333160,45.110085>>,<<37.580025,-0.041530,-165.663498>>,50.0)
SHAKE_CAM(ScriptedCamera, "HAND_SHAKE", 0.15)
RENDER_SCRIPT_CAMS(TRUE, FALSE)
iStageProgress++
ENDIF
ENDIF
ENDIF
ENDIF
BREAK
CASE 3
IF IS_SYNCHRONIZED_SCENE_RUNNING(iPhoneCallSceneID)
SET_CAM_PARAMS(ScriptedCamera, <<-90.226990,-417.333160,45.110085>>,<<37.580025,-0.041530,-165.663498>>,50.0)
SET_NO_LOADING_SCREEN(FALSE)
IF IS_SCREEN_FADED_OUT()
DO_SCREEN_FADE_IN(DEFAULT_FADE_TIME_LONG)
ENDIF
IF NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_LOUT_1")
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_LOUT", CONV_PRIORITY_MEDIUM)
SET_LABEL_AS_TRIGGERED("FAM3_LOUT_1", TRUE)
iCameraTimer = GET_GAME_TIMER()
iCameraProgress = 0
iStageProgress++
ENDIF
ENDIF
ENDIF
BREAK
CASE 4
DISABLE_ON_FOOT_FIRST_PERSON_VIEW_THIS_UPDATE()
DISABLE_FIRST_PERSON_FLASH_EFFECT_THIS_UPDATE()
IF IS_SYNCHRONIZED_SCENE_RUNNING(iPhoneCallSceneID)
SWITCH iCameraProgress
CASE 0
IF GET_GAME_TIMER() - iCameraTimer > 250
SET_CAM_PARAMS(ScriptedCamera, <<-90.226990,-417.333160,45.110085>>,<<37.580025,-0.041530,-165.663498>>,50.0)
SET_CAM_PARAMS(ScriptedCamera, <<-93.942017,-413.060974,36.347176>>, <<7.278719,0.000000,134.331406>>, 50.0,
14000, GRAPH_TYPE_SIN_ACCEL_DECEL, GRAPH_TYPE_SIN_ACCEL_DECEL)
iCameraTimer = GET_GAME_TIMER()
iCameraProgress = 1
ENDIF
BREAK
CASE 1
IF GET_GAME_TIMER() - iCameraTimer > 14000
STOP_RENDERING_SCRIPT_CAMS_USING_CATCH_UP()
DESTROY_CAM(ScriptedCamera)
iPhoneCallSceneID = CREATE_SYNCHRONIZED_SCENE(<< -95.550, -415.100, 35.6750 >>, << 0.0, 0.0, 133.0 >>)
SET_SYNCHRONIZED_SCENE_LOOPED(iPhoneCallSceneID, FALSE)
TASK_SYNCHRONIZED_SCENE(PLAYER_PED_ID(), iPhoneCallSceneID, "switch@michael@bench", "exit_forward",
WALK_BLEND_IN, SLOW_BLEND_OUT, SYNCED_SCENE_USE_PHYSICS|SYNCED_SCENE_DONT_INTERRUPT|SYNCED_SCENE_TAG_SYNC_OUT)
FORCE_PED_AI_AND_ANIMATION_UPDATE(PLAYER_PED_ID(), TRUE)
iStageProgress++
ENDIF
BREAK
ENDSWITCH
ENDIF
BREAK
CASE 5
DISABLE_ON_FOOT_FIRST_PERSON_VIEW_THIS_UPDATE()
DISABLE_FIRST_PERSON_FLASH_EFFECT_THIS_UPDATE()
DISABLE_CONTROL_ACTION(CAMERA_CONTROL, INPUT_NEXT_CAMERA)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_DUCK)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_JUMP)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_ENTER)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_COVER)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_SPRINT)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_WHISTLE)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_CONTEXT)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_SELECT_WEAPON)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_SPECIAL_ABILITY)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_CHARACTER_WHEEL)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_AIM)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_ATTACK)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_ATTACK2)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_MELEE_ATTACK_HEAVY)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_MELEE_ATTACK_LIGHT)
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
IF IS_SYNCHRONIZED_SCENE_RUNNING(iPhoneCallSceneID)
IF GET_SYNCHRONIZED_SCENE_PHASE(iPhoneCallSceneID) > 0.99
IF GET_CAM_VIEW_MODE_FOR_CONTEXT(CAM_VIEW_MODE_CONTEXT_ON_FOOT) = CAM_VIEW_MODE_FIRST_PERSON
bResetFirstPersonCamera = TRUE
ELSE
DISPLAY_HUD(TRUE)
DISPLAY_RADAR(TRUE)
ENDIF
CLEAR_PED_TASKS(PLAYER_PED_ID())
SET_PLAYER_CONTROL(PLAYER_ID(), TRUE)
TASK_PLAY_ANIM(PLAYER_PED_ID(), "switch@michael@bench", "cellphone_call_listen_base", INSTANT_BLEND_IN, WALK_BLEND_OUT, -1, AF_SECONDARY | AF_LOOPING | AF_UPPERBODY)
FORCE_PED_AI_AND_ANIMATION_UPDATE(PLAYER_PED_ID())
iStageProgress++
ELIF GET_SYNCHRONIZED_SCENE_PHASE(iPhoneCallSceneID) > fFirstPersonFlashPhase3
IF GET_CAM_VIEW_MODE_FOR_CONTEXT(CAM_VIEW_MODE_CONTEXT_ON_FOOT) = CAM_VIEW_MODE_FIRST_PERSON
IF bFirstPersonFlashPlayed = FALSE
ANIMPOSTFX_PLAY("CamPushInNeutral", 0, FALSE)
PLAY_SOUND_FRONTEND(-1, "1st_Person_Transition", "PLAYER_SWITCH_CUSTOM_SOUNDSET")
bFirstPersonFlashPlayed = TRUE
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
BREAK
CASE 6
IF ( bResetFirstPersonCamera = TRUE )
IF GET_CAM_VIEW_MODE_FOR_CONTEXT(CAM_VIEW_MODE_CONTEXT_ON_FOOT) = CAM_VIEW_MODE_FIRST_PERSON
DISPLAY_HUD(TRUE)
DISPLAY_RADAR(TRUE)
SET_GAMEPLAY_CAM_RELATIVE_PITCH()
SET_GAMEPLAY_CAM_RELATIVE_HEADING()
bResetFirstPersonCamera = FALSE
ENDIF
ENDIF
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
IF IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(), "switch@michael@bench", "cellphone_call_listen_base")
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_DUCK)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_JUMP)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_ENTER)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_COVER)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_SPRINT)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_WHISTLE)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_CONTEXT)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_SELECT_WEAPON)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_SPECIAL_ABILITY)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_CHARACTER_WHEEL)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_AIM)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_ATTACK)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_ATTACK2)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_MELEE_ATTACK_HEAVY)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_MELEE_ATTACK_LIGHT)
SET_PED_MAX_MOVE_BLEND_RATIO(PLAYER_PED_ID(), PEDMOVE_WALK)
IF ( bLeadoutConversationEnded = FALSE )
IF HAS_LABEL_BEEN_TRIGGERED("FAM3_LOUT_1")
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
TEXT_LABEL_23 CurrentRoot, CurrentLabel
CurrentRoot = GET_CURRENTLY_PLAYING_STANDARD_CONVERSATION_ROOT()
CurrentLabel = GET_CURRENTLY_PLAYING_STANDARD_CONVERSATION_LABEL()
IF NOT IS_STRING_NULL_OR_EMPTY(CurrentRoot)
AND NOT IS_STRING_NULL_OR_EMPTY(CurrentLabel)
IF ARE_STRINGS_EQUAL(CurrentRoot, "FAM3_LOUT")
AND ARE_STRINGS_EQUAL(CurrentLabel, "FAM3_LOUT_17")
KILL_ANY_CONVERSATION()
KILL_FACE_TO_FACE_CONVERSATION()
bLeadoutConversationEnded = TRUE
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
IF HAS_LABEL_BEEN_TRIGGERED("FAM3_LOUT_1")
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
ANIM_DATA LocalAnimData, EmptyAnimData
LocalAnimData.type = APT_SINGLE_ANIM
LocalAnimData.dictionary0 = "switch@michael@bench"
LocalAnimData.anim0 = "cellphone_call_out"
LocalAnimData.flags = AF_SECONDARY
LocalAnimData.blendInDelta = WALK_BLEND_IN
LocalAnimData.blendOutDelta = WALK_BLEND_OUT
LocalAnimData.filter = GET_HASH_KEY("bonemask_head_neck_and_r_arm")
TASK_SCRIPTED_ANIMATION(PLAYER_PED_ID(), LocalAnimData, EmptyAnimData, EmptyAnimData, SLOW_BLEND_DURATION, SLOW_BLEND_DURATION)
FORCE_PED_AI_AND_ANIMATION_UPDATE(PLAYER_PED_ID())
iStageProgress++
ENDIF
ENDIF
ENDIF
ENDIF
BREAK
CASE 7
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
IF IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(), "switch@michael@bench", "cellphone_call_out")
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_DUCK)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_JUMP)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_ENTER)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_COVER)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_SPRINT)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_WHISTLE)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_CONTEXT)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_SELECT_WEAPON)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_SPECIAL_ABILITY)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_CHARACTER_WHEEL)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_AIM)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_ATTACK)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_ATTACK2)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_MELEE_ATTACK_HEAVY)
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_MELEE_ATTACK_LIGHT)
SET_PED_MAX_MOVE_BLEND_RATIO(PLAYER_PED_ID(), PEDMOVE_WALK)
IF NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_LOUT_2")
IF CREATE_CONVERSATION_FROM_SPECIFIC_LINE(sFamily3Conversation, "FAM3AUD", "FAM3_LOUT", "FAM3_LOUT_19", CONV_PRIORITY_MEDIUM)
SET_LABEL_AS_TRIGGERED("FAM3_LOUT_2", TRUE)
ENDIF
ENDIF
IF GET_ENTITY_ANIM_CURRENT_TIME(PLAYER_PED_ID(), "switch@michael@bench", "cellphone_call_out") > 0.3
IF DOES_ENTITY_EXIST(osCellphone.ObjectIndex)
IF IS_ENTITY_ATTACHED(osCellphone.ObjectIndex)
DETACH_ENTITY(osCellphone.ObjectIndex, FALSE)
ENDIF
DELETE_OBJECT(osCellphone.ObjectIndex)
ENDIF
CLEAR_PED_TASKS(PLAYER_PED_ID())
iStageProgress++
ENDIF
ENDIF
ENDIF
BREAK
CASE 8
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF DOES_ENTITY_EXIST(vsMichaelsEndCar.VehicleIndex)
IF NOT IS_ENTITY_DEAD(vsMichaelsEndCar.VehicleIndex)
SET_MISSION_VEHICLE_GEN_VEHICLE(vsMichaelsEndCar.VehicleIndex, vsMichaelsEndCar.vPosition, vsMichaelsEndCar.fHeading)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Setting Michael's mission start vehicle as vehicle gen in position ", vsMichaelsEndCar.vPosition, " and heading ", vsMichaelsEndCar.fHeading, ".")
#ENDIF
ENDIF
ENDIF
DISPLAY_HUD(TRUE)
DISPLAY_RADAR(TRUE)
DISABLE_CELLPHONE(FALSE)
SET_PLAYER_CONTROL(PLAYER_ID(), TRUE)
REMOVE_ANIM_DICT("switch@michael@bench")
RETURN TRUE
ENDIF
BREAK
ENDSWITCH
RETURN FALSE
ENDFUNC
PROC UPDATE_BLIPS_FOR_GOONS_AND_VEHICLE(PED_STRUCT &array[], VEH_STRUCT &vehicle)
INT i
BOOL bAtLeastOnePedInVehicle
IF DOES_ENTITY_EXIST(vehicle.VehicleIndex)
IF IS_VEHICLE_DRIVEABLE(vehicle.VehicleIndex)
FOR i = 0 TO ( COUNT_OF(array) - 1 )
IF NOT IS_PED_INJURED(array[i].PedIndex)
IF IS_PED_IN_VEHICLE(array[i].PedIndex, vehicle.VehicleIndex)
IF DOES_BLIP_EXIST(array[i].BlipIndex)
REMOVE_BLIP(array[i].BlipIndex)
ENDIF
bAtLeastOnePedInVehicle = TRUE
ELSE
IF NOT DOES_BLIP_EXIST(array[i].BlipIndex)
array[i].BlipIndex = CREATE_BLIP_FOR_PED(array[i].PedIndex, TRUE)
ENDIF
ENDIF
ENDIF
ENDFOR
IF NOT DOES_BLIP_EXIST(vehicle.BlipIndex)
IF ( bAtLeastOnePedInVehicle = TRUE )
vehicle.BlipIndex = CREATE_BLIP_FOR_COORD(GET_ENTITY_COORDS(vehicle.VehicleIndex))
SET_BLIP_COLOUR(vehicle.BlipIndex, BLIP_COLOUR_RED)
SET_BLIP_PRIORITY(vehicle.BlipIndex, BLIPPRIORITY_HIGHEST)
SET_BLIP_NAME_FROM_TEXT_FILE(vehicle.BlipIndex, "BLIP_VEH")
ENDIF
ELSE
VECTOR vBlipPosition = GET_BLIP_COORDS(vehicle.BlipIndex)
VECTOR vVehiclePosition = GET_ENTITY_COORDS(vehicle.VehicleIndex)
vBlipPosition.X = vBlipPosition.X +@((vVehiclePosition.X - vBlipPosition.X) / BLIP_SLIDE_AMOUNT)
vBlipPosition.Y = vBlipPosition.Y +@((vVehiclePosition.Y - vBlipPosition.Y) / BLIP_SLIDE_AMOUNT)
vBlipPosition.Z = vBlipPosition.Z +@((vVehiclePosition.Z - vBlipPosition.Z) / BLIP_SLIDE_AMOUNT)
SET_BLIP_COORDS(vehicle.BlipIndex, vBlipPosition)
IF ( bAtLeastOnePedInVehicle = FALSE )
REMOVE_BLIP(vehicle.BlipIndex)
ENDIF
ENDIF
ELSE
IF DOES_BLIP_EXIST(vehicle.BlipIndex)
REMOVE_BLIP(vehicle.BlipIndex)
ENDIF
FOR i = 0 TO ( COUNT_OF(array) - 1 )
IF NOT IS_PED_INJURED(array[i].PedIndex)
IF NOT DOES_BLIP_EXIST(array[i].BlipIndex)
array[i].BlipIndex = CREATE_BLIP_FOR_PED(array[i].PedIndex, TRUE)
ENDIF
ENDIF
ENDFOR
ENDIF
ENDIF
ENDPROC
PROC CLEANUP_GOONS_AND_VEHICLE(PED_STRUCT &array[], VEH_STRUCT &vehicle, FLOAT fCleanupDistanceInVehicle = 300.0, FLOAT fCleanupDistanceOnFoot = 150.0)
INT i
BOOL bAtLeastOnePedAlive
BOOL bAtLeastOnePedInVehicle
FOR i = 0 TO ( COUNT_OF(array) - 1 )
IF DOES_ENTITY_EXIST(array[i].PedIndex)
IF IS_PED_INJURED(array[i].PedIndex)
IF ( array[i].eCleanupReason = PED_CLEANUP_NO_CLEANUP ) //ped has no cleanup reason
array[i].eCleanupReason = GET_PED_CLEANUP_REASON(array[i])
UPDATE_PLAYER_AND_BUDDY_KILL_COUNTERS(array[i].eCleanupReason, iPlayerMichaelKills, iPlayerFranklinKills, iBuddyMichaelKills, iBuddyFranklinKills)
IF DOES_BLIP_EXIST(array[i].BlipIndex)
REMOVE_BLIP(array[i].BlipIndex)
ENDIF
ELSE //ped has a valid cleanup reason
REPLAY_RECORD_BACK_FOR_TIME(3, 0, REPLAY_IMPORTANCE_HIGH)
SET_PED_AS_NO_LONGER_NEEDED(array[i].PedIndex)
ENDIF
ELSE
bAtLeastOnePedAlive = TRUE
IF NOT IS_PED_IN_ANY_VEHICLE(array[i].PedIndex)
IF ( GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), array[i].PedIndex) > fCleanupDistanceOnFoot )
array[i].eCleanupReason = PED_CLEANUP_LOST //flag ped cleanup reason as lost
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Ped on foot ", array[i].sDebugName, " cleaned up with reason PED_CLEANUP_LOST.")
#ENDIF
SET_PED_AS_NO_LONGER_NEEDED(array[i].PedIndex)
IF DOES_BLIP_EXIST(array[i].BlipIndex)
REMOVE_BLIP(array[i].BlipIndex)
ENDIF
ENDIF
ELSE
IF DOES_ENTITY_EXIST(vehicle.VehicleIndex)
IF IS_VEHICLE_DRIVEABLE(vehicle.VehicleIndex)
IF IS_PED_IN_VEHICLE(array[i].PedIndex, vehicle.VehicleIndex)
bAtLeastOnePedInVehicle = TRUE
IF ( GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), array[i].PedIndex) > fCleanupDistanceInVehicle )
array[i].eCleanupReason = PED_CLEANUP_LOST //flag ped cleanup reason as lost
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Ped in vehicle ", vehicle.sDebugName, " ", array[i].sDebugName, " cleaned up with reason PED_CLEANUP_LOST.")
#ENDIF
SET_PED_AS_NO_LONGER_NEEDED(array[i].PedIndex)
IF DOES_BLIP_EXIST(array[i].BlipIndex)
REMOVE_BLIP(array[i].BlipIndex)
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDFOR
IF DOES_ENTITY_EXIST(vehicle.VehicleIndex)
IF IS_VEHICLE_DRIVEABLE(vehicle.VehicleIndex)
IF ( bAtLeastOnePedAlive = TRUE )
OR ( bAtLeastOnePedInVehicle = TRUE )
IF ( GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), vehicle.VehicleIndex) > fCleanupDistanceInVehicle )
REMOVE_VEHICLE_STUCK_CHECK(vehicle.VehicleIndex)
REMOVE_VEHICLE_UPSIDEDOWN_CHECK(vehicle.VehicleIndex)
REMOVE_ENTITY_FROM_AUDIO_MIX_GROUP(vehicle.VehicleIndex)
SET_VEHICLE_AS_NO_LONGER_NEEDED(vehicle.VehicleIndex)
IF DOES_BLIP_EXIST(vehicle.BlipIndex)
REMOVE_BLIP(vehicle.BlipIndex)
ENDIF
ENDIF
ELSE
REMOVE_VEHICLE_STUCK_CHECK(vehicle.VehicleIndex)
REMOVE_VEHICLE_UPSIDEDOWN_CHECK(vehicle.VehicleIndex)
REMOVE_ENTITY_FROM_AUDIO_MIX_GROUP(vehicle.VehicleIndex)
SET_VEHICLE_AS_NO_LONGER_NEEDED(vehicle.VehicleIndex)
IF DOES_BLIP_EXIST(vehicle.BlipIndex)
REMOVE_BLIP(vehicle.BlipIndex)
ENDIF
ENDIF
ELSE
REMOVE_VEHICLE_STUCK_CHECK(vehicle.VehicleIndex)
REMOVE_VEHICLE_UPSIDEDOWN_CHECK(vehicle.VehicleIndex)
REMOVE_ENTITY_FROM_AUDIO_MIX_GROUP(vehicle.VehicleIndex)
SET_VEHICLE_AS_NO_LONGER_NEEDED(vehicle.VehicleIndex)
IF DOES_BLIP_EXIST(vehicle.BlipIndex)
REMOVE_BLIP(vehicle.BlipIndex)
ENDIF
ENDIF
ENDIF
ENDPROC
PROC MANAGE_GOON_PED_IN_VEHICLE(PED_STRUCT &ped, VEH_STRUCT &vehicle, PED_INDEX TargetPedIndex, VEHICLE_INDEX TargetVehicleIndex,
BOOL &bAggressive)
IF NOT IS_PED_INJURED(ped.PedIndex)
AND NOT IS_PED_INJURED(TargetPedIndex)
#IF IS_DEBUG_BUILD
IF ( bDrawDebugStates = TRUE )
DRAW_DEBUG_TEXT_ABOVE_ENTITY(ped.PedIndex, GET_PED_STATE_NAME_FOR_DEBUG(ped.eState), 1.25)
DRAW_DEBUG_TEXT_ABOVE_ENTITY(ped.PedIndex, GET_STRING_FROM_FLOAT(ped.fDistanceToTarget), 1.5)
ENDIF
#ENDIF
//calculate distance to target ped every frame
ped.fDistanceToTarget = GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(ped.PedIndex), GET_ENTITY_COORDS(TargetPedIndex))
//check if target ped (the player) damaged the security ped or vehicle with a weapon
IF ( bAggressive = FALSE )
IF HAS_ENTITY_BEEN_DAMAGED_BY_ENTITY(ped.PedIndex, TargetPedIndex, TRUE)
IF HAS_ENTITY_BEEN_DAMAGED_BY_WEAPON(ped.PedIndex, WEAPONTYPE_INVALID, GENERALWEAPON_TYPE_ANYWEAPON)
CLEAR_ENTITY_LAST_DAMAGE_ENTITY(ped.PedIndex)
bAggressive = TRUE
ENDIF
ENDIF
IF DOES_ENTITY_EXIST(vehicle.VehicleIndex)
IF NOT IS_ENTITY_DEAD(vehicle.VehicleIndex)
IF HAS_ENTITY_BEEN_DAMAGED_BY_ENTITY(vehicle.VehicleIndex, TargetPedIndex, TRUE)
IF HAS_ENTITY_BEEN_DAMAGED_BY_WEAPON(vehicle.VehicleIndex, WEAPONTYPE_INVALID, GENERALWEAPON_TYPE_ANYWEAPON)
CLEAR_ENTITY_LAST_DAMAGE_ENTITY(vehicle.VehicleIndex)
bAggressive = TRUE
ENDIF
ENDIF
ENDIF
ENDIF
IF ( ped.iAgressiveTimer <> 0 )
IF HAS_TIME_PASSED(10000, ped.iAgressiveTimer)
bAggressive = TRUE
ENDIF
ENDIF
ENDIF
IF ( ped.eState != PED_STATE_COMBAT_ON_FOOT )
IF IS_PED_FLEEING(ped.PedIndex) OR IS_PED_BEING_JACKED(ped.PedIndex)
GO_TO_PED_STATE(ped, PED_STATE_COMBAT_ON_FOOT)
ENDIF
ENDIF
SWITCH ped.eState
CASE PED_STATE_IDLE
GO_TO_PED_STATE(ped, PED_STATE_COMBAT_FROM_CAR_SHOOTING)
BREAK
CASE PED_STATE_COMBAT_ON_FOOT
IF ( ped.bHasTask = FALSE )
SET_PED_COMBAT_RANGE(ped.PedIndex, CR_NEAR)
SET_PED_COMBAT_MOVEMENT(ped.PedIndex, CM_WILLADVANCE)
SET_PED_COMBAT_ABILITY(ped.PedIndex, CAL_PROFESSIONAL)
SET_PED_COMBAT_ATTRIBUTES(ped.PedIndex, CA_CAN_FLANK, TRUE)
SET_PED_COMBAT_ATTRIBUTES(ped.PedIndex, CA_CAN_CHARGE, TRUE)
SET_PED_COMBAT_ATTRIBUTES(ped.PedIndex, CA_AGGRESSIVE, TRUE)
SET_PED_COMBAT_ATTRIBUTES(ped.PedIndex, CA_USE_VEHICLE, FALSE)
SET_PED_COMBAT_ATTRIBUTES(ped.PedIndex, CA_LEAVE_VEHICLES, TRUE)
SET_PED_COMBAT_ATTRIBUTES(ped.PedIndex, CA_CAN_CHASE_TARGET_ON_FOOT, TRUE)
SET_COMBAT_FLOAT(ped.PedIndex, CCF_WALK_WHEN_STRAFING_CHANCE, 0.1)
SET_PED_ACCURACY(ped.PedIndex, 6)
SET_PED_SHOOT_RATE(ped.PedIndex, 125)
TASK_COMBAT_HATED_TARGETS_AROUND_PED(ped.PedIndex, 200.0)
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(ped.PedIndex, FALSE)
ped.bHasTask = TRUE
ENDIF
IF IS_PED_DRIVING_VEHICLE(TargetPedIndex, TargetVehicleIndex)
IF ( ped.fDistanceToTarget > 20.0)
IF DOES_ENTITY_EXIST(vehicle.VehicleIndex)
IF IS_VEHICLE_DRIVEABLE(vehicle.VehicleIndex)
AND GET_ENTITY_HEALTH(vehicle.VehicleIndex) > 0
AND GET_VEHICLE_ENGINE_HEALTH(vehicle.VehicleIndex) > 0
AND NOT IS_VEHICLE_STUCK_ON_ROOF(vehicle.VehicleIndex)
AND NOT IS_VEHICLE_PERMANENTLY_STUCK(vehicle.VehicleIndex)
AND NOT IS_ENTITY_UPSIDEDOWN(vehicle.VehicleIndex)
IF NOT IS_PED_IN_VEHICLE(ped.PedIndex, vehicle.VehicleIndex)
IF IS_VEHICLE_SEAT_FREE(vehicle.VehicleIndex, VS_DRIVER)
OR IS_VEHICLE_SEAT_FREE(vehicle.VehicleIndex, VS_FRONT_RIGHT)
GO_TO_PED_STATE(ped, PED_STATE_ENTERING_VEHICLE)
ENDIF
ELSE
IF IS_PED_SITTING_IN_VEHICLE(ped.PedIndex, vehicle.VehicleIndex)
IF ( bAggressive = TRUE )
GO_TO_PED_STATE(ped, PED_STATE_COMBAT_FROM_CAR_SHOOTING)
ELSE
GO_TO_PED_STATE(ped, PED_STATE_COMBAT_FROM_CAR_NO_SHOOTING)
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
BREAK
CASE PED_STATE_COMBAT_FROM_CAR_NO_SHOOTING
IF ( ped.bHasTask = FALSE )
IF IS_PED_SITTING_IN_VEHICLE_SEAT(ped.PedIndex, vehicle.VehicleIndex, VS_DRIVER)
IF NOT IS_VEHICLE_SEAT_FREE(vehicle.VehicleIndex, VS_FRONT_RIGHT)
PED_INDEX PedInFrontRightSeat
PedInFrontRightSeat = GET_PED_IN_VEHICLE_SEAT(vehicle.VehicleIndex, VS_FRONT_RIGHT)
IF DOES_ENTITY_EXIST(PedInFrontRightSeat)
AND NOT IS_ENTITY_DEAD(PedInFrontRightSeat)
SET_PED_CONFIG_FLAG(ped.PedIndex, PCF_FallsOutOfVehicleWhenKilled, TRUE)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Setting goon ped ", ped.sDebugName, " config flag PCF_FallsOutOfVehicleWhenKilled to TRUE.")
#ENDIF
ELSE
SET_PED_CONFIG_FLAG(ped.PedIndex, PCF_FallsOutOfVehicleWhenKilled, FALSE)
ENDIF
ELSE
SET_PED_CONFIG_FLAG(ped.PedIndex, PCF_FallsOutOfVehicleWhenKilled, FALSE)
ENDIF
ENDIF
SET_PED_COMBAT_ATTRIBUTES(ped.PedIndex, CA_LEAVE_VEHICLES, FALSE)
SET_PED_COMBAT_ATTRIBUTES(ped.PedIndex, CA_USE_VEHICLE, TRUE)
SET_PED_COMBAT_ATTRIBUTES(ped.PedIndex, CA_DO_DRIVEBYS, FALSE)
TASK_COMBAT_HATED_TARGETS_AROUND_PED(ped.PedIndex, 200.0)
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(ped.PedIndex, FALSE)
ped.iAgressiveTimer = GET_GAME_TIMER()
ped.bHasTask = TRUE
ENDIF
SET_PED_RESET_FLAG(ped.PedIndex, PRF_BlockWeaponFire, TRUE) //block weapon fire in no shooting state each frame
IF ( bAggressive = TRUE )
GO_TO_PED_STATE(ped, PED_STATE_COMBAT_FROM_CAR_SHOOTING)
ENDIF
IF IS_VEHICLE_DRIVEABLE(vehicle.VehicleIndex)
IF IS_PED_SITTING_IN_VEHICLE(ped.PedIndex, vehicle.VehicleIndex)
IF ( ped.fDistanceToTarget < 17.5 )
IF NOT IS_PED_DRIVING_VEHICLE(TargetPedIndex, TargetVehicleIndex)
GO_TO_PED_STATE(ped, PED_STATE_COMBAT_ON_FOOT)
ENDIF
ENDIF
IF IS_VEHICLE_SEAT_FREE(vehicle.VehicleIndex, VS_DRIVER)
GO_TO_PED_STATE(ped, PED_STATE_SHUFFLING_VEHICLE_SEATS)
ENDIF
ENDIF
ENDIF
IF NOT IS_VEHICLE_DRIVEABLE(vehicle.VehicleIndex)
GO_TO_PED_STATE(ped, PED_STATE_COMBAT_ON_FOOT)
ELSE
IF IS_VEHICLE_STOPPED(vehicle.VehicleIndex)
IF IS_VEHICLE_STUCK_ON_ROOF(vehicle.VehicleIndex)
OR IS_ENTITY_UPSIDEDOWN(vehicle.VehicleIndex)
OR NOT IS_VEHICLE_ON_ALL_WHEELS(vehicle.VehicleIndex)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Enemy vehicle ", vehicle.sDebugName, " is stopped upside down, stuck on roof or not all wheels.")
#ENDIF
IF IS_PED_IN_VEHICLE(ped.PedIndex, vehicle.VehicleIndex)
TASK_LEAVE_ANY_VEHICLE(ped.PedIndex, 0, ECF_DONT_CLOSE_DOOR)
ENDIF
GO_TO_PED_STATE(ped, PED_STATE_COMBAT_ON_FOOT)
ENDIF
ENDIF
ENDIF
BREAK
CASE PED_STATE_COMBAT_FROM_CAR_SHOOTING
IF ( ped.bHasTask = FALSE )
IF IS_PED_SITTING_IN_VEHICLE_SEAT(ped.PedIndex, vehicle.VehicleIndex, VS_DRIVER)
IF NOT IS_VEHICLE_SEAT_FREE(vehicle.VehicleIndex, VS_FRONT_RIGHT)
PED_INDEX PedInFrontRightSeat
PedInFrontRightSeat = GET_PED_IN_VEHICLE_SEAT(vehicle.VehicleIndex, VS_FRONT_RIGHT)
IF DOES_ENTITY_EXIST(PedInFrontRightSeat)
AND NOT IS_ENTITY_DEAD(PedInFrontRightSeat)
SET_PED_CONFIG_FLAG(ped.PedIndex, PCF_FallsOutOfVehicleWhenKilled, TRUE)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Setting goon ped ", ped.sDebugName, " config flag PCF_FallsOutOfVehicleWhenKilled to TRUE.")
#ENDIF
ELSE
SET_PED_CONFIG_FLAG(ped.PedIndex, PCF_FallsOutOfVehicleWhenKilled, FALSE)
ENDIF
ELSE
SET_PED_CONFIG_FLAG(ped.PedIndex, PCF_FallsOutOfVehicleWhenKilled, FALSE)
ENDIF
ENDIF
SET_PED_COMBAT_ATTRIBUTES(ped.PedIndex, CA_LEAVE_VEHICLES, FALSE)
SET_PED_COMBAT_ATTRIBUTES(ped.PedIndex, CA_USE_VEHICLE, TRUE)
SET_PED_COMBAT_ATTRIBUTES(ped.PedIndex, CA_DO_DRIVEBYS, TRUE)
SET_PED_ACCURACY(ped.PedIndex, 3)
SET_PED_SHOOT_RATE(ped.PedIndex, 80)
TASK_COMBAT_HATED_TARGETS_AROUND_PED(ped.PedIndex, 200.0)
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(ped.PedIndex, FALSE)
ped.bHasTask = TRUE
ENDIF
IF IS_VEHICLE_DRIVEABLE(vehicle.VehicleIndex)
IF IS_PED_SITTING_IN_VEHICLE(ped.PedIndex, vehicle.VehicleIndex)
IF IS_VEHICLE_SEAT_FREE(vehicle.VehicleIndex, VS_DRIVER)
GO_TO_PED_STATE(ped, PED_STATE_SHUFFLING_VEHICLE_SEATS)
ENDIF
IF ( ped.fDistanceToTarget < 17.5 )
IF NOT IS_PED_DRIVING_VEHICLE(TargetPedIndex, TargetVehicleIndex)
GO_TO_PED_STATE(ped, PED_STATE_COMBAT_ON_FOOT)
ENDIF
ENDIF
ENDIF
ENDIF
IF NOT IS_VEHICLE_DRIVEABLE(vehicle.VehicleIndex)
GO_TO_PED_STATE(ped, PED_STATE_COMBAT_ON_FOOT)
ELSE
IF IS_VEHICLE_STOPPED(vehicle.VehicleIndex)
IF IS_VEHICLE_STUCK_ON_ROOF(vehicle.VehicleIndex)
OR IS_ENTITY_UPSIDEDOWN(vehicle.VehicleIndex)
OR NOT IS_VEHICLE_ON_ALL_WHEELS(vehicle.VehicleIndex)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Enemy vehicle ", vehicle.sDebugName, " is stopped upside down, stuck on roof or not all wheels.")
#ENDIF
IF IS_PED_IN_VEHICLE(ped.PedIndex, vehicle.VehicleIndex)
TASK_LEAVE_ANY_VEHICLE(ped.PedIndex, 0, ECF_DONT_CLOSE_DOOR)
ENDIF
GO_TO_PED_STATE(ped, PED_STATE_COMBAT_ON_FOOT)
ENDIF
ENDIF
ENDIF
BREAK
CASE PED_STATE_SHUFFLING_VEHICLE_SEATS
IF ( ped.bHasTask = FALSE )
IF IS_VEHICLE_DRIVEABLE(vehicle.VehicleIndex)
TASK_SHUFFLE_TO_NEXT_VEHICLE_SEAT(ped.PedIndex, vehicle.VehicleIndex)
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(ped.PedIndex, TRUE)
ENDIF
ped.bHasTask = TRUE
ENDIF
IF NOT IS_VEHICLE_DRIVEABLE(vehicle.VehicleIndex)
GO_TO_PED_STATE(ped, PED_STATE_COMBAT_ON_FOOT)
ELSE
IF IS_PED_SITTING_IN_VEHICLE(ped.PedIndex, vehicle.VehicleIndex)
IF IS_PED_SITTING_IN_VEHICLE_SEAT(ped.PedIndex, vehicle.VehicleIndex, VS_DRIVER)
IF NOT IS_VEHICLE_SEAT_FREE(vehicle.VehicleIndex, VS_FRONT_RIGHT)
PED_INDEX PedInFrontRightSeat
PedInFrontRightSeat = GET_PED_IN_VEHICLE_SEAT(vehicle.VehicleIndex, VS_FRONT_RIGHT)
IF DOES_ENTITY_EXIST(PedInFrontRightSeat)
AND NOT IS_ENTITY_DEAD(PedInFrontRightSeat)
SET_PED_CONFIG_FLAG(ped.PedIndex, PCF_FallsOutOfVehicleWhenKilled, TRUE)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Setting goon ped ", ped.sDebugName, " config flag PCF_FallsOutOfVehicleWhenKilled to TRUE.")
#ENDIF
ELSE
SET_PED_CONFIG_FLAG(ped.PedIndex, PCF_FallsOutOfVehicleWhenKilled, FALSE)
ENDIF
ELSE
SET_PED_CONFIG_FLAG(ped.PedIndex, PCF_FallsOutOfVehicleWhenKilled, FALSE)
ENDIF
IF ( bAggressive = TRUE )
GO_TO_PED_STATE(ped, PED_STATE_COMBAT_FROM_CAR_SHOOTING)
ELSE
GO_TO_PED_STATE(ped, PED_STATE_COMBAT_FROM_CAR_NO_SHOOTING)
ENDIF
ELSE
//IF IS_VEHICLE_SEAT_FREE(vehicle.VehicleIndex, VS_DRIVER)
// IF GET_SCRIPT_TASK_STATUS(ped.PedIndex, SCRIPT_TASK_SHUFFLE_TO_NEXT_VEHICLE_SEAT) != PERFORMING_TASK
// GO_TO_PED_STATE(ped, PED_STATE_SHUFFLING_VEHICLE_SEATS)
// ENDIF
//ENDIF
IF ( ped.fDistanceToTarget < 17.5 )
IF NOT IS_PED_DRIVING_VEHICLE(TargetPedIndex, TargetVehicleIndex)
GO_TO_PED_STATE(ped, PED_STATE_COMBAT_ON_FOOT)
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
IF NOT IS_PED_IN_ANY_VEHICLE(ped.PedIndex)
IF NOT IS_PED_DRIVING_VEHICLE(TargetPedIndex, TargetVehicleIndex)
IF ( ped.fDistanceToTarget < 17.5 )
GO_TO_PED_STATE(ped, PED_STATE_COMBAT_ON_FOOT)
ENDIF
ELSE
GO_TO_PED_STATE(ped, PED_STATE_ENTERING_VEHICLE)
ENDIF
ENDIF
BREAK
CASE PED_STATE_ENTERING_VEHICLE //use warp when off camera
IF ( ped.bHasTask = FALSE )
IF DOES_ENTITY_EXIST(vehicle.VehicleIndex)
IF IS_VEHICLE_DRIVEABLE(vehicle.VehicleIndex)
SET_PED_COMBAT_ATTRIBUTES(ped.PedIndex, CA_LEAVE_VEHICLES, FALSE)
SET_PED_COMBAT_ATTRIBUTES(ped.PedIndex, CA_USE_VEHICLE, TRUE)
IF IS_VEHICLE_SEAT_FREE(vehicle.VehicleIndex, VS_DRIVER)
TASK_ENTER_VEHICLE(ped.PedIndex, vehicle.VehicleIndex, DEFAULT_TIME_BEFORE_WARP, VS_DRIVER, PEDMOVE_RUN, ECF_JACK_ANYONE | ECF_RESUME_IF_INTERRUPTED)
ELIF IS_VEHICLE_SEAT_FREE(vehicle.VehicleIndex, VS_FRONT_RIGHT)
TASK_ENTER_VEHICLE(ped.PedIndex, vehicle.VehicleIndex, DEFAULT_TIME_BEFORE_WARP, VS_FRONT_RIGHT, PEDMOVE_RUN, ECF_JACK_ANYONE | ECF_RESUME_IF_INTERRUPTED)
ENDIF
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(ped.PedIndex, TRUE)
ped.iTimer = GET_GAME_TIMER()
ENDIF
ENDIF
ped.bHasTask = TRUE
ENDIF
IF DOES_ENTITY_EXIST(vehicle.VehicleIndex)
AND IS_VEHICLE_DRIVEABLE(vehicle.VehicleIndex)
AND GET_ENTITY_HEALTH(vehicle.VehicleIndex) > 0
AND GET_VEHICLE_ENGINE_HEALTH(vehicle.VehicleIndex) > 0
IF IS_PED_IN_VEHICLE(ped.PedIndex, vehicle.VehicleIndex)
IF ( bAggressive = TRUE )
GO_TO_PED_STATE(ped, PED_STATE_COMBAT_FROM_CAR_SHOOTING)
ELSE
GO_TO_PED_STATE(ped, PED_STATE_COMBAT_FROM_CAR_NO_SHOOTING)
ENDIF
ELSE
IF ( ped.bHasTask = TRUE )
IF HAS_TIME_PASSED(5000, ped.iTimer)
IF ( ped.fDistanceToTarget > 25.0 )
AND ( GET_DISTANCE_BETWEEN_ENTITIES(ped.PedIndex, vehicle.VehicleIndex) < 10.0 )
IF NOT IS_ENTITY_ON_SCREEN(ped.PedIndex)
AND NOT IS_ENTITY_ON_SCREEN(vehicle.VehicleIndex)
IF IS_VEHICLE_SEAT_FREE(vehicle.VehicleIndex, VS_DRIVER)
SET_PED_INTO_VEHICLE(ped.PedIndex, vehicle.VehicleIndex, VS_DRIVER)
ELIF IS_VEHICLE_SEAT_FREE(vehicle.VehicleIndex, VS_FRONT_RIGHT)
SET_PED_INTO_VEHICLE(ped.PedIndex, vehicle.VehicleIndex, VS_FRONT_RIGHT)
ENDIF
ENDIF
ELSE
GO_TO_PED_STATE(ped, PED_STATE_COMBAT_ON_FOOT)
ENDIF
ENDIF
ENDIF
//if seat is no longer free while ped is running to the seat, pick a seat again
//also if while entering vehicle player is close and not driving then go to combat
IF GET_SCRIPT_TASK_STATUS(ped.PedIndex, SCRIPT_TASK_ENTER_VEHICLE) = PERFORMING_TASK
IF NOT IS_PED_GETTING_INTO_A_VEHICLE(ped.PedIndex)
IF NOT IS_VEHICLE_SEAT_FREE(vehicle.VehicleIndex, VS_DRIVER)
OR NOT IS_VEHICLE_SEAT_FREE(vehicle.VehicleIndex, VS_FRONT_RIGHT)
GO_TO_PED_STATE(ped, PED_STATE_ENTERING_VEHICLE)
ENDIF
IF ( ped.fDistanceToTarget < 17.5 )
IF NOT IS_PED_DRIVING_VEHICLE(TargetPedIndex, TargetVehicleIndex)
GO_TO_PED_STATE(ped, PED_STATE_COMBAT_ON_FOOT)
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ELSE
GO_TO_PED_STATE(ped, PED_STATE_COMBAT_ON_FOOT)
ENDIF
BREAK
ENDSWITCH
ENDIF
ENDPROC
FUNC BOOL CAN_GET_CLOSEST_NTH_VEHICLE_NODE_TO_ENTITY_BETWEEN_ANGLES(ENTITY_INDEX EntityIndex, VECTOR &vCurrentClosestNodePosition,
FLOAT &fOutHeading, INT iNodeNumber, FLOAT fMinAngle,
FLOAT fMaxAngle, NODE_FLAGS eNodeFlags = NF_NONE)
///
/// Angles
/// use 0 - 90 for vehicle nodes in front of the entity
/// use 90 - 180 for vehicle nodes behind the player
IF DOES_ENTITY_EXIST(EntityIndex)
IF NOT IS_ENTITY_DEAD(EntityIndex)
VECTOR vEntityPosition
VECTOR vEntityForwardVector
VECTOR vVectorFromNodeToEntity
VECTOR vClosestNodePosition
FLOAT fClosestNodeHeading
FLOAT fAngle
INT iTotalLanes
vEntityPosition = GET_ENTITY_COORDS(EntityIndex)
vEntityForwardVector = GET_ENTITY_FORWARD_VECTOR(EntityIndex)
IF GET_NTH_CLOSEST_VEHICLE_NODE_WITH_HEADING(vEntityPosition, iNodeNumber, vClosestNodePosition, fClosestNodeHeading, iTotalLanes, eNodeFlags)
vVectorFromNodeToEntity = vClosestNodePosition - vEntityPosition
fAngle = GET_ANGLE_BETWEEN_2D_VECTORS(vVectorFromNodeToEntity.X, vVectorFromNodeToEntity.Y, vEntityForwardVector.X, vEntityForwardVector.Y)
IF ( fAngle > fMinAngle AND fAngle < fMaxAngle )
IF NOT ARE_VECTORS_EQUAL(vCurrentClosestNodePosition, vClosestNodePosition)
vCurrentClosestNodePosition = vClosestNodePosition
fOutHeading = fClosestNodeHeading
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), "************* CAN_GET_CLOSEST_NTH_VEHICLE_NODE_TO_VEHICLE_BETWEEN_ANGLES **************")
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Closest vehicle node found at ", vClosestNodePosition, " and heading ", fClosestNodeHeading , ".")
PRINTLN(GET_THIS_SCRIPT_NAME(), "***************************************************************************************")
DRAW_DEBUG_SPHERE(vClosestNodePosition, 1.0)
#ENDIF
RETURN TRUE
ENDIF
ENDIF
#IF IS_DEBUG_BUILD
IF ( bDrawDebugLinesAndSpheres = TRUE )
DRAW_DEBUG_SPHERE(vClosestNodePosition, 1.0, 255, 0, 0)
ENDIF
#ENDIF
ENDIF
#IF IS_DEBUG_BUILD
IF ( bDrawDebugLinesAndSpheres = TRUE )
DRAW_DEBUG_TEXT_ABOVE_ENTITY(EntityIndex, GET_STRING_FROM_FLOAT(fAngle), 1.5)
ENDIF
#ENDIF
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
PROC STORE_ENTITY_POSITION_AND_HEADING(ENTITY_INDEX EntityIndex, VECTOR &vPosition, FLOAT &fHeading)
IF DOES_ENTITY_EXIST(EntityIndex)
IF NOT IS_ENTITY_DEAD(EntityIndex)
vPosition = GET_ENTITY_COORDS(EntityIndex)
fHeading = GET_ENTITY_HEADING(EntityIndex)
ENDIF
ENDIF
ENDPROC
PROC RUN_VEHICLE_IMPACT_SOUND_CHECK(VEHICLE_INDEX PlayerVehicleIndex, VEHICLE_INDEX EnemyVehicleIndex)
IF DOES_ENTITY_EXIST(PlayerVehicleIndex)
IF NOT IS_ENTITY_DEAD(PlayerVehicleIndex)
IF IS_THIS_MODEL_A_CAR(GET_ENTITY_MODEL(PlayerVehicleIndex))
IF DOES_ENTITY_EXIST(EnemyVehicleIndex)
IF NOT IS_ENTITY_DEAD(EnemyVehicleIndex)
IF GET_GAME_TIMER() - iVehicleImpactSoundTimer > 0
IF IS_ENTITY_TOUCHING_ENTITY(EnemyVehicleIndex, PlayerVehicleIndex)
OR HAS_ENTITY_BEEN_DAMAGED_BY_ENTITY(PlayerVehicleIndex, EnemyVehicleIndex)
IF IS_ENTITY_IN_ANGLED_AREA(EnemyVehicleIndex, GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(PlayerVehicleIndex, <<0.0, -1.0, -1.5>>),
GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(PlayerVehicleIndex, <<0.0, -6.0, 3.0>>), 4.0)
PLAY_SOUND_FROM_ENTITY(-1, "FAMILY3_REAR_END_MASTER", PlayerVehicleIndex)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Playing sound FAMILY3_REAR_END_MASTER.")
#ENDIF
ENDIF
CLEAR_ENTITY_LAST_DAMAGE_ENTITY(PlayerVehicleIndex)
iVehicleImpactSoundTimer = GET_GAME_TIMER() + GET_RANDOM_INT_IN_RANGE(3000, 5000)
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDPROC
PROC RUN_VEHICLE_DAMAGE_CHECK(VEHICLE_INDEX VehicleIndex, INT iSmokeHealth)
IF DOES_ENTITY_EXIST(VehicleIndex)
IF NOT IS_ENTITY_DEAD(VehicleIndex)
#IF IS_DEBUG_BUILD
IF ( bDrawDebugLinesAndSpheres = TRUE )
DRAW_DEBUG_TEXT_ABOVE_ENTITY(VehicleIndex, GET_STRING_FROM_INT(GET_ENTITY_HEALTH(VehicleIndex)), 2.25)
DRAW_DEBUG_TEXT_ABOVE_ENTITY(VehicleIndex, GET_STRING_FROM_FLOAT(GET_VEHICLE_ENGINE_HEALTH(VehicleIndex)), 2.0)
DRAW_DEBUG_TEXT_ABOVE_ENTITY(VehicleIndex, GET_STRING_FROM_FLOAT(GET_VEHICLE_PETROL_TANK_HEALTH(VehicleIndex)), 1.75)
ENDIF
#ENDIF
IF ( GET_ENTITY_HEALTH(VehicleIndex) < iSmokeHealth )
SET_ENTITY_HEALTH(VehicleIndex, 0)
SET_VEHICLE_ENGINE_HEALTH(VehicleIndex, 0)
ENDIF
ENDIF
ENDIF
ENDPROC
PROC ADD_POSITION(VECTOR &array[], FLOAT &farray[])
INT i
FOR i = ( COUNT_OF(array) - 1 ) TO 1 STEP -1
array[i] = array[i - 1]
farray[i] = farray[i - 1]
ENDFOR
STORE_ENTITY_POSITION_AND_HEADING(PLAYER_PED_ID(), array[0], farray[0])
// #IF IS_DEBUG_BUILD
// PRINTLN(GET_THIS_SCRIPT_NAME(), ": ************************************************************")
// FOR i = 0 TO ( COUNT_OF(array) - 1 )
// PRINTLN(GET_THIS_SCRIPT_NAME(), ": array[", i, "] ", array[i], " farray[", i, "] ", farray[i], ".")
// ENDFOR
// PRINTLN(GET_THIS_SCRIPT_NAME(), ": ************************************************************")
// #ENDIF
ENDPROC
PROC UPDATE_PLAYER_POSITIONS(VECTOR &array[], FLOAT &farray[])
IF IS_VECTOR_ZERO(array[0])
STORE_ENTITY_POSITION_AND_HEADING(PLAYER_PED_ID(), array[0], farray[0])
ELSE
IF GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), array[0]) > 30.0
ADD_POSITION(array, farray)
ENDIF
INT i
FOR i = 0 TO ( COUNT_OF(array) - 1 )
#IF IS_DEBUG_BUILD
IF ( bDrawDebugLinesAndSpheres = TRUE )
IF NOT IS_VECTOR_ZERO(array[i])
DRAW_DEBUG_SPHERE(array[i], 0.5, 0, 255, 0, 255)
DRAW_DEBUG_TEXT_ABOVE_COORDS(array[i], GET_STRING_FROM_INT(i), 1.0, 0, 255, 0, 255)
ENDIF
ENDIF
#ENDIF
ENDFOR
ENDIF
ENDPROC
PROC RUN_VEHICLE_WARP_CHECK_BASED_ON_TARGET_VEHICLE(VEHICLE_INDEX VehicleIndex, VEHICLE_INDEX TargetVehicleIndex, VECTOR &vWarpPosition,
FLOAT &fWarpHeading, VECTOR &vLastTargetPosition, FLOAT &fLastTargetHeading,
INT &iWarpTimer, VECTOR vWarpOffset, INT iWarpTimeDelay, FLOAT fWarpDistance,
FLOAT &fLastKnownDistance #IF IS_DEBUG_BUILD, STRING sDebugName = NULL #ENDIF)
UPDATE_PLAYER_POSITIONS(vPlayerPositions, fPlayerHeadings)
IF DOES_ENTITY_EXIST(VehicleIndex)
AND IS_VEHICLE_DRIVEABLE(VehicleIndex)
IF DOES_ENTITY_EXIST(TargetVehicleIndex)
AND ( VehicleIndex != TargetVehicleIndex)
AND NOT IS_THIS_MODEL_A_BOAT(GET_ENTITY_MODEL(TargetVehicleIndex))
AND NOT IS_THIS_MODEL_A_PLANE(GET_ENTITY_MODEL(TargetVehicleIndex))
AND NOT IS_THIS_MODEL_A_HELI(GET_ENTITY_MODEL(TargetVehicleIndex))
AND NOT IS_THIS_MODEL_A_TRAIN(GET_ENTITY_MODEL(TargetVehicleIndex))
AND IS_VEHICLE_ON_ALL_WHEELS(TargetVehicleIndex)
AND NOT IS_VEHICLE_STOPPED(TargetVehicleIndex)
AND DOES_VEHICLE_HAVE_A_DRIVER(VehicleIndex)
AND GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(TargetVehicleIndex), GET_ENTITY_COORDS(VehicleIndex)) > fLastKnownDistance
IF GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(TargetVehicleIndex), vLastTargetPosition) > 20.0
vWarpPosition = vLastTargetPosition //store last target vehicle positon as the new warp position
fWarpHeading = fLastTargetHeading //store last target vehicle heading as the new warp heading
vWarpPosition = GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(vWarpPosition, fWarpHeading, vWarpOffset)
STORE_ENTITY_POSITION_AND_HEADING(TargetVehicleIndex, vLastTargetPosition, fLastTargetHeading)
ENDIF
#IF IS_DEBUG_BUILD
IF ( bDrawDebugLinesAndSpheres = TRUE )
DRAW_DEBUG_TEXT_ABOVE_ENTITY(VehicleIndex, GET_STRING_FROM_FLOAT(GET_DISTANCE_BETWEEN_ENTITIES(VehicleIndex, TargetVehicleIndex)), 1.5)
DRAW_DEBUG_SPHERE(vWarpPosition, 0.25)
DRAW_DEBUG_TEXT_ABOVE_COORDS(vWarpPosition, sDebugName, 1.75)
ENDIF
#ENDIF
IF NOT IS_ENTITY_OCCLUDED(VehicleIndex)
iWarpTimer = GET_GAME_TIMER()
ELIF GET_GAME_TIMER() - iWarpTimer > iWarpTimeDelay
IF GET_DISTANCE_BETWEEN_ENTITIES(VehicleIndex, TargetVehicleIndex) > fWarpDistance
AND GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(TargetVehicleIndex), vWarpPosition) > 25.0
IF NOT IS_VECTOR_ZERO(vWarpPosition)
IF NOT IS_SPHERE_VISIBLE(vWarpPosition, 3.0)
CLEAR_AREA_OF_PEDS(vWarpPosition, 1.5)
CLEAR_AREA_OF_VEHICLES(vWarpPosition, 3.0)
SET_ENTITY_COORDS(VehicleIndex, vWarpPosition)
SET_ENTITY_HEADING(VehicleIndex, fWarpHeading)
SET_VEHICLE_ON_GROUND_PROPERLY(VehicleIndex)
SET_VEHICLE_FORWARD_SPEED(VehicleIndex, 10.0)
SET_VEHICLE_ENGINE_ON(VehicleIndex, TRUE, TRUE)
iWarpTimer = GET_GAME_TIMER()
fLastKnownDistance = GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(TargetVehicleIndex), GET_ENTITY_COORDS(VehicleIndex))
iReplayCameraWarpTimer = GET_GAME_TIMER() + 1000
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Warping vehicle ", sDebugName, " to new position ", vWarpPosition, " and heading ", fWarpHeading, ".")
#ENDIF
ELSE
INT i
VECTOR vNewWarpPosition
REPEAT COUNT_OF(vPlayerPositions) i
vNewWarpPosition = GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(vPlayerPositions[i], fPlayerHeadings[i], vWarpOffset)
IF NOT IS_VECTOR_ZERO(vNewWarpPosition)
IF NOT IS_SPHERE_VISIBLE(vNewWarpPosition, 2.0)
CLEAR_AREA_OF_PEDS(vNewWarpPosition, 1.5)
CLEAR_AREA_OF_VEHICLES(vNewWarpPosition, 3.0)
SET_ENTITY_COORDS(VehicleIndex, vNewWarpPosition)
SET_ENTITY_HEADING(VehicleIndex, fPlayerHeadings[i])
SET_VEHICLE_ON_GROUND_PROPERLY(VehicleIndex)
SET_VEHICLE_FORWARD_SPEED(VehicleIndex, 10.0)
SET_VEHICLE_ENGINE_ON(VehicleIndex, TRUE, TRUE)
iWarpTimer = GET_GAME_TIMER()
fLastKnownDistance = GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(TargetVehicleIndex), GET_ENTITY_COORDS(VehicleIndex))
EXIT
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Warping vehicle ", sDebugName, " to new position ", vNewWarpPosition, " at index ", i, ".")
SCRIPT_ASSERT("Warping to new position")
#ENDIF
iReplayCameraWarpTimer = GET_GAME_TIMER() + 1000
ENDIF
ENDIF
ENDREPEAT
ENDIF
ENDIF
ENDIF
ENDIF
ELSE
iWarpTimer = GET_GAME_TIMER()
ENDIF
ENDIF
ENDPROC
PROC MANAGE_GOONS(INT &iProgress)
IF ( bGoonsAllowed = FALSE )
//player has to leave the dirt road under the balcony
IF NOT IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), << -1184.89, 709.60, 132.38 >>, << -1133.41, 679.84, 161.10 >>, 36.0)
AND NOT IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), << -1062.28, 662.22, 125.02 >>, << -1138.02, 681.84, 161.37 >>, 36.0)
AND NOT IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), << -1065.68, 661.26, 121.10 >>, << -976.84, 641.13, 153.91 >>, 36.0)
AND NOT IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), << -894.49, 655.77, 113.47 >>, << -985.13, 640.53, 154.35 >>, 36.0)
AND NOT IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), << -898.85, 657.44, 113.60 >>, << -823.46, 645.49, 144.01 >>, 36.0)
AND NOT IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), << -770.93, 551.06, 101.91 >>, << -827.24, 649.55, 144.36 >>, 36.0)
AND NOT IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), << -770.974, 557.36, 102.67 >>, << -700.16, 501.75, 124.60 >>, 36.0)
//use timer to allow goons with time delay once the dirt road is left behind
IF ( iGoonsChaseDelayTimer = 0 )
IF ( bStartGoonTimerDelay = TRUE )
iGoonsChaseDelayTimer = GET_GAME_TIMER()
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Starting goons delay timer.")
#ENDIF
ENDIF
ELSE
IF HAS_TIME_PASSED(10000, iGoonsChaseDelayTimer)
bGoonsAllowed = TRUE
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Goons are allowed to spawn due to timer.")
#ENDIF
ENDIF
ENDIF
//allow goons if player reaches Michael's house before the goons were allowed to spawn
IF GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), vMichaelsHousePosition) < 100.0//175.0
bGoonsAllowed = TRUE
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Goons are allowed to spawn due to proximity to Michael's house.")
#ENDIF
ENDIF
ENDIF
ENDIF
SWITCH iProgress
CASE 0 //request models
REQUEST_MODEL(BALLER)
REQUEST_MODEL(G_M_Y_POLOGOON_01)
IF HAS_MODEL_LOADED(BALLER)
AND HAS_MODEL_LOADED(G_M_Y_POLOGOON_01)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Models ", GET_MODEL_NAME_FOR_DEBUG(BALLER), " and ", GET_MODEL_NAME_FOR_DEBUG(G_M_Y_POLOGOON_01), " are loaded.")
#ENDIF
vEnemyCarsOffset[0] = << -2.15, -3.0, 0.0 >>
vEnemyCarsOffset[1] = << 2.15, 3.0, 0.0 >>
iProgress++
ENDIF
BREAK
CASE 1
IF ( bGoonsAllowed = TRUE )
VECTOR vPlayerPosition
VECTOR vClosestNodeToPlayer
vPlayerPosition = GET_ENTITY_COORDS(PLAYER_PED_ID())
//fix for spawning when inside the problematic junction in B*1821876
IF IS_ENTITY_AT_COORD(PLAYER_PED_ID(), <<-857.873779,220.178818,73.882767>>,<<20.000000,28.000000,8.000000>>)
IF GET_CLOSEST_VEHICLE_NODE(vPlayerPosition, vClosestNodeToPlayer, NF_NONE)
#IF IS_DEBUG_BUILD
IF ( bDrawDebugLinesAndSpheres = TRUE )
DRAW_DEBUG_SPHERE(vClosestNodeToPlayer, 1.0, 0, 255, 0, 128)
ENDIF
#ENDIF
IF ( GET_DISTANCE_BETWEEN_COORDS(vPlayerPosition, vClosestNodeToPlayer) < 7.0 )
#IF IS_DEBUG_BUILD
IF ( bDrawDebugLinesAndSpheres = TRUE )
DRAW_DEBUG_SPHERE(vClosestNodeToPlayer, 0.5, 255, 255, 255, 255)
ENDIF
#ENDIF
IF CAN_GET_CLOSEST_NTH_VEHICLE_NODE_TO_ENTITY_BETWEEN_ANGLES(PLAYER_PED_ID(), vClosestRoadNode, fClosestRoadNodeHeading, 18,
PICK_FLOAT(IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_LOOK_BEHIND), 10.0, 100.0),
PICK_FLOAT(IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_LOOK_BEHIND), 60.0, 180.0))
IF NOT IS_SPHERE_VISIBLE(vClosestRoadNode, 3.0)
INT i
FLOAT fHeadingDifference
FLOAT fPlayerHeading
FLOAT fSpawnHeading
fPlayerHeading = GET_ENTITY_HEADING(PLAYER_PED_ID())
fHeadingDifference = ABSF(fPlayerHeading - fClosestRoadNodeHeading)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), " fPlayerHeading: ", fPlayerHeading,
" fClosestRoadNodeHeading: ", fClosestRoadNodeHeading,
" fHeadingDifference: ", fHeadingDifference, ".")
#ENDIF
IF ( fHeadingDifference > 180.0 )
fHeadingDifference = ABSF(fHeadingDifference - 360.0)
ENDIF
IF ( fHeadingDifference < 90.0 )
fSpawnHeading = fClosestRoadNodeHeading
ELSE
fSpawnHeading = fClosestRoadNodeHeading + 180
ENDIF
REPEAT COUNT_OF(vsEnemyCars) i
vsEnemyCars[i].ModelName = BALLER
vsEnemyCars[i].vPosition = GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(vClosestRoadNode, fClosestRoadNodeHeading, vEnemyCarsOffset[i])
vsEnemyCars[i].fHeading = fSpawnHeading
vsEnemyCars[i].bLOSFlag = FALSE
CLEAR_AREA_OF_VEHICLES(vsEnemyCars[i].vPosition, 3.0)
ENDREPEAT
#IF IS_DEBUG_BUILD
bStageResetFlag = TRUE
#ENDIF
iProgress++
ENDIF
ENDIF
ENDIF
ENDIF
ELSE //normal spawning when outside the problematic junction in B*1821876
IF GET_CLOSEST_VEHICLE_NODE(vPlayerPosition, vClosestNodeToPlayer, NF_NONE)
#IF IS_DEBUG_BUILD
IF ( bDrawDebugLinesAndSpheres = TRUE )
DRAW_DEBUG_SPHERE(vClosestNodeToPlayer, 1.0, 0, 255, 0, 128)
ENDIF
#ENDIF
IF ( GET_DISTANCE_BETWEEN_COORDS(vPlayerPosition, vClosestNodeToPlayer) < 5.0 )
#IF IS_DEBUG_BUILD
IF ( bDrawDebugLinesAndSpheres = TRUE )
DRAW_DEBUG_SPHERE(vClosestNodeToPlayer, 0.5, 255, 255, 255, 255)
ENDIF
#ENDIF
IF CAN_GET_CLOSEST_NTH_VEHICLE_NODE_TO_ENTITY_BETWEEN_ANGLES(PLAYER_PED_ID(), vClosestRoadNode, fClosestRoadNodeHeading, 18,
PICK_FLOAT(IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_LOOK_BEHIND), 15.0, 125.0),
PICK_FLOAT(IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_LOOK_BEHIND), 60.0, 180.0))
IF NOT IS_SPHERE_VISIBLE(vClosestRoadNode, 3.0)
INT i
FLOAT fHeadingDifference
FLOAT fPlayerHeading
FLOAT fSpawnHeading
fPlayerHeading = GET_ENTITY_HEADING(PLAYER_PED_ID())
fHeadingDifference = ABSF(fPlayerHeading - fClosestRoadNodeHeading)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), " fPlayerHeading: ", fPlayerHeading,
" fClosestRoadNodeHeading: ", fClosestRoadNodeHeading,
" fHeadingDifference: ", fHeadingDifference, ".")
#ENDIF
IF ( fHeadingDifference > 180.0 )
fHeadingDifference = ABSF(fHeadingDifference - 360.0)
ENDIF
IF ( fHeadingDifference < 90.0 )
fSpawnHeading = fClosestRoadNodeHeading
ELSE
fSpawnHeading = fClosestRoadNodeHeading + 180
ENDIF
REPEAT COUNT_OF(vsEnemyCars) i
vsEnemyCars[i].ModelName = BALLER
vsEnemyCars[i].vPosition = GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(vClosestRoadNode, fClosestRoadNodeHeading, vEnemyCarsOffset[i])
vsEnemyCars[i].fHeading = fSpawnHeading
vsEnemyCars[i].bLOSFlag = FALSE
CLEAR_AREA_OF_VEHICLES(vsEnemyCars[i].vPosition, 3.0)
ENDREPEAT
#IF IS_DEBUG_BUILD
bStageResetFlag = TRUE
#ENDIF
iProgress++
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
BREAK
CASE 2 //create enemies in vehicles
REPLAY_DISABLE_CAMERA_MOVEMENT_THIS_FRAME() //Fix for bug 2229077
IF HAS_MISSION_VEHICLE_BEEN_CREATED(vsEnemyCars[0], FALSE, FALSE, NO_CHARACTER, FALSE, -1, 0, 0, 3, 0 #IF IS_DEBUG_BUILD, "EnemyCar 0" #ENDIF)
AND HAS_MISSION_VEHICLE_BEEN_CREATED(vsEnemyCars[1], FALSE, FALSE, NO_CHARACTER, FALSE, -1, 0, 0, 3, 0 #IF IS_DEBUG_BUILD, "EnemyCar 1" #ENDIF)
psEnemyGoonsCar0[0].PedIndex = CREATE_ENEMY_PED_IN_VEHICLE(vsEnemyCars[0].VehicleIndex, G_M_Y_POLOGOON_01, VS_DRIVER, 200, WEAPONTYPE_PISTOL #IF IS_DEBUG_BUILD, "EnemyCar0 0" #ENDIF)
psEnemyGoonsCar0[1].PedIndex = CREATE_ENEMY_PED_IN_VEHICLE(vsEnemyCars[0].VehicleIndex, G_M_Y_POLOGOON_01, VS_FRONT_RIGHT, 200, WEAPONTYPE_PISTOL #IF IS_DEBUG_BUILD, "EnemyCar0 1" #ENDIF)
psEnemyGoonsCar1[0].PedIndex = CREATE_ENEMY_PED_IN_VEHICLE(vsEnemyCars[1].VehicleIndex, G_M_Y_POLOGOON_01, VS_DRIVER, 200, WEAPONTYPE_PISTOL #IF IS_DEBUG_BUILD, "EnemyCar1 0" #ENDIF)
psEnemyGoonsCar1[1].PedIndex = CREATE_ENEMY_PED_IN_VEHICLE(vsEnemyCars[1].VehicleIndex, G_M_Y_POLOGOON_01, VS_FRONT_RIGHT, 200, WEAPONTYPE_PISTOL #IF IS_DEBUG_BUILD, "EnemyCar1 1" #ENDIF)
IF IS_VEHICLE_DRIVEABLE(vsEnemyCars[0].VehicleIndex)
SET_ENTITY_HEALTH(vsEnemyCars[0].VehicleIndex, 1000)
SET_VEHICLE_ENGINE_HEALTH(vsEnemyCars[0].VehicleIndex, 1000)
SET_VEHICLE_PETROL_TANK_HEALTH(vsEnemyCars[0].VehicleIndex, 1000)
ADD_VEHICLE_UPSIDEDOWN_CHECK(vsEnemyCars[0].VehicleIndex)
ADD_VEHICLE_STUCK_CHECK_WITH_WARP(vsEnemyCars[0].VehicleIndex, 10, 1000, FALSE, FALSE, FALSE, -1)
SET_VEHICLE_ON_GROUND_PROPERLY(vsEnemyCars[0].VehicleIndex)
SET_VEHICLE_FORWARD_SPEED(vsEnemyCars[0].VehicleIndex, 5.0)
ADD_ENTITY_TO_AUDIO_MIX_GROUP(vsEnemyCars[0].VehicleIndex, "FAMILY_3_ENEMY_CARS_GROUP")
ENDIF
IF IS_VEHICLE_DRIVEABLE(vsEnemyCars[1].VehicleIndex)
SET_ENTITY_HEALTH(vsEnemyCars[1].VehicleIndex, 1000)
SET_VEHICLE_ENGINE_HEALTH(vsEnemyCars[1].VehicleIndex, 1000)
SET_VEHICLE_PETROL_TANK_HEALTH(vsEnemyCars[1].VehicleIndex, 1000)
ADD_VEHICLE_UPSIDEDOWN_CHECK(vsEnemyCars[1].VehicleIndex)
ADD_VEHICLE_STUCK_CHECK_WITH_WARP(vsEnemyCars[1].VehicleIndex, 10, 1000, FALSE, FALSE, FALSE, -1)
SET_VEHICLE_ON_GROUND_PROPERLY(vsEnemyCars[1].VehicleIndex)
SET_VEHICLE_FORWARD_SPEED(vsEnemyCars[1].VehicleIndex, 5.0)
ADD_ENTITY_TO_AUDIO_MIX_GROUP(vsEnemyCars[1].VehicleIndex, "FAMILY_3_ENEMY_CARS_GROUP")
ENDIF
#IF IS_DEBUG_BUILD
vsEnemyCars[0].sDebugName = "EnemyCar 0"
vsEnemyCars[1].sDebugName = "EnemyCar 1"
psEnemyGoonsCar0[0].sDebugName = "EnemyCar0 0"
psEnemyGoonsCar0[1].sDebugName = "EnemyCar0 1"
psEnemyGoonsCar1[0].sDebugName = "EnemyCar1 0"
psEnemyGoonsCar1[1].sDebugName = "EnemyCar1 1"
#ENDIF
psEnemyGoonsCar0[0].iConversationTimer = 0
psEnemyGoonsCar0[1].iConversationTimer = 0
psEnemyGoonsCar1[0].iConversationTimer = 0
psEnemyGoonsCar1[1].iConversationTimer = 0
GO_TO_PED_STATE(psEnemyGoonsCar0[0], PED_STATE_IDLE)
GO_TO_PED_STATE(psEnemyGoonsCar0[1], PED_STATE_IDLE)
GO_TO_PED_STATE(psEnemyGoonsCar1[0], PED_STATE_IDLE)
GO_TO_PED_STATE(psEnemyGoonsCar1[1], PED_STATE_IDLE)
SET_MODEL_AS_NO_LONGER_NEEDED(BALLER)
SET_MODEL_AS_NO_LONGER_NEEDED(G_M_Y_POLOGOON_01)
INFORM_MISSION_STATS_OF_HEADSHOT_WATCH_ENTITY(psEnemyGoonsCar0[0].PedIndex) //track headshots on goons
INFORM_MISSION_STATS_OF_HEADSHOT_WATCH_ENTITY(psEnemyGoonsCar0[1].PedIndex)
INFORM_MISSION_STATS_OF_HEADSHOT_WATCH_ENTITY(psEnemyGoonsCar1[0].PedIndex)
INFORM_MISSION_STATS_OF_HEADSHOT_WATCH_ENTITY(psEnemyGoonsCar1[1].PedIndex)
INFORM_MISSION_STATS_SYSTEM_OF_TIME_WINDOW_OPEN(FAM3_GOON_LOSS_TIME) //start goon chase stat timer
vsEnemyCars[0].vWarpOffset = << -2.15, -3.0, 0.0 >>
vsEnemyCars[1].vWarpOffset = << 2.15, 3.0, 0.0 >>
vsEnemyCars[0].fDistanceToTarget = GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), GET_ENTITY_COORDS(vsEnemyCars[0].VehicleIndex))
vsEnemyCars[1].fDistanceToTarget = GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), GET_ENTITY_COORDS(vsEnemyCars[1].VehicleIndex))
STORE_ENTITY_POSITION_AND_HEADING(GET_VEHICLE_PED_IS_USING(PLAYER_PED_ID()), vsEnemyCars[0].vTargetPosition, vsEnemyCars[0].fTargetHeading)
STORE_ENTITY_POSITION_AND_HEADING(GET_VEHICLE_PED_IS_USING(PLAYER_PED_ID()), vsEnemyCars[1].vTargetPosition, vsEnemyCars[1].fTargetHeading)
TRIGGER_MUSIC_EVENT("FAM3_MEX_CHASE")
//give some pistol ammo to the player when goons spawn, give 2 clips
ADD_AMMO_TO_PED(PLAYER_PED_ID(), WEAPONTYPE_PISTOL, GET_MAX_AMMO_IN_CLIP(PLAYER_PED_ID(), WEAPONTYPE_PISTOL) * 2)
bGoonsChaseInProgress = TRUE
iGoonsChaseInitialTimer = GET_GAME_TIMER()
bGoonsChaseInitialTimePassed = FALSE
iProgress++
ENDIF
BREAK
CASE 3 //update enemies
INT i
IF ( bGoonsChaseInitialTimePassed = FALSE )
IF HAS_TIME_PASSED(10000, iGoonsChaseInitialTimer)
bGoonsChaseInitialTimePassed = TRUE
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Setting bGoonsChaseInitialTimePassed to TRUE as iGoonsChaseInitialTimer has passed 10000 ms.")
#ENDIF
ENDIF
ENDIF
UPDATE_BLIPS_FOR_GOONS_AND_VEHICLE(psEnemyGoonsCar0, vsEnemyCars[0])
UPDATE_BLIPS_FOR_GOONS_AND_VEHICLE(psEnemyGoonsCar1, vsEnemyCars[1])
CLEANUP_GOONS_AND_VEHICLE(psEnemyGoonsCar0, vsEnemyCars[0], 300.0, PICK_FLOAT(bGoonsChaseInitialTimePassed, 150.0, 200.0))
CLEANUP_GOONS_AND_VEHICLE(psEnemyGoonsCar1, vsEnemyCars[1], 300.0, PICK_FLOAT(bGoonsChaseInitialTimePassed, 150.0, 200.0))
MANAGE_GOON_PED_IN_VEHICLE(psEnemyGoonsCar0[0], vsEnemyCars[0], PLAYER_PED_ID(), GET_VEHICLE_PED_IS_USING(PLAYER_PED_ID()), bGoonsAggressive)
MANAGE_GOON_PED_IN_VEHICLE(psEnemyGoonsCar0[1], vsEnemyCars[0], PLAYER_PED_ID(), GET_VEHICLE_PED_IS_USING(PLAYER_PED_ID()), bGoonsAggressive)
MANAGE_GOON_PED_IN_VEHICLE(psEnemyGoonsCar1[0], vsEnemyCars[1], PLAYER_PED_ID(), GET_VEHICLE_PED_IS_USING(PLAYER_PED_ID()), bGoonsAggressive)
MANAGE_GOON_PED_IN_VEHICLE(psEnemyGoonsCar1[1], vsEnemyCars[1], PLAYER_PED_ID(), GET_VEHICLE_PED_IS_USING(PLAYER_PED_ID()), bGoonsAggressive)
IF ( vsEnemyCars[0].bLOSFlag = FALSE AND vsEnemyCars[1].bLOSFlag = FALSE ) //check enemy cars line of sight to Franklin
IF DOES_ENTITY_EXIST(vsEnemyCars[0].VehicleIndex)
vsEnemyCars[0].bLOSFlag = HAS_ENTITY_CLEAR_LOS_TO_ENTITY(vsEnemyCars[0].VehicleIndex, GET_PED_INDEX(CHAR_FRANKLIN))
vsEnemyCars[0].bLOSFlag = HAS_ENTITY_CLEAR_LOS_TO_ENTITY(vsEnemyCars[0].VehicleIndex, GET_PED_INDEX(CHAR_MICHAEL))
ENDIF
IF DOES_ENTITY_EXIST(vsEnemyCars[1].VehicleIndex)
vsEnemyCars[1].bLOSFlag = HAS_ENTITY_CLEAR_LOS_TO_ENTITY(vsEnemyCars[1].VehicleIndex, GET_PED_INDEX(CHAR_FRANKLIN))
vsEnemyCars[1].bLOSFlag = HAS_ENTITY_CLEAR_LOS_TO_ENTITY(vsEnemyCars[1].VehicleIndex, GET_PED_INDEX(CHAR_MICHAEL))
ENDIF
ENDIF
FOR i = 0 TO 1
RUN_VEHICLE_DAMAGE_CHECK(vsEnemyCars[i].VehicleIndex, 200)
RUN_VEHICLE_IMPACT_SOUND_CHECK(GET_VEHICLE_PED_IS_USING(PLAYER_PED_ID()), vsEnemyCars[i].VehicleIndex)
RUN_VEHICLE_WARP_CHECK_BASED_ON_TARGET_VEHICLE(vsEnemyCars[i].VehicleIndex, GET_VEHICLE_PED_IS_USING(PLAYER_PED_ID()),
vsEnemyCars[i].vPosition, vsEnemyCars[i].fHeading,
vsEnemyCars[i].vTargetPosition, vsEnemyCars[i].fTargetHeading,
vsEnemyCars[i].iWarpTimer, vsEnemyCars[i].vWarpOffset,
3500, 45.0, vsEnemyCars[i].fDistanceToTarget
#IF IS_DEBUG_BUILD, vsEnemyCars[i].sDebugName #ENDIF)
ENDFOR
IF NOT DOES_ENTITY_EXIST(vsEnemyCars[0].VehicleIndex)
AND NOT DOES_ENTITY_EXIST(vsEnemyCars[1].VehicleIndex)
AND NOT DOES_ENTITY_EXIST(psEnemyGoonsCar0[0].PedIndex)
AND NOT DOES_ENTITY_EXIST(psEnemyGoonsCar0[1].PedIndex)
AND NOT DOES_ENTITY_EXIST(psEnemyGoonsCar1[0].PedIndex)
AND NOT DOES_ENTITY_EXIST(psEnemyGoonsCar1[1].PedIndex)
INFORM_MISSION_STATS_SYSTEM_OF_TIME_WINDOW_CLOSED() //end goon chase stat timer
bGoonsChaseFinished = TRUE
bGoonsChaseInProgress = FALSE
bRunLocatesHeaderCheck = TRUE
SET_MAX_WANTED_LEVEL(5)
SET_CREATE_RANDOM_COPS(TRUE) //restore wanted level default settings
SET_WANTED_LEVEL_MULTIPLIER(1.0)
SET_PLAYER_CAN_CHANGE_CLOTHES_ON_MISSION(TRUE) //allow player to change clothes after goons chase
SET_ALL_SHOPS_TEMPORARILY_UNAVAILABLE(FALSE) //allow shops
RELEASE_SUPPRESSED_EMERGENCY_CALLS() //allow emergency calls
REMOVE_ANIM_DICT("missfam3") //no need for anim dict after losing goons
TRIGGER_MUSIC_EVENT("FAM3_MEX_LOST")
iProgress++
ENDIF
BREAK
ENDSWITCH
ENDPROC
PROC MANAGE_CONVERSATIONS_DURING_ESCAPE_GOONS(INT &iProgress)
INT i
TEXT_LABEL_23 CurrentRoot
TEXT_LABEL_23 CurrentLabel
IF ( bRunLocatesHeaderCheck = TRUE )
IF DOES_BLIP_EXIST(sLocatesData.LocationBlip)
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF IS_FACE_TO_FACE_CONVERSATION_PAUSED()
PAUSE_FACE_TO_FACE_CONVERSATION(FALSE)
ENDIF
ENDIF
ELSE
IF IS_PLAYER_WANTED_LEVEL_GREATER(PLAYER_ID(), 0) //when wanted, kill conversation and play wanted conversation
IF ( bConversationPaused = FALSE )
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
lConversationRoot = GET_CURRENTLY_PLAYING_STANDARD_CONVERSATION_ROOT()
lConversationLabel = GET_STANDARD_CONVERSATION_LABEL_FOR_FUTURE_RESUMPTION()
KILL_FACE_TO_FACE_CONVERSATION_DO_NOT_FINISH_LAST_LINE()
ENDIF
IF NOT IS_ANY_TEXT_BEING_DISPLAYED(sLocatesData, IAT_IGNORE_GOD_TEXT_IF_SUBTITLES_OFF)
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_WNTD2", CONV_PRIORITY_MEDIUM)
bConversationPaused = TRUE
ENDIF
ENDIF
ENDIF
ELSE //player not wanted, must be out of the car, pause face to face conversations
IF ( bAllowConvsersationOutsideOfCar = FALSE )
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF NOT IS_FACE_TO_FACE_CONVERSATION_PAUSED()
PAUSE_FACE_TO_FACE_CONVERSATION(TRUE)
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
SWITCH iProgress
CASE 0
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
CurrentLabel = GET_CURRENTLY_PLAYING_STANDARD_CONVERSATION_LABEL()
IF NOT IS_STRING_NULL_OR_EMPTY(CurrentLabel)
IF ARE_STRINGS_EQUAL(CurrentLabel, "FAM3_DOWN_10")
OR ARE_STRINGS_EQUAL(CurrentLabel, "FAM3_DOWNA_17")
KILL_ANY_CONVERSATION()
KILL_FACE_TO_FACE_CONVERSATION()
PAUSE_FACE_TO_FACE_CONVERSATION(FALSE)
ENDIF
ENDIF
ELSE
bRunLocatesHeaderCheck = TRUE
SETTIMERA(0)
iProgress++
ENDIF
BREAK
CASE 1
IF DOES_BLIP_EXIST(sLocatesData.LocationBlip)
IF TIMERA() > 6000
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
AND NOT IS_PED_INJURED(psFranklin.PedIndex)
IF CHAR_CALL_PLAYER_CELLPHONE_FORCE_ANSWER(sFamily3Conversation, CHAR_TENNIS_COACH, "FAM3AUD", "FAM3_TCPC", CONV_PRIORITY_MEDIUM)
REPLAY_RECORD_BACK_FOR_TIME(3.0, 10.0, REPLAY_IMPORTANCE_HIGHEST)
SET_LABEL_AS_TRIGGERED("FAM3_TCPC", TRUE)
bPhoneCallInterruptedByPlayer = FALSE
bAllowConvsersationOutsideOfCar = TRUE
iProgress++
ENDIF
ENDIF
ENDIF
ENDIF
BREAK
CASE 2
IF HAS_LABEL_BEEN_TRIGGERED("FAM3_TCPC")
IF NOT IS_THIS_CONVERSATION_PLAYING("FAM3_TCPC")
iProgress++
ENDIF
IF WAS_LAST_CELLPHONE_CALL_INTERRUPTED()
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Last phone call was interrupted.")
#ENDIF
bPhoneCallInterruptedByPlayer = TRUE
ENDIF
ENDIF
BREAK
CASE 3
IF NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_MAD")
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF ( bPhoneCallInterruptedByPlayer = FALSE )
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_MAD", CONV_PRIORITY_MEDIUM)
REPLAY_RECORD_BACK_FOR_TIME(4.0, 10.0, REPLAY_IMPORTANCE_HIGHEST)
SET_LABEL_AS_TRIGGERED("FAM3_MAD", TRUE)
ENDIF
ELSE
bStartGoonTimerDelay = TRUE
bRunLocatesHeaderCheck = TRUE
iProgress++
ENDIF
ENDIF
ELSE
IF NOT IS_THIS_CONVERSATION_PLAYING("FAM3_MAD")
bStartGoonTimerDelay = TRUE
bRunLocatesHeaderCheck = TRUE
iProgress++
ELSE
IF NOT IS_FACE_TO_FACE_CONVERSATION_PAUSED()
IF DOES_BLIP_EXIST(sLocatesData.BuddyBlipID[0])
PAUSE_FACE_TO_FACE_CONVERSATION(TRUE)
ENDIF
ELSE
IF NOT DOES_BLIP_EXIST(sLocatesData.BuddyBlipID[0])
PAUSE_FACE_TO_FACE_CONVERSATION(FALSE)
ENDIF
ENDIF
IF ( bGoonsChaseInProgress = TRUE ) //if the goons spawn during the FAM3_MAD conversations (can happen if player rushes home quickly)
iProgress++
ENDIF
ENDIF
ENDIF
BREAK
CASE 4
IF ( bGoonsChaseInProgress = FALSE )
IF ( bGoonsChaseFinished = TRUE )
//handle conversation for ending the goons chase and presenting the reason why chase has ended
IF NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_GCEK")
AND NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_GCEL")
FOR i = 0 TO 1
//#IF IS_DEBUG_BUILD
// PRINTLN(GET_THIS_SCRIPT_NAME(), ": psEnemyGoonsCar0[", i, "].bCleanupConversationTriggered is ", psEnemyGoonsCar0[i].bCleanupConversationTriggered)
// PRINTLN(GET_THIS_SCRIPT_NAME(), ": psEnemyGoonsCar0[", i, "].eCleanupReason is ", ENUM_TO_INT(psEnemyGoonsCar0[i].eCleanupReason))
// PRINTLN(GET_THIS_SCRIPT_NAME(), ": psEnemyGoonsCar1[", i, "].bCleanupConversationTriggered is ", psEnemyGoonsCar1[i].bCleanupConversationTriggered)
// PRINTLN(GET_THIS_SCRIPT_NAME(), ": psEnemyGoonsCar1[", i, "].eCleanupReason is ", ENUM_TO_INT(psEnemyGoonsCar1[i].eCleanupReason))
//#ENDIF
//loop through first vehicle group
IF ( psEnemyGoonsCar0[i].bCleanupConversationTriggered = FALSE )
IF ( psEnemyGoonsCar0[i].eCleanupReason <> PED_CLEANUP_NO_CLEANUP )
SWITCH psEnemyGoonsCar0[i].eCleanupReason
CASE PED_CLEANUP_KILLED_BY_MICHAEL
CASE PED_CLEANUP_KILLED_BY_FRANKLIN
CASE PED_CLEANUP_KILLED_BY_PLAYER_AS_MICHAEL
CASE PED_CLEANUP_KILLED_BY_PLAYER_AS_FRANKLIN
CASE PED_CLEANUP_KILLED_BY_VEHICLE
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_GCEK", CONV_PRIORITY_MEDIUM)
psEnemyGoonsCar0[i].bCleanupConversationTriggered = TRUE
SET_LABEL_AS_TRIGGERED("FAM3_GCEK", TRUE)
ENDIF
BREAK
CASE PED_CLEANUP_LOST
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_GCEL", CONV_PRIORITY_MEDIUM)
psEnemyGoonsCar0[i].bCleanupConversationTriggered = TRUE
SET_LABEL_AS_TRIGGERED("FAM3_GCEL", TRUE)
ENDIF
BREAK
ENDSWITCH
ENDIF
ENDIF
//loop through second vehicle group
IF ( psEnemyGoonsCar1[i].bCleanupConversationTriggered = FALSE )
IF ( psEnemyGoonsCar1[i].eCleanupReason <> PED_CLEANUP_NO_CLEANUP )
SWITCH psEnemyGoonsCar1[i].eCleanupReason
CASE PED_CLEANUP_KILLED_BY_MICHAEL
CASE PED_CLEANUP_KILLED_BY_FRANKLIN
CASE PED_CLEANUP_KILLED_BY_PLAYER_AS_MICHAEL
CASE PED_CLEANUP_KILLED_BY_PLAYER_AS_FRANKLIN
CASE PED_CLEANUP_KILLED_BY_VEHICLE
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_GCEK", CONV_PRIORITY_MEDIUM)
psEnemyGoonsCar1[i].bCleanupConversationTriggered = TRUE
SET_LABEL_AS_TRIGGERED("FAM3_GCEK", TRUE)
ENDIF
BREAK
CASE PED_CLEANUP_LOST
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_GCEL", CONV_PRIORITY_MEDIUM)
psEnemyGoonsCar1[i].bCleanupConversationTriggered = TRUE
SET_LABEL_AS_TRIGGERED("FAM3_GCEL", TRUE)
ENDIF
BREAK
ENDSWITCH
ENDIF
ENDIF
ENDFOR
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED() //if for all enemies cleanup conversation
IF NOT IS_ANY_TEXT_BEING_DISPLAYED(sLocatesData) //were somehow triggered earlier
IF ( psEnemyGoonsCar0[0].bCleanupConversationTriggered = TRUE ) //play this conversation as a backup
AND ( psEnemyGoonsCar0[1].bCleanupConversationTriggered = TRUE )
AND ( psEnemyGoonsCar1[0].bCleanupConversationTriggered = TRUE )
AND ( psEnemyGoonsCar1[1].bCleanupConversationTriggered = TRUE )
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": All enemies have their cleanup conversations triggered.")
#ENDIF
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_GCEL", CONV_PRIORITY_MEDIUM)
SET_LABEL_AS_TRIGGERED("FAM3_GCEL", TRUE)
ENDIF
ENDIF
ENDIF
ENDIF
ELSE
//play conversation after killing or losing the goons when player ends as Michael or Franklin
IF NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_GCEM")
AND NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_GCEH")
IF DOES_BLIP_EXIST(sLocatesData.LocationBlip)
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF NOT IS_ANY_TEXT_BEING_DISPLAYED(sLocatesData, IAT_IGNORE_GOD_TEXT_IF_SUBTITLES_OFF)
IF IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<-768.763489,167.945328,58.474373>>,
<<-848.048279,171.888687,77.934120>>, 50)
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_GCEH", CONV_PRIORITY_MEDIUM)
SET_LABEL_AS_TRIGGERED("FAM3_GCEH", TRUE)
ENDIF
ELSE
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_GCEM", CONV_PRIORITY_MEDIUM)
SET_LABEL_AS_TRIGGERED("FAM3_GCEM", TRUE)
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
//play shooting stat conversation
IF NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_STATA")
AND NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_STATB")
IF DOES_BLIP_EXIST(sLocatesData.LocationBlip)
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF NOT IS_ANY_TEXT_BEING_DISPLAYED(sLocatesData, IAT_IGNORE_GOD_TEXT_IF_SUBTITLES_OFF)
IF ( iPlayerFranklinKills + iBuddyFranklinKills > 0 )
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_STATA", CONV_PRIORITY_MEDIUM)
bAllowConvsersationOutsideOfCar = FALSE
SET_LABEL_AS_TRIGGERED("FAM3_STATA", TRUE)
bAllowConvsersationOutsideOfCar = TRUE
bConversationPaused = FALSE
ENDIF
ELSE
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_STATB", CONV_PRIORITY_MEDIUM)
bAllowConvsersationOutsideOfCar = FALSE
SET_LABEL_AS_TRIGGERED("FAM3_STATB", TRUE)
bAllowConvsersationOutsideOfCar = TRUE
bConversationPaused = FALSE
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ELSE
IF NOT IS_THIS_CONVERSATION_PLAYING("FAM3_STATA")
AND NOT IS_THIS_CONVERSATION_PLAYING("FAM3_STATB")
bStatConversationFinished = TRUE
ENDIF
ENDIF
IF NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_DBHA")
IF DOES_BLIP_EXIST(sLocatesData.LocationBlip)
IF ARE_PEDS_IN_THE_SAME_VEHICLE(GET_PED_INDEX(CHAR_MICHAEL), GET_PED_INDEX(CHAR_FRANKLIN))
IF NOT IS_ANY_TEXT_BEING_DISPLAYED(sLocatesData, IAT_IGNORE_GOD_TEXT_IF_SUBTITLES_OFF)
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_DBHA", CONV_PRIORITY_MEDIUM)
bAllowConvsersationOutsideOfCar = TRUE
bConversationPaused = FALSE
SET_LABEL_AS_TRIGGERED("FAM3_DBHA", TRUE)
ENDIF
ENDIF
ENDIF
ENDIF
ELSE
IF ( bConversationPaused = TRUE )
IF DOES_BLIP_EXIST(sLocatesData.LocationBlip) //wanted level off
IF ARE_STRINGS_EQUAL(lConversationRoot, "FAM3_DBHA")
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF CREATE_CONVERSATION_FROM_SPECIFIC_LINE(sFamily3Conversation, "FAM3AUD", "FAM3_DBHA", lConversationLabel, CONV_PRIORITY_MEDIUM)
bAllowConvsersationOutsideOfCar = TRUE
bConversationPaused = FALSE
ENDIF
ENDIF
ENDIF
ENDIF
ELSE
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
CurrentRoot = GET_CURRENTLY_PLAYING_STANDARD_CONVERSATION_ROOT()
IF NOT IS_STRING_NULL_OR_EMPTY(CurrentRoot)
IF ARE_STRINGS_EQUAL(CurrentRoot, "FAM3_DBHA")
IF ( psFranklin.fDistanceToTarget > BUDDY_SEPARATION_DIST / 2 )
KILL_FACE_TO_FACE_CONVERSATION()
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
IF NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_DBHB")
IF DOES_BLIP_EXIST(sLocatesData.LocationBlip)
IF ARE_PEDS_IN_THE_SAME_VEHICLE(GET_PED_INDEX(CHAR_MICHAEL), GET_PED_INDEX(CHAR_FRANKLIN))
IF NOT IS_ANY_TEXT_BEING_DISPLAYED(sLocatesData, IAT_IGNORE_GOD_TEXT_IF_SUBTITLES_OFF)
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_DBHB", CONV_PRIORITY_MEDIUM)
bAllowConvsersationOutsideOfCar = TRUE
bConversationPaused = FALSE
SET_LABEL_AS_TRIGGERED("FAM3_DBHB", TRUE)
ENDIF
ENDIF
ENDIF
ENDIF
ELSE
IF ( bConversationPaused = TRUE )
IF DOES_BLIP_EXIST(sLocatesData.LocationBlip) //wanted level off
IF ARE_STRINGS_EQUAL(lConversationRoot, "FAM3_DBHB")
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF CREATE_CONVERSATION_FROM_SPECIFIC_LINE(sFamily3Conversation, "FAM3AUD", "FAM3_DBHB", lConversationLabel, CONV_PRIORITY_MEDIUM)
bAllowConvsersationOutsideOfCar = TRUE
bConversationPaused = FALSE
ENDIF
ENDIF
ENDIF
ENDIF
ELSE
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
CurrentRoot = GET_CURRENTLY_PLAYING_STANDARD_CONVERSATION_ROOT()
IF NOT IS_STRING_NULL_OR_EMPTY(CurrentRoot)
IF ARE_STRINGS_EQUAL(CurrentRoot, "FAM3_DBHB")
IF ( psFranklin.fDistanceToTarget > BUDDY_SEPARATION_DIST / 2 )
KILL_FACE_TO_FACE_CONVERSATION()
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ELSE
//play conversations after god text to go back to Michael's house has been displayed but goons chase has not yet started
IF NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_DBHC")
IF DOES_BLIP_EXIST(sLocatesData.LocationBlip)
IF HAS_LABEL_BEEN_TRIGGERED(sLabelDHOUSE) OR IS_STRING_NULL_OR_EMPTY(sLabelDHOUSE)
IF ARE_PEDS_IN_THE_SAME_VEHICLE(GET_PED_INDEX(CHAR_MICHAEL), GET_PED_INDEX(CHAR_FRANKLIN))
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF NOT IS_ANY_TEXT_BEING_DISPLAYED(sLocatesData)
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_DBHC", CONV_PRIORITY_MEDIUM)
SET_LABEL_AS_TRIGGERED("FAM3_DBHC", TRUE)
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ELSE
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
CurrentRoot = GET_CURRENTLY_PLAYING_STANDARD_CONVERSATION_ROOT()
IF NOT IS_STRING_NULL_OR_EMPTY(CurrentRoot)
IF ARE_STRINGS_EQUAL(CurrentRoot, "FAM3_DBHC")
IF ( psFranklin.fDistanceToTarget > BUDDY_SEPARATION_DIST / 2 )
KILL_FACE_TO_FACE_CONVERSATION()
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ELSE //goons chase is in progress
IF NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_GCFSG") //play conversation for Franklin spotting the goons
INT k, j
IF ( vsEnemyCars[0].bLOSFlag = TRUE OR vsEnemyCars[1].bLOSFlag = TRUE )
OR DOES_ENTITY_EXIST(GET_CLOSEST_PED_FROM_GROUP(psEnemyGoonsCar0, k)) AND psEnemyGoonsCar0[k].fDistanceToTarget < 10.0
OR DOES_ENTITY_EXIST(GET_CLOSEST_PED_FROM_GROUP(psEnemyGoonsCar1, j)) AND psEnemyGoonsCar1[j].fDistanceToTarget < 10.0
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
//don't check for god text here, allow god text to be interrupted, spawning goons is the priority
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_GCFSG", CONV_PRIORITY_MEDIUM)
IF NOT IS_PED_IN_ANY_VEHICLE(GET_PED_INDEX(CHAR_FRANKLIN))
VEHICLE_INDEX ClosestEnemyCar
ClosestEnemyCar = GET_CLOSEST_MISSION_VEHICLE_TO_ENTITY(GET_PED_INDEX(CHAR_FRANKLIN), 100.0, BALLER)
IF DOES_ENTITY_EXIST(ClosestEnemyCar)
IF NOT IS_ENTITY_DEAD(ClosestEnemyCar)
SEQUENCE_INDEX PedSequence
OPEN_SEQUENCE_TASK(PedSequence)
TASK_TURN_PED_TO_FACE_ENTITY(NULL, ClosestEnemyCar)
TASK_LOOK_AT_ENTITY(NULL, ClosestEnemyCar, 3000)
CLOSE_SEQUENCE_TASK(PedSequence)
TASK_PERFORM_SEQUENCE(GET_PED_INDEX(CHAR_FRANKLIN), PedSequence)
CLEAR_SEQUENCE_TASK(PedSequence)
ENDIF
ENDIF
ENDIF
REPLAY_RECORD_BACK_FOR_TIME(3.0, 3.0)
SET_LABEL_AS_TRIGGERED("FAM3_GCFSG", TRUE)
ENDIF
ELSE
KILL_FACE_TO_FACE_CONVERSATION()
ENDIF
ENDIF
ELSE
IF NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_GCSM") //play conversation for Michael asking Franklin for help dealing with goons
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF NOT IS_ANY_TEXT_BEING_DISPLAYED(sLocatesData, IAT_IGNORE_GOD_TEXT_IF_SUBTITLES_OFF)
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_GCSM", CONV_PRIORITY_MEDIUM)
SET_LABEL_AS_TRIGGERED("FAM3_GCSM", TRUE)
ENDIF
ENDIF
ENDIF
ELSE
IF NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_GCSFA") //play Franklins response while they are in the car
AND NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_GCSFB") //play Franklins response while they are on foot
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF NOT IS_ANY_TEXT_BEING_DISPLAYED(sLocatesData, IAT_IGNORE_GOD_TEXT_IF_SUBTITLES_OFF)
IF IS_PED_SITTING_IN_ANY_VEHICLE(GET_PED_INDEX(CHAR_MICHAEL))
AND IS_PED_SITTING_IN_ANY_VEHICLE(GET_PED_INDEX(CHAR_FRANKLIN))
//converstaion when Michael and Franklin are in the car, Franklin tells Michael to drive
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_GCSFA", CONV_PRIORITY_MEDIUM)
iPlayerShootingTimer = GET_GAME_TIMER()
SET_LABEL_AS_TRIGGERED("FAM3_GCSFA", TRUE)
ENDIF
ELSE
//converstaion when Michael or Franklin is not in the car, Franklin tells Michael he will help
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_GCSFB", CONV_PRIORITY_MEDIUM)
iPlayerShootingTimer = GET_GAME_TIMER()
SET_LABEL_AS_TRIGGERED("FAM3_GCSFB", TRUE)
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
IF NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_GCSGS")
AND NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_GCSPS")
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF NOT IS_ANY_TEXT_BEING_DISPLAYED(sLocatesData, IAT_IGNORE_GOD_TEXT_IF_SUBTITLES_OFF)
//converstaion when player as Michael attacks the goons first
IF ( bGoonsAttacked = TRUE )
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_GCSPS", CONV_PRIORITY_MEDIUM)
SET_LABEL_AS_TRIGGERED("FAM3_GCSPS", TRUE)
ENDIF
ENDIF
//converstaion when Michael or Franklin are being shot at by the goons
IF IS_BULLET_IN_AREA(GET_ENTITY_COORDS(GET_PED_INDEX(CHAR_MICHAEL), FALSE), 7.5, FALSE)
OR IS_BULLET_IN_AREA(GET_ENTITY_COORDS(GET_PED_INDEX(CHAR_FRANKLIN), FALSE), 7.5, FALSE)
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_GCSGS", CONV_PRIORITY_MEDIUM)
SET_LABEL_AS_TRIGGERED("FAM3_GCSGS", TRUE)
ENDIF
ENDIF
//converstaion when Michael or Franklin are still chased by the goons and time for goons to shoot has expired
IF HAS_TIME_PASSED(12500, iPlayerShootingTimer)
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_GCSGS", CONV_PRIORITY_MEDIUM)
SET_LABEL_AS_TRIGGERED("FAM3_GCSGS", TRUE)
ENDIF
ENDIF
ELSE
IF IS_THIS_PRINT_BEING_DISPLAYED("FAM3_LGOONS")
//converstaion when Michael or Franklin are being shot at by the goons
IF IS_BULLET_IN_AREA(GET_ENTITY_COORDS(GET_PED_INDEX(CHAR_MICHAEL), FALSE), 7.5, FALSE)
OR IS_BULLET_IN_AREA(GET_ENTITY_COORDS(GET_PED_INDEX(CHAR_FRANKLIN), FALSE), 7.5, FALSE)
IF NOT IS_AMBIENT_SPEECH_PLAYING(GET_PED_INDEX(CHAR_MICHAEL))
PLAY_PED_AMBIENT_SPEECH_WITH_VOICE(GET_PED_INDEX(CHAR_MICHAEL), "FAM3_DDAA", "MICHAEL", SPEECH_PARAMS_FORCE_NORMAL)
SET_LABEL_AS_TRIGGERED("FAM3_GCSGS", TRUE)
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ELSE
IF ( bRandomConversationAllowed = FALSE )
psMichael.iConversationTimer = GET_GAME_TIMER() //reset timers for random dialogue
psFranklin.iConversationTimer = GET_GAME_TIMER()
iPlayerShootingTimer = GET_GAME_TIMER()
bRandomConversationAllowed = TRUE //allow random conversations
ENDIF
ENDIF
ENDIF
ENDIF
//play random conversations during the goons chase
//play dialogue for enemies being killed by Michael and Franklin
FOR i = 0 TO 1
//loop through first vehicle group
IF ( psEnemyGoonsCar0[i].bCleanupConversationTriggered = FALSE )
IF ( psEnemyGoonsCar0[i].eCleanupReason <> PED_CLEANUP_NO_CLEANUP )
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
AND NOT IS_ANY_TEXT_BEING_DISPLAYED(sLocatesData, IAT_IGNORE_GOD_TEXT_IF_SUBTITLES_OFF)
SWITCH psEnemyGoonsCar0[i].eCleanupReason
CASE PED_CLEANUP_LOST
//psEnemyGoonsCar0[i].bCleanupConversationTriggered = TRUE
BREAK
CASE PED_CLEANUP_KILLED_BY_MICHAEL
CASE PED_CLEANUP_KILLED_BY_PLAYER_AS_MICHAEL
IF NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_GCMKG_2")
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_GCMKG", CONV_PRIORITY_MEDIUM)
iMichaelEnemyKillConversations++
psEnemyGoonsCar0[i].bCleanupConversationTriggered = TRUE
psMichael.iConversationTimer = GET_GAME_TIMER()
psFranklin.iConversationTimer = GET_GAME_TIMER()
IF ( iMichaelEnemyKillConversations >= 2 )
SET_LABEL_AS_TRIGGERED("FAM3_GCMKG_2", TRUE)
ENDIF
ENDIF
ELSE
psEnemyGoonsCar0[i].bCleanupConversationTriggered = TRUE
psMichael.iConversationTimer = GET_GAME_TIMER()
psFranklin.iConversationTimer = GET_GAME_TIMER()
ENDIF
BREAK
CASE PED_CLEANUP_KILLED_BY_FRANKLIN
CASE PED_CLEANUP_KILLED_BY_PLAYER_AS_FRANKLIN
IF NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_GCFKG_3")
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_GCFKG", CONV_PRIORITY_MEDIUM)
iFranklinEnemyKillConversations++
psEnemyGoonsCar0[i].bCleanupConversationTriggered = TRUE
psMichael.iConversationTimer = GET_GAME_TIMER()
psFranklin.iConversationTimer = GET_GAME_TIMER()
IF ( iFranklinEnemyKillConversations >= 3 )
SET_LABEL_AS_TRIGGERED("FAM3_GCFKG_3", TRUE)
ENDIF
ENDIF
ELSE
psEnemyGoonsCar0[i].bCleanupConversationTriggered = TRUE
psMichael.iConversationTimer = GET_GAME_TIMER()
psFranklin.iConversationTimer = GET_GAME_TIMER()
ENDIF
BREAK
ENDSWITCH
ELSE
IF ( psEnemyGoonsCar0[i].iConversationTimer = 0 )
psEnemyGoonsCar0[i].iConversationTimer = GET_GAME_TIMER()
ELSE
IF HAS_TIME_PASSED(3000, psEnemyGoonsCar0[i].iConversationTimer)
psEnemyGoonsCar0[i].bCleanupConversationTriggered = TRUE
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Unable to play ped ", psEnemyGoonsCar0[i].sDebugName ," cleanup conversation due to another conversation ongoing or queued or text being displayed.")
#ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
//loop through second vehicle group
IF ( psEnemyGoonsCar1[i].bCleanupConversationTriggered = FALSE )
IF ( psEnemyGoonsCar1[i].eCleanupReason <> PED_CLEANUP_NO_CLEANUP )
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
AND NOT IS_ANY_TEXT_BEING_DISPLAYED(sLocatesData, IAT_IGNORE_GOD_TEXT_IF_SUBTITLES_OFF)
SWITCH psEnemyGoonsCar1[i].eCleanupReason
CASE PED_CLEANUP_LOST
//psEnemyGoonsCar1[i].bCleanupConversationTriggered = TRUE
BREAK
CASE PED_CLEANUP_KILLED_BY_MICHAEL
CASE PED_CLEANUP_KILLED_BY_PLAYER_AS_MICHAEL
IF NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_GCMKG_2")
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_GCMKG", CONV_PRIORITY_MEDIUM)
iMichaelEnemyKillConversations++
psEnemyGoonsCar1[i].bCleanupConversationTriggered = TRUE
psMichael.iConversationTimer = GET_GAME_TIMER()
psFranklin.iConversationTimer = GET_GAME_TIMER()
IF ( iMichaelEnemyKillConversations >= 2 )
SET_LABEL_AS_TRIGGERED("FAM3_GCMKG_2", TRUE)
ENDIF
ENDIF
ELSE
psEnemyGoonsCar1[i].bCleanupConversationTriggered = TRUE
psMichael.iConversationTimer = GET_GAME_TIMER()
psFranklin.iConversationTimer = GET_GAME_TIMER()
ENDIF
BREAK
CASE PED_CLEANUP_KILLED_BY_FRANKLIN
CASE PED_CLEANUP_KILLED_BY_PLAYER_AS_FRANKLIN
IF NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_GCFKG_3")
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_GCFKG", CONV_PRIORITY_MEDIUM)
iFranklinEnemyKillConversations++
psEnemyGoonsCar1[i].bCleanupConversationTriggered = TRUE
psMichael.iConversationTimer = GET_GAME_TIMER()
psFranklin.iConversationTimer = GET_GAME_TIMER()
IF ( iFranklinEnemyKillConversations >= 3 )
SET_LABEL_AS_TRIGGERED("FAM3_GCFKG_3", TRUE)
ENDIF
ENDIF
ELSE
psEnemyGoonsCar1[i].bCleanupConversationTriggered = TRUE
psMichael.iConversationTimer = GET_GAME_TIMER()
psFranklin.iConversationTimer = GET_GAME_TIMER()
ENDIF
BREAK
ENDSWITCH
ELSE
IF ( psEnemyGoonsCar1[i].iConversationTimer = 0 )
psEnemyGoonsCar1[i].iConversationTimer = GET_GAME_TIMER()
ELSE
IF HAS_TIME_PASSED(3000, psEnemyGoonsCar1[i].iConversationTimer)
psEnemyGoonsCar1[i].bCleanupConversationTriggered = TRUE
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Unable to play ped ", psEnemyGoonsCar1[i].sDebugName ," cleanup conversation due to another conversation ongoing or queued or text being displayed.")
#ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDFOR
IF ( bRandomConversationAllowed = TRUE )
//play random Michael line
IF HAS_TIME_PASSED(10000, psMichael.iConversationTimer)
IF ARE_PEDS_IN_THE_SAME_VEHICLE(GET_PED_INDEX(CHAR_MICHAEL), GET_PED_INDEX(CHAR_FRANKLIN))
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF NOT IS_ANY_TEXT_BEING_DISPLAYED(sLocatesData, IAT_IGNORE_GOD_TEXT_IF_SUBTITLES_OFF)
//Michael is in the driver seat
IF IS_PED_SITTING_IN_THIS_VEHICLE(GET_PED_INDEX(CHAR_MICHAEL), GET_VEHICLE_PED_IS_USING(GET_PED_INDEX(CHAR_MICHAEL)))
IF GET_PED_VEHICLE_SEAT(GET_PED_INDEX(CHAR_MICHAEL), GET_VEHICLE_PED_IS_USING(GET_PED_INDEX(CHAR_MICHAEL))) = VS_DRIVER
IF GET_DISTANCE_TO_CLOSEST_PED_FROM_GROUPS(psEnemyGoonsCar0, psEnemyGoonsCar1) < 30.0
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_GCMEF", CONV_PRIORITY_MEDIUM)
psMichael.iConversationTimer = GET_GAME_TIMER()
ENDIF
ELSE
IF ( psMichael.iConversationCounter < 4 )
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_GCMAF", CONV_PRIORITY_MEDIUM)
psMichael.iConversationTimer = GET_GAME_TIMER()
psMichael.iConversationCounter++
ENDIF
ELSE
psMichael.iConversationTimer = GET_GAME_TIMER()
ENDIF
ENDIF
ELSE //Michael is in a passenger seat
SWITCH GET_RANDOM_INT_IN_RANGE(0, 2)
CASE 0 //Michael in combat from car dialgoue
IF GET_DISTANCE_TO_CLOSEST_PED_FROM_GROUPS(psEnemyGoonsCar0, psEnemyGoonsCar1) < 20.0
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_GCMAG", CONV_PRIORITY_MEDIUM)
psMichael.iConversationTimer = GET_GAME_TIMER()
ENDIF
ENDIF
BREAK
CASE 1 //Michael telling Franklin to drive faster
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_GCMDF", CONV_PRIORITY_MEDIUM)
psMichael.iConversationTimer = GET_GAME_TIMER()
ENDIF
BREAK
ENDSWITCH
ENDIF
ENDIF
ENDIF
ENDIF
ELSE //Michael and Franklin are on foot
IF NOT IS_PED_IN_ANY_VEHICLE(GET_PED_INDEX(CHAR_MICHAEL))
AND NOT IS_PED_IN_ANY_VEHICLE(GET_PED_INDEX(CHAR_FRANKLIN))
IF ( psFranklin.fDistanceToTarget < BUDDY_SEPARATION_DIST )
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF NOT IS_ANY_TEXT_BEING_DISPLAYED(sLocatesData, IAT_IGNORE_GOD_TEXT_IF_SUBTITLES_OFF)
SWITCH GET_RANDOM_INT_IN_RANGE(0, 2)
CASE 0 //Michael in combat on foot dialogue
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_GCMAG", CONV_PRIORITY_MEDIUM)
psMichael.iConversationTimer = GET_GAME_TIMER()
ENDIF
BREAK
CASE 1 //Michael encouraging Franklin for combat
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_GCMEF", CONV_PRIORITY_MEDIUM)
psMichael.iConversationTimer = GET_GAME_TIMER()
ENDIF
BREAK
ENDSWITCH
ENDIF
ENDIF
ELSE
psMichael.iConversationTimer = GET_GAME_TIMER()
ENDIF
ENDIF
ENDIF
ENDIF
//play random Franklin line
IF HAS_TIME_PASSED(8000, psFranklin.iConversationTimer)
IF ARE_PEDS_IN_THE_SAME_VEHICLE(GET_PED_INDEX(CHAR_MICHAEL), GET_PED_INDEX(CHAR_FRANKLIN))
//Franklin is in the driver seat
IF IS_PED_SITTING_IN_THIS_VEHICLE(GET_PED_INDEX(CHAR_FRANKLIN), GET_VEHICLE_PED_IS_USING(GET_PED_INDEX(CHAR_FRANKLIN)))
IF GET_PED_VEHICLE_SEAT(GET_PED_INDEX(CHAR_FRANKLIN), GET_VEHICLE_PED_IS_USING(GET_PED_INDEX(CHAR_FRANKLIN))) = VS_DRIVER
IF GET_DISTANCE_TO_CLOSEST_PED_FROM_GROUPS(psEnemyGoonsCar0, psEnemyGoonsCar1) < 30.0
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_GCFEM", CONV_PRIORITY_MEDIUM)
psFranklin.iConversationTimer = GET_GAME_TIMER()
ENDIF
ELSE
IF ( psFranklin.iConversationCounter < 4 )
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_GCFAM", CONV_PRIORITY_MEDIUM)
psFranklin.iConversationTimer = GET_GAME_TIMER()
psFranklin.iConversationCounter++
ENDIF
ELSE
psFranklin.iConversationTimer = GET_GAME_TIMER()
ENDIF
ENDIF
ELSE //Franklin is in a passenger seat
SWITCH GET_RANDOM_INT_IN_RANGE(0, 2)
CASE 0 //Franklin in combat from car dialgoue
IF GET_DISTANCE_TO_CLOSEST_PED_FROM_GROUPS(psEnemyGoonsCar0, psEnemyGoonsCar1) < 20.0
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_GCFAG", CONV_PRIORITY_MEDIUM)
psFranklin.iConversationTimer = GET_GAME_TIMER()
ENDIF
ENDIF
BREAK
CASE 1 //Franklin telling Michael to drive faster
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_GCFDF", CONV_PRIORITY_MEDIUM)
psFranklin.iConversationTimer = GET_GAME_TIMER()
ENDIF
BREAK
ENDSWITCH
ENDIF
ELSE
ENDIF
ELSE //Michael and Franklin are on foot
IF NOT IS_PED_IN_ANY_VEHICLE(GET_PED_INDEX(CHAR_MICHAEL))
AND NOT IS_PED_IN_ANY_VEHICLE(GET_PED_INDEX(CHAR_FRANKLIN))
IF ( psFranklin.fDistanceToTarget < BUDDY_SEPARATION_DIST )
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF NOT IS_ANY_TEXT_BEING_DISPLAYED(sLocatesData, IAT_IGNORE_GOD_TEXT_IF_SUBTITLES_OFF)
SWITCH GET_RANDOM_INT_IN_RANGE(0, 2)
CASE 0 //Franklin in combat on foot dialogue
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_GCFAG", CONV_PRIORITY_MEDIUM)
psFranklin.iConversationTimer = GET_GAME_TIMER()
ENDIF
BREAK
CASE 1 //Franklin encouraging Michael for combat
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_GCFEM", CONV_PRIORITY_MEDIUM)
psFranklin.iConversationTimer = GET_GAME_TIMER()
ENDIF
BREAK
ENDSWITCH
ENDIF
ENDIF
ELSE
psFranklin.iConversationTimer = GET_GAME_TIMER()
ENDIF
ENDIF
ENDIF
ENDIF
//play conversations for player being reminded to shoot the goons when not shooting the goons
IF NOT IS_PED_SHOOTING(PLAYER_PED_ID())
AND NOT ( IS_PED_SITTING_IN_THIS_VEHICLE(PLAYER_PED_ID(), GET_VEHICLE_PED_IS_USING(PLAYER_PED_ID())) AND GET_PED_VEHICLE_SEAT(PLAYER_PED_ID(), GET_VEHICLE_PED_IS_USING(PLAYER_PED_ID())) = VS_DRIVER )
IF HAS_TIME_PASSED(10000, iPlayerShootingTimer)
IF ( psFranklin.fDistanceToTarget < BUDDY_SEPARATION_DIST )
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF NOT IS_ANY_TEXT_BEING_DISPLAYED(sLocatesData, IAT_IGNORE_GOD_TEXT_IF_SUBTITLES_OFF)
SWITCH GET_CURRENT_PLAYER_PED_ENUM()
CASE CHAR_MICHAEL
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_GCMNS", CONV_PRIORITY_MEDIUM)
psMichael.iConversationTimer = GET_GAME_TIMER()
psFranklin.iConversationTimer = GET_GAME_TIMER()
iPlayerShootingTimer = GET_GAME_TIMER()
ENDIF
BREAK
CASE CHAR_FRANKLIN
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_GCFNS", CONV_PRIORITY_MEDIUM)
psMichael.iConversationTimer = GET_GAME_TIMER()
psFranklin.iConversationTimer = GET_GAME_TIMER()
iPlayerShootingTimer = GET_GAME_TIMER()
ENDIF
BREAK
ENDSWITCH
ENDIF
ENDIF
ELSE
iPlayerShootingTimer = GET_GAME_TIMER()
ENDIF
ENDIF
ELSE
iPlayerShootingTimer = GET_GAME_TIMER()
ENDIF
ENDIF
ENDIF
BREAK
ENDSWITCH
//play conversation for Michael and Franklin taking a different vehicle than the initial player truck or leaving truck behind
IF NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_GCCVTM")
AND NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_GCCVTF")
IF ( iVehicleSwitchTimer = 0 )
//if player decides to use another vehicle
IF DOES_ENTITY_EXIST(GET_VEHICLE_PED_IS_USING(PLAYER_PED_ID())) AND GET_VEHICLE_PED_IS_USING(PLAYER_PED_ID()) <> vsPlayersCar.VehicleIndex
iVehicleSwitchTimer = GET_GAME_TIMER()
ENDIF
ELSE
IF HAS_TIME_PASSED(7500, iVehicleSwitchTimer)
SET_LABEL_AS_TRIGGERED("FAM3_GCCVTM", TRUE)
SET_LABEL_AS_TRIGGERED("FAM3_GCCVTF", TRUE)
ELSE
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF NOT IS_ANY_TEXT_BEING_DISPLAYED(sLocatesData, IAT_IGNORE_GOD_TEXT_IF_SUBTITLES_OFF)
IF ( psFranklin.fDistanceToTarget <= BUDDY_SEPARATION_DIST / 2 )
IF ( bStopScriptedConversations = FALSE )
SWITCH GET_CURRENT_PLAYER_PED_ENUM()
CASE CHAR_MICHAEL
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_GCCVTM", CONV_PRIORITY_MEDIUM)
SET_LABEL_AS_TRIGGERED("FAM3_GCCVTM", TRUE)
ENDIF
BREAK
CASE CHAR_FRANKLIN
IF CREATE_CONVERSATION(sFamily3Conversation, "FAM3AUD", "FAM3_GCCVTF", CONV_PRIORITY_MEDIUM)
SET_LABEL_AS_TRIGGERED("FAM3_GCCVTF", TRUE)
ENDIF
BREAK
ENDSWITCH
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDPROC
PROC MANAGE_OTHER_PLAYER_PED_DURING_ESCAPE_GOONS(PED_INDEX PedIndex, PED_STRUCT &ped, PED_INDEX TargetPedIndex,
VEHICLE_INDEX TargetVehicleIndex, BOOL bEnemiesPresent)
IF DOES_ENTITY_EXIST(PedIndex)
AND NOT IS_ENTITY_DEAD(PedIndex)
IF DOES_ENTITY_EXIST(TargetPedIndex)
AND NOT IS_ENTITY_DEAD(TargetPedIndex)
#IF IS_DEBUG_BUILD //debug information
IF ( bDrawDebugStates = TRUE )
DRAW_DEBUG_TEXT_ABOVE_ENTITY(PedIndex, GET_PED_STATE_NAME_FOR_DEBUG(ped.eState), 1.25)
ENDIF
SWITCH GET_CURRENT_PLAYER_PED_ENUM()
CASE CHAR_MICHAEL
ped.sDebugName = "Franklin"
BREAK
CASE CHAR_FRANKLIN
ped.sDebugName = "Michael"
BREAK
ENDSWITCH
#ENDIF
ped.fDistanceToTarget = GET_DISTANCE_BETWEEN_ENTITIES(PedIndex, TargetPedIndex)
FLOAT fDistanceToDestination = GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PedIndex), vMichaelsHousePosition)
SET_PED_RESET_FLAG(PedIndex, PRF_BlockWeaponReactionsUnlessDead, TRUE)
SET_PED_CAN_PLAY_AMBIENT_ANIMS(PedIndex, FALSE)
SET_PED_CAN_PLAY_AMBIENT_BASE_ANIMS(PedIndex, FALSE)
IF ( bEnemiesPresent = TRUE )
IF ( bCombatAllowed = TRUE )
IF ( GET_AMMO_IN_PED_WEAPON(PedIndex, WEAPONTYPE_PISTOL) < GET_MAX_AMMO_IN_CLIP(PedIndex, WEAPONTYPE_PISTOL) )
ADD_AMMO_TO_PED(PedIndex, WEAPONTYPE_PISTOL, GET_MAX_AMMO_IN_CLIP(PedIndex, WEAPONTYPE_PISTOL))
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Adding extra pistol clip with ", GET_MAX_AMMO_IN_CLIP(PedIndex, WEAPONTYPE_PISTOL), " bullets to buddy ped ", ped.sDebugName, ".")
#ENDIF
ENDIF
ENDIF
ENDIF
SWITCH ped.eState
CASE PED_STATE_IDLE
IF ( ped.bHasTask = FALSE )
SET_PED_INFINITE_AMMO(PedIndex, FALSE)
GIVE_WEAPON_TO_PED(PedIndex, WEAPONTYPE_PISTOL, GET_MAX_AMMO_IN_CLIP(PedIndex, WEAPONTYPE_PISTOL) * 6, FALSE, TRUE)
SET_CURRENT_PED_WEAPON(PedIndex, WEAPONTYPE_PISTOL)
SET_RAGDOLL_BLOCKING_FLAGS(PedIndex, RBF_BULLET_IMPACT)
SET_RAGDOLL_BLOCKING_FLAGS(PedIndex, RBF_PLAYER_IMPACT)
SET_PED_SUFFERS_CRITICAL_HITS(PedIndex, FALSE)
SET_PED_MAX_HEALTH_WITH_SCALE(PedIndex, MAX_BUDDY_PED_HEALTH)
IF NOT IS_PED_GROUP_MEMBER(PedIndex, PLAYER_GROUP_ID())
SET_PED_AS_GROUP_MEMBER(PedIndex, PLAYER_GROUP_ID())
SET_PED_GROUP_MEMBER_PASSENGER_INDEX(PedIndex, VS_FRONT_RIGHT)
SET_PED_CAN_TELEPORT_TO_GROUP_LEADER(PedIndex, PLAYER_GROUP_ID(), TRUE)
SET_PED_CONFIG_FLAG(PedIndex, PCF_TeleportToLeaderVehicle, FALSE)
ENDIF
SET_PED_CONFIG_FLAG(PedIndex, PCF_DisableHurt, TRUE)
SET_PED_CONFIG_FLAG(PedIndex, PCF_DisablePanicInVehicle, TRUE)
SET_PED_CONFIG_FLAG(PedIndex, PCF_OnlyAttackLawIfPlayerIsWanted, TRUE)
SET_COMBAT_FLOAT(PedIndex, CCF_TIME_TO_INVALIDATE_INJURED_TARGET, 1.0)
SET_PED_COMBAT_ATTRIBUTES(PedIndex, CA_ALWAYS_EQUIP_BEST_WEAPON, FALSE)
SET_PED_COMBAT_ATTRIBUTES(PedIndex, CA_CAN_FIGHT_ARMED_PEDS_WHEN_NOT_ARMED, TRUE)
ADD_ENTITY_TO_AUDIO_MIX_GROUP(PedIndex, "FAMILY_3_BUDDY_GROUP")
ped.bHasTask = TRUE
ENDIF
GO_TO_PED_STATE(ped, PED_STATE_FOLLOWING_PLAYER)
BREAK
CASE PED_STATE_FOLLOWING_PLAYER
IF ( ped.bHasTask = FALSE )
IF NOT IS_PED_GROUP_MEMBER(PedIndex, PLAYER_GROUP_ID())
SET_PED_AS_GROUP_MEMBER(PedIndex, PLAYER_GROUP_ID())
ENDIF
SET_GROUP_SEPARATION_RANGE(PLAYER_GROUP_ID(), BUDDY_SEPARATION_DIST)
SET_PED_GROUP_MEMBER_PASSENGER_INDEX(PedIndex, VS_FRONT_RIGHT)
SET_PED_CAN_TELEPORT_TO_GROUP_LEADER(PedIndex, PLAYER_GROUP_ID(), TRUE)
SET_PED_ACCURACY(PedIndex, 20)
SET_PED_SHOOT_RATE(PedIndex, 115)
SET_PED_HIGHLY_PERCEPTIVE(PedIndex, TRUE)
SET_PED_COMBAT_ATTRIBUTES(PedIndex, CA_USE_COVER, TRUE)
SET_PED_COMBAT_ATTRIBUTES(PedIndex, CA_DO_DRIVEBYS, TRUE)
SET_PED_COMBAT_ATTRIBUTES(PedIndex, CA_USE_VEHICLE, TRUE)
SET_PED_COMBAT_ATTRIBUTES(PedIndex, CA_LEAVE_VEHICLES, FALSE)
SET_COMBAT_FLOAT(PedIndex, CCF_STRAFE_WHEN_MOVING_CHANCE, 0.9)
SET_COMBAT_FLOAT(PedIndex, CCF_WALK_WHEN_STRAFING_CHANCE, 0.0)
SET_PED_COMBAT_MOVEMENT(PedIndex, CM_DEFENSIVE)
SET_PED_DEFENSIVE_SPHERE_ATTACHED_TO_PED(PedIndex, TargetPedIndex, << 0.0, 0.0, 0.0 >>, 5.0)
SET_PED_CAN_RAGDOLL(PedIndex, TRUE)
SET_RAGDOLL_BLOCKING_FLAGS(PedIndex, RBF_MELEE)
SET_RAGDOLL_BLOCKING_FLAGS(PedIndex, RBF_BULLET_IMPACT)
SET_RAGDOLL_BLOCKING_FLAGS(PedIndex, RBF_PLAYER_IMPACT)
SET_PED_SUFFERS_CRITICAL_HITS(PedIndex, FALSE)
SET_ENTITY_ONLY_DAMAGED_BY_PLAYER(PedIndex, FALSE)
SET_PED_CONFIG_FLAG(PedIndex, PCF_DisableHurt, TRUE)
SET_PED_CONFIG_FLAG(PedIndex, PCF_TeleportToLeaderVehicle, FALSE)
SET_PED_CONFIG_FLAG(PedIndex, PCF_DisableGoToWritheWhenInjured, TRUE)
SET_PED_CONFIG_FLAG(PedIndex, PCF_OnlyAttackLawIfPlayerIsWanted, TRUE)
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(PedIndex, FALSE)
IF ( bWantedLevelBlockedOnBuddyDrive = TRUE )
SET_MAX_WANTED_LEVEL(5)
SET_CREATE_RANDOM_COPS(TRUE) //unblock wanted level if it was blocked when buddy was driving
SET_WANTED_LEVEL_MULTIPLIER(1.0)
bWantedLevelBlockedOnBuddyDrive = FALSE
ENDIF
ped.bHasTask = TRUE
ENDIF
IF ( ped.bHasTask = TRUE)
IF ( bEnemiesPresent = TRUE )
IF ( bCombatAllowed = FALSE )
IF IS_PED_IN_THIS_VEHICLE(PedIndex, TargetVehicleIndex)
IF IS_PED_SITTING_IN_THIS_VEHICLE(PedIndex, TargetVehicleIndex)
IF ( vsEnemyCars[0].bLOSFlag = TRUE OR vsEnemyCars[1].bLOSFlag = TRUE )
GO_TO_PED_STATE(ped, PED_STATE_LOOKING_BEHIND_IN_VEHICLE)
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
IF ( ped.fDistanceToTarget > BUDDY_SEPARATION_DIST )
OR NOT IS_PED_GROUP_MEMBER(ped.PedIndex, PLAYER_GROUP_ID())
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Ped with debug name ", ped.sDebugName, " is not player group member any more.")
#ENDIF
GO_TO_PED_STATE(ped, PED_STATE_WAITING_FOR_PLAYER)
ENDIF
ENDIF
IF ( bBuddyPedCoverTaskCleared = FALSE )
IF ( bGoonsChaseFinished = TRUE AND bGoonsChaseInProgress = FALSE )
IF IS_PED_IN_COVER(PedIndex) OR IS_PED_GOING_INTO_COVER(PedIndex) OR IS_PED_IN_COMBAT(PedIndex)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Clearing buddy ped tasks for ped with debug name ", ped.sDebugName, " due to ped being in cover when goons chase ends.")
#ENDIF
CLEAR_PED_TASKS(PedIndex)
ENDIF
bBuddyPedCoverTaskCleared = TRUE
ENDIF
ENDIF
BREAK
CASE PED_STATE_WAITING_FOR_PLAYER
IF ( ped.bHasTask = FALSE )
SET_PED_COMBAT_MOVEMENT(PedIndex, CM_DEFENSIVE)
SET_PED_DEFENSIVE_SPHERE_ATTACHED_TO_PED(PedIndex, TargetPedIndex, << 0.0, 0.0, 0.0 >>, 7.5)
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(PedIndex, FALSE)
ped.bHasTask = TRUE
ENDIF
IF ( ped.bHasTask = TRUE)
IF ( ped.fDistanceToTarget <= BUDDY_SEPARATION_DIST / 3 )
GO_TO_PED_STATE(ped, PED_STATE_FOLLOWING_PLAYER)
ENDIF
ENDIF
BREAK
CASE PED_STATE_SITTING_IN_VEHICLE_DRIVER
IF ( ped.bHasTask = FALSE )
IF IS_PED_SITTING_IN_THIS_VEHICLE(PedIndex, TargetVehicleIndex)
CLEAR_PED_TASKS(PedIndex)
TASK_VEHICLE_MISSION_COORS_TARGET(PedIndex, TargetVehicleIndex, GET_ENTITY_COORDS(TargetVehicleIndex), MISSION_STOP, 2.5, DRIVINGMODE_AVOIDCARS, 5.0, 5.0)
ENDIF
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(PedIndex, TRUE)
ped.bHasTask = TRUE
ENDIF
IF IS_PED_SITTING_IN_THIS_VEHICLE(TargetPedIndex, TargetVehicleIndex)
IF ( bEnemiesPresent = TRUE )
GO_TO_PED_STATE(ped, PED_STATE_DRIVE_FLEE_TARGETS)
ELSE
GO_TO_PED_STATE(ped, PED_STATE_DRIVE_TO_DESTINATION)
ENDIF
ELSE
CLEAR_PED_TASKS(PedIndex)
GO_TO_PED_STATE(ped, PED_STATE_FOLLOWING_PLAYER)
ENDIF
BREAK
CASE PED_STATE_LOOKING_BEHIND_IN_VEHICLE
IF ( ped.bHasTask = FALSE )
IF NOT IS_ENTITY_PLAYING_LOOK_BEHIND_ANIM(PedIndex)
IF IS_PED_SITTING_IN_THIS_VEHICLE(PedIndex, TargetVehicleIndex)
REQUEST_ANIM_DICT("missfam3")
IF HAS_ANIM_DICT_LOADED("missfam3")
TASK_PLAY_LOOK_BEHIND_ANIM(PedIndex, GET_PED_VEHICLE_SEAT(PedIndex, TargetVehicleIndex), 6000)
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(PedIndex, TRUE)
ENDIF
ENDIF
ELSE
ped.iTimer = GET_GAME_TIMER()
ped.bHasTask = TRUE
ENDIF
ENDIF
IF IS_ENTITY_PLAYING_LOOK_BEHIND_ANIM(PedIndex)
IF HAS_TIME_PASSED(2000, ped.iTimer) //make sure the animation is played for at least a brief moment
IF NOT IS_PED_SITTING_IN_ANY_VEHICLE(PedIndex)
CLEAR_PED_SECONDARY_TASK(PedIndex)
ENDIF
VEHICLE_INDEX ClosestEnemyCar
ClosestEnemyCar = GET_CLOSEST_MISSION_VEHICLE_TO_ENTITY(PedIndex, 100.0, BALLER)
IF DOES_ENTITY_EXIST(TargetVehicleIndex)
AND DOES_ENTITY_EXIST(ClosestEnemyCar)
VECTOR vTargetVehicleForwardVector
VECTOR vEnemyCarForwardVector
VECTOR vOffset
FLOAT fAngleBetweenVectors
vEnemyCarForwardVector = GET_ENTITY_FORWARD_VECTOR(ClosestEnemyCar)
vTargetVehicleForwardVector = GET_ENTITY_FORWARD_VECTOR(TargetVehicleIndex)
//check angle between player's car and closest enemy car
fAngleBetweenVectors = GET_ANGLE_BETWEEN_2D_VECTORS(vTargetVehicleForwardVector.X, vTargetVehicleForwardVector.Y,
vEnemyCarForwardVector.X, vEnemyCarForwardVector.Y)
//check if player is behind or in front of closest enemy car
vOffset = GET_OFFSET_FROM_ENTITY_GIVEN_WORLD_COORDS(ClosestEnemyCar, GET_ENTITY_COORDS(PedIndex, FALSE))
#IF IS_DEBUG_BUILD
IF ( bDrawDebugLinesAndSpheres = TRUE )
DRAW_DEBUG_TEXT_ABOVE_ENTITY(TargetVehicleIndex, GET_STRING_FROM_FLOAT(fAngleBetweenVectors), 2.0)
DRAW_DEBUG_LINE(GET_ENTITY_COORDS(TargetVehicleIndex, FALSE), GET_ENTITY_COORDS(ClosestEnemyCar, FALSE))
DRAW_DEBUG_TEXT_ABOVE_ENTITY(TargetVehicleIndex, GET_STRING_FROM_FLOAT(vOffset.Y), 2.5)
ENDIF
#ENDIF
IF ( vOffset.Y < 0.0 OR fAngleBetweenVectors > 100.0 )
CLEAR_PED_SECONDARY_TASK(PedIndex)
ENDIF
ENDIF
ENDIF
ENDIF
IF ( bCombatAllowed = TRUE )
CLEAR_PED_TASKS(PedIndex)
CLEAR_PED_SECONDARY_TASK(PedIndex)
REMOVE_ANIM_DICT("missfam3")
GO_TO_PED_STATE(ped, PED_STATE_FOLLOWING_PLAYER)
ENDIF
BREAK
CASE PED_STATE_DRIVE_FLEE_TARGETS
IF (ped.bHasTask = FALSE )
INT i, k
PED_INDEX EnemyPedIndex
GET_CLOSEST_PED_FROM_GROUP(psEnemyGoonsCar0, i)
GET_CLOSEST_PED_FROM_GROUP(psEnemyGoonsCar1, k)
IF ( i <> -1 AND k <> -1)
IF ( psEnemyGoonsCar0[i].fDistanceToTarget <= psEnemyGoonsCar1[k].fDistanceToTarget )
EnemyPedIndex = psEnemyGoonsCar0[i].PedIndex
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Closest enemy ped to flee from is ", psEnemyGoonsCar0[i].sDebugName, ".")
#ENDIF
ELSE
EnemyPedIndex = psEnemyGoonsCar1[k].PedIndex
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Closest enemy ped to flee from is ", psEnemyGoonsCar1[k].sDebugName, ".")
#ENDIF
ENDIF
ELSE
IF ( i <> -1 )
EnemyPedIndex = psEnemyGoonsCar0[i].PedIndex
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Closest enemy ped to flee from is ", psEnemyGoonsCar0[i].sDebugName, ".")
#ENDIF
ELIF ( k <> -1 )
EnemyPedIndex = psEnemyGoonsCar1[k].PedIndex
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Closest enemy ped to flee from is ", psEnemyGoonsCar1[k].sDebugName, ".")
#ENDIF
ENDIF
ENDIF
IF NOT IS_ENTITY_AT_COORD(PedIndex, << -804.86, 166.51, 70.56 >>, << 36.0, 24.0, 12.0 >>)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Buddy ped away from Michael's house area.")
#ENDIF
IF DOES_ENTITY_EXIST(EnemyPedIndex) //found enemy to flee
#IF IS_DEBUG_BUILD
VECTOR vPrintCoords
vPrintCoords = GET_ENTITY_COORDS(EnemyPedIndex, FALSE)
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Found closest enemy to flee. Fleeing coords of enemy ", vPrintCoords, ".")
DRAW_DEBUG_LINE(GET_ENTITY_COORDS(PedIndex, FALSE), GET_ENTITY_COORDS(EnemyPedIndex, FALSE), 255, 255, 255)
#ENDIF
CLEAR_PED_TASKS(PedIndex)
//flee from coords where closest enemy ped is
TASK_VEHICLE_MISSION_COORS_TARGET(PedIndex, TargetVehicleIndex, GET_ENTITY_COORDS(EnemyPedIndex, FALSE), MISSION_FLEE, 25.0,
DF_SteerAroundObjects | DF_SteerAroundPeds | DF_SteerAroundStationaryCars |
DF_ChangeLanesAroundObstructions | DF_ForceJoinInRoadDirection |
DF_SwerveAroundAllCars, //| DF_UseStringPullingAtJunctions,
500.0, 10.0, FALSE)
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(PedIndex, TRUE)
ped.iTimer = GET_GAME_TIMER()
ELSE //not found enemy to flee
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Not found nearby enemies. Fleeing coords of vehicle player ped is using.")
#ENDIF
CLEAR_PED_TASKS(PedIndex)
TASK_VEHICLE_MISSION_COORS_TARGET(PedIndex, TargetVehicleIndex, GET_ENTITY_COORDS(TargetVehicleIndex), MISSION_FLEE, 26.0,
DF_SteerAroundObjects | DF_SteerAroundPeds | DF_SteerAroundStationaryCars |
DF_ChangeLanesAroundObstructions | DF_ForceJoinInRoadDirection |
DF_SwerveAroundAllCars, //| DF_UseStringPullingAtJunctions,
500.0, 10.0, FALSE)
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(PedIndex, TRUE)
ped.iTimer = GET_GAME_TIMER()
ENDIF
ELSE
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Buddy ped doing drive flee task in Michael's house area.")
#ENDIF
CLEAR_PED_TASKS(PedIndex)
GO_TO_PED_STATE(ped, PED_STATE_COMBAT_ON_FOOT)
ENDIF
ped.bHasTask = TRUE
ENDIF
IF ( bEnemiesPresent = FALSE )
IF ( bDriveTaskDelayed = FALSE )
GO_TO_PED_STATE(ped, PED_STATE_DRIVE_FLEE_TARGETS) //when goons are lost task the buddy to flee once more
bDriveTaskDelayed = TRUE //until dialogue to go home triggers or delay timer expires
ENDIF
IF ( iDriveTaskDelayTimer = 0 )
iDriveTaskDelayTimer = GET_GAME_TIMER()
ENDIF
IF ( ( iDriveTaskDelayTimer != 0 ) AND HAS_TIME_PASSED(12500, iDriveTaskDelayTimer) )
OR HAS_LABEL_BEEN_TRIGGERED("FAM3_GCEM") OR HAS_LABEL_BEEN_TRIGGERED("FAM3_GCEF")
GO_TO_PED_STATE(ped, PED_STATE_DRIVE_TO_DESTINATION)
ELSE
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Waiting for drive to destination task to be given.")
#ENDIF
ENDIF
ELSE
SWITCH GET_SCRIPT_TASK_STATUS(PedIndex, SCRIPT_TASK_VEHICLE_MISSION)
CASE PERFORMING_TASK
IF HAS_TIME_PASSED(5000, ped.iTimer)
GO_TO_PED_STATE(ped, PED_STATE_DRIVE_FLEE_TARGETS)
ENDIF
BREAK
CASE FINISHED_TASK
GO_TO_PED_STATE(ped, PED_STATE_DRIVE_FLEE_TARGETS)
BREAK
ENDSWITCH
ENDIF
IF NOT IS_PED_IN_THIS_VEHICLE(TargetPedIndex, TargetVehicleIndex)
GO_TO_PED_STATE(ped, PED_STATE_SITTING_IN_VEHICLE_DRIVER)
ENDIF
IF IS_PED_IN_THIS_VEHICLE(PedIndex, TargetVehicleIndex)
AND IS_PED_IN_THIS_VEHICLE(TargetPedIndex, TargetVehicleIndex)
IF IS_ENTITY_AT_COORD(PedIndex, << -804.86, 166.51, 70.56 >>, << 36.0, 24.0, 12.0 >>)
CLEAR_PED_TASKS(PedIndex)
GO_TO_PED_STATE(ped, PED_STATE_COMBAT_ON_FOOT)
ENDIF
ENDIF
BREAK
CASE PED_STATE_DRIVE_FLEE_COPS
IF (ped.bHasTask = FALSE )
CLEAR_PED_TASKS(PedIndex)
PED_INDEX CopPedIndex
CopPedIndex = GET_PED_CLOSEST_PED_FROM_RELATIONSHIP_GROUP(PedIndex, RELGROUPHASH_COP)
IF DOES_ENTITY_EXIST(CopPedIndex)
#IF IS_DEBUG_BUILD
DRAW_DEBUG_LINE(GET_ENTITY_COORDS(PedIndex, FALSE), GET_ENTITY_COORDS(CopPedIndex, FALSE), 255, 255, 255)
#ENDIF
TASK_VEHICLE_MISSION_PED_TARGET(PedIndex, TargetVehicleIndex, CopPedIndex, MISSION_FLEE, 30.0,
DF_SteerAroundObjects | DF_SteerAroundPeds | DF_SteerAroundStationaryCars |
DF_ChangeLanesAroundObstructions | DF_ForceJoinInRoadDirection |
DF_SwerveAroundAllCars, //| DF_UseStringPullingAtJunctions,
400.0, 100.0, FALSE)
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(PedIndex, TRUE)
ped.iTimer = GET_GAME_TIMER()
ELSE
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Not found nearby cops. Fleeing coords.")
#ENDIF
TASK_VEHICLE_MISSION_COORS_TARGET(PedIndex, TargetVehicleIndex, GET_ENTITY_COORDS(TargetVehicleIndex), MISSION_FLEE, 25.0,
DF_SteerAroundObjects | DF_SteerAroundPeds | DF_SteerAroundStationaryCars |
DF_ChangeLanesAroundObstructions | DF_ForceJoinInRoadDirection |
DF_SwerveAroundAllCars, //| DF_UseStringPullingAtJunctions,
400.0, 100.0, FALSE)
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(PedIndex, TRUE)
ped.iTimer = GET_GAME_TIMER()
ENDIF
ped.bHasTask = TRUE
ENDIF
IF IS_PLAYER_PLAYING(PLAYER_ID())
IF NOT IS_PLAYER_WANTED_LEVEL_GREATER(PLAYER_ID(), 0)
GO_TO_PED_STATE(ped, PED_STATE_DRIVE_TO_DESTINATION)
ELSE
SWITCH GET_SCRIPT_TASK_STATUS(PedIndex, SCRIPT_TASK_VEHICLE_MISSION)
CASE PERFORMING_TASK
IF HAS_TIME_PASSED(5000, ped.iTimer)
GO_TO_PED_STATE(ped, PED_STATE_DRIVE_FLEE_COPS)
ENDIF
BREAK
CASE FINISHED_TASK
GO_TO_PED_STATE(ped, PED_STATE_DRIVE_FLEE_COPS)
BREAK
ENDSWITCH
ENDIF
ENDIF
IF NOT IS_PED_IN_THIS_VEHICLE(TargetPedIndex, TargetVehicleIndex)
GO_TO_PED_STATE(ped, PED_STATE_SITTING_IN_VEHICLE_DRIVER)
ENDIF
BREAK
CASE PED_STATE_DRIVE_TO_DESTINATION
IF ( ped.bHasTask = FALSE )
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Ped in PED_STATE_DRIVE_TO_DESTINATION state.")
#ENDIF
IF DOES_ENTITY_EXIST(TargetVehicleIndex)
CALCULATE_PATH_NODES_AREA_FOR_POS(GET_ENTITY_COORDS(TargetVehicleIndex))
REQUEST_PATH_NODES_IN_AREA_THIS_FRAME(fMinX, fMinY, fMaxX, fMaxY)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Calling REQUEST_PATH_NODES_IN_AREA_THIS_FRAME(",
fMinX, ",", fMinY, ",", fMaxX, ",", fMaxY, ").")
#ENDIF
IF ARE_NODES_LOADED_FOR_AREA(fMinX, fMinY, fMaxX, fMaxY)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Path nodes loaded in area (",
fMinX, ",", fMinY, ",", fMaxX, ",", fMaxY, ").")
#ENDIF
CLEAR_PED_TASKS(PedIndex)
TASK_VEHICLE_MISSION_COORS_TARGET(PedIndex, TargetVehicleIndex, vMichaelsHousePosition, MISSION_GOTO, 20.0,
DF_SteerAroundStationaryCars | DF_StopForPeds | DF_StopAtLights |
DF_ChangeLanesAroundObstructions | DF_StopForCars | DF_ForceJoinInRoadDirection, 1.0, 2.0, FALSE)
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(PedIndex, TRUE)
ped.bHasTask = TRUE
ENDIF
ENDIF
ENDIF
IF DOES_ENTITY_EXIST(TargetVehicleIndex)
CALCULATE_PATH_NODES_AREA_FOR_POS(GET_ENTITY_COORDS(TargetVehicleIndex))
REQUEST_PATH_NODES_IN_AREA_THIS_FRAME(fMinX, fMinY, fMaxX, fMaxY)
ENDIF
IF ( bEnemiesPresent = TRUE )
IF ( fDistanceToDestination < 125.0 )
GO_TO_PED_STATE(ped, PED_STATE_DRIVE_FLEE_TARGETS)
ENDIF
ENDIF
IF IS_PED_SITTING_IN_THIS_VEHICLE(PedIndex, TargetVehicleIndex)
IF IS_ENTITY_AT_COORD(TargetVehicleIndex, << -847.36, 159.09, 66.32 >>, << 8.0, 3.5, 3.0 >>)
SET_DRIVE_TASK_CRUISE_SPEED(PedIndex, 10.0) //make the buddy slow down when reaching mansion gate
IF ( bWantedLevelBlockedOnBuddyDrive = FALSE )
IF IS_PLAYER_PLAYING(PLAYER_ID())
IF NOT IS_PLAYER_WANTED_LEVEL_GREATER(PLAYER_ID(), 0) //block wanted level when buddy is driving home
SET_MAX_WANTED_LEVEL(0) //this is stop buddy AI and player becoming wanted
SET_WANTED_LEVEL_MULTIPLIER(0.0) //when they drive into the mansion driveway
SET_CREATE_RANDOM_COPS(FALSE) //since AI has trouble fleeing from there
bWantedLevelBlockedOnBuddyDrive = TRUE //set the wanted level blocked here only
ENDIF
ENDIF
ENDIF
ENDIF
ENDIf
IF NOT IS_PED_IN_THIS_VEHICLE(TargetPedIndex, TargetVehicleIndex)
GO_TO_PED_STATE(ped, PED_STATE_SITTING_IN_VEHICLE_DRIVER)
ENDIF
IF IS_PLAYER_PLAYING(PLAYER_ID())
IF IS_PLAYER_WANTED_LEVEL_GREATER(PLAYER_ID(), 0)
GO_TO_PED_STATE(ped, PED_STATE_DRIVE_FLEE_COPS)
ENDIF
ENDIF
BREAK
CASE PED_STATE_ENTERING_VEHICLE
IF ( ped.bHasTask = FALSE )
IF NOT IS_PED_GROUP_MEMBER(PedIndex, PLAYER_GROUP_ID())
SET_PED_AS_GROUP_MEMBER(PedIndex, PLAYER_GROUP_ID())
SET_PED_GROUP_MEMBER_PASSENGER_INDEX(PedIndex, VS_FRONT_RIGHT)
SET_PED_CAN_TELEPORT_TO_GROUP_LEADER(PedIndex, PLAYER_GROUP_ID(), TRUE)
SET_PED_CONFIG_FLAG(PedIndex, PCF_TeleportToLeaderVehicle, TRUE)
ENDIF
TASK_ENTER_VEHICLE(PedIndex, TargetVehicleIndex, DEFAULT_TIME_BEFORE_WARP, VS_ANY_PASSENGER, PEDMOVE_RUN)
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(PedIndex, TRUE)
ped.bHasTask = TRUE
ENDIF
IF IS_PED_SITTING_IN_THIS_VEHICLE(PedIndex, TargetVehicleIndex)
GO_TO_PED_STATE(ped, PED_STATE_FOLLOWING_PLAYER)
ENDIF
BREAK
CASE PED_STATE_COMBAT_ON_FOOT
IF ( ped.bHasTask = FALSE )
CLEAR_PED_TASKS(PedIndex)
IF IS_PED_GROUP_MEMBER(PedIndex, PLAYER_GROUP_ID())
REMOVE_PED_FROM_GROUP(PedIndex)
ENDIF
SET_PED_COMBAT_ATTRIBUTES(PedIndex, CA_USE_VEHICLE, FALSE)
SET_PED_COMBAT_ATTRIBUTES(PedIndex, CA_LEAVE_VEHICLES, TRUE)
SET_COMBAT_FLOAT(PedIndex, CCF_STRAFE_WHEN_MOVING_CHANCE, 0.9)
SET_COMBAT_FLOAT(PedIndex, CCF_WALK_WHEN_STRAFING_CHANCE, 0.0)
SET_PED_COMBAT_MOVEMENT(PedIndex, CM_DEFENSIVE)
SET_PED_DEFENSIVE_SPHERE_ATTACHED_TO_PED(PedIndex, TargetPedIndex, << 0.0, 0.0, 0.0 >>, 5.0)
TASK_COMBAT_HATED_TARGETS_AROUND_PED(PedIndex, 250.0)
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(PedIndex, FALSE)
ped.bHasTask = TRUE
ENDIF
IF ( bEnemiesPresent = FALSE )
CLEAR_PED_TASKS(PedIndex)
GO_TO_PED_STATE(ped, PED_STATE_FOLLOWING_PLAYER)
ENDIF
IF NOT IS_PED_IN_ANY_VEHICLE(TargetPedIndex)
GO_TO_PED_STATE(ped, PED_STATE_FOLLOWING_PLAYER)
ENDIF
BREAK
CASE PED_STATE_WAITING_FOR_TASK_AFTER_SWITCH
IF ( ped.bHasTask = FALSE )
IF ( bWantedLevelBlockedOnBuddyDrive = TRUE )
SET_MAX_WANTED_LEVEL(5)
SET_CREATE_RANDOM_COPS(TRUE) //unblock wanted level if it was blocked when buddy was driving
SET_WANTED_LEVEL_MULTIPLIER(1.0)
bWantedLevelBlockedOnBuddyDrive = FALSE
ENDIF
ped.bHasTask = TRUE
ENDIF
IF IS_PED_IN_THIS_VEHICLE(PedIndex, TargetVehicleIndex)
IF IS_PED_SITTING_IN_THIS_VEHICLE(PedIndex, TargetVehicleIndex)
SWITCH GET_PED_VEHICLE_SEAT(PedIndex, TargetVehicleIndex)
CASE VS_DRIVER
IF ( bEnemiesPresent = TRUE )
GO_TO_PED_STATE(ped, PED_STATE_DRIVE_FLEE_TARGETS)
ELSE
GO_TO_PED_STATE(ped, PED_STATE_DRIVE_TO_DESTINATION)
ENDIF
BREAK
DEFAULT
GO_TO_PED_STATE(ped, PED_STATE_FOLLOWING_PLAYER)
BREAK
ENDSWITCH
ENDIF
ELSE
GO_TO_PED_STATE(ped, PED_STATE_FOLLOWING_PLAYER)
ENDIF
BREAK
ENDSWITCH
ENDIF
ENDIF
ENDPROC
FUNC BOOL IS_MISSION_STAGE_ESCAPE_GOONS_COMPLETED(INT &iStageProgress)
//don't use locates header J skip
SET_BIT(sLocatesData.iLocatesBitSet, BS_DONT_DO_J_SKIP)
SUPPRESS_CONTEXT_BUTTON_ACTIONS_THIS_FRAME()
DISABLE_CINEMATIC_BONNET_CAMERA_FOR_LOOK_BEHIND_ANIMATION()
IF IS_PLAYER_PLAYING(PLAYER_ID())
SET_ALL_RANDOM_PEDS_FLEE_THIS_FRAME(PLAYER_ID())
ENDIF
MANAGE_GOONS(iGoonsProgress)
IF ( bAllowHotSwap = TRUE )
IF ( bGoonsChaseFinished = TRUE )
IF NOT IS_SELECTOR_CAM_ACTIVE()
IF NOT IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
bAllowHotSwap = FALSE
ELSE
IF IS_PED_SITTING_IN_THIS_VEHICLE(PLAYER_PED_ID(), GET_VEHICLE_PED_IS_USING(PLAYER_PED_ID()))
IF IS_PED_SITTING_IN_VEHICLE_SEAT(PLAYER_PED_ID(), GET_VEHICLE_PED_IS_USING(PLAYER_PED_ID()), VS_DRIVER)
bAllowHotSwap = FALSE
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
IF ( bHotSwapHinted = FALSE )
SET_SELECTOR_PED_HINT(sSelectorPeds, SELECTOR_PED_FRANKLIN, TRUE)
bHotSwapHinted = TRUE
ENDIF
IF ( bHotSwapTriggered = FALSE)
IF NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_HSWITCH2")
IF ( iHotSwapHintTimer = 0 )
iHotSwapHintTimer = GET_GAME_TIMER()
ELSE
IF HAS_TIME_PASSED(30000, iHotSwapHintTimer)
PRINT_HELP("FAM3_HSWITCH", DEFAULT_HELP_TEXT_TIME + 2500)
SET_LABEL_AS_TRIGGERED("FAM3_HSWITCH2", TRUE)
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
MANAGE_CONVERSATIONS_DURING_ESCAPE_GOONS(iConversationProgress)
UPDATE_TRIGGERED_LABEL(sLabelDHOUSE)
UPDATE_TRIGGERED_LABEL(sLabelGETBCK)
UPDATE_TRIGGERED_LABEL(sLabelFLEAVE)
UPDATE_TRIGGERED_LABEL(sLabelMLEAVE)
UPDATE_TRIGGERED_LABEL(sLabelLWANTED)
IF NOT DOES_PARTICLE_FX_LOOPED_EXIST(ptfxDustCloud) //make sure dust particles are created
REQUEST_PTFX_ASSET()
IF HAS_PTFX_ASSET_LOADED()
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Starting particle fx ent_ray_fam3_dust_settle.")
#ENDIF
ptfxDustCloud = START_PARTICLE_FX_LOOPED_AT_COORD("ent_ray_fam3_dust_settle", << -1016.0, 642.0, 141.0 >>, << 0.0, 0.0, 0.0 >>)
ENDIF
ENDIF
SWITCH GET_CURRENT_PLAYER_PED_ENUM()
CASE CHAR_MICHAEL //player playing as Michael, update Franklin
//update Franklin's tasks
MANAGE_OTHER_PLAYER_PED_DURING_ESCAPE_GOONS(GET_PED_INDEX(CHAR_FRANKLIN), psFranklin, PLAYER_PED_ID(),
GET_VEHICLE_PED_IS_USING(PLAYER_PED_ID()), bGoonsChaseInProgress)
//display warning when player is leaving Franklin behind
IF NOT DOES_BLIP_EXIST(sLocatesData.LocationBlip)
AND NOT DOES_BLIP_EXIST(sLocatesData.BuddyBlipID[0])
IF psFranklin.fDistanceToTarget > BUDDY_SEPARATION_DIST
IF NOT DOES_BLIP_EXIST(psFranklin.BlipIndex)
psFranklin.BlipIndex = CREATE_BLIP_ON_ENTITY(GET_PED_INDEX(CHAR_FRANKLIN), TRUE)
ENDIF
IF NOT HAS_LABEL_BEEN_TRIGGERED(sLabelFLEAVE)
PRINT_GOD_TEXT_ADVANCED(sLabelFLEAVE, DEFAULT_GOD_TEXT_TIME, TRUE)
ENDIF
ENDIF
IF DOES_BLIP_EXIST(psFranklin.BlipIndex)
IF ( psFranklin.fDistanceToTarget <= BUDDY_SEPARATION_DIST / 3 )
IF IS_THIS_PRINT_BEING_DISPLAYED(sLabelFLEAVE)
CLEAR_PRINTS()
ENDIF
REMOVE_BLIP(psFranklin.BlipIndex)
ENDIF
ENDIF
ENDIF
IF ( bGoonsChaseInProgress = TRUE )
IF NOT IS_AUDIO_SCENE_ACTIVE("FAMILY_3_ESCAPE_AS_MICHAEL")
START_AUDIO_SCENE("FAMILY_3_ESCAPE_AS_MICHAEL")
ENDIF
IF IS_AUDIO_SCENE_ACTIVE("FAMILY_3_ESCAPE_AS_FRANKLIN")
STOP_AUDIO_SCENE("FAMILY_3_ESCAPE_AS_FRANKLIN")
ENDIF
ENDIF
BREAK
CASE CHAR_FRANKLIN //player playing as Franklin, update Michael
//update Michael's tasks
MANAGE_OTHER_PLAYER_PED_DURING_ESCAPE_GOONS(GET_PED_INDEX(CHAR_MICHAEL), psFranklin, PLAYER_PED_ID(),
GET_VEHICLE_PED_IS_USING(PLAYER_PED_ID()), bGoonsChaseInProgress)
//display warning when player is leaving Michael behind
IF DOES_BLIP_EXIST(sLocatesData.LocationBlip)
AND NOT DOES_BLIP_EXIST(sLocatesData.BuddyBlipID[0])
IF psFranklin.fDistanceToTarget > BUDDY_SEPARATION_DIST
IF NOT DOES_BLIP_EXIST(psMichael.BlipIndex)
psMichael.BlipIndex = CREATE_BLIP_ON_ENTITY(GET_PED_INDEX(CHAR_MICHAEL), TRUE)
ENDIF
IF NOT HAS_LABEL_BEEN_TRIGGERED(sLabelMLEAVE)
PRINT_GOD_TEXT_ADVANCED(sLabelMLEAVE, DEFAULT_GOD_TEXT_TIME, TRUE)
ENDIF
ENDIF
IF DOES_BLIP_EXIST(psMichael.BlipIndex)
IF ( psMichael.fDistanceToTarget <= BUDDY_SEPARATION_DIST / 3 )
IF IS_THIS_PRINT_BEING_DISPLAYED(sLabelMLEAVE)
CLEAR_PRINTS()
ENDIF
REMOVE_BLIP(psMichael.BlipIndex)
ENDIF
ENDIF
ENDIF
IF ( bGoonsChaseInProgress = TRUE )
IF NOT IS_AUDIO_SCENE_ACTIVE("FAMILY_3_ESCAPE_AS_FRANKLIN")
START_AUDIO_SCENE("FAMILY_3_ESCAPE_AS_FRANKLIN")
ENDIF
IF IS_AUDIO_SCENE_ACTIVE("FAMILY_3_ESCAPE_AS_MICHAEL")
STOP_AUDIO_SCENE("FAMILY_3_ESCAPE_AS_MICHAEL")
ENDIF
ENDIF
BREAK
ENDSWITCH
IF ( bGoonsChaseFinished = TRUE )
IF IS_PLAYER_BROWSING_ITEMS_IN_ANY_SHOP()
OR IS_PLAYER_CHANGING_CLOTHES()
IF HAS_THIS_CUTSCENE_LOADED("family_3_ext")
OR HAS_CUTSCENE_LOADED()
OR IS_CUTSCENE_ACTIVE()
REMOVE_CUTSCENE()
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Player browsing items in a shop or changing clothes. Removing cutscene.")
#ENDIF
ENDIF
ELSE
IF GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), vMichaelsHousePosition) < DEFAULT_CUTSCENE_LOAD_DIST
REQUEST_MODEL(BALLER)
REQUEST_CUTSCENE("family_3_ext")
IF CAN_REQUEST_ASSETS_FOR_CUTSCENE_ENTITY()
IF NOT IS_PED_INJURED(GET_PED_INDEX(CHAR_MICHAEL))
SET_CUTSCENE_PED_COMPONENT_VARIATION_FROM_PED("Michael", GET_PED_INDEX(CHAR_MICHAEL))
ENDIF
IF NOT IS_PED_INJURED(GET_PED_INDEX(CHAR_FRANKLIN))
SET_CUTSCENE_PED_COMPONENT_VARIATION_FROM_PED("Franklin", GET_PED_INDEX(CHAR_FRANKLIN))
ENDIF
bCutsceneAssetsRequested = TRUE
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Setting cutscene ped components for cutscene ped Michael and Franklin from peds during stage ", GET_MISSION_STAGE_NAME_FOR_DEBUG(eMissionStage), ".")
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Setting bCutsceneAssetsRequested to ", bCutsceneAssetsRequested, ".")
#ENDIF
ENDIF
ELSE
IF HAS_THIS_CUTSCENE_LOADED("family_3_ext")
OR HAS_CUTSCENE_LOADED()
OR IS_CUTSCENE_ACTIVE()
REMOVE_CUTSCENE()
SET_MODEL_AS_NO_LONGER_NEEDED(BALLER)
bCutsceneAssetsRequested = FALSE
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Player too far away from destination to keep cutscene in memory. Removing cutscene.")
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Setting bCutsceneAssetsRequested to ", bCutsceneAssetsRequested, ".")
#ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
SWITCH iStageProgress
CASE 0
IF ( bGoonsChaseInProgress = FALSE ) //goons chase not in progress
IF ( bRunLocatesHeaderCheck = TRUE )
IF ( bGoonsChaseFinished = FALSE ) //goons chase not finished
//display this initially but also progress the mission if the player gets to the house without spawning goons
IF IS_PLAYER_AT_ANGLED_AREA_WITH_BUDDY_ANY_MEANS(sLocatesData, vMichaelsHousePosition,
<< -824.81, 185.38, 69.95 >>,
<< -820.61, 179.79, 73.64 >>, 8.5, TRUE,
GET_PED_INDEX(CHAR_FRANKLIN), sLabelDHOUSE,
sLabelFLEAVE, FALSE, TRUE)
IF IS_PED_SITTING_IN_ANY_VEHICLE(PLAYER_PED_ID())
IF IS_VEHICLE_ON_ALL_WHEELS(GET_VEHICLE_PED_IS_USING(PLAYER_PED_ID()))
KILL_ANY_CONVERSATION()
KILL_FACE_TO_FACE_CONVERSATION() //kill conversations and let last line play out
bStopScriptedConversations = TRUE
SETTIMERA(0) //start backup timer in case the conversations are busted by streaming
bGoonsChaseFinished = TRUE //consider the chase ended if the player gets to the house before goons spawn
iStageProgress++
ENDIF
ELSE
KILL_ANY_CONVERSATION()
KILL_FACE_TO_FACE_CONVERSATION() //kill conversations and let last line play out
bStopScriptedConversations = TRUE
SETTIMERA(0) //start backup timer in case the conversations are busted by streaming
bGoonsChaseFinished = TRUE //consider the chase ended if the player gets to the house before goons spawn
iStageProgress++
ENDIF
ENDIF
ELSE //goons chase finished, goons lost or killed
IF IS_AUDIO_SCENE_ACTIVE("FAMILY_3_ESCAPE_AS_MICHAEL")
STOP_AUDIO_SCENE("FAMILY_3_ESCAPE_AS_MICHAEL")
ENDIF
IF IS_AUDIO_SCENE_ACTIVE("FAMILY_3_ESCAPE_AS_FRANKLIN")
STOP_AUDIO_SCENE("FAMILY_3_ESCAPE_AS_FRANKLIN")
ENDIF
IF NOT IS_AUDIO_SCENE_ACTIVE("FAMILY_3_DRIVE_HOME")
IF DOES_BLIP_EXIST(sLocatesData.LocationBlip)
START_AUDIO_SCENE("FAMILY_3_DRIVE_HOME")
ENDIF
ENDIF
IF DOES_BLIP_EXIST(psFranklin.BlipIndex) //remove buddy ped blips, locates header
REMOVE_BLIP(psFranklin.BlipIndex) //will handle the blips once goons are lost
ENDIF
IF DOES_BLIP_EXIST(psMichael.BlipIndex)
REMOVE_BLIP(psMichael.BlipIndex)
ENDIF
IF IS_THIS_HELP_MESSAGE_BEING_DISPLAYED("FAM3_HSWITCH")
CLEAR_HELP() //remove switch help text if still on screen
ENDIF
IF NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_HSTAT1")
IF HAS_LABEL_BEEN_TRIGGERED("FAM3_STATA")
OR HAS_LABEL_BEEN_TRIGGERED("FAM3_STATB")
IF ( bStatConversationFinished = TRUE )
IF DOES_BLIP_EXIST(sLocatesData.LocationBlip)
PRINT_HELP("FAM3_HSTAT1", DEFAULT_HELP_TEXT_TIME + 2500)
SET_LABEL_AS_TRIGGERED("FAM3_HSTAT1", TRUE)
ENDIF
ENDIF
ENDIF
ELSE
IF NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_HSTAT2")
IF DOES_BLIP_EXIST(sLocatesData.LocationBlip)
IF NOT IS_THIS_HELP_MESSAGE_BEING_DISPLAYED("FAM3_HSTAT1")
PRINT_HELP("FAM3_HSTAT2", DEFAULT_HELP_TEXT_TIME + 2500)
SET_LABEL_AS_TRIGGERED("FAM3_HSTAT2", TRUE)
ENDIF
ENDIF
ENDIF
ENDIF
//just display the blip and locates checks for correct player ped
SWITCH GET_CURRENT_PLAYER_PED_ENUM()
CASE CHAR_MICHAEL
//just display locates header check
IS_PLAYER_AT_LOCATION_WITH_BUDDY_ANY_MEANS(sLocatesData, vMichaelsHousePosition,
DEFAULT_LOCATES_SIZE_VECTOR(), TRUE,
GET_PED_INDEX(CHAR_FRANKLIN), sLabelDHOUSE,
sLabelFLEAVE, FALSE, TRUE, NOT bLoseWantedDisplayed)
BREAK
CASE CHAR_FRANKLIN
//just display locates header check
IS_PLAYER_AT_LOCATION_WITH_BUDDY_ANY_MEANS(sLocatesData, vMichaelsHousePosition,
DEFAULT_LOCATES_SIZE_VECTOR(), TRUE,
GET_PED_INDEX(CHAR_MICHAEL), sLabelDHOUSE,
sLabelMLEAVE, FALSE, TRUE, NOT bLoseWantedDisplayed)
BREAK
ENDSWITCH
IF ( bLoseWantedDisplayed = FALSE ) //player is not wanted
IF NOT DOES_BLIP_EXIST(sLocatesData.LocationBlip)
IF IS_PLAYER_WANTED_LEVEL_GREATER(PLAYER_ID(), 0)
IF HAS_LABEL_BEEN_TRIGGERED(sLabelLWANTED)
bLoseWantedDisplayed = TRUE
ENDIF
ENDIF
ENDIF
ELSE //player is wanted
IF DOES_BLIP_EXIST(sLocatesData.LocationBlip)
IF NOT IS_PLAYER_WANTED_LEVEL_GREATER(PLAYER_ID(), 0)
sLabelLWANTED = "LOSE_WANTED"
bLoseWantedDisplayed = FALSE
ENDIF
ENDIF
ENDIF
//do the check to progress the stage here
IF DOES_BLIP_EXIST(sLocatesData.LocationBlip)
//both peds in vehicle angled area
IF ARE_PEDS_IN_THE_SAME_VEHICLE(GET_PED_INDEX(CHAR_MICHAEL), GET_PED_INDEX(CHAR_FRANKLIN))
IF IS_ENTITY_IN_ANGLED_AREA(GET_PED_INDEX(CHAR_MICHAEL), << -824.81, 185.38, 69.95 >>, << -820.61, 179.79, 73.64 >>, 8.5) //7.5
AND IS_ENTITY_IN_ANGLED_AREA(GET_PED_INDEX(CHAR_FRANKLIN), << -824.81, 185.38, 69.95 >>, << -820.61, 179.79, 73.64 >>, 8.5) //7.5
IF IS_VEHICLE_ON_ALL_WHEELS(GET_VEHICLE_PED_IS_USING(PLAYER_PED_ID()))
CLEAR_MISSION_LOCATION_TEXT_AND_BLIPS(sLocatesData)
KILL_ANY_CONVERSATION()
KILL_FACE_TO_FACE_CONVERSATION() //kill conversations and let last line play out
bStopScriptedConversations = TRUE
SETTIMERA(0) //start backup timer in case the conversations are busted by streaming
iStageProgress++
ENDIF
ENDIF
ELSE //one of the peds on foot, while the other on foot
IF IS_ENTITY_AT_COORD(GET_PED_INDEX(CHAR_MICHAEL), << -823.28, 180.69, 71.63 >>, << 8.0, 8.0, 3.0 >>)
AND IS_ENTITY_AT_COORD(GET_PED_INDEX(CHAR_FRANKLIN), << -823.28, 180.69, 71.63 >>, << 8.0, 8.0, 3.0 >>)
IF IS_PED_SITTING_IN_ANY_VEHICLE(PLAYER_PED_ID())
IF IS_VEHICLE_ON_ALL_WHEELS(GET_VEHICLE_PED_IS_USING(PLAYER_PED_ID()))
CLEAR_MISSION_LOCATION_TEXT_AND_BLIPS(sLocatesData)
KILL_ANY_CONVERSATION()
KILL_FACE_TO_FACE_CONVERSATION() //kill conversations and let last line play out
bStopScriptedConversations = TRUE
SETTIMERA(0) //start backup timer in case the conversations are busted by streaming
iStageProgress++
ENDIF
ELSE
CLEAR_MISSION_LOCATION_TEXT_AND_BLIPS(sLocatesData)
KILL_ANY_CONVERSATION()
KILL_FACE_TO_FACE_CONVERSATION() //kill conversations and let last line play out
bStopScriptedConversations = TRUE
SETTIMERA(0) //start backup timer in case the conversations are busted by streaming
iStageProgress++
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ELSE
//not running locates header check when being chased by the goons
ENDIF
ELSE //goons chase in progress
IF ( bRunLocatesHeaderCheck = TRUE ) //disable locates header checks when goons chase starts
//clear locates header blip and text
CLEAR_MISSION_LOCATION_TEXT_AND_BLIPS(sLocatesData)
//set the flag again to false because clearing locates header stuff sets the flag to TRUE
SET_PED_CONFIG_FLAG(GET_PED_INDEX(CHAR_MICHAEL), PCF_WillFlyThroughWindscreen, FALSE)
SET_PED_CONFIG_FLAG(GET_PED_INDEX(CHAR_FRANKLIN), PCF_WillFlyThroughWindscreen, FALSE)
bRunLocatesHeaderCheck = FALSE
ENDIF
//check if player fired at least once as passenger
IF ( bPlayerFiredAsPassenger = FALSE )
IF ARE_PEDS_IN_THE_SAME_VEHICLE(GET_PED_INDEX(CHAR_MICHAEL), GET_PED_INDEX(CHAR_FRANKLIN))
IF IS_PED_SITTING_IN_VEHICLE(PLAYER_PED_ID(), GET_VEHICLE_PED_IS_USING(PLAYER_PED_ID()))
IF ( GET_PED_VEHICLE_SEAT(PLAYER_PED_ID(), GET_VEHICLE_PED_IS_USING(PLAYER_PED_ID())) <> VS_DRIVER )
IF IS_PED_SHOOTING(PLAYER_PED_ID())
bPlayerFiredAsPassenger = TRUE
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
IF ( bCombatAllowed = FALSE ) //allow Franklin to go to comabt, which will allow hot swap afterwards
IF ( bGoonsAttacked = FALSE )
IF IS_PED_SHOOTING_AT_ENTITY(PLAYER_PED_ID(), psEnemyGoonsCar0[0].PedIndex, TRUE)
OR IS_PED_SHOOTING_AT_ENTITY(PLAYER_PED_ID(), psEnemyGoonsCar0[1].PedIndex, TRUE)
OR IS_PED_SHOOTING_AT_ENTITY(PLAYER_PED_ID(), psEnemyGoonsCar0[0].PedIndex, TRUE)
OR IS_PED_SHOOTING_AT_ENTITY(PLAYER_PED_ID(), psEnemyGoonsCar1[1].PedIndex, TRUE)
bGoonsAttacked = TRUE
ENDIF
ENDIF
IF HAS_LABEL_BEEN_TRIGGERED("FAM3_GCSGS")
OR HAS_LABEL_BEEN_TRIGGERED("FAM3_GCSGT")
OR ( bGoonsAttacked = TRUE )
bCombatAllowed = TRUE
ENDIF
ENDIF
IF NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_LGOONS")
IF HAS_LABEL_BEEN_TRIGGERED("FAM3_GCSFA")
OR HAS_LABEL_BEEN_TRIGGERED("FAM3_GCSFB")
IF NOT IS_ANY_TEXT_BEING_DISPLAYED(sLocatesData, IAT_IGNORE_GOD_TEXT_IF_SUBTITLES_OFF)
PRINT_GOD_TEXT_ADVANCED("FAM3_LGOONS", DEFAULT_GOD_TEXT_TIME, TRUE)
ENDIF
ENDIF
ELSE
IF ( bCombatAllowed = TRUE )
bAllowHotSwap = TRUE //enable hotswap by default
IF IS_PED_IN_ANY_VEHICLE(GET_PED_INDEX(CHAR_MICHAEL)) //check what vehicle Michael is in
VEHICLE_INDEX MichaelVehicleIndex
MichaelVehicleIndex = GET_VEHICLE_PED_IS_IN(GET_PED_INDEX(CHAR_MICHAEL), TRUE)
IF DOES_ENTITY_EXIST(MichaelVehicleIndex)
IF NOT IS_THIS_MODEL_A_CAR(GET_ENTITY_MODEL(MichaelVehicleIndex)) //allow only cars
AND NOT IS_THIS_MODEL_A_BIKE(GET_ENTITY_MODEL(MichaelVehicleIndex)) //allow only bikes
AND NOT IS_THIS_MODEL_A_QUADBIKE(GET_ENTITY_MODEL(MichaelVehicleIndex)) //allow only quadbikes
bAllowHotSwap = FALSE
ENDIF
ENDIF
ENDIF
IF IS_PED_IN_ANY_VEHICLE(GET_PED_INDEX(CHAR_FRANKLIN)) //check what vehicle Franklin is in
VEHICLE_INDEX FranklinVehicleIndex
FranklinVehicleIndex = GET_VEHICLE_PED_IS_IN(GET_PED_INDEX(CHAR_FRANKLIN), TRUE)
IF DOES_ENTITY_EXIST(FranklinVehicleIndex)
IF NOT IS_THIS_MODEL_A_CAR(GET_ENTITY_MODEL(FranklinVehicleIndex)) //allow only cars
AND NOT IS_THIS_MODEL_A_BIKE(GET_ENTITY_MODEL(FranklinVehicleIndex)) //allow only bikes
AND NOT IS_THIS_MODEL_A_QUADBIKE(GET_ENTITY_MODEL(FranklinVehicleIndex)) //allow only quadbikes
bAllowHotSwap = FALSE
ENDIF
ENDIF
ENDIF
IF NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_HSWITCH")
IF ( bAllowHotSwap = TRUE )
//display floating help text above the switch icon
PRINT_HELP("FAM3_HSWITCH", DEFAULT_HELP_TEXT_TIME + 2500)
SET_LABEL_AS_TRIGGERED("FAM3_HSWITCH", TRUE)
ENDIF
ELSE
IF IS_THIS_HELP_MESSAGE_BEING_DISPLAYED("FAM3_HSWITCH")
IF IS_SELECTOR_CAM_ACTIVE() //remove switch help text when switch is in progress
OR IS_PLAYER_SWITCH_IN_PROGRESS()
OR bHotSwapTriggered = TRUE //used in first person switch as we're not running the switch cam
CLEAR_HELP()
ENDIF
ENDIF
//help text about shooting as passenger in vehicle
IF NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_HPASS1")
IF ARE_PEDS_IN_THE_SAME_VEHICLE(GET_PED_INDEX(CHAR_MICHAEL), GET_PED_INDEX(CHAR_FRANKLIN))
IF IS_PED_SITTING_IN_VEHICLE(PLAYER_PED_ID(), GET_VEHICLE_PED_IS_USING(PLAYER_PED_ID()))
IF ( GET_PED_VEHICLE_SEAT(PLAYER_PED_ID(), GET_VEHICLE_PED_IS_USING(PLAYER_PED_ID())) <> VS_DRIVER )
IF NOT IS_HELP_MESSAGE_BEING_DISPLAYED()
PRINT_HELP("FAM3_HPASS1", DEFAULT_HELP_TEXT_TIME + 2500)
SET_LABEL_AS_TRIGGERED("FAM3_HPASS1", TRUE)
ENDIF
ENDIF
ENDIF
ENDIF
ELSE
//help text about switching weapons in vehicle
IF NOT HAS_LABEL_BEEN_TRIGGERED("FAM3_HPASS2")
IF ARE_PEDS_IN_THE_SAME_VEHICLE(GET_PED_INDEX(CHAR_MICHAEL), GET_PED_INDEX(CHAR_FRANKLIN))
IF IS_PED_SITTING_IN_VEHICLE(PLAYER_PED_ID(), GET_VEHICLE_PED_IS_USING(PLAYER_PED_ID()))
IF ( GET_PED_VEHICLE_SEAT(PLAYER_PED_ID(), GET_VEHICLE_PED_IS_USING(PLAYER_PED_ID())) <> VS_DRIVER )
IF ( bPlayerFiredAsPassenger = TRUE )
IF HAS_PED_GOT_WEAPON(PLAYER_PED_ID(), WEAPONTYPE_MICROSMG)
OR HAS_PED_GOT_WEAPON(PLAYER_PED_ID(), WEAPONTYPE_SAWNOFFSHOTGUN)
OR HAS_PED_GOT_WEAPON(PLAYER_PED_ID(), WEAPONTYPE_COMBATPISTOL)
OR HAS_PED_GOT_WEAPON(PLAYER_PED_ID(), WEAPONTYPE_APPISTOL)
OR HAS_PED_GOT_WEAPON(PLAYER_PED_ID(), WEAPONTYPE_STUNGUN)
OR HAS_PED_GOT_WEAPON(PLAYER_PED_ID(), WEAPONTYPE_GRENADE)
OR HAS_PED_GOT_WEAPON(PLAYER_PED_ID(), WEAPONTYPE_SMOKEGRENADE)
OR HAS_PED_GOT_WEAPON(PLAYER_PED_ID(), WEAPONTYPE_STICKYBOMB)
OR HAS_PED_GOT_WEAPON(PLAYER_PED_ID(), WEAPONTYPE_MOLOTOV)
IF NOT IS_HELP_MESSAGE_BEING_DISPLAYED()
PRINT_HELP(PICK_STRING(IS_USING_KEYBOARD_AND_MOUSE(PLAYER_CONTROL), "FAM3_HPASS3", "FAM3_HPASS2"), DEFAULT_HELP_TEXT_TIME + 2500)
SET_LABEL_AS_TRIGGERED("FAM3_HPASS2", TRUE)
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
BREAK
CASE 1
IF IS_PED_SITTING_IN_ANY_VEHICLE(PLAYER_PED_ID())
IF ( bVehicleReversed = FALSE )
IF IS_VEHICLE_REVERSING(GET_VEHICLE_PED_IS_USING(PLAYER_PED_ID()))
bVehicleReversed = TRUE
ENDIF
ENDIF
IF BRING_VEHICLE_TO_HALT_AND_DISABLE_VEH_CONTROLS(GET_VEHICLE_PED_IS_USING(PLAYER_PED_ID()), 2.0)
IF NOT IS_SCRIPTED_CONVERSATION_ONGOING() //check if scripted conversations are not ongoing using native command
OR NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED() //check if any conversations are not ongoing using script command
OR ( TIMERA() > 5000 ) //check backup timer in case the conversations are busted by streaming
CALCULATE_VEHICLE_EXIT_DELAYS()
SEQUENCE_INDEX SequenceIndex
CLEAR_SEQUENCE_TASK(SequenceIndex)
OPEN_SEQUENCE_TASK(SequenceIndex)
TASK_LEAVE_ANY_VEHICLE(NULL, iMichaelsVehicleExitDelay)
TASK_FOLLOW_NAV_MESH_TO_COORD(NULL, << -819.05, 177.24, 70.83 >>, PEDMOVE_WALK, DEFAULT_TIME_BEFORE_WARP * 3)
CLOSE_SEQUENCE_TASK(SequenceIndex)
TASK_PERFORM_SEQUENCE(GET_PED_INDEX(CHAR_MICHAEL), SequenceIndex)
CLEAR_SEQUENCE_TASK(SequenceIndex)
CLEAR_SEQUENCE_TASK(SequenceIndex)
OPEN_SEQUENCE_TASK(SequenceIndex)
TASK_LEAVE_ANY_VEHICLE(NULL, iFranklinsVehicleExitDelay)
TASK_FOLLOW_NAV_MESH_TO_COORD(NULL, << -819.05, 177.24, 70.83 >>, PEDMOVE_WALK, DEFAULT_TIME_BEFORE_WARP * 3)
CLOSE_SEQUENCE_TASK(SequenceIndex)
TASK_PERFORM_SEQUENCE(GET_PED_INDEX(CHAR_FRANKLIN), SequenceIndex)
CLEAR_SEQUENCE_TASK(SequenceIndex)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Peds CHAR_MICHAEL and CHAR_FRANKLIN tasked to leave any vehicle.")
#ENDIF
bPedsTaskedToLeaveAnyVehicle = TRUE
iStageProgress++
ENDIF
ENDIF
ELSE
IF NOT IS_SCRIPTED_CONVERSATION_ONGOING() //check if scripted conversations are not ongoing using native command
OR NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED() //check if any conversations are not ongoing using script command
OR ( TIMERA() > 5000 ) //check backup timer in case the conversations are busted by streaming
iStageProgress++
ENDIF
ENDIF
BREAK
CASE 2
IF NOT IS_PED_IN_ANY_VEHICLE(GET_PED_INDEX(CHAR_MICHAEL))
AND NOT IS_PED_IN_ANY_VEHICLE(GET_PED_INDEX(CHAR_FRANKLIN))
IF NOT IS_SCRIPTED_CONVERSATION_ONGOING() //check if scripted conversations are not ongoing using native command
OR NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED() //check if any conversations are not ongoing using script command
OR ( TIMERA() > 5000 ) //check backup timer in case the conversations are busted by streaming
IF ( bCutsceneAssetsRequested = TRUE ) //progress if cutscene ped variations were requested
//otherwise cutscene might play with default ped variations
REMOVE_ENTITY_FROM_AUDIO_MIX_GROUP(GET_PED_INDEX(CHAR_MICHAEL))
REMOVE_ENTITY_FROM_AUDIO_MIX_GROUP(GET_PED_INDEX(CHAR_FRANKLIN))
STOP_AUDIO_SCENE("FAMILY_3_DRIVE_HOME")
IF DOES_PARTICLE_FX_LOOPED_EXIST(ptfxDustCloud)
REMOVE_PARTICLE_FX(ptfxDustCloud)
ENDIF
REMOVE_PTFX_ASSET()
RETURN TRUE
ENDIF
ENDIF
ELSE
IF ( bPedsTaskedToLeaveAnyVehicle = FALSE )
CALCULATE_VEHICLE_EXIT_DELAYS()
SEQUENCE_INDEX SequenceIndex
IF IS_PED_IN_ANY_VEHICLE(GET_PED_INDEX(CHAR_MICHAEL))
IF GET_SCRIPT_TASK_STATUS(GET_PED_INDEX(CHAR_MICHAEL), SCRIPT_TASK_PERFORM_SEQUENCE) != PERFORMING_TASK
CLEAR_SEQUENCE_TASK(SequenceIndex)
OPEN_SEQUENCE_TASK(SequenceIndex)
TASK_LEAVE_ANY_VEHICLE(NULL, iMichaelsVehicleExitDelay)
TASK_FOLLOW_NAV_MESH_TO_COORD(NULL, << -819.05, 177.24, 70.83 >>, PEDMOVE_WALK, DEFAULT_TIME_BEFORE_WARP * 3)
CLOSE_SEQUENCE_TASK(SequenceIndex)
TASK_PERFORM_SEQUENCE(GET_PED_INDEX(CHAR_MICHAEL), SequenceIndex)
CLEAR_SEQUENCE_TASK(SequenceIndex)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Retasking CHAR_MICHAEL to leave any vehicle.")
#ENDIF
ENDIF
ENDIF
IF IS_PED_IN_ANY_VEHICLE(GET_PED_INDEX(CHAR_MICHAEL))
IF GET_SCRIPT_TASK_STATUS(GET_PED_INDEX(CHAR_MICHAEL), SCRIPT_TASK_PERFORM_SEQUENCE) != PERFORMING_TASK
CLEAR_SEQUENCE_TASK(SequenceIndex)
OPEN_SEQUENCE_TASK(SequenceIndex)
TASK_LEAVE_ANY_VEHICLE(NULL, iFranklinsVehicleExitDelay)
TASK_FOLLOW_NAV_MESH_TO_COORD(NULL, << -819.05, 177.24, 70.83 >>, PEDMOVE_WALK, DEFAULT_TIME_BEFORE_WARP * 3)
CLOSE_SEQUENCE_TASK(SequenceIndex)
TASK_PERFORM_SEQUENCE(GET_PED_INDEX(CHAR_FRANKLIN), SequenceIndex)
CLEAR_SEQUENCE_TASK(SequenceIndex)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Retasking CHAR_FRANKLIN to leave any vehicle.")
#ENDIF
ENDIF
ENDIF
bPedsTaskedToLeaveAnyVehicle = TRUE
ENDIF
ENDIF
BREAK
ENDSWITCH
RETURN FALSE
ENDFUNC
#IF IS_DEBUG_BUILD
FUNC BOOL IS_MISSION_STAGE_DEBUG_RECORD_CHASE_COMPLETED(INT &iStageProgress)
SWITCH iStageProgress
CASE 0
IF IS_VEHICLE_DRIVEABLE(vsCoachsCar.VehicleIndex)
SET_PED_INTO_VEHICLE(PLAYER_PED_ID(), vsCoachsCar.VehicleIndex)
SET_ENTITY_INVINCIBLE(vsCoachsCar.VehicleIndex, TRUE)
SET_VEHICLE_CAN_BE_VISIBLY_DAMAGED(vsCoachsCar.VehicleIndex, FALSE)
ENDIF
#IF IS_DEBUG_BUILD
INIT_UBER_RECORDING(sUberRecordingFile)
#ENDIF
INSTANTLY_FILL_VEHICLE_POPULATION()
iStageProgress++
BREAK
CASE 1
#IF IS_DEBUG_BUILD
UPDATE_UBER_RECORDING()
#ENDIF
BREAK
ENDSWITCH
RETURN FALSE
ENDFUNC
FUNC BOOL IS_MISSION_STAGE_DEBUG_PLAYBACK_CHASE_COMPLETED(INT &iStageProgress)
SWITCH iStageProgress
CASE 0
IF IS_VEHICLE_DRIVEABLE(vsCoachsCar.VehicleIndex)
SET_PED_INTO_VEHICLE(PLAYER_PED_ID(), vsCoachsCar.VehicleIndex)
SET_ENTITY_INVINCIBLE(vsCoachsCar.VehicleIndex, TRUE)
SET_VEHICLE_CAN_BE_VISIBLY_DAMAGED(vsCoachsCar.VehicleIndex, FALSE)
ENDIF
INITIALISE_UBER_PLAYBACK(sVehicleRecordingsFile, vsCoachsCar.iRecordingNumber)
INITIALISE_UBER_ARRAY()
iStageProgress++
BREAK
CASE 1
IF IS_VEHICLE_DRIVEABLE(vsCoachsCar.VehicleIndex)
IF IS_PLAYBACK_GOING_ON_FOR_VEHICLE(vsCoachsCar.VehicleIndex)
DRAW_DEBUG_TEXT_ABOVE_ENTITY(vsCoachsCar.VehicleIndex, GET_STRING_FROM_FLOAT(GET_TIME_POSITION_IN_RECORDING(vsCoachsCar.VehicleIndex)), 1.25)
ENDIF
ENDIF
UPDATE_UBER_PLAYBACK(vsCoachsCar.VehicleIndex, 1.0)
BREAK
ENDSWITCH
RETURN FALSE
ENDFUNC
#ENDIF
//|============================= END MISSION STAGES FUNCTIONS ============================|
//|=================================== MAIN SCRIPT LOOP ==================================|
SCRIPT
SET_MISSION_FLAG(TRUE)
//check for death or arrest
IF HAS_FORCE_CLEANUP_OCCURRED()
Mission_Flow_Mission_Force_Cleanup()
CLEANUP_RAYFIRE_MAP_OBJECT(TRUE, TRUE)
MISSION_CLEANUP()
TERMINATE_THIS_THREAD()
ENDIF
#IF IS_DEBUG_BUILD
CREATE_DEBUG_MISSION_STAGE_MENU()
CREATE_DEBUG_WIDGETS()
#ENDIF
IF IS_REPLAY_IN_PROGRESS()
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Mission replay is in progress.")
#ENDIF
SET_MISSION_STAGE_FOR_REPLAY(eMissionStage, Get_Replay_Mid_Mission_Stage())
bReplayFlag = TRUE
//handle shitskip message
IF ( g_bShitSkipAccepted = TRUE )
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Shitskip accepted by the player.")
#ENDIF
eMissionStage = GET_NEXT_MISSION_STAGE(eMissionStage)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Shitskip changed mission stage to ", GET_MISSION_STAGE_NAME_FOR_DEBUG(eMissionStage), ".")
#ENDIF
ELSE
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Shitskip not triggered.")
#ENDIF
ENDIF
ELSE
SET_REPLAY_MID_MISSION_STAGE_WITH_NAME(ENUM_TO_INT(MID_MISSION_STAGE_CAR_CHASE), "CAR CHASE", FALSE)
ENDIF
IF IS_REPEAT_PLAY_ACTIVE()
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Repeat play is active.")
#ENDIF
IF NOT IS_REPLAY_IN_PROGRESS()
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Repeat play is active and mission replay is not in progress.")
#ENDIF
eMissionStage = MISSION_STAGE_CUTSCENE_INTRO
bReplayFlag = TRUE
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Setting local replay flag to TRUE for stage loading.")
#ENDIF
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Mission stage is ", GET_MISSION_STAGE_NAME_FOR_DEBUG(eMissionStage), " for repeat play and no mission replay.")
#ENDIF
ELSE
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Repeat play is active and mission replay is in progress.")
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Mission stage is ", GET_MISSION_STAGE_NAME_FOR_DEBUG(eMissionStage), " for repeat play and mission replay.")
#ENDIF
ENDIF
ENDIF
WHILE TRUE
SET_MUST_LEAVE_AREA_VEHICLE_GEN_FLAG(VEHGEN_MICHAEL_SAVEHOUSE)
//check each frame if mission is failed due to fail conditions
//check only if mission stage loading has finished
IF ( bLoadingFlag = TRUE )
RUN_FAIL_CHECKS(eMissionStage, eMissionFail)
ENDIF
//check each frame for hotswap if it is allowed
IF ( bAllowHotSwap = TRUE )
RUN_HOTSWAP()
ENDIF
REPLAY_CHECK_FOR_EVENT_THIS_FRAME("M_MarriageCounselling")
IF iReplayCameraWarpTimer > GET_GAME_TIMER()
REPLAY_DISABLE_CAMERA_MOVEMENT_THIS_FRAME() //Fix for bug 2229077
ENDIF
SWITCH eMissionStage
CASE MISSION_STAGE_CUTSCENE_INTRO
SET_PED_DENSITY_MULTIPLIER_THIS_FRAME(0)
SET_VEHICLE_DENSITY_MULTIPLIER_THIS_FRAME(0)
IF IS_MISSION_STAGE_LOADED(eMissionStage, iStageSetupProgress, bLoadingFlag, bSkipFlag, bReplayFlag)
IF IS_MISSION_STAGE_CUTSCENE_INTRO_COMPLETED(iMissionStageProgress)
RESET_MISSION_FLAGS()
eMissionStage = MISSION_STAGE_CAR_CHASE
ENDIF
ENDIF
BREAK
CASE MISSION_STAGE_CAR_CHASE
UPDATE_THIRD_PERSON_RUN_TO_VEHICLE_CAMERA()
IF IS_MISSION_STAGE_LOADED(eMissionStage, iStageSetupProgress, bLoadingFlag, bSkipFlag, bReplayFlag)
IF IS_MISSION_STAGE_CAR_CHASE_COMPLETED(iMissionStageProgress)
RESET_MISSION_FLAGS()
eMissionStage = MISSION_STAGE_CUTSCENE_BACK_OF_HOUSE
ENDIF
ENDIF
BREAK
CASE MISSION_STAGE_CUTSCENE_BACK_OF_HOUSE
SET_PED_DENSITY_MULTIPLIER_THIS_FRAME(0)
SET_VEHICLE_DENSITY_MULTIPLIER_THIS_FRAME(0)
IF IS_MISSION_STAGE_LOADED(eMissionStage, iStageSetupProgress, bLoadingFlag, bSkipFlag, bReplayFlag)
IF IS_MISSION_STAGE_CUTSCENE_BACK_OF_HOUSE_COMPLETED(iMissionStageProgress)
RESET_MISSION_FLAGS()
eMissionStage = MISSION_STAGE_PULL_HOUSE_DOWN
ENDIF
ENDIF
BREAK
CASE MISSION_STAGE_PULL_HOUSE_DOWN
SET_PED_DENSITY_MULTIPLIER_THIS_FRAME(0)
SET_VEHICLE_DENSITY_MULTIPLIER_THIS_FRAME(0)
IF IS_MISSION_STAGE_LOADED(eMissionStage, iStageSetupProgress, bLoadingFlag, bSkipFlag, bReplayFlag)
IF IS_MISSION_STAGE_PULL_HOUSE_DOWN_COMPLETED(iMissionStageProgress)
RESET_MISSION_FLAGS()
eMissionStage = MISSION_STAGE_ESCAPE_GOONS
ENDIF
ENDIF
BREAK
CASE MISSION_STAGE_ESCAPE_GOONS
IF ( bGoonsChaseFinished = FALSE )
SET_VEHICLE_DENSITY_MULTIPLIER_THIS_FRAME(0.4)
ENDIF
IF IS_MISSION_STAGE_LOADED(eMissionStage, iStageSetupProgress, bLoadingFlag, bSkipFlag, bReplayFlag)
IF IS_MISSION_STAGE_ESCAPE_GOONS_COMPLETED(iMissionStageProgress)
RESET_MISSION_FLAGS()
eMissionStage = MISSION_STAGE_CUTSCENE_END
ENDIF
ENDIF
BREAK
CASE MISSION_STAGE_CUTSCENE_END
IF IS_MISSION_STAGE_LOADED(eMissionStage, iStageSetupProgress, bLoadingFlag, bSkipFlag, bReplayFlag)
IF IS_MISSION_STAGE_CUTSCENE_END_COMPLETED(iMissionStageProgress)
RESET_MISSION_FLAGS()
IF NOT IS_REPEAT_PLAY_ACTIVE()
eMissionStage = MISSION_STAGE_LEADOUT
ELSE
eMissionStage = MISSION_STAGE_PASSED
ENDIF
ENDIF
ENDIF
BREAK
CASE MISSION_STAGE_LEADOUT
HIDE_HUD_COMPONENT_THIS_FRAME(NEW_HUD_AREA_NAME)
HIDE_HUD_COMPONENT_THIS_FRAME(NEW_HUD_STREET_NAME)
HIDE_HUD_COMPONENT_THIS_FRAME(NEW_HUD_DISTRICT_NAME)
IF IS_MISSION_STAGE_LOADED(eMissionStage, iStageSetupProgress, bLoadingFlag, bSkipFlag, bReplayFlag)
IF IS_MISSION_STAGE_LEADOUT_COMPLETED(iMissionStageProgress)
RESET_MISSION_FLAGS()
eMissionStage = MISSION_STAGE_PASSED
ENDIF
ENDIF
BREAK
CASE MISSION_STAGE_PASSED
MISSION_FLOW_MISSION_PASSED()
MISSION_CLEANUP()
TERMINATE_THIS_THREAD()
BREAK
CASE MISSION_STAGE_FAILED
SET_MISSION_FAILED_WITH_REASON(eMissionFail)
CLEAR_HELP()
CLEAR_PRINTS()
KILL_ANY_CONVERSATION()
TRIGGER_MUSIC_EVENT("FAM3_MISSION_FAIL")
WHILE NOT GET_MISSION_FLOW_SAFE_TO_CLEANUP()
WAIT(0)
#IF IS_DEBUG_BUILD
PRINTLN(GET_THIS_SCRIPT_NAME(), ": Waiting for GET_MISSION_FLOW_SAFE_TO_CLEANUP() to return TRUE.")
#ENDIF
ENDWHILE
CLEANUP_RAYFIRE_MAP_OBJECT(TRUE, FALSE)
MISSION_CLEANUP() // must only take 1 frame and terminate the thread
TERMINATE_THIS_THREAD()
BREAK
#IF IS_DEBUG_BUILD //debug mission stages
CASE MISSION_STAGE_DEBUG_RECORD_CHASE
IF IS_MISSION_STAGE_LOADED(eMissionStage, iStageSetupProgress, bLoadingFlag, bSkipFlag, bReplayFlag)
IF IS_MISSION_STAGE_DEBUG_RECORD_CHASE_COMPLETED(iMissionStageProgress)
RESET_MISSION_FLAGS()
eMissionStage = MISSION_STAGE_PASSED
ENDIF
ENDIF
BREAK
CASE MISSION_STAGE_DEBUG_PLAYBACK_CHASE
IF IS_MISSION_STAGE_LOADED(eMissionStage, iStageSetupProgress, bLoadingFlag, bSkipFlag, bReplayFlag)
IF IS_MISSION_STAGE_DEBUG_PLAYBACK_CHASE_COMPLETED(iMissionStageProgress)
RESET_MISSION_FLAGS()
eMissionStage = MISSION_STAGE_PASSED
ENDIF
ENDIF
BREAK
#ENDIF
ENDSWITCH
#IF IS_DEBUG_BUILD //handle debug functionality
RUN_DEBUG_PASS_AND_FAIL_CHECK(eMissionStage, eMissionFail) //handle key_f and key_s presses
RUN_DEBUG_MISSION_STAGE_MENU(iReturnStage, eMissionStage, bSkipFlag, bStageResetFlag) //handle z-skip menu
RUN_DEBUG_SKIPS(eMissionStage, bSkipFlag, bStageResetFlag) //handle j-skip and p-skip
RUN_DEBUG_WIDGETS(eMissionStage) //handle rag widgets
RUN_DEBUG_INFORMATION_DISPLAY() //handle drawing of debug information
#ENDIF
WAIT(0)
ENDWHILE
ENDSCRIPT