Files
2025-09-29 00:52:08 +02:00

4450 lines
147 KiB
Python
Executable File

//Compile out Title Update changes to header functions.
//Must be before includes.
//CONST_INT USE_TU_CHANGES 0 // Removed by Kenneth R.
USING "rage_builtins.sch"
USING "globals.sch"
USING "cutscene_public.sch"
USING "commands_cutscene.sch"
USING "commands_entity.sch"
USING "commands_script.sch"
USING "dialogue_public.sch"
USING "script_player.sch"
USING "RC_launcher_public.sch"
USING "RC_Helper_Functions.sch"
USING "CompletionPercentage_public.sch"
USING "chase_hint_cam.sch" CHASE_HINT_CAM_STRUCT localChaseHintCamStruct
USING "replay_public.sch"
USING "initial_scenes_epsilon.sch"
USING "commands_recording.sch"
#IF IS_DEBUG_BUILD
USING "select_mission_stage.sch"
#ENDIF
// *****************************************************************************************
// *****************************************************************************************
// *****************************************************************************************
//
// MISSION NAME : Epsilon6.sc
// AUTHOR : Ian Gander
// DESCRIPTION : After wearing an Epsilon robe for 10 days, Jimmy texts Michael
// to ask him to steal a Plane for the organisation
//
// *****************************************************************************************
// *****************************************************************************************
// *****************************************************************************************
// -----------------------------------------------------------------------------------------------------------
// Enums
// -----------------------------------------------------------------------------------------------------------
ENUM MISSION_STAGE
MS_INIT = 0,
MS_FLIGHT,
MS_LANDING,
MS_SEEJIMMY,
MS_ENDCUTSCENE,
MS_WAITFORJIMMY,
MS_FAILED
ENDENUM
ENUM SUB_STATE
SS_INIT,
SS_RUNNING,
SS_SHUTDOWN
ENDENUM
ENUM VEHICLE_STATE
VS_IDLE,
VS_GOTO,
VS_WANDER
ENDENUM
ENUM FAILED_REASON
FAILED_DEFAULT = 0,
FAILED_LEFT_PLANE,
FAILED_LEFT_DROPOFF,
FAILED_LEFT_PICKUP,
FAILED_DESTROYED,
FAILED_SPOOKED_JIMMY,
FAILED_ATTACKED_JIMMY,
FAILED_KILLED_JIMMY,
FAILED_HURT_JIMMY,
FAILED_KILLED_BUDDY,
FAILED_SPOOKED_BUDDY,
FAILED_HURT_BUDDY,
FAILED_STICKYBOMB
ENDENUM
ENUM JIMMY_CALL_STATE
CALL_WAITING,
CALL_BUFFERING,
CALL_PLAYING,
CALL_DONE
ENDENUM
ENUM ARMY_BACKUP_STATE
BACKUP_WAITING,
BACKUP_LOADING,
BACKUP_CREATION,
BACKUP_PLAYING,
BACKUP_DONE
ENDENUM
ENUM INTRO_STATE
INTRO_INIT = 0,
INTRO_SEENMIKE,
INTRO_INPLANE,
INTRO_INTERRUPTED
ENDENUM
ENUM EPS_STATE
EPS_INIT = 0,
EPS_INCAR = 1,
EPS_FOLLOW = 2,
EPS_HANDSUP = 3,
EPS_SAFE = 4,
EPS_WAIT = 5,
EPS_FLEEING = 6,
EPS_DEAD = 7
ENDENUM
ENUM EPS_MOVE
EPSMOVE_OK,
EPSMOVE_CHANGE,
EPSMOVE_MOVING
ENDENUM
ENUM EPS_ATTK
EPSATTK_OK,
EPSATTK_CHANGE,
EPSATTK_CHANGED
ENDENUM
ENUM ARMY_STATE
ARMY_WAITING = 0,
ARMY_LOADING = 1,
ARMY_CREATION = 2,
ARMY_DRIVING = 3,
ARMY_LEAVETRUCK = 4,
ARMY_AIMBOTH = 5,
ARMY_SHOOTEPS = 6,
ARMY_AIMPLAYER = 7,
ARMY_SHOOTPLAYER = 8,
ARMY_SHOOTALL = 9,
ARMY_DEAD = 10
ENDENUM
ENUM EPS6_WANDER_STATE
WANDER_INIT,
WANDER_GOTO,
WANDER_NOWGOINGTO,
WANDER_IDLEANIM,
WANDER_IDLEFINISH
ENDENUM
ENUM STATE_MODE
STATE_SETUP,
STATE_RUN
ENDENUM
// -----------------------------------------------------------------------------------------------------------
// Structs
// -----------------------------------------------------------------------------------------------------------
STRUCT MyVehicle // Custom vehicle struct
VEHICLE_INDEX VehIdx
MODEL_NAMES VehName
BLIP_INDEX biBlipIdx
Vector VehPos
Float Heading
ENDSTRUCT
STRUCT MySceneVehicle // Custom vehicle struct
VEHICLE_INDEX VehIdx
Vector VehPos
Float Heading
VEHICLE_STATE VehState
ENDSTRUCT
STRUCT MyPlaneCP // Struct to hold a vehicle destination
VECTOR vPointPos
BLIP_INDEX biBlipIdx
ENDSTRUCT
STRUCT MyPed // Custom ped struct
PED_INDEX piPedIdx
BLIP_INDEX biPedBlip
VECTOR vPos
FLOAT fHeading
STRING AnimDict
STRING AnimName
// BOOL bHasAttachments = FALSE
// MODEL_NAMES propModel
ENDSTRUCT
//STRUCT MyProp // Hold info for props I want for cover
// OBJECT_INDEX PropIdx
// MODEL_NAMES PropName
// VECTOR vPropPos
// VECTOR vPropRot
//ENDSTRUCT
//
//STRUCT Area // Non-AA struct for the zones for Gonz to advance through
// VECTOR vPos1
// VECTOR vPos2
// float fWidth
//ENDSTRUCT
// -----------------------------------------------------------------------------------------------------------
// Consts
// -----------------------------------------------------------------------------------------------------------
CONST_INT STUNT_PLANE_CHECKPOINT_SCALE 15
CONST_INT CP_START 0
CONST_INT CP_LANDING 1
CONST_INT CP_OUTRO 2
CONST_INT CP_JIMMY 3
CONST_INT CP_COMPLETE 4
CONST_INT Z_SKIP_INIT 0
CONST_INT Z_SKIP_FLIGHT 1
CONST_INT Z_SKIP_LANDING 2
CONST_INT Z_SKIP_SEEJIMMY 3
CONST_INT Z_SKIP_OUTRO 4
CONST_INT Z_SKIP_WAITJIMMY 5
CONST_INT Z_SKIP_COMPLETE 6
CONST_INT LENGTH_OF_CONVOY 5
CONST_INT ARMYDRIVER_ID 0
CONST_INT ARMYPASSENGER_ID 1
CONST_FLOAT MAX_WARNING_DISTANCE 300.0
CONST_FLOAT MAX_FAIL_DISTANCE 350.0
CONST_INT MAX_SECTIONS 4
CONST_INT TOP_LEFT 0
CONST_INT TOP_RIGHT 1
CONST_INT BOTTOM_LEFT 2
CONST_INT BOTTOM_RIGHT 3
// -----------------------------------------------------------------------------------------------------------
// Globals
// -----------------------------------------------------------------------------------------------------------
// Scene entities from mission launcher
g_structRCScriptArgs sRCLauncherDataLocal
MyVehicle mv_plane
MyVehicle mv_RewardCar
MyPlaneCP pcp_LandingGoal
MyPed mp_Jimmy
MyPed mp_Cultist
MISSION_STAGE missionStage = MS_INIT
SUB_STATE subState = SS_INIT
JIMMY_CALL_STATE CallState = CALL_WAITING
INTRO_STATE IntroState = INTRO_INIT
EPS_STATE EpsState = EPS_INIT
STATE_MODE EpsMode = STATE_SETUP
EPS_MOVE EpsMove = EPSMOVE_OK
EPS6_WANDER_STATE Eps6Wander = WANDER_INIT
INT iWanderStage = 0
VECTOR vTomCoords[3]
BOOL bHasSkipped = FALSE
BOOL bCompleteShitskip = FALSE
BOOL bShownGetInPlane = FALSE
BOOL bShownExitVehicle = FALSE
BOOL bShownLoseCops = FALSE
BOOL bAbandonment = FALSE
BOOL bPausedConv = FALSE
INT iPausedConvLn
INT iPausedConvTimer
TEXT_LABEL_23 tlPausedConvRoot
BOOL bPlaneTooCloseConv = FALSE
BOOL bShownGoToAirfield = FALSE
BOOL bShownLandAtAirfield = TRUE
BOOL bShownGoToJimmy = FALSE
BOOL bPlayerGoneTooFar = FALSE
BOOL bSetCP = FALSE
BOOL bSpawnJimmy = FALSE
//BOOL bCultistRagdoll = FALSE
BOOL bTomPushedOver = FALSE
BOOL bTomSaidPushedOver = FALSE
BOOL bTeleOnFail = FALSE
BOOL bCultistAimConv = FALSE
BOOL bCultistNoSubIntro = FALSE
INT iDetectorHumID = -1
INT iDetectorBeepID = -1
INT iCultistRoamStage = 0
INT iCultistHandsUpTimer
INT iJimmyCallTimer
INT iJimmyBeckonTimer
INT iJimmyPlaneWarningTimer
int iJimmyFlyStage
int iJimmyFlyGearTimer
BOOL bJimmyGearDone = FALSE
INT iCutsceneStage = 0
INT iCultistRoamTimer
INT iCultistConvDelayTimer
//INT g_iOutroTimer
INT iConvTimer
// Floats used for the shrinking abandonment values for the See Jimmy stage
FLOAT g_fJimmyWarningRange = MAX_WARNING_DISTANCE
FLOAT g_fJimmyFailRange = MAX_FAIL_DISTANCE
INT g_iAbandonCap = 5
// The area at the airfield the plane must be detected in
VECTOR vPlaneDetect1 = <<1720.961304,3254.950684, 42.5>>
VECTOR vPlaneDetect2 = <<1620.34, 3228.95, 37.650513>>
BOOL bDoneMusic = FALSE
STREAMVOL_ID cutsceneStreamvol
SEQUENCE_INDEX seq
//CAMERA_INDEX ciOutro
OBJECT_INDEX oiJimmyPhone
INT iNavBlockingObj = -1
FAILED_REASON FailedReason = FAILED_DEFAULT
structPedsForConversation s_conversation_cult
structPedsForConversation s_conversation_flight
structPedsForConversation s_conversation_outro
REL_GROUP_HASH relGroupPlayer
MODEL_NAMES vehModel = VELUM
MODEL_NAMES cultModel = IG_TOMEPSILON
// Replay stuff
BOOL bReplayTrackOn = FALSE
#IF IS_DEBUG_BUILD
int i_debug_jump_stage
MissionStageMenuTextStruct s_skip_menu[6]
BOOL bDebug_PrintToTTY = TRUE
BOOL bDebugFlyingBuff = FALSE
WIDGET_GROUP_ID widgetGroup
#ENDIF
//PURPOSE: Print debug string to Rag.
//PARAMS: s - the string we want to print.
PROC DEBUG_PRINT(String s)
#IF IS_DEBUG_BUILD
IF bDebug_PrintToTTY
CPRINTLN(DEBUG_MISSION, "Epsilon 6: ", s)
ENDIF
#ENDIF
s = s
ENDPROC
//PURPOSE: Print debug string with float to Rag.
//PARAMS: s - the string we want to print. f - the float we want to print.
PROC DEBUG_PRINTFLOAT(String s, FLOAT f)
#IF IS_DEBUG_BUILD
IF bDebug_PrintToTTY
CPRINTLN(DEBUG_MISSION, "Epsilon 6: ", s, " ", f)
ENDIF
#ENDIF
s = s
f = f
ENDPROC
//PURPOSE: Print debug string with int to Rag.
//PARAMS: s - the string we want to print. i - the int we want to print.
PROC DEBUG_PRINTINT(String s, int i)
#IF IS_DEBUG_BUILD
IF bDebug_PrintToTTY
CPRINTLN(DEBUG_MISSION, "Epsilon 6: ", s, ": ", i)
ENDIF
#ENDIF
s = s
i = i
ENDPROC
/// PURPOSE:
/// Print a state change notification for the Epsilonist
/// PARAMS:
/// newState - The state the Epsilonist's changed to
PROC EPS_STATE_PRINT(EPS_STATE newState)
#IF IS_DEBUG_BUILD
IF bDebug_PrintToTTY
CPRINTLN(DEBUG_MISSION, "Epsilon 6: ","EPSILONIST: Changed state to ", INT_TO_ENUM(EPS_STATE, newState))
ENDIF
#ENDIF
newState = newState
ENDPROC
/// PURPOSE:
/// Print a state change notification for the Army
/// PARAMS:
/// newState - The state the Epsilonist's changed to
PROC ARMY_STATE_PRINT(int iSoldierID, ARMY_STATE newState)
#IF IS_DEBUG_BUILD
IF bDebug_PrintToTTY
CPRINTLN(DEBUG_MISSION, "Epsilon 6: ", "ARMY ID #", iSoldierID, ": Changed state to ", INT_TO_ENUM(ARMY_STATE, newState))
ENDIF
#ENDIF
iSoldierID = iSoldierID
newState = newState
ENDPROC
//PURPOSE: Checks that a particular conversation root is currently playing.
//PARAMS: RootToCheck - The conversation root we want to check is playing.
//RETURNS: TRUE if the root is currently playing, FALSE otherwise.
FUNC BOOL IS_THIS_CONVERSATION_ROOT_PLAYING(STRING RootToCheck)
TEXT_LABEL_23 blah
blah = GET_CURRENTLY_PLAYING_STANDARD_CONVERSATION_ROOT()
IF ARE_STRINGS_EQUAL(blah,RootToCheck)
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// Converts a debug cam rotation into a facing direction (for streamvol frustums) - shamelessly stolen from Chinese 2
/// PARAMS:
/// vRot - The rot we want to convert
/// RETURNS:
/// A direction vector
FUNC VECTOR CONVERT_ROTATION_TO_DIRECTION_VECTOR(VECTOR vRot)
RETURN <<-SIN(vRot.z) * COS(vRot.x), COS(vRot.z) * COS(vRot.x), SIN(vRot.x)>>
ENDFUNC
// ===========================================================================================================
// Termination
// ===========================================================================================================
//PURPOSE: Deletes (or alternatively releases) every entity in the mission.
//PARAMS: ReleaseInstead - if TRUE, release the entities rather than delete them outright.
PROC DeleteEverything(BOOL ReleaseInstead = FALSE)
// ReleaseInstead is used in Script_Cleanup(), where we don't want to see vehicles disappear in front of the player
IF ReleaseInstead
DEBUG_PRINT("DeleteEverything: Releasing entities")
// End-of-the-line cleanup - Jimmy probably won't exist at this point anyway
SAFE_RELEASE_PED(mp_Jimmy.piPedIdx)
SAFE_RELEASE_VEHICLE(mv_plane.VehIdx)
REMOVE_ANIM_DICT(mp_Jimmy.AnimDict)
SAFE_RELEASE_VEHICLE(mv_RewardCar.VehIdx)
// remove cultist from player's group, so he doesn't come with you for a replay
IF IS_ENTITY_ALIVE(mp_Cultist.piPedIdx)
IF IS_PED_IN_GROUP(mp_Cultist.piPedIdx)
REMOVE_PED_FROM_GROUP(mp_Cultist.piPedIdx)
ENDIF
ENDIF
SAFE_RELEASE_PED(mp_Cultist.piPedIdx)
ELSE
SAFE_DELETE_VEHICLE(mv_plane.VehIdx)
DEBUG_PRINT("Deleted Plane")
IF DOES_ENTITY_EXIST(mv_plane.VehIdx)
DEBUG_PRINT("Plane still exists!!")
ENDIF
REMOVE_ANIM_DICT(mp_Jimmy.AnimDict)
// End-of-the-line cleanup - Jimmy probably won't exist at this point anyway
SAFE_DELETE_PED(mp_Jimmy.piPedIdx)
SAFE_DELETE_VEHICLE(mv_RewardCar.VehIdx)
SAFE_DELETE_PED(mp_Cultist.piPedIdx)
ENDIF
ENDPROC
// -----------------------------------------------------------------------------------------------------------
// Script Cleanup
// -----------------------------------------------------------------------------------------------------------
//PURPOSE: Cleans up the script.
PROC Script_Cleanup()
// If the mission was triggered then additional mission cleanup will be required.
IF (Random_Character_Cleanup_If_Triggered())
DEBUG_PRINT("...Random Character Script was triggered so additional cleanup required")
ENDIF
DeleteEverything(TRUE)
KILL_CHASE_HINT_CAM(localChaseHintCamStruct)
ENABLE_DISPATCH_SERVICE(DT_POLICE_AUTOMOBILE, TRUE)
ENABLE_DISPATCH_SERVICE(DT_POLICE_HELICOPTER, TRUE)
ENABLE_DISPATCH_SERVICE(DT_FIRE_DEPARTMENT, TRUE)
ENABLE_DISPATCH_SERVICE(DT_AMBULANCE_DEPARTMENT, TRUE)
SET_MAX_WANTED_LEVEL(5)
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
TASK_CLEAR_LOOK_AT(PLAYER_PED_ID())
ENDIF
if IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
KILL_ANY_CONVERSATION()
ENDIF
IF HAS_CUTSCENE_LOADED()
REMOVE_CUTSCENE()
ENDIF
REMOVE_ANIM_DICT("rcm_epsilonism4")
IF DOES_SCENARIO_GROUP_EXIST("SANDY_PLANES")
IF NOT IS_SCENARIO_GROUP_ENABLED("SANDY_PLANES")
SET_SCENARIO_GROUP_ENABLED("SANDY_PLANES",TRUE)
ENDIF
ENDIF
// Cleanup scene entities created by the RC launcher
RC_CleanupSceneEntities(sRCLauncherDataLocal, FALSE)
SET_ROADS_BACK_TO_ORIGINAL(<<-195.709671,1881.431641,196.157059>>, <<842.235168,2249.857178,48.501358>>)
SET_ROADS_BACK_TO_ORIGINAL(<<816.852661,2107.933838,63.374523>>, <<176.167633,2902.729980,46.615326>>)
SET_ROADS_BACK_TO_ORIGINAL(<<-36.251339,-465.831512,39.122559>>, <<25.801004,-287.171631,47.758629>>)
//SET_ROADS_BACK_TO_ORIGINAL(<<1542.315796,3767.182617,33.163731>>, <<1705.179199,3496.898926,36.706730>>)
DISABLE_CELLPHONE(FALSE)
TERMINATE_THIS_THREAD()
ENDPROC
// -----------------------------------------------------------------------------------------------------------
// Script Pass
// -----------------------------------------------------------------------------------------------------------
//PURPOSE: Passes the script.
PROC Script_Passed()
SET_VEHICLE_GEN_AVAILABLE(VEHGEN_EPSILON6_PLANE, FALSE)
Random_Character_Passed(CP_RAND_C_EPS6)
PRINTSTRING("******************* MISSION PASSED *********************")
PRINTNL()
CLEAR_PLAYER_WANTED_LEVEL( PLAYER_ID() )
//PRINT_NOW("EPS6_WIN", 7000, 1)
IF (IS_PLAYER_PLAYING(PLAYER_ID()))
// As a standard, holster the players gun on mission passed.
SET_CURRENT_PED_WEAPON(PLAYER_PED_ID(), WEAPONTYPE_UNARMED, FALSE)
// Clear the player's wanted level.
SET_PLAYER_WANTED_LEVEL(PLAYER_ID(), 0)
// Block contributions to the wanted level for 5 seconds.
START_FIRING_AMNESTY()
ENDIF
//Set epsilon step stat
INT iCurrent
STAT_GET_INT(NUM_EPSILON_STEP,iCurrent)
IF iCurrent < 17
STAT_SET_INT(NUM_EPSILON_STEP,17)
SET_ACHIEVEMENT_PROGRESS_SAFE(ENUM_TO_INT(ACH20),17)
CPRINTLN(debug_dan,"Epsilon progress:",17)
ENDIF
DEBUG_PRINT("Doing cleanup now")
Script_Cleanup()
ENDPROC
// ===========================================================================================================
// MISSION FUNCTIONS & PROCEDURES
// ===========================================================================================================
//PURPOSE: Sets the given ped into the given group, and updates the relationship of that group with the player
//PARAMS: pedindex - the ped we want to put into a group.
// BuddyGroup - the group hash that we want the ped to be added to.
// RelType - the relationship we want to set the given group hash to have with the player
PROC CREATE_SAFE_RELATIONSHIP(PED_INDEX &pedindex, REL_GROUP_HASH BuddyGroup, RELATIONSHIP_TYPE RelType)
IF IS_ENTITY_ALIVE(pedindex)
SET_PED_RELATIONSHIP_GROUP_HASH(pedindex, BuddyGroup)
SET_RELATIONSHIP_BETWEEN_GROUPS(RelType, BuddyGroup, RELGROUPHASH_PLAYER)
ENDIF
ENDPROC
//PURPOSE: Checks that the plane is OK and not stuck on its roof.
//RETURNS: TRUE if the plane is fine, FALSE if it's broken.
FUNC BOOL IsPlaneOK()
IF IS_VEHICLE_OK(mv_plane.VehIdx)
IF GET_LANDING_GEAR_STATE(mv_plane.VehIdx) = LGS_BROKEN
DEBUG_PRINT("Detected plane landing gear is broken")
return FALSE
ELIF IS_VEHICLE_STUCK_ON_ROOF(mv_plane.VehIdx)
DEBUG_PRINT("Detected plane is stuck on roof")
return FALSE
ELIF GET_VEHICLE_ENGINE_HEALTH(mv_plane.VehIdx) <= 0
DEBUG_PRINT("Detected plane engine health is <= 0")
return FALSE
ELIF IS_VEHICLE_STUCK_TIMER_UP(mv_plane.VehIdx, VEH_STUCK_JAMMED, JAMMED_TIME)
DEBUG_PRINT("Detected plane IS_VEHICLE_STUCK_TIMER_UP > JAMMED_TIME")
return FALSE
ELSE
return TRUE
ENDIF
ENDIF
DEBUG_PRINT("The plane is broken!")
RETURN FALSE
ENDFUNC
//PURPOSE: Checks whether the plane is moving so slowly that we might as well consider it "stopped".
//RETURNS: TRUE if the plane can be considered to have stopped, FALSE otherwise.
FUNC BOOL HAS_PLANE_ALMOST_STOPPED()
// The plane appears to never fully "stop" anymore for IS_VEHICLE_STOPPED to return true, so this will check the plane has slowed to such a speed that we can consider it so
IF IsPlaneOK()
FLOAT fTemp
fTemp = GET_ENTITY_SPEED(mv_plane.VehIdx)
IF (fTemp > -0.5)
AND (fTemp < 0.5)
RETURN TRUE
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
//PURPOSE: Checks whether the player has touched any of the flight controls.
//RETURNS: TRUE if any player flight input is detected, FALSE otherwise.
FUNC BOOL HAS_PLAYER_TOUCHED_FLYING_CONTROLS()
IF IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_VEH_MOVE_LR)
OR IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_VEH_MOVE_UD) // Leave old inputs, just in case
OR IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_VEH_FLY_ROLL_LR)
OR IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_VEH_FLY_PITCH_UD)
OR IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_VEH_FLY_UNDERCARRIAGE)
OR IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_VEH_FLY_ATTACK)
OR IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_VEH_FLY_THROTTLE_DOWN)
OR IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_VEH_FLY_THROTTLE_UP)
OR IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_VEH_FLY_YAW_LEFT)
OR IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_VEH_FLY_YAW_RIGHT)
DEBUG_PRINT("*** Player input detected")
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
//PURPOSE: Releases plane control the player after a debug skip when the screen is faded in, if they have tried to move the plane in any way.
PROC HANDLE_SKIP_FLYING_CONTROLS()
IF IS_SCREEN_FADED_IN()
IF IS_VEHICLE_OK(mv_plane.VehIdx)
IF IS_PLAYBACK_GOING_ON_FOR_VEHICLE(mv_plane.VehIdx)
IF HAS_PLAYER_TOUCHED_FLYING_CONTROLS()
STOP_PLAYBACK_RECORDED_VEHICLE(mv_plane.VehIdx)
SET_PLAYER_CONTROL(PLAYER_ID(), TRUE)
ENDIF
ENDIF
ENDIF
ENDIF
ENDPROC
//PURPOSE: Loads and sets up some basic global resources that are needed during the mission at all times, called once at the start of the mission.
PROC LOAD_GLOBAL_RESOURCES()
#IF IS_DEBUG_BUILD
s_skip_menu[0].sTxtLabel = "Start"
s_skip_menu[1].sTxtLabel = "Flight"
s_skip_menu[2].sTxtLabel = "Landing"
s_skip_menu[3].sTxtLabel = "Walk to Jimmy"
s_skip_menu[4].sTxtLabel = "Outro"
s_skip_menu[5].sTxtLabel = "Wait for Jimmy"
IF NOT DOES_WIDGET_GROUP_EXIST(widgetGroup)
widgetGroup = START_WIDGET_GROUP("Epsilon 6 widgets")
ADD_WIDGET_BOOL("TTY Toggle - Print Mission Debug Info", bDebug_PrintToTTY)
ADD_WIDGET_BOOL("Buff player flying stat", bDebugFlyingBuff)
STOP_WIDGET_GROUP()
ENDIF
#ENDIF
mv_RewardCar.Heading = 132.923
mv_RewardCar.VehName = f620
mv_RewardCar.VehPos = <<1692.160, 3271.055, 40.633>>
mv_plane.VehName = VELUM
mp_Jimmy.vPos = <<1687.51, 3278.35, 40.12>>
mp_Jimmy.fHeading = 212.0820
mp_Jimmy.AnimDict = "rcmepsilonism6"
mp_Jimmy.AnimName = "idle_a"
pcp_LandingGoal.vPointPos = <<1620.34, 3228.95, 39.71>>
ENABLE_DISPATCH_SERVICE(DT_POLICE_AUTOMOBILE, FALSE)
ENABLE_DISPATCH_SERVICE(DT_POLICE_HELICOPTER, FALSE)
ENABLE_DISPATCH_SERVICE(DT_FIRE_DEPARTMENT, FALSE)
ENABLE_DISPATCH_SERVICE(DT_AMBULANCE_DEPARTMENT, FALSE)
SET_MAX_WANTED_LEVEL(0)
ADD_CONTACT_TO_PHONEBOOK(CHAR_MARNIE, MICHAEL_BOOK, FALSE)
ADD_CONTACT_TO_PHONEBOOK(CHAR_JIMMY_BOSTON, MICHAEL_BOOK, FALSE)
REQUEST_ADDITIONAL_TEXT("EPS6", MISSION_TEXT_SLOT)
WHILE not HAS_ADDITIONAL_TEXT_LOADED(MISSION_TEXT_SLOT)
WAIT(0)
ENDWHILE
REGISTER_SCRIPT_WITH_AUDIO()
ENDPROC
/// PURPOSE:
/// Sets the player up in whatever starting state he should be in, at whatever stage the mission is currently at
PROC SETUP_PLAYER()
SWITCH missionStage
CASE MS_INIT
DEBUG_PRINT("*** Moving/realigning player...")
IF NOT IS_REPLAY_BEING_SET_UP()
SAFE_TELEPORT_ENTITY(PLAYER_PED_ID(), <<-2914.7070, 3234.6392, 9.7863>>, 215.2149)
ENDIF
BREAK
CASE MS_FLIGHT
// warp player into vehicle, turn engine on, move them
IF IS_VEHICLE_OK(mv_plane.VehIdx)
SAFE_TELEPORT_ENTITY(PLAYER_PED_ID(), <<-2892.93,3192.37,11.66>>)
SET_PED_INTO_VEHICLE(PLAYER_PED_ID(), mv_plane.VehIdx)
ENDIF
BREAK
CASE MS_LANDING
IF NOT IS_REPLAY_BEING_SET_UP()
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
AND IS_VEHICLE_OK(mv_plane.VehIdx)
IF NOT IS_PED_IN_VEHICLE(PLAYER_PED_ID(), mv_plane.VehIdx)
SET_PED_INTO_VEHICLE(PLAYER_PED_ID(), mv_plane.VehIdx)
ENDIF
SET_PED_COORDS_KEEP_VEHICLE(PLAYER_PED_ID(), <<376.0205, 2886.5520, 171.3085>>)
ENDIF
ENDIF
BREAK
CASE MS_SEEJIMMY
FALLTHRU
CASE MS_ENDCUTSCENE
IF NOT IS_REPLAY_BEING_SET_UP()
SAFE_TELEPORT_ENTITY(PLAYER_PED_ID(), <<1681.54, 3259.38, 39.77>>, 298.33)
ENDIF
BREAK
CASE MS_WAITFORJIMMY
IF NOT IS_REPLAY_BEING_SET_UP()
SAFE_TELEPORT_ENTITY(PLAYER_PED_ID(), << 1688.45, 3277.15, 40.08 >>, 131.1749, TRUE)
ENDIF
BREAK
ENDSWITCH
SET_GAMEPLAY_CAM_RELATIVE_HEADING()
SET_GAMEPLAY_CAM_RELATIVE_PITCH()
ENDPROC
/// PURPOSE:
/// Sets the reward car up
PROC SETUP_CAR()
SWITCH missionStage
CASE MS_ENDCUTSCENE
FALLTHRU
CASE MS_WAITFORJIMMY
IF NOT IS_VEHICLE_OK(mv_RewardCar.VehIdx)
mv_RewardCar.VehIdx = CREATE_VEHICLE(mv_RewardCar.VehName, mv_RewardCar.VehPos, mv_RewardCar.Heading)
SET_VEHICLE_ON_GROUND_PROPERLY(mv_RewardCar.VehIdx)
SET_VEHICLE_HAS_BEEN_OWNED_BY_PLAYER(mv_RewardCar.VehIdx, TRUE)
SET_VEHICLE_DIRT_LEVEL(mv_RewardCar.VehIdx, 13)
SET_VEHICLE_COLOURS(mv_RewardCar.VehIdx, 157, 157)
SET_VEHICLE_EXTRA_COLOURS(mv_RewardCar.VehIdx, 157, 5)
ENDIF
BREAK
DEFAULT
IF NOT IS_VEHICLE_OK(mv_RewardCar.VehIdx)
mv_RewardCar.VehIdx = CREATE_VEHICLE(mv_RewardCar.VehName, mv_RewardCar.VehPos, mv_RewardCar.Heading)
SET_VEHICLE_ON_GROUND_PROPERLY(mv_RewardCar.VehIdx)
SET_VEHICLE_HAS_BEEN_OWNED_BY_PLAYER(mv_RewardCar.VehIdx, TRUE)
SET_VEHICLE_DOORS_LOCKED(mv_RewardCar.VehIdx, VEHICLELOCK_LOCKOUT_PLAYER_ONLY)
SET_VEHICLE_DIRT_LEVEL(mv_RewardCar.VehIdx, 13)
SET_VEHICLE_COLOURS(mv_RewardCar.VehIdx, 157, 157)
SET_VEHICLE_EXTRA_COLOURS(mv_RewardCar.VehIdx, 157, 5)
ENDIF
BREAK
ENDSWITCH
SET_VEHICLE_MODEL_IS_SUPPRESSED(mv_RewardCar.VehName, TRUE)
SET_MODEL_AS_NO_LONGER_NEEDED(mv_RewardCar.VehName)
ENDPROC
/// PURPOSE:
/// Sets Jimmy Boston up in whatever starting state he should be in, at whatever stage the mission is currently at
PROC SETUP_JIMMY()
SWITCH missionStage
CASE MS_INIT
FALLTHRU // Same as MS_FLIGHT
CASE MS_FLIGHT
SAFE_DELETE_PED(mp_Jimmy.piPedIdx)
SAFE_REMOVE_BLIP(mp_Jimmy.biPedBlip)
BREAK
CASE MS_LANDING
FALLTHRU
CASE MS_SEEJIMMY
FALLTHRU
CASE MS_ENDCUTSCENE
IF NOT IS_ENTITY_ALIVE(mp_Jimmy.piPedIdx)
WHILE NOT RC_CREATE_NPC_PED(mp_Jimmy.piPedIdx, CHAR_JIMMY_BOSTON, mp_Jimmy.vPos, mp_Jimmy.fHeading, "JimmyB")
WAIT(0)
ENDWHILE
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(mp_Jimmy.piPedIdx, TRUE)
SET_PED_CAN_RAGDOLL_FROM_PLAYER_IMPACT(mp_Jimmy.piPedIdx, FALSE)
SET_PED_CAN_BE_TARGETTED(mp_Jimmy.piPedIdx, FALSE)
SET_PED_CONFIG_FLAG(mp_Jimmy.piPedIdx, PCF_UseKinematicModeWhenStationary, TRUE)
SET_PED_PROP_INDEX(mp_Jimmy.piPedIdx, ANCHOR_EYES, 0, 0)
SET_PED_RELATIONSHIP_GROUP_HASH(mp_Jimmy.piPedIdx, relGroupPlayer)
SET_PED_CONFIG_FLAG(mp_Jimmy.piPedIdx, PCF_KeepRelationshipGroupAfterCleanUp, TRUE)
TASK_PLAY_ANIM(mp_Jimmy.piPedIdx, mp_Jimmy.AnimDict, mp_Jimmy.AnimName, NORMAL_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_UPPERBODY | AF_LOOPING | AF_SECONDARY)
ELSE
SAFE_TELEPORT_ENTITY(mp_Jimmy.piPedIdx, mp_Jimmy.vPos, mp_Jimmy.fHeading)
IF IS_ENTITY_ALIVE(mp_Jimmy.piPedIdx)
TASK_PLAY_ANIM(mp_Jimmy.piPedIdx, mp_Jimmy.AnimDict, mp_Jimmy.AnimName, NORMAL_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_UPPERBODY | AF_LOOPING | AF_SECONDARY)
SET_PED_PROP_INDEX(mp_Jimmy.piPedIdx, ANCHOR_EYES, 0, 0)
ENDIF
ENDIF
IF NOT DOES_ENTITY_EXIST(oiJimmyPhone)
oiJimmyPhone = CREATE_OBJECT(p_amb_phone_01, GET_ENTITY_COORDS(mp_Jimmy.piPedIdx))
ENDIF
IF NOT IS_ENTITY_ATTACHED(oiJimmyPhone)
ATTACH_ENTITY_TO_ENTITY(oiJimmyPhone, mp_Jimmy.piPedIdx, GET_PED_BONE_INDEX(mp_Jimmy.piPedIdx, BONETAG_PH_R_HAND), <<0,0,0>>, <<0,0,0>>, TRUE)
ENDIF
SET_NPC_PED_MODEL_AS_NO_LONGER_NEEDED(CHAR_JIMMY_BOSTON)
BREAK
CASE MS_WAITFORJIMMY
IF NOT bCompleteShitskip
IF NOT IS_ENTITY_ALIVE(mp_Jimmy.piPedIdx)
WHILE NOT RC_CREATE_NPC_PED(mp_Jimmy.piPedIdx, CHAR_JIMMY_BOSTON, <<1683.76, 3270.74, 39.78>>, 168.3395 , "JimmyB")
WAIT(0)
ENDWHILE
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(mp_Jimmy.piPedIdx, TRUE)
SET_PED_CAN_RAGDOLL_FROM_PLAYER_IMPACT(mp_Jimmy.piPedIdx, FALSE)
SET_PED_CAN_BE_TARGETTED(mp_Jimmy.piPedIdx, FALSE)
SET_PED_CONFIG_FLAG(mp_Jimmy.piPedIdx, PCF_UseKinematicModeWhenStationary, TRUE)
SET_PED_PROP_INDEX(mp_Jimmy.piPedIdx, ANCHOR_EYES, 0, 0)
SET_PED_RELATIONSHIP_GROUP_HASH(mp_Jimmy.piPedIdx, relGroupPlayer)
SET_PED_CONFIG_FLAG(mp_Jimmy.piPedIdx, PCF_KeepRelationshipGroupAfterCleanUp, TRUE)
IF NOT DOES_BLIP_EXIST(mp_Jimmy.biPedBlip)
mp_Jimmy.biPedBlip = CREATE_PED_BLIP(mp_Jimmy.piPedIdx, TRUE, TRUE, BLIPPRIORITY_HIGHEST)
ENDIF
IF IS_ENTITY_ALIVE(mp_Jimmy.piPedIdx)
AND IsPlaneOK()
OPEN_SEQUENCE_TASK(seq)
TASK_FOLLOW_NAV_MESH_TO_COORD(NULL, <<1682.44, 3258.81, 39.81>>, PEDMOVEBLENDRATIO_RUN, DEFAULT_TIME_BEFORE_WARP, 7.5, ENAV_NO_STOPPING)
TASK_ENTER_VEHICLE(NULL, mv_plane.VehIdx, DEFAULT_TIME_BEFORE_WARP, VS_DRIVER)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(mp_Jimmy.piPedIdx, seq)
CLEAR_SEQUENCE_TASK(seq)
ENDIF
FORCE_PED_AI_AND_ANIMATION_UPDATE(mp_Jimmy.piPedIdx, FALSE)
ELSE
SAFE_TELEPORT_ENTITY(mp_Jimmy.piPedIdx, <<1683.76, 3270.74, 39.78>>, 168.3395)
IF NOT DOES_BLIP_EXIST(mp_Jimmy.biPedBlip)
mp_Jimmy.biPedBlip = CREATE_PED_BLIP(mp_Jimmy.piPedIdx, TRUE, TRUE, BLIPPRIORITY_HIGHEST)
ENDIF
IF IS_ENTITY_ALIVE(mp_Jimmy.piPedIdx)
AND IsPlaneOK()
OPEN_SEQUENCE_TASK(seq)
TASK_FOLLOW_NAV_MESH_TO_COORD(NULL, <<1682.44, 3258.81, 39.81>>, PEDMOVEBLENDRATIO_RUN, DEFAULT_TIME_BEFORE_WARP, 7.5, ENAV_NO_STOPPING)
TASK_ENTER_VEHICLE(NULL, mv_plane.VehIdx, DEFAULT_TIME_BEFORE_WARP, VS_DRIVER)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(mp_Jimmy.piPedIdx, seq)
CLEAR_SEQUENCE_TASK(seq)
ENDIF
FORCE_PED_AI_AND_ANIMATION_UPDATE(mp_Jimmy.piPedIdx, TRUE)
ENDIF
SAFE_DELETE_OBJECT(oiJimmyPhone)
ELSE
SAFE_REMOVE_BLIP(mp_Jimmy.biPedBlip)
SAFE_DELETE_PED(mp_Jimmy.piPedIdx)
ENDIF
SET_NPC_PED_MODEL_AS_NO_LONGER_NEEDED(CHAR_JIMMY_BOSTON)
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE:
/// Sets the plane up in whatever starting state it should be in, at whatever stage the mission is currently at
PROC SETUP_PLANE()
SWITCH missionStage
CASE MS_INIT
IF DOES_ENTITY_EXIST(mv_plane.VehIdx)
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
IF IS_PED_IN_VEHICLE(PLAYER_PED_ID(), mv_plane.VehIdx)
SAFE_TELEPORT_ENTITY(PLAYER_PED_ID(), <<-2882.42, 3197.76, 10.74>>)
ENDIF
ENDIF
DELETE_VEHICLE(mv_plane.VehIdx)
ENDIF
mv_plane.VehIdx = CREATE_VEHICLE(vehModel,<<-2892.93,3192.37,11.66>>, -132.35, FALSE, FALSE)
SET_VEHICLE_ON_GROUND_PROPERLY(mv_plane.VehIdx)
ADD_VEHICLE_UPSIDEDOWN_CHECK(mv_plane.VehIdx)
SET_VEHICLE_COLOURS(mv_plane.VehIdx, 157, 157)
SET_VEHICLE_EXTRA_COLOURS(mv_plane.VehIdx, 157, 5)
SET_VEHICLE_LIVERY(mv_plane.VehIdx, 3)
SET_VEHICLE_ENGINE_CAN_DEGRADE(mv_plane.VehIdx, FALSE)
SET_VEHICLE_HAS_STRONG_AXLES(mv_plane.VehIdx, TRUE)
SET_VEHICLE_AS_RESTRICTED(mv_plane.VehIdx, 0)
DEBUG_PRINT("Creating plane in init skip...")
BREAK
CASE MS_FLIGHT
// Can't use SAFE_DELETE_VEHICLE here, in case the player is inside the plane at the time and we get duplicate planes!
IF DOES_ENTITY_EXIST(mv_plane.VehIdx)
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
IF IS_PED_IN_VEHICLE(PLAYER_PED_ID(), mv_plane.VehIdx)
SAFE_TELEPORT_ENTITY(PLAYER_PED_ID(), <<-2882.42, 3197.76, 10.74>>)
ENDIF
ENDIF
DELETE_VEHICLE(mv_plane.VehIdx)
ENDIF
mv_plane.VehIdx = CREATE_VEHICLE(vehModel,<<-2892.93,3192.37,11.66>>, -132.35, FALSE, FALSE)
SET_VEHICLE_ON_GROUND_PROPERLY(mv_plane.VehIdx)
ADD_VEHICLE_UPSIDEDOWN_CHECK(mv_plane.VehIdx)
SET_VEHICLE_COLOURS(mv_plane.VehIdx, 157, 157)
SET_VEHICLE_EXTRA_COLOURS(mv_plane.VehIdx, 157, 5)
SET_VEHICLE_LIVERY(mv_plane.VehIdx, 3)
SET_VEHICLE_ENGINE_ON(mv_plane.VehIdx, TRUE, TRUE)
SET_VEHICLE_ENGINE_CAN_DEGRADE(mv_plane.VehIdx, FALSE)
SET_VEHICLE_HAS_STRONG_AXLES(mv_plane.VehIdx, TRUE)
SET_VEHICLE_AS_RESTRICTED(mv_plane.VehIdx, 0)
DEBUG_PRINT("Creating plane in Flight skip...")
BREAK
CASE MS_LANDING
IF IsPlaneOK()
SET_VEHICLE_DOORS_LOCKED(mv_plane.VehIdx, VEHICLELOCK_UNLOCKED)
SET_ENTITY_HEADING(mv_plane.VehIdx, 290.8230)
SET_VEHICLE_ENGINE_ON(mv_plane.VehIdx, TRUE, TRUE)
SET_VEHICLE_FORWARD_SPEED(mv_plane.VehIdx, 75)
SET_VEHICLE_ENGINE_CAN_DEGRADE(mv_plane.VehIdx, FALSE)
SET_VEHICLE_HAS_STRONG_AXLES(mv_plane.VehIdx, TRUE)
CONTROL_LANDING_GEAR(mv_plane.VehIdx, LGC_RETRACT_INSTANT)
FREEZE_ENTITY_POSITION(mv_plane.VehIdx, TRUE)
ELSE
mv_plane.VehIdx = CREATE_VEHICLE(vehModel, <<595.7562, 2926.4202, 173.2301>>, 283.3833, FALSE, FALSE)
SET_VEHICLE_ON_GROUND_PROPERLY(mv_plane.VehIdx)
ADD_VEHICLE_UPSIDEDOWN_CHECK(mv_plane.VehIdx)
SET_VEHICLE_COLOURS(mv_plane.VehIdx, 157, 157)
SET_VEHICLE_EXTRA_COLOURS(mv_plane.VehIdx, 157, 5)
SET_VEHICLE_LIVERY(mv_plane.VehIdx, 3)
SET_VEHICLE_ENGINE_ON(mv_plane.VehIdx, TRUE, TRUE)
SET_VEHICLE_ENGINE_CAN_DEGRADE(mv_plane.VehIdx, FALSE)
SET_VEHICLE_HAS_STRONG_AXLES(mv_plane.VehIdx, TRUE)
SET_VEHICLE_AS_RESTRICTED(mv_plane.VehIdx, 0)
IF NOT IS_REPLAY_BEING_SET_UP()
SET_PED_INTO_VEHICLE(PLAYER_PED_ID(), mv_plane.VehIdx)
ENDIF
CONTROL_LANDING_GEAR(mv_plane.VehIdx, LGC_RETRACT_INSTANT)
FREEZE_ENTITY_POSITION(mv_plane.VehIdx, TRUE)
DEBUG_PRINT("Creating plane for landing skip...")
ENDIF
BREAK
CASE MS_SEEJIMMY
FALLTHRU
CASE MS_ENDCUTSCENE
DEBUG_PRINT("Doing plane skip for SeeJimmy/EndCutscene")
IF IS_VEHICLE_OK(mv_plane.VehIdx)
IF IS_PLAYBACK_GOING_ON_FOR_VEHICLE(mv_plane.VehIdx)
STOP_PLAYBACK_RECORDED_VEHICLE(mv_plane.VehIdx)
ENDIF
SAFE_DELETE_VEHICLE(mv_plane.VehIdx)
ENDIF
mv_plane.VehIdx = CREATE_VEHICLE(mv_plane.VehName, <<1684.78, 3255.58, 41.78>>, 284.26)
IF IS_VEHICLE_OK(mv_plane.VehIdx)
SET_VEHICLE_ON_GROUND_PROPERLY(mv_plane.VehIdx)
ADD_VEHICLE_UPSIDEDOWN_CHECK(mv_plane.VehIdx)
SET_VEHICLE_DOORS_LOCKED(mv_plane.VehIdx, VEHICLELOCK_LOCKOUT_PLAYER_ONLY)
SET_VEHICLE_COLOURS(mv_plane.VehIdx, 157, 157)
SET_VEHICLE_EXTRA_COLOURS(mv_plane.VehIdx, 157, 5)
SET_VEHICLE_LIVERY(mv_plane.VehIdx, 3)
SET_VEHICLE_ENGINE_CAN_DEGRADE(mv_plane.VehIdx, FALSE)
SET_VEHICLE_HAS_STRONG_AXLES(mv_plane.VehIdx, TRUE)
SET_VEHICLE_AS_RESTRICTED(mv_plane.VehIdx, 0)
ENDIF
SAFE_REMOVE_BLIP(mv_plane.biBlipIdx)
BREAK
CASE MS_WAITFORJIMMY
DEBUG_PRINT("Doing plane skip for WaitForJimmy")
IF NOT bCompleteShitskip
IF IS_VEHICLE_OK(mv_plane.VehIdx)
IF IS_PLAYBACK_GOING_ON_FOR_VEHICLE(mv_plane.VehIdx)
STOP_PLAYBACK_RECORDED_VEHICLE(mv_plane.VehIdx)
ENDIF
SAFE_DELETE_VEHICLE(mv_plane.VehIdx)
ENDIF
mv_plane.VehIdx = CREATE_VEHICLE(mv_plane.VehName, <<1674.91, 3252.47, 41.69>>, 284.26)
IF IS_VEHICLE_OK(mv_plane.VehIdx)
SET_VEHICLE_ON_GROUND_PROPERLY(mv_plane.VehIdx)
ADD_VEHICLE_UPSIDEDOWN_CHECK(mv_plane.VehIdx)
SET_VEHICLE_DOORS_LOCKED(mv_plane.VehIdx, VEHICLELOCK_LOCKOUT_PLAYER_ONLY)
SET_VEHICLE_COLOURS(mv_plane.VehIdx, 157, 157)
SET_VEHICLE_EXTRA_COLOURS(mv_plane.VehIdx, 157, 5)
SET_VEHICLE_LIVERY(mv_plane.VehIdx, 3)
SET_VEHICLE_ENGINE_CAN_DEGRADE(mv_plane.VehIdx, FALSE)
SET_VEHICLE_HAS_STRONG_AXLES(mv_plane.VehIdx, TRUE)
SET_VEHICLE_AS_RESTRICTED(mv_plane.VehIdx, 0)
ENDIF
SAFE_REMOVE_BLIP(mv_plane.biBlipIdx)
IF NOT IS_PLAYBACK_GOING_ON_FOR_VEHICLE(mv_plane.VehIdx)
IF HAS_VEHICLE_RECORDING_BEEN_LOADED(501, "Eps6_Takeoff")
START_PLAYBACK_RECORDED_VEHICLE(mv_plane.VehIdx, 501, "Eps6_Takeoff")
FORCE_PLAYBACK_RECORDED_VEHICLE_UPDATE(mv_plane.VehIdx)
PAUSE_PLAYBACK_RECORDED_VEHICLE(mv_plane.VehIdx)
DEBUG_PRINT("Started/paused vehicle recording on plane (skip)")
ENDIF
ENDIF
ELSE
SAFE_REMOVE_BLIP(mv_plane.biBlipIdx)
SAFE_DELETE_VEHICLE(mv_plane.VehIdx)
ENDIF
BREAK
ENDSWITCH
SET_VEHICLE_MODEL_IS_SUPPRESSED(mv_plane.VehName, TRUE)
ENDPROC
/// PURPOSE:
/// Give the cultist his default wandering-around task at the start of the mission
PROC CULTIST_GIVE_TASK()
GIVE_WEAPON_TO_PED(mp_Cultist.piPedIdx, WEAPONTYPE_DIGISCANNER, 0, TRUE)
SET_PED_CAN_SWITCH_WEAPON(mp_Cultist.piPedIdx, FALSE)
STOP_PED_SPEAKING(mp_Cultist.piPedIdx, TRUE)
// SET_PED_LEG_IK_MODE(mp_Cultist.piPedIdx, LEG_IK_PARTIAL)
SET_PED_DIES_WHEN_INJURED(mp_Cultist.piPedIdx, TRUE)
SET_PED_CAN_BE_TARGETTED(mp_Cultist.piPedIdx, FALSE)
OPEN_SEQUENCE_TASK(seq)
TASK_GO_TO_COORD_WHILE_AIMING_AT_COORD(NULL, <<-2887.95, 3194.88, 10.06>>, <<-2887.95, 3194.88, 10.06>>, 1.2, FALSE)
TASK_PLAY_ANIM(NULL, "rcmepsilonism6", "cultist_idle_a", REALLY_SLOW_BLEND_IN, REALLY_SLOW_BLEND_OUT)
TASK_GO_TO_COORD_WHILE_AIMING_AT_COORD(NULL, <<-2888.92, 3203.76, 10.60>>, <<-2888.92, 3203.76, 10.60>>, 1.2, FALSE)
TASK_PLAY_ANIM(NULL, "rcmepsilonism6", "cultist_idle_a", REALLY_SLOW_BLEND_IN, REALLY_SLOW_BLEND_OUT)
TASK_GO_TO_COORD_WHILE_AIMING_AT_COORD(NULL, <<-2895.37, 3199.37, 10.03>>, <<-2895.37, 3199.37, 10.03>>, 1.2, FALSE)
TASK_PLAY_ANIM(NULL, "rcmepsilonism6", "cultist_idle_a", REALLY_SLOW_BLEND_IN, REALLY_SLOW_BLEND_OUT)
SET_SEQUENCE_TO_REPEAT(seq, REPEAT_FOREVER)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(mp_Cultist.piPedIdx, seq)
ENDPROC
/// PURPOSE:
/// Sets the Epsilonist up in whatever starting state he should be in, at whatever stage the mission is currently at
PROC SETUP_EPSILONIST()
SWITCH missionStage
CASE MS_INIT
IF IS_ENTITY_ALIVE(mp_Cultist.piPedIdx)
SET_ENTITY_HEADING(mp_Cultist.piPedIdx, 254.1723)
SET_ENTITY_COORDS(mp_Cultist.piPedIdx, << -2881.7554, 3188.1252, 10.1136 >>)
CLEAR_PED_TASKS(mp_Cultist.piPedIdx)
CULTIST_GIVE_TASK()
ELSE
SAFE_DELETE_PED(mp_Cultist.piPedIdx)
mp_Cultist.piPedIdx = CREATE_PED(PEDTYPE_MISSION, cultModel,<< -2881.7554, 3188.1252, 10.1136 >>, 254.1723)
SET_PED_DEFAULT_COMPONENT_VARIATION(mp_Cultist.piPedIdx)
CULTIST_GIVE_TASK()
ENDIF
IF IS_ENTITY_ALIVE(mp_Cultist.piPedIdx)
SET_PED_MAX_MOVE_BLEND_RATIO(mp_Cultist.piPedIdx, 0)
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(mp_Cultist.piPedIdx, TRUE)
SET_PED_CONFIG_FLAG(mp_Cultist.piPedIdx,PCF_DontEnterVehiclesInPlayersGroup, TRUE)
STOP_PED_SPEAKING(mp_Cultist.piPedIdx, TRUE)
// SET_PED_LEG_IK_MODE(mp_Cultist.piPedIdx, LEG_IK_PARTIAL)
SET_PED_DIES_WHEN_INJURED(mp_Cultist.piPedIdx, TRUE)
SET_PED_CAN_BE_TARGETTED(mp_Cultist.piPedIdx, FALSE)
SET_PED_CONFIG_FLAG(mp_Cultist.piPedIdx, PCF_UseKinematicModeWhenStationary, TRUE)
SET_PED_CONFIG_FLAG(mp_Cultist.piPedIdx, PCF_DisableHurt, FALSE)
//SET_PED_CAN_RAGDOLL(mp_Cultist.piPedIdx, FALSE)
SET_PED_RELATIONSHIP_GROUP_HASH(mp_Cultist.piPedIdx, relGroupPlayer)
SET_PED_CONFIG_FLAG(mp_Cultist.piPedIdx, PCF_KeepRelationshipGroupAfterCleanUp, TRUE)
ADD_PED_FOR_DIALOGUE(s_conversation_cult, 4, mp_Cultist.piPedIdx, "TOM", TRUE)
ENDIF
BREAK
CASE MS_FLIGHT
IF IS_ENTITY_ALIVE(mp_Cultist.piPedIdx)
SET_ENTITY_HEADING(mp_Cultist.piPedIdx, 254.1723)
SET_ENTITY_COORDS(mp_Cultist.piPedIdx, << -2889.89, 3198.69, 10.11 >>)
CLEAR_PED_TASKS(mp_Cultist.piPedIdx)
ELSE
SAFE_DELETE_PED(mp_Cultist.piPedIdx)
mp_Cultist.piPedIdx = CREATE_PED(PEDTYPE_MISSION, cultModel,<<-2889.89, 3198.69, 10.11 >>, 254.1723)
SET_PED_DEFAULT_COMPONENT_VARIATION(mp_Cultist.piPedIdx)
ENDIF
IF IS_ENTITY_ALIVE(mp_Cultist.piPedIdx)
SET_PED_MAX_MOVE_BLEND_RATIO(mp_Cultist.piPedIdx, 0)
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(mp_Cultist.piPedIdx, TRUE)
SET_PED_CONFIG_FLAG(mp_Cultist.piPedIdx,PCF_DontEnterVehiclesInPlayersGroup, TRUE)
STOP_PED_SPEAKING(mp_Cultist.piPedIdx, TRUE)
// SET_PED_LEG_IK_MODE(mp_Cultist.piPedIdx, LEG_IK_PARTIAL)
SET_PED_DIES_WHEN_INJURED(mp_Cultist.piPedIdx, TRUE)
SET_PED_CAN_BE_TARGETTED(mp_Cultist.piPedIdx, FALSE)
SET_PED_CONFIG_FLAG(mp_Cultist.piPedIdx, PCF_DisableHurt, FALSE)
SET_PED_CONFIG_FLAG(mp_Cultist.piPedIdx, PCF_UseKinematicModeWhenStationary, TRUE)
//SET_PED_CAN_RAGDOLL(mp_Cultist.piPedIdx, FALSE)
SET_PED_RELATIONSHIP_GROUP_HASH(mp_Cultist.piPedIdx, relGroupPlayer)
SET_PED_CONFIG_FLAG(mp_Cultist.piPedIdx, PCF_KeepRelationshipGroupAfterCleanUp, TRUE)
ADD_PED_FOR_DIALOGUE(s_conversation_cult, 4, mp_Cultist.piPedIdx, "TOM", TRUE)
ENDIF
BREAK
DEFAULT
IF IS_ENTITY_ALIVE(mp_Cultist.piPedIdx)
IF IS_PED_IN_GROUP(mp_Cultist.piPedIdx)
REMOVE_PED_FROM_GROUP(mp_Cultist.piPedIdx)
ENDIF
ENDIF
SAFE_REMOVE_BLIP(mp_Cultist.biPedBlip)
SAFE_DELETE_PED(mp_Cultist.piPedIdx)
BREAK
ENDSWITCH
SET_MODEL_AS_NO_LONGER_NEEDED(cultModel)
ENDPROC
/// PURPOSE:
/// Loads and sets up whatever resources we need when going into a stage through a skip/checkpoint
PROC LoadSkip()
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
KILL_ANY_CONVERSATION()
ENDIF
SWITCH missionStage
CASE MS_INIT
REQUEST_MODEL(cultModel)
REQUEST_MODEL(vehModel)
REQUEST_ANIM_DICT("rcm_epsilonism4")
WHILE NOT HAS_MODEL_LOADED(cultModel)
OR NOT HAS_MODEL_LOADED(vehModel)
OR NOT HAS_ANIM_DICT_LOADED("rcm_epsilonism4")
DEBUG_PRINT("WAITING FOR MS_INIT RESOURCES")
WAIT(0)
ENDWHILE
bShownGetInPlane = FALSE
bShownGoToAirfield = FALSE
// bCultistRagdoll = FALSE
bCultistAimConv = FALSE
bDoneMusic = FALSE
bSpawnJimmy = FALSE
bSetCP = FALSE
bCultistNoSubIntro = FALSE
iCultistRoamStage = 0
IntroState = INTRO_INIT
EpsState = EPS_INIT
EpsMode = STATE_SETUP
SETUP_PLAYER()
SETUP_JIMMY()
SETUP_PLANE()
SETUP_EPSILONIST()
SAFE_REMOVE_BLIP(pcp_LandingGoal.biBlipIdx)
SET_MODEL_AS_NO_LONGER_NEEDED(cultModel)
SET_MODEL_AS_NO_LONGER_NEEDED(vehModel)
SET_MAX_WANTED_LEVEL(0) // Because this won't be triggered by the phonecall in a skip
BREAK
CASE MS_FLIGHT
REQUEST_MODEL(vehModel)
REQUEST_MODEL(cultModel)
WHILE NOT HAS_MODEL_LOADED(vehModel)
OR NOT HAS_MODEL_LOADED(cultModel)
DEBUG_PRINT("WAITING FOR MS_FLIGHT RESOURCES")
WAIT(0)
ENDWHILE
bShownGoToAirfield = FALSE
// bCultistRagdoll = FALSE
bCultistAimConv = FALSE
bSpawnJimmy = FALSE
bSetCP = FALSE
IntroState = INTRO_INPLANE
EpsState = EPS_SAFE
EpsMode = STATE_SETUP
SETUP_PLANE()
SETUP_JIMMY()
SETUP_PLAYER()
SETUP_EPSILONIST()
STOP_SOUND(iDetectorBeepID)
STOP_SOUND(iDetectorHumID)
TRIGGER_MUSIC_EVENT("EPS6_START")
SET_MAX_WANTED_LEVEL(0) // Because this won't be triggered by the phonecall in a skip
SET_MODEL_AS_NO_LONGER_NEEDED(cultModel)
SET_MODEL_AS_NO_LONGER_NEEDED(vehModel)
BREAK
CASE MS_LANDING
REQUEST_MODEL(vehModel)
WHILE NOT HAS_MODEL_LOADED(vehModel)
DEBUG_PRINT("WAITING FOR MS_LANDING SKIP RESOURCES")
WAIT(0)
ENDWHILE
IntroState = INTRO_INTERRUPTED
EpsState = EPS_FLEEING
bShownLandAtAirfield = FALSE
bShownGoToJimmy = FALSE
bSpawnJimmy = FALSE
SETUP_PLAYER()
SETUP_PLANE()
SETUP_EPSILONIST()
SAFE_REMOVE_BLIP(mp_Jimmy.biPedBlip)
STOP_SOUND(iDetectorBeepID)
STOP_SOUND(iDetectorHumID)
TRIGGER_MUSIC_EVENT("EPS6_START")
SET_REPLAY_MID_MISSION_STAGE_WITH_NAME(CP_LANDING, "Landing stage") // Set the checkpoint now in case we've shitskipped
bSetCP = TRUE // Don't try to set this again now
SET_MAX_WANTED_LEVEL(5) // Because this won't be triggered by the phonecall in a skip
IF IsPlaneOK()
IF NOT IS_REPLAY_BEING_SET_UP()
WAIT_FOR_WORLD_TO_LOAD(GET_ENTITY_COORDS(mv_plane.VehIdx), 200)
ENDIF
IF IsPlaneOK() // Since the first check is no longer valid after waiting for the world to load...
FREEZE_ENTITY_POSITION(mv_plane.VehIdx, FALSE)
if HAS_VEHICLE_RECORDING_BEEN_LOADED(500, "Eps6_LandingSkip")
IF NOT IS_PLAYBACK_GOING_ON_FOR_VEHICLE(mv_plane.VehIdx)
IF NOT IS_REPLAY_BEING_SET_UP()
DEBUG_PRINT("Doing plane boost")
SET_PLAYER_CONTROL(PLAYER_ID(), FALSE)
START_PLAYBACK_RECORDED_VEHICLE(mv_plane.VehIdx, 500, "Eps6_LandingSkip")
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
SET_MODEL_AS_NO_LONGER_NEEDED(vehModel)
BREAK
CASE MS_SEEJIMMY
REQUEST_ANIM_DICT(mp_Jimmy.AnimDict)
REQUEST_MODEL(vehModel)
REQUEST_MODEL(mv_RewardCar.VehName)
REQUEST_NPC_PED_MODEL(CHAR_JIMMY_BOSTON)
WHILE NOT HAS_MODEL_LOADED(vehModel)
OR NOT HAS_MODEL_LOADED(mv_RewardCar.VehName)
OR NOT HAS_ANIM_DICT_LOADED(mp_Jimmy.AnimDict)
OR NOT HAS_NPC_PED_MODEL_LOADED(CHAR_JIMMY_BOSTON)
DEBUG_PRINT("WAITING FOR MS_SEEJIMMY RESOURCES")
WAIT(0)
ENDWHILE
SETUP_PLAYER()
SETUP_PLANE()
SETUP_JIMMY()
SETUP_CAR()
SETUP_EPSILONIST()
SAFE_REMOVE_BLIP(pcp_LandingGoal.biBlipIdx)
SAFE_REMOVE_BLIP(mp_Cultist.biPedBlip)
STOP_SOUND(iDetectorBeepID)
STOP_SOUND(iDetectorHumID)
TRIGGER_MUSIC_EVENT("EPS6_START")
SET_MAX_WANTED_LEVEL(5) // Because this won't be triggered by the phonecall in a skip
SET_MODEL_AS_NO_LONGER_NEEDED(vehModel)
IF iNavBlockingObj != -1
REMOVE_NAVMESH_BLOCKING_OBJECT(iNavBlockingObj)
DEBUG_PRINT("Navmesh blocking object removed")
iNavBlockingObj = -1
ENDIF
g_iAbandonCap = 5 // In case we've Z-skipped to the same stage (and effectively reset it), and need to reset the abandonment check
BREAK
CASE MS_ENDCUTSCENE
IF NOT IS_REPLAY_BEING_SET_UP()
REQUEST_CUTSCENE("ep_6_rcm", CUTSCENE_REQUESTED_FROM_Z_SKIP)
ENDIF
REQUEST_MODEL(mv_RewardCar.VehName)
REQUEST_MODEL(mv_plane.VehName)
REQUEST_ANIM_DICT(mp_Jimmy.AnimDict)
REQUEST_VEHICLE_RECORDING(501, "Eps6_Takeoff")
REQUEST_NPC_PED_MODEL(CHAR_JIMMY_BOSTON)
IF NOT IS_REPLAY_BEING_SET_UP()
WHILE NOT HAS_MODEL_LOADED(mv_RewardCar.VehName)
OR NOT HAS_CUTSCENE_LOADED()
OR NOT HAS_MODEL_LOADED(mv_plane.VehName)
OR NOT HAS_ANIM_DICT_LOADED(mp_Jimmy.AnimDict)
OR NOT HAS_VEHICLE_RECORDING_BEEN_LOADED(501, "Eps6_Takeoff")
OR NOT HAS_NPC_PED_MODEL_LOADED(CHAR_JIMMY_BOSTON)
IF CAN_REQUEST_ASSETS_FOR_CUTSCENE_ENTITY()
SET_CUTSCENE_PED_PROP_VARIATION("Jimmy_Boston", ANCHOR_EYES, 0)
ENDIF
DEBUG_PRINT("WAITING FOR MS_ENDCUTSCENE RESOURCES")
WAIT(0)
ENDWHILE
ELSE
WHILE NOT HAS_MODEL_LOADED(mv_RewardCar.VehName)
OR NOT HAS_MODEL_LOADED(mv_plane.VehName)
OR NOT HAS_ANIM_DICT_LOADED(mp_Jimmy.AnimDict)
OR NOT HAS_VEHICLE_RECORDING_BEEN_LOADED(501, "Eps6_Takeoff")
OR NOT HAS_NPC_PED_MODEL_LOADED(CHAR_JIMMY_BOSTON)
DEBUG_PRINT("WAITING FOR MS_ENDCUTSCENE RESOURCES")
WAIT(0)
ENDWHILE
ENDIF
SAFE_REMOVE_BLIP(pcp_LandingGoal.biBlipIdx)
SAFE_REMOVE_BLIP(mp_Cultist.biPedBlip)
STOP_SOUND(iDetectorBeepID)
STOP_SOUND(iDetectorHumID)
SET_MAX_WANTED_LEVEL(5) // Because this won't be triggered by the phonecall in a skip
SETUP_CAR()
SETUP_PLANE()
SETUP_JIMMY()
SETUP_PLAYER()
SETUP_EPSILONIST()
IF NOT IS_REPLAY_BEING_SET_UP()
IF IS_SCREEN_FADED_OUT()
WAIT(5000) // Do a wait if the screen is faded out to give the world some time to load in
ENDIF
ENDIF
IF iNavBlockingObj != -1
REMOVE_NAVMESH_BLOCKING_OBJECT(iNavBlockingObj)
DEBUG_PRINT("Navmesh blocking object removed")
iNavBlockingObj = -1
ENDIF
IF iNavBlockingObj = -1
iNavBlockingObj = ADD_NAVMESH_BLOCKING_OBJECT(<<1687.9539, 3277.7268, 40.2500>>, <<6,6,6>>, 0)
DEBUG_PRINT("Navmesh blocking object created")
ENDIF
BREAK
CASE MS_WAITFORJIMMY
REQUEST_ANIM_DICT(mp_Jimmy.AnimDict)
REQUEST_MODEL(mv_RewardCar.VehName)
REQUEST_MODEL(mv_plane.VehName)
REQUEST_VEHICLE_RECORDING(501, "Eps6_Takeoff")
REQUEST_NPC_PED_MODEL(CHAR_JIMMY_BOSTON)
WHILE NOT HAS_MODEL_LOADED(mv_RewardCar.VehName)
OR NOT HAS_MODEL_LOADED(mv_plane.VehName)
OR NOT HAS_ANIM_DICT_LOADED(mp_Jimmy.AnimDict)
OR NOT HAS_VEHICLE_RECORDING_BEEN_LOADED(501, "Eps6_Takeoff")
OR NOT HAS_NPC_PED_MODEL_LOADED(CHAR_JIMMY_BOSTON)
DEBUG_PRINT("WAITING FOR MS_WAITFORJIMMY RESOURCES")
WAIT(0)
ENDWHILE
SAFE_REMOVE_BLIP(pcp_LandingGoal.biBlipIdx)
SAFE_REMOVE_BLIP(mp_Cultist.biPedBlip)
STOP_SOUND(iDetectorBeepID)
STOP_SOUND(iDetectorHumID)
SET_MAX_WANTED_LEVEL(5) // Because this won't be triggered by the phonecall in a skip
SETUP_PLAYER()
SETUP_PLANE()
SETUP_JIMMY()
SETUP_CAR()
SETUP_EPSILONIST()
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE:
///
/// RETURNS:
///
FUNC BOOL IS_PLAYER_IN_EPS_PLANE()
IF IS_VEHICLE_OK(mv_plane.VehIdx)
AND IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID(), TRUE)
IF mv_plane.VehIdx = GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID(), TRUE)
DEBUG_PRINT("Player is in plane...")
RETURN TRUE
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
//PURPOSE: Makes Jimmy Boston flee the player.
PROC MAKE_JIMMY_FLEE()
IF IS_ENTITY_ALIVE(mp_Jimmy.piPedIdx)
CLEAR_PED_TASKS(mp_Jimmy.piPedIdx)
SET_PED_KEEP_TASK(mp_Jimmy.piPedIdx, TRUE)
TASK_SMART_FLEE_PED(mp_Jimmy.piPedIdx, PLAYER_PED_ID(), 100, -1)
ENDIF
ENDPROC
//PURPOSE: Checks whether the player is attacking or shooting at, or near, Jimmy Boston and fails if so
PROC CHECK_JIMMY_AGGRO()
IF IS_ENTITY_ALIVE(mp_Jimmy.piPedIdx)
IF HAS_PLAYER_THREATENED_PED(mp_Jimmy.piPedIdx, FALSE, DEFAULT, DEFAULT, TRUE)
OR IS_BULLET_IN_AREA(GET_ENTITY_COORDS(mp_Jimmy.piPedIdx), 3, TRUE)
IF missionStage <> MS_WAITFORJIMMY
AND missionStage <> MS_SEEJIMMY
bTeleOnFail = TRUE
ENDIF
FailedReason = FAILED_ATTACKED_JIMMY
subState = SS_INIT
missionStage = MS_FAILED
TRIGGER_MUSIC_EVENT("EPS_FAIL")
ADD_PED_FOR_DIALOGUE(s_conversation_outro, 3, mp_Jimmy.piPedIdx, "JIMMYBOSTON")
ADD_PED_FOR_DIALOGUE(s_conversation_outro, ENUM_TO_INT(CHAR_MICHAEL), PLAYER_PED_ID(), "MICHAEL")
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
KILL_ANY_CONVERSATION()
ADD_NON_CRITICAL_STANDARD_CONVERSATION_TO_BUFFER(s_conversation_outro, "EPS6AUD", "EPS6_SHOT", CONV_PRIORITY_VERY_HIGH, DO_NOT_DISPLAY_SUBTITLES)
ELSE
CREATE_CONVERSATION(s_conversation_outro, "EPS6AUD", "EPS6_SHOT", CONV_PRIORITY_VERY_HIGH, DO_NOT_DISPLAY_SUBTITLES)
ENDIF
MAKE_JIMMY_FLEE()
ELIF HAS_PED_BUMPED_PED_WITH_VEHICLE(PLAYER_PED_ID(), mp_Jimmy.piPedIdx)
OR IS_BULLET_IN_AREA(GET_ENTITY_COORDS(mp_Jimmy.piPedIdx), 3, FALSE)
OR IS_PED_BEING_JACKED(mp_Jimmy.piPedIdx)
IF missionStage <> MS_WAITFORJIMMY
AND missionStage <> MS_SEEJIMMY
bTeleOnFail = TRUE
ENDIF
FailedReason = FAILED_SPOOKED_JIMMY
subState = SS_INIT
missionStage = MS_FAILED
TRIGGER_MUSIC_EVENT("EPS_FAIL")
ADD_PED_FOR_DIALOGUE(s_conversation_outro, 3, mp_Jimmy.piPedIdx, "JIMMYBOSTON")
ADD_PED_FOR_DIALOGUE(s_conversation_outro, ENUM_TO_INT(CHAR_MICHAEL), PLAYER_PED_ID(), "MICHAEL")
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
KILL_ANY_CONVERSATION()
ADD_NON_CRITICAL_STANDARD_CONVERSATION_TO_BUFFER(s_conversation_outro, "EPS6AUD", "EPS6_SHOT", CONV_PRIORITY_VERY_HIGH, DO_NOT_DISPLAY_SUBTITLES)
ELSE
CREATE_CONVERSATION(s_conversation_outro, "EPS6AUD", "EPS6_SHOT", CONV_PRIORITY_VERY_HIGH, DO_NOT_DISPLAY_SUBTITLES)
ENDIF
MAKE_JIMMY_FLEE()
ELIF HAS_ENTITY_BEEN_DAMAGED_BY_ENTITY(mp_Jimmy.piPedIdx, PLAYER_PED_ID())
IF HAS_PED_BEEN_DAMAGED_BY_WEAPON(mp_Jimmy.piPedIdx, WEAPONTYPE_INVALID, GENERALWEAPON_TYPE_ANYWEAPON)
IF missionStage <> MS_WAITFORJIMMY
AND missionStage <> MS_SEEJIMMY
bTeleOnFail = TRUE
ENDIF
FailedReason = FAILED_HURT_JIMMY
subState = SS_INIT
missionStage = MS_FAILED
TRIGGER_MUSIC_EVENT("EPS_FAIL")
ADD_PED_FOR_DIALOGUE(s_conversation_outro, 3, mp_Jimmy.piPedIdx, "JIMMYBOSTON")
ADD_PED_FOR_DIALOGUE(s_conversation_outro, ENUM_TO_INT(CHAR_MICHAEL), PLAYER_PED_ID(), "MICHAEL")
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
KILL_ANY_CONVERSATION()
ADD_NON_CRITICAL_STANDARD_CONVERSATION_TO_BUFFER(s_conversation_outro, "EPS6AUD", "EPS6_SHOT", CONV_PRIORITY_VERY_HIGH, DO_NOT_DISPLAY_SUBTITLES)
ELSE
CREATE_CONVERSATION(s_conversation_outro, "EPS6AUD", "EPS6_SHOT", CONV_PRIORITY_VERY_HIGH, DO_NOT_DISPLAY_SUBTITLES)
ENDIF
MAKE_JIMMY_FLEE()
ENDIF
ENDIF
ELSE // Jimmy is dead
IF bSpawnJimmy = TRUE // Only check this after we've spawned Jimmy!
IF missionStage <> MS_WAITFORJIMMY
AND missionStage <> MS_SEEJIMMY
bTeleOnFail = TRUE
ENDIF
FailedReason = FAILED_KILLED_JIMMY
subState = SS_INIT
missionStage = MS_FAILED
TRIGGER_MUSIC_EVENT("EPS_FAIL")
ENDIF
ENDIF
ENDPROC
//PURPOSE: Checks whether the player has flown the plane too close to Jimmy Boston, usually when trying to land it.
PROC CHECK_JIMMY_PLANE_FEAR()
IF IS_ENTITY_ALIVE(mp_Jimmy.piPedIdx)
// Warning
IF GET_DISTANCE_BETWEEN_ENTITIES(mp_Jimmy.piPedIdx, mv_plane.VehIdx) < 17
IF NOT bPlaneTooCloseConv
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF CREATE_CONVERSATION(s_conversation_outro, "EPS6AUD", "EPS6_CLOSE", CONV_PRIORITY_VERY_HIGH)
bPlaneTooCloseConv = TRUE
iJimmyPlaneWarningTimer = GET_GAME_TIMER()
CLEAR_PED_TASKS(mp_Jimmy.piPedIdx)
TASK_LOOK_AT_ENTITY(mp_Jimmy.piPedIdx, PLAYER_PED_ID(), 10000, SLF_WIDEST_PITCH_LIMIT|SLF_WIDEST_YAW_LIMIT)
DEBUG_PRINT("*** Played diag EPS6_CLOSE")
ENDIF
ENDIF
ELSE
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF (GET_GAME_TIMER() - iJimmyPlaneWarningTimer) > 10000
bPlaneTooCloseConv = FALSE
ENDIF
ENDIF
ENDIF
ELSE
IF NOT IS_ENTITY_PLAYING_ANIM(mp_Jimmy.piPedIdx, mp_Jimmy.AnimDict, mp_Jimmy.AnimName)
DEBUG_PRINT("*** Retasking Jimmy to play anim from plane fear check")
TASK_PLAY_ANIM(mp_Jimmy.piPedIdx, mp_Jimmy.AnimDict, mp_Jimmy.AnimName, NORMAL_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_UPPERBODY | AF_LOOPING | AF_SECONDARY)
ENDIF
ENDIF
// Actual fail
IF GET_DISTANCE_BETWEEN_ENTITIES(mp_Jimmy.piPedIdx, mv_plane.VehIdx) < 12
MAKE_JIMMY_FLEE()
FailedReason = FAILED_SPOOKED_JIMMY
subState = SS_INIT
missionStage = MS_FAILED
TRIGGER_MUSIC_EVENT("EPS_FAIL")
EXIT
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Removes the cultist from the player's group and makes the them flee the player
PROC MAKE_CULTIST_FLEE()
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
KILL_FACE_TO_FACE_CONVERSATION_DO_NOT_FINISH_LAST_LINE()
ENDIF
IF IS_PED_UNINJURED(mp_Cultist.piPedIdx)
CLEAR_PED_TASKS(mp_Cultist.piPedIdx)
IF IS_PED_IN_GROUP(mp_Cultist.piPedIdx)
REMOVE_PED_FROM_GROUP(mp_Cultist.piPedIdx)
ENDIF
TASK_SMART_FLEE_PED(mp_Cultist.piPedIdx, PLAYER_PED_ID(), 500, -1)
SAFE_REMOVE_BLIP(mp_Cultist.biPedBlip)
ENDIF
ENDPROC
/// PURPOSE:
/// Tells what side of a plane a point is on
/// PARAMS:
/// pNorm - plane normal
/// pOrg - plane origin
/// v - point we want to check
/// RETURNS:
/// Returns -1 if behind plane, +1 if in front and 0 if on plane
FUNC INT GET_PLANE_SIDE(VECTOR pNorm, VECTOR pOrg, VECTOR v)
FLOAT dot = DOT_PRODUCT(v - pOrg, pNorm)
IF (dot < 0)
RETURN -1 // it's behind the plane
ELIF (dot > 0)
RETURN 1 // it's in front of the plane
ENDIF
RETURN 0 // ON PLANE
ENDFUNC
/// PURPOSE:
/// Switch the Cultist to a new state
/// PARAMS:
/// newState - The state we want to put the Cultist into
PROC SWITCH_CULTIST(EPS_STATE newState)
EPS_STATE_PRINT(newState)
EpsState = newState
EpsMode = STATE_SETUP
ENDPROC
/// PURPOSE:
/// Checks if the player damaged the plane as long as they're not in it
/// RETURNS:
/// TRUE if they damaged it, FALSE otherwise
FUNC BOOL DID_PLAYER_DAMAGE_PLANE()
if IsPlaneOK()
AND IS_ENTITY_ALIVE(mp_Cultist.piPedIdx) // Don't care if the player damages the plane when the cultist is already dead!
IF NOT IS_PED_IN_VEHICLE(PLAYER_PED_ID(), mv_plane.VehIdx, TRUE)
IF HAS_ENTITY_BEEN_DAMAGED_BY_ENTITY(mv_plane.VehIdx, PLAYER_PED_ID())
DEBUG_PRINT("Player damaged plane")
CLEAR_ENTITY_LAST_DAMAGE_ENTITY(mv_plane.VehIdx)
RETURN TRUE
ENDIF
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
FUNC BOOL DID_PLAYER_PLACE_STICKY_BOMB_ON_PLANE()
if IsPlaneOK()
IF IS_PROJECTILE_TYPE_WITHIN_DISTANCE(GET_ENTITY_COORDS(mv_plane.VehIdx, FALSE), WEAPONTYPE_STICKYBOMB, 10)
DEBUG_PRINT("Sticky bomb in range of plane")
RETURN TRUE
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
PROC STICKY_BOMB_FAIL()
IF IS_ENTITY_ALIVE(mp_Cultist.piPedIdx)
SWITCH_CULTIST(EPS_FLEEING)
ENDIF
FailedReason = FAILED_STICKYBOMB
subState = SS_INIT
missionStage = MS_FAILED
TRIGGER_MUSIC_EVENT("EPS_FAIL")
ENDPROC
/// PURPOSE:
/// Fails the mission if the player has aggro'd or harmed the Cultist in any way
PROC CULTIST_AGGRO_FAIL()
IF IS_ENTITY_ALIVE(mp_Cultist.piPedIdx)
IF IS_PED_UNINJURED(mp_Cultist.piPedIdx)
IF NOT HAS_ENTITY_BEEN_DAMAGED_BY_ENTITY(mp_Cultist.piPedIdx, PLAYER_PED_ID())
DEBUG_PRINT("EPSILONIST got scared by player, will never stop fleeing...")
SWITCH_CULTIST(EPS_FLEEING)
FailedReason = FAILED_SPOOKED_BUDDY
subState = SS_INIT
missionStage = MS_FAILED
TRIGGER_MUSIC_EVENT("EPS_FAIL")
ELSE
// Is injured but not dead - hurt?
DEBUG_PRINT("EPSILONIST got hurt by player - 2ND CHECK, NOT INJURED?")
SWITCH_CULTIST(EPS_FLEEING)
FailedReason = FAILED_HURT_BUDDY
subState = SS_INIT
missionStage = MS_FAILED
TRIGGER_MUSIC_EVENT("EPS_FAIL")
ENDIF
ELSE
// Is injured but not dead - hurt?
DEBUG_PRINT("EPSILONIST got hurt by player...")
FailedReason = FAILED_HURT_BUDDY
subState = SS_INIT
missionStage = MS_FAILED
TRIGGER_MUSIC_EVENT("EPS_FAIL")
ENDIF
ELSE
// if the ped is not alive at all, player must've killed him
DEBUG_PRINT("EPSILONIST got killed by player...")
FailedReason = FAILED_KILLED_BUDDY
subState = SS_INIT
missionStage = MS_FAILED
TRIGGER_MUSIC_EVENT("EPS_FAIL")
ENDIF
IF IntroState <= INTRO_SEENMIKE
IntroState = INTRO_INTERRUPTED
ENDIF
// The aggro check doesn't always catch every instance of the ped getting killed
IF DOES_ENTITY_EXIST(mp_Cultist.piPedIdx)
IF HAS_ENTITY_BEEN_DAMAGED_BY_ENTITY(mp_Cultist.piPedIdx, PLAYER_PED_ID())
IF IS_ENTITY_DEAD(mp_Cultist.piPedIdx)
DEBUG_PRINT("EPSILONIST got killed by player - 2ND CHECK")
FailedReason = FAILED_KILLED_BUDDY
subState = SS_INIT
missionStage = MS_FAILED
TRIGGER_MUSIC_EVENT("EPS_FAIL")
ENDIF
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// A kind of 'soft aggro' check against the Cultist that only checks for if the player outright damages him or shoots around him
/// This is being used for when the Cultist is doing his 'attacking' thing and the player has to be shooting around the guy,
/// because we don't want to scare him off when HAS_PLAYER_THREATENED_PED() would return true
/// RETURNS:
/// TRUE if the player damages the Cultist, FALSE otherwise.
FUNC BOOL CULTIST_CHECK_PLAYER_DAMAGE()
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
AND IS_ENTITY_ALIVE(mp_Cultist.piPedIdx)
if IS_PLAYER_SHOOTING_NEAR_PED(mp_Cultist.piPedIdx, FALSE)
DEBUG_PRINT("Player shot near cultist")
RETURN TRUE
ENDIF
IF HAS_ENTITY_BEEN_DAMAGED_BY_ENTITY(mp_Cultist.piPedIdx, PLAYER_PED_ID())
DEBUG_PRINT("Player damaged cultist")
RETURN TRUE
ENDIF
ELSE
IF DOES_ENTITY_EXIST(mp_Cultist.piPedIdx)
IF HAS_ENTITY_BEEN_DAMAGED_BY_ENTITY(mp_Cultist.piPedIdx, PLAYER_PED_ID(), TRUE)
DEBUG_PRINT("Player damaged cultist (while he wasn't alive, so dead?)")
RETURN TRUE
ENDIF
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// Checks player aggro against the Cultist, and makes them flee.
/// RETURNS:
/// TRUE if the player aggros the Cultist, FALSE otherwise.
FUNC BOOL CULTIST_CHECK_AGGRO()
if HAS_PLAYER_THREATENED_PED(mp_Cultist.piPedIdx, FALSE)
OR HAS_PED_BUMPED_PED_WITH_VEHICLE(PLAYER_PED_ID(), mp_Cultist.piPedIdx, FALSE)
OR DID_PLAYER_DAMAGE_PLANE()
if HAS_PLAYER_THREATENED_PED(mp_Cultist.piPedIdx, FALSE)
DEBUG_PRINT("Player threatened cultist")
ENDIF
IF HAS_PED_BUMPED_PED_WITH_VEHICLE(PLAYER_PED_ID(), mp_Cultist.piPedIdx, FALSE)
DEBUG_PRINT("Player bumped cultist with vehicle")
ENDIF
iCultistRoamStage = 3 // To ensure combat isn't interrupted by roaming commands
IF IS_PED_UNINJURED(mp_Cultist.piPedIdx)
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
KILL_ANY_CONVERSATION()
ENDIF
PLAY_PED_AMBIENT_SPEECH_WITH_VOICE(mp_Cultist.piPedIdx, "FIGHT_RUN", "TOM", SPEECH_PARAMS_FORCE_FRONTEND)
ENDIF
return true
ENDIF
RETURN FALSE
ENDFUNC
VECTOR vTempPlayer
/// PURPOSE:
/// Manage where the cultist should stand during the intro sequence
PROC MANAGE_CULTISTS_POSITION()
IF EpsState = EPS_FOLLOW
SWITCH EpsMove
CASE EPSMOVE_OK
// Nothing to do!
BREAK
CASE EPSMOVE_CHANGE
IF IS_ENTITY_ALIVE(mp_Cultist.piPedIdx)
AND IS_ENTITY_ALIVE(PLAYER_PED_ID())
CLEAR_PED_TASKS(mp_Cultist.piPedIdx)
vTempPlayer = GET_ENTITY_COORDS(PLAYER_PED_ID())
OPEN_SEQUENCE_TASK(seq)
TASK_LOOK_AT_ENTITY(NULL, PLAYER_PED_ID(), -1)
TASK_FOLLOW_NAV_MESH_TO_COORD(NULL, vTempPlayer, PEDMOVEBLENDRATIO_WALK)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(mp_Cultist.piPedIdx, seq)
CLEAR_SEQUENCE_TASK(seq)
EpsMove = EPSMOVE_MOVING
ENDIF
BREAK
CASE EPSMOVE_MOVING
IF IS_ENTITY_ALIVE(mp_Cultist.piPedIdx)
AND IS_ENTITY_ALIVE(PLAYER_PED_ID())
IF GET_DISTANCE_BETWEEN_ENTITIES(mp_Cultist.piPedIdx, PLAYER_PED_ID()) < 5
OR GET_SCRIPT_TASK_STATUS(mp_Cultist.piPedIdx, SCRIPT_TASK_PERFORM_SEQUENCE) = FINISHED_TASK
CLEAR_PED_TASKS(mp_Cultist.piPedIdx)
TASK_TURN_PED_TO_FACE_ENTITY(mp_Cultist.piPedIdx, PLAYER_PED_ID(), -1)
EpsMove = EPSMOVE_OK
ENDIF
ENDIF
BREAK
ENDSWITCH
ENDIF
ENDPROC
PROC DO_CULTIST_COMBAT_MOVEMENT(VECTOR vCoord, PED_INDEX target)
IF IS_PED_UNINJURED(mp_Cultist.piPedIdx)
AND IS_ENTITY_ALIVE(target)
OPEN_SEQUENCE_TASK(seq)
TASK_GO_TO_COORD_WHILE_AIMING_AT_ENTITY(NULL, vCoord, target, 1, FALSE, 0.5, 4, TRUE)
TASK_COMBAT_PED(NULL, target)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(mp_Cultist.piPedIdx, seq)
CLEAR_SEQUENCE_TASK(seq)
ENDIF
ENDPROC
/// PURPOSE:
/// Manage whether ragdoll is enabled for the Cultist or not depending on whether the player is in a vehicle
PROC MANAGE_CULTIST_RAGDOLL()
IF bTomSaidPushedOver = FALSE
IF IS_PED_UNINJURED(mp_Cultist.piPedIdx)
AND IS_ENTITY_ALIVE(PLAYER_PED_ID())
IF bTomPushedOver = FALSE
IF IS_ENTITY_TOUCHING_ENTITY(PLAYER_PED_ID(), mp_Cultist.piPedIdx)
AND IS_PED_RAGDOLL(mp_Cultist.piPedIdx)
KILL_ANY_CONVERSATION()
DEBUG_PRINT("Player knocked Tom over!")
bTomPushedOver = TRUE
ENDIF
ELSE
IF IS_PED_UNINJURED(mp_Cultist.piPedIdx)
IF IS_PED_GETTING_UP(mp_Cultist.piPedIdx)
OR IS_PED_ON_FOOT(mp_Cultist.piPedIdx)
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
AND NOT IS_MESSAGE_BEING_DISPLAYED()
IF CREATE_CONVERSATION(s_conversation_cult, "EPS6AUD", "EPS6_PUSHED", CONV_PRIORITY_HIGH)
bTomPushedOver = FALSE
bTomSaidPushedOver = TRUE
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// State machine to handle Tom wandering around at the start of Eps 6
PROC DO_DETECTOR_WANDER()
IF IS_ENTITY_ALIVE(mp_Cultist.piPedIdx)
SWITCH Eps6Wander
CASE WANDER_INIT
iWanderStage = 0
vTomCoords[0] = <<-2887.15, 3197.88, 10.17>>
vTomCoords[1] = <<-2888.92, 3203.76, 10.60>>
vTomCoords[2] = <<-2895.37, 3199.37, 10.03>>
REQUEST_ANIM_DICT("rcmepsilonism6")
IF HAS_ANIM_DICT_LOADED("rcmepsilonism6")
AND NOT IS_ENTITY_PLAYING_ANIM(mp_Cultist.piPedIdx, "rcmepsilonism6", "cultist_idle_a") // Don't interrupt this anim if it's ongoing
TASK_PLAY_ANIM(mp_Cultist.piPedIdx, "rcmepsilonism6", "cultist_upperstatic", DEFAULT, DEFAULT, -1, AF_UPPERBODY|AF_SECONDARY|AF_LOOPING)
Eps6Wander = WANDER_GOTO
DEBUG_PRINT("Initialised Eps 6 Tom state machine")
ENDIF
BREAK
CASE WANDER_GOTO
IF NOT IsPedPerformingTask(mp_Cultist.piPedIdx, SCRIPT_TASK_FOLLOW_NAV_MESH_TO_COORD)
TASK_FOLLOW_NAV_MESH_TO_COORD(mp_Cultist.piPedIdx, vTomCoords[iWanderStage], PEDMOVEBLENDRATIO_WALK, DEFAULT_TIME_BEFORE_WARP)
DEBUG_PRINT("Eps 6: Nav tasking Tom...")
Eps6Wander = WANDER_NOWGOINGTO
ENDIF
BREAK
CASE WANDER_NOWGOINGTO
IF GET_DISTANCE_BETWEEN_ENTITY_AND_COORD(mp_Cultist.piPedIdx, vTomCoords[iWanderStage]) <= 1.2
Eps6Wander = WANDER_IDLEANIM
DEBUG_PRINT("Eps 6: Tom at coord; do idle anim")
ENDIF
BREAK
CASE WANDER_IDLEANIM
CLEAR_PED_TASKS(mp_Cultist.piPedIdx)
TASK_PLAY_ANIM(mp_Cultist.piPedIdx, "rcmepsilonism6", "cultist_idle_a", FAST_BLEND_IN, REALLY_SLOW_BLEND_OUT, -1, AF_FORCE_START)
FORCE_PED_AI_AND_ANIMATION_UPDATE(mp_Cultist.piPedIdx)
Eps6Wander = WANDER_IDLEFINISH
DEBUG_PRINT("Eps 6: Done Tom idle anim")
BREAK
CASE WANDER_IDLEFINISH
IF IS_ENTITY_PLAYING_ANIM(mp_Cultist.piPedIdx, "rcmepsilonism6", "cultist_idle_a")
IF GET_ENTITY_ANIM_CURRENT_TIME(mp_Cultist.piPedIdx, "rcmepsilonism6", "cultist_idle_a") >=0.98
IF iWanderStage >= 2
iWanderStage = 0
ELSE
iWanderStage++
ENDIF
TASK_PLAY_ANIM(mp_Cultist.piPedIdx, "rcmepsilonism6", "cultist_upperstatic", FAST_BLEND_IN, DEFAULT, -1, AF_UPPERBODY|AF_SECONDARY|AF_LOOPING)
FORCE_PED_AI_AND_ANIMATION_UPDATE(mp_Cultist.piPedIdx)
Eps6Wander = WANDER_GOTO
DEBUG_PRINT("Eps 6: Tom idle anim >0.98")
ENDIF
ELSE
IF iWanderStage >= 2
iWanderStage = 0
ELSE
iWanderStage++
ENDIF
TASK_PLAY_ANIM(mp_Cultist.piPedIdx, "rcmepsilonism6", "cultist_upperstatic", DEFAULT, DEFAULT, -1, AF_UPPERBODY|AF_SECONDARY|AF_LOOPING)
Eps6Wander = WANDER_GOTO
DEBUG_PRINT("Eps 6: Tom idle anim not playing")
ENDIF
BREAK
ENDSWITCH
ENDIF
ENDPROC
/// PURPOSE:
/// Update the actions of the Cultist during the intro.
PROC UPDATE_CULTIST()
MANAGE_CULTIST_RAGDOLL()
IF EpsState = EPS_INIT
OR EpsState = EPS_INCAR
IF CULTIST_CHECK_AGGRO()
CULTIST_AGGRO_FAIL()
ENDIF
ELSE
IF CULTIST_CHECK_PLAYER_DAMAGE()
CULTIST_AGGRO_FAIL()
ENDIF
ENDIF
SWITCH EpsState
CASE EPS_INIT
IF EpsMode = STATE_SETUP
IF IS_ENTITY_ALIVE(mp_Cultist.piPedIdx)
EpsMode = STATE_RUN
ENDIF
ELIF EpsMode = STATE_RUN
DO_DETECTOR_WANDER()
SWITCH iCultistRoamStage
CASE 0
IF GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), mp_Cultist.piPedIdx) < 50
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF NOT IS_MESSAGE_BEING_DISPLAYED()
OR GET_PROFILE_SETTING(PROFILE_DISPLAY_SUBTITLES) = 0
iCultistRoamStage++
ENDIF
ENDIF
ENDIF
BREAK
CASE 1
IF CREATE_CONVERSATION(s_conversation_cult, "EPS6AUD", "EPS6_CULT", CONV_PRIORITY_HIGH)
iCultistRoamStage++
iCultistRoamTimer = GET_GAME_TIMER()
ENDIF
BREAK
CASE 2
IF (GET_GAME_TIMER() - iCultistRoamTimer) > 12000
iCultistRoamStage = 0
ENDIF
BREAK
ENDSWITCH
IF IS_ENTITY_ALIVE(PLAYER_PED_ID()) AND IS_VEHICLE_OK(mv_plane.VehIdx)
IF GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), mp_Cultist.piPedIdx) < 10
OR GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), mv_plane.VehIdx) < 10
IF NOT IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<-2915.730469,3195.935791,7.803610>>, <<-2897.806885,3171.756348,12.604198>>, 16.000000)
// This area is the sandy slope to the right of the plane - we want the Cultist to ignore the player if they're in here,
// because this is an awkward area for him to run to and the scene would look crap if he stood around here
IF NOT IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
SWITCH_CULTIST(EPS_FOLLOW)
IntroState = INTRO_SEENMIKE
ELSE
SWITCH_CULTIST(EPS_INCAR)
// if the Cultist goes into this state, he hasn't 'recognised' Michael yet, so don't trigger the rest of the scene
ENDIF
IF NOT IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
SWITCH_CULTIST(EPS_FOLLOW)
IntroState = INTRO_SEENMIKE
ELSE
SWITCH_CULTIST(EPS_INCAR)
// if the Cultist goes into this state, he hasn't 'recognised' Michael yet as he's in his car, so don't trigger the rest of the scene
ENDIF
ENDIF
ENDIF
ENDIF
IF NOT IS_ENTITY_ALIVE(mp_Cultist.piPedIdx)
SWITCH_CULTIST(EPS_DEAD)
ENDIF
ENDIF
BREAK
CASE EPS_INCAR
IF EpsMode = STATE_SETUP
IF IS_PED_UNINJURED(mp_Cultist.piPedIdx)
CLEAR_PED_TASKS(mp_Cultist.piPedIdx)
TASK_TURN_PED_TO_FACE_ENTITY(mp_Cultist.piPedIdx, PLAYER_PED_ID())
IF IS_MESSAGE_BEING_DISPLAYED()
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
KILL_FACE_TO_FACE_CONVERSATION()
ADD_NON_CRITICAL_STANDARD_CONVERSATION_TO_BUFFER(s_conversation_cult, "EPS6AUD", "EPS6_INCAR", CONV_PRIORITY_MEDIUM)
ELSE
CREATE_CONVERSATION(s_conversation_cult, "EPS6AUD", "EPS6_INCAR", CONV_PRIORITY_HIGH, DO_NOT_DISPLAY_SUBTITLES)
ENDIF
ELSE
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
KILL_FACE_TO_FACE_CONVERSATION_DO_NOT_FINISH_LAST_LINE()
ADD_NON_CRITICAL_STANDARD_CONVERSATION_TO_BUFFER(s_conversation_cult, "EPS6AUD", "EPS6_INCAR", CONV_PRIORITY_HIGH)
ELSE
CREATE_CONVERSATION(s_conversation_cult, "EPS6AUD", "EPS6_INCAR", CONV_PRIORITY_HIGH)
ENDIF
ENDIF
EpsMode = STATE_RUN
ENDIF
ELIF EpsMode = STATE_RUN
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
AND IS_VEHICLE_OK(mv_plane.VehIdx)
AND IS_PED_UNINJURED(mp_Cultist.piPedIdx)
IF NOT IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
IF GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), mp_Cultist.piPedIdx) < 15
OR GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), mv_plane.VehIdx) < 10
IF NOT IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<-2915.730469,3195.935791,7.803610>>, <<-2897.806885,3171.756348,12.604198>>, 16.000000)
// This area is the sandy slope to the right of the plane - we want the Cultist to ignore the player if they're in here,
// because this is an awkward area for him to run to and the scene would look crap if he stood around here
SWITCH_CULTIST(EPS_FOLLOW)
IntroState = INTRO_SEENMIKE
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
BREAK
CASE EPS_FOLLOW
IF EpsMode = STATE_SETUP
IF IS_ENTITY_ALIVE(mp_Cultist.piPedIdx)
CLEAR_PED_TASKS(mp_Cultist.piPedIdx)
EpsMove = EPSMOVE_CHANGE
MANAGE_CULTISTS_POSITION()
STOP_SOUND(iDetectorBeepID)
STOP_SOUND(iDetectorHumID)
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
KILL_FACE_TO_FACE_CONVERSATION_DO_NOT_FINISH_LAST_LINE()
ENDIF
// If the player runs up before the God text disappears, we need to do a bunch of weird shit to make the conversation play in a timely manner
// (for LB B*1342750)
// If this happens, we play the first line of EPS6_SPOT only, with no subs, and set bCultistNoSubIntro
// Then in the run loop, if that's happened, we wait for that single line to finish and the God text to go, and then
// play the rest of the conversation starting from the second line, WITH subtitles
// If there's no God text when you run up to the Epsilonist, then we don't bother with any of this and play the conv straight with subs
IF IS_MESSAGE_BEING_DISPLAYED()
PLAY_SINGLE_LINE_FROM_CONVERSATION(s_conversation_cult, "EPS6AUD", "EPS6_SPOT", "EPS6_SPOT_1", CONV_PRIORITY_HIGH, DO_NOT_DISPLAY_SUBTITLES)
iCultistConvDelayTimer = 0
bCultistNoSubIntro = TRUE
DEBUG_PRINT("EPSILONIST: Play single line with subs")
TASK_LOOK_AT_ENTITY(PLAYER_PED_ID(), mp_Cultist.piPedIdx, -1)
TASK_LOOK_AT_ENTITY(mp_Cultist.piPedIdx, PLAYER_PED_ID(), -1)
REPLAY_RECORD_BACK_FOR_TIME(3.0, 10.0, REPLAY_IMPORTANCE_LOW)
EpsMode = STATE_RUN
ELSE
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
// I think this is almost guaranteed to fire as the cultist should be looping "EPS6_CULT"...
KILL_FACE_TO_FACE_CONVERSATION_DO_NOT_FINISH_LAST_LINE()
ADD_NON_CRITICAL_STANDARD_CONVERSATION_TO_BUFFER(s_conversation_cult, "EPS6AUD", "EPS6_SPOT", CONV_PRIORITY_HIGH)
iCultistConvDelayTimer = GET_GAME_TIMER()
DEBUG_PRINT("EPSILONIST: Play full convo as add to buffer")
TASK_LOOK_AT_ENTITY(PLAYER_PED_ID(), mp_Cultist.piPedIdx, -1)
TASK_LOOK_AT_ENTITY(mp_Cultist.piPedIdx, PLAYER_PED_ID(), -1)
REPLAY_RECORD_BACK_FOR_TIME(3.0, 10.0, REPLAY_IMPORTANCE_LOW)
EpsMode = STATE_RUN
ELSE
IF CREATE_CONVERSATION(s_conversation_cult, "EPS6AUD", "EPS6_SPOT", CONV_PRIORITY_HIGH)
iCultistConvDelayTimer = 0
DEBUG_PRINT("EPSILONIST: Play full convo normally")
TASK_LOOK_AT_ENTITY(PLAYER_PED_ID(), mp_Cultist.piPedIdx, -1)
TASK_LOOK_AT_ENTITY(mp_Cultist.piPedIdx, PLAYER_PED_ID(), -1)
REPLAY_RECORD_BACK_FOR_TIME(3.0, 10.0, REPLAY_IMPORTANCE_LOW)
EpsMode = STATE_RUN
ENDIF
ENDIF
ENDIF
ELSE
SWITCH_CULTIST(EPS_DEAD)
ENDIF
ELIF EpsMode = STATE_RUN
IF NOT IS_ENTITY_ALIVE(mp_Cultist.piPedIdx)
SWITCH_CULTIST(EPS_DEAD)
ENDIF
MANAGE_CULTISTS_POSITION()
IF DID_PLAYER_DAMAGE_PLANE()
IF CREATE_CONVERSATION(s_conversation_cult, "EPS6AUD", "EPS6_SHPLNE", CONV_PRIORITY_HIGH)
bCultistAimConv = TRUE // So we don't get the normal "you aimed at me" conv
SWITCH_CULTIST(EPS_HANDSUP)
ENDIF
ENDIF
IF IS_PLAYER_VISIBLY_TARGETTING_PED(mp_Cultist.piPedIdx)
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
KILL_FACE_TO_FACE_CONVERSATION_DO_NOT_FINISH_LAST_LINE()
ENDIF
SWITCH_CULTIST(EPS_HANDSUP)
ENDIF
// See above - handles firing "EPS6_SPOT" again if we played the first line with no subs
IF bCultistNoSubIntro = TRUE
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF NOT bTomSaidPushedOver
IF CREATE_CONVERSATION_FROM_SPECIFIC_LINE(s_conversation_cult, "EPS6AUD", "EPS6_SPOT", "EPS6_SPOT_3", CONV_PRIORITY_HIGH)
bCultistNoSubIntro = FALSE
DEBUG_PRINT("EPSILONIST: Play rest of EPS6_SPOT")
ENDIF
ELSE
bCultistNoSubIntro = FALSE // Just skip this if we've pushed Tom over
ENDIF
ENDIF
ELSE
IF (GET_GAME_TIMER() - iCultistConvDelayTimer) > 1000
OR iCultistConvDelayTimer = 0
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
DEBUG_PRINT("No conversation is ongoing at all...")
ELSE
DEBUG_PRINT("A conversation is playing!")
ENDIF
// Do actions while EPS6_SPOT is playing
IF IS_THIS_CONVERSATION_ROOT_PLAYING("EPS6_SPOT")
DEBUG_PRINT("EPS6_SPOT is playing...")
IF GET_CURRENT_SCRIPTED_CONVERSATION_LINE() >= 5
SAFE_REMOVE_BLIP(mp_Cultist.biPedBlip)
IF NOT DOES_BLIP_EXIST(mv_plane.biBlipIdx)
mv_plane.biBlipIdx = CREATE_VEHICLE_BLIP(mv_plane.VehIdx)
ENDIF
IF bDoneMusic = FALSE
TRIGGER_MUSIC_EVENT("EPS6_START")
bDoneMusic = TRUE
ENDIF
ENDIF
// Only do the "too far" check after the first line to give the Cultist time to get close to Michael
IF GET_CURRENT_SCRIPTED_CONVERSATION_LINE() >= 3
IF GET_DISTANCE_BETWEEN_PEDS(mp_Cultist.piPedIdx, PLAYER_PED_ID()) > 10
KILL_ANY_CONVERSATION() // Interrupt the convo
bPlayerGoneTooFar = TRUE
ENDIF
ENDIF
ELSE
DEBUG_PRINT("EPSILONIST: EPS6_SPOT not playing")
SAFE_REMOVE_BLIP(mp_Cultist.biPedBlip)
IF NOT DOES_BLIP_EXIST(mv_plane.biBlipIdx)
mv_plane.biBlipIdx = CREATE_VEHICLE_BLIP(mv_plane.VehIdx)
ENDIF
SWITCH_CULTIST(EPS_SAFE) // Switch him to 'safe' so he walks away if we've got here (pushed Tom over?)
ENDIF
ELSE
DEBUG_PRINT("EPS6_SPOT delay timer...")
ENDIF
ENDIF
// Player has gone too far from the plane (as above), so progress like this
IF bPlayerGoneTooFar
IF CREATE_CONVERSATION(s_conversation_cult, "EPS6AUD", "EPS6_TOOFAR", CONV_PRIORITY_HIGH)
SWITCH_CULTIST(EPS_WAIT)
ENDIF
ENDIF
// If the player rushes into the plane or pushes the Epsilonist over, stop the ongoing convo, play a single line and progress
IF IS_VEHICLE_OK(mv_plane.VehIdx)
AND IS_ENTITY_ALIVE(mp_Cultist.piPedIdx)
IF IS_PED_IN_VEHICLE(PLAYER_PED_ID(), mv_plane.VehIdx, TRUE)
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
KILL_ANY_CONVERSATION()
DEBUG_PRINT("Kill convo as player getting into plane (1)")
ENDIF
WHILE NOT CREATE_CONVERSATION(s_conversation_cult, "EPS6AUD", "EPS6_LEAVE", CONV_PRIORITY_HIGH)
WAIT(0)
ENDWHILE
SWITCH_CULTIST(EPS_SAFE)
IntroState = INTRO_INPLANE
ENDIF
ENDIF
ENDIF
BREAK
CASE EPS_HANDSUP
IF EpsMode = STATE_SETUP
DEBUG_PRINT("EPSILONIST: In EPS_HANDSUP")
IF bCultistAimConv = FALSE
//IF CREATE_CONVERSATION(s_conversation_cult, "EPS6AUD", "EPS6_AIMING", CONV_PRIORITY_HIGH)
PLAY_PED_AMBIENT_SPEECH_WITH_VOICE(mp_Cultist.piPedIdx, "AIMED_AT_BY_PLAYER", "TOM", SPEECH_PARAMS_FORCE_FRONTEND)
IF NOT IsPedPerformingTask(mp_Cultist.piPedIdx, SCRIPT_TASK_HANDS_UP)
CLEAR_PED_TASKS(mp_Cultist.piPedIdx)
TASK_HANDS_UP(mp_Cultist.piPedIdx, -1, PLAYER_PED_ID(), -1, HANDS_UP_STRAIGHT_TO_LOOP)
ENDIF
iCultistHandsUpTimer = -1
EpsMode = STATE_RUN
//ENDIF
ELSE
IF NOT IsPedPerformingTask(mp_Cultist.piPedIdx, SCRIPT_TASK_HANDS_UP)
CLEAR_PED_TASKS(mp_Cultist.piPedIdx)
TASK_HANDS_UP(mp_Cultist.piPedIdx, -1, PLAYER_PED_ID(), -1, HANDS_UP_STRAIGHT_TO_LOOP)
ENDIF
iCultistHandsUpTimer = -1
EpsMode = STATE_RUN
ENDIF
ELIF EpsMode = STATE_RUN
IF NOT IS_PLAYER_VISIBLY_TARGETTING_PED(mp_Cultist.piPedIdx)
IF iCultistHandsUpTimer = -1
iCultistHandsUpTimer = GET_GAME_TIMER()
ELSE // Makes the cultist keep his hands up for just over a second after the player puts their gun down
IF (GET_GAME_TIMER() - iCultistHandsUpTimer) > 1200
CLEAR_PED_TASKS(mp_Cultist.piPedIdx)
TASK_LOOK_AT_ENTITY(mp_Cultist.piPedIdx, PLAYER_PED_ID(), -1)
TASK_TURN_PED_TO_FACE_ENTITY(mp_Cultist.piPedIdx, PLAYER_PED_ID())
IF bCultistAimConv = FALSE
IF CREATE_CONVERSATION(s_conversation_cult, "EPS6AUD", "EPS6_LEAVE", CONV_PRIORITY_HIGH)
bCultistAimConv = TRUE
SWITCH_CULTIST(EPS_SAFE)
ENDIF
ELSE
SWITCH_CULTIST(EPS_SAFE)
ENDIF
ENDIF
ENDIF
ELSE
iCultistHandsUpTimer = -1
ENDIF
ENDIF
BREAK
CASE EPS_WAIT
IF EpsMode = STATE_SETUP
DEBUG_PRINT("EPSILONIST: In EPS_WAIT")
TASK_TURN_PED_TO_FACE_ENTITY(mp_Cultist.piPedIdx, PLAYER_PED_ID(), -1)
EpsMode = STATE_RUN
ELIF EpsMode = STATE_RUN
IF bShownGetInPlane = FALSE
IF NOT IS_MESSAGE_BEING_DISPLAYED()
AND NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
AND NOT IS_PED_IN_VEHICLE(PLAYER_PED_ID(), mv_plane.VehIdx, TRUE)
REPLAY_RECORD_BACK_FOR_TIME(3.0, 10.0, REPLAY_IMPORTANCE_LOW)
PRINT("EPS6_GETIN", DEFAULT_GOD_TEXT_TIME, 1)
DEBUG_PRINT("Printed EPS6_GETIN from EPS_WAIT")
bShownGetInPlane = TRUE
ENDIF
ENDIF
IF IS_VEHICLE_OK(mv_plane.VehIdx)
AND IS_ENTITY_ALIVE(mp_Cultist.piPedIdx)
IF IS_PED_IN_VEHICLE(PLAYER_PED_ID(), mv_plane.VehIdx, TRUE)
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
KILL_ANY_CONVERSATION()
DEBUG_PRINT("Kill convo as player getting into plane (2)")
ENDIF
IF CREATE_CONVERSATION(s_conversation_cult, "EPS6AUD", "EPS6_LEAVE", CONV_PRIORITY_HIGH)
SWITCH_CULTIST(EPS_SAFE)
IntroState = INTRO_INPLANE
ENDIF
ENDIF
ENDIF
IF DID_PLAYER_DAMAGE_PLANE()
IF CREATE_CONVERSATION(s_conversation_cult, "EPS6AUD", "EPS6_SHPLNE", CONV_PRIORITY_HIGH)
bCultistAimConv = TRUE // No "you aimed at me" conv
SWITCH_CULTIST(EPS_HANDSUP)
ENDIF
ENDIF
IF IS_PLAYER_VISIBLY_TARGETTING_PED(mp_Cultist.piPedIdx)
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
KILL_FACE_TO_FACE_CONVERSATION_DO_NOT_FINISH_LAST_LINE()
ENDIF
SWITCH_CULTIST(EPS_HANDSUP)
ENDIF
IF NOT IS_ENTITY_ALIVE(mp_Cultist.piPedIdx)
SWITCH_CULTIST(EPS_DEAD)
ENDIF
ENDIF
BREAK
CASE EPS_SAFE
IF EpsMode = STATE_SETUP
IF IS_PED_UNINJURED(mp_Cultist.piPedIdx)
IF GET_DISTANCE_BETWEEN_ENTITY_AND_COORD(mp_Cultist.piPedIdx, <<-2884.9338, 3200.1558, 10.7036>>) > 2.0
// Only do this if the Cultist isn't already at the coords (in case we come back here after aiming at him)
CLEAR_PED_TASKS(mp_Cultist.piPedIdx)
TASK_CLEAR_LOOK_AT(mp_Cultist.piPedIdx)
OPEN_SEQUENCE_TASK(seq)
TASK_LOOK_AT_ENTITY(NULL, PLAYER_PED_ID(), -1)
TASK_PLAY_ANIM(NULL, "gestures@m@standing@casual", "gesture_bye_soft")
TASK_FOLLOW_NAV_MESH_TO_COORD(NULL, <<-2884.9338, 3200.1558, 10.7036>>, PEDMOVE_WALK, DEFAULT_TIME_BEFORE_WARP)
TASK_TURN_PED_TO_FACE_ENTITY(NULL, PLAYER_PED_ID(), -1)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(mp_Cultist.piPedIdx, seq)
CLEAR_SEQUENCE_TASK(seq)
ENDIF
EpsMode = STATE_RUN
ENDIF
IF NOT IS_ENTITY_ALIVE(mp_Cultist.piPedIdx)
SWITCH_CULTIST(EPS_DEAD)
ENDIF
ELIF EpsMode = STATE_RUN
// IF missionStage = MS_FLIGHT
// SWITCH_CULTIST(EPS_WAIT)
// ENDIF
IF missionStage = MS_INIT
IF bShownGetInPlane = FALSE
IF NOT IS_THIS_CONVERSATION_ROOT_PLAYING("EPS6_SPOT")
AND NOT IS_PED_IN_VEHICLE(PLAYER_PED_ID(), mv_plane.VehIdx, TRUE)
AND NOT IS_PED_GETTING_INTO_A_VEHICLE(PLAYER_PED_ID())
PRINT("EPS6_GETIN", DEFAULT_GOD_TEXT_TIME, 1)
DEBUG_PRINT("Printed EPS6_GETIN from EPS_SAFE")
bShownGetInPlane = TRUE
ENDIF
ENDIF
ENDIF
IF DID_PLAYER_DAMAGE_PLANE()
IF CREATE_CONVERSATION(s_conversation_cult, "EPS6AUD", "EPS6_SHPLNE", CONV_PRIORITY_HIGH)
bCultistAimConv = TRUE // No "you aimed at me" conv
SWITCH_CULTIST(EPS_HANDSUP)
ENDIF
ENDIF
IF IS_PLAYER_VISIBLY_TARGETTING_PED(mp_Cultist.piPedIdx)
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
KILL_FACE_TO_FACE_CONVERSATION_DO_NOT_FINISH_LAST_LINE()
ENDIF
SWITCH_CULTIST(EPS_HANDSUP)
ENDIF
IF NOT IS_ENTITY_ALIVE(mp_Cultist.piPedIdx)
SWITCH_CULTIST(EPS_DEAD)
ENDIF
ENDIF
BREAK
CASE EPS_FLEEING
IF EpsMode = STATE_SETUP
MAKE_CULTIST_FLEE()
IF NOT DOES_BLIP_EXIST(mv_plane.biBlipIdx)
mv_plane.biBlipIdx = CREATE_VEHICLE_BLIP(mv_plane.VehIdx)
ENDIF
EpsMode = STATE_RUN
ELIF EpsMode = STATE_RUN
IF NOT IS_ENTITY_ALIVE(mp_Cultist.piPedIdx)
SWITCH_CULTIST(EPS_DEAD)
ENDIF
ENDIF
BREAK
CASE EPS_DEAD
IF EpsMode = STATE_SETUP
DEBUG_PRINT("EPSILONIST: Dead!?")
SAFE_REMOVE_BLIP(mp_Cultist.biPedBlip)
EpsMode = STATE_RUN
ELIF EpsMode = STATE_RUN
// Nothing to do!
ENDIF
BREAK
ENDSWITCH
ENDPROC
//PURPOSE: The main process to control what happens around the player near the Army base.
PROC INTRO_SCENE_CONTROLLER()
IF missionStage < MS_LANDING
SWITCH IntroState
CASE INTRO_INIT
UPDATE_CULTIST()
BREAK
CASE INTRO_SEENMIKE
UPDATE_CULTIST()
BREAK
CASE INTRO_INPLANE
UPDATE_CULTIST()
BREAK
CASE INTRO_INTERRUPTED
UPDATE_CULTIST()
BREAK
ENDSWITCH
ENDIF
// Checking a couple of things when we're in the plane
IF missionStage >= MS_FLIGHT
VECTOR vTempCheck = <<-2896.33, 3201.92, 10.01>>
// If we're flying away in the plane, kill the convo between the Epsilonist and Army peds when we get too far away
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF IS_THIS_CONVERSATION_ROOT_PLAYING("EPS6_ARMY")
OR IS_THIS_CONVERSATION_ROOT_PLAYING("EPS6_LEAVE")
OR IS_THIS_CONVERSATION_ROOT_PLAYING("EPS6_SAFE")
OR IS_THIS_CONVERSATION_ROOT_PLAYING("EPS6_PUSHED")
IF GET_DISTANCE_BETWEEN_ENTITY_AND_COORD(PLAYER_PED_ID(), vTempCheck) > 35
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
DEBUG_PRINT("*** Killing an intro conversation because player is too far away")
KILL_ANY_CONVERSATION()
ENDIF
ENDIF
ENDIF
ENDIF
IF GET_DISTANCE_BETWEEN_ENTITY_AND_COORD(PLAYER_PED_ID(), vTempCheck) > 450
SAFE_RELEASE_PED(mp_Cultist.piPedIdx)
ENDIF
ENDIF
ENDPROC
//PURPOSE: Handles the initial phone call from Jimmy after you have just stolen back the plane to trigger at the appropriate moment.
PROC HANDLE_JIMMY_PHONECALL()
VECTOR vPlanePos
SWITCH CallState
CASE CALL_WAITING
IF GET_PLAYER_WANTED_LEVEL(PLAYER_ID()) = 0
IF IsPlaneOK()
vPlanePos = GET_ENTITY_COORDS(mv_plane.VehIdx)
if vPlanePos.z > 15.0
DEBUG_PRINT("vPlanePos.z is > 15.0")
iJimmyCallTimer = GET_GAME_TIMER()
SAFE_RELEASE_PED(mp_Cultist.piPedIdx, TRUE)
DEBUG_PRINT("RELEASING CULTIST PED VIA JIMMY PHONECALL")
//CREATE_ARMY_CONVOY()
CallState = CALL_BUFFERING
ENDIF
ENDIF
ENDIF
BREAK
CASE CALL_BUFFERING
IF (GET_GAME_TIMER() - iJimmyCallTimer) > 12000
CallState = CALL_PLAYING
ENDIF
BREAK
CASE CALL_PLAYING
IF GET_PLAYER_WANTED_LEVEL(PLAYER_ID()) = 0
IF PLAYER_CALL_CHAR_CELLPHONE(s_conversation_flight, CHAR_JIMMY_BOSTON, "EPS6AUD", "EPS6_FLIGHT", CONV_PRIORITY_CELLPHONE)
SET_MAX_WANTED_LEVEL(5) // It's safe to change the wanted level to normal now
REPLAY_RECORD_BACK_FOR_TIME(3.0, 10.0, REPLAY_IMPORTANCE_LOW)
CallState = CALL_DONE
ENDIF
ENDIF
BREAK
CASE CALL_DONE
// Played the call, do nothing
BREAK
ENDSWITCH
ENDPROC
//PURPOSE: Handle Jimmy's beckon lines when the player has handled at the air field.
PROC HANDLE_JIMMY_BECKON_LINES()
IF IS_ENTITY_ALIVE(mp_Jimmy.piPedIdx)
IF GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), mp_Jimmy.piPedIdx) <= 15
IF NOT IS_PED_HEADTRACKING_PED(mp_Jimmy.piPedIdx, PLAYER_PED_ID())
DEBUG_PRINT("Jimmy headlooking")
TASK_LOOK_AT_ENTITY(mp_Jimmy.piPedIdx, PLAYER_PED_ID(), -1, SLF_WHILE_NOT_IN_FOV|SLF_WIDEST_PITCH_LIMIT|SLF_WIDEST_YAW_LIMIT)
ENDIF
ELIF GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), mp_Jimmy.piPedIdx) <= 25
AND IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF NOT IS_PED_HEADTRACKING_PED(mp_Jimmy.piPedIdx, PLAYER_PED_ID())
DEBUG_PRINT("Jimmy headlooking (during conv)")
TASK_LOOK_AT_ENTITY(mp_Jimmy.piPedIdx, PLAYER_PED_ID(), -1, SLF_WHILE_NOT_IN_FOV|SLF_WIDEST_PITCH_LIMIT|SLF_WIDEST_YAW_LIMIT)
ENDIF
ELSE
IF IS_PED_HEADTRACKING_PED(mp_Jimmy.piPedIdx, PLAYER_PED_ID())
AND NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
DEBUG_PRINT("Clear Jimmy headlook")
TASK_CLEAR_LOOK_AT(mp_Jimmy.piPedIdx)
ENDIF
ENDIF
ENDIF
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
AND NOT IS_MESSAGE_BEING_DISPLAYED()
IF IS_ENTITY_ALIVE(mp_Jimmy.piPedIdx)
AND IS_ENTITY_ALIVE(PLAYER_PED_ID())
IF IS_ENTITY_IN_RANGE_ENTITY(PLAYER_PED_ID(), mp_Jimmy.piPedIdx, 25.0)
IF (GET_GAME_TIMER() - iJimmyBeckonTimer) > 15000
IF CREATE_CONVERSATION(s_conversation_outro, "EPS6AUD", "EPS6_BECKON", CONV_PRIORITY_HIGH)
iJimmyBeckonTimer = GET_GAME_TIMER()
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Check for the player flying under one of the Raton Canyon River bridges for the stat
PROC TRACK_UNDER_BRIDGE_STAT()
IF IsPlaneOK()
IF IS_PED_IN_VEHICLE(PLAYER_PED_ID(), mv_plane.VehIdx)
if IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<-2611.599121,2953.921875,10.794971>>, <<-2698.713135,2367.250000,-0.336048>>, 3.000000) // Long highway bridge by airbase
OR IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<-1506.538086,2717.231201,15.289821>>, <<-1377.952515,2609.015137,0.028772>>, 3.000000) // Bridge to airbase entrance
OR IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<-395.950104,2960.713867,23.473852>>, <<-426.353912,2966.561035,14.004027>>, 3.000000) // Small covered road bridge
IF NOT bReplayTrackOn
bReplayTrackOn = TRUE
ENDIF
INFORM_STAT_SYSTEM_OF_BOOL_STAT_HAPPENED(EP6_UNDER_BRIDGE)
ELSE
// Once the player has hit one of the under-bridge areas, we track the previous 3 seconds once they've exited out of it
IF bReplayTrackOn = TRUE
REPLAY_RECORD_BACK_FOR_TIME(3.0)
bReplayTrackOn = FALSE
ENDIF
ENDIF
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Check whether the player is 'in the air' by seeing if they're more than 5m above the ground Z of their current coord
/// RETURNS:
/// TRUE if they're in the air, FALSE otherwise
FUNC BOOL IS_PLAYER_IN_AIR()
VECTOR vPlayerPos
FLOAT fReturnZ
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
vPlayerPos = GET_ENTITY_COORDS(PLAYER_PED_ID())
GET_GROUND_Z_FOR_3D_COORD(vPlayerPos, fReturnZ)
IF vPlayerPos.Z > fReturnZ + 5.0 // if the player's Z coord is more than 5m above the ground Z of their coord, we consider them 'in the air'
RETURN TRUE
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
//PURPOSE: Checks the player's current wanted level - if 0, make sure the flight can process. If >0, make the player lose the cops before trying to land.
PROC CHECK_FOR_WANTED_LEVEL()
// If player has a wanted level, tell them to lose the cops before giving them the next objective
IF GET_PLAYER_WANTED_LEVEL(PLAYER_ID()) > 0
if not bShownLoseCops
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
PRINT_NOW("EPS6_COPS", DEFAULT_GOD_TEXT_TIME, 1) //Lose the cops.
bShownLoseCops = TRUE
ENDIF
ENDIF
SAFE_REMOVE_BLIP(pcp_LandingGoal.biBlipIdx)
ELSE // *** Reset check - clear prints, recreate checkpoints and blips
IF bShownLoseCops
CLEAR_PRINTS()
bShownLoseCops = FALSE
ENDIF
IF NOT DOES_BLIP_EXIST(pcp_LandingGoal.biBlipIdx)
pcp_LandingGoal.biBlipIdx = CREATE_COORD_BLIP(pcp_LandingGoal.vPointPos)
ENDIF
ENDIF
ENDPROC
//PURPOSE: Handle and gradually shrink the mission abandonment range when the player is close to Jimmy
PROC HANDLE_JIMMY_ABANDONMENT()
FLOAT fCurrentDistance
// Every frame, grab the distance between the player and Jimmy
IF IS_ENTITY_ALIVE(mp_Jimmy.piPedIdx)
AND IS_ENTITY_ALIVE(PLAYER_PED_ID())
fCurrentDistance = GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), GET_ENTITY_COORDS(mp_Jimmy.piPedIdx))
ENDIF
// Then incrementally check each distance - the closer we get, the smaller the warning and fail ranges become
// The AbandonCap incrementally decreases, and prevents larger distances from resetting the warning/fail ranges if we've moved closer to Jimmy
IF fCurrentDistance < 50
g_fJimmyWarningRange = 100
g_fJimmyFailRange = 150
g_iAbandonCap = 1
//DEBUG_PRINT("Setting g_iAbandonCap = 1")
ELIF fCurrentDistance < 100
IF g_iAbandonCap > 1
g_fJimmyWarningRange = 150
g_fJimmyFailRange = 200
g_iAbandonCap = 2
//DEBUG_PRINT("Setting g_iAbandonCap = 2")
ENDIF
ELIF fCurrentDistance < 150
IF g_iAbandonCap > 2
g_fJimmyWarningRange = 200
g_fJimmyFailRange = 250
g_iAbandonCap = 3
//DEBUG_PRINT("Setting g_iAbandonCap = 3")
ENDIF
ELIF fCurrentDistance < 200
IF g_iAbandonCap > 3
g_fJimmyWarningRange = 250
g_fJimmyFailRange = 300
g_iAbandonCap = 4
//DEBUG_PRINT("Setting g_iAbandonCap = 4")
ENDIF
ENDIF
IF (GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), GET_ENTITY_COORDS(mp_Jimmy.piPedIdx)) > g_fJimmyWarningRange)
// Check to make sure the player hasn't run too far away from Jimmy
IF NOT bAbandonment
PRINT_NOW("EPS6_GOBACK", DEFAULT_GOD_TEXT_TIME, 1) // Return to ~b~Jimmy Boston.
bAbandonment = TRUE // Uh oh, player is >warning range away from Jimmy, are they abandoning the mission?
ELIF (GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), GET_ENTITY_COORDS(mp_Jimmy.piPedIdx)) > g_fJimmyFailRange)
FailedReason = FAILED_LEFT_DROPOFF
subState = SS_INIT
missionStage = MS_FAILED
TRIGGER_MUSIC_EVENT("EPS_FAIL")
ENDIF
ELSE
IF bAbandonment
bAbandonment = false //Less than warning range away from Jimmy, player isn't abandoning the mission
ENDIF
ENDIF
ENDPROC
FUNC BOOL DO_MICHAEL_EXIT()
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
IF CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY("Michael")
FORCE_PED_MOTION_STATE(PLAYER_PED_ID(), MS_ON_FOOT_IDLE, FALSE, FAUS_CUTSCENE_EXIT)
SET_GAMEPLAY_CAM_RELATIVE_HEADING()
SET_GAMEPLAY_CAM_RELATIVE_PITCH()
TASK_LOOK_AT_ENTITY(PLAYER_PED_ID(), mp_Jimmy.piPedIdx, -1)
DEBUG_PRINT("Do Michael exit")
SAFE_TELEPORT_ENTITY(mv_RewardCar.VehIdx, mv_RewardCar.VehPos, mv_RewardCar.Heading, TRUE) // Move the reward car back to the player
IF IS_VEHICLE_OK(mv_RewardCar.VehIdx)
SET_VEHICLE_DOORS_LOCKED(mv_RewardCar.VehIdx, VEHICLELOCK_UNLOCKED)
ENDIF
RETURN TRUE
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
PROC DO_JIMMY_EXIT()
IF IS_ENTITY_ALIVE(mp_Jimmy.piPedIdx)
IF CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY("Jimmy_Boston")
DEBUG_PRINT("Doing Jimmy exit state")
IF IS_ENTITY_ALIVE(mp_Jimmy.piPedIdx)
AND IsPlaneOK()
SAFE_TELEPORT_ENTITY(mp_Jimmy.piPedIdx, <<1682.13, 3268.65, 39.75>>, 183.3768)
OPEN_SEQUENCE_TASK(seq)
TASK_FOLLOW_NAV_MESH_TO_COORD(NULL, <<1682.44, 3258.81, 39.81>>, PEDMOVEBLENDRATIO_RUN, DEFAULT_TIME_BEFORE_WARP, 7.5, ENAV_NO_STOPPING)
TASK_ENTER_VEHICLE(NULL, mv_plane.VehIdx, DEFAULT_TIME_BEFORE_WARP, VS_DRIVER)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(mp_Jimmy.piPedIdx, seq)
CLEAR_SEQUENCE_TASK(seq)
ENDIF
FORCE_PED_MOTION_STATE(mp_Jimmy.piPedIdx, MS_ON_FOOT_RUN, FALSE, FAUS_CUTSCENE_EXIT)
ENDIF
ENDIF
ENDPROC
PROC DO_PLANE_EXIT()
IF CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY("ep_plane")
DEBUG_PRINT("Doing plane exit state")
If IsPlaneOK()
SET_ENTITY_COORDS (mv_plane.VehIdx, <<1684.78, 3255.58, 41.78>>)
SET_ENTITY_HEADING (mv_plane.VehIdx, 284.26)
SET_VEHICLE_ON_GROUND_PROPERLY(mv_plane.VehIdx)
ELSE
SAFE_DELETE_VEHICLE(mv_plane.VehIdx)
mv_plane.VehIdx = CREATE_VEHICLE(mv_plane.VehName, <<1684.78, 3255.58, 41.78>>, 284.26)
SET_VEHICLE_AS_RESTRICTED(mv_plane.VehIdx, 0)
SET_VEHICLE_ON_GROUND_PROPERLY(mv_plane.VehIdx)
ENDIF
IF NOT IS_PLAYBACK_GOING_ON_FOR_VEHICLE(mv_plane.VehIdx)
IF HAS_VEHICLE_RECORDING_BEEN_LOADED(501, "Eps6_Takeoff")
START_PLAYBACK_RECORDED_VEHICLE(mv_plane.VehIdx, 501, "Eps6_Takeoff")
FORCE_PLAYBACK_RECORDED_VEHICLE_UPDATE(mv_plane.VehIdx)
PAUSE_PLAYBACK_RECORDED_VEHICLE(mv_plane.VehIdx)
DEBUG_PRINT("Started/paused vehicle recording on plane")
ENDIF
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Handles creating or removing the streamvol depending on distance from the player to Jimmy
PROC HANDLE_STREAMVOL_SETUP()
IF GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), mp_Jimmy.piPedIdx) <= 15
IF NOT IS_STREAMVOL_ACTIVE()
IF NOT STREAMVOL_HAS_LOADED(cutsceneStreamvol)
DEBUG_PRINT("Loading streamvol")
cutsceneStreamvol = STREAMVOL_CREATE_FRUSTUM(<<1684.85, 3276.16, 39.93>>, CONVERT_ROTATION_TO_DIRECTION_VECTOR(<<-2.1719, 0.0000, -78.5672>>), 50, FLAG_MAPDATA)
ENDIF
ENDIF
ELSE
IF IS_STREAMVOL_ACTIVE()
DEBUG_PRINT("Removing streamvol")
STREAMVOL_DELETE(cutsceneStreamvol)
ENDIF
ENDIF
ENDPROC
//PURPOSE: Main mission state process forthe start of the mission.
PROC m_pInit()
SWITCH subState
CASE SS_INIT
DEBUG_PRINT("*** Doing Init initialisation")
IF bHasSkipped = TRUE
LoadSkip()
IF NOT IS_REPLAY_BEING_SET_UP()
RC_END_Z_SKIP()
ENDIF
bHasSkipped = FALSE
ENDIF
REQUEST_ANIM_DICT("rcmepsilonism6")
REQUEST_ANIM_DICT("gestures@m@standing@casual")
WHILE NOT HAS_ANIM_DICT_LOADED("rcmepsilonism6")
OR NOT HAS_ANIM_DICT_LOADED("gestures@m@standing@casual")
WAIT(0)
ENDWHILE
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
ADD_PED_FOR_DIALOGUE(s_conversation_cult, ENUM_TO_INT(CHAR_MICHAEL), PLAYER_PED_ID(), "MICHAEL")
ENDIF
IF IS_ENTITY_ALIVE(mp_Cultist.piPedIdx)
ADD_PED_FOR_DIALOGUE(s_conversation_cult, 4, mp_Cultist.piPedIdx, "TOM", TRUE)
STOP_PED_SPEAKING(mp_Cultist.piPedIdx, TRUE)
// SET_PED_LEG_IK_MODE(mp_Cultist.piPedIdx, LEG_IK_PARTIAL)
SET_PED_DIES_WHEN_INJURED(mp_Cultist.piPedIdx, TRUE)
SET_PED_CAN_BE_TARGETTED(mp_Cultist.piPedIdx, FALSE)
SET_PED_CONFIG_FLAG(mp_Cultist.piPedIdx,PCF_DontEnterVehiclesInPlayersGroup, TRUE)
SET_PED_CONFIG_FLAG(mp_Cultist.piPedIdx, PCF_UseKinematicModeWhenStationary, TRUE)
// SET_PED_CAN_RAGDOLL(mp_Cultist.piPedIdx, FALSE)
SET_PED_CAN_SWITCH_WEAPON(mp_Cultist.piPedIdx, FALSE)
// Play hum sound
iDetectorHumID = GET_SOUND_ID()
iDetectorBeepID = GET_SOUND_ID()
PLAY_SOUND_FROM_ENTITY(iDetectorHumID, "DEVICE", GET_CURRENT_PED_WEAPON_ENTITY_INDEX(mp_Cultist.piPedIdx), "EPSILONISM_04_SOUNDSET")
PLAY_SOUND_FROM_ENTITY(iDetectorBeepID, "IDLE_BEEP_NPC", GET_CURRENT_PED_WEAPON_ENTITY_INDEX(mp_Cultist.piPedIdx), "EPSILONISM_04_SOUNDSET")
ENDIF
IF NOT DOES_BLIP_EXIST(mp_Cultist.biPedBlip)
mp_Cultist.biPedBlip = CREATE_PED_BLIP(mp_Cultist.piPedIdx, TRUE, TRUE)
ENDIF
//CREATE_BOAT()
IF IsPlaneOK()
DEBUG_PRINTINT("*** Plane 'entity' health: ", GET_ENTITY_HEALTH(mv_plane.VehIdx))
DEBUG_PRINTFLOAT("*** Plane engine health: ", GET_VEHICLE_ENGINE_HEALTH(mv_plane.VehIdx))
DEBUG_PRINTFLOAT("*** Plane petrol tank health: ", GET_VEHICLE_PETROL_TANK_HEALTH(mv_plane.VehIdx))
ENDIF
IF Is_Replay_In_Progress()
IF IS_REPLAY_BEING_SET_UP()
END_REPLAY_SETUP()
ENDIF
RC_END_Z_SKIP()
ENDIF
REPLAY_RECORD_BACK_FOR_TIME(0.0, 15.0, REPLAY_IMPORTANCE_LOW)
DEBUG_PRINT("*** Epsilon 6 initialised, now running")
bTomSaidPushedOver = FALSE
bPlayerGoneTooFar = FALSE
bAbandonment = FALSE // Reset abandonment check
iCultistRoamStage = 0
PRINT_NOW("EPS6_01", DEFAULT_GOD_TEXT_TIME, 1) //Meet the ~b~Epsilonist.
iCultistRoamTimer = GET_GAME_TIMER()
DEBUG_PRINT("*** Going into Init running state")
subState = SS_RUNNING
BREAK
CASE SS_RUNNING
IF DID_PLAYER_PLACE_STICKY_BOMB_ON_PLANE()
STICKY_BOMB_FAIL()
ENDIF
INTRO_SCENE_CONTROLLER()
IF NOT IS_VEHICLE_OK(mv_plane.VehIdx)
// Plane has been destroyed somehow, fail the mission
DEBUG_PRINT("*** FAILED: Plane destroyed")
FailedReason = FAILED_DESTROYED
subState = SS_INIT
missionStage = MS_FAILED
TRIGGER_MUSIC_EVENT("EPS_FAIL")
ELSE // Do abandonment checks
IF (GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), GET_ENTITY_COORDS(mv_plane.VehIdx)) > 50)
// Check to make sure the player hasn't run too far away from the plane
IF NOT bAbandonment
IF IS_SCRIPTED_CONVERSATION_ONGOING()
iPausedConvLn = GET_CURRENT_SCRIPTED_CONVERSATION_LINE()
tlPausedConvRoot = GET_CURRENTLY_PLAYING_STANDARD_CONVERSATION_ROOT()
KILL_ANY_CONVERSATION()
bPausedConv = TRUE
iPausedConvTimer = GET_GAME_TIMER() - DEFAULT_GOD_TEXT_TIME
ENDIF
PRINT_NOW("EPS6_BACKPL", DEFAULT_GOD_TEXT_TIME, 1) //Return to the ~b~plane.
bAbandonment = TRUE // Uh oh, player is >100m away from the plane, are they abandoning the mission?
ELSE
IF (GET_GAME_TIMER() - iPausedConvTimer) > DEFAULT_GOD_TEXT_TIME
AND NOT IS_MESSAGE_BEING_DISPLAYED()
IF CREATE_CONVERSATION(s_conversation_cult, "EPS6AUD", "EPS6_RUNAWAY", CONV_PRIORITY_HIGH)
iPausedConvTimer = GET_GAME_TIMER()
ENDIF
ENDIF
IF (GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), GET_ENTITY_COORDS(mv_plane.VehIdx)) > 100)
FailedReason = FAILED_LEFT_PLANE
subState = SS_INIT
missionStage = MS_FAILED
TRIGGER_MUSIC_EVENT("EPS_FAIL")
ENDIF
ENDIF
ELSE
IF bAbandonment
IF bPausedConv
TEXT_LABEL_23 tlNew
tlNew += tlPausedConvRoot
tlNew += "_"
tlNew += iPausedConvLn
IF CREATE_CONVERSATION_FROM_SPECIFIC_LINE(s_conversation_cult, "EPS6AUD", tlPausedConvRoot, tlNew, CONV_PRIORITY_HIGH)
bPausedConv = FALSE
bAbandonment = false //Less than 100m away from the plane, player isn't abandoning the mission
ENDIF
ELSE
bAbandonment = false //Less than 100m away from the plane, player isn't abandoning the mission
ENDIF
ENDIF
ENDIF
ENDIF
IF IS_ENTITY_ALIVE(PLAYER_PED_ID()) AND IS_VEHICLE_OK(mv_plane.VehIdx)
IF IS_PED_IN_VEHICLE(PLAYER_PED_ID(), mv_plane.VehIdx)
subState = SS_SHUTDOWN
ENDIF
ENDIF
BREAK
CASE SS_SHUTDOWN
DEBUG_PRINT("*** Doing Init cleanup")
SAFE_REMOVE_BLIP(mp_Cultist.biPedBlip)
SAFE_REMOVE_BLIP(mv_plane.biBlipIdx)
missionStage = MS_FLIGHT
subState = SS_INIT
BREAK
ENDSWITCH
ENDPROC
//PURPOSE: Main mission state process for when the player has entered and is flying the plane.
PROC m_pFlight()
SWITCH subState
CASE SS_INIT
DEBUG_PRINT("*** Doing Flight init")
IF bHasSkipped = TRUE
LoadSkip()
RC_END_Z_SKIP()
bHasSkipped = FALSE
ENDIF
SET_ROADS_IN_ANGLED_AREA(<<-36.251339,-465.831512,39.122559>>, <<25.801004,-287.171631,47.758629>>, 59.500000, false, false)
ADD_PED_FOR_DIALOGUE(s_conversation_flight, 3, NULL, "JIMMYBOSTON")
ADD_PED_FOR_DIALOGUE(s_conversation_flight, ENUM_TO_INT(CHAR_MICHAEL), PLAYER_PED_ID(), "MICHAEL")
ADD_PED_FOR_DIALOGUE(s_conversation_cult, ENUM_TO_INT(CHAR_MICHAEL), PLAYER_PED_ID(), "MICHAEL")
// IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
// KILL_ANY_CONVERSATION()
// ENDIF
TASK_CLEAR_LOOK_AT(PLAYER_PED_ID())
IF IntroState <= INTRO_INIT
CREATE_CONVERSATION(s_conversation_cult, "EPS6AUD", "EPS6_LEAVE", CONV_PRIORITY_HIGH)
ENDIF
IF IsPlaneOK()
DEBUG_PRINTINT("*** Plane 'entity' health: ", GET_ENTITY_HEALTH(mv_plane.VehIdx))
DEBUG_PRINTFLOAT("*** Plane engine health: ", GET_VEHICLE_ENGINE_HEALTH(mv_plane.VehIdx))
DEBUG_PRINTFLOAT("*** Plane petrol tank health: ", GET_VEHICLE_PETROL_TANK_HEALTH(mv_plane.VehIdx))
ENDIF
IF bDoneMusic = FALSE
TRIGGER_MUSIC_EVENT("EPS6_START")
bDoneMusic = TRUE
ENDIF
bAbandonment = FALSE
CallState = CALL_WAITING
DEBUG_PRINT("*** Going into Flight running state")
subState = SS_RUNNING
BREAK
CASE SS_RUNNING
INTRO_SCENE_CONTROLLER()
//HANDLE_ARMY_CONVOY() // These aren't created immediately - only when the phonecall is given
//HANDLE_DUMPING_SCENE() // same as above
//HANDLE_BOAT()
TRACK_UNDER_BRIDGE_STAT()
HANDLE_JIMMY_PHONECALL()
IF DID_PLAYER_PLACE_STICKY_BOMB_ON_PLANE()
STICKY_BOMB_FAIL()
ENDIF
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF bShownGoToAirfield = FALSE
PRINT_NOW("EPS6_02", DEFAULT_GOD_TEXT_TIME, 1) //Deliver the plane to the ~y~airfield.
bShownGoToAirfield = TRUE
ENDIF
ENDIF
IF IsPlaneOK()
if IS_PED_IN_VEHICLE(PLAYER_PED_ID(), mv_plane.VehIdx)
CHECK_FOR_WANTED_LEVEL()
SAFE_REMOVE_BLIP(mv_plane.biBlipIdx)
// Keep the military base runway strobe component turned off
SET_MINIMAP_COMPONENT(MINIMAP_COMPONENT_RUNWAY_4, FALSE)
IF GET_PLAYER_WANTED_LEVEL(PLAYER_ID()) = 0
IF GET_DISTANCE_BETWEEN_ENTITY_AND_COORD(PLAYER_PED_ID(), pcp_LandingGoal.vPointPos, FALSE) < 2300
subState = SS_SHUTDOWN
ENDIF
ENDIF
ELSE
IF NOT DOES_BLIP_EXIST(mv_plane.biBlipIdx)
mv_plane.biBlipIdx = CREATE_VEHICLE_BLIP(mv_plane.VehIdx)
DEBUG_PRINT("***** GET BACK IN PLANE")
if not bShownExitVehicle
PRINT_NOW("EPS6_03", DEFAULT_GOD_TEXT_TIME, 1) //Get back in the ~b~plane.
bShownExitVehicle = TRUE
ENDIF
ENDIF
IF bShownLoseCops
bShownLoseCops = FALSE
ENDIF
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF IS_THIS_CONVERSATION_ROOT_PLAYING("EPS6_ARMY")
OR IS_THIS_CONVERSATION_ROOT_PLAYING("EPS6_LEAVE")
OR IS_THIS_CONVERSATION_ROOT_PLAYING("EPS6_SAFE")
OR IS_THIS_CONVERSATION_ROOT_PLAYING("EPS6_PUSHED")
OR IS_THIS_CONVERSATION_ROOT_PLAYING("EPS6_FLIGHT")
KILL_ANY_CONVERSATION()
ENDIF
ENDIF
SAFE_REMOVE_BLIP(pcp_LandingGoal.biBlipIdx)
IF (GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), GET_ENTITY_COORDS(mv_plane.VehIdx)) > 80)
// Check to make sure the player hasn't run too far away from the plane
IF NOT bAbandonment
PRINT_NOW("EPS6_BACKPL", DEFAULT_GOD_TEXT_TIME, 1) //Return to the ~b~plane.
bAbandonment = TRUE // Uh oh, player is >80m away from the plane, are they abandoning the mission?
ELIF (GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), GET_ENTITY_COORDS(mv_plane.VehIdx)) > 120)
if IS_PLAYER_IN_AIR()
bTeleOnFail = TRUE
ENDIF
FailedReason = FAILED_LEFT_PLANE
subState = SS_INIT
missionStage = MS_FAILED
TRIGGER_MUSIC_EVENT("EPS_FAIL")
ENDIF
ELSE
IF bAbandonment
bAbandonment = false //Less than 80m away from the plane, player isn't abandoning the mission
ENDIF
ENDIF
ENDIF
ELSE
// Something's gone wrong with the plane here, so fail the mission
FailedReason = FAILED_DESTROYED
subState = SS_INIT
missionStage = MS_FAILED
bTeleOnFail = TRUE
TRIGGER_MUSIC_EVENT("EPS_FAIL")
ENDIF
BREAK
CASE SS_SHUTDOWN
DEBUG_PRINT("*** Doing Flight cleanup")
missionStage = MS_LANDING
subState = SS_INIT
BREAK
ENDSWITCH
ENDPROC
//PURPOSE: main mission state process for when the player is coming in to land at the air field.
PROC m_pLanding()
SWITCH subState
CASE SS_INIT
DEBUG_PRINT("*** Doing Landing init")
REMOVE_ANIM_DICT("gestures@m@standing@casual")
// If we've used a skip, we need this vehicle recording to keep the plane in the air while the fade-in occurs and everything is loading
if bHasSkipped
REQUEST_VEHICLE_RECORDING(500, "Eps6_LandingSkip")
ENDIF
DEBUG_PRINT("Landing resources loaded!")
// As above - but we can't IF check a bool in the middle of a WHILE, so we have to do it separately here
if bHasSkipped
WHILE NOT HAS_VEHICLE_RECORDING_BEEN_LOADED(500, "Eps6_LandingSkip")
DEBUG_PRINT("WAITING FOR LANDING SKIP RECORDING")
WAIT(0)
ENDWHILE
DEBUG_PRINT("Landing skip loaded!")
ENDIF
g_iAbandonCap = 5
SAFE_RELEASE_PED(mp_Cultist.piPedIdx)
bAbandonment = FALSE
bSetCP = FALSE
IF bHasSkipped = TRUE
LoadSkip()
IF NOT IS_REPLAY_BEING_SET_UP()
RC_END_Z_SKIP()
ENDIF
bHasSkipped = FALSE
ENDIF
// Check around the wrecked bus on the airfield for any ambient vehicles stuck inside and clear them (#709593)
CLEAR_ANGLED_AREA_OF_VEHICLES(<<1727.441895,3288.314697,39.406002>>, <<1706.909058,3280.668945,45.132561>>, 14.250000)
IF Is_Replay_In_Progress()
IF IS_REPLAY_BEING_SET_UP()
END_REPLAY_SETUP(mv_plane.VehIdx)
IF IS_VEHICLE_OK(mv_plane.VehIdx)
START_PLAYBACK_RECORDED_VEHICLE(mv_plane.VehIdx, 500, "Eps6_LandingSkip")
ENDIF
WAIT(750)
ENDIF
RC_END_Z_SKIP()
ENDIF
// Double check for the skip handling - just in case we're hanging out in the init here for whatever reason
HANDLE_SKIP_FLYING_CONTROLS()
DEBUG_PRINT("*** Going into Landing running state")
subState = SS_RUNNING
BREAK
CASE SS_RUNNING
INTRO_SCENE_CONTROLLER()
TRACK_UNDER_BRIDGE_STAT()
//HANDLE_ARMY_CONVOY() // Will release the convoy vehicles when it hits this point
//HANDLE_DUMPING_SCENE()
//HANDLE_BOAT()
// IF NOT bShownLandAtAirfield
// CLEAR_PRINTS()
// PRINT("EPS6_02", DEFAULT_GOD_TEXT_TIME, 1) //Deliver the plane to the ~y~airfield.
// bShownLandAtAirfield = TRUE
// ENDIF
CHECK_JIMMY_AGGRO()
IF DID_PLAYER_PLACE_STICKY_BOMB_ON_PLANE()
STICKY_BOMB_FAIL()
ENDIF
IF IsPlaneOK()
IF bSetCP = FALSE
IF GET_DISTANCE_BETWEEN_ENTITY_AND_COORD(mv_plane.VehIdx, pcp_LandingGoal.vPointPos) < 1100
SET_REPLAY_MID_MISSION_STAGE_WITH_NAME(CP_LANDING, "Landing stage")
bSetCP = TRUE
DEBUG_PRINT("Landing checkpoint set")
ENDIF
ENDIF
IF bSpawnJimmy = FALSE
IF GET_DISTANCE_BETWEEN_ENTITY_AND_COORD(mv_plane.VehIdx, pcp_LandingGoal.vPointPos) < 350
REQUEST_MODEL(mv_RewardCar.VehName)
REQUEST_NPC_PED_MODEL(CHAR_JIMMY_BOSTON)
REQUEST_ANIM_DICT(mp_Jimmy.AnimDict)
REQUEST_MODEL(p_amb_phone_01)
DEBUG_PRINT("Requesting Jimmy resources...")
IF HAS_MODEL_LOADED(mv_RewardCar.VehName)
AND HAS_NPC_PED_MODEL_LOADED(CHAR_JIMMY_BOSTON)
AND HAS_ANIM_DICT_LOADED(mp_Jimmy.AnimDict)
AND HAS_MODEL_LOADED(p_amb_phone_01)
SETUP_JIMMY()
SETUP_CAR()
ADD_PED_FOR_DIALOGUE(s_conversation_outro, 3, mp_Jimmy.piPedIdx, "JIMMYBOSTON")
ADD_PED_FOR_DIALOGUE(s_conversation_outro, ENUM_TO_INT(CHAR_MICHAEL), PLAYER_PED_ID(), "MICHAEL")
bSpawnJimmy = TRUE
DEBUG_PRINT("Jimmy created")
ENDIF
ENDIF
ENDIF
if IS_PED_IN_VEHICLE(PLAYER_PED_ID(), mv_plane.VehIdx)
// Skip handling
HANDLE_SKIP_FLYING_CONTROLS()
CHECK_FOR_WANTED_LEVEL()
CHECK_JIMMY_PLANE_FEAR()
// Keep the military base runway strobe component turned off - must be called every frame
SET_MINIMAP_COMPONENT(MINIMAP_COMPONENT_RUNWAY_4, FALSE)
// *** Never show the plane blip when we're inside it
SAFE_REMOVE_BLIP(mv_plane.biBlipIdx)
SAFE_REMOVE_BLIP(mp_Jimmy.biPedBlip)
// ***********
// PLANE IN LANDING AREA CHECK
// ***********
IF GET_PLAYER_WANTED_LEVEL(PLAYER_ID()) = 0 // Only progress if the player does not have a wanted level
IF IS_ENTITY_IN_ANGLED_AREA(mv_plane.VehIdx, vPlaneDetect1, vPlaneDetect2,
33.250000, FALSE, TRUE, TM_IN_VEHICLE)
DEBUG_PRINT("Plane detected")
DEBUG_PRINT("*** Entering Landing cleanup")
subState = SS_SHUTDOWN
ENDIF
ENDIF
ELSE // *** The player is NOT in the plane and they need to get back in
// *** Reblip the plane and keep it blipped
IF NOT DOES_BLIP_EXIST(mv_plane.biBlipIdx)
mv_plane.biBlipIdx = CREATE_VEHICLE_BLIP(mv_plane.VehIdx)
DEBUG_PRINT("***** GET BACK IN PLANE")
if not bShownExitVehicle
PRINT_NOW("EPS6_03", 7500, 1) //Get back in the ~b~plane.
bShownExitVehicle = TRUE
ENDIF
ENDIF
// *** If we've shown "Lose the cops" already, we can show it again if the player gets a wanted level while on foot
IF bShownLoseCops
bShownLoseCops = FALSE
ENDIF
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF IS_THIS_CONVERSATION_ROOT_PLAYING("EPS6_ARMY")
OR IS_THIS_CONVERSATION_ROOT_PLAYING("EPS6_LEAVE")
OR IS_THIS_CONVERSATION_ROOT_PLAYING("EPS6_SAFE")
OR IS_THIS_CONVERSATION_ROOT_PLAYING("EPS6_PUSHED")
OR IS_THIS_CONVERSATION_ROOT_PLAYING("EPS6_FLIGHT")
KILL_ANY_CONVERSATION()
ENDIF
ENDIF
// *** Keep the landing goal blip gone while out of the plane
SAFE_REMOVE_BLIP(pcp_LandingGoal.biBlipIdx)
// *** If you get any more than 120m away from the plane, you fail the mission
IF (GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), GET_ENTITY_COORDS(mv_plane.VehIdx)) > 80)
// Check to make sure the player hasn't run too far away from the plane
// If the player's left the plane within about 50m of Jimmy, increase the range of abandonment
// (this is so if they roll it into the area at high speed and bail,
// the mission won't automatically fail if the plane exits the locate on the other side)
IF GET_DISTANCE_BETWEEN_ENTITY_AND_COORD(mv_plane.VehIdx, <<1654.72, 3239.21, 39.55>>) >= 50
IF NOT bAbandonment
PRINT_NOW("EPS6_BACKPL", DEFAULT_GOD_TEXT_TIME, 1) //Return to the ~b~plane.
bAbandonment = TRUE // Uh oh, player is >80m away from the plane, are they abandoning the mission?
ELIF (GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), GET_ENTITY_COORDS(mv_plane.VehIdx)) > 150)
if IS_PLAYER_IN_AIR()
bTeleOnFail = TRUE
ENDIF
FailedReason = FAILED_LEFT_PLANE
subState = SS_INIT
missionStage = MS_FAILED
TRIGGER_MUSIC_EVENT("EPS_FAIL")
ENDIF
ELSE
IF NOT bAbandonment
PRINT_NOW("EPS6_BACKPL", DEFAULT_GOD_TEXT_TIME, 1) //Return to the ~b~plane.
bAbandonment = TRUE // Uh oh, player is >80m away from the plane, are they abandoning the mission?
ELIF (GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), GET_ENTITY_COORDS(mv_plane.VehIdx)) > 250)
if IS_PLAYER_IN_AIR()
bTeleOnFail = TRUE
ENDIF
FailedReason = FAILED_LEFT_PLANE
subState = SS_INIT
missionStage = MS_FAILED
TRIGGER_MUSIC_EVENT("EPS_FAIL")
ENDIF
ENDIF
ELSE
IF bAbandonment
bAbandonment = false //Less than 80m away from the plane, player isn't abandoning the mission
ENDIF
ENDIF
// ***********
// PLANE IN LANDING AREA CHECK
// ***********
// The player may have bailed from the plane and rolled it into the landing area, so check for this (B*1162916)
IF GET_PLAYER_WANTED_LEVEL(PLAYER_ID()) = 0 // Only progress if the player does not have a wanted level
IF IS_ENTITY_IN_ANGLED_AREA(mv_plane.VehIdx, vPlaneDetect1, vPlaneDetect2,
33.250000, FALSE, TRUE, TM_IN_VEHICLE)
DEBUG_PRINT("Plane detected")
DEBUG_PRINT("*** Entering Landing cleanup")
subState = SS_SHUTDOWN
ENDIF
ENDIF
// // *** If the player's in the plane, make Jimmy do his anim - otherwise keep him looking at the player
// IF IS_ENTITY_ALIVE(mp_Jimmy.piPedIdx)
// IF IS_PED_IN_ANY_PLANE(PLAYER_PED_ID())
// if not IS_ENTITY_PLAYING_ANIM(mp_Jimmy.piPedIdx, mp_Jimmy.AnimDict, mp_Jimmy.AnimName)
// TASK_TURN_PED_TO_FACE_ENTITY(mp_Jimmy.piPedIdx, mv_plane.VehIdx)
// TASK_PLAY_ANIM(mp_Jimmy.piPedIdx, mp_Jimmy.AnimDict, mp_Jimmy.AnimName, NORMAL_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_UPPERBODY | AF_LOOPING | AF_SECONDARY)
// ENDIF
// ELSE
// if NOT IS_PED_FACING_PED(mp_Jimmy.piPedIdx, PLAYER_PED_ID(), 45)
// TASK_TURN_PED_TO_FACE_ENTITY(mp_Jimmy.piPedIdx, mv_plane.VehIdx)
// TASK_STAND_STILL(mp_Jimmy.piPedIdx, -1)
// ENDIF
// ENDIF
// ENDIF
CHECK_JIMMY_AGGRO()
ENDIF
ELSE
// Something's gone wrong with the plane here, so fail the mission
FailedReason = FAILED_DESTROYED
subState = SS_INIT
missionStage = MS_FAILED
bTeleOnFail = TRUE
TRIGGER_MUSIC_EVENT("EPS_FAIL")
ENDIF
IF bSpawnJimmy = TRUE // Don't check this until we've set the checkpoint and spawned Jimmy
IF NOT IS_ENTITY_ALIVE(mp_Jimmy.piPedIdx)
FailedReason = FAILED_KILLED_JIMMY
subState = SS_INIT
missionStage = MS_FAILED
TRIGGER_MUSIC_EVENT("EPS_FAIL")
ENDIF
ENDIF
BREAK
CASE SS_SHUTDOWN
If IS_VEHICLE_OK(mv_plane.VehIdx)
IF IS_ENTITY_IN_ANGLED_AREA(mv_plane.VehIdx, vPlaneDetect1, vPlaneDetect2,
33.250000, FALSE, TRUE, TM_IN_VEHICLE)
SAFE_REMOVE_BLIP(mv_plane.biBlipIdx)
IF GET_LANDING_GEAR_STATE(mv_plane.VehIdx) = LGS_LOCKED_DOWN
OR GET_LANDING_GEAR_STATE(mv_plane.VehIdx) = LGS_DEPLOYING
// Blip Jimmy, remove landing spot blip
IF NOT DOES_BLIP_EXIST(mp_Jimmy.biPedBlip)
mp_Jimmy.biPedBlip = CREATE_PED_BLIP(mp_Jimmy.piPedIdx, TRUE, TRUE, BLIPPRIORITY_HIGHEST)
ENDIF
SAFE_REMOVE_BLIP(pcp_LandingGoal.biBlipIdx)
IF bShownLandAtAirfield
// Only clear prints once, then God Text loop will stop this
CLEAR_PRINTS()
ENDIF
IF NOT bShownGoToJimmy
REPLAY_RECORD_BACK_FOR_TIME(15.0, 5.0, REPLAY_IMPORTANCE_LOW)
PRINT_NOW("EPS6_LEAVE", DEFAULT_GOD_TEXT_TIME, 1) // Go to ~b~Jimmy Boston.
bShownGoToJimmy = TRUE
bShownLandAtAirfield = FALSE // Set this to FALSE so if the player flies out of the area, it will give them the god text again
ENDIF
IF HAS_PLANE_ALMOST_STOPPED()
AND NOT IS_PED_IN_VEHICLE(PLAYER_PED_ID(), mv_plane.VehIdx)
DEBUG_PRINT("*** Finishing Landing cleanup")
DEBUG_PRINTINT("*** Plane 'entity' health: ", GET_ENTITY_HEALTH(mv_plane.VehIdx))
DEBUG_PRINTFLOAT("*** Plane engine health: ", GET_VEHICLE_ENGINE_HEALTH(mv_plane.VehIdx))
DEBUG_PRINTFLOAT("*** Plane petrol tank health: ", GET_VEHICLE_PETROL_TANK_HEALTH(mv_plane.VehIdx))
IF GET_ENTITY_HEALTH(mv_plane.VehIdx) = 1000
AND GET_VEHICLE_ENGINE_HEALTH(mv_plane.VehIdx) = 1000.0
AND GET_VEHICLE_PETROL_TANK_HEALTH(mv_plane.VehIdx) = 1000.0
INFORM_STAT_SYSTEM_OF_BOOL_STAT_HAPPENED(EP6_PERFECT_LANDING)
ENDIF
SAFE_REMOVE_BLIP(pcp_LandingGoal.biBlipIdx)
missionStage = MS_SEEJIMMY
subState = SS_INIT
ENDIF
ENDIF
IF GET_LANDING_GEAR_STATE(mv_plane.VehIdx) = LGS_RETRACTING
OR GET_LANDING_GEAR_STATE(mv_plane.VehIdx) = LGS_LOCKED_UP
OR GET_LANDING_GEAR_STATE(mv_plane.VehIdx) = LGS_BROKEN
// The player has fucked up the landing gear on the plane
DEBUG_PRINT("In the landing area and landing gear is retracting, locked up or broken")
FailedReason = FAILED_DESTROYED
subState = SS_INIT
missionStage = MS_FAILED
TRIGGER_MUSIC_EVENT("EPS_FAIL")
ENDIF
ELSE
DEBUG_PRINT("*** Plane out of delivery area, reverting back to Landing running state")
SET_VEHICLE_ENGINE_ON(mv_plane.VehIdx, TRUE, FALSE)
SET_VEHICLE_DOORS_LOCKED(mv_plane.VehIdx, VEHICLELOCK_UNLOCKED)
subState = SS_RUNNING
ENDIF
ELSE
// The player has fucked up the plane
DEBUG_PRINT("Plane not OK in landing cleanup")
FailedReason = FAILED_DESTROYED
subState = SS_INIT
missionStage = MS_FAILED
TRIGGER_MUSIC_EVENT("EPS_FAIL")
ENDIF
BREAK
ENDSWITCH
ENDPROC
VECTOR vTempJimmy
//PURPOSE: Main mission state process for the player to go and walk to Jimmy by the air field.
PROC m_pSeeJimmy()
SWITCH subState
case SS_INIT
DEBUG_PRINT("*** Doing See Jimmy init")
SET_REPLAY_MID_MISSION_STAGE_WITH_NAME(CP_LANDING, "See Jimmy stage") // Just in case we've skipped straight to here
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
KILL_ANY_CONVERSATION()
ENDIF
REQUEST_NPC_PED_MODEL(CHAR_JIMMY_BOSTON)
REQUEST_ANIM_DICT(mp_Jimmy.AnimDict)
REQUEST_MODEL(mv_RewardCar.VehName)
REQUEST_MODEL(p_amb_phone_01)
REQUEST_VEHICLE_RECORDING(501, "Eps6_Takeoff")
WHILE NOT HAS_NPC_PED_MODEL_LOADED(CHAR_JIMMY_BOSTON)
OR NOT HAS_ANIM_DICT_LOADED(mp_Jimmy.AnimDict)
OR NOT HAS_MODEL_LOADED(mv_RewardCar.VehName)
OR NOT HAS_MODEL_LOADED(p_amb_phone_01)
OR NOT HAS_VEHICLE_RECORDING_BEEN_LOADED(501, "Eps6_Takeoff")
WAIT(0)
ENDWHILE
IF bHasSkipped
LoadSkip()
IF NOT IS_REPLAY_BEING_SET_UP()
RC_END_Z_SKIP()
ENDIF
bHasSkipped = FALSE
ENDIF
ADD_PED_FOR_DIALOGUE(s_conversation_outro, 3, mp_Jimmy.piPedIdx, "JIMMYBOSTON")
ADD_PED_FOR_DIALOGUE(s_conversation_outro, ENUM_TO_INT(CHAR_MICHAEL), PLAYER_PED_ID(), "MICHAEL")
IF IS_ENTITY_ALIVE(mp_Jimmy.piPedIdx)
TASK_PLAY_ANIM(mp_Jimmy.piPedIdx, mp_Jimmy.AnimDict, mp_Jimmy.AnimName, NORMAL_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_UPPERBODY | AF_LOOPING | AF_SECONDARY) // temp animation
ENDIF
// Wait for the player to be fully out of the plane before showing the God text and progressing the mission
IF IsPlaneOK()
SET_VEHICLE_ENGINE_ON(mv_plane.VehIdx, false, false)
ENDIF
// Blip Jimmy, remove landing spot blip
IF NOT DOES_BLIP_EXIST(mp_Jimmy.biPedBlip)
mp_Jimmy.biPedBlip = CREATE_PED_BLIP(mp_Jimmy.piPedIdx, TRUE, TRUE, BLIPPRIORITY_HIGHEST)
ENDIF
IF Is_Replay_In_Progress()
IF IS_REPLAY_BEING_SET_UP()
END_REPLAY_SETUP()
ENDIF
RC_END_Z_SKIP()
ENDIF
IF CAN_REQUEST_ASSETS_FOR_CUTSCENE_ENTITY()
DEBUG_PRINT("Trying to set player component variation (init)")
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
SET_CUTSCENE_PED_COMPONENT_VARIATION_FROM_PED_SAFE("Michael", PLAYER_PED_ID())
ENDIF
SET_CUTSCENE_PED_PROP_VARIATION("Jimmy_Boston", ANCHOR_EYES, 0)
ENDIF
IF iNavBlockingObj = -1
iNavBlockingObj = ADD_NAVMESH_BLOCKING_OBJECT(<<1687.9539, 3277.7268, 40.2500>>, <<6,6,6>>, 0)
DEBUG_PRINT("Navmesh blocking object created")
ENDIF
iJimmyBeckonTimer = GET_GAME_TIMER() - 10000
bAbandonment = false // Reset abandonment check
//PRINT_NOW("EPS6_GOTO", DEFAULT_GOD_TEXT_TIME, 1)
DEBUG_PRINT("*** Going into See Jimmy running state")
subState = SS_RUNNING
BREAK
CASE SS_RUNNING
IF DID_PLAYER_PLACE_STICKY_BOMB_ON_PLANE()
STICKY_BOMB_FAIL()
ENDIF
IF IS_ENTITY_ALIVE(mp_Jimmy.piPedIdx)
IF GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), mp_Jimmy.piPedIdx) < DEFAULT_CUTSCENE_LOAD_DIST
IF NOT HAS_CUTSCENE_LOADED()
REQUEST_CUTSCENE("ep_6_rcm")
DEBUG_PRINT("Requesting cutscene now")
ENDIF
ELIF GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), mp_Jimmy.piPedIdx) > DEFAULT_CUTSCENE_UNLOAD_DIST
IF HAS_CUTSCENE_LOADED()
DEBUG_PRINT("Player moved away - unloading midtro")
REMOVE_CUTSCENE()
ENDIF
ENDIF
ENDIF
IF CAN_REQUEST_ASSETS_FOR_CUTSCENE_ENTITY()
DEBUG_PRINT("Trying to set player component variation (running)")
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
SET_CUTSCENE_PED_COMPONENT_VARIATION_FROM_PED_SAFE("Michael", PLAYER_PED_ID())
ENDIF
SET_CUTSCENE_PED_PROP_VARIATION("Jimmy_Boston", ANCHOR_EYES, 0)
ENDIF
//HANDLE_DUMPING_SCENE() // Should release everything when it hits this point
HANDLE_JIMMY_BECKON_LINES()
HANDLE_JIMMY_ABANDONMENT()
HANDLE_STREAMVOL_SETUP()
IF IsPlaneOK()
//SET_VEHICLE_ENGINE_ON(mv_plane.VehIdx, false, false) // Keep plane engine off
CHECK_JIMMY_AGGRO() // Make sure the mission fails if the player starts shooting at Jimmy
// If the player's in a vehicle, play the outro when ~13m away after getting out of the car
// If on foot, do it ~5m away
IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
// If the player has got back into the plane, punt them back to the Landing stage
IF IS_PED_IN_VEHICLE(PLAYER_PED_ID(), mv_plane.VehIdx)
subState = SS_SHUTDOWN
missionStage = MS_LANDING
ENDIF
IF IS_ENTITY_IN_RANGE_ENTITY(PLAYER_PED_ID(), mp_Jimmy.piPedIdx, 13)
IF NOT IS_VEHICLE_STOPPED(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()))
BRING_VEHICLE_TO_HALT(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()), 2, -1)
ELSE
TASK_LEAVE_ANY_VEHICLE(PLAYER_PED_ID())
WHILE IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
WAIT(0)
ENDWHILE
subState = SS_SHUTDOWN
ENDIF
ENDIF
ELSE
IF IS_ENTITY_IN_RANGE_ENTITY(PLAYER_PED_ID(), mp_Jimmy.piPedIdx, 5)
IF IS_ENTITY_ALIVE(PLAYER_PED_ID()) AND IS_ENTITY_ALIVE(mp_Jimmy.piPedIdx)
vTempPlayer = GET_ENTITY_COORDS(PLAYER_PED_ID())
vTempJimmy = GET_ENTITY_COORDS(mp_Jimmy.piPedIdx)
IF (vTempPlayer.z - vTempJimmy.z) < 1.5
AND NOT IS_PED_FALLING(PLAYER_PED_ID())
AND NOT IS_PED_RAGDOLL(PLAYER_PED_ID())
subState = SS_SHUTDOWN
ENDIF
ENDIF
ENDIF
ENDIF
ELSE
// Something's gone wrong with the plane here, so fail the mission
FailedReason = FAILED_DESTROYED
subState = SS_INIT
missionStage = MS_FAILED
TRIGGER_MUSIC_EVENT("EPS_FAIL")
ENDIF
BREAK
CASE SS_SHUTDOWN
DEBUG_PRINT("*** Doing See Jimmy cleanup")
missionStage = MS_ENDCUTSCENE
subState = SS_INIT
BREAK
ENDSWITCH
ENDPROC
//PURPOSE: Main mission state process for the ending mocap and scripted cutscene.
PROC m_pEndCutscene()
SWITCH subState
case SS_INIT
DEBUG_PRINT("*** Doing End Cutscene init")
if bHasSkipped = TRUE
LoadSkip()
IF NOT IS_REPLAY_BEING_SET_UP()
RC_END_Z_SKIP()
ENDIF
bHasSkipped = FALSE
ENDIF
IF NOT DOES_BLIP_EXIST(mp_Jimmy.biPedBlip)
mp_Jimmy.biPedBlip = CREATE_PED_BLIP(mp_Jimmy.piPedIdx, TRUE, TRUE, BLIPPRIORITY_HIGHEST)
ENDIF
ADD_PED_FOR_DIALOGUE(s_conversation_outro, 3, mp_Jimmy.piPedIdx, "JIMMYBOSTON")
ADD_PED_FOR_DIALOGUE(s_conversation_outro, ENUM_TO_INT(CHAR_MICHAEL), PLAYER_PED_ID(), "MICHAEL")
IF Is_Replay_In_Progress()
IF IS_REPLAY_BEING_SET_UP()
END_REPLAY_SETUP()
REQUEST_CUTSCENE("ep_6_rcm")
DEBUG_PRINT("Requested cutscene for replay skip")
IF CAN_REQUEST_ASSETS_FOR_CUTSCENE_ENTITY()
SET_CUTSCENE_PED_PROP_VARIATION("Jimmy_Boston", ANCHOR_EYES, 0)
ENDIF
WHILE NOT HAS_CUTSCENE_LOADED()
DEBUG_PRINT("Waiting for cutscene to load in replay skip...")
IF CAN_REQUEST_ASSETS_FOR_CUTSCENE_ENTITY()
SET_CUTSCENE_PED_PROP_VARIATION("Jimmy_Boston", ANCHOR_EYES, 0)
ENDIF
WAIT(0)
ENDWHILE
RC_END_Z_SKIP(FALSE, FALSE, FALSE)
ENDIF
ENDIF
IF RC_IS_CUTSCENE_OK_TO_START()
SET_ROADS_IN_ANGLED_AREA(<<1775.157349,3373.424805,37.246861>>, <<1893.735107,3203.022217,48.487232>>, 96.5, FALSE, FALSE)
SAFE_REMOVE_BLIP(mv_plane.biBlipIdx) // Just in case
//SAFE_REMOVE_BLIP(mp_Jimmy.biBlipIdx)
If IsPlaneOK()
SET_ENTITY_COORDS (mv_plane.VehIdx, <<1674.91, 3252.47, 41.69>>)
SET_ENTITY_HEADING (mv_plane.VehIdx, 284.26)
SET_VEHICLE_ON_GROUND_PROPERLY(mv_plane.VehIdx)
ELSE
SAFE_DELETE_VEHICLE(mv_plane.VehIdx)
mv_plane.VehIdx = CREATE_VEHICLE(mv_plane.VehName, <<1674.91, 3252.47, 41.69>>, 284.26)
SET_VEHICLE_AS_RESTRICTED(mv_plane.VehIdx, 0)
SET_VEHICLE_ON_GROUND_PROPERLY(mv_plane.VehIdx)
ENDIF
IF IS_ENTITY_ALIVE(mp_Jimmy.piPedIdx)
REGISTER_ENTITY_FOR_CUTSCENE(mp_Jimmy.piPedIdx, "Jimmy_Boston", CU_ANIMATE_EXISTING_SCRIPT_ENTITY)
ENDIF
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
REGISTER_ENTITY_FOR_CUTSCENE(PLAYER_PED_ID(), "Michael", CU_ANIMATE_EXISTING_SCRIPT_ENTITY)
ENDIF
IF IS_ENTITY_ALIVE(mv_plane.VehIdx)
REGISTER_ENTITY_FOR_CUTSCENE(mv_plane.VehIdx, "ep_plane", CU_ANIMATE_EXISTING_SCRIPT_ENTITY)
ENDIF
// iCutsceneStage = 0
REPLAY_START_EVENT(REPLAY_IMPORTANCE_LOW)
TRIGGER_MUSIC_EVENT("EPS6_STOP")
START_CUTSCENE()
WAIT(0)
IF Is_Replay_In_Progress()
SAFE_FADE_SCREEN_IN_FROM_BLACK(DEFAULT, FALSE)
ENDIF
SAFE_DELETE_OBJECT(oiJimmyPhone)
RESOLVE_VEHICLES_INSIDE_ANGLED_AREA_WITH_SIZE_LIMIT(<<1679.916748,3270.734619,39.344662>>, <<1697.998535,3281.171631,44.149509>>, 7.75,
<< 1530.8623, 3767.0510, 33.0489 >>, 304.28, GET_DEFAULT_ALLOWABLE_VEHICLE_SIZE_VECTOR())
RC_START_CUTSCENE_MODE(<< 1525.0846, 3772.6855, 33.5119 >>, TRUE, FALSE, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT)
DEBUG_PRINT("*** Going into End Cutscene running state")
subState = SS_RUNNING
ENDIF
CHECK_JIMMY_AGGRO()
BREAK
CASE SS_RUNNING
IF iCutsceneStage = 0
//SET_GAMEPLAY_CAM_RELATIVE_HEADING()
//SET_GAMEPLAY_CAM_RELATIVE_PITCH()
// While the mocap is going on, prepare for the scripted cutscene and set this all up
IF IS_CUTSCENE_SKIP_BUTTON_JUST_PRESSED_WITH_DELAY()
SET_GAMEPLAY_CAM_RELATIVE_HEADING()
SET_GAMEPLAY_CAM_RELATIVE_PITCH()
iCutsceneStage = 1
ENDIF
IF CAN_SET_EXIT_STATE_FOR_CAMERA()
// SAFE_TELEPORT_ENTITY(mv_RewardCar.VehIdx, mv_RewardCar.VehPos, mv_RewardCar.Heading, TRUE) // Move the reward car back to the player
// IF IS_VEHICLE_OK(mv_RewardCar.VehIdx)
// SET_VEHICLE_DOORS_LOCKED(mv_RewardCar.VehIdx, VEHICLELOCK_UNLOCKED)
// ENDIF
ENDIF
IF DO_MICHAEL_EXIT()
iCutsceneStage = 1
ENDIF
DO_JIMMY_EXIT()
DO_PLANE_EXIT()
ELIF iCutsceneStage = 1
DO_JIMMY_EXIT()
DO_MICHAEL_EXIT()
DO_PLANE_EXIT()
IF WAS_CUTSCENE_SKIPPED()
SET_GAMEPLAY_CAM_RELATIVE_HEADING()
SET_GAMEPLAY_CAM_RELATIVE_PITCH()
ENDIF
IF CAN_SET_EXIT_STATE_FOR_CAMERA()
REPLAY_STOP_EVENT()
// SAFE_TELEPORT_ENTITY(mv_RewardCar.VehIdx, mv_RewardCar.VehPos, mv_RewardCar.Heading, TRUE) // Move the reward car back to the player
// IF IS_VEHICLE_OK(mv_RewardCar.VehIdx)
// SET_VEHICLE_DOORS_LOCKED(mv_RewardCar.VehIdx, VEHICLELOCK_UNLOCKED)
// ENDIF
ENDIF
IF NOT IS_CUTSCENE_ACTIVE()
SET_GAMEPLAY_CAM_RELATIVE_HEADING()
SET_GAMEPLAY_CAM_RELATIVE_PITCH()
subState = SS_SHUTDOWN
ENDIF
ENDIF
BREAK
CASE SS_SHUTDOWN
DEBUG_PRINT("*** Doing End Cutscene cleanup")
// SAFE_TELEPORT_ENTITY(PLAYER_PED_ID(), <<1629.8502, 3252.1289, 39.8499>>, 106.52, TRUE)
// We need to do a teleport here so we can reset the game camera, otherwise it won't work!
//SAFE_TELEPORT_ENTITY(PLAYER_PED_ID(), << 1688.45, 3277.15, 40.08 >>, 131.1749, TRUE)
IF IS_VEHICLE_OK(mv_RewardCar.VehIdx)
SET_VEHICLE_DOORS_LOCKED(mv_plane.VehIdx, VEHICLELOCK_LOCKOUT_PLAYER_ONLY)
ENDIF
SAFE_TELEPORT_ENTITY(mv_plane.VehIdx, <<1684.78, 3255.58, 41.78>>, 284.26)
IF IS_STREAMVOL_ACTIVE()
STREAMVOL_DELETE(cutsceneStreamvol)
ENDIF
SET_ROADS_BACK_TO_ORIGINAL_IN_ANGLED_AREA(<<1775.157349,3373.424805,37.246861>>, <<1893.735107,3203.022217,48.487232>>, 96.5)
RC_END_CUTSCENE_MODE()
missionStage = MS_WAITFORJIMMY
subState = SS_INIT
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE:
/// Main process to wait for Jimmy to get in the plane and fly away after the mocap
PROC m_pWaitForJimmy()
SWITCH subState
case SS_INIT
DEBUG_PRINT("*** Doing Wait for Jimmy init")
SET_REPLAY_MID_MISSION_STAGE_WITH_NAME(CP_JIMMY, "Wait For Jimmy stage") // Just in case we've skipped straight to here
if bHasSkipped = TRUE
LoadSkip()
IF NOT IS_REPLAY_BEING_SET_UP()
RC_END_Z_SKIP()
ENDIF
bHasSkipped = FALSE
ENDIF
REQUEST_VEHICLE_RECORDING(501, "Eps6_Takeoff")
iJimmyFlyStage = 0
bJimmyGearDone = FALSE
IF Is_Replay_In_Progress()
IF IS_REPLAY_BEING_SET_UP()
END_REPLAY_SETUP()
ENDIF
RC_END_Z_SKIP()
ENDIF
IF IS_VEHICLE_OK(mv_RewardCar.VehIdx)
SET_VEHICLE_DOORS_LOCKED(mv_RewardCar.VehIdx, VEHICLELOCK_UNLOCKED)
ENDIF
IF iNavBlockingObj != -1
REMOVE_NAVMESH_BLOCKING_OBJECT(iNavBlockingObj)
DEBUG_PRINT("Navmesh blocking object removed")
ENDIF
iConvTimer = GET_GAME_TIMER() - 6000
DEBUG_PRINT("*** Going into Wait for Jimmy loop")
subState = SS_RUNNING
BREAK
case SS_RUNNING
IF DID_PLAYER_PLACE_STICKY_BOMB_ON_PLANE()
STICKY_BOMB_FAIL()
ENDIF
IF bCompleteShitskip // Skip the wait for Jimmy stage if the player keeps being a dick and shooting at him and causing a shitskip
subState = SS_SHUTDOWN
ELSE
CHECK_JIMMY_AGGRO()
IF IsPlaneOK()
IF GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), mv_plane.VehIdx) > 300
AND NOT IS_ENTITY_ON_SCREEN(mv_plane.VehIdx)
OPEN_SEQUENCE_TASK(seq)
TASK_PLANE_MISSION(NULL, mv_plane.VehIdx, NULL, NULL, <<3891.4780, 2298.5537, 301.6707>>, MISSION_GOTO, 40, 10, -1, 300, 30)
TASK_PLANE_MISSION(NULL, mv_plane.VehIdx, NULL, NULL, <<1562.0986, 2167.6770, 329.9366>>, MISSION_GOTO, 40, 10, -1, 300, 100)
SET_SEQUENCE_TO_REPEAT(seq, REPEAT_FOREVER)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(mp_Jimmy.piPedIdx, seq)
CLEAR_SEQUENCE_TASK(seq)
subState = SS_SHUTDOWN // If the player drives away before Jimmy flies away, end the mission when far enough away
ENDIF
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
AND NOT IS_PED_FLEEING(mp_Jimmy.piPedIdx)
AND NOT IS_PED_RAGDOLL(mp_Jimmy.piPedIdx)
AND NOT IS_PED_PRONE(mp_Jimmy.piPedIdx)
AND NOT IS_PED_INJURED(mp_Jimmy.piPedIdx)
AND NOT IS_PED_IN_ANY_VEHICLE(mp_Jimmy.piPedIdx)
IF GET_DISTANCE_BETWEEN_ENTITIES(mp_Jimmy.piPedIdx, PLAYER_PED_ID()) <= 2.3
IF (GET_GAME_TIMER() - iConvTimer) > 8000
IF CREATE_CONVERSATION(s_conversation_outro, "EPS6AUD", "EPS6_FOLLOW", CONV_PRIORITY_MEDIUM)
iConvTimer = GET_GAME_TIMER()
ENDIF
ENDIF
ENDIF
ENDIF
switch iJimmyFlyStage
CASE 0
IF IS_PED_SITTING_IN_VEHICLE(mp_Jimmy.piPedIdx, mv_plane.VehIdx)
iJimmyFlyStage++
ENDIF
BREAK
CASE 1
IF NOT IS_PLAYBACK_GOING_ON_FOR_VEHICLE(mv_plane.VehIdx)
IF HAS_VEHICLE_RECORDING_BEEN_LOADED(501, "Eps6_Takeoff")
START_PLAYBACK_RECORDED_VEHICLE(mv_plane.VehIdx, 501, "Eps6_Takeoff")
FORCE_PLAYBACK_RECORDED_VEHICLE_UPDATE(mv_plane.VehIdx)
DEBUG_PRINT("Started vehicle recording on plane #2")
iJimmyFlyStage++
iJimmyFlyGearTimer = GET_GAME_TIMER()
ENDIF
ELSE
DEBUG_PRINT("Unpaused vehicle recording on plane")
UNPAUSE_PLAYBACK_RECORDED_VEHICLE(mv_plane.VehIdx)
SET_HELI_BLADES_SPEED(mv_plane.VehIdx, 1.0)
iJimmyFlyStage++
iJimmyFlyGearTimer = GET_GAME_TIMER()
ENDIF
BREAK
CASE 2
IF IS_PLAYBACK_GOING_ON_FOR_VEHICLE(mv_plane.VehIdx)
SET_HELI_BLADES_SPEED(mv_plane.VehIdx, 1.0)
IF bJimmyGearDone = FALSE
IF (GET_GAME_TIMER() - iJimmyFlyGearTimer) > 23000
DEBUG_PRINT(" Retracting Jimmy's landing gear")
CONTROL_LANDING_GEAR(mv_plane.VehIdx, LGC_RETRACT)
bJimmyGearDone = TRUE
ENDIF
ENDIF
ELSE
OPEN_SEQUENCE_TASK(seq)
TASK_PLANE_MISSION(NULL, mv_plane.VehIdx, NULL, NULL, <<3891.4780, 2298.5537, 301.6707>>, MISSION_GOTO, 40, 10, -1, 300, 30)
TASK_PLANE_MISSION(NULL, mv_plane.VehIdx, NULL, NULL, <<1562.0986, 2167.6770, 329.9366>>, MISSION_GOTO, 40, 10, -1, 300, 100)
SET_SEQUENCE_TO_REPEAT(seq, REPEAT_FOREVER)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(mp_Jimmy.piPedIdx, seq)
IF IS_VEHICLE_OK(mv_plane.VehIdx)
SET_VEHICLE_ENGINE_ON(mv_plane.VehIdx, TRUE, TRUE)
ENDIF
CLEAR_SEQUENCE_TASK(seq)
iJimmyFlyStage++
ENDIF
BREAK
CASE 3
//IF GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), mv_plane.VehIdx) > 300
//AND NOT IS_ENTITY_ON_SCREEN(mv_plane.VehIdx)
subState = SS_SHUTDOWN
//ENDIF
BREAK
ENDSWITCH
ELSE
// Something's gone wrong with the plane here, so fail the mission
FailedReason = FAILED_DESTROYED
subState = SS_INIT
missionStage = MS_FAILED
IF IS_PED_IN_VEHICLE(PLAYER_PED_ID(), mv_plane.VehIdx)
bTeleOnFail = TRUE
ENDIF
TRIGGER_MUSIC_EVENT("EPS_FAIL")
ENDIF
ENDIF
BREAK
CASE SS_SHUTDOWN
DEBUG_PRINT("*** Doing Wait for Jimmy cleanup")
IF NOT bCompleteShitskip
IF IsPlaneOK()
IF GET_LANDING_GEAR_STATE(mv_plane.VehIdx) != LGS_LOCKED_UP
OR GET_LANDING_GEAR_STATE(mv_plane.VehIdx) != LGS_RETRACTING
DEBUG_PRINT(" Retracting Jimmy's landing gear (cleanup)")
CONTROL_LANDING_GEAR(mv_plane.VehIdx, LGC_RETRACT)
ENDIF
ENDIF
SAFE_RELEASE_PED(mp_Jimmy.piPedIdx)
SAFE_RELEASE_VEHICLE(mv_plane.VehIdx)
ELSE
SAFE_DELETE_PED(mp_Jimmy.piPedIdx)
SAFE_DELETE_VEHICLE(mv_plane.VehIdx)
ENDIF
SCRIPT_PASSED()
BREAK
ENDSWITCH
ENDPROC
//******************************************
// Skip functionality
//******************************************
//PURPOSE: Skip back a stage in the mission.
PROC SkipBack()
RC_START_Z_SKIP()
IF IS_CUTSCENE_ACTIVE()
STOP_CUTSCENE_IMMEDIATELY()
RC_END_CUTSCENE_MODE()
ENDIF
TRIGGER_MUSIC_EVENT("EPS_FAIL")
switch missionStage
CASE MS_INIT
subState = SS_INIT
BREAK
CASE MS_FLIGHT
SAFE_REMOVE_BLIP(mv_plane.biBlipIdx)
SAFE_RELEASE_PED(mp_Jimmy.piPedIdx)
SAFE_DELETE_VEHICLE(mv_RewardCar.VehIdx)
missionStage = MS_INIT
subState = SS_INIT
BREAK
CASE MS_LANDING
IF IS_VEHICLE_OK(mv_plane.VehIdx)
IF GET_DISTANCE_BETWEEN_ENTITY_AND_COORD(mv_plane.VehIdx, pcp_LandingGoal.vPointPos) < 1300
// Fake-skip back to the start of the Landing stage if within 1300m of the landing spot, so the player can attempt the landing again
subState = SS_INIT
ELSE
missionStage = MS_FLIGHT
subState = SS_INIT
ENDIF
ENDIF
BREAK
CASE MS_SEEJIMMY
missionStage = MS_LANDING
subState = SS_INIT
BREAK
CASE MS_ENDCUTSCENE
missionStage = MS_SEEJIMMY
subState = SS_INIT
BREAK
CASE MS_WAITFORJIMMY
missionStage = MS_ENDCUTSCENE
subState = SS_INIT
BREAK
DEFAULT
BREAK
ENDSWITCH
ENDPROC
//PURPOSE: Skip forward a stage in the mission.
PROC SkipForward()
RC_START_Z_SKIP()
IF IS_CUTSCENE_ACTIVE()
STOP_CUTSCENE_IMMEDIATELY()
RC_END_CUTSCENE_MODE()
ENDIF
TRIGGER_MUSIC_EVENT("EPS_FAIL")
switch missionStage
CASE MS_INIT
missionStage = MS_FLIGHT
subState = SS_INIT
BREAK
CASE MS_FLIGHT
missionStage = MS_LANDING
subState = SS_INIT
BREAK
CASE MS_LANDING
missionStage = MS_SEEJIMMY
subState = SS_INIT
BREAK
CASE MS_SEEJIMMY
missionStage = MS_ENDCUTSCENE
subState = SS_INIT
BREAK
CASE MS_ENDCUTSCENE
missionStage = MS_WAITFORJIMMY
subState = SS_INIT
BREAK
DEFAULT
RC_END_Z_SKIP()
BREAK
ENDSWITCH
ENDPROC
//PURPOSE: Jump directly to a stage in the mission.
PROC JUMP_TO_STAGE(int iStage)
IF NOT IS_REPLAY_BEING_SET_UP()
RC_START_Z_SKIP()
TRIGGER_MUSIC_EVENT("EPS_FAIL")
ENDIF
bHasSkipped = TRUE
SWITCH iStage
CASE Z_SKIP_INIT
MissionStage = MS_INIT
SubState = SS_INIT
BREAK
CASE Z_SKIP_FLIGHT
MissionStage = MS_FLIGHT
SubState = SS_INIT
BREAK
CASE Z_SKIP_LANDING
MissionStage = MS_LANDING
SubState = SS_INIT
BREAK
CASE Z_SKIP_SEEJIMMY
MissionStage = MS_SEEJIMMY
SubState = SS_INIT
BREAK
CASE Z_SKIP_OUTRO
MissionStage = MS_ENDCUTSCENE
SubState = SS_INIT
BREAK
CASE Z_SKIP_WAITJIMMY
MissionStage = MS_WAITFORJIMMY
SubState = SS_INIT
BREAK
CASE Z_SKIP_COMPLETE
MissionStage = MS_WAITFORJIMMY
SubState = SS_INIT
bCompleteShitskip = TRUE
BREAK
DEFAULT
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE: Check for Forced Pass or Fail
PROC DEBUG_Check_Debug_Keys()
#IF IS_DEBUG_BUILD
IF missionStage <> MS_FAILED
// Skip forward
if IS_KEYBOARD_KEY_JUST_PRESSED(KEY_J)
bHasSkipped = TRUE
SkipForward()
ENDIF
// Skip back
if IS_KEYBOARD_KEY_JUST_PRESSED(KEY_P)
bHasSkipped = TRUE
SkipBack()
ENDIF
// Mission success
if IS_KEYBOARD_KEY_JUST_PRESSED(KEY_S)
bHasSkipped = TRUE
CLEAR_PRINTS()
WAIT_FOR_CUTSCENE_TO_STOP()
TRIGGER_MUSIC_EVENT("EPS6_STOP")
Script_Passed()
ENDIF
// Mission fail
if IS_KEYBOARD_KEY_JUST_PRESSED(KEY_F)
bHasSkipped = TRUE
CLEAR_PRINTS()
WAIT_FOR_CUTSCENE_TO_STOP()
FailedReason = FAILED_DEFAULT
subState = SS_INIT
missionStage = MS_FAILED
TRIGGER_MUSIC_EVENT("EPS_FAIL")
ENDIF
IF LAUNCH_MISSION_STAGE_MENU(s_skip_menu, i_debug_jump_stage)
JUMP_TO_STAGE(i_debug_jump_stage)
ENDIF
ENDIF
// Handle flying buff here
IF bDebugFlyingBuff
INT iStatValue
IF STAT_GET_INT(GET_SP_PLAYER_STAT_ENUM(GET_CURRENT_PLAYER_PED_ENUM(), PS_FLYING_ABILITY), iStatValue)
IF iStatValue < 70
STAT_SET_INT(GET_SP_PLAYER_STAT_ENUM(GET_CURRENT_PLAYER_PED_ENUM(), PS_FLYING_ABILITY), 70)
ENDIF
ENDIF
ENDIF
#ENDIF
ENDPROC
//PURPOSE: Main mission failed state while the fade is ongoing.
PROC m_pFailed()
SWITCH subState
CASE SS_INIT
DEBUG_PRINT("******************* MISSION FAILED *********************")
CLEAR_PRINTS()
CLEAR_HELP()
IF FailedReason <> FAILED_HURT_JIMMY
and FailedReason <> FAILED_SPOOKED_JIMMY
AND FailedReason <> FAILED_SPOOKED_BUDDY
AND FailedReason <> FAILED_HURT_BUDDY
WHILE IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
DEBUG_PRINT("*** Failed() kill conversation")
KILL_ANY_CONVERSATION()
WAIT(0)
ENDWHILE
ENDIF
SET_VEHICLE_GEN_AVAILABLE(VEHGEN_EPSILON6_PLANE, TRUE)
SAFE_REMOVE_BLIP(mv_plane.biBlipIdx)
SAFE_REMOVE_BLIP(mp_Jimmy.biPedBlip)
SAFE_REMOVE_BLIP(pcp_LandingGoal.biBlipIdx)
IF bPlaneTooCloseConv
// We've failed the mission by getting too close to Jimmy while in the plane, need to set up the reaction dialogue
ADD_PED_FOR_DIALOGUE(s_conversation_outro, 3, mp_Jimmy.piPedIdx, "JIMMYBOSTON")
ADD_PED_FOR_DIALOGUE(s_conversation_outro, ENUM_TO_INT(CHAR_MICHAEL), PLAYER_PED_ID(), "MICHAEL")
ENDIF
// set fail string
STRING FailedString
SWITCH FailedReason
CASE FAILED_DESTROYED
FailedString = "EPS6_FAIL"
BREAK
CASE FAILED_KILLED_JIMMY
FailedString = "EPS6_DEAD"
BREAK
CASE FAILED_HURT_JIMMY
FailedString = "EPS6_HURT"
BREAK
CASE FAILED_SPOOKED_JIMMY
FailedString = "EPS6_SPOOK"
BREAK
CASE FAILED_ATTACKED_JIMMY
FailedString = "EPS6_ATTACK"
BREAK
CASE FAILED_LEFT_PLANE
FailedString = "EPS6_04"
BREAK
CASE FAILED_LEFT_DROPOFF
FailedString = "EPS6_LEFT"
BREAK
CASE FAILED_LEFT_PICKUP
FailedString = "EPS6_ABAND"
BREAK
CASE FAILED_KILLED_BUDDY
FailedString = "EPS6_BUDDYDEAD"
BREAK
CASE FAILED_SPOOKED_BUDDY
FailedString = "EPS6_BUDDYSPOOK"
BREAK
CASE FAILED_HURT_BUDDY
FailedString = "EPS6_BUDDYHURT"
BREAK
CASE FAILED_STICKYBOMB
FailedString = "EPS6_STICKYB"
BREAK
DEFAULT
BREAK
ENDSWITCH
IF FailedReason = FAILED_DEFAULT
Random_Character_Failed()
ELSE
Random_Character_Failed_With_Reason(FailedString)
ENDIF
subState = SS_RUNNING
BREAK
CASE SS_RUNNING
IF GET_MISSION_FLOW_SAFE_TO_CLEANUP()
// Call RemovePlayerFromRestrictedVehicle() here if you need to
// Do a check here to see if we need to warp the player at all
// (only set the fail warp locations if we can't leave the player where he was)
IF bTeleOnFail
// Only set the player back here (near the army base) if they failed the mission before reaching Jimmy Boston
MISSION_FLOW_SET_FAIL_WARP_LOCATION(<< -2932.7339, 3241.3037, 9.4520 >>, 228.8328)
SET_REPLAY_DECLINED_VEHICLE_WARP_LOCATION(<< -2932.7339, 3241.3037, 9.4520 >>, 228.8328)
ENDIF
DeleteEverything()
Script_Cleanup() // script_cleanup should terminate the thread
ELSE
// not finished fading out
// you may want to handle dialogue etc here.
IF bPlaneTooCloseConv
ENDIF
ENDIF
BREAK
ENDSWITCH
ENDPROC
// ===========================================================================================================
// Script Loop
// ===========================================================================================================
SCRIPT(g_structRCScriptArgs sRCLauncherDataIn)
DEBUG_PRINT("*** Epsilon 6 is now running")
sRCLauncherDataLocal = sRCLauncherDataIn
RC_TakeEntityOwnership(sRCLauncherDataLocal)
RC_SET_ENTITY_PROOFS_FOR_CUTSCENE(sRCLauncherDataLocal, FALSE)
RC_CLEANUP_LAUNCHER()
SET_MISSION_FLAG(TRUE)
// Setup callback when player is killed, arrested or goes to multiplayer
IF (HAS_FORCE_CLEANUP_OCCURRED(DEFAULT_FORCE_CLEANUP_FLAGS|FORCE_CLEANUP_FLAG_DEBUG_MENU))
PRINT_LAUNCHER_DEBUG("Force cleanup [TERMINATING]")
TRIGGER_MUSIC_EVENT("EPS_FAIL")
Random_Character_Failed()
Script_Cleanup()
ENDIF
IF NOT Is_Replay_In_Progress()
IF NOT IS_CUTSCENE_ACTIVE()
REQUEST_CUTSCENE("ep_6_rcm")
DEBUG_PRINT("Requesting cutscene now")
ENDIF
ELSE // Set up the initial scene for replays
IF Get_Replay_Mid_Mission_Stage() = CP_START
g_bSceneAutoTrigger = TRUE
eInitialSceneStage = IS_REQUEST_SCENE
WHILE NOT SetupScene_EPSILON_6(sRCLauncherDataLocal)
WAIT(0)
ENDWHILE
g_bSceneAutoTrigger = FALSE
ENDIF
ENDIF
// Assign vehicle handle to the one used by this script
IF IS_VEHICLE_OK(sRCLauncherDataLocal.vehID[0])
mv_plane.VehIdx = sRCLauncherDataLocal.vehID[0]
SET_VEHICLE_AS_RESTRICTED(mv_plane.VehIdx, 0)
SET_VEHICLE_HAS_STRONG_AXLES(mv_plane.VehIdx, TRUE)
SET_VEHICLE_DOORS_LOCKED(mv_plane.VehIdx, VEHICLELOCK_UNLOCKED)
ENDIF
IF IS_PED_UNINJURED(PLAYER_PED_ID())
relGroupPlayer = GET_PED_RELATIONSHIP_GROUP_HASH(PLAYER_PED_ID())
ENDIF
// Assign initial scene peds to script handles
IF IS_ENTITY_ALIVE(sRCLauncherDataLocal.pedID[0]) // The player may have killed the Cultist by this point, so do this check
mp_Cultist.piPedIdx = sRCLauncherDataLocal.pedID[0]
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(mp_Cultist.piPedIdx, TRUE)
SET_PED_RELATIONSHIP_GROUP_HASH(mp_Cultist.piPedIdx, relGroupPlayer)
SET_PED_CONFIG_FLAG(mp_Cultist.piPedIdx, PCF_KeepRelationshipGroupAfterCleanUp, TRUE)
ENDIF
LOAD_GLOBAL_RESOURCES()
DEBUG_PRINT("*** Epsilon 6 is now in loop")
IF Is_Replay_In_Progress()
DEBUG_PRINT("*** Replay detected! Skipping to appropriate stage!")
INT iReplayStage = Get_Replay_Mid_Mission_Stage()
IF g_bShitskipAccepted = TRUE
iReplayStage++ // player is skipping this stage
ENDIF
SWITCH iReplayStage
CASE CP_START
START_REPLAY_SETUP(<<-2907.2898, 3215.9097, 9.8660>>, 215.2019)
// Do nothing - mission will start as normal
BREAK
CASE CP_LANDING
START_REPLAY_SETUP(<<376.0205, 2886.5520, 171.3085>>, -132.35)
JUMP_TO_STAGE(Z_SKIP_LANDING) // Go to MS_LANDING
BREAK
CASE CP_OUTRO
START_REPLAY_SETUP(<<1681.54, 3259.38, 39.77>>, 298.33)
JUMP_TO_STAGE(Z_SKIP_OUTRO) // Go to MS_OUTRO (if the player screws up the landing 3 times and shitskips it)
BREAK
CASE CP_JIMMY
START_REPLAY_SETUP(<< 1688.45, 3277.15, 40.08 >>, 131.1749)
JUMP_TO_STAGE(Z_SKIP_WAITJIMMY) // Go to MS_WAITFORJIMMY
BREAK
CASE CP_COMPLETE
START_REPLAY_SETUP(<< 1688.45, 3277.15, 40.08 >>, 131.1749)
JUMP_TO_STAGE(Z_SKIP_COMPLETE) // Go to MS_WAITFORJIMMY with special bool (shitskip only)
BREAK
DEFAULT
SCRIPT_ASSERT("Replay in progress: Unknown checkpoint selected?")
BREAK
ENDSWITCH
ELSE
RC_END_Z_SKIP(FALSE)
ENDIF
// Loop within here until the mission passes or fails
WHILE(TRUE)
REPLAY_CHECK_FOR_EVENT_THIS_FRAME("SF_Epsilon6")
WAIT(0)
UPDATE_MISSION_NAME_DISPLAYING(sRCLauncherDataLocal.sIntroCutscene)
// Keep searching for this, as the group has to be loaded in for it to actually disable the group
IF DOES_SCENARIO_GROUP_EXIST("SANDY_PLANES")
IF IS_SCENARIO_GROUP_ENABLED("SANDY_PLANES")
SET_SCENARIO_GROUP_ENABLED("SANDY_PLANES",FALSE)
DEBUG_PRINT("Disabled Sandy planes")
ENDIF
ENDIF
SWITCH missionStage
CASE MS_INIT
m_pInit()
BREAK
CASE MS_FLIGHT
m_pFlight()
BREAK
CASE MS_LANDING
m_pLanding()
BREAK
CASE MS_SEEJIMMY
m_pSeeJimmy()
BREAK
CASE MS_ENDCUTSCENE
m_pEndCutscene()
BREAK
CASE MS_WAITFORJIMMY
m_pWaitForJimmy()
BREAK
CASE MS_FAILED
m_pFailed()
BREAK
ENDSWITCH
// Check debug completion/failure
DEBUG_Check_Debug_Keys()
ENDWHILE
// Script should never reach here. Always terminate with cleanup function.
ENDSCRIPT