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

5272 lines
184 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 "commands_cutscene.sch"
USING "commands_entity.sch"
USING "commands_event.sch"
USING "commands_script.sch"
USING "cutscene_public.sch"
USING "dialogue_public.sch"
USING "randomChar_public.sch"
USING "rgeneral_include.sch"
USING "RC_Helper_Functions.sch"
USING "replay_public.sch"
USING "script_ped.sch"
USING "script_player.sch"
USING "shared_hud_displays.sch"
USING "CompletionPercentage_public.sch"
USING "RC_Threat_public.sch"
USING "RC_Setup_public.sch"
USING "initial_scenes_fanatic.sch"
USING "cheat_controller_public.sch"
USING "commands_recording.sch"
#IF IS_DEBUG_BUILD
USING "select_mission_stage.sch"
#ENDIF
// *****************************************************************************************
// *****************************************************************************************
// *****************************************************************************************
//
// MISSION NAME : Fanatic1.sc
// AUTHOR : Neil Beggs (originally)/Ian Gander (June 12 onwards)
// DESCRIPTION : Foot race against Mary Ann, a fitness fanatic
//
// *****************************************************************************************
// *****************************************************************************************
// *****************************************************************************************
//----------------------
// CHECKPOINTS
//----------------------
CONST_INT CP_AFTER_MOCAP 0
//-------------------------------------------------------------------------------------------------------------------------------------------------
// ENUMS:
//-------------------------------------------------------------------------------------------------------------------------------------------------
ENUM MISSION_STAGE
MS_LEADIN,
MS_CUTSCENE,
MS_START_RUNNING,
MS_ROAD_RUNNING_SECTION,
MS_STEPS_DOWN,
MS_SPRINT_TO_FINISH,
MS_DEBUG_NEAR_FINISH_LINE,
MS_PLAYER_IN_VEHICLE,
MS_END_CUTSCENE,
MS_LOST_RACE,
MS_FAIL_WAIT_FOR_FADE
ENDENUM
ENUM FINISH_TACTIC
FINISHED_BY_STEROIDS,
FINISHED_BY_SHORTCUT
ENDENUM
ENUM STAGE_STAGE
SS_SETUP,
SS_STAGE
ENDENUM
ENUM STUCK_STAGE
STUCK_UPDATE,
STUCK_LOOP,
STUCK_FIX
ENDENUM
ENUM debugSkipToMissionStage
DEBUG_TO_INTRO = 0,
DEBUG_TO_START,
DEBUG_TO_ROAD,
DEBUG_TO_STEPS_DOWN,
DEBUG_TO_BEACH,
DEBUG_TO_FINISH_LINE,
DEBUG_NEXT_TO_FINISH
ENDENUM
ENUM FAIL_REASON
FAIL_FANATIC_KILLED,
FAIL_FANATIC_INJURED,
FAIL_FANATIC_SCARED,
FAIL_IN_CAR,
FAIL_YOU_DIDNT_KEEP_UP,
FAIL_SHE_BEAT_YOU_TO_BIKE,
FAIL_LEFT_RACE,
REASON_SILENT
ENDENUM
ENUM CUTSCENE_ENUM
CS_PLAYER_WINS,
CS_WAIT_FOR_ANN,
CS_MARY_ANN_LEAVES,
CS_SAY_FINAL_LINE,
CS_CUTSCENE_ENDS
ENDENUM
ENUM CAMERA_TARGET
CAM_TARGET_PLAYER,
CAM_MARY_ANN_LEAVES
ENDENUM
ENUM SPRINT_STATE
SPRINT_WAITING,
SPRINT_ACTIVE,
SPRINT_REDUCE,
SPRINT_COOLDOWN
ENDENUM
ENUM DRIVE_BY_STATE
DRIVE_BY_LOAD,
DRIVE_BY_PRE_TASK,
DRIVE_BY_SET_DRIVE_TASK,
DRIVE_BY_DRIVE,
DRIVE_BY_SET_FINGER_TASK,
DRIVE_BY_FINGERING,
DRIVE_BY_RELEASE
ENDENUM
ENUM MARY_ANN_DIALOGUE_STATE
MA_WITHIN_TALKING_RANGE,
MA_OUT_OF_TALKING_RANGE,
MA_SHOUTING_TO_KEEP_UP,
MA_SAYING_YOU_CAUGHT_UP
ENDENUM
ENUM DOG_STATE_ENUM
DOG_LOADING,
DOG_WAITING,
DOG_FOLLOWING_PLAYER
ENDENUM
ENUM CPR_STATE
CPR_LOADING,
CPR_WAITING,
CPR_GOING_TO_SCENE,
CPR_INTRO,
CPR_IDLE,
CPR_GETTING_UP,
CPR_INTERUPTED,
CPR_WATCHING_PLAYER,
CPR_FLEE
ENDENUM
//-------------------------------------------------------------------------------------------------------------------------------------------------
// :STRUCTS:
//-------------------------------------------------------------------------------------------------------------------------------------------------
STRUCT JOGGERS
PED_INDEX thisIndex
MODEL_NAMES thisModel
VECTOR thisPosition
VECTOR thisGoToPos1
VECTOR thisGoToPos2
Float thisHeading
ENDSTRUCT
STRUCT VEHICLE_STRUCT
PED_INDEX Driver
PED_INDEX Passenger
VEHICLE_INDEX thisCarIndex
MODEL_NAMES thisPedModel
MODEL_NAMES thisCarModel
VECTOR thisPosition
VECTOR thisGoToPos
Float thisHeading
FLOAT thisSpeed
ENDSTRUCT
STRUCT CONV_STRUCT
STRING rootLabel
STRING dialogueLine
BOOL hasBeenPlayed = FALSE
BOOL hasBeenInterrupted = FALSE
INT restartLine = -1
ENDSTRUCT
STRUCT RANDOM_CONV_STRUCT
STRING dialogueLine
INT timesPlayed = 0
INT restartLine = -1
ENDSTRUCT
STRUCT GOD_TEXT_STRUCT
STRING textLabel
BOOL hasBeenShown = FALSE
ENDSTRUCT
//-------------------------------------------------------------------------------------------------------------------------------------------------
// :VARIABLES:
//-------------------------------------------------------------------------------------------------------------------------------------------------
// The Random Character - sRCLauncherDataLocal.pedID[0]
g_structRCScriptArgs sRCLauncherDataLocal
// Mission stuff
STAGE_STAGE stageStage = SS_SETUP
MISSION_STAGE missionStage = MS_LEADIN
MISSION_STAGE currentMissionStage
FAIL_REASON failReason
FINISH_TACTIC finishReason = FINISHED_BY_STEROIDS
BOOL b_LeadInConvo = FALSE
BOOL b_CutsceneSkipped = FALSE
BOOL b_MusicTriggered = FALSE
BOOL b_DoneOutOfBreath = FALSE
BOOL b_CheatedLine = FALSE
BOOL b_IsTheRoadSwitchedOn = TRUE
BOOL b_PlayerJumpedDownTheCliff = FALSE
BOOL b_ForcePlayerRunningAtStart = TRUE
BOOL b_ScriptedEnding = FALSE
BOOL b_PlayerOnMAsBike = FALSE
BOOL b_MaryAnnFinalOrdersGiven = FALSE
BOOL b_DrivebyHorn = FALSE
BOOL bHasChanged
GOD_TEXT_STRUCT leftBehindWarning
GOD_TEXT_STRUCT leftRaceWarning
GOD_TEXT_STRUCT vehicleWarning
REL_GROUP_HASH relGroupFriendly
sequence_index seq
structPedsForConversation MyLocalPedStruct
// Mary Ann stuff
MARY_ANN_DIALOGUE_STATE MADialogueState = MA_WITHIN_TALKING_RANGE
PED_INDEX MARY_ANN
BLIP_INDEX FANATIC_BLIP
SPRINT_STATE MASprintState = SPRINT_WAITING
INT iSprintTimer
INT iSprintLength = 1800
INT iSprintDelay = 4500
FLOAT fMBRMax = 1.025
FLOAT fMBR_IncreaseRatio = fMBRMax
FLOAT fMBR_MaxRunSpeed = 3.00
FLOAT fMBR_RunSpeed = fMBR_MaxRunSpeed
FLOAT fMBR_SprintCap = -1.0
BOOL b_DoPedOvertake = FALSE
BOOL b_LoadCollisionAroudMaryAnn = FALSE
BOOL bMARY_ANN_CHASING_YOU_IN_CAR = FALSE
BOOL bMARY_ANN_IS_GOING_TO_RUN_SCARED = FALSE
STUCK_STAGE StuckStage = STUCK_UPDATE
INT iStuckTimer
INT iWaypointStuckCheck
// Running Dialogue Stuff
CONST_INT MAX_CHECKPOINTS 10
INT iHurryUpLineNumber = 0
CONST_INT iMAXHurryUpLineNumber 2
STRING HURRY_UP_LINE[iMAXHurryUpLineNumber]
INT iCatchUpLineNumber = 0
CONST_INT iMAXCatchUpLineNumber 2
INT iRaceLineNumber = 0
CONST_INT iMAXRaceLineNumber 3
STRING RACE_LINE[iMAXRaceLineNumber]
TEXT_LABEL tDialogueRoot
RANDOM_CONV_STRUCT MikePushMALine
RANDOM_CONV_STRUCT MikePushPedLine
RANDOM_CONV_STRUCT OvertakeLines
INT iOvertakeTimer
BOOL bOvertaken
BOOL bOvertakenSkip = FALSE
BOOL bCatchupCheatLineSaid = FALSE
INT iOneLinerSeq = 0
INT iOneLinerTimer
INT iRoadCounter = 0
INT iRoadTimer
CONV_STRUCT pushLine[3]
CONV_STRUCT startRunConversation
CONV_STRUCT road1Conversation
CONV_STRUCT road2Conversation
CONV_STRUCT raceConversation
CONV_STRUCT cheatedRanAcrossGrass
CONV_STRUCT cheatedLeaptFence
CONV_STRUCT returnAfterCheatedLine
// Mary Anns Bike stuff
VEHICLE_INDEX MAS_BIKE
VECTOR MAS_BIKE_POS = <<-2002.52, -503.53, 11.27>>
FLOAT MAS_BIKE_DIR = 0.13
MODEL_NAMES MARYSBIKEMODEL = SCORCHER
// Cutscene stuff
CUTSCENE_ENUM cutsceneStage
CAMERA_TARGET myCam = CAM_TARGET_PLAYER
BOOL b_TIRED_ANIM_PLAYING = FALSE
STRING dialogueOptionFinish
CAMERA_INDEX camCutsceneStart
INT iCutsceneStage = 0
//BOOL bCutsceneSkipped = FALSE
ANIM_DATA adBreathEnter
ANIM_DATA adBreathIdle1
ANIM_DATA adBreathIdle2
ANIM_DATA adBreathIdle3
// World filler stuff
VEHICLE_STRUCT DRIVEBY_FINGER_CAR
DRIVE_BY_STATE driveByState = DRIVE_BY_LOAD
VEHICLE_STRUCT FOLLOWING_CAR
JOGGERS OtherJoggers[4]
MODEL_NAMES JOGGERMODEL = A_F_Y_FITNESS_01
BOOL b_FinalPedsStartedWalking = FALSE
PED_INDEX QUAD_DRIVER
PED_INDEX INJURED_PED
PED_INDEX cprWatcher1
PED_INDEX cprWatcher2
VEHICLE_INDEX CHEAT_QUAD
VECTOR vPos_CHEAT_QUAD = <<-1818.96, -751.50, 7.99>>
VECTOR vPos_CPRScene
VECTOR vRot_CPRScene
INT CPRSynchSceneID
INT IdleSynchSceneID
INT NavBlockerID = -1
INT CutsceneNavBlockerID = -1
SCENARIO_BLOCKING_INDEX sbiCutscene // For the benches in the background that occasionally spawn peds in view around 15 secs into the cutscene
SCENARIO_BLOCKING_INDEX sbiWallPeds
SCENARIO_BLOCKING_INDEX sbiPathPeds
SCENARIO_BLOCKING_INDEX sbiMobilePed
PED_INDEX BEACH_DOG
VECTOR vPos_DOG = <<-1957.213013,-555.261414,11.083831>>
FLOAT fDir_DOG = -87.356987
DOG_STATE_ENUM beachDogState = DOG_LOADING
// Race Stuff
STRING sFANATIC_ROUTE = "Fanatic1MaryAnn"
INT place
INT iNum_WAYPOINTS
INT iNum_PlayerClosestWaypoint
INT iNum_NPCClosestWaypoint
VECTOR vPos_PlayerClosestWaypoint
VECTOR vPos_StartOfRoadRunning
VECTOR vPos_StartOfBeachRunning
VECTOR vPos_FinishLine = <<-2005.65, -508.08, 10.76>>
BLIP_INDEX DESTINATION_BLIP
BLIP_INDEX NEXT_DESTINATION_BLIP
CHECKPOINT_INDEX Checkpoint
CHECKPOINT_INDEX PrevCheckpoint
INT iPrevAlpha
INT iMaxRacePositions
VECTOR RACE_POSITIONS[10]
INT iCURRENT_RACE_POS = 0
INT iNPC_RACE_POS = 1
INT start_time = 0
INT iRollingStartTimer
INT iConversationTimer
INT iDrivebyTimer
INT iVehicleFailTimer
INT iHeartbeatAudioID
BOOL bHeartbeatStarted = FALSE
FLOAT fHintFov = 40.0
FLOAT fHintFollow = 0.35
FLOAT fHintPitchOrbit = 0.000
FLOAT fHintSide = -0.80
FLOAT fHintVert = -0.050
// Debug Stuff
#if IS_DEBUG_BUILD
CONST_INT MAX_SKIP_MENU_LENGTH 7
INT i_debug_jump_stage = 0
MissionStageMenuTextStruct s_skip_menu[MAX_SKIP_MENU_LENGTH]
BOOL bDebug_PrintToTTY = TRUE
BOOL bDebug_SpeedDebug = FALSE
FLOAT fPlayerSprintRemaining
WIDGET_GROUP_ID widgetGroup
#ENDIF
CPR_STATE cprState = CPR_LOADING
// ===========================================================================================================
// Debug prints
// ===========================================================================================================
/// PURPOSE: Print a string to the console
PROC DEBUG_PRINTSTRING(STRING s)
#IF IS_DEBUG_BUILD
IF bDebug_PrintToTTY
CPRINTLN(DEBUG_MISSION, s)
ENDIF
#ENDIF
// Stop release compile error
s = s
ENDPROC
/// PURPOSE: Print a string with a float to the console
PROC DEBUG_PRINTSF(STRING s, FLOAT f)
#IF IS_DEBUG_BUILD
IF bDebug_PrintToTTY
CPRINTLN(DEBUG_MISSION, s, f)
ENDIF
#ENDIF
// Stop release compile error
s = s
f = f
ENDPROC
/// PURPOSE: Print a string with an int to the console
PROC DEBUG_PRINTSI(STRING s, INT i)
#IF IS_DEBUG_BUILD
IF bDebug_PrintToTTY
CPRINTLN(DEBUG_MISSION, s, i)
ENDIF
#ENDIF
// Stop release compile error
s = s
i = i
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
// ===========================================================================================================
// Termination
// ===========================================================================================================
// -----------------------------------------------------------------------------------------------------------
// Script Cleanup
// -----------------------------------------------------------------------------------------------------------
//PURPOSE: general cutscene cleanup
PROC FINISH_CUTSCENE(BOOL bInterp = TRUE, BOOL bResetGamePlayCamera = TRUE)
CLEAR_HELP()
DISPLAY_HUD(TRUE)
DISPLAY_RADAR(TRUE)
SET_WIDESCREEN_BORDERS(FALSE, 500)
RENDER_SCRIPT_CAMS(FALSE, bInterp)
IF DOES_CAM_EXIST(camCutsceneStart)
SET_CAM_ACTIVE(camCutsceneStart, FALSE)
DESTROY_CAM (camCutsceneStart)
ENDIF
IF bResetGamePlayCamera
SET_GAMEPLAY_CAM_RELATIVE_HEADING()
SET_GAMEPLAY_CAM_RELATIVE_PITCH(-5)
ENDIF
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
SET_PLAYER_CONTROL(PLAYER_ID(), TRUE)
ENDIF
// RC_SETUP_SCRIPT_FOR_CUTSCENE(FALSE, <<0,0,0>>, <<0,0,0>>, 0)
ENDPROC
/// PURPOSE: Cleanup peds and resources loaded for the CPR synced scene
PROC CLEANUP_QUAD_SCENE()
SAFE_RELEASE_PED(QUAD_DRIVER)
SAFE_RELEASE_PED(INJURED_PED)
SAFE_RELEASE_PED(cprWatcher1)
SAFE_RELEASE_PED(cprWatcher2)
REMOVE_ANIM_DICT("mini@cpr@char_a@cpr_def")
REMOVE_ANIM_DICT("mini@cpr@char_b@cpr_def")
REMOVE_ANIM_DICT("mini@cpr@char_a@cpr_str")
REMOVE_ANIM_DICT("mini@cpr@char_b@cpr_str")
REMOVE_ANIM_DICT("rcmfanatic1")
SET_PED_PATHS_IN_AREA(<<-1875.16, -630.82, 10.00>>, <<-1867.90, -625.78, 10.25>>, TRUE)
DISABLE_NAVMESH_IN_AREA(<<-1875.16, -630.82, 10.00>>, <<-1867.90, -625.78, 10.25>>, FALSE)
ENDPROC
/// PURPOSE: Turn the road where the driveby fingering occurs back on
PROC TURN_ROADS_ON(BOOL on = TRUE)
IF b_IsTheRoadSwitchedOn <> on
SET_ROADS_IN_ANGLED_AREA(<<-1708.313965,-574.026611,36.873383>>, <<-2044.766357,-370.916718,9.152167>>, 27.250000, FALSE, on)
b_IsTheRoadSwitchedOn = on
ENDIF
ENDPROC
PROC Script_Cleanup()
// Ensure launcher is terminated
RC_CLEANUP_LAUNCHER()
// If the mission was triggered then additional mission cleanup will be required.
IF (Random_Character_Cleanup_If_Triggered())
DEBUG_PRINTSTRING("...Random Character Script was triggered so additional cleanup required")
ENDIF
IF IS_ENTITY_ALIVE(MARY_ANN)
SET_PED_CAN_BE_KNOCKED_OFF_VEHICLE(MARY_ANN, KNOCKOFFVEHICLE_DEFAULT)
ENDIF
REMOVE_RELATIONSHIP_GROUP(relGroupFriendly)
IF IS_AUDIO_SCENE_ACTIVE("FANATIC_MIX_SCENE")
IF DOES_ENTITY_EXIST(MARY_ANN)
REMOVE_ENTITY_FROM_AUDIO_MIX_GROUP(MARY_ANN)
ENDIF
STOP_AUDIO_SCENE("FANATIC_MIX_SCENE")
ENDIF
TRIGGER_MUSIC_EVENT("RC6A_FAIL") // In case this wasn't triggered before
SAFE_RELEASE_VEHICLE(MAS_BIKE)
SAFE_RELEASE_PED(MARY_ANN)
SAFE_REMOVE_BLIP(DESTINATION_BLIP)
SAFE_REMOVE_BLIP(FANATIC_BLIP)
INT j
FOR j = 0 TO 3
SAFE_RELEASE_PED(OtherJoggers[j].thisIndex)
ENDFOR
SAFE_RELEASE_PED(DRIVEBY_FINGER_CAR.Driver)
IF IS_ENTITY_ALIVE(DRIVEBY_FINGER_CAR.Passenger)
SET_PED_COMBAT_ATTRIBUTES(DRIVEBY_FINGER_CAR.Passenger, CA_LEAVE_VEHICLES, TRUE)
SAFE_RELEASE_PED(DRIVEBY_FINGER_CAR.Passenger)
ENDIF
SAFE_RELEASE_VEHICLE(DRIVEBY_FINGER_CAR.thisCarIndex)
SAFE_RELEASE_PED(BEACH_DOG)
REMOVE_WAYPOINT_RECORDING(sFANATIC_ROUTE)
REMOVE_WAYPOINT_RECORDING("Fanatic1RollingStart")
// REMOVE_ANIM_DICT("GESTURES@MALE")
REMOVE_ANIM_DICT("rcmfanatic1out_of_breath")
REMOVE_ANIM_DICT("move_f@runner")
REMOVE_ANIM_DICT("rcmfanatic1")
REMOVE_ANIM_SET("FEMALE_FAST_RUNNER")
SET_MODEL_AS_NO_LONGER_NEEDED(JOGGERMODEL)
SET_MODEL_AS_NO_LONGER_NEEDED(A_M_Y_BEACH_01)
SET_MODEL_AS_NO_LONGER_NEEDED(A_F_Y_BEACH_01)
SET_MODEL_AS_NO_LONGER_NEEDED(BANSHEE)
SET_MODEL_AS_NO_LONGER_NEEDED(MARYSBIKEMODEL)
SET_MODEL_AS_NO_LONGER_NEEDED(A_C_ROTTWEILER)
SET_MODEL_AS_NO_LONGER_NEEDED(BLAZER2)
SET_MODEL_AS_NO_LONGER_NEEDED(S_M_Y_BayWatch_01)
SET_MODEL_AS_NO_LONGER_NEEDED(G_M_Y_SALVAGOON_01)
SET_MODEL_AS_NO_LONGER_NEEDED(A_M_M_TRAMPBEAC_01)
SET_MODEL_AS_NO_LONGER_NEEDED(IG_MARYANN)
CLEANUP_QUAD_SCENE()
TURN_ROADS_ON()
//Re-enable vehicle generators near steps
SET_ALL_VEHICLE_GENERATORS_ACTIVE_IN_AREA(<<-1842.30, -517.70, 26.68>>, <<-1823.52, -515.43, 29.27>>, TRUE)
SET_PED_PATHS_BACK_TO_ORIGINAL(<<-1864.08, -632.07, 10.09>>, <<-1863.31, -631.53, 10.15>>)
SET_PED_PATHS_BACK_TO_ORIGINAL(<<-1820.57, -552.41, 17.40>>, <<-1865.76, -617.48, 10.58>>)
CLEAR_PED_NON_CREATION_AREA()
REMOVE_SCENARIO_BLOCKING_AREA(sbiWallPeds)
REMOVE_SCENARIO_BLOCKING_AREA(sbiPathPeds)
REMOVE_SCENARIO_BLOCKING_AREA(sbiMobilePed)
REMOVE_SCENARIO_BLOCKING_AREAS()
STOP_SOUND(iHeartbeatAudioID)
CLEAR_ADDITIONAL_TEXT(MISSION_TEXT_SLOT, TRUE)
DISABLE_CHEAT(CHEAT_TYPE_FAST_RUN, FALSE)
RC_CleanupSceneEntities(sRCLauncherDataLocal, FALSE)
TERMINATE_THIS_THREAD()
ENDPROC
/// PURPOSE: Snap a given ped the closest Z-coord
PROC SET_PED_ON_THE_GROUND(PED_INDEX ped)
IF IS_PED_UNINJURED(ped)
VECTOR pos = GET_ENTITY_COORDS(ped)
FLOAT zCoord
GET_GROUND_Z_FOR_3D_COORD(pos, zCoord)
SET_ENTITY_COORDS(ped, <<pos.x, pos.y, zCoord>>)
ENDIF
ENDPROC
// -----------------------------------------------------------------------------------------------------------
// Script Pass
// -----------------------------------------------------------------------------------------------------------
PROC Script_Passed()
IF IS_SCRIPTED_CONVERSATION_ONGOING()
DEBUG_PRINTSTRING("Stopping scripted convo at script_passed")
KILL_FACE_TO_FACE_CONVERSATION_DO_NOT_FINISH_LAST_LINE()
ENDIF
IF finishReason <> FINISHED_BY_SHORTCUT
INFORM_STAT_SYSTEM_OF_BOOL_STAT_HAPPENED(FA1_SHORTCUT_USED)
ENDIF
CLEAR_PRINTS()
ADD_CONTACT_TO_PHONEBOOK(CHAR_MARY_ANN, MICHAEL_BOOK, TRUE)
Random_Character_Passed(CP_RAND_C_FAN1)
Script_Cleanup()
ENDPROC
/// PURPOSE: Check whether the player has jumped down the cliff instead of going down the stairs, and start a conversation for this
PROC CHECK_IF_PLAYER_JUMPS_THE_CLIFF()
IF b_PlayerJumpedDownTheCliff = FALSE
IF IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<-1827.530396,-538.121277,21.831240>>, <<-1805.926025,-555.623901,31.773228>>, 2.000000)
IF MADialogueState = MA_WITHIN_TALKING_RANGE
IF IS_SCRIPTED_CONVERSATION_ONGOING()
DEBUG_PRINTSTRING("Stopping scripted convo at check if player jumps off cliff")
KILL_ANY_CONVERSATION()
CLEAR_PRINTS()
ENDIF
IF CREATE_CONVERSATION(MyLocalPedStruct, "FAN1AU", "FAN1_5", CONV_PRIORITY_MEDIUM)
finishReason = FINISHED_BY_SHORTCUT
b_PlayerJumpedDownTheCliff = TRUE
ENDIF
ENDIF
g_savedGlobals.sRandomChars.g_bFanaticCheated = TRUE // Set this even if the conversation doesn't trigger
ENDIF
ENDIF
ENDPROC
/// PURPOSE: Load the resources for the driveby sequence, and return TRUE when finished loading
FUNC BOOL LOAD_DRIVEBY()
REQUEST_MODEL(G_M_Y_SALVAGOON_01)
REQUEST_MODEL(BANSHEE)
IF HAS_MODEL_LOADED(G_M_Y_SALVAGOON_01)
AND HAS_MODEL_LOADED(BANSHEE)
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE: Load the resources for the CPR synced scene, and return TRUE when finished loading
FUNC BOOL LOAD_CPR()
REQUEST_ANIM_DICT("mini@cpr@char_a@cpr_def")
REQUEST_ANIM_DICT("mini@cpr@char_b@cpr_def")
REQUEST_ANIM_DICT("mini@cpr@char_a@cpr_str")
REQUEST_ANIM_DICT("mini@cpr@char_b@cpr_str")
REQUEST_ANIM_DICT("rcmfanatic1")
REQUEST_WAYPOINT_RECORDING("Fanatic1Quad")
REQUEST_MODEL(BLAZER2)
REQUEST_MODEL(A_F_Y_BEACH_01)
REQUEST_MODEL(S_M_Y_BayWatch_01)
REQUEST_MODEL(A_M_M_Beach_01)
IF HAS_ANIM_DICT_LOADED("mini@cpr@char_a@cpr_def")
AND HAS_ANIM_DICT_LOADED("mini@cpr@char_b@cpr_def")
AND HAS_ANIM_DICT_LOADED("mini@cpr@char_a@cpr_str")
AND HAS_ANIM_DICT_LOADED("mini@cpr@char_b@cpr_str")
AND HAS_ANIM_DICT_LOADED("rcmfanatic1")
AND GET_IS_WAYPOINT_RECORDING_LOADED("Fanatic1Quad")
AND HAS_MODEL_LOADED(A_F_Y_BEACH_01)
AND HAS_MODEL_LOADED(S_M_Y_BayWatch_01)
AND HAS_MODEL_LOADED(A_M_M_Beach_01)
AND HAS_MODEL_LOADED(BLAZER2)
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE: Load the resources for the dog on the final stretch, and return TRUE when finished loading
FUNC BOOL LOAD_DOG()
REQUEST_MODEL(A_C_ROTTWEILER)
IF HAS_MODEL_LOADED(A_C_ROTTWEILER)
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE: Load the basic resources needed for the mission, such as Mary Ann's model, animations and route
PROC LOAD_OTHER_ASSETS()
REQUEST_ANIM_DICT("rcmfanatic1")
REQUEST_ANIM_DICT("rcmfanatic1celebrate")
REQUEST_ANIM_DICT("rcmfanatic1yell")
REQUEST_ANIM_DICT("move_f@runner")
REQUEST_ANIM_SET("FEMALE_FAST_RUNNER")
REQUEST_WAYPOINT_RECORDING(sFANATIC_ROUTE)
REQUEST_WAYPOINT_RECORDING("Fanatic1RollingStart")
REQUEST_ADDITIONAL_TEXT("FATIC1", MISSION_TEXT_SLOT)
REQUEST_MODEL(IG_MARYANN)
WHILE NOT HAS_ANIM_DICT_LOADED("rcmfanatic1")
OR NOT HAS_ANIM_DICT_LOADED("rcmfanatic1celebrate")
OR NOT HAS_ANIM_DICT_LOADED("rcmfanatic1yell")
OR NOT HAS_ANIM_DICT_LOADED("move_f@runner")
OR NOT HAS_ANIM_SET_LOADED("FEMALE_FAST_RUNNER")
OR NOT GET_IS_WAYPOINT_RECORDING_LOADED(sFANATIC_ROUTE)
OR NOT GET_IS_WAYPOINT_RECORDING_LOADED("Fanatic1RollingStart")
OR NOT HAS_ADDITIONAL_TEXT_LOADED(MISSION_TEXT_SLOT)
OR NOT HAS_MODEL_LOADED(IG_MARYANN)
DEBUG_PRINTSTRING("Loading other assets")
WAIT(0)
ENDWHILE
ENDPROC
/// PURPOSE: Load the resources and create the joggers on the final stretch if they don't already exist
PROC CREATE_JOGGERS()
IF NOT IS_ENTITY_ALIVE(OtherJoggers[0].thisIndex)
REQUEST_MODEL(JOGGERMODEL)
REQUEST_MODEL(A_M_Y_BEACH_01)
REQUEST_MODEL(A_F_Y_BEACH_01)
IF HAS_MODEL_LOADED(JOGGERMODEL)
AND HAS_MODEL_LOADED(A_M_Y_BEACH_01)
AND HAS_MODEL_LOADED(A_F_Y_BEACH_01)
IF NOT DOES_ENTITY_EXIST(OtherJoggers[0].thisIndex) // 1ST JOGGER
OtherJoggers[0].thisPosition = <<-1951.48, -556.16, 11.71>>
OtherJoggers[0].thisHeading = -121.42
OtherJoggers[0].thisGoToPos1 = <<-1910.10, -591.56, 10.67>>
OtherJoggers[0].thisGoToPos2 = <<-1843.73, -649.16, 9.53>>
OtherJoggers[0].thisModel = JOGGERMODEL
OtherJoggers[0].thisIndex = CREATE_PED(PEDTYPE_CIVFEMALE, OtherJoggers[0].thisModel, OtherJoggers[0].thisPosition, OtherJoggers[0].thisHeading)
SET_PED_COMBAT_MOVEMENT(OtherJoggers[0].thisIndex, CM_WILLRETREAT)
SET_PED_COMBAT_ATTRIBUTES(OtherJoggers[0].thisIndex, CA_ALWAYS_FLEE, TRUE)
SET_PED_ON_THE_GROUND(OtherJoggers[0].thisIndex)
IF IS_PED_UNINJURED(OtherJoggers[0].thisIndex)
OPEN_SEQUENCE_TASK(seq)
TASK_FOLLOW_NAV_MESH_TO_COORD(NULL, OtherJoggers[0].thisGoToPos1, 2.0, DEFAULT_TIME_BEFORE_WARP)
TASK_FOLLOW_NAV_MESH_TO_COORD(NULL, OtherJoggers[0].thisGoToPos2, 2.0, DEFAULT_TIME_BEFORE_WARP)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(OtherJoggers[0].thisIndex, seq)
CLEAR_SEQUENCE_TASK(seq)
ENDIF
ENDIF
IF NOT DOES_ENTITY_EXIST(OtherJoggers[1].thisIndex) // 2ND JOGGER
OtherJoggers[1].thisPosition = <<-1953.85, -555.66, 11>>
OtherJoggers[1].thisHeading = -121.42
OtherJoggers[1].thisGoToPos1 = <<-1911.54, -591.70, 10.61>>
OtherJoggers[1].thisGoToPos2 = <<-1839.87, -651.49, 9.53>>
OtherJoggers[1].thisModel = JOGGERMODEL
OtherJoggers[1].thisIndex = CREATE_PED(PEDTYPE_CIVFEMALE, OtherJoggers[1].thisModel, OtherJoggers[1].thisPosition, OtherJoggers[1].thisHeading)
SET_PED_COMBAT_MOVEMENT(OtherJoggers[1].thisIndex, CM_WILLRETREAT)
SET_PED_COMBAT_ATTRIBUTES(OtherJoggers[1].thisIndex, CA_ALWAYS_FLEE, TRUE)
IF IS_PED_UNINJURED(OtherJoggers[1].thisIndex)
OPEN_SEQUENCE_TASK(seq)
TASK_FOLLOW_NAV_MESH_TO_COORD(NULL, OtherJoggers[1].thisGoToPos1, 2.05, DEFAULT_TIME_BEFORE_WARP)
TASK_FOLLOW_NAV_MESH_TO_COORD(NULL, OtherJoggers[1].thisGoToPos2, 2.05, DEFAULT_TIME_BEFORE_WARP)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(OtherJoggers[1].thisIndex, seq)
CLEAR_SEQUENCE_TASK(seq)
ENDIF
ENDIF
IF NOT DOES_ENTITY_EXIST(OtherJoggers[2].thisIndex) // GIRL WALKER AT END
OtherJoggers[2].thisPosition = <<-1999.40, -508.02, 11>>
OtherJoggers[2].thisHeading = 167.30
OtherJoggers[2].thisGoToPos1 = <<-1997.21, -517.17, 10.73>>
OtherJoggers[2].thisGoToPos2 = <<-1961.31, -547.96, 10.70>>
OtherJoggers[2].thisModel = A_F_Y_BEACH_01
OtherJoggers[2].thisIndex = CREATE_PED(PEDTYPE_CIVFEMALE, OtherJoggers[2].thisModel, OtherJoggers[2].thisPosition, OtherJoggers[2].thisHeading)
SET_PED_COMBAT_MOVEMENT(OtherJoggers[2].thisIndex, CM_WILLRETREAT)
SET_PED_COMBAT_ATTRIBUTES(OtherJoggers[2].thisIndex, CA_ALWAYS_FLEE, TRUE)
SET_PED_ON_THE_GROUND(OtherJoggers[2].thisIndex)
ELSE
IF IS_PED_UNINJURED(OtherJoggers[2].thisIndex)
CLEAR_PED_TASKS_IMMEDIATELY(OtherJoggers[2].thisIndex)
SET_ENTITY_COORDS(OtherJoggers[2].thisIndex, OtherJoggers[2].thisPosition)
SET_ENTITY_HEADING(OtherJoggers[2].thisIndex, OtherJoggers[2].thisHeading)
SET_PED_ON_THE_GROUND(OtherJoggers[2].thisIndex)
ENDIF
ENDIF
IF NOT DOES_ENTITY_EXIST(OtherJoggers[3].thisIndex) // GUY WALKER AT END
OtherJoggers[3].thisPosition = <<-2000.19, -507.37, 11>>
OtherJoggers[3].thisHeading = 83.65
OtherJoggers[3].thisGoToPos1 = <<-1998.27, -517.46, 10.67>>
OtherJoggers[3].thisGoToPos2 = <<-1962.75, -549.56, 10.62>>
OtherJoggers[3].thisModel = A_M_Y_BEACH_01
OtherJoggers[3].thisIndex = CREATE_PED(PEDTYPE_CIVMALE, OtherJoggers[3].thisModel, OtherJoggers[3].thisPosition, OtherJoggers[3].thisHeading)
SET_PED_COMBAT_MOVEMENT(OtherJoggers[3].thisIndex, CM_WILLRETREAT)
SET_PED_COMBAT_ATTRIBUTES(OtherJoggers[3].thisIndex, CA_ALWAYS_FLEE, TRUE)
SET_PED_ON_THE_GROUND(OtherJoggers[3].thisIndex)
ELSE
IF IS_PED_UNINJURED(OtherJoggers[3].thisIndex)
CLEAR_PED_TASKS_IMMEDIATELY(OtherJoggers[3].thisIndex)
SET_ENTITY_COORDS(OtherJoggers[3].thisIndex, OtherJoggers[3].thisPosition)
SET_ENTITY_HEADING(OtherJoggers[3].thisIndex, OtherJoggers[3].thisHeading)
SET_PED_ON_THE_GROUND(OtherJoggers[3].thisIndex)
ENDIF
ENDIF
SET_MODEL_AS_NO_LONGER_NEEDED(A_F_Y_BEACH_01)
SET_MODEL_AS_NO_LONGER_NEEDED(A_M_Y_BEACH_01)
SET_MODEL_AS_NO_LONGER_NEEDED(JOGGERMODEL)
ENDIF
ENDIF
ENDPROC
/// PURPOSE: Create Mary Ann's bike at the end of the mission
PROC CREATE_MARY_ANNS_BIKE()
IF NOT IS_VEHICLE_OK(MAS_BIKE)
REQUEST_MODEL(MARYSBIKEMODEL)
IF HAS_MODEL_LOADED(MARYSBIKEMODEL)
MAS_BIKE = CREATE_VEHICLE(MARYSBIKEMODEL, MAS_BIKE_POS, MAS_BIKE_DIR)
SET_MODEL_AS_NO_LONGER_NEEDED(MARYSBIKEMODEL)
ENDIF
ENDIF
ENDPROC
/// PURPOSE: Load and create the resources for the driveby sequence
PROC CREATE_CARS()
REQUEST_MODEL(G_M_Y_SALVAGOON_01)
REQUEST_MODEL(BANSHEE)
REQUEST_MODEL(REGINA)
WHILE NOT HAS_MODEL_LOADED(G_M_Y_SALVAGOON_01)
OR NOT HAS_MODEL_LOADED(BANSHEE)
OR NOT HAS_MODEL_LOADED(REGINA)
WAIT(0)
ENDWHILE
CLEAR_AREA_OF_VEHICLES(<<1829.384277, -516.190002, 27.857389>>, 7.0) // Try and delete any vehicle parked where checkpoint 4 is
IF NOT IS_VEHICLE_OK(DRIVEBY_FINGER_CAR.thisCarIndex) // PARKED HONKING CAR
DRIVEBY_FINGER_CAR.thisPosition = <<-1833.329956,-513.388306,28.210709>>
DRIVEBY_FINGER_CAR.thisHeading = 286.3430
DRIVEBY_FINGER_CAR.thisGoToPos = <<-1721.02, -559.70, 37.46>>
DRIVEBY_FINGER_CAR.thisSpeed = 18
DRIVEBY_FINGER_CAR.thisCarModel = BANSHEE
DRIVEBY_FINGER_CAR.thisCarIndex = CREATE_VEHICLE(DRIVEBY_FINGER_CAR.thisCarModel, DRIVEBY_FINGER_CAR.thisPosition, DRIVEBY_FINGER_CAR.thisHeading)
SET_VEHICLE_COLOURS(DRIVEBY_FINGER_CAR.thisCarIndex, 1, 1)
DRIVEBY_FINGER_CAR.Driver = CREATE_PED_INSIDE_VEHICLE(DRIVEBY_FINGER_CAR.thisCarIndex, PEDTYPE_CIVMALE, G_M_Y_SALVAGOON_01)
DRIVEBY_FINGER_CAR.Passenger = CREATE_PED_INSIDE_VEHICLE(DRIVEBY_FINGER_CAR.thisCarIndex, PEDTYPE_CIVMALE, G_M_Y_SALVAGOON_01, VS_FRONT_RIGHT)
SET_PED_COMBAT_ATTRIBUTES(DRIVEBY_FINGER_CAR.Passenger, CA_LEAVE_VEHICLES, FALSE)
SET_PED_COMBAT_ATTRIBUTES(DRIVEBY_FINGER_CAR.Passenger, CA_CAN_TAUNT_IN_VEHICLE, TRUE)
SET_PED_COMBAT_ATTRIBUTES(DRIVEBY_FINGER_CAR.Driver, CA_ALWAYS_FLEE, TRUE)
/*
ELSE
IF IS_PED_UNINJURED(DRIVEBY_FINGER_CAR.Driver)
IF IS_VEHICLE_OK(DRIVEBY_FINGER_CAR.thisCarIndex)
CLEAR_PED_TASKS_IMMEDIATELY(DRIVEBY_FINGER_CAR.Driver)
SET_ENTITY_COORDS(DRIVEBY_FINGER_CAR.thisCarIndex, DRIVEBY_FINGER_CAR.thisPosition)
SET_ENTITY_HEADING(DRIVEBY_FINGER_CAR.thisCarIndex, DRIVEBY_FINGER_CAR.thisHeading)
IF NOT IS_PED_IN_VEHICLE(DRIVEBY_FINGER_CAR.Driver, DRIVEBY_FINGER_CAR.thisCarIndex)
TASK_WARP_PED_INTO_VEHICLE(DRIVEBY_FINGER_CAR.Driver, DRIVEBY_FINGER_CAR.thisCarIndex)
ENDIF
ENDIF
ELSE
DRIVEBY_FINGER_CAR.Driver = CREATE_PED_INSIDE_VEHICLE(DRIVEBY_FINGER_CAR.thisCarIndex, PEDTYPE_CIVMALE, G_M_Y_SALVAGOON_01)
ENDIF
*/
ENDIF
IF NOT IS_VEHICLE_OK(FOLLOWING_CAR.thisCarIndex) // PARKED HONKING CAR
FOLLOWING_CAR.thisPosition = <<-2000.79, -494.35, 11.09>>
FOLLOWING_CAR.thisHeading = 321.61
FOLLOWING_CAR.thisGoToPos = <<-1719.08, -559.41, 36.33>>
FOLLOWING_CAR.thisSpeed = 12
FOLLOWING_CAR.thisCarModel = REGINA
FOLLOWING_CAR.thisCarIndex = CREATE_VEHICLE(FOLLOWING_CAR.thisCarModel, FOLLOWING_CAR.thisPosition, FOLLOWING_CAR.thisHeading)
FOLLOWING_CAR.Driver = CREATE_PED_INSIDE_VEHICLE(FOLLOWING_CAR.thisCarIndex, PEDTYPE_CIVMALE, G_M_Y_SALVAGOON_01)
FOLLOWING_CAR.Passenger = CREATE_PED_INSIDE_VEHICLE(FOLLOWING_CAR.thisCarIndex, PEDTYPE_CIVMALE, G_M_Y_SALVAGOON_01, VS_FRONT_RIGHT)
SET_PED_COMBAT_ATTRIBUTES(FOLLOWING_CAR.Driver, CA_ALWAYS_FLEE, TRUE)
SET_PED_COMBAT_ATTRIBUTES(FOLLOWING_CAR.Passenger, CA_ALWAYS_FLEE, TRUE)
ENDIF
SET_MODEL_AS_NO_LONGER_NEEDED(G_M_Y_SALVAGOON_01)
SET_MODEL_AS_NO_LONGER_NEEDED(BANSHEE)
SET_MODEL_AS_NO_LONGER_NEEDED(REGINA)
ENDPROC
/// PURPOSE: Create the dog on the final stretch
PROC CREATE_DOGS()
IF NOT IS_ENTITY_ALIVE(BEACH_DOG)
BEACH_DOG = CREATE_PED(PEDTYPE_MISSION, A_C_ROTTWEILER, vPos_DOG, fDir_DOG)
SET_PED_CAN_RAGDOLL(BEACH_DOG, TRUE)
ENDIF
ENDPROC
/// PURPOSE: Create the peds and vehicles for the CPR synced scene, and return TRUE when finished loading
PROC CREATE_QUAD_BIKE_SCENE(BOOL fromStart = TRUE)
IF NOT IS_VEHICLE_OK(CHEAT_QUAD)
SET_PED_PATHS_IN_AREA(<<-1875.16, -630.82, 10.00>>, <<-1867.90, -625.78, 10.25>>, FALSE)
DISABLE_NAVMESH_IN_AREA(<<-1875.16, -630.82, 10.00>>, <<-1867.90, -625.78, 10.25>>, TRUE)
IF NavBlockerID > -1
REMOVE_NAVMESH_BLOCKING_OBJECT(NavBlockerID)
NavBlockerID = -1
ENDIF
NavBlockerID = ADD_NAVMESH_BLOCKING_OBJECT(<<-1870.54, -628.10, 10.09>>, <<4, 4, 4>>, 0)
IF NavBlockerID = -1
SCRIPT_ASSERT("Failed to add a navmesh blocking object to CPR scene! You may see peds walking through it. Please send a message to Ian Gander @ Leeds about this...")
ENDIF
INJURED_PED = CREATE_PED(PEDTYPE_CIVMALE, A_M_M_Beach_01, <<-1870.54, -628.10, 10.09>>, 80)
SET_ENTITY_LOAD_COLLISION_FLAG(INJURED_PED, TRUE)
CLEAR_PED_TASKS_IMMEDIATELY(INJURED_PED)
SET_PED_MONEY(INJURED_PED, 0)
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(INJURED_PED, TRUE)
SET_PED_CAN_BE_TARGETTED(INJURED_PED, FALSE)
vPos_CPRScene = GET_ENTITY_COORDS(INJURED_PED)
GET_GROUND_Z_FOR_3D_COORD(GET_ENTITY_COORDS(INJURED_PED), vPos_CPRScene.z)
vRot_CPRScene = GET_ENTITY_ROTATION(INJURED_PED)
IdleSynchSceneID = CREATE_SYNCHRONIZED_SCENE(vPos_CPRScene, vRot_CPRScene)
TASK_SYNCHRONIZED_SCENE (INJURED_PED, IdleSynchSceneID, "mini@cpr@char_b@cpr_def", "cpr_intro", NORMAL_BLEND_IN, NORMAL_BLEND_OUT, SYNCED_SCENE_NONE, RBF_PLAYER_IMPACT)
SET_SYNCHRONIZED_SCENE_RATE(IdleSynchSceneID, 0.0)
cprWatcher1 = CREATE_PED(PEDTYPE_CIVFEMALE, A_F_Y_BEACH_01, <<-1869.76, -627.70, 10.10>>)
SET_PED_COMBAT_ATTRIBUTES(cprWatcher1, CA_ALWAYS_FLEE, TRUE)
OPEN_SEQUENCE_TASK(seq)
TASK_TURN_PED_TO_FACE_ENTITY(NULL, INJURED_PED)
TASK_PLAY_ANIM(null, "rcmfanatic1", "idle_a", SLOW_BLEND_IN, SLOW_BLEND_OUT)
TASK_PLAY_ANIM(null, "rcmfanatic1", "base", NORMAL_BLEND_IN, SLOW_BLEND_OUT)
TASK_PLAY_ANIM(null, "rcmfanatic1", "base", NORMAL_BLEND_IN, SLOW_BLEND_OUT)
TASK_PLAY_ANIM(null, "rcmfanatic1", "idle_C", NORMAL_BLEND_IN, SLOW_BLEND_OUT)
TASK_PLAY_ANIM(null, "rcmfanatic1", "base", NORMAL_BLEND_IN, SLOW_BLEND_OUT)
TASK_PLAY_ANIM(null, "rcmfanatic1", "idle_b", NORMAL_BLEND_IN, SLOW_BLEND_OUT)
TASK_PLAY_ANIM(null, "rcmfanatic1", "base", NORMAL_BLEND_IN, SLOW_BLEND_OUT)
TASK_PLAY_ANIM(null, "rcmfanatic1", "base", NORMAL_BLEND_IN, SLOW_BLEND_OUT)
TASK_PLAY_ANIM(null, "rcmfanatic1", "base", NORMAL_BLEND_IN, SLOW_BLEND_OUT)
TASK_PLAY_ANIM(null, "rcmfanatic1", "idle_b", NORMAL_BLEND_IN, SLOW_BLEND_OUT)
SET_SEQUENCE_TO_REPEAT(seq, REPEAT_FOREVER)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(cprWatcher1, seq)
CLEAR_SEQUENCE_TASK(seq)
cprWatcher2 = CREATE_PED(PEDTYPE_CIVFEMALE, A_F_Y_BEACH_01, <<-1873.61, -628.88, 11.16>>)
SET_PED_COMBAT_ATTRIBUTES(cprWatcher2, CA_ALWAYS_FLEE, TRUE)
OPEN_SEQUENCE_TASK(seq)
TASK_TURN_PED_TO_FACE_ENTITY(NULL, INJURED_PED)
TASK_PLAY_ANIM(null, "rcmfanatic1", "base", SLOW_BLEND_IN, SLOW_BLEND_OUT)
TASK_PLAY_ANIM(null, "rcmfanatic1", "idle_b", NORMAL_BLEND_IN, SLOW_BLEND_OUT)
TASK_PLAY_ANIM(null, "rcmfanatic1", "idle_a", NORMAL_BLEND_IN, SLOW_BLEND_OUT)
TASK_PLAY_ANIM(null, "rcmfanatic1", "base", NORMAL_BLEND_IN, SLOW_BLEND_OUT)
TASK_PLAY_ANIM(null, "rcmfanatic1", "base", NORMAL_BLEND_IN, SLOW_BLEND_OUT)
TASK_PLAY_ANIM(null, "rcmfanatic1", "idle_a", NORMAL_BLEND_IN, SLOW_BLEND_OUT)
TASK_PLAY_ANIM(null, "rcmfanatic1", "idle_b", NORMAL_BLEND_IN, SLOW_BLEND_OUT)
TASK_PLAY_ANIM(null, "rcmfanatic1", "base", NORMAL_BLEND_IN, SLOW_BLEND_OUT)
TASK_PLAY_ANIM(null, "rcmfanatic1", "base", NORMAL_BLEND_IN, SLOW_BLEND_OUT)
SET_SEQUENCE_TO_REPEAT(seq, REPEAT_FOREVER)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(cprWatcher2, seq)
CLEAR_SEQUENCE_TASK(seq)
if fromStart
CHEAT_QUAD = CREATE_VEHICLE(BLAZER2, vPos_CHEAT_QUAD, 36.64)
SET_VEHICLE_ON_GROUND_PROPERLY(CHEAT_QUAD)
SET_ENTITY_LOAD_COLLISION_FLAG(CHEAT_QUAD, TRUE)
QUAD_DRIVER = CREATE_PED_INSIDE_VEHICLE(CHEAT_QUAD, PEDTYPE_MEDIC, S_M_Y_BAYWATCH_01)
cprState = CPR_WAITING
ELSE
CHEAT_QUAD = CREATE_VEHICLE(BLAZER2, <<-1871.55, -640.01, 10.65>>, 297.76)
SET_VEHICLE_ON_GROUND_PROPERLY(CHEAT_QUAD)
SET_ENTITY_LOAD_COLLISION_FLAG(CHEAT_QUAD, TRUE)
QUAD_DRIVER = CREATE_PED_INSIDE_VEHICLE(CHEAT_QUAD, PEDTYPE_CIVMALE, S_M_Y_BAYWATCH_01)
OPEN_SEQUENCE_TASK(seq)
TASK_LOOK_AT_ENTITY(NULL, INJURED_PED, -1)
TASK_LEAVE_VEHICLE(NULL, CHEAT_QUAD)
TASK_FOLLOW_NAV_MESH_TO_COORD(NULL, GET_ENTITY_COORDS(INJURED_PED), 1.8)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(QUAD_DRIVER, seq)
CLEAR_SEQUENCE_TASK(seq)
cprState = CPR_GOING_TO_SCENE
ENDIF
SET_PED_COMBAT_ATTRIBUTES(QUAD_DRIVER, CA_ALWAYS_FLEE, TRUE)
SET_ENTITY_LOAD_COLLISION_FLAG(QUAD_DRIVER, TRUE)
SET_PED_KEEP_TASK(INJURED_PED, TRUE)
ENDIF
SET_MODEL_AS_NO_LONGER_NEEDED(BLAZER2)
SET_MODEL_AS_NO_LONGER_NEEDED(A_F_Y_BEACH_01)
SET_MODEL_AS_NO_LONGER_NEEDED(S_M_Y_BayWatch_01)
SET_MODEL_AS_NO_LONGER_NEEDED(A_M_M_Beach_01)
ENDPROC
/// PURPOSE: Works out which checkpoint type is needed based upon angle between checkpoints
FUNC CHECKPOINT_TYPE GET_RACE_CHECKPOINT_TYPE(INT iCheckNum)
VECTOR pos, pos2, pos3
VECTOR vec1, vec2
FLOAT fReturnAngle
FLOAT fChevron1 = 180.0
FLOAT fChevron2 = 140.0
FLOAT fChevron3 = 80.0
pos = RACE_POSITIONS[iCheckNum]
// If we're checking the last checkpoint of the current array, just return the appropriate flag checkpoint, we don't care about angles
IF (iCheckNum = iMaxRacePositions-1)
RETURN CHECKPOINT_RACE_GROUND_FLAG
ELSE
// Otherwise, we need to do the angle shit
// If this is the first checkpoint, we need to check a position behind it
IF iCheckNum = 0
pos3 = <<-1869.12, -445.17, 45.17>>
pos2 = RACE_POSITIONS[iCheckNum + 1]
ELSE
// The checkpoint is neither first nor last, wooo, straightforward
pos3 = RACE_POSITIONS[iCheckNum - 1]
pos2 = RACE_POSITIONS[iCheckNum + 1]
ENDIF
ENDIF
// Create some vectors via maths magic
vec1 = pos3 - pos
vec2 = pos2 - pos
// Get the final angle value via code magic
fReturnAngle = GET_ANGLE_BETWEEN_2D_VECTORS(vec1.x, vec1.y, vec2.x, vec2.y)
// Make sure reflex angles don't break things via more maths magic
IF fReturnAngle > 180
fReturnAngle = (360.0 - fReturnAngle)
ENDIF
// We have our angles through MAGIC!!!!, now to return the correct checkpoint type
IF fReturnAngle < fChevron3
RETURN CHECKPOINT_RACE_GROUND_CHEVRON_3
ELIF fReturnAngle < fChevron2
RETURN CHECKPOINT_RACE_GROUND_CHEVRON_2
ELIF fReturnAngle < fChevron1
RETURN CHECKPOINT_RACE_GROUND_CHEVRON_1
ELSE
RETURN CHECKPOINT_RACE_GROUND_CHEVRON_1
ENDIF
// If we've got here, return this as a default, even though we REALLY REALLY SHOULDN'T and this would concern me greatly
RETURN CHECKPOINT_RACE_GROUND_CHEVRON_1
ENDFUNC
/// PURPOSE: Gets appropriate checkpoint colour based on chevron type
FUNC HUD_COLOURS GET_RACE_CHECKPOINT_COLOUR(CHECKPOINT_TYPE cpType)
// IF cpType = CHECKPOINT_RACE_GROUND_CHEVRON_3
// RETURN HUD_COLOUR_YELLOWDARK
//
// ELIF cpType = CHECKPOINT_RACE_GROUND_CHEVRON_2
// OR cpType = CHECKPOINT_RACE_GROUND_FLAG
// RETURN HUD_COLOUR_YELLOWLIGHT
// ELSE
// RETURN HUD_COLOUR_YELLOWLIGHT
// ENDIF
// Returning YELLOWDARK for all checkpoints (B*1454575)
cpType = cpType // Compile fix
RETURN HUD_COLOUR_YELLOWLIGHT
ENDFUNC
/// PURPOSE: Work out and update the coord of the waypoint the player is closest to on Mary Ann's route,
/// and update which number waypoint the player and Mary Ann is closest to
PROC DETERMINE_CLOSEST_WAYPOINTS()
IF GET_IS_WAYPOINT_RECORDING_LOADED(sFANATIC_ROUTE)
WAYPOINT_RECORDING_GET_CLOSEST_WAYPOINT(sFANATIC_ROUTE, GET_ENTITY_COORDS(PLAYER_PED_ID()), iNum_PlayerClosestWaypoint)
WAYPOINT_RECORDING_GET_CLOSEST_WAYPOINT(sFANATIC_ROUTE, GET_ENTITY_COORDS(MARY_ANN), iNum_NPCClosestWaypoint)
IF iCURRENT_RACE_POS < iMaxRacePositions
WAYPOINT_RECORDING_GET_COORD(sFANATIC_ROUTE, iNum_PlayerClosestWaypoint, vPos_PlayerClosestWaypoint)
ENDIF
ENDIF
ENDPROC
/// PURPOSE: Work out the coord of the NEXT waypoint on Mary Ann's route to the one Mary Ann is currently closest to
FUNC VECTOR GET_COORD_FURTHER_ALONG_ROUTE()
DETERMINE_CLOSEST_WAYPOINTS()
VECTOR vPos
IF iNum_NPCClosestWaypoint < iNum_WAYPOINTS - 1
WAYPOINT_RECORDING_GET_COORD(sFANATIC_ROUTE, iNum_NPCClosestWaypoint + 1, vPos)
ELSE
WAYPOINT_RECORDING_GET_COORD(sFANATIC_ROUTE, iNum_WAYPOINTS - 1, vPos)
ENDIF
RETURN vPos
ENDFUNC
/// PURPOSE: Return the number of Mary Ann's NEXT waypoint
FUNC INT GET_MARY_ANNS_NEXT_WAYPOINT()
INT i
WAYPOINT_RECORDING_GET_CLOSEST_WAYPOINT(sFANATIC_ROUTE, GET_COORD_FURTHER_ALONG_ROUTE(), i)
RETURN i
ENDFUNC
/// PURPOSE:
/// Debug function to keep Mary Ann running after skipping
/// PARAMS:
/// nextMS - sets the mission stage that we are skipping to
PROC KEEP_RUNNING(MISSION_STAGE nextMS, BOOL bSkipping = TRUE)
IF IS_PED_UNINJURED(MARY_ANN)
IF NOT IS_STRING_NULL(sFANATIC_ROUTE)
IF GET_IS_WAYPOINT_RECORDING_LOADED(sFANATIC_ROUTE)
OPEN_SEQUENCE_TASK(seq)
TASK_SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(NULL, TRUE)
TASK_FOLLOW_WAYPOINT_RECORDING(NULL, sFANATIC_ROUTE, GET_MARY_ANNS_NEXT_WAYPOINT(), EWAYPOINT_START_FROM_CLOSEST_POINT | EWAYPOINT_VEHICLES_USE_AI_SLOWDOWN | EWAYPOINT_ALLOW_STEERING_AROUND_PEDS | EWAYPOINT_NAVMESH_BACK_TO_WAYPOINT_IF_LEFT_ROUTE , -1)
TASK_LOOK_AT_ENTITY(NULL, PLAYER_PED_ID(), -1)
TASK_PLAY_ANIM(null, "move_f@runner", "idle", SLOW_BLEND_IN, SLOW_BLEND_OUT, -1, AF_LOOPING)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(MARY_ANN, seq)
CLEAR_SEQUENCE_TASK(seq)
ENDIF
ENDIF
DEBUG_PRINTSTRING("Keep Running used")
SET_PED_CAN_RAGDOLL_FROM_PLAYER_IMPACT(MARY_ANN, FALSE)
IF bSkipping = TRUE
stageStage = SS_SETUP
missionStage = nextMS
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Makes Mary Ann say a single line, possibly interrupt conversation
/// PARAMS:
/// blockOfText - blockOfText
/// rootLabel - rootLabel
/// bShouldInterrupt - if true will stop the conversation to play line
FUNC BOOL CAN_MARY_ANN_SAY_SINGLE_LINE(STRING blockOfText, STRING rootLabel, BOOL bShouldInterrupt, INT& interruptedLine)
IF MADialogueState = MA_WITHIN_TALKING_RANGE
AND NOT IS_MESSAGE_BEING_DISPLAYED()
if bShouldInterrupt
IF IS_SCRIPTED_CONVERSATION_ONGOING()
interruptedLine = GET_CURRENT_SCRIPTED_CONVERSATION_LINE()
DEBUG_PRINTSTRING("Stopping scripted convo at can Mary Ann say single line")
KILL_FACE_TO_FACE_CONVERSATION_DO_NOT_FINISH_LAST_LINE()
CLEAR_PRINTS()
ENDIF
IF PLAY_SINGLE_LINE_FROM_CONVERSATION(MyLocalPedStruct, "FAN1AU", blockOfText, rootLabel, CONV_PRIORITY_MEDIUM)
RETURN TRUE
ENDIF
ELSE
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF PLAY_SINGLE_LINE_FROM_CONVERSATION(MyLocalPedStruct, "FAN1AU", blockOfText, rootLabel, CONV_PRIORITY_MEDIUM)
RETURN TRUE
ENDIF
ENDIF
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// Tries to create a conversation with the given root label and returns true if it triggers - for random lines during the mission
/// PARAMS:
/// rootLabel - the label we're trying to play
/// RETURNS:
/// TRUE if the conversation plays, FALSE if it fails or can't be played
FUNC BOOL CAN_MARY_ANN_SAY_RANDOM_LINE(STRING rootLabel)
IF MADialogueState = MA_WITHIN_TALKING_RANGE
AND NOT IS_MESSAGE_BEING_DISPLAYED()
IF CREATE_CONVERSATION(MyLocalPedStruct, "FAN1AU", rootLabel, CONV_PRIORITY_MEDIUM)
RETURN TRUE
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE: Checks if she can start her standard run conversation, not random comment
FUNC BOOL CAN_CREATE_RUNNING_CONVERSATION()
IF MADialogueState = MA_WITHIN_TALKING_RANGE
AND NOT IS_MESSAGE_BEING_DISPLAYED()
AND NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
RETURN TRUE
ELSE
RETURN FALSE
ENDIF
ENDFUNC
/// PURPOSE:
/// Play a one-liner for Mary Ann
PROC PLAY_MARY_ANN_ONE_LINER()
IF place = 2 // only do a Mary Ann one-liner if the player is behind
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
AND MADialogueState = MA_WITHIN_TALKING_RANGE
AND NOT IS_MESSAGE_BEING_DISPLAYED()
IF CREATE_CONVERSATION(MyLocalPedStruct, "FAN1AU", "FAN1_TAUNT", CONV_PRIORITY_MEDIUM)
iOneLinerSeq++
iOneLinerTimer = GET_GAME_TIMER()
ENDIF
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Play a one-liner for Michael
PROC PLAY_MICHAEL_ONE_LINER()
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
AND MADialogueState = MA_WITHIN_TALKING_RANGE
AND NOT IS_MESSAGE_BEING_DISPLAYED()
IF CREATE_CONVERSATION(MyLocalPedStruct, "FAN1AU", "FAN1_ONELIN", CONV_PRIORITY_MEDIUM)
iOneLinerSeq++
iOneLinerTimer = GET_GAME_TIMER()
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Try and play a one-liner for one of the characters
PROC TRY_ONE_LINER()
IF (GET_GAME_TIMER() - iOneLinerTimer) > 10000 // Possibly randomise this value a bit?
SWITCH iOneLinerSeq
CASE 0
PLAY_MARY_ANN_ONE_LINER()
BREAK
CASE 1
PLAY_MICHAEL_ONE_LINER()
BREAK
CASE 2
PLAY_MARY_ANN_ONE_LINER()
BREAK
CASE 3
PLAY_MICHAEL_ONE_LINER()
BREAK
CASE 4
PLAY_MARY_ANN_ONE_LINER()
BREAK
CASE 5
PLAY_MICHAEL_ONE_LINER()
BREAK
CASE 6
PLAY_MARY_ANN_ONE_LINER()
BREAK
CASE 7
PLAY_MICHAEL_ONE_LINER()
BREAK
CASE 8
PLAY_MARY_ANN_ONE_LINER()
BREAK
CASE 9
PLAY_MICHAEL_ONE_LINER()
BREAK
DEFAULT
// No more lines available to play
BREAK
ENDSWITCH
ENDIF
ENDPROC
/// PURPOSE:
/// Keeps trying to play the keep up or catch up lines while we're waiting for any prior conversation to finish
PROC TRY_KEEPUP_OR_CATCHUP_LINES()
IF MADialogueState = MA_SHOUTING_TO_KEEP_UP
IF iHurryUpLineNumber < iMAXHurryUpLineNumber
IF (cheatedRanAcrossGrass.hasBeenPlayed
OR cheatedLeaptFence.hasBeenPlayed)
AND missionStage = MS_START_RUNNING
MADialogueState = MA_OUT_OF_TALKING_RANGE
DEBUG_PRINTSTRING("MA Dialogue: Now in MA_OUT_OF_TALKING_RANGE")
ELSE
IF place = 2 // Only say this if the player is behind
IF PLAY_SINGLE_LINE_FROM_CONVERSATION(MyLocalPedStruct, "FAN1AU", "FAN1_FALLB", HURRY_UP_LINE[iHurryUpLineNumber], CONV_PRIORITY_HIGH)
iHurryUpLineNumber++
MADialogueState = MA_OUT_OF_TALKING_RANGE
DEBUG_PRINTSTRING("MA Dialogue: Played keep up line, now in MA_OUT_OF_TALKING_RANGE")
ENDIF
ELSE
MADialogueState = MA_OUT_OF_TALKING_RANGE
DEBUG_PRINTSTRING("MA Dialogue: Player in 1st place so no need for keep up line, now in MA_OUT_OF_TALKING_RANGE")
ENDIF
ENDIF
ELSE
DEBUG_PRINTSTRING("MA Dialogue: Said all keep up lines, now in MA_OUT_OF_TALKING_RANGE")
MADialogueState = MA_OUT_OF_TALKING_RANGE
ENDIF
ELIF MADialogueState = MA_SAYING_YOU_CAUGHT_UP
IF iCatchUpLineNumber < iMAXCatchUpLineNumber
IF (cheatedRanAcrossGrass.hasBeenPlayed
OR cheatedLeaptFence.hasBeenPlayed)
AND missionStage = MS_START_RUNNING
IF bCatchupCheatLineSaid = FALSE
IF CREATE_CONVERSATION(MyLocalPedStruct, "FAN1AU", "FAN1_CATCHC", CONV_PRIORITY_HIGH)
bCatchupCheatLineSaid = TRUE
b_CheatedLine = FALSE // Stop the other cheated line from playing if we've done this instead
ENDIF
ENDIF
MADialogueState = MA_WITHIN_TALKING_RANGE
DEBUG_PRINTSTRING("MA Dialogue: Now in MA_WITHIN_TALKING_RANGE")
ELSE
IF place = 2 // Only say this if the player is behind
IF CAN_MARY_ANN_SAY_RANDOM_LINE("FAN1_CATCHU")
iCatchUpLineNumber++
MADialogueState = MA_WITHIN_TALKING_RANGE
DEBUG_PRINTSTRING("MA Dialogue: Played catchup line, now in MA_WITHIN_TALKING_RANGE")
ENDIF
ELSE
MADialogueState = MA_WITHIN_TALKING_RANGE
DEBUG_PRINTSTRING("MA Dialogue: Player in 1st place so no need for catchup line, now in MA_WITHIN_TALKING_RANGE")
ENDIF
ENDIF
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// This function switches her Dialogue State and plays a "Catch up" line if player gets too far, or "Welcome back" line if they catch up.
/// The dialogue state is used to make sure she is nearby before talking
PROC SET_MARY_ANN_DIALOGUE_STATE(MARY_ANN_DIALOGUE_STATE newState)
IF MADialogueState <> newState
SWITCH MADialogueState
CASE MA_WITHIN_TALKING_RANGE
IF newstate = MA_OUT_OF_TALKING_RANGE
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
KILL_ANY_CONVERSATION()
ENDIF
DEBUG_PRINTSTRING("MA Dialogue: Kill convo, switch to MA_OUT_OF_TALKING_RANGE, trying keep up line if possible")
MADialogueState = MA_SHOUTING_TO_KEEP_UP
ENDIF
BREAK
CASE MA_OUT_OF_TALKING_RANGE
IF newstate = MA_WITHIN_TALKING_RANGE
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
KILL_ANY_CONVERSATION()
ENDIF
DEBUG_PRINTSTRING("MA Dialogue: Kill convo, switch to MA_WITHIN_TALKING_RANGE, trying you caught up line if possible")
MADialogueState = MA_SAYING_YOU_CAUGHT_UP
ENDIF
BREAK
// Shouting to keep up and Saying you caught up now handled in TRY_KEEPUP_OR_CATCHUP_LINES()
ENDSWITCH
ENDIF
ENDPROC
PROC TELEPORT_STUCK_MARY_ANN(int iTeleportTo)
VECTOR vTeleCoord
FLOAT fNewHeading
WAYPOINT_RECORDING_GET_COORD(sFANATIC_ROUTE, iTeleportTo, vTeleCoord)
VECTOR vNextCoord
WAYPOINT_RECORDING_GET_COORD(sFANATIC_ROUTE, iTeleportTo+1, vNextCoord)
fNewHeading = GET_HEADING_FROM_COORDS(vTeleCoord, vNextCoord)
SAFE_TELEPORT_ENTITY(MARY_ANN, vTeleCoord, fNewHeading, TRUE)
IF iTeleportTo < 6
iNPC_RACE_POS = 1
ELIF iTeleportTo < 30
iNPC_RACE_POS = 1
ELIF iTeleportTo < 36
iNPC_RACE_POS = 2
ELIF iTeleportTo < 48
iNPC_RACE_POS = 3
ELIF iTeleportTo < 62
iNPC_RACE_POS = 4
ELIF iTeleportTo < 81
iNPC_RACE_POS = 5
ELIF iTeleportTo < 95
iNPC_RACE_POS = 6
ELIF iTeleportTo < 106
iNPC_RACE_POS = 7
ELSE
iNPC_RACE_POS = 8
ENDIF
ENDPROC
PROC CHECK_FOR_GETTING_STUCK()
switch StuckStage
CASE STUCK_UPDATE
// Change the waypoint we're checking to Mary Ann's the nearest one
iWaypointStuckCheck = iNum_NPCClosestWaypoint
iStuckTimer = GET_GAME_TIMER()
StuckStage = STUCK_LOOP
BREAK
CASE STUCK_LOOP
IF iWaypointStuckCheck = iNum_NPCClosestWaypoint
IF (GET_GAME_TIMER() - iStuckTimer) > 20000 // If Mary Ann's closest waypoint doesn't change for 20 secs, something needs fixing
DEBUG_PRINTSTRING("Mary Ann got stuck!")
StuckStage = STUCK_FIX
ENDIF
ELSE
StuckStage = STUCK_UPDATE // If the closest waypoint doesn't match anymore, update it
ENDIF
BREAK
CASE STUCK_FIX
INT iMaxPoints
WAYPOINT_RECORDING_GET_NUM_POINTS(sFANATIC_ROUTE, iMaxPoints)
IF (iWaypointStuckCheck+4) > iMaxPoints
TELEPORT_STUCK_MARY_ANN(iMaxPoints-1) // Teleport to the one before last waypoint so there's somewhere to go
ELSE
TELEPORT_STUCK_MARY_ANN(iWaypointStuckCheck+4)
ENDIF
KEEP_RUNNING(missionStage, FALSE) // This isn't a debug teleport, so don't do the stage-skippy stuff
StuckStage = STUCK_UPDATE
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE: Speed Mary Ann up where required at a constantly increasing ratio until it hits a cap
PROC SPEED_MARY_ANN_UP()
fMBR_IncreaseRatio += GET_FRAME_TIME()/20
IF fMBR_IncreaseRatio > fMBRMax
fMBR_IncreaseRatio = fMBRMax
ENDIF
#IF IS_DEBUG_BUILD
IF bDebug_SpeedDebug
//DEBUG_PRINTSF("SPEED UP: fMBR_IncreaseRatio = ", fMBR_IncreaseRatio)
ENDIF
#ENDIF
fMBR_RunSpeed += 0.02
IF fMBR_RunSpeed > fMBR_MaxRunSpeed
fMBR_RunSpeed = fMBR_MaxRunSpeed
ENDIF
//
#IF IS_DEBUG_BUILD
IF bDebug_SpeedDebug
IF MASprintState <> SPRINT_ACTIVE
DEBUG_PRINTSF("SPEED UP: fMBR_RunSpeed = ", fMBR_RunSpeed)
ENDIF
ENDIF
#ENDIF
ENDPROC
/// PURPOSE: Slow Mary Ann down where required at a constantly increasing ratio until it hits a cap
PROC SLOW_MARY_ANN_DOWN()
IF fMBR_IncreaseRatio > 1
fMBR_IncreaseRatio -= 0.02
ELSE
fMBR_IncreaseRatio = 1
ENDIF
// Re-cap
IF fMBR_IncreaseRatio > fMBRMax
fMBR_IncreaseRatio = fMBRMax
ENDIF
FLOAT slowDownValue
slowDownValue = 4.5 - (GET_DISTANCE_BETWEEN_PEDS(PLAYER_PED_ID(), MARY_ANN)/2)
IF slowDownValue < 1.8
slowDownValue = 1.8
ELIF slowDownValue > fMBR_MaxRunSpeed
slowDownValue = fMBR_MaxRunSpeed
ENDIF
IF fMBR_RunSpeed > slowDownValue
fMBR_RunSpeed -= 0.01
ELSE
fMBR_RunSpeed = slowDownValue
ENDIF
#IF IS_DEBUG_BUILD
IF bDebug_SpeedDebug
IF MASprintState <> SPRINT_ACTIVE
DEBUG_PRINTSF("SLOW DOWN: fMBR_RunSpeed = ", fMBR_RunSpeed)
ENDIF
ENDIF
#ENDIF
ENDPROC
/// PURPOSE:
/// Because of B*886738, we need to keep Mary Ann sprinting for a few seconds whenever she goes >2.5 MBR, so she doesn't quickly slow down again and keep jerking
/// back and forth between her running and sprint animations as her MBR keeps flicking above and below 2.5MBR
PROC HANDLE_SPRINT_BOOST()
SWITCH MASprintState
CASE SPRINT_WAITING
IF IS_ENTITY_ALIVE(MARY_ANN)
// Don't do the sprint if Mary Ann is in this area (basically on the steps down to the bridge) - tries to prevent B*1426943
IF NOT IS_ENTITY_IN_ANGLED_AREA(MARY_ANN, <<-1809.172852,-549.010559,14.031675>>, <<-1841.728638,-529.457520,33.641205>>, 21.75)
IF fMBR_RunSpeed >= 2.5
IF IS_ENTITY_ALIVE(MARY_ANN)
TASK_LOOK_AT_ENTITY(MARY_ANN, PLAYER_PED_ID(), 1500, SLF_WIDEST_PITCH_LIMIT|SLF_WIDEST_YAW_LIMIT|SLF_USE_TORSO|SLF_WHILE_NOT_IN_FOV, SLF_LOOKAT_VERY_HIGH)
ENDIF
fMBR_SprintCap = fMBR_RunSpeed
MASprintState = SPRINT_ACTIVE
iSprintTimer = GET_GAME_TIMER()
#IF IS_DEBUG_BUILD
IF bDebug_SpeedDebug
DEBUG_PRINTSTRING("*** SPRINT BOOST ACTIVE")
ENDIF
#ENDIF
ENDIF
ENDIF
ENDIF
BREAK
CASE SPRINT_ACTIVE
IF (GET_GAME_TIMER() - iSprintTimer) < iSprintLength
IF fMBR_SprintCap < fMBR_RunSpeed
fMBR_SprintCap = fMBR_RunSpeed
ENDIF
ELSE
fMBR_RunSpeed = fMBR_SprintCap
#IF IS_DEBUG_BUILD
IF bDebug_SpeedDebug
DEBUG_PRINTSTRING("*** SPRINT BOOST REDUCE")
ENDIF
#ENDIF
MASprintState = SPRINT_REDUCE
ENDIF
BREAK
CASE SPRINT_REDUCE
// Gradually reduce Mary Ann's speed if she's ahead
IF place = 2
IF fMBR_RunSpeed > 2.49
fMBR_RunSpeed -= 0.002
ELSE
#IF IS_DEBUG_BUILD
IF bDebug_SpeedDebug
DEBUG_PRINTSTRING("*** SPRINT BOOST COOLDOWN")
ENDIF
#ENDIF
MASprintState = SPRINT_COOLDOWN
iSprintTimer = GET_GAME_TIMER()
ENDIF
ENDIF
BREAK
CASE SPRINT_COOLDOWN
IF (GET_GAME_TIMER() - iSprintTimer) > iSprintDelay
DEBUG_PRINTSTRING("*** SPRINT BOOST WAITING")
MASprintState = SPRINT_WAITING
ENDIF
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE:
/// Handles the rubber-banding behaviour in the final section
PROC DO_MA_FINISH_SPRINT_STYLE()
CONST_FLOAT fBehindMaxSpeed 2.55
IF IS_ENTITY_ALIVE(MARY_ANN)
IF place = 2
// IF IS_PED_SPRINTING(PLAYER_PED_ID())
// FLOAT fSprintTimeLeft = GET_PLAYER_SPRINT_TIME_REMAINING(PLAYER_ID())
//
// ENDIF
FLOAT fDistance = GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), MARY_ANN)
IF fDistance < 15
FLOAT fSpeedReduce = fDistance / 100
IF fMBR_RunSpeed > 2.42
fMBR_RunSpeed -= fSpeedReduce
ENDIF
ELSE
IF fMBR_RunSpeed < 2.52
fMBR_RunSpeed += 0.002
ENDIF
ENDIF
ELSE
FLOAT fDistance = GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), MARY_ANN)
// FLOAT fPlayerMBR = GET_PED_DESIRED_MOVE_BLEND_RATIO(PLAYER_PED_ID())
FLOAT fSpeedModifier = fDistance / 300
IF fDistance < 10
// IF fMBR_RunSpeed < fPlayerMBR
// fMBR_RunSpeed += fSpeedModifier
// ELIF fMBR_RunSpeed > fPlayerMBR
// fMBR_RunSpeed -= fSpeedModifier
// ENDIF
// Have a minimum speed that Mary Ann can run at, so the player can't jog and win
IF fMBR_RunSpeed < 2.487
fMBR_RunSpeed += 0.002
// But also have a max speed so she can be outrun
ELIF fMBR_RunSpeed > 2.492
fMBR_RunSpeed -= 0.002
ENDIF
ELSE
IF fMBR_RunSpeed < fBehindMaxSpeed
fMBR_RunSpeed += fSpeedModifier
ELIF fMBR_RunSpeed > fBehindMaxSpeed
fMBR_RunSpeed -= fSpeedModifier
ENDIF
IF fMBR_RunSpeed > 3.0
fMBR_RunSpeed = 3.0
ENDIF
ENDIF
ENDIF
#IF IS_DEBUG_BUILD
IF bDebug_SpeedDebug
DEBUG_PRINTSF("RACE TO FINISH SPEED: fMBR_RunSpeed = ", fMBR_RunSpeed)
ENDIF
#ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Handles the normal rubber-banding behaviour
PROC DO_MA_RUBBER_BANDING()
IF iNum_PlayerClosestWaypoint = iNum_NPCClosestWaypoint
vector nextPoint
WAYPOINT_RECORDING_GET_COORD(sFANATIC_ROUTE, iNum_NPCClosestWaypoint + 1, nextPoint)
IF GET_DISTANCE_BETWEEN_ENTITY_AND_COORD(PLAYER_PED_ID(), nextPoint) < GET_DISTANCE_BETWEEN_ENTITY_AND_COORD(MARY_ANN, nextPoint)
SPEED_MARY_ANN_UP()
ELSE
SLOW_MARY_ANN_DOWN()
ENDIF
ELIF iNum_PlayerClosestWaypoint > iNum_NPCClosestWaypoint
SPEED_MARY_ANN_UP()
ELSE
SLOW_MARY_ANN_DOWN()
ENDIF
ENDPROC
/// PURPOSE: Update Mary Ann's running speed every frame
PROC UPDATE_HER_RUN_SPEED()
IF missionStage <> MS_END_CUTSCENE
IF missionStage = MS_SPRINT_TO_FINISH
MASprintState = SPRINT_COOLDOWN // Ensure the sprint boost is never active here
DO_MA_FINISH_SPRINT_STYLE()
ELSE
// Don't do the normal rubber banding stuff if Mary Ann is reducing her speed
IF MASprintState <> SPRINT_REDUCE
DO_MA_RUBBER_BANDING()
// Otherwise, if she's meant to be reducing her speed but is behind the player, do the rubber banding stuff anyway
ELIF place = 1
DO_MA_RUBBER_BANDING()
ENDIF
// The SPRINT_REDUCE stage will skip over reducing her speed if she's behind
HANDLE_SPRINT_BOOST()
ENDIF
// Prints for Mary Ann
#IF IS_DEBUG_BUILD
IF bDebug_SpeedDebug
IF MASprintState = SPRINT_WAITING
//DEBUG_PRINTSF("SPRINT WAITING SPEED: fMBR_RunSpeed = ", fMBR_RunSpeed)
ELIF MASprintState = SPRINT_ACTIVE
DEBUG_PRINTSF("SPRINT ACTIVE SPEED: fMBR_SprintCap = ", fMBR_SprintCap)
ELIF MASprintState = SPRINT_REDUCE
DEBUG_PRINTSF("SPRINT REDUCE SPEED: fMBR_RunSpeed = ", fMBR_RunSpeed)
ELIF MASprintState = SPRINT_COOLDOWN
//DEBUG_PRINTSF("SPRINT COOLDOWN SPEED: fMBR_RunSpeed = ", fMBR_RunSpeed)
ENDIF
ENDIF
#ENDIF
IF IS_WAYPOINT_PLAYBACK_GOING_ON_FOR_PED(MARY_ANN)
// If the sprint boost (to stop 886738) is active, use the sprint cap value instead of the calculated fMBR_RunSpeed
IF MASprintState = SPRINT_ACTIVE
WAYPOINT_PLAYBACK_OVERRIDE_SPEED(MARY_ANN, fMBR_SprintCap)
ELSE
WAYPOINT_PLAYBACK_OVERRIDE_SPEED(MARY_ANN, fMBR_RunSpeed)
ENDIF
ENDIF
// SHE HAS A MINIMUM SPEED SO THAT SHE CAN RUN DOWN THE STEPS QUICKLY LIKE THE PLAYER. SHOULD BE A TEMP FIX WHILE CODE SORTS THIS
SET_PED_MIN_MOVE_BLEND_RATIO(MARY_ANN, fMBR_RunSpeed - 0.5)
SET_PED_MOVE_RATE_OVERRIDE(MARY_ANN, fMBR_IncreaseRatio)
ENDIF
ENDPROC
/// PURPOSE: Check to make a ped ragdoll if Mary Ann collides with them
PROC CHECK_IF_MARY_ANN_RUNS_INTO_A_PED()
IF HAS_ENTITY_COLLIDED_WITH_ANYTHING(MARY_ANN)
PED_INDEX ped
GET_CLOSEST_PED(GET_ENTITY_COORDS(MARY_ANN), 0.75, TRUE, TRUE, ped)
IF DOES_ENTITY_EXIST(ped)
AND NOT IS_ENTITY_DEAD(ped)
IF NOT IS_PED_RAGDOLL(ped)
AND IS_ENTITY_TOUCHING_ENTITY(MARY_ANN, ped)
CLEAR_PED_TASKS(ped)
SET_PED_TO_RAGDOLL(ped, 800, 1500, TASK_NM_BALANCE)
VECTOR pushDir = -GET_OFFSET_FROM_ENTITY_GIVEN_WORLD_COORDS(MARY_ANN, GET_ENTITY_COORDS(ped))
APPLY_FORCE_TO_ENTITY(ped, APPLY_TYPE_IMPULSE, pushDir, <<0,0,0>>, GET_PED_RAGDOLL_BONE_INDEX(ped, RAGDOLL_SPINE), FALSE, FALSE, TRUE)
if not IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF PED_HAS_SEXINESS_FLAG_SET(ped, SF_HOT_PERSON)
IF pushLine[2].hasBeenPlayed = FALSE
INT temp
IF CAN_MARY_ANN_SAY_SINGLE_LINE("FAN1_PUSH", pushLine[2].dialogueLine, FALSE, temp)
pushLine[2].hasBeenPlayed = TRUE
ENDIF
ELSE
IF pushLine[0].hasBeenPlayed = FALSE
INT temp
IF CAN_MARY_ANN_SAY_SINGLE_LINE("FAN1_PUSH", pushLine[0].dialogueLine, FALSE, temp)
pushLine[0].hasBeenPlayed = TRUE
ENDIF
ENDIF
ENDIF
ELSE
IF pushLine[1].hasBeenPlayed = FALSE
INT temp
IF CAN_MARY_ANN_SAY_SINGLE_LINE("FAN1_PUSH", pushLine[1].dialogueLine, FALSE, temp)
pushLine[1].hasBeenPlayed = TRUE
ENDIF
ELSE
IF pushLine[0].hasBeenPlayed = FALSE
INT temp
IF CAN_MARY_ANN_SAY_SINGLE_LINE("FAN1_PUSH", pushLine[0].dialogueLine, FALSE, temp)
pushLine[0].hasBeenPlayed = TRUE
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
//DEBUG_PRINTSTRING("SHE COLLIDED WITH SOMETHING")
ENDIF
ENDPROC
/// PURPOSE: Large, encompassing process to control Mary Ann's behaviour throughout the mission
PROC DEAL_WITH_MARY_ANN()
IF IS_PED_UNINJURED(MARY_ANN)
IF missionStage <> MS_END_CUTSCENE
CHECK_IF_MARY_ANN_RUNS_INTO_A_PED()
ELSE
// B*1765019 - If player manages to make Mary Ann quit her task, keep retasking her until she gets on the goddamn bike
IF cutsceneStage >= CS_SAY_FINAL_LINE
IF NOT IsPedPerformingTask(MARY_ANN, SCRIPT_TASK_PERFORM_SEQUENCE)
AND NOT b_PlayerOnMAsBike
IF IS_VEHICLE_OK(MAS_BIKE)
OPEN_SEQUENCE_TASK(seq)
TASK_ENTER_VEHICLE(NULL, MAS_BIKE, DEFAULT_TIME_BEFORE_WARP, VS_DRIVER, PEDMOVEBLENDRATIO_RUN)
TASK_CLEAR_LOOK_AT(NULL)
TASK_LOOK_AT_ENTITY(NULL, PLAYER_PED_ID(), 2000)
TASK_VEHICLE_DRIVE_TO_COORD(NULL, MAS_BIKE, <<-2018.17, -461.00, 10.56>>, 10, DRIVINGSTYLE_NORMAL, MARYSBIKEMODEL, DF_SteerAroundStationaryCars, 3, 50)
TASK_VEHICLE_DRIVE_TO_COORD(NULL, MAS_BIKE, <<-2014.96, -455.47, 10.48>>, 10, DRIVINGSTYLE_NORMAL, MARYSBIKEMODEL, DF_SteerAroundStationaryCars, 3, 50)
TASK_VEHICLE_DRIVE_WANDER(NULL, MAS_BIKE, 10, DRIVINGMODE_AVOIDCARS_STOPFORPEDS_OBEYLIGHTS)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(MARY_ANN, seq)
CLEAR_SEQUENCE_TASK(seq)
SET_PED_KEEP_TASK(MARY_ANN, TRUE)
DEBUG_PRINTSTRING("Emergency retasked Mary Ann!")
ENDIF
ENDIF
ENDIF
ENDIF
TRY_KEEPUP_OR_CATCHUP_LINES() // Keep trying to play these lines if we're waiting for a prior conversation to finish
// If she gets far from the player we need to load the world around her so that she keeps running
IF GET_DISTANCE_BETWEEN_PEDS(PLAYER_PED_ID(), MARY_ANN) > 80
IF b_LoadCollisionAroudMaryAnn = FALSE
SET_ENTITY_LOAD_COLLISION_FLAG(MARY_ANN, TRUE)
b_LoadCollisionAroudMaryAnn = TRUE
ENDIF
ELSE
IF b_LoadCollisionAroudMaryAnn = TRUE
SET_ENTITY_LOAD_COLLISION_FLAG(MARY_ANN, FALSE)
b_LoadCollisionAroudMaryAnn = FALSE
ENDIF
ENDIF
IF missionStage <> MS_END_CUTSCENE
AND missionStage <> MS_PLAYER_IN_VEHICLE
AND missionStage <> MS_LOST_RACE
IF MADialogueState <> MA_OUT_OF_TALKING_RANGE
IF GET_DISTANCE_BETWEEN_PEDS(PLAYER_PED_ID(), MARY_ANN) > 25
SET_MARY_ANN_DIALOGUE_STATE(MA_OUT_OF_TALKING_RANGE)
ENDIF
ENDIF
ENDIF
IF MADialogueState <> MA_WITHIN_TALKING_RANGE
IF GET_DISTANCE_BETWEEN_PEDS(PLAYER_PED_ID(), MARY_ANN) < 24
SET_MARY_ANN_DIALOGUE_STATE(MA_WITHIN_TALKING_RANGE)
ENDIF
ENDIF
UPDATE_HER_RUN_SPEED()
IF missionStage <> MS_END_CUTSCENE
AND missionStage <> MS_CUTSCENE
AND missionStage <> MS_LOST_RACE
IF NOT IS_ENTITY_IN_ANGLED_AREA(MARY_ANN, <<-1809.172852,-549.010559,14.031675>>, <<-1841.728638,-529.457520,33.641205>>, 21.75)
IF b_DoPedOvertake = FALSE
SET_PED_STEERS_AROUND_PEDS(MARY_ANN, true)
b_DoPedOvertake = TRUE
DEBUG_PRINTSTRING("Set Mary Ann to steer round peds")
ENDIF
ELSE
IF b_DoPedOvertake = TRUE
SET_PED_STEERS_AROUND_PEDS(MARY_ANN, FALSE)
b_DoPedOvertake = FALSE
DEBUG_PRINTSTRING("Unset Mary Ann to steer round peds")
ENDIF
ENDIF
CHECK_FOR_GETTING_STUCK()
ENDIF
ENDIF
ENDPROC
/// PURPOSE: Set all the models we may have requested as no longer needed
PROC UNLOAD_ALL_MODELS()
SET_MODEL_AS_NO_LONGER_NEEDED(G_M_Y_SALVAGOON_01)
SET_MODEL_AS_NO_LONGER_NEEDED(JOGGERMODEL)
SET_MODEL_AS_NO_LONGER_NEEDED(A_M_Y_BEACH_01)
SET_MODEL_AS_NO_LONGER_NEEDED(A_F_Y_BEACH_01)
SET_MODEL_AS_NO_LONGER_NEEDED(A_C_ROTTWEILER)
SET_MODEL_AS_NO_LONGER_NEEDED(S_M_Y_BayWatch_01)
SET_MODEL_AS_NO_LONGER_NEEDED(IG_MARYANN)
SET_MODEL_AS_NO_LONGER_NEEDED(MARYSBIKEMODEL)
SET_MODEL_AS_NO_LONGER_NEEDED(BLAZER2)
SET_MODEL_AS_NO_LONGER_NEEDED(BANSHEE)
SET_MODEL_AS_NO_LONGER_NEEDED(REGINA)
ENDPROC
/// PURPOSE:
/// Part of the race tracking might check the distance between Michael and Mary Ann's next checkpoint in order to determine who is in front
/// The problem is that if the player is just in front and has just hit a CP, Mary Ann may be very close to that CP behind Michael,
/// so the check thinks that Mary Ann in 1st position because she is closer to "her" CP (until she hits it, and it starts checking the same CP again)
/// Instead of checking each individual's CP, let's check the one furthest away and return that
/// RETURNS:
/// The furthest away checkpoint
FUNC INT RETURN_FURTHEST_CHECKPOINT()
IF iCURRENT_RACE_POS > iNPC_RACE_POS
IF iCURRENT_RACE_POS >= MAX_CHECKPOINTS
RETURN 9
ELSE
RETURN iCURRENT_RACE_POS
ENDIF
ELSE
IF iNPC_RACE_POS >= MAX_CHECKPOINTS
RETURN 9
ELSE
RETURN iNPC_RACE_POS
ENDIF
ENDIF
ENDFUNC
/// PURPOSE: Control the race checkpoints througout the mission as it progresses
PROC DEAL_WITH_RACE_BLIPS()
HUD_COLOURS currentCPColour
INT iR, iG, iB, iA
INT PreviR, PreviG, PreviB
IF iCURRENT_RACE_POS < iMaxRacePositions
IF iCURRENT_RACE_POS < iMaxRacePositions - 1
IF IS_ENTITY_AT_COORD(PLAYER_PED_ID(), RACE_POSITIONS[iCURRENT_RACE_POS], <<4,4,3>>)
OR NOT DOES_BLIP_EXIST(DESTINATION_BLIP)
SAFE_REMOVE_BLIP(DESTINATION_BLIP)
SAFE_REMOVE_BLIP(NEXT_DESTINATION_BLIP)
IF checkPoint != NULL
DEBUG_PRINTSTRING("Create prev CP")
iPrevAlpha = 180
currentCPColour = HUD_COLOUR_WHITE
GET_HUD_COLOUR(currentCPColour, PreviR, PreviG, PreviB, iPrevAlpha)
PrevCheckpoint = CREATE_CHECKPOINT(GET_RACE_CHECKPOINT_TYPE(iCURRENT_RACE_POS), RACE_POSITIONS[iCURRENT_RACE_POS]+<<0, 0, 2.0>>, RACE_POSITIONS[iCURRENT_RACE_POS + 1], 3.2, PreviR, PreviG, PreviB, iPrevAlpha)
SET_CHECKPOINT_RGBA(PrevCheckpoint, PreviR, PreviG, PreviB, iPrevAlpha)
SET_CHECKPOINT_RGBA2(PrevCheckpoint, PreviR,PreviG, PreviB, iPrevAlpha)
ENDIF
DELETE_CHECKPOINT(checkPoint)
IF iCURRENT_RACE_POS != 0
// Play the checkpoint sound - only want to do this after the very first pass through, otherwise we get the sfx after the cutscene
PLAY_SOUND_FRONTEND(-1, "CHECKPOINT_NORMAL", "HUD_MINI_GAME_SOUNDSET", FALSE)
ENDIF
iCURRENT_RACE_POS++
// If we're not at the final checkpoint, do a small blip for the next one too
IF iCURRENT_RACE_POS < iMaxRacePositions - 1
checkpoint = CREATE_CHECKPOINT(GET_RACE_CHECKPOINT_TYPE(iCURRENT_RACE_POS), RACE_POSITIONS[iCURRENT_RACE_POS]+<<0, 0, 2.0>>, RACE_POSITIONS[iCURRENT_RACE_POS + 1], 3.2, iR, iG, iB, iA)
SET_CHECKPOINT_CYLINDER_HEIGHT(checkpoint,1.6,1.6,100)
currentCPColour = HUD_COLOUR_YELLOWLIGHT
GET_HUD_COLOUR(currentCPColour, iR, iG, iB, iA)
SET_CHECKPOINT_RGBA(checkpoint, iR, iG, iB, iA)
currentCPColour = HUD_COLOUR_NORTH_BLUE
GET_HUD_COLOUR(currentCPColour, iR, iG, iB, iA)
SET_CHECKPOINT_RGBA2(checkpoint, iR, iG, iB, iA)
DESTINATION_BLIP = ADD_BLIP_FOR_COORD(RACE_POSITIONS[iCURRENT_RACE_POS])
SHOW_HEIGHT_ON_BLIP(DESTINATION_BLIP, FALSE)
SET_BLIP_SCALE(DESTINATION_BLIP, 1.2)
NEXT_DESTINATION_BLIP = ADD_BLIP_FOR_COORD(RACE_POSITIONS[iCURRENT_RACE_POS + 1])
IF (iCURRENT_RACE_POS + 1) = iMaxRacePositions - 1
SET_BLIP_SCALE(NEXT_DESTINATION_BLIP, 1.2) // The final next-checkpoint blip has a scale of 1.2
SET_BLIP_SPRITE(NEXT_DESTINATION_BLIP, RADAR_TRACE_RACEFLAG)
SHOW_HEIGHT_ON_BLIP(NEXT_DESTINATION_BLIP, FALSE)
ELSE
SET_BLIP_SCALE(NEXT_DESTINATION_BLIP, 0.7)
SHOW_HEIGHT_ON_BLIP(NEXT_DESTINATION_BLIP, FALSE)
ENDIF
ELIF iCURRENT_RACE_POS = iMaxRacePositions - 1
currentCPColour = GET_RACE_CHECKPOINT_COLOUR(GET_RACE_CHECKPOINT_TYPE(iCURRENT_RACE_POS))
GET_HUD_COLOUR(currentCPColour, iR, iG, iB, iA)
checkpoint = CREATE_CHECKPOINT(GET_RACE_CHECKPOINT_TYPE(iCURRENT_RACE_POS), RACE_POSITIONS[iCURRENT_RACE_POS]+<<0, 0, 2.0>>, RACE_POSITIONS[iCURRENT_RACE_POS], 3.2, iR, iG, iB, iA)
SET_CHECKPOINT_CYLINDER_HEIGHT(checkpoint,1.6,1.6,100)
DESTINATION_BLIP = ADD_BLIP_FOR_COORD(RACE_POSITIONS[iCURRENT_RACE_POS])
SET_BLIP_SCALE(DESTINATION_BLIP, 1.2)
SET_BLIP_SPRITE(DESTINATION_BLIP, RADAR_TRACE_RACEFLAG)
SHOW_HEIGHT_ON_BLIP(DESTINATION_BLIP, FALSE)
ENDIF
ENDIF
ELSE
IF iCURRENT_RACE_POS = iMaxRacePositions - 1
IF GET_DISTANCE_BETWEEN_ENTITY_AND_COORD(PLAYER_PED_ID(), vPos_FinishLine) < 4
IF NOT IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
IF checkPoint != NULL
DEBUG_PRINTSTRING("Create prev CP")
iPrevAlpha = 180
currentCPColour = HUD_COLOUR_WHITE
GET_HUD_COLOUR(currentCPColour, PreviR, PreviG, PreviB, iPrevAlpha)
PrevCheckpoint = CREATE_CHECKPOINT(CHECKPOINT_RACE_GROUND_FLAG, RACE_POSITIONS[iCURRENT_RACE_POS]+<<0, 0, 2.0>>, RACE_POSITIONS[iCURRENT_RACE_POS], 3.2, PreviR, PreviG, PreviB, iPrevAlpha)
SET_CHECKPOINT_RGBA(PrevCheckpoint, PreviR, PreviG, PreviB, iPrevAlpha)
SET_CHECKPOINT_RGBA2(PrevCheckpoint, PreviR,PreviG, PreviB, iPrevAlpha)
ENDIF
// Play the checkpoint sound
PLAY_SOUND_FRONTEND(-1, "CHECKPOINT_NORMAL", "HUD_MINI_GAME_SOUNDSET", FALSE)
cutsceneStage = CS_WAIT_FOR_ANN
stageStage = SS_SETUP
missionStage = MS_END_CUTSCENE
DEBUG_PRINTSTRING("PLAYER_AT_FINISH_LINE")
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
IF NOT IS_ENTITY_DEAD(PLAYER_PED_ID())
FLOAT fDis = GET_DISTANCE_BETWEEN_COORDS(RACE_POSITIONS[iCURRENT_RACE_POS],GET_ENTITY_COORDS(PLAYER_PED_ID()))
IF checkpoint != NULL // Make sure the checkpoint exists first
IF fDis > 100.0
iA = 240
currentCPColour = HUD_COLOUR_YELLOWLIGHT
GET_HUD_COLOUR(currentCPColour, iR, iG, iB, iA)
SET_CHECKPOINT_RGBA(checkpoint, iR, iG, iB, iA)
currentCPColour = HUD_COLOUR_NORTH_BLUE
GET_HUD_COLOUR(currentCPColour, iR, iG, iB, iA)
SET_CHECKPOINT_RGBA2(checkpoint, iR, iG, iB, iA)
ELSE
//DEBUG_PRINTSTRING("Dim current CP")
currentCPColour = HUD_COLOUR_YELLOWLIGHT
GET_HUD_COLOUR(currentCPColour, iR, iG, iB, iA)
iA = ROUND(fDis*2.4)
IF iA < 60
iA = 60
ENDIF
SET_CHECKPOINT_RGBA(checkpoint, iR, iG, iB, iA)
currentCPColour = HUD_COLOUR_NORTH_BLUE
GET_HUD_COLOUR(currentCPColour, iR, iG, iB, iA)
iA = ROUND(fDis*2.4)
IF iA < 60
iA = 60
ENDIF
SET_CHECKPOINT_RGBA2(checkpoint, iR, iG, iB, iA)
ENDIF
ENDIF
ENDIF
IF PrevCheckpoint != NULL
//DEBUG_PRINTSTRING("Fade previous CP")
iPrevAlpha -= 25
IF iPrevAlpha > 0
GET_HUD_COLOUR(HUD_COLOUR_WHITE, PreviR, PreviG, PreviB, iA)
SET_CHECKPOINT_RGBA(PrevCheckpoint, PreviR, PreviG, PreviB, iPrevAlpha)
SET_CHECKPOINT_RGBA2(PrevCheckpoint, PreviR, PreviG, PreviB, iPrevAlpha)
ELSE
DELETE_CHECKPOINT(PrevCheckpoint)
ENDIF
ENDIF
IF iNPC_RACE_POS < iMaxRacePositions
IF IS_ENTITY_AT_COORD(MARY_ANN, RACE_POSITIONS[iNPC_RACE_POS], <<3,3,3>>)
iNPC_RACE_POS++
ENDIF
ENDIF
/*
DEBUG_PRINTSI("current player pos - ",iCURRENT_RACE_POS)
DEBUG_PRINTSI("current NPC pos - ",iNPC_RACE_POS)
DEBUG_PRINTSI("MAX POSITIONS - ",iMaxRacePositions)
*/
ENDPROC
/// PURPOSE: Track the locations of the player and Mary Ann and update the race positions accordingly
PROC DEAL_WITH_THE_RACE_TRACKING()
IF IS_PED_UNINJURED(MARY_ANN)
IF ENUM_TO_INT(missionStage) < ENUM_TO_INT(MS_END_CUTSCENE)
AND ENUM_TO_INT(missionStage) > ENUM_TO_INT(MS_CUTSCENE)
DEAL_WITH_RACE_BLIPS()
UPDATE_CHASE_BLIP(FANATIC_BLIP, MARY_ANN, 70, 0.72)
IF iNum_PlayerClosestWaypoint > iNum_NPCClosestWaypoint
IF place != 1
place = 1
IF (GET_GAME_TIMER() - iOvertakeTimer) > 3000
DEBUG_PRINTSTRING("Trying an overtake line...")
bOvertaken = TRUE
iOvertakeTimer = GET_GAME_TIMER()
ELSE
DEBUG_PRINTSI("Can't do overtake line, overtake timer is = ", (GET_GAME_TIMER() - iOvertakeTimer))
ENDIF
ENDIF
ELIF iNum_PlayerClosestWaypoint < iNum_NPCClosestWaypoint
IF place != 2
place = 2
ENDIF
ELSE
IF GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(MARY_ANN), RACE_POSITIONS[RETURN_FURTHEST_CHECKPOINT()]) < GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), RACE_POSITIONS[RETURN_FURTHEST_CHECKPOINT()])
IF place != 2
place = 2
ENDIF
ELSE
IF place != 1
place = 1
IF (GET_GAME_TIMER() - iOvertakeTimer) > 3000
DEBUG_PRINTSTRING("Trying an overtake line...")
bOvertaken = TRUE
iOvertakeTimer = GET_GAME_TIMER()
ELSE
DEBUG_PRINTSI("Can't do overtake line, overtake timer is = ", (GET_GAME_TIMER() - iOvertakeTimer))
ENDIF
ENDIF
ENDIF
ENDIF
// IF iNPC_RACE_POS > iCURRENT_RACE_POS
// IF place != 2
// place = 2
// ENDIF
// ELIF iNPC_RACE_POS < iCURRENT_RACE_POS
// IF place != 1
// place = 1
// IF (GET_GAME_TIMER() - iOvertakeTimer) > 3000
// DEBUG_PRINTSTRING("Trying an overtake line...")
// bOvertaken = TRUE
// iOvertakeTimer = GET_GAME_TIMER()
// ENDIF
// ENDIF
// ELSE
// IF GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(MARY_ANN), RACE_POSITIONS[iNPC_RACE_POS]) < GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), RACE_POSITIONS[iCURRENT_RACE_POS])
// IF place != 2
// place = 2
// ENDIF
// ELSE
// IF place != 1
// place = 1
// IF (GET_GAME_TIMER() - iOvertakeTimer) > 3000
// DEBUG_PRINTSTRING("Trying an overtake line...")
// bOvertaken = TRUE
// iOvertakeTimer = GET_GAME_TIMER()
// ENDIF
// ENDIF
// ENDIF
// ENDIF
//DRAW_BIG_DOUBLE_SCORE_HUD(iCURRENT_RACE_POS, iMaxRacePositions, "FATIC1_CP", HUD_COLOUR_YELLOWLIGHT )
SET_FAR_RIGHT_TITLE_POSITION_HUD_THIS_FRAME()
DRAW_RACE_HUD((GET_GAME_TIMER() - start_time), "", -1, -1, "", place, 2, "", DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT,
DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, TRUE) // turn milliseconds off!
ENDIF
ENDIF
ENDPROC
/// PURPOSE: Delete every entity in the mission
PROC DELETE_EVERYTHING()
IF IS_AUDIO_SCENE_ACTIVE("FANATIC_MIX_SCENE")
REMOVE_ENTITY_FROM_AUDIO_MIX_GROUP(MARY_ANN)
ENDIF
SAFE_DELETE_PED(MARY_ANN)
SAFE_DELETE_PED(QUAD_DRIVER)
SAFE_DELETE_PED(cprWatcher1)
SAFE_DELETE_PED(cprWatcher2)
SAFE_DELETE_PED(INJURED_PED)
SAFE_DELETE_PED(BEACH_DOG)
SAFE_DELETE_PED(OtherJoggers[0].thisIndex)
SAFE_DELETE_PED(OtherJoggers[1].thisIndex)
SAFE_DELETE_PED(OtherJoggers[2].thisIndex)
SAFE_DELETE_PED(OtherJoggers[3].thisIndex)
SAFE_DELETE_PED(DRIVEBY_FINGER_CAR.Driver)
SAFE_DELETE_PED(DRIVEBY_FINGER_CAR.Passenger)
SAFE_DELETE_PED(FOLLOWING_CAR.Driver)
SAFE_DELETE_PED(FOLLOWING_CAR.Passenger)
SAFE_DELETE_VEHICLE(DRIVEBY_FINGER_CAR.thisCarIndex)
SAFE_DELETE_VEHICLE(FOLLOWING_CAR.thisCarIndex)
SAFE_DELETE_VEHICLE(CHEAT_QUAD)
SAFE_DELETE_VEHICLE(MAS_BIKE)
ENDPROC
/// PURPOSE: Reset all of the bools used to track which conversations have been said to the default
PROC RESET_DIALOGUE_BOOLS()
bCatchupCheatLineSaid = FALSE
bOvertaken = FALSE
iOvertakeTimer = GET_GAME_TIMER()
iOneLinerTimer = GET_GAME_TIMER()
iRoadTimer = GET_GAME_TIMER()
iRoadCounter = 0
OvertakeLines.timesPlayed = 0
MikePushMALine.timesPlayed = 0
MikePushPedLine.timesPlayed = 0
pushLine[0].hasBeenPlayed = FALSE
pushLine[1].hasBeenPlayed = FALSE
pushLine[2].hasBeenPlayed = FALSE
cheatedLeaptFence.hasBeenPlayed = FALSE
cheatedRanAcrossGrass.hasBeenPlayed = FALSE
returnAfterCheatedLine.hasBeenPlayed = FALSE
startRunConversation.hasBeenPlayed = FALSE
road1Conversation.hasBeenPlayed = FALSE
road2Conversation.hasBeenPlayed = FALSE
raceConversation.hasBeenPlayed = FALSE
leftRaceWarning.hasBeenShown = FALSE
leftBehindWarning.hasBeenShown = FALSE
vehicleWarning.hasBeenShown = FALSE
iHurryUpLineNumber = 0
iCatchUpLineNumber = 0
ENDPROC
/// PURPOSE: Handle Z-skipping from stage to stage in a mission
PROC JUMP_TO_STAGE(debugSkipToMissionStage newStage)
RC_START_Z_SKIP()
CLEAR_PRINTS()
SET_PLAYER_WANTED_LEVEL(PLAYER_ID(), 0)
FINISH_CUTSCENE(FALSE, TRUE)
DISPLAY_RADAR(TRUE)
STOP_SOUND(iHeartbeatAudioID)
bHeartbeatStarted = FALSE
CLEAR_PED_TASKS(PLAYER_PED_ID())
RESET_PLAYER_STAMINA(PLAYER_ID())
b_FinalPedsStartedWalking = FALSE
b_DrivebyHorn = FALSE
SAFE_REMOVE_BLIP(DESTINATION_BLIP)
SAFE_REMOVE_BLIP(NEXT_DESTINATION_BLIP)
DELETE_CHECKPOINT(checkPoint)
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
DEBUG_PRINTSTRING("Stopping scripted convo at jump_to_stage")
KILL_FACE_TO_FACE_CONVERSATION_DO_NOT_FINISH_LAST_LINE()
ENDIF
REMOVE_RELATIONSHIP_GROUP(relGroupFriendly)
ADD_RELATIONSHIP_GROUP("FRIENDLIES", relGroupFriendly)
SET_RELATIONSHIP_BETWEEN_GROUPS(ACQUAINTANCE_TYPE_PED_LIKE, relGroupFriendly, RELGROUPHASH_PLAYER)
SET_RELATIONSHIP_BETWEEN_GROUPS(ACQUAINTANCE_TYPE_PED_LIKE, RELGROUPHASH_PLAYER, relGroupFriendly)
REQUEST_MODEL(IG_MARYANN)
WHILE NOT HAS_MODEL_LOADED(IG_MARYANN)
WAIT(0)
ENDWHILE
DELETE_EVERYTHING()
RESET_DIALOGUE_BOOLS()
iOvertakeTimer = GET_GAME_TIMER()
iOneLinerTimer = GET_GAME_TIMER()
bOvertaken = FALSE
MARY_ANN = CREATE_PED(PEDTYPE_MISSION, IG_MARYANN, <<-1865.90, -448.81, 45.13>>, -143.87)
SET_PED_RELATIONSHIP_GROUP_HASH(MARY_ANN, relGroupFriendly)
SET_PED_MOVEMENT_CLIPSET(MARY_ANN, "FEMALE_FAST_RUNNER")
SET_PED_COMPONENT_VARIATION(MARY_ANN, PED_COMP_LEG, 1, 0)
ADD_PED_FOR_DIALOGUE(MyLocalPedStruct, 3, MARY_ANN, "MARYANN")
IF newStage <= DEBUG_TO_STEPS_DOWN
iSprintLength = 1800
iSprintDelay = 4500
ENDIF
IF newStage = DEBUG_TO_INTRO
IF IS_AUDIO_SCENE_ACTIVE("FANATIC_MIX_SCENE")
REMOVE_ENTITY_FROM_AUDIO_MIX_GROUP(MARY_ANN)
STOP_AUDIO_SCENE("FANATIC_MIX_SCENE")
ENDIF
ELSE
IF NOT IS_AUDIO_SCENE_ACTIVE("FANATIC_MIX_SCENE")
START_AUDIO_SCENE("FANATIC_MIX_SCENE")
IF IS_ENTITY_ALIVE(MARY_ANN)
ADD_ENTITY_TO_AUDIO_MIX_GROUP(MARY_ANN,"FANATIC_MIX_MARY_ANNE")
ENDIF
ENDIF
ENDIF
SWITCH newStage
CASE DEBUG_TO_INTRO
RC_REQUEST_CUTSCENE("ef_1_rcm")
IF CAN_REQUEST_ASSETS_FOR_CUTSCENE_ENTITY()
DEBUG_PRINTSTRING("Trying to set Mary Ann component variation")
SET_CUTSCENE_PED_COMPONENT_VARIATION_FROM_PED("Mary_Ann", MARY_ANN, CS_MARYANN)
ENDIF
iCURRENT_RACE_POS = 0
iNPC_RACE_POS = 1
REMOVE_RELATIONSHIP_GROUP(relGroupFriendly)
TURN_ROADS_ON(FALSE)
LOAD_OTHER_ASSETS()
CREATE_CARS()
UNLOAD_ALL_MODELS()
stageStage = SS_SETUP
missionStage = MS_CUTSCENE
BREAK
CASE DEBUG_TO_START
iCURRENT_RACE_POS = 0
iNPC_RACE_POS = 1
IF NOT IS_REPLAY_BEING_SET_UP()
SET_ENTITY_COORDS(PLAYER_PED_ID(), <<-1878.2344, -439.6985, 45.0299>>)
SET_ENTITY_HEADING(PLAYER_PED_ID(), 241.0468)
ENDIF
CLEAR_AREA_OF_PEDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), 7)
SET_ENTITY_COORDS(MARY_ANN, <<-1869.24, -444.99, 45.17>>)
SET_ENTITY_HEADING(MARY_ANN, -143.87)
TURN_ROADS_ON(FALSE)
LOAD_OTHER_ASSETS()
CREATE_CARS()
UNLOAD_ALL_MODELS()
KEEP_RUNNING(MS_START_RUNNING)
IF NOT IS_REPLAY_BEING_SET_UP() // Can't do these while a replay is being set up, will do them at the end instead
// This is to keep Michael running when the mission is replayed after a fail (or a skip I guess)
FORCE_PED_MOTION_STATE(PLAYER_PED_ID(), MS_ON_FOOT_RUN, TRUE, FAUS_DEFAULT)
SIMULATE_PLAYER_INPUT_GAIT(PLAYER_ID(), PEDMOVEBLENDRATIO_RUN, 5000)
SET_CURRENT_PED_WEAPON(PLAYER_PED_ID(), WEAPONTYPE_UNARMED, TRUE)
ENDIF
BREAK
CASE DEBUG_TO_ROAD
iCURRENT_RACE_POS = 3
iNPC_RACE_POS = 4
CLEAR_PED_TASKS(PLAYER_PED_ID())
SET_ENTITY_COORDS(PLAYER_PED_ID(), <<-1731.05, -549.78, 36.40>>)
SET_ENTITY_HEADING(PLAYER_PED_ID(), 104.26)
CLEAR_PED_TASKS(MARY_ANN)
SET_ENTITY_COORDS(MARY_ANN, <<-1732.880493,-551.763245,36.5>>)
SET_ENTITY_HEADING(MARY_ANN, 115.26)
TURN_ROADS_ON(FALSE)
CLEAR_AREA_OF_VEHICLES(<<-1806.495483,-525.869629,29.925911>> , 100)
LOAD_OTHER_ASSETS()
CREATE_CARS()
UNLOAD_ALL_MODELS()
KEEP_RUNNING(MS_ROAD_RUNNING_SECTION)
BREAK
CASE DEBUG_TO_STEPS_DOWN
iCURRENT_RACE_POS = 5
iNPC_RACE_POS = 6
CLEAR_PED_TASKS(PLAYER_PED_ID())
SET_ENTITY_COORDS(PLAYER_PED_ID(), <<-1832.52, -519.37, 27.89>>)
SET_ENTITY_HEADING(PLAYER_PED_ID(), 162.59)
CLEAR_PED_TASKS(MARY_ANN)
SET_ENTITY_COORDS(MARY_ANN, <<-1833.81, -523.70, 28.14>>)
SET_ENTITY_HEADING(MARY_ANN, 172.66)
LOAD_OTHER_ASSETS()
WHILE NOT LOAD_CPR()
OR NOT LOAD_DOG()
WAIT(0)
ENDWHILE
CREATE_DOGS()
CREATE_QUAD_BIKE_SCENE()
CREATE_JOGGERS()
UNLOAD_ALL_MODELS()
TURN_ROADS_ON()
KEEP_RUNNING(MS_STEPS_DOWN)
BREAK
CASE DEBUG_TO_BEACH
iCURRENT_RACE_POS = 6
iNPC_RACE_POS = 7
CLEAR_PED_TASKS(PLAYER_PED_ID())
SET_ENTITY_COORDS(PLAYER_PED_ID(), <<-1850.10, -592.21, 18.2>>)
SET_ENTITY_HEADING(PLAYER_PED_ID(), 124.19)
CLEAR_PED_TASKS(MARY_ANN)
SET_ENTITY_COORDS(MARY_ANN, <<-1849.61, -592.90, 18.2>>)
SET_ENTITY_HEADING(MARY_ANN, 135.16)
LOAD_OTHER_ASSETS()
WHILE NOT LOAD_CPR()
OR NOT LOAD_DOG()
WAIT(0)
ENDWHILE
CREATE_DOGS()
CREATE_QUAD_BIKE_SCENE(FALSE)
CREATE_JOGGERS()
IF IS_PED_UNINJURED(INJURED_PED)
ADD_SHOCKING_EVENT_FOR_ENTITY(EVENT_SHOCKING_INJURED_PED, INJURED_PED, -1)
ENDIF
UNLOAD_ALL_MODELS()
TURN_ROADS_ON()
IF IS_OUTFIT_SUITABLE_FOR_FANATIC_MISSION(1)
CREATE_CONVERSATION(MyLocalPedStruct, "FAN1AU", "FAN1_BCHB", CONV_PRIORITY_MEDIUM)
ELSE
CREATE_CONVERSATION(MyLocalPedStruct, "FAN1AU", "FAN1_BCHA", CONV_PRIORITY_MEDIUM)
ENDIF
KEEP_RUNNING(MS_SPRINT_TO_FINISH)
BREAK
CASE DEBUG_TO_FINISH_LINE
iCURRENT_RACE_POS = 8
iNPC_RACE_POS = 9
LOAD_OTHER_ASSETS()
WHILE NOT LOAD_CPR()
OR NOT LOAD_DOG()
WAIT(0)
ENDWHILE
CREATE_DOGS()
CREATE_QUAD_BIKE_SCENE()
CREATE_JOGGERS()
UNLOAD_ALL_MODELS()
CLEAR_PED_TASKS(PLAYER_PED_ID())
SET_ENTITY_COORDS(PLAYER_PED_ID(), vPos_FinishLine)
SET_ENTITY_HEADING(PLAYER_PED_ID(), 19.95)
IF IS_PED_UNINJURED(MARY_ANN)
CLEAR_PED_TASKS(MARY_ANN)
SET_ENTITY_COORDS(MARY_ANN, <<-1986.93, -526.39, 11.70>>)
SET_ENTITY_HEADING(MARY_ANN, 44.46)
ENDIF
TURN_ROADS_ON()
KEEP_RUNNING(MS_DEBUG_NEAR_FINISH_LINE)
BREAK
CASE DEBUG_NEXT_TO_FINISH
// This is a special option in case you want to let Mary Ann win, and see the "you lost" cutscene.
iCURRENT_RACE_POS = 8
iNPC_RACE_POS = 9
LOAD_OTHER_ASSETS()
WHILE NOT LOAD_CPR()
OR NOT LOAD_DOG()
WAIT(0)
ENDWHILE
CREATE_DOGS()
CREATE_QUAD_BIKE_SCENE()
CREATE_JOGGERS()
UNLOAD_ALL_MODELS()
CLEAR_PED_TASKS(PLAYER_PED_ID())
SET_ENTITY_COORDS(PLAYER_PED_ID(), <<-2001.27, -514.18, 11>>)
SET_ENTITY_HEADING(PLAYER_PED_ID(), 19.95)
IF IS_PED_UNINJURED(MARY_ANN)
CLEAR_PED_TASKS(MARY_ANN)
SET_ENTITY_COORDS(MARY_ANN, <<-1986.93, -526.39, 11.70>>)
SET_ENTITY_HEADING(MARY_ANN, 44.46)
ENDIF
TURN_ROADS_ON()
KEEP_RUNNING(MS_DEBUG_NEAR_FINISH_LINE)
BREAK
ENDSWITCH
SET_PED_ON_THE_GROUND(MARY_ANN)
SET_PED_ON_THE_GROUND(PLAYER_PED_ID())
IF DOES_ENTITY_EXIST(MARY_ANN)
AND DOES_ENTITY_EXIST(PLAYER_PED_ID())
DETERMINE_CLOSEST_WAYPOINTS()
DEAL_WITH_THE_RACE_TRACKING()
ENDIF
IF IS_REPLAY_BEING_SET_UP()
DEBUG_PRINTSTRING("JUMP_TO_STAGE: replay being set up")
END_REPLAY_SETUP()
// This stuff wouldn't be done before because of the replay being set up
SIMULATE_PLAYER_INPUT_GAIT(PLAYER_ID(), PEDMOVEBLENDRATIO_RUN, 5000)
FORCE_PED_MOTION_STATE(PLAYER_PED_ID(), MS_ON_FOOT_RUN, TRUE, FAUS_DEFAULT)
SET_CURRENT_PED_WEAPON(PLAYER_PED_ID(), WEAPONTYPE_UNARMED, TRUE)
wait(1000)
RC_END_Z_SKIP()
ELSE
DEBUG_PRINTSTRING("JUMP_TO_STAGE: replay not being set up")
IF missionStage = MS_CUTSCENE
WHILE NOT RC_IS_CUTSCENE_OK_TO_START()
IF CAN_REQUEST_ASSETS_FOR_CUTSCENE_ENTITY()
IF IS_ENTITY_ALIVE(MARY_ANN)
DEBUG_PRINTSTRING("Trying to set Mary Ann component variation")
SET_CUTSCENE_PED_COMPONENT_VARIATION_FROM_PED("Mary_Ann", MARY_ANN, CS_MARYANN)
ENDIF
ENDIF
RC_REQUEST_CUTSCENE("ef_1_rcm")
WAIT(0)
ENDWHILE
ELSE
wait(1000)
RC_END_Z_SKIP()
ENDIF
ENDIF
ENDPROC
// ===========================================================================================================
// DEBUG FUNCTIONS
// ===========================================================================================================
/// PURPOSE: Check for Forced Pass or Fail
PROC DEBUG_Check_Debug_Keys()
#IF IS_DEBUG_BUILD
// Check for Pass
IF (IS_KEYBOARD_KEY_JUST_PRESSED(KEY_S))
WAIT_FOR_CUTSCENE_TO_STOP()
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
CLEAR_PED_TASKS(PLAYER_PED_ID())
ENDIF
Script_Passed()
ENDIF
// Check for Fail
IF (IS_KEYBOARD_KEY_JUST_PRESSED(KEY_F))
WAIT_FOR_CUTSCENE_TO_STOP()
TRIGGER_MUSIC_EVENT("RC6A_FAIL")
failReason = REASON_SILENT
stageStage = SS_SETUP
missionStage = MS_FAIL_WAIT_FOR_FADE
ENDIF
IF IS_KEYBOARD_KEY_JUST_PRESSED(KEY_J)
SWITCH missionStage
CASE MS_CUTSCENE
WAIT_FOR_CUTSCENE_TO_STOP()
JUMP_TO_STAGE(DEBUG_TO_START)
BREAK
CASE MS_START_RUNNING
JUMP_TO_STAGE(DEBUG_TO_ROAD)
BREAK
CASE MS_ROAD_RUNNING_SECTION
JUMP_TO_STAGE(DEBUG_TO_STEPS_DOWN)
BREAK
CASE MS_STEPS_DOWN
JUMP_TO_STAGE(DEBUG_TO_BEACH)
BREAK
CASE MS_SPRINT_TO_FINISH
IF NOT IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<-2015.758545,-501.566437,10.732570>>, <<-1992.435425,-522.269409,11.678237>>, 17.750000, FALSE, FALSE)
JUMP_TO_STAGE(DEBUG_TO_FINISH_LINE)
ELSE
RC_END_CUTSCENE_MODE()
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
CLEAR_PED_TASKS(PLAYER_PED_ID())
ENDIF
Script_Passed()
ENDIF
BREAK
CASE MS_DEBUG_NEAR_FINISH_LINE
RC_END_CUTSCENE_MODE()
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
CLEAR_PED_TASKS(PLAYER_PED_ID())
ENDIF
Script_Passed()
BREAK
CASE MS_END_CUTSCENE
RC_END_CUTSCENE_MODE()
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
CLEAR_PED_TASKS(PLAYER_PED_ID())
ENDIF
Script_Passed()
BREAK
ENDSWITCH
ENDIF
IF IS_KEYBOARD_KEY_JUST_PRESSED(KEY_P)
SWITCH missionStage
CASE MS_START_RUNNING
JUMP_TO_STAGE(DEBUG_TO_INTRO)
BREAK
CASE MS_ROAD_RUNNING_SECTION
JUMP_TO_STAGE(DEBUG_TO_START)
BREAK
CASE MS_STEPS_DOWN
JUMP_TO_STAGE(DEBUG_TO_ROAD)
BREAK
CASE MS_SPRINT_TO_FINISH
IF NOT IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<-2015.758545,-501.566437,10.732570>>, <<-1992.435425,-522.269409,11.678237>>, 17.750000, FALSE, FALSE)
JUMP_TO_STAGE(DEBUG_TO_STEPS_DOWN)
ELSE
JUMP_TO_STAGE(DEBUG_TO_BEACH)
ENDIF
BREAK
CASE MS_DEBUG_NEAR_FINISH_LINE
JUMP_TO_STAGE(DEBUG_TO_BEACH)
BREAK
CASE MS_END_CUTSCENE
JUMP_TO_STAGE(DEBUG_TO_BEACH)
BREAK
ENDSWITCH
ENDIF
IF LAUNCH_MISSION_STAGE_MENU(s_skip_menu, i_debug_jump_stage)
WAIT_FOR_CUTSCENE_TO_STOP()
INT e_stage = i_debug_jump_stage
JUMP_TO_STAGE(INT_TO_ENUM(debugSkipToMissionStage, e_stage))
ENDIF
// Update the amount of sprint time remaining in the RAG widget
fPlayerSprintRemaining = GET_PLAYER_SPRINT_TIME_REMAINING(PLAYER_ID())
#ENDIF
ENDPROC
/// PURPOSE: Handle the behaviour of the dog on the final stretch
PROC DEAL_WITH_THE_DOG()
IF IS_PED_UNINJURED(BEACH_DOG)
SWITCH beachDogState
CASE DOG_LOADING
IF LOAD_DOG()
IF NOT IS_ENTITY_ALIVE(BEACH_DOG)
BEACH_DOG = CREATE_PED(PEDTYPE_MISSION, A_C_ROTTWEILER, vPos_DOG, fDir_DOG)
SET_PED_CAN_RAGDOLL(BEACH_DOG, TRUE)
ENDIF
SET_MODEL_AS_NO_LONGER_NEEDED(A_C_ROTTWEILER)
DEBUG_PRINTSTRING("Loaded and created dog - progressing")
beachDogState = DOG_WAITING
ENDIF
BREAK
CASE DOG_WAITING
IF NOT IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
IF iNum_PlayerClosestWaypoint = 109
TASK_FOLLOW_TO_OFFSET_OF_ENTITY(BEACH_DOG, PLAYER_PED_ID(), <<-2, 2, 0>>, 2.5, -1, 0.2)
beachDogState = DOG_FOLLOWING_PLAYER
ENDIF
ENDIF
BREAK
ENDSWITCH
ENDIF
ENDPROC
/// PURPOSE: Check to see if the player has threatened any ped involved in the CPR synced scene
FUNC BOOL HAS_PLAYER_THREATENED_THE_CPR_SCENE()
IF HAS_PLAYER_THREATENED_PED(QUAD_DRIVER)
OR HAS_PLAYER_THREATENED_PED(INJURED_PED)
OR HAS_PLAYER_THREATENED_PED(cprWatcher1)
OR HAS_PLAYER_THREATENED_PED(cprWatcher2)
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE: Handle the overall behaviour and events in the CPR synced scene by the beach
PROC DEAL_WITH_THE_QUAD()
SWITCH cprState
CASE CPR_LOADING
IF LOAD_CPR()
DEBUG_PRINTSTRING("CPR scene resources loaded - progressing")
CREATE_QUAD_BIKE_SCENE()
cprState = CPR_WAITING
ENDIF
BREAK
CASE CPR_WAITING
IF iCURRENT_RACE_POS >= 7
IF IS_VEHICLE_OK(CHEAT_QUAD)
IF IS_PED_UNINJURED(QUAD_DRIVER)
AND IS_PED_UNINJURED(INJURED_PED)
OPEN_SEQUENCE_TASK(seq)
TASK_VEHICLE_FOLLOW_WAYPOINT_RECORDING(NULL, CHEAT_QUAD, "Fanatic1Quad", DF_SteerAroundPeds, 14)
TASK_LEAVE_VEHICLE(NULL, CHEAT_QUAD)
TASK_LOOK_AT_ENTITY(NULL, INJURED_PED, -1)
TASK_GO_STRAIGHT_TO_COORD(NULL, GET_ENTITY_COORDS(INJURED_PED), 1.8)//GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(INJURED_PED, <<-0.5, 0, 0>>), 1.8)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(QUAD_DRIVER, seq)
CLEAR_SEQUENCE_TASK(seq)
SET_VEHICLE_FORWARD_SPEED(CHEAT_QUAD, 5)
SET_VEHICLE_AS_NO_LONGER_NEEDED(CHEAT_QUAD)
cprState = CPR_GOING_TO_SCENE
ENDIF
ENDIF
ENDIF
BREAK
CASE CPR_GOING_TO_SCENE
IF IS_PED_UNINJURED(QUAD_DRIVER)
AND IS_PED_UNINJURED(INJURED_PED)
IF IS_PED_RAGDOLL(INJURED_PED)
cprState = CPR_INTERUPTED
ENDIF
IF GET_DISTANCE_BETWEEN_ENTITIES(INJURED_PED, QUAD_DRIVER) < 2
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(QUAD_DRIVER, TRUE)
CPRSynchSceneID = CREATE_SYNCHRONIZED_SCENE(vPos_CPRScene, vRot_CPRScene)
TASK_SYNCHRONIZED_SCENE(QUAD_DRIVER, CPRSynchSceneID, "mini@cpr@char_a@cpr_def", "cpr_intro", SLOW_BLEND_IN, NORMAL_BLEND_OUT, SYNCED_SCENE_USE_PHYSICS, RBF_NONE, SLOW_BLEND_IN)
TASK_SYNCHRONIZED_SCENE(INJURED_PED, CPRSynchSceneID, "mini@cpr@char_b@cpr_def", "cpr_intro", NORMAL_BLEND_IN, NORMAL_BLEND_OUT, SYNCED_SCENE_DONT_INTERRUPT)
cprState = CPR_INTRO
ENDIF
ENDIF
BREAK
CASE CPR_INTRO
IF IS_PED_UNINJURED(QUAD_DRIVER)
AND IS_PED_UNINJURED(INJURED_PED)
IF IS_PED_RAGDOLL(QUAD_DRIVER)
OR IS_PED_RAGDOLL(INJURED_PED)
cprState = CPR_INTERUPTED
ELSE
IF GET_SYNCHRONIZED_SCENE_PHASE(CPRSynchSceneID) > 0.99
CPRSynchSceneID = CREATE_SYNCHRONIZED_SCENE(vPos_CPRScene, vRot_CPRScene)
TASK_SYNCHRONIZED_SCENE(QUAD_DRIVER, CPRSynchSceneID, "mini@cpr@char_a@cpr_str", "cpr_pumpchest", NORMAL_BLEND_IN, NORMAL_BLEND_OUT, SYNCED_SCENE_USE_PHYSICS, RBF_NONE)
TASK_SYNCHRONIZED_SCENE (INJURED_PED, CPRSynchSceneID, "mini@cpr@char_b@cpr_str", "cpr_pumpchest", NORMAL_BLEND_IN, NORMAL_BLEND_OUT, SYNCED_SCENE_DONT_INTERRUPT, RBF_NONE)
SET_SYNCHRONIZED_SCENE_LOOPED(CPRSynchSceneID, TRUE)
cprState = CPR_IDLE
ENDIF
ENDIF
IF HAS_PLAYER_THREATENED_THE_CPR_SCENE()
IF GET_SYNCHRONIZED_SCENE_PHASE(CPRSynchSceneID) > 0.23
cprState = CPR_GETTING_UP
ELSE
OPEN_SEQUENCE_TASK(seq)
TASK_LOOK_AT_ENTITY(NULL, PLAYER_PED_ID(), -1)
TASK_SMART_FLEE_PED(NULL, PLAYER_PED_ID(), 80, -1)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(QUAD_DRIVER, seq)
CLEAR_SEQUENCE_TASK(seq)
IF IS_PED_UNINJURED(cprWatcher1)
OPEN_SEQUENCE_TASK(seq)
TASK_PAUSE(NULL, 200)
TASK_SMART_FLEE_PED(NULL, PLAYER_PED_ID(), 80, -1)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(cprWatcher1, seq)
CLEAR_SEQUENCE_TASK(seq)
ENDIF
IF IS_PED_UNINJURED(cprWatcher2)
OPEN_SEQUENCE_TASK(seq)
TASK_PAUSE(NULL, 500)
TASK_SMART_FLEE_PED(NULL, PLAYER_PED_ID(), 80, -1)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(cprWatcher2, seq)
CLEAR_SEQUENCE_TASK(seq)
ENDIF
cprState = CPR_FLEE
ENDIF
ENDIF
ENDIF
BREAK
CASE CPR_IDLE
IF IS_PED_UNINJURED(QUAD_DRIVER)
AND IS_PED_UNINJURED(INJURED_PED)
IF IS_PED_RAGDOLL(QUAD_DRIVER)
OR IS_PED_RAGDOLL(INJURED_PED)
cprState = CPR_INTERUPTED
ELSE
IF HAS_PLAYER_THREATENED_THE_CPR_SCENE()
cprState = CPR_GETTING_UP
ENDIF
ENDIF
ENDIF
BREAK
CASE CPR_GETTING_UP
IF IS_PED_UNINJURED(QUAD_DRIVER)
AND NOT IS_PED_FLEEING(QUAD_DRIVER)
OPEN_SEQUENCE_TASK(seq)
TASK_LOOK_AT_ENTITY(NULL, PLAYER_PED_ID(), -1)
TASK_PLAY_ANIM(NULL, "rcmfanatic1", "KNEEL_EXIT", SLOW_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_EXIT_AFTER_INTERRUPTED)
TASK_SMART_FLEE_PED(NULL, PLAYER_PED_ID(), 80, -1)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(QUAD_DRIVER, seq)
CLEAR_SEQUENCE_TASK(seq)
ENDIF
IF IS_PED_UNINJURED(cprWatcher1)
AND NOT IS_PED_FLEEING(cprWatcher1)
OPEN_SEQUENCE_TASK(seq)
TASK_PAUSE(NULL, 200)
TASK_SMART_FLEE_PED(NULL, PLAYER_PED_ID(), 80, -1)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(cprWatcher1, seq)
CLEAR_SEQUENCE_TASK(seq)
ENDIF
IF IS_PED_UNINJURED(cprWatcher2)
AND NOT IS_PED_FLEEING(cprWatcher2)
OPEN_SEQUENCE_TASK(seq)
TASK_PAUSE(NULL, 500)
TASK_SMART_FLEE_PED(NULL, PLAYER_PED_ID(), 80, -1)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(cprWatcher2, seq)
CLEAR_SEQUENCE_TASK(seq)
ENDIF
IF IS_PED_UNINJURED(INJURED_PED)
SET_ENTITY_HEALTH(INJURED_PED, 0)
ENDIF
cprState = CPR_FLEE
BREAK
CASE CPR_INTERUPTED
IF IS_PED_UNINJURED(QUAD_DRIVER)
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(QUAD_DRIVER, FALSE)
OPEN_SEQUENCE_TASK(seq)
IF NOT IS_PED_RAGDOLL(QUAD_DRIVER)
TASK_PLAY_ANIM(NULL, "rcmfanatic1", "KNEEL_EXIT", SLOW_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_EXIT_AFTER_INTERRUPTED)
ENDIF
TASK_LOOK_AT_ENTITY(NULL, PLAYER_PED_ID(), -1)
TASK_TURN_PED_TO_FACE_ENTITY(NULL, PLAYER_PED_ID(), 0)
// TASK_PLAY_ANIM(NULL, "GESTURES@MALE", "HOW_COULD_YOU", NORMAL_BLEND_IN, SLOW_BLEND_OUT, -1, AF_UPPERBODY)
TASK_LOOK_AT_ENTITY(NULL, INJURED_PED, -1)
IF GET_DISTANCE_BETWEEN_ENTITIES(QUAD_DRIVER, INJURED_PED) > 2
TASK_FOLLOW_NAV_MESH_TO_COORD(NULL, GET_ENTITY_COORDS(INJURED_PED), 1, DEFAULT_TIME_BEFORE_WARP, 1.5)
ENDIF
TASK_TURN_PED_TO_FACE_ENTITY(NULL, INJURED_PED, 0)
TASK_USE_MOBILE_PHONE_TIMED(NULL, 10000)
TASK_LOOK_AT_ENTITY(NULL, PLAYER_PED_ID(), -1)
TASK_TURN_PED_TO_FACE_ENTITY(NULL, PLAYER_PED_ID(), -1)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(QUAD_DRIVER, seq)
CLEAR_SEQUENCE_TASK(seq)
ENDIF
IF IS_PED_UNINJURED(cprWatcher1)
STOP_ANIM_PLAYBACK(cprWatcher1, AF_PRIORITY_LOW)
TASK_LOOK_AT_ENTITY(cprWatcher1, INJURED_PED, 2000)
TASK_TURN_PED_TO_FACE_ENTITY(cprWatcher1, INJURED_PED)
SAFE_RELEASE_PED(cprWatcher1)
ENDIF
IF IS_PED_UNINJURED(cprWatcher2)
STOP_ANIM_PLAYBACK(cprWatcher2, AF_PRIORITY_LOW)
TASK_LOOK_AT_ENTITY(cprWatcher2, INJURED_PED, 2000)
TASK_TURN_PED_TO_FACE_ENTITY(cprWatcher2, INJURED_PED)
SAFE_RELEASE_PED(cprWatcher2)
ENDIF
IF IS_PED_UNINJURED(INJURED_PED)
SET_ENTITY_HEALTH(INJURED_PED, 0)
ENDIF
cprState = CPR_WATCHING_PLAYER
BREAK
CASE CPR_WATCHING_PLAYER
IF IS_PED_UNINJURED(QUAD_DRIVER)
if GET_SCRIPT_TASK_STATUS(QUAD_DRIVER, SCRIPT_TASK_DUCK) <> PERFORMING_TASK
AND GET_SCRIPT_TASK_STATUS(QUAD_DRIVER, SCRIPT_TASK_DUCK) <> WAITING_TO_START_TASK
AND IS_PED_RAGDOLL(QUAD_DRIVER)
OPEN_SEQUENCE_TASK(seq)
TASK_LOOK_AT_ENTITY(NULL, PLAYER_PED_ID(), -1)
TASK_TURN_PED_TO_FACE_ENTITY(NULL, PLAYER_PED_ID(), 0)
// TASK_PLAY_ANIM(NULL, "GESTURES@MALE", "HOW_COULD_YOU", NORMAL_BLEND_IN, SLOW_BLEND_OUT, -1, AF_UPPERBODY)
TASK_LOOK_AT_ENTITY(NULL, INJURED_PED, -1)
IF GET_DISTANCE_BETWEEN_ENTITIES(QUAD_DRIVER, INJURED_PED) > 2
TASK_FOLLOW_NAV_MESH_TO_COORD(NULL, GET_ENTITY_COORDS(INJURED_PED), 1, DEFAULT_TIME_BEFORE_WARP, 1.5)
ENDIF
TASK_TURN_PED_TO_FACE_ENTITY(NULL, INJURED_PED, 0)
TASK_USE_MOBILE_PHONE_TIMED(NULL, 10000)
TASK_LOOK_AT_ENTITY(NULL, PLAYER_PED_ID(), -1)
TASK_TURN_PED_TO_FACE_ENTITY(NULL, PLAYER_PED_ID(), -1)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(QUAD_DRIVER, seq)
CLEAR_SEQUENCE_TASK(seq)
ENDIF
ENDIF
IF HAS_PLAYER_THREATENED_THE_CPR_SCENE()
IF IS_PED_UNINJURED(QUAD_DRIVER)
AND NOT IS_PED_FLEEING(QUAD_DRIVER)
TASK_SMART_FLEE_PED(QUAD_DRIVER, PLAYER_PED_ID(), 80, -1)
ENDIF
IF IS_PED_UNINJURED(cprWatcher1)
AND NOT IS_PED_FLEEING(cprWatcher1)
TASK_SMART_FLEE_PED(cprWatcher1, PLAYER_PED_ID(), 80, -1)
ENDIF
IF IS_PED_UNINJURED(cprWatcher2)
AND NOT IS_PED_FLEEING(cprWatcher2)
TASK_SMART_FLEE_PED(cprWatcher2, PLAYER_PED_ID(), 80, -1)
ENDIF
cprState = CPR_FLEE
ENDIF
BREAK
CASE CPR_FLEE
BREAK
ENDSWITCH
IF IS_PED_UNINJURED(cprWatcher1)
and NOT IS_PED_FLEEING(cprWatcher1)
IF IS_PED_RAGDOLL(cprWatcher1)
CLEAR_PED_TASKS(cprWatcher1)
SAFE_RELEASE_PED(cprWatcher1)
ENDIF
ENDIF
IF IS_PED_UNINJURED(cprWatcher2)
and NOT IS_PED_FLEEING(cprWatcher2)
IF IS_PED_RAGDOLL(cprWatcher2)
CLEAR_PED_TASKS(cprWatcher2)
SAFE_RELEASE_PED(cprWatcher2)
ENDIF
ENDIF
IF IS_PED_UNINJURED(INJURED_PED)
ADD_SHOCKING_EVENT_FOR_ENTITY(EVENT_SHOCKING_DEAD_BODY, INJURED_PED, 1)
ENDIF
ENDPROC
/// PURPOSE: Handle the two final jogging peds at the end of the final stretch of the race
PROC DEAL_WITH_THE_TWO_FINAL_PEDS()
// Use this function to check the first set of two joggers near the start and make them flee if the player bumps into them
INT j
FOR j = 0 TO 1
IF IS_PED_UNINJURED(OtherJoggers[j].thisIndex)
AND IS_PED_RAGDOLL(OtherJoggers[j].thisIndex)
CLEAR_PED_TASKS(OtherJoggers[j].thisIndex)
OPEN_SEQUENCE_TASK(seq)
IF GET_DISTANCE_BETWEEN_ENTITIES(OtherJoggers[j].thisIndex, PLAYER_PED_ID()) < GET_DISTANCE_BETWEEN_ENTITIES(OtherJoggers[j].thisIndex, MARY_ANN)
TASK_LOOK_AT_ENTITY(NULL, PLAYER_PED_ID(), -1)
TASK_TURN_PED_TO_FACE_ENTITY(NULL, PLAYER_PED_ID(), 0)
ELSE
TASK_LOOK_AT_ENTITY(NULL, MARY_ANN, -1)
TASK_TURN_PED_TO_FACE_ENTITY(NULL, MARY_ANN, 0)
ENDIF
TASK_PAUSE(NULL, 3000)
TASK_FOLLOW_NAV_MESH_TO_COORD(NULL, OtherJoggers[j].thisGoToPos2, 0.7, DEFAULT_TIME_BEFORE_WARP, 1, ENAV_NO_STOPPING)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(OtherJoggers[j].thisIndex, seq)
CLEAR_SEQUENCE_TASK(seq)
ENDIF
IF IS_ENTITY_ALIVE(OtherJoggers[j].thisIndex)
IF IS_ENTITY_TOUCHING_ENTITY(PLAYER_PED_ID(), OtherJoggers[j].thisIndex)
CLEAR_PED_TASKS(OtherJoggers[j].thisIndex)
TASK_SMART_FLEE_PED(OtherJoggers[j].thisIndex, PLAYER_PED_ID(), 200, -1, TRUE)
SAFE_RELEASE_PED(OtherJoggers[j].thisIndex)
ENDIF
ENDIF
ENDFOR
IF b_FinalPedsStartedWalking = FALSE
IF iNum_PlayerClosestWaypoint > 114
IF IS_PED_UNINJURED(OtherJoggers[2].thisIndex)
AND IS_PED_UNINJURED(OtherJoggers[3].thisIndex)
INT k
FOR k = 2 TO 3
OPEN_SEQUENCE_TASK(seq)
TASK_FOLLOW_NAV_MESH_TO_COORD(NULL, OtherJoggers[k].thisGoToPos1, 0.7, DEFAULT_TIME_BEFORE_WARP, 1, ENAV_NO_STOPPING)
TASK_FOLLOW_NAV_MESH_TO_COORD(NULL, OtherJoggers[k].thisGoToPos2, 0.7, DEFAULT_TIME_BEFORE_WARP, 1, ENAV_NO_STOPPING)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(OtherJoggers[k].thisIndex, seq)
CLEAR_SEQUENCE_TASK(seq)
ENDFOR
TASK_LOOK_AT_ENTITY(OtherJoggers[2].thisIndex, OtherJoggers[3].thisIndex, -1)
TASK_LOOK_AT_ENTITY(OtherJoggers[3].thisIndex, OtherJoggers[2].thisIndex, -1)
ENDIF
IF IS_PED_UNINJURED(BEACH_DOG)
CLEAR_PED_TASKS(BEACH_DOG)
ENDIF
b_FinalPedsStartedWalking = TRUE
ENDIF
ELSE
INT k
FOR k = 2 TO 3
IF IS_PED_UNINJURED(OtherJoggers[k].thisIndex)
AND IS_PED_RAGDOLL(OtherJoggers[k].thisIndex)
CLEAR_PED_TASKS(OtherJoggers[k].thisIndex)
OPEN_SEQUENCE_TASK(seq)
IF GET_DISTANCE_BETWEEN_ENTITIES(OtherJoggers[k].thisIndex, PLAYER_PED_ID()) < GET_DISTANCE_BETWEEN_ENTITIES(OtherJoggers[k].thisIndex, MARY_ANN)
TASK_LOOK_AT_ENTITY(NULL, PLAYER_PED_ID(), -1)
TASK_TURN_PED_TO_FACE_ENTITY(NULL, PLAYER_PED_ID(), 0)
ELSE
TASK_LOOK_AT_ENTITY(NULL, MARY_ANN, -1)
TASK_TURN_PED_TO_FACE_ENTITY(NULL, MARY_ANN, 0)
ENDIF
TASK_PAUSE(NULL, 3000)
TASK_FOLLOW_NAV_MESH_TO_COORD(NULL, OtherJoggers[k].thisGoToPos2, 0.7, DEFAULT_TIME_BEFORE_WARP, 1, ENAV_NO_STOPPING)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(OtherJoggers[k].thisIndex, seq)
CLEAR_SEQUENCE_TASK(seq)
ENDIF
IF IS_ENTITY_ALIVE(OtherJoggers[k].thisIndex)
IF IS_ENTITY_TOUCHING_ENTITY(PLAYER_PED_ID(), OtherJoggers[k].thisIndex)
CLEAR_PED_TASKS(OtherJoggers[k].thisIndex)
TASK_SMART_FLEE_PED(OtherJoggers[k].thisIndex, PLAYER_PED_ID(), 200, -1, TRUE)
SAFE_RELEASE_PED(OtherJoggers[k].thisIndex)
ENDIF
ENDIF
ENDFOR
ENDIF
ENDPROC
/// PURPOSE: Handle the behaviour and events for the driveby fingering near the steps
PROC UPDATE_DRIVEBY_FINGERING()
IF IS_PED_UNINJURED(DRIVEBY_FINGER_CAR.Passenger)
AND IS_VEHICLE_OK(DRIVEBY_FINGER_CAR.thisCarIndex)
AND IS_PED_UNINJURED(DRIVEBY_FINGER_CAR.Driver)
SWITCH driveByState
CASE DRIVE_BY_LOAD
IF LOAD_DRIVEBY()
DEBUG_PRINTSTRING("Driveby scene resources loaded - progressing")
driveByState = DRIVE_BY_PRE_TASK
ENDIF
BREAK
CASE DRIVE_BY_PRE_TASK
// Wait here until told to progress in ROAD_RUNNING_SECTION
BREAK
CASE DRIVE_BY_SET_DRIVE_TASK
OPEN_SEQUENCE_TASK(seq)
TASK_PAUSE(NULL, 1500)
TASK_VEHICLE_DRIVE_TO_COORD(NULL, DRIVEBY_FINGER_CAR.thisCarIndex, DRIVEBY_FINGER_CAR.thisGoToPos, DRIVEBY_FINGER_CAR.thisSpeed,
DRIVINGSTYLE_NORMAL, DRIVEBY_FINGER_CAR.thisCarModel, DF_SteerAroundPeds, 10, 10)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(DRIVEBY_FINGER_CAR.Driver, seq)
CLEAR_SEQUENCE_TASK(seq)
b_DrivebyHorn = FALSE
driveByState = DRIVE_BY_DRIVE
BREAK
CASE DRIVE_BY_DRIVE
IF GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(DRIVEBY_FINGER_CAR.thisCarIndex), GET_ENTITY_COORDS(MARY_ANN)) <= 45
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
KILL_FACE_TO_FACE_CONVERSATION()
ENDIF
IF GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(DRIVEBY_FINGER_CAR.thisCarIndex), GET_ENTITY_COORDS(MARY_ANN)) <= 20
IF b_DrivebyHorn = FALSE
START_VEHICLE_HORN(DRIVEBY_FINGER_CAR.thisCarIndex, 4500)
IF IS_PED_UNINJURED(MARY_ANN)
TASK_LOOK_AT_ENTITY(MARY_ANN, DRIVEBY_FINGER_CAR.thisCarIndex, 3000, SLF_WIDEST_PITCH_LIMIT|SLF_WIDEST_YAW_LIMIT|SLF_USE_TORSO)
ENDIF
b_DrivebyHorn = TRUE
ENDIF
IF MADialogueState = MA_WITHIN_TALKING_RANGE
IF NOT IS_MESSAGE_BEING_DISPLAYED()
IF CREATE_CONVERSATION(MyLocalPedStruct, "FAN1AU", road2Conversation.rootLabel, CONV_PRIORITY_VERY_HIGH)
road2Conversation.hasBeenPlayed = TRUE
DEBUG_PRINTSTRING("Doing Mary Ann's anim...")
TASK_PLAY_ANIM(MARY_ANN, "rcmfanatic1yell", "yell_d", NORMAL_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_UPPERBODY|AF_SECONDARY)
driveByState = DRIVE_BY_SET_FINGER_TASK
MADialogueState = MA_WITHIN_TALKING_RANGE
IF MASprintState = SPRINT_ACTIVE
MASprintState = SPRINT_REDUCE
ENDIF
ENDIF
ENDIF
ELSE
IF CREATE_CONVERSATION(MyLocalPedStruct, "FAN1AU", road2Conversation.rootLabel, CONV_PRIORITY_VERY_HIGH, DO_NOT_DISPLAY_SUBTITLES)
road2Conversation.hasBeenPlayed = TRUE
DEBUG_PRINTSTRING("Doing Mary Ann's anim...")
TASK_PLAY_ANIM(MARY_ANN, "rcmfanatic1yell", "yell_d", NORMAL_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_UPPERBODY|AF_SECONDARY)
driveByState = DRIVE_BY_SET_FINGER_TASK
MADialogueState = MA_OUT_OF_TALKING_RANGE
IF MASprintState = SPRINT_ACTIVE
MASprintState = SPRINT_REDUCE
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
BREAK
CASE DRIVE_BY_SET_FINGER_TASK
CLEAR_PED_TASKS(DRIVEBY_FINGER_CAR.Driver)
OPEN_SEQUENCE_TASK(seq)
TASK_VEHICLE_DRIVE_WANDER(NULL, DRIVEBY_FINGER_CAR.thisCarIndex, 6, DF_SteerAroundPeds)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(DRIVEBY_FINGER_CAR.Driver, seq)
CLEAR_SEQUENCE_TASK(seq)
TASK_DRIVE_BY(DRIVEBY_FINGER_CAR.Passenger, MARY_ANN, NULL, <<0,0,0>>, 25, 100, FALSE, FIRING_PATTERN_FULL_AUTO)
iOneLinerTimer = GET_GAME_TIMER() - 3000 // Reset the one-liner timer so there's a gap after Mary Ann finishes her above line
driveByState = DRIVE_BY_FINGERING
BREAK
CASE DRIVE_BY_FINGERING
IF IS_ENTITY_PLAYING_ANIM(MARY_ANN, "rcmfanatic1yell", "yell_d")
IF GET_ENTITY_ANIM_CURRENT_TIME(MARY_ANN, "rcmfanatic1yell", "yell_d") > 0.44
CLEAR_PED_SECONDARY_TASK(MARY_ANN)
iDrivebyTimer = GET_GAME_TIMER()
driveByState = DRIVE_BY_RELEASE
TURN_ROADS_ON()
ENDIF
ELSE // Just in case the anim doesn't play for some reason...
iDrivebyTimer = GET_GAME_TIMER()
driveByState = DRIVE_BY_RELEASE
TURN_ROADS_ON()
ENDIF
BREAK
CASE DRIVE_BY_RELEASE
IF (GET_GAME_TIMER() - iDrivebyTimer) > 3000
IF IS_PED_UNINJURED(DRIVEBY_FINGER_CAR.Driver)
IF IS_VEHICLE_OK(DRIVEBY_FINGER_CAR.thisCarIndex)
// IF IS_PED_UNINJURED(DRIVEBY_FINGER_CAR.Passenger)
// CLEAR_PED_TASKS(DRIVEBY_FINGER_CAR.Passenger)
// ENDIF
CLEAR_PED_TASKS(DRIVEBY_FINGER_CAR.Driver)
CLEAR_PED_SECONDARY_TASK(DRIVEBY_FINGER_CAR.Driver)
TASK_VEHICLE_DRIVE_WANDER(DRIVEBY_FINGER_CAR.Driver, DRIVEBY_FINGER_CAR.thisCarIndex, 15, DF_SteerAroundPeds | DRIVINGMODE_AVOIDCARS_OBEYLIGHTS)
SET_PED_KEEP_TASK(DRIVEBY_FINGER_CAR.Driver, TRUE)
SAFE_RELEASE_PED(DRIVEBY_FINGER_CAR.Driver)
SAFE_RELEASE_VEHICLE(DRIVEBY_FINGER_CAR.thisCarIndex)
ENDIF
ENDIF
SAFE_RELEASE_PED(DRIVEBY_FINGER_CAR.Passenger)
SAFE_RELEASE_PED(FOLLOWING_CAR.Driver)
IF IS_PED_UNINJURED(FOLLOWING_CAR.Passenger)
DEBUG_PRINTSTRING("*** Clearing driveby task and releasing")
CLEAR_PED_TASKS(FOLLOWING_CAR.Passenger)
SAFE_RELEASE_PED(FOLLOWING_CAR.Passenger, TRUE)
ENDIF
SAFE_RELEASE_VEHICLE(FOLLOWING_CAR.thisCarIndex)
ENDIF
BREAK
ENDSWITCH
ENDIF
ENDPROC
/// PURPOSE:
/// Manages the playback of the dynamic heartbeat audio during the mission
PROC DEAL_WITH_HEARTBEAT_AUDIO()
IF NOT bHeartbeatStarted
IF iCURRENT_RACE_POS > 3
PLAY_SOUND_FRONTEND(iHeartbeatAudioID, "HEARTBEAT", "FANATIC_SOUNDSET")
bHeartbeatStarted = TRUE
ENDIF
ENDIF
ENDPROC
SEQUENCE_INDEX seq_michael
PROC DEAL_WITH_MICHAEL_OUT_OF_BREATH()
ANIM_DATA none
IF b_DoneOutOfBreath = FALSE
IF GET_SCRIPT_TASK_STATUS(PLAYER_PED_ID(), SCRIPT_TASK_PERFORM_SEQUENCE) != PERFORMING_TASK
AND GET_SCRIPT_TASK_STATUS(PLAYER_PED_ID(), SCRIPT_TASK_PERFORM_SEQUENCE) != WAITING_TO_START_TASK
OPEN_SEQUENCE_TASK(seq_michael)
TASK_SCRIPTED_ANIMATION(NULL, adBreathEnter, none, none)
TASK_SCRIPTED_ANIMATION(NULL, adBreathIdle1, none, none)
TASK_SCRIPTED_ANIMATION(NULL, adBreathIdle2, none, none)
TASK_SCRIPTED_ANIMATION(NULL, adBreathIdle3, none, none)
// TASK_PLAY_ANIM(NULL, "rcmfanatic1out_of_breath", "p_zero_tired_enter", NORMAL_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_SECONDARY|AF_UPPERBODY|AF_PRIORITY_MEDIUM)
// TASK_PLAY_ANIM(NULL, "rcmfanatic1out_of_breath", "p_zero_tired_01", NORMAL_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_SECONDARY|AF_UPPERBODY|AF_PRIORITY_MEDIUM)
// TASK_PLAY_ANIM(NULL, "rcmfanatic1out_of_breath", "p_zero_tired_02", NORMAL_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_SECONDARY|AF_UPPERBODY|AF_PRIORITY_MEDIUM)
// TASK_PLAY_ANIM(NULL, "rcmfanatic1out_of_breath", "p_zero_tired_01", NORMAL_BLEND_IN, SLOW_BLEND_OUT, -1, AF_SECONDARY|AF_UPPERBODY|AF_LOOPING|AF_PRIORITY_MEDIUM)
CLOSE_SEQUENCE_TASK(seq_michael)
TASK_PERFORM_SEQUENCE(PLAYER_PED_ID(), seq_michael)
//SET_ANIM_FILTER(PLAYER_PED_ID(), "UpperbodyFeathered_NoLeftArm_filter" , AF_PRIORITY_MEDIUM, TRUE)
DEBUG_PRINTSTRING("Starting out of breath anim loop")
b_DoneOutOfBreath = TRUE
CLEAR_SEQUENCE_TASK(seq_michael)
ENDIF
ELSE
//SET_ANIM_FILTER(PLAYER_PED_ID(), "UpperbodyFeathered_NoLeftArm_filter" , AF_PRIORITY_MEDIUM, TRUE)
IF IS_PED_IN_VEHICLE(PLAYER_PED_ID(), MAS_BIKE, TRUE)
IF IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(), "rcmfanatic1out_of_breath", "p_zero_tired_enter")
OR IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(), "rcmfanatic1out_of_breath", "p_zero_tired_01")
OR IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(), "rcmfanatic1out_of_breath", "p_zero_tired_02")
CLEAR_PED_TASKS(PLAYER_PED_ID())
ENDIF
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Make Mary Ann continually face the player if she's playing her "jogging_on_spot" animation
PROC DEAL_WITH_MARY_ANN_FACING_PLAYER()
IF IS_ENTITY_ALIVE(MARY_ANN)
IF IS_ENTITY_PLAYING_ANIM(MARY_ANN, "rcmfanatic1", "jogging_on_spot")
// MATHS
VECTOR n
VECTOR b = NORMALISE_VECTOR(GET_ENTITY_COORDS(PLAYER_PED_ID()) - GET_ENTITY_COORDS(MARY_ANN))
VECTOR a = GET_ENTITY_FORWARD_VECTOR(MARY_ANN)
FLOAT t = 0.25
// AARON IS A FUCKING MATHS WIZARD
n = a + ((b - a) * t)
SET_ENTITY_HEADING(MARY_ANN, GET_HEADING_FROM_COORDS(<<0, 0, 0>>, n))
ENDIF
ENDIF
ENDPROC
/// PURPOSE: Handle things if the player decides to jack a vehicle during the race
PROC STAGE_PLAYER_IN_VEHICLE()
SWITCH stageStage
CASE SS_SETUP
DEBUG_PRINTSTRING("SETUP PLAYER IN VEHICLE STATE")
IF IS_SCRIPTED_CONVERSATION_ONGOING()
PAUSE_SCRIPTED_CONVERSATION(FALSE)
ENDIF
IF DOES_BLIP_EXIST(DESTINATION_BLIP)
SET_BLIP_ALPHA(DESTINATION_BLIP, 0)
ENDIF
CLEAR_PRINTS()
IF IS_WAYPOINT_PLAYBACK_GOING_ON_FOR_PED(MARY_ANN)
WAYPOINT_PLAYBACK_PAUSE(MARY_ANN, TRUE)
ENDIF
TASK_FOLLOW_TO_OFFSET_OF_ENTITY(MARY_ANN, PLAYER_PED_ID(), <<0,0,0>>, 3, -1, 3)
iVehicleFailTimer = GET_GAME_TIMER()
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
DEBUG_PRINTSTRING("stop scripted conversation at STAGE_PLAYER_IN_VEHICLE")
KILL_FACE_TO_FACE_CONVERSATION_DO_NOT_FINISH_LAST_LINE()
ENDIF
bMARY_ANN_CHASING_YOU_IN_CAR = TRUE
DEBUG_PRINTSTRING("STARTING PLAYER IN VEHICLE LOOP")
stageStage = SS_STAGE
BREAK
CASE SS_STAGE
IF bMARY_ANN_CHASING_YOU_IN_CAR
IF GET_DISTANCE_BETWEEN_PEDS(PLAYER_PED_ID(), MARY_ANN) < 4
CLEAR_PED_TASKS(MARY_ANN)
TASK_TURN_PED_TO_FACE_ENTITY(MARY_ANN, PLAYER_PED_ID(), -1)
bMARY_ANN_CHASING_YOU_IN_CAR = FALSE
ENDIF
ELSE
IF GET_DISTANCE_BETWEEN_PEDS(PLAYER_PED_ID(), MARY_ANN) > 5
CLEAR_PED_TASKS(MARY_ANN)
TASK_FOLLOW_TO_OFFSET_OF_ENTITY(MARY_ANN, PLAYER_PED_ID(), <<0,0,0>>, 3, -1, 3)
bMARY_ANN_CHASING_YOU_IN_CAR = TRUE
ENDIF
ENDIF
IF (GET_GAME_TIMER() - iVehicleFailTimer) > 4000
TRIGGER_MUSIC_EVENT("RC6A_FAIL")
failReason = FAIL_IN_CAR
stageStage = SS_SETUP
missionstage = MS_FAIL_WAIT_FOR_FADE
ENDIF
IF NOT IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
CLEAR_PRINTS()
IF NOT IS_STRING_NULL(sFANATIC_ROUTE)
IF GET_IS_WAYPOINT_RECORDING_LOADED(sFANATIC_ROUTE)
OPEN_SEQUENCE_TASK(seq)
TASK_LOOK_AT_ENTITY(NULL, PLAYER_PED_ID(), -1, SLF_DEFAULT)
TASK_FOLLOW_NAV_MESH_TO_COORD(null, GET_COORD_FURTHER_ALONG_ROUTE(), 3)
TASK_FOLLOW_WAYPOINT_RECORDING(NULL, sFANATIC_ROUTE, GET_MARY_ANNS_NEXT_WAYPOINT(), EWAYPOINT_DEFAULT | EWAYPOINT_VEHICLES_USE_AI_SLOWDOWN | EWAYPOINT_ALLOW_STEERING_AROUND_PEDS, -1)
TASK_LOOK_AT_ENTITY(NULL, PLAYER_PED_ID(), -1)
TASK_PLAY_ANIM(null, "move_f@runner", "idle", SLOW_BLEND_IN, SLOW_BLEND_OUT, -1, AF_LOOPING)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(MARY_ANN, seq)
CLEAR_SEQUENCE_TASK(seq)
ENDIF
ENDIF
stageStage = SS_STAGE
missionStage = currentMissionStage
IF DOES_BLIP_EXIST(DESTINATION_BLIP)
SET_BLIP_ALPHA(DESTINATION_BLIP, 255)
ENDIF
RESTART_SCRIPTED_CONVERSATION()
ENDIF
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE: Check if the player has skipped a checkpoint, and return true if the distance between them is over the distance passed in
FUNC BOOL PLAYER_SKIPPED_CHECKPOINT(FLOAT distance)
IF iCURRENT_RACE_POS < iMaxRacePositions - 1
INT closestWaypointToBlip
WAYPOINT_RECORDING_GET_CLOSEST_WAYPOINT(sFANATIC_ROUTE, RACE_POSITIONS[iCURRENT_RACE_POS], closestWaypointToBlip)
if closestWaypointToBlip < iNum_PlayerClosestWaypoint
IF GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), RACE_POSITIONS[iCURRENT_RACE_POS]) > distance
RETURN TRUE
ENDIF
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE: Check if the player has abandoned the race route by a significant margin, or if the distance between them and Mary Ann
/// has gotten too great
PROC CHECK_IF_PLAYER_LEFT_THE_COURSE_OR_MARY_ANN()
// THIS CHECKS IF YOU LEAVE THE ROUTE BY DISTANCE CHECKING THE CLOSEST POINT ON THE WAYPOINT REC
// OR IF THE PLAYER RUNS PAST A CHECKPOINT AND CONTINUES ON THE COURSE
IF GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), vPos_PlayerClosestWaypoint) > 60
OR PLAYER_SKIPPED_CHECKPOINT(60)
TRIGGER_MUSIC_EVENT("RC6A_FAIL")
failReason = FAIL_LEFT_RACE
stageStage = SS_SETUP
missionstage = MS_FAIL_WAIT_FOR_FADE
ELSE
IF leftRaceWarning.hasBeenShown = FALSE
IF NOT IS_THIS_PRINT_BEING_DISPLAYED(leftBehindWarning.textLabel)
IF GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), vPos_PlayerClosestWaypoint) > 40
OR PLAYER_SKIPPED_CHECKPOINT(40)
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
DEBUG_PRINTSTRING("stop scripted conversation at CHECK_IF_PLAYER_LEFT_THE_COURSE_OR_MARY_ANN")
KILL_ANY_CONVERSATION()
ENDIF
CLEAR_PRINTS()
PRINT(leftRaceWarning.textLabel, DEFAULT_GOD_TEXT_TIME, 1) //Return to the ~y~race.
leftRaceWarning.hasBeenShown = TRUE
ENDIF
ENDIF
ENDIF
ENDIF
// IF THE PLAYER IS BEHIND MARY ANN CHECK HOW FAR
IF iNum_PlayerClosestWaypoint < iNum_NPCClosestWaypoint
IF GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), GET_ENTITY_COORDS(MARY_ANN)) > 70
TRIGGER_MUSIC_EVENT("RC6A_FAIL")
failReason = FAIL_YOU_DIDNT_KEEP_UP
stageStage = SS_SETUP
missionstage = MS_FAIL_WAIT_FOR_FADE
ELIF leftBehindWarning.hasBeenShown = FALSE
AND NOT IS_THIS_PRINT_BEING_DISPLAYED(leftRaceWarning.textLabel)
IF GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), GET_ENTITY_COORDS(MARY_ANN)) > 50
PRINT_NOW(leftBehindWarning.textLabel, DEFAULT_GOD_TEXT_TIME, 1) //Catch up with ~b~Mary Ann.
leftBehindWarning.hasBeenShown = TRUE
ENDIF
ENDIF
ENDIF
ENDPROC
/// PURPOSE: Check if the player has got into a vehicle during the mission
PROC CHECK_IF_PLAYER_IS_IN_A_VEHICLE()
IF missionStage <> MS_PLAYER_IN_VEHICLE
AND missionStage <> MS_FAIL_WAIT_FOR_FADE
AND missionStage <> MS_END_CUTSCENE
AND missionStage <> MS_FAIL_WAIT_FOR_FADE
AND missionStage <> MS_LOST_RACE
IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
IF vehicleWarning.hasBeenShown = FALSE
PRINT_HELP(vehicleWarning.textLabel)
vehicleWarning.hasBeenShown = TRUE
ENDIF
IF CAN_PED_SEE_PLAYER(MARY_ANN)
OR GET_DISTANCE_BETWEEN_PEDS(PLAYER_PED_ID(), MARY_ANN) < 7
currentMissionStage = missionstage
stageStage = SS_SETUP
missionStage = MS_PLAYER_IN_VEHICLE
ENDIF
ENDIF
ELIF missionStage = MS_END_CUTSCENE
// If we're in here, this is being called from END_CUTSCENE() and we need to check for the player dicking about during the unscripted scene
IF cutsceneStage <> CS_CUTSCENE_ENDS
IF IS_VEHICLE_OK(MAS_BIKE)
IF IS_PED_IN_VEHICLE(PLAYER_PED_ID(), MAS_BIKE)
b_PlayerOnMAsBike = TRUE
// IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
// KILL_FACE_TO_FACE_CONVERSATION_DO_NOT_FINISH_LAST_LINE()
// ENDIF
// IF PLAY_SINGLE_LINE_FROM_CONVERSATION(MyLocalPedStruct, "FAN1AU", "FAN1_AGGRO", "FAN1_AGGRO_1", CONV_PRIORITY_VERY_HIGH)
// CLEAR_PED_TASKS(MARY_ANN)
// TASK_SMART_FLEE_PED(MARY_ANN, PLAYER_PED_ID(), 150, -1)
// cutsceneStage = CS_CUTSCENE_ENDS
// ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Checks for Michael bumping into anyone and plays an appropriate line of dialogue if possible
PROC CHECK_PLAYER_COLLISIONS()
IF HAS_ENTITY_COLLIDED_WITH_ANYTHING(PLAYER_PED_ID())
PED_INDEX ped[32]
IF GET_PED_NEARBY_PEDS(PLAYER_PED_ID(), ped) > 0
// If the ped index exists, the player probably bumped into a ped rather than an object or whatever
IF DOES_ENTITY_EXIST(ped[0])
AND NOT IS_ENTITY_DEAD(ped[0])
IF IS_ENTITY_TOUCHING_ENTITY(PLAYER_PED_ID(), ped[0])
// Do different things depending on whether the ped is Mary Ann or an ambient civvie
IF ped[0] = MARY_ANN
DEBUG_PRINTSTRING("Player touched Mary Ann!")
if not IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF MikePushMALine.timesPlayed <= 3
IF CAN_MARY_ANN_SAY_RANDOM_LINE(MikePushMALine.dialogueLine)
DEBUG_PRINTSI("Saying MikePushMALine #", MikePushMALine.timesPlayed)
MikePushMALine.timesPlayed++
ENDIF
ENDIF
ENDIF
ELSE
DEBUG_PRINTSTRING("Player touched a civ!")
IF NOT IS_PED_IN_ANY_VEHICLE(ped[0]) // Ignore if in a vehicle, otherwise it asserts...
// We can't do this to Mary Ann very easily, but we can for civvies without causing horribleness!
IF NOT IS_PED_RAGDOLL(ped[0])
CLEAR_PED_TASKS(ped[0])
SET_PED_TO_RAGDOLL(ped[0], 800, 1500, TASK_NM_BALANCE)
VECTOR pushDir = -GET_OFFSET_FROM_ENTITY_GIVEN_WORLD_COORDS(PLAYER_PED_ID(), GET_ENTITY_COORDS(ped[0]))
APPLY_FORCE_TO_ENTITY(ped[0], APPLY_TYPE_IMPULSE, pushDir, <<0,0,0>>, GET_PED_RAGDOLL_BONE_INDEX(ped[0], RAGDOLL_SPINE), FALSE, FALSE, TRUE)
ENDIF
if not IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF MikePushPedLine.timesPlayed <= 3
IF CAN_MARY_ANN_SAY_RANDOM_LINE(MikePushPedLine.dialogueLine)
DEBUG_PRINTSI("Said MikePushPedLine #", MikePushPedLine.timesPlayed)
MikePushPedLine.timesPlayed++
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// If the player's just overtaken Mary Ann, make her try and say an overtake line if possible
PROC TRY_OVERTAKE_LINE()
IF bOvertaken = TRUE
AND (GET_GAME_TIMER() - iOvertakeTimer) < 1500 // If it's been less than 1.5s since we overtook Mary Ann, do the line
if not IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF OvertakeLines.timesPlayed <= 3
IF bOvertakenSkip = FALSE
IF CAN_MARY_ANN_SAY_RANDOM_LINE(OvertakeLines.dialogueLine)
DEBUG_PRINTSI("Said OvertakeLines #", OvertakeLines.timesPlayed)
OvertakeLines.timesPlayed++
bOvertaken = FALSE
bOvertakenSkip = true // Skip the next time we overtake to reduce frequency of dialogue (B*1416011)
iOvertakeTimer = GET_GAME_TIMER() // Make sure we can't keep playing the overtake line over and over
ENDIF
ELSE
bOvertakenSkip = FALSE
bOvertaken = FALSE
iOvertakeTimer = GET_GAME_TIMER()
ENDIF
ELSE
bOvertaken = FALSE
iOvertakeTimer = GET_GAME_TIMER()
ENDIF
ELSE
bOvertaken = FALSE
iOvertakeTimer = GET_GAME_TIMER()
ENDIF
ELSE
IF bOvertaken = TRUE // Only do this reset if necessary! (or it keeps resetting the timer and we never get any overtake lines...)
bOvertaken = FALSE
iOvertakeTimer = GET_GAME_TIMER()
ENDIF
ENDIF
ENDPROC
/// PURPOSE: Check if the player has threatened, injured or killed Mary Ann
PROC CHECK_IF_MARY_ANN_IS_INJURED_KILLED_OR_SCARED()
IF IS_ENTITY_DEAD(MARY_ANN)
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
DEBUG_PRINTSTRING("stop scripted conversation at CHECK_IF_MARY_ANN_IS_INJURED_KILLED_OR_SCARED 1")
KILL_FACE_TO_FACE_CONVERSATION_DO_NOT_FINISH_LAST_LINE()
ENDIF
DEBUG_PRINTSTRING("Mary Ann killed")
TRIGGER_MUSIC_EVENT("RC6A_FAIL")
failReason = FAIL_FANATIC_KILLED
stageStage = SS_SETUP
missionstage = MS_FAIL_WAIT_FOR_FADE
ELSE
IF HAS_ENTITY_BEEN_DAMAGED_BY_ENTITY(MARY_ANN, PLAYER_PED_ID())
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
DEBUG_PRINTSTRING("stop scripted conversation at CHECK_IF_MARY_ANN_IS_INJURED_KILLED_OR_SCARED 2")
KILL_FACE_TO_FACE_CONVERSATION_DO_NOT_FINISH_LAST_LINE()
ENDIF
DEBUG_PRINTSTRING("Mary Ann injured by player")
TRIGGER_MUSIC_EVENT("RC6A_FAIL")
failReason = FAIL_FANATIC_INJURED
stageStage = SS_SETUP
missionstage = MS_FAIL_WAIT_FOR_FADE
ENDIF
IF HAS_PED_BEEN_DAMAGED_BY_WEAPON(MARY_ANN, WEAPONTYPE_INVALID, GENERALWEAPON_TYPE_ANYWEAPON)
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
DEBUG_PRINTSTRING("stop scripted conversation at CHECK_IF_MARY_ANN_IS_INJURED_KILLED_OR_SCARED 3")
KILL_FACE_TO_FACE_CONVERSATION_DO_NOT_FINISH_LAST_LINE()
ENDIF
DEBUG_PRINTSTRING("Mary Ann injured by some form of weapon")
TRIGGER_MUSIC_EVENT("RC6A_FAIL")
failReason = FAIL_FANATIC_INJURED
stageStage = SS_SETUP
missionstage = MS_FAIL_WAIT_FOR_FADE
ENDIF
ENDIF
IF bMARY_ANN_IS_GOING_TO_RUN_SCARED = TRUE
DEBUG_PRINTSTRING("Mary Ann scared")
IF IS_ENTITY_ALIVE(MARY_ANN)
CLEAR_PED_TASKS(MARY_ANN)
ENDIF
TRIGGER_MUSIC_EVENT("RC6A_FAIL")
failReason = FAIL_FANATIC_SCARED
stageStage = SS_SETUP
missionstage = MS_FAIL_WAIT_FOR_FADE
ELSE
IF IS_ENTITY_ALIVE(MARY_ANN)
IF IS_PLAYER_SHOOTING_NEAR_PED(MARY_ANN)
OR HAS_PLAYER_THREATENED_PED(MARY_ANN)
OR IS_BULLET_IN_AREA(GET_ENTITY_COORDS(MARY_ANN), 10, FALSE)
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
DEBUG_PRINTSTRING("Killing any convo before scared convo")
KILL_FACE_TO_FACE_CONVERSATION_DO_NOT_FINISH_LAST_LINE()
ENDIF
bMARY_ANN_IS_GOING_TO_RUN_SCARED = TRUE
ENDIF
ENDIF
ENDIF
ENDPROC
/// PURPOSE: Check if Mary Ann has beaten the player to the finish line
PROC CHECK_IF_MARY_ANN_WINS_RACE()
IF missionStage <> MS_LOST_RACE // Don't want to keep resetting the Lost Race state once it's been triggered!
AND missionStage <> MS_FAIL_WAIT_FOR_FADE
IF GET_DISTANCE_BETWEEN_ENTITY_AND_COORD(MARY_ANN, vPos_FinishLine) < 3
DEBUG_PRINTSTRING("Detected Mary Ann won race")
failReason = FAIL_SHE_BEAT_YOU_TO_BIKE
stageStage = SS_SETUP
missionstage = MS_LOST_RACE
ENDIF
ENDIF
ENDPROC
/// PURPOSE: Check for all fail possibilities during the mission
PROC CHECK_FAIL_POSSIBILITIES()
IF ENUM_TO_INT(missionStage) <> ENUM_TO_INT(MS_END_CUTSCENE)
AND ENUM_TO_INT(missionStage) <> ENUM_TO_INT(MS_FAIL_WAIT_FOR_FADE)
AND ENUM_TO_INT(missionStage) > ENUM_TO_INT(MS_CUTSCENE)
IF DOES_ENTITY_EXIST(MARY_ANN)
CHECK_IF_MARY_ANN_IS_INJURED_KILLED_OR_SCARED()
CHECK_IF_PLAYER_IS_IN_A_VEHICLE()
DETERMINE_CLOSEST_WAYPOINTS()
CHECK_IF_PLAYER_LEFT_THE_COURSE_OR_MARY_ANN()
CHECK_IF_MARY_ANN_WINS_RACE()
ENDIF
ENDIF
ENDPROC
PROC CLEAR_RACE_ROUTE_OF_VEHICLES()
IF GET_IS_WAYPOINT_RECORDING_LOADED(sFANATIC_ROUTE)
INT iMaxPoints = 0
WAYPOINT_RECORDING_GET_NUM_POINTS(sFANATIC_ROUTE, iMaxPoints)
INT i = 0
FOR i = 0 to iMaxPoints
VECTOR vNewCoord = <<0,0,0>>
WAYPOINT_RECORDING_GET_COORD(sFANATIC_ROUTE, i, vNewCoord)
CLEAR_AREA_OF_VEHICLES(vNewCoord, 4)
DEBUG_PRINTSI("Clearing area around waypoint", i)
ENDFOR
ENDIF
ENDPROC
//PURPOSE: general cutscene setup
PROC GO_TO_CUTSCENE()
camCutsceneStart = CREATE_CAM("DEFAULT_SCRIPTED_CAMERA", TRUE)
SET_CAM_PARAMS(camCutsceneStart,<<-2006.4041, -505.1258, 12.1679>>, <<-8.4110, 0.0000, -152.3152>>, 50)//<<-2004.4519, -496.6223, 12.3469>>, << -11.3454, -0.0000, -160.9836 >>, 50)
RENDER_SCRIPT_CAMS(TRUE, FALSE)
SET_CAM_ACTIVE(camCutsceneStart, TRUE)
ENDPROC
//PURPOSE: Once Mary Ann reaches this position the next stage of the race begins
FUNC BOOL RACE_LEG_FINISHED(VECTOR pos)
IF IS_ENTITY_AT_COORD(MARY_ANN, pos, <<3,3,2>>)
RETURN TRUE
ENDIF
return FALSE
ENDFUNC
/// PURPOSE:
/// Handles whether the player needs to see the global stamina help message low on stamina. B*1416022.
PROC HANDLE_GLOBAL_STAMINA_HELP()
IF NOT g_savedGlobals.sRandomChars.g_bFanaticStamina
IF GET_PLAYER_SPRINT_TIME_REMAINING(PLAYER_ID()) <= 5.0
IF NOT IS_HELP_MESSAGE_BEING_DISPLAYED()
PRINT_HELP("AM_H_NOSTAM")
g_savedGlobals.sRandomChars.g_bFanaticStamina = TRUE
ENDIF
ENDIF
ENDIF
ENDPROC
/// PURPOSE: Initialise some basic elements of the mission such as the Z-skip list, the race checkpoints, and environment settings
PROC INIT()
CLEAR_PRINTS()
DEBUG_PRINTSTRING("IN INIT")
#IF IS_DEBUG_BUILD
s_skip_menu[0].sTxtLabel = "INTRO CUTSCENE"
s_skip_menu[1].sTxtLabel = "START THE RUN"
s_skip_menu[2].sTxtLabel = "RUNNING ON ROAD"
s_skip_menu[3].sTxtLabel = "RUNNING DOWN STEPS"
s_skip_menu[4].sTxtLabel = "RACE TO THE FINISH"
s_skip_menu[5].sTxtLabel = "END OF RACE"
s_skip_menu[6].sTxtLabel = "***DEBUG: Next to finish line"
#ENDIF
sFANATIC_ROUTE = "Fanatic1MaryAnn"
// CLEARS THE ROUTE OF VEHICLES, IN CASE PLAYER HAS DROPPED ANY
CLEAR_ANGLED_AREA_OF_VEHICLES(<<-1877.022217,-439.566315,47.061394>>, <<-1809.614868,-493.493958,39.585079>>, 12.750000, TRUE)
CLEAR_ANGLED_AREA_OF_VEHICLES(<<-1816.865234,-492.408051,42.839161>>, <<-1792.158447,-470.209503,38.512688>>, 12.750000, TRUE)
CLEAR_ANGLED_AREA_OF_VEHICLES(<<-1792.193726,-470.231934,42.514709>>, <<-1726.926392,-552.837463,35.241489>>, 12.750000, TRUE)
CLEAR_ANGLED_AREA_OF_VEHICLES(<<-1728.023682,-561.872070,39.497372>>, <<-1835.284546,-514.933289,26.335573>>, 19.750000, TRUE)
CLEAR_ANGLED_AREA_OF_VEHICLES(<<-1822.225586,-535.309204,31.955553>>, <<-1890.278320,-616.276367,9.657555>>, 39.750000, TRUE)
CLEAR_ANGLED_AREA_OF_VEHICLES(<<-1867.242798,-622.763000,13.383512>>, <<-2013.266968,-497.979950,9.736394>>, 23.750000, TRUE)
REMOVE_RELATIONSHIP_GROUP(relGroupFriendly)
ADD_RELATIONSHIP_GROUP("FRIENDLIES", relGroupFriendly)
SET_RELATIONSHIP_BETWEEN_GROUPS(ACQUAINTANCE_TYPE_PED_LIKE, relGroupFriendly, RELGROUPHASH_PLAYER)
SET_RELATIONSHIP_BETWEEN_GROUPS(ACQUAINTANCE_TYPE_PED_LIKE, RELGROUPHASH_PLAYER, relGroupFriendly)
ADD_PED_FOR_DIALOGUE(MyLocalPedStruct, 0, PLAYER_PED_ID(), "MICHAEL")
LOAD_OTHER_ASSETS()
//SET_PLAYER_HAS_CHANGE_CLOTHES_ON_MISSION(CHAR_MICHAEL)
IF IS_ENTITY_ALIVE(MARY_ANN)
SET_PED_RELATIONSHIP_GROUP_HASH(MARY_ANN, relGroupFriendly)
SET_PED_SEEING_RANGE(MARY_ANN, 25.0)
SET_PED_MOVEMENT_CLIPSET(MARY_ANN, "FEMALE_FAST_RUNNER")
ENDIF
CLEAR_RACE_ROUTE_OF_VEHICLES()
CREATE_CARS()
//UNLOAD_ALL_MODELS()
TURN_ROADS_ON(FALSE)
sbiWallPeds = ADD_SCENARIO_BLOCKING_AREA(<<-1979.0620, -534.3250, 10.4558>>, <<-1973.3320, -528.2116, 13.7014>>)
sbiPathPeds = ADD_SCENARIO_BLOCKING_AREA(<<-1914.7804, -591.1177, 9.8302>>, <<-1910.3289, -586.7218, 12.0195>>)
sbiMobilePed = ADD_SCENARIO_BLOCKING_AREA(<<-1991.0669, -523.5920, 10.4269>>, <<-1989.1447, -521.6824, 11.3735>>)
adBreathEnter.type = APT_SINGLE_ANIM
adBreathEnter.dictionary0 = "rcmfanatic1out_of_breath"
adBreathEnter.anim0 = "p_zero_tired_enter"
adBreathEnter.blendInDelta = REALLY_SLOW_BLEND_IN
adBreathEnter.blendOutDelta = NORMAL_BLEND_OUT
adBreathEnter.flags = AF_SECONDARY|AF_UPPERBODY
adBreathEnter.filter = GET_HASH_KEY("UpperbodyFeathered_NoLefttArm_filter")
adBreathIdle1.type = APT_SINGLE_ANIM
adBreathIdle1.dictionary0 = "rcmfanatic1out_of_breath"
adBreathIdle1.anim0 = "p_zero_tired_01"
adBreathIdle1.blendInDelta = NORMAL_BLEND_IN
adBreathIdle1.blendOutDelta = NORMAL_BLEND_OUT
adBreathIdle1.flags = AF_SECONDARY|AF_UPPERBODY
adBreathIdle1.filter = GET_HASH_KEY("UpperbodyFeathered_NoLefttArm_filter")
adBreathIdle2.type = APT_SINGLE_ANIM
adBreathIdle2.dictionary0 = "rcmfanatic1out_of_breath"
adBreathIdle2.anim0 = "p_zero_tired_02"
adBreathIdle2.blendInDelta = NORMAL_BLEND_IN
adBreathIdle2.blendOutDelta = NORMAL_BLEND_OUT
adBreathIdle2.flags = AF_SECONDARY|AF_UPPERBODY
adBreathIdle2.filter = GET_HASH_KEY("UpperbodyFeathered_NoLefttArm_filter")
adBreathIdle3.type = APT_SINGLE_ANIM
adBreathIdle3.dictionary0 = "rcmfanatic1out_of_breath"
adBreathIdle3.anim0 = "p_zero_tired_01"
adBreathIdle3.blendInDelta = NORMAL_BLEND_IN
adBreathIdle3.blendOutDelta = INSTANT_BLEND_OUT
adBreathIdle3.flags = AF_SECONDARY|AF_UPPERBODY|AF_LOOPING
adBreathIdle3.filter = GET_HASH_KEY("UpperbodyFeathered_NoLefttArm_filter")
vPos_StartOfRoadRunning = <<-1730.2838, -551.7269, 36.3939>>
vPos_StartOfBeachRunning = <<-1870.6702, -616.2423, 10.8184>>
WAYPOINT_RECORDING_GET_NUM_POINTS(sFANATIC_ROUTE, iNum_WAYPOINTS)
RACE_POSITIONS[0] = <<-1868.36, -447.84, 45.20>>
RACE_POSITIONS[1] = <<-1835.81, -468.73, 43.45>>
RACE_POSITIONS[2] = <<-1753.45, -523.30, 37.35>>
RACE_POSITIONS[3] = vPos_StartOfRoadRunning
RACE_POSITIONS[4] = <<-1755.65, -558.99, 36.11>>
RACE_POSITIONS[5] = <<-1828.99, -516.33, 27.87>> // CLOSEST TO STEPS
RACE_POSITIONS[6] = <<-1819.20, -555.86, 15.77>>
RACE_POSITIONS[7] = vPos_StartOfBeachRunning
RACE_POSITIONS[8] = <<-1918.04, -583.45, 10.76>>
RACE_POSITIONS[9] = vPos_FinishLine
iMaxRacePositions = COUNT_OF(RACE_POSITIONS)
HURRY_UP_LINE[0] = "FAN1_FALLB_1"
HURRY_UP_LINE[1] = "FAN1_FALLB_2"
RACE_LINE[0] = "FAN1_FAST_1"
RACE_LINE[1] = "FAN1_FAST_2"
RACE_LINE[2] = "FAN1_FAST_3"
MikePushMALine.dialogueLine = "FAN1_RUNIN"
MikePushPedLine.dialogueLine = "FAN1_RUNIN2"
OvertakeLines.dialogueLine = "FAN1_OVERT"
pushLine[0].dialogueLine = "FAN1_PUSH_1"
pushLine[1].dialogueLine = "FAN1_PUSH_2"
pushLine[2].dialogueLine = "FAN1_PUSH_3"
cheatedLeaptFence.dialogueLine = "FAN1_CHEAT_1"
cheatedLeaptFence.rootLabel = "FAN1_CHEAT"
cheatedRanAcrossGrass.dialogueLine = "FAN1_CHEAT_2"
cheatedRanAcrossGrass.rootLabel = "FAN1_CHEAT"
returnAfterCheatedLine.dialogueLine = "FAN1_CATCHC_1"
returnAfterCheatedLine.rootLabel = "FAN1_CATCHC"
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
IF IS_OUTFIT_SUITABLE_FOR_FANATIC_MISSION(1)
startRunConversation.rootLabel = "FAN1_STRTB"
raceConversation.rootLabel = "FAN1_BCHB"
ELSE
startRunConversation.rootLabel = "FAN1_STRTA"
raceConversation.rootLabel = "FAN1_BCHA"
ENDIF
ENDIF
road1Conversation.rootLabel = "FAN1_RD1"
road2Conversation.rootLabel = "FAN1_RD2"
leftRaceWarning.textLabel = "FATIC1_7"
leftBehindWarning.textLabel = "FATIC1_6"
vehicleWarning.textLabel = "FATIC1_H"
DEBUG_PRINTSTRING("end of init")
ENDPROC
/// PURPOSE:
/// Main state for doing the lead-in
PROC LEADIN()
// Disable controls and exit current vehicle
RC_PLAYER_TRIGGER_SCENE_LOCK_IN()
SWITCH stageStage
CASE SS_SETUP
IF NOT Is_Replay_In_Progress()
IF GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), MARY_ANN) <= 1.2
// Kill the leadin convo early if it's started
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
KILL_FACE_TO_FACE_CONVERSATION_DO_NOT_FINISH_LAST_LINE()
ENDIF
DEBUG_PRINTSTRING("Player too close to Mary Ann, starting cutscene early")
stageStage = SS_SETUP
missionStage = MS_CUTSCENE
ENDIF
IF NOT IS_GAMEPLAY_HINT_ACTIVE()
SET_GAMEPLAY_ENTITY_HINT(MARY_ANN, <<0,0,0>>, TRUE, 30000)
SET_GAMEPLAY_HINT_FOV(fHintFov)
SET_GAMEPLAY_HINT_FOLLOW_DISTANCE_SCALAR(fHintFollow)
SET_GAMEPLAY_HINT_BASE_ORBIT_PITCH_OFFSET(fHintPitchOrbit)
SET_GAMEPLAY_HINT_CAMERA_RELATIVE_SIDE_OFFSET(fHintSide)
SET_GAMEPLAY_HINT_CAMERA_RELATIVE_VERTICAL_OFFSET(fHintVert)
SET_GAMEPLAY_HINT_CAMERA_BLEND_TO_FOLLOW_PED_MEDIUM_VIEW_MODE(TRUE)
ELSE
STOP_GAMEPLAY_HINT_BEING_CANCELLED_THIS_UPDATE(TRUE)
ENDIF
REQUEST_ANIM_DICT("rcmfanatic1")
// Check for the anim dict being loaded, then if Mary Ann is in an early phase of her idle loop, then try to do the lead in convo and anims...
IF HAS_ANIM_DICT_LOADED("rcmfanatic1")
AND missionStage = MS_LEADIN // Ensure the stage is still lead-in in case the cutscene skip above occurred
IF IS_ENTITY_ALIVE(MARY_ANN)
IF IS_ENTITY_PLAYING_ANIM(MARY_ANN, "rcmfanatic1", "ef_1_rcm_mary_ann_streching_base")
IF GET_ENTITY_ANIM_CURRENT_TIME(MARY_ANN, "rcmfanatic1", "ef_1_rcm_mary_ann_streching_base") <0.1
FREEZE_ENTITY_POSITION(MARY_ANN, FALSE)
ADD_PED_FOR_DIALOGUE(MyLocalPedStruct, 3, MARY_ANN, "MARYANN")
ADD_PED_FOR_DIALOGUE(MyLocalPedStruct, 0, PLAYER_PED_ID(), "MICHAEL")
TASK_PLAY_ANIM_ADVANCED(MARY_ANN, "rcmfanatic1", "ef_1_rcm_mary_ann_leadin", <<-1878.223022,-440.518127,46.039829>>, <<0, 0, 159.97>>,
NORMAL_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_HOLD_LAST_FRAME|AF_USE_KINEMATIC_PHYSICS|AF_NOT_INTERRUPTABLE)
DEBUG_PRINTSTRING("Done Mary Ann leadin anim")
stageStage = SS_STAGE
ELSE
DEBUG_PRINTSTRING("Waiting to blend the lead-in...")
ENDIF
ENDIF
ENDIF
ENDIF
ELSE
DEBUG_PRINTSTRING("Replay in progress or in wrong area - skipping to intro")
missionStage = MS_CUTSCENE
ENDIF
BREAK
CASE SS_STAGE
IF IS_PED_UNINJURED(MARY_ANN)
IF NOT IS_GAMEPLAY_HINT_ACTIVE()
SET_GAMEPLAY_ENTITY_HINT(MARY_ANN, <<0,0,0>>, TRUE, 30000)
SET_GAMEPLAY_HINT_FOV(fHintFov)
SET_GAMEPLAY_HINT_FOLLOW_DISTANCE_SCALAR(fHintFollow)
SET_GAMEPLAY_HINT_BASE_ORBIT_PITCH_OFFSET(fHintPitchOrbit)
SET_GAMEPLAY_HINT_CAMERA_RELATIVE_SIDE_OFFSET(fHintSide)
SET_GAMEPLAY_HINT_CAMERA_RELATIVE_VERTICAL_OFFSET(fHintVert)
SET_GAMEPLAY_HINT_CAMERA_BLEND_TO_FOLLOW_PED_MEDIUM_VIEW_MODE(TRUE)
ELSE
STOP_GAMEPLAY_HINT_BEING_CANCELLED_THIS_UPDATE(TRUE)
ENDIF
IF IS_ENTITY_PLAYING_ANIM(MARY_ANN, "rcmfanatic1", "ef_1_rcm_mary_ann_leadin")
IF b_LeadInConvo = FALSE
IF CREATE_CONVERSATION(MyLocalPedStruct, "FAN1AU", "FAN1_LDI", CONV_PRIORITY_HIGH)
DEBUG_PRINTSTRING("Done Mary Ann leadin conv")
b_LeadInConvo = TRUE
ENDIF
ELSE
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
DEBUG_PRINTSTRING("Mary Ann leadin conv over")
WAIT(250) // Short wait just to add a more natural sounding pause after the final line before the CS starts
stageStage = SS_SETUP
missionStage = MS_CUTSCENE
ENDIF
ENDIF
// IF GET_ENTITY_ANIM_CURRENT_TIME(MARY_ANN, "rcmfanatic1", "ef_1_rcm_mary_ann_leadin") > 0.90
// DEBUG_PRINTSTRING("Mary Ann leadin anim over")
// stageStage = SS_SETUP
// missionStage = MS_CUTSCENE
// ENDIF
ELSE
DEBUG_PRINTSTRING("Mary Ann not playing leadin anim anymore - skip to cutscene for safety")
stageStage = SS_SETUP
missionStage = MS_CUTSCENE
ENDIF
// If player gets within 4m of Mary Ann, stop the player and make them face Mary Ann (B*231024)
IF GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), MARY_ANN) <= 4.0
SET_PLAYER_CONTROL(PLAYER_ID(), FALSE)
IF NOT IsPedPerformingTask(PLAYER_PED_ID(), SCRIPT_TASK_TURN_PED_TO_FACE_ENTITY)
TASK_TURN_PED_TO_FACE_ENTITY(PLAYER_PED_ID(), MARY_ANN)
TASK_LOOK_AT_ENTITY(PLAYER_PED_ID(), MARY_ANN, -1)
ENDIF
ENDIF
ENDIF
BREAK
ENDSWITCH
ENDPROC
FUNC BOOL DO_MICHAEL_BLEND()
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
IF CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY("Michael")
DEBUG_PRINTSTRING("*** Forcing Michael's move state")
FORCE_PED_MOTION_STATE(PLAYER_PED_ID(), MS_ON_FOOT_RUN, FALSE, FAUS_CUTSCENE_EXIT)
SIMULATE_PLAYER_INPUT_GAIT(PLAYER_ID(), PEDMOVEBLENDRATIO_RUN, 5000)
RETURN TRUE
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
PROC DO_MARY_ANN_BLEND()
IF IS_ENTITY_ALIVE(MARY_ANN)
IF CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY("Mary_Ann", IG_MARYANN)
DEBUG_PRINTSTRING("*** Forcing Mary Ann's move state")
DEBUG_PRINTSTRING("SET MARY ANNS TASK")
IF b_CutsceneSkipped
SAFE_TELEPORT_ENTITY(MARY_ANN, <<-1867.64, -446.01, 45.16>>, 229.3557)
ENDIF
OPEN_SEQUENCE_TASK(seq)
TASK_SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(NULL, TRUE)
TASK_LOOK_AT_ENTITY(NULL, PLAYER_PED_ID(), -1, SLF_DEFAULT)
TASK_FOLLOW_WAYPOINT_RECORDING(NULL, sFANATIC_ROUTE, 1, EWAYPOINT_START_FROM_CLOSEST_POINT | EWAYPOINT_VEHICLES_USE_AI_SLOWDOWN | EWAYPOINT_ALLOW_STEERING_AROUND_PEDS | EWAYPOINT_NAVMESH_BACK_TO_WAYPOINT_IF_LEFT_ROUTE , -1)
TASK_PLAY_ANIM(null, "move_f@runner", "idle", SLOW_BLEND_IN, SLOW_BLEND_OUT, -1, AF_LOOPING)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(MARY_ANN, seq)
CLEAR_SEQUENCE_TASK(seq)
FORCE_PED_MOTION_STATE(MARY_ANN, MS_ON_FOOT_RUN, FALSE, FAUS_CUTSCENE_EXIT)
ENDIF
ENDIF
ENDPROC
/// PURPOSE: Main process to handle the intro cutscene
PROC INTRO_CUTSCENE()
SWITCH stageStage
CASE SS_SETUP
DEBUG_PRINTSTRING("Intro Cutscene")
RC_REQUEST_CUTSCENE("ef_1_rcm", TRUE)
IF CAN_REQUEST_ASSETS_FOR_CUTSCENE_ENTITY()
DEBUG_PRINTSTRING("Trying to set Mary Ann component variation")
SET_CUTSCENE_PED_COMPONENT_VARIATION_FROM_PED("Mary_Ann", MARY_ANN, CS_MARYANN)
ENDIF
iCutsceneStage = 0
b_MusicTriggered = FALSE
IF CutsceneNavBlockerID = -1
CutsceneNavBlockerID = ADD_NAVMESH_BLOCKING_OBJECT(<<-1877.30, -439.70, 45.05>>, <<4, 6, 2>>, 45.0)
ENDIF
IF RC_IS_CUTSCENE_OK_TO_START()
IF IS_ENTITY_ALIVE(MARY_ANN)
REGISTER_ENTITY_FOR_CUTSCENE(MARY_ANN, "Mary_Ann", CU_ANIMATE_EXISTING_SCRIPT_ENTITY, IG_MARYANN)
DEBUG_PRINTSTRING("Registered Mary Ann")
ENDIF
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
REGISTER_ENTITY_FOR_CUTSCENE(PLAYER_PED_ID(), "Michael", CU_ANIMATE_EXISTING_SCRIPT_ENTITY)
DEBUG_PRINTSTRING("Registered Michael")
ENDIF
sbiCutscene = ADD_SCENARIO_BLOCKING_AREA(<<-1926.6536, -387.8897, 46.7354>>, <<-1897.3219, -374.5802, 51.0241>>)
// Cleanup launcher which will remove lead-in blip
RC_CLEANUP_LAUNCHER()
RESET_PLAYER_STAMINA(PLAYER_ID())
STOP_GAMEPLAY_HINT()
REPLAY_START_EVENT(REPLAY_IMPORTANCE_LOW)
//CLEAR_AREA_OF_VEHICLES(<<-1793.82, -472.73, 39.58>>, 40.0, DEFAULT, DEFAULT, TRUE, TRUE)
START_CUTSCENE()
WAIT(0)
SAFE_FADE_SCREEN_IN_FROM_BLACK(DEFAULT, FALSE)
RESOLVE_VEHICLES_INSIDE_ANGLED_AREA_WITH_SIZE_LIMIT(<<-1873.525513,-441.621063,44.693626>>, <<-1882.030029,-436.991730,47.483791>>, 7.0,
<<-1875.09, -431.08, 45.21>>, 236.42, GET_DEFAULT_ALLOWABLE_VEHICLE_SIZE_VECTOR())
RESOLVE_VEHICLES_INSIDE_ANGLED_AREA_WITH_SIZE_LIMIT(<<-1875.814819,-443.119110,49.135151>>, <<-1808.560669,-491.788696,36.580292>>, 11.0,
<<-1875.09, -431.08, 45.21>>, 236.42, GET_DEFAULT_ALLOWABLE_VEHICLE_SIZE_VECTOR())
RC_START_CUTSCENE_MODE(<<-1877.23, -440.46, 45.07>>, TRUE, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT)
INIT()
CLEAR_ANGLED_AREA_OF_VEHICLES(<<-1799.513428,-467.645935,43.138790>>, <<-1789.602783,-476.661560,36.837288>>, 7.50)
b_CutsceneSkipped = FALSE
DEBUG_PRINTSTRING("Going into cutscene main loop now")
stageStage = SS_STAGE
ELSE
DEBUG_PRINTSTRING("Waiting for cutscene to be OK to start...")
ENDIF
BREAK
CASE SS_STAGE
IF iCutsceneStage = 0
IF GET_CUTSCENE_TIME() >= 31000
IF NOT b_MusicTriggered
IF TRIGGER_MUSIC_EVENT("RC6A_START")
DEBUG_PRINTSTRING("Starting music")
b_MusicTriggered = TRUE
ENDIF
ENDIF
ENDIF
// Keep spamming for the blend
SET_GAMEPLAY_CAM_RELATIVE_PITCH()
SET_GAMEPLAY_CAM_RELATIVE_HEADING()
IF WAS_CUTSCENE_SKIPPED()
DEBUG_PRINTSTRING("*** Cutscene skip detected")
DEBUG_PRINTSTRING("*** Cam exit state pitch/heading on skip")
SET_GAMEPLAY_CAM_RELATIVE_PITCH()
SET_GAMEPLAY_CAM_RELATIVE_HEADING()
IF IS_ENTITY_ALIVE(MARY_ANN)
SET_ENTITY_COORDS(MARY_ANN, <<-1869.24, -444.99, 45.17>>)
SET_ENTITY_HEADING(MARY_ANN, -143.87)
ENDIF
b_CutsceneSkipped = TRUE
iCutsceneStage = 1
ENDIF
// IF CAN_SET_EXIT_STATE_FOR_CAMERA()
// IF b_CutsceneSkipped
// DEBUG_PRINTSTRING("*** Cam exit state pitch/heading")
// SET_GAMEPLAY_CAM_RELATIVE_PITCH()
// SET_GAMEPLAY_CAM_RELATIVE_HEADING()
// ENDIF
// ENDIF
// Move on if blend happens
IF DO_MICHAEL_BLEND()
iCutsceneStage = 1
ENDIF
// Keep checking
DO_MARY_ANN_BLEND()
ELIF iCutsceneStage = 1
IF GET_CUTSCENE_TIME() >= 31000
IF NOT b_MusicTriggered
IF TRIGGER_MUSIC_EVENT("RC6A_START")
DEBUG_PRINTSTRING("Starting music")
b_MusicTriggered = TRUE
ENDIF
ENDIF
ENDIF
IF WAS_CUTSCENE_SKIPPED()
DEBUG_PRINTSTRING("*** Cutscene skip detected")
DEBUG_PRINTSTRING("*** Cam exit state pitch/heading on skip")
SET_GAMEPLAY_CAM_RELATIVE_PITCH()
SET_GAMEPLAY_CAM_RELATIVE_HEADING()
IF IS_ENTITY_ALIVE(MARY_ANN)
SET_ENTITY_COORDS(MARY_ANN, <<-1869.24, -444.99, 45.17>>)
SET_ENTITY_HEADING(MARY_ANN, -143.87)
ENDIF
IF NOT b_MusicTriggered
IF TRIGGER_MUSIC_EVENT("RC6A_START")
DEBUG_PRINTSTRING("Starting music from skip")
b_MusicTriggered = TRUE
ENDIF
ENDIF
ENDIF
// Keep checking in case we skipped
DO_MARY_ANN_BLEND()
// Keep checking in case missed in previous stage
DO_MICHAEL_BLEND()
IF NOT IS_CUTSCENE_ACTIVE()
REPLAY_STOP_EVENT()
REMOVE_NAVMESH_BLOCKING_OBJECT(CutsceneNavBlockerID)
CutsceneNavBlockerID = -1 // Reset so can be used again if we skip
REMOVE_SCENARIO_BLOCKING_AREA(sbiCutscene)
iOvertakeTimer = GET_GAME_TIMER()
stageStage = SS_SETUP
missionStage = MS_START_RUNNING
ENDIF
ENDIF
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE: Main process to handle the race immediately following the intro cutscene
PROC START_RUNNING()
SWITCH stageStage
CASE SS_SETUP
DEBUG_PRINTSTRING("Setup START_RUNNING")
REMOVE_VEHICLES_FROM_GENERATORS_IN_AREA(<<-1835.529785,-518.723816,25.116776>>, <<-1822.431030,-513.893311,30.386765>>)
SET_ALL_VEHICLE_GENERATORS_ACTIVE_IN_AREA(<<-1835.529785,-518.723816,25.116776>>, <<-1822.431030,-513.893311,30.386765>>, FALSE)
//CLEAR_AREA_OF_VEHICLES(<<-1793.82, -472.73, 39.58>>, 15.0)
// IF DOES_ENTITY_EXIST(MARY_ANN)
// SET_ENTITY_COORDS(MARY_ANN, <<-1865.90, -448.81, 45.2>>)
// SET_ENTITY_HEADING(MARY_ANN, -143.87)
// SET_PED_ON_THE_GROUND(MARY_ANN)
// ENDIF
IF NOT IS_AUDIO_SCENE_ACTIVE("FANATIC_MIX_SCENE")
START_AUDIO_SCENE("FANATIC_MIX_SCENE")
IF IS_ENTITY_ALIVE(MARY_ANN)
ADD_ENTITY_TO_AUDIO_MIX_GROUP(MARY_ANN,"FANATIC_MIX_MARY_ANNE")
ENDIF
ENDIF
// In case the cutscene gets skipped or the trigger just somehow misses, do it here
IF NOT b_MusicTriggered
IF TRIGGER_MUSIC_EVENT("RC6A_START")
DEBUG_PRINTSTRING("Starting music - start_running() init")
b_MusicTriggered = TRUE
ENDIF
ENDIF
ADD_PED_FOR_DIALOGUE(MyLocalPedStruct, 3, MARY_ANN, "MARYANN")
RC_END_CUTSCENE_MODE(TRUE, FALSE)
RC_SET_ENTITY_PROOFS_FOR_CUTSCENE(sRCLauncherDataLocal, FALSE)
IF IS_ENTITY_ALIVE(MARY_ANN)
SET_ENTITY_PROOFS(MARY_ANN, FALSE, FALSE, FALSE, FALSE, FALSE)
ENDIF
start_time = GET_GAME_TIMER()
IF NOT DOES_BLIP_EXIST(FANATIC_BLIP)
FANATIC_BLIP = CREATE_PED_BLIP(MARY_ANN, TRUE, TRUE)
SET_BLIP_AS_FRIENDLY(FANATIC_BLIP, TRUE)
ENDIF
IF IS_PED_UNINJURED(MARY_ANN)
SET_PED_CAN_RAGDOLL_FROM_PLAYER_IMPACT(MARY_ANN, FALSE)
//FORCE_PED_MOTION_STATE(MARY_ANN, MS_ON_FOOT_RUN, true, FAUS_CUTSCENE_EXIT )
ENDIF
MASprintState = SPRINT_COOLDOWN
iSprintTimer = GET_GAME_TIMER()
IF GET_IS_WAYPOINT_RECORDING_LOADED("Fanatic1RollingStart")
DEBUG_PRINTSTRING("*** Using assisted movement...")
USE_WAYPOINT_RECORDING_AS_ASSISTED_MOVEMENT_ROUTE("Fanatic1RollingStart", TRUE, 2, 0.7)
ENDIF
b_ForcePlayerRunningAtStart = TRUE
iRollingStartTimer = GET_GAME_TIMER()
iConversationTimer = GET_GAME_TIMER()
DEBUG_PRINTSTRING("GOING INTO START_RUNNING LOOP")
REPLAY_RECORD_BACK_FOR_TIME(0.0, 10.0, REPLAY_IMPORTANCE_LOW)
stageStage = SS_STAGE
BREAK
CASE SS_STAGE
// B*1422947
IF NOT g_savedGlobals.sRandomChars.g_bFanaticHelp
IF NOT IS_HELP_MESSAGE_BEING_DISPLAYED()
PRINT_HELP("FAN_HELP")
g_savedGlobals.sRandomChars.g_bFanaticHelp = TRUE
ENDIF
ENDIF
IF b_ForcePlayerRunningAtStart = TRUE
if (GET_GAME_TIMER() - iRollingStartTimer) < 5000
IF (GET_GAME_TIMER() - iRollingStartTimer) > 1000
IF IS_SCREEN_FADED_OUT()
DEBUG_PRINTSTRING("FADING IN NOW")
SAFE_FADE_SCREEN_IN_FROM_BLACK(500, FALSE)
RC_END_CUTSCENE_MODE(TRUE, FALSE)
ENDIF
ENDIF
//DEBUG_PRINTSTRING("USING ASSISTED ROUTE")
ELSE
b_ForcePlayerRunningAtStart = FALSE
DEBUG_PRINTSTRING("TURNING OFF ASSISTED ROUTE")
USE_WAYPOINT_RECORDING_AS_ASSISTED_MOVEMENT_ROUTE("Fanatic1RollingStart", FALSE)
REMOVE_WAYPOINT_RECORDING("Fanatic1RollingStart")
ENDIF
ENDIF
IF IS_ENTITY_ALIVE(MARY_ANN)
if GET_SCRIPT_TASK_STATUS(MARY_ANN, SCRIPT_TASK_PERFORM_SEQUENCE) != PERFORMING_TASK
DEBUG_PRINTSTRING("Re-set Mary Ann's task post-cutscene")
OPEN_SEQUENCE_TASK(seq)
TASK_SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(NULL, TRUE)
TASK_LOOK_AT_ENTITY(NULL, PLAYER_PED_ID(), -1, SLF_DEFAULT)
TASK_FOLLOW_WAYPOINT_RECORDING(NULL, sFANATIC_ROUTE, 1, EWAYPOINT_START_FROM_CLOSEST_POINT | EWAYPOINT_VEHICLES_USE_AI_SLOWDOWN | EWAYPOINT_ALLOW_STEERING_AROUND_PEDS | EWAYPOINT_NAVMESH_BACK_TO_WAYPOINT_IF_LEFT_ROUTE, -1)
TASK_LOOK_AT_ENTITY(NULL, PLAYER_PED_ID(), -1)
TASK_PLAY_ANIM(null, "move_f@runner", "idle", SLOW_BLEND_IN, SLOW_BLEND_OUT, -1, AF_LOOPING)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(MARY_ANN, seq)
CLEAR_SEQUENCE_TASK(seq)
ENDIF
ENDIF
IF cheatedLeaptFence.hasBeenPlayed = FALSE
IF iNum_NPCClosestWaypoint < 17
IF IS_PLAYER_CLIMBING(PLAYER_ID())
IF IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<-1799.070801,-468.659149,40.074013>>, <<-1820.118530,-492.413879,41.743690>>, 18.250000)
IF NOT IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<-1798.075562,-468.229706,39.025360>>, <<-1816.664307,-484.317017,43.642105>>, 12.500000)
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
KILL_ANY_CONVERSATION()
ENDIF
IF CAN_MARY_ANN_SAY_SINGLE_LINE(cheatedLeaptFence.rootLabel, cheatedLeaptFence.dialogueLine, FALSE, startRunConversation.restartLine)
IF startRunConversation.restartLine != -1
startRunConversation.hasBeenInterrupted = TRUE
DEBUG_PRINTSTRING("*** startRunConversation interrupted!")
DEBUG_PRINTSI("*** startRunConversation will restart on line: ",startRunConversation.restartLine)
ENDIF
finishReason = FINISHED_BY_SHORTCUT
b_CheatedLine = TRUE // Do a returnAfterCheatedLine
cheatedLeaptFence.hasBeenPlayed = TRUE
g_savedGlobals.sRandomChars.g_bFanaticCheated = TRUE
ELSE
DEBUG_PRINTSTRING("*** Waiting for prior conversation to end before can play cheated line!")
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
IF cheatedRanAcrossGrass.hasBeenPlayed = FALSE
IF IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<-1772.761719,-532.997131,35.589294>>, <<-1797.245850,-492.129211,39.270397>>, 26.000000)
OR GET_DISTANCE_BETWEEN_ENTITY_AND_COORD(PLAYER_PED_ID(), <<-1812.910278,-468.525330,41.320290>>) < 10
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
KILL_ANY_CONVERSATION()
ENDIF
IF CAN_MARY_ANN_SAY_SINGLE_LINE(cheatedRanAcrossGrass.rootLabel, cheatedRanAcrossGrass.dialogueLine, FALSE, startRunConversation.restartLine)
IF startRunConversation.restartLine != -1
startRunConversation.hasBeenInterrupted = TRUE
DEBUG_PRINTSTRING("*** startRunConversation interrupted!")
DEBUG_PRINTSI("*** startRunConversation will restart on line: ",startRunConversation.restartLine)
ENDIF
finishReason = FINISHED_BY_SHORTCUT
b_CheatedLine = TRUE // Do a returnAfterCheatedLine
cheatedRanAcrossGrass.hasBeenPlayed = TRUE
g_savedGlobals.sRandomChars.g_bFanaticCheated = TRUE
ELSE
DEBUG_PRINTSTRING("*** Waiting for prior conversation to end before can play cheated line!")
ENDIF
ENDIF
ENDIF
IF b_CheatedLine = TRUE // Player has cheated, do a return line
IF returnAfterCheatedLine.hasBeenPlayed = FALSE
if GET_DISTANCE_BETWEEN_PEDS(PLAYER_PED_ID(), MARY_ANN) < 10
INT temp
IF CAN_MARY_ANN_SAY_SINGLE_LINE(returnAfterCheatedLine.rootLabel, returnAfterCheatedLine.dialogueLine, FALSE, temp)
returnAfterCheatedLine.hasBeenPlayed = TRUE
b_CheatedLine = FALSE
iOneLinerTimer = GET_GAME_TIMER()
ENDIF
ENDIF
ENDIF
ENDIF
IF CAN_CREATE_RUNNING_CONVERSATION()
IF startRunConversation.hasBeenPlayed = FALSE
AND (GET_GAME_TIMER() - iConversationTimer) > 3500
CREATE_CONVERSATION(MyLocalPedStruct, "FAN1AU", startRunConversation.rootLabel, CONV_PRIORITY_MEDIUM)
DEBUG_PRINTSTRING("SETTING UP THE CONVERSATION")
startRunConversation.hasBeenPlayed = TRUE
iOneLinerTimer = GET_GAME_TIMER()
ELSE
IF startRunConversation.hasBeenInterrupted = TRUE
IF returnAfterCheatedLine.hasBeenPlayed = TRUE // We want to wait for the return after cheated line to be played first
tDialogueRoot = startRunConversation.rootLabel
tDialogueRoot += "_"
tDialogueRoot += startRunConversation.restartLine
IF CREATE_CONVERSATION_FROM_SPECIFIC_LINE(MyLocalPedStruct, "FAN1AU", startRunConversation.rootLabel, tDialogueRoot, CONV_PRIORITY_MEDIUM)
startRunConversation.hasBeenInterrupted = FALSE
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
// if the main conversation has been played, try doing the one-liners
IF startRunConversation.hasBeenPlayed
TRY_ONE_LINER()
ENDIF
IF RACE_LEG_FINISHED(vPos_StartOfRoadRunning)
fMBR_IncreaseRatio = 1.15
stageStage = SS_SETUP
missionStage = MS_ROAD_RUNNING_SECTION
ENDIF
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE: Main process to handle the road running section
PROC ROAD_RUNNING_SECTION()
SWITCH stageStage
CASE SS_SETUP
DEBUG_PRINTSTRING("SETUP ROAD_RUNNING_SECTION")
IF NOT DOES_BLIP_EXIST(FANATIC_BLIP)
FANATIC_BLIP = CREATE_PED_BLIP(MARY_ANN, TRUE, TRUE)
SET_BLIP_AS_FRIENDLY(FANATIC_BLIP, TRUE)
ENDIF
IF b_IsTheRoadSwitchedOn = TRUE
TURN_ROADS_ON(FALSE)
ENDIF
b_PlayerJumpedDownTheCliff = FALSE
iRoadTimer = GET_GAME_TIMER()
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
DEBUG_PRINTSTRING("stop scripted conversation at ROAD_RUNNING_SECTION")
KILL_ANY_CONVERSATION()
ENDIF
IF IS_VEHICLE_OK(FOLLOWING_CAR.thisCarIndex)
AND IS_PED_UNINJURED(FOLLOWING_CAR.Driver)
SET_ENTITY_COORDS(FOLLOWING_CAR.thisCarIndex, <<-1934.15, -438.19, 19.60>>)
SET_ENTITY_HEADING(FOLLOWING_CAR.thisCarIndex, 237.78)
SET_VEHICLE_ON_GROUND_PROPERLY(FOLLOWING_CAR.thisCarIndex)
TASK_VEHICLE_MISSION_COORS_TARGET(FOLLOWING_CAR.Driver, FOLLOWING_CAR.thisCarIndex, FOLLOWING_CAR.thisGoToPos, MISSION_GOTO, FOLLOWING_CAR.thisSpeed, DRIVINGMODE_AVOIDCARS_STOPFORPEDS_OBEYLIGHTS, 3, 3)
SET_ENTITY_LOAD_COLLISION_FLAG(FOLLOWING_CAR.Driver, TRUE)
ENDIF
DEBUG_PRINTSTRING("GOING INTO ROAD_RUNNING_SECTION LOOP")
driveByState = DRIVE_BY_PRE_TASK
stageStage = SS_STAGE
BREAK
CASE SS_STAGE
SET_PED_DENSITY_MULTIPLIER_THIS_FRAME(0.5)
IF CAN_CREATE_RUNNING_CONVERSATION()
IF road1Conversation.hasBeenPlayed = FALSE
INT i
IF IS_ENTITY_ALIVE(MARY_ANN)
WAYPOINT_RECORDING_GET_CLOSEST_WAYPOINT(sFANATIC_ROUTE, GET_ENTITY_COORDS(MARY_ANN), i)
ENDIF
IF i <= 52 // Only try and play the road conversation is Mary Ann is earlier or at the 54th waypoint, otherwise it's too late
IF cheatedLeaptFence.hasBeenPlayed = FALSE
AND cheatedRanAcrossGrass.hasBeenPlayed = FALSE
AND place = 2 // Only do the full one if the player is in second place
CREATE_CONVERSATION(MyLocalPedStruct, "FAN1AU", road1Conversation.rootLabel, CONV_PRIORITY_MEDIUM)
ELSE
CREATE_CONVERSATION_FROM_SPECIFIC_LINE(MyLocalPedStruct, "FAN1AU", road1Conversation.rootLabel, "FAN1_RD1_3", CONV_PRIORITY_MEDIUM)
ENDIF
road1Conversation.hasBeenPlayed = TRUE
ENDIF
ENDIF
ENDIF
IF driveByState = DRIVE_BY_PRE_TASK
IF iNum_NPCClosestWaypoint > 41
driveByState = DRIVE_BY_SET_DRIVE_TASK
ENDIF
ENDIF
// Only try this stuff if the main road conversations haven't been played
IF road1Conversation.hasBeenPlayed = TRUE
AND road2Conversation.hasBeenPlayed = TRUE
// Try and do a Mary Ann road rage conversation if a vehicle passes by
VECTOR vOffset
VEHICLE_INDEX vIdx
IF IS_ENTITY_ALIVE(MARY_ANN)
vOffset = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(MARY_ANN, <<0,6,0>>)
vIdx = GET_CLOSEST_VEHICLE(vOffset, 8, DUMMY_MODEL_FOR_SCRIPT, 2) // 2 = Return mission vehicles
if vIdx <> NULL
IF MADialogueState = MA_WITHIN_TALKING_RANGE
AND iRoadTimer > 2000
AND iRoadCounter < 5 // Max number of road rage lines
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF CREATE_CONVERSATION(MyLocalPedStruct, "FAN1AU", "FAN1_RD3", CONV_PRIORITY_MEDIUM)
iRoadCounter++
iRoadTimer = GET_GAME_TIMER()
ENDIF
ENDIF
ENDIF
ELSE
vIdx = GET_CLOSEST_VEHICLE(vOffset, 8, DUMMY_MODEL_FOR_SCRIPT, 4)
if vIdx <> NULL
IF MADialogueState = MA_WITHIN_TALKING_RANGE
AND iRoadTimer > 2000
AND iRoadCounter < 5 // Max number of road rage lines
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF CREATE_CONVERSATION(MyLocalPedStruct, "FAN1AU", "FAN1_RD3", CONV_PRIORITY_MEDIUM)
iRoadCounter++
iRoadTimer = GET_GAME_TIMER()
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
// If a road rage conversation above hasn't fired, try doing a one liner
TRY_ONE_LINER()
ENDIF
CHECK_IF_PLAYER_JUMPS_THE_CLIFF()
UPDATE_DRIVEBY_FINGERING()
IF iNum_NPCClosestWaypoint > 61
stageStage = SS_SETUP
missionStage = MS_STEPS_DOWN
ENDIF
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE: Main process to handle the steps down the cliff and over the freeway bridge
PROC STEPS_DOWN()
SWITCH stageStage
CASE SS_SETUP
DEBUG_PRINTSTRING("STEPS DOWN SETUP")
IF NOT DOES_BLIP_EXIST(FANATIC_BLIP)
FANATIC_BLIP = CREATE_PED_BLIP(MARY_ANN, TRUE, TRUE)
SET_BLIP_AS_FRIENDLY(FANATIC_BLIP, TRUE)
ENDIF
SET_PED_NON_CREATION_AREA(<<-1865.76, -617.48, 10.58>>, <<-1820.57, -552.41, 17.40>>)
//ADD_SCENARIO_BLOCKING_AREA(<<-1865.76, -617.48, 10.58>>, <<-1820.57, -552.41, 17.40>>)
SET_PED_PATHS_IN_AREA(<<-1865.76, -617.48, 10.58>>, <<-1820.57, -552.41, 17.40>>, FALSE)
IF IS_PED_UNINJURED(DRIVEBY_FINGER_CAR.Driver)
CLEAR_PED_TASKS(DRIVEBY_FINGER_CAR.Driver)
SAFE_RELEASE_PED(DRIVEBY_FINGER_CAR.Driver)
ENDIF
IF IS_VEHICLE_OK(DRIVEBY_FINGER_CAR.thisCarIndex)
SAFE_RELEASE_VEHICLE(DRIVEBY_FINGER_CAR.thisCarIndex)
ENDIF
DEBUG_PRINTSTRING("GOING INTO STEPS_DOWN MAIN LOOP")
stageStage = SS_STAGE
BREAK
CASE SS_STAGE
DEAL_WITH_THE_QUAD()
TRY_ONE_LINER()
SET_PED_DENSITY_MULTIPLIER_THIS_FRAME(0.5)
IF b_PlayerJumpedDownTheCliff = FALSE
CHECK_IF_PLAYER_JUMPS_THE_CLIFF()
ENDIF
IF RACE_LEG_FINISHED(vPos_StartOfBeachRunning)
fMBR_IncreaseRatio = 1.15
stageStage = SS_SETUP
missionStage = MS_SPRINT_TO_FINISH
ENDIF
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE: Main process to handle the final beach sprint
PROC SPRINT_TO_FINISH()
SWITCH stageStage
CASE SS_SETUP
DEBUG_PRINTSTRING("SETUP SPRINT_TO_FINISH")
IF NOT DOES_BLIP_EXIST(FANATIC_BLIP)
FANATIC_BLIP = CREATE_PED_BLIP(MARY_ANN, TRUE, TRUE)
SET_BLIP_AS_FRIENDLY(FANATIC_BLIP, TRUE)
ENDIF
beachDogState = DOG_LOADING
stageStage = SS_STAGE
DEBUG_PRINTSTRING("GOING INTO SPRINT_TO_FINISH MAIN LOOP")
BREAK
CASE SS_STAGE
SET_PED_DENSITY_MULTIPLIER_THIS_FRAME(0.5)
IF raceConversation.hasBeenPlayed = FALSE
AND iNum_NPCClosestWaypoint < 105
IF CAN_CREATE_RUNNING_CONVERSATION()
AND GET_DISTANCE_BETWEEN_PEDS(PLAYER_PED_ID(), MARY_ANN) < 25
IF CREATE_CONVERSATION(MyLocalPedStruct, "FAN1AU", raceConversation.rootLabel, CONV_PRIORITY_MEDIUM)
raceConversation.hasBeenPlayed = TRUE
TASK_PLAY_ANIM(MARY_ANN, "rcmfanatic1yell", "yell_c", NORMAL_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_UPPERBODY|AF_SECONDARY)
ENDIF
ENDIF
ENDIF
IF IS_THIS_CONVERSATION_ROOT_PLAYING(raceConversation.rootLabel)
IF GET_DISTANCE_BETWEEN_PEDS(PLAYER_PED_ID(), MARY_ANN) > 30
KILL_ANY_CONVERSATION()
ENDIF
ENDIF
CREATE_JOGGERS()
CREATE_MARY_ANNS_BIKE()
DEAL_WITH_THE_DOG()
DEAL_WITH_THE_QUAD()
DEAL_WITH_THE_TWO_FINAL_PEDS()
IF iRaceLineNumber < iMAXRaceLineNumber
AND iNum_NPCClosestWaypoint < 117
AND iNum_PlayerClosestWaypoint < 117
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF (GET_GAME_TIMER() - iConversationTimer) > 3000
int temp
if CAN_MARY_ANN_SAY_SINGLE_LINE("FAN1_FAST", RACE_LINE[iRaceLineNumber], FALSE, temp)
iRaceLineNumber++
ENDIF
ENDIF
ELSE
iConversationTimer = GET_GAME_TIMER()
ENDIF
ENDIF
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE: Special process to debug move the player close to the finish line rather than directly on top of it
PROC DEBUG_NEAR_FINISH_LINE()
SWITCH stageStage
CASE SS_SETUP
IF NOT DOES_BLIP_EXIST(FANATIC_BLIP)
FANATIC_BLIP = CREATE_PED_BLIP(MARY_ANN, TRUE, TRUE)
SET_BLIP_AS_FRIENDLY(FANATIC_BLIP, TRUE)
ENDIF
stageStage = SS_STAGE
BREAK
CASE SS_STAGE
CREATE_MARY_ANNS_BIKE()
DEAL_WITH_THE_TWO_FINAL_PEDS()
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE: Main process to handle the end cutscene, either realtime or scripted
PROC END_CUTSCENE()
// handle the previous checkpoint in here to fade it out
IF PrevCheckpoint != NULL
INT PreviR, PreviG, PreviB, iA
DEBUG_PRINTSTRING("Fade previous CP")
iPrevAlpha -= 25
IF iPrevAlpha > 0
GET_HUD_COLOUR(HUD_COLOUR_WHITE, PreviR, PreviG, PreviB, iA)
SET_CHECKPOINT_RGBA(PrevCheckpoint, PreviR, PreviG, PreviB, iPrevAlpha)
SET_CHECKPOINT_RGBA2(PrevCheckpoint, PreviR, PreviG, PreviB, iPrevAlpha)
ELSE
DELETE_CHECKPOINT(PrevCheckpoint)
ENDIF
ENDIF
SWITCH stageStage
CASE SS_SETUP
SAFE_REMOVE_BLIP(DESTINATION_BLIP)
DELETE_CHECKPOINT(checkPoint)
IF IS_PED_UNINJURED(BEACH_DOG)
CLEAR_PED_TASKS(BEACH_DOG)
TASK_SMART_FLEE_PED(BEACH_DOG, PLAYER_PED_ID(), 40, -1)
ENDIF
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
DEBUG_PRINTSTRING("stop scripted conversation at END_CUTSCENE")
KILL_FACE_TO_FACE_CONVERSATION_DO_NOT_FINISH_LAST_LINE()
ENDIF
IF IS_ENTITY_ALIVE(MARY_ANN)
SET_ENTITY_LOAD_COLLISION_FLAG(MARY_ANN, TRUE)
SET_PED_CAN_BE_KNOCKED_OFF_VEHICLE(MARY_ANN, KNOCKOFFVEHICLE_NEVER)
ENDIF
b_DoneOutOfBreath = FALSE
TRIGGER_MUSIC_EVENT("RC6A_FINISH")
WEAPON_TYPE currentWeapon
GET_CURRENT_PED_WEAPON(PLAYER_PED_ID(), currentWeapon, FALSE)
IF currentWeapon != WEAPONTYPE_UNARMED
SET_CURRENT_PED_WEAPON(PLAYER_PED_ID(), WEAPONTYPE_UNARMED, TRUE) // Force player to be unarmed so anim looks right
ENDIF
IF b_ScriptedEnding
CLEAR_AREA_OF_PEDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), 30)
RESOLVE_VEHICLES_INSIDE_ANGLED_AREA_WITH_SIZE_LIMIT(<<-2010.692993,-504.882050,9.529695>>, <<-1995.946777,-517.249390,13.764661>>, 10.0, <<-2008.54, -494.10, 11.04>>, 48.19,
GET_DEFAULT_ALLOWABLE_VEHICLE_SIZE_VECTOR())
RC_START_CUTSCENE_MODE(vPos_FinishLine, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, FALSE)
GO_TO_CUTSCENE()
IF GET_DISTANCE_BETWEEN_PEDS(PLAYER_PED_ID(), MARY_ANN) > 32
SET_ENTITY_COORDS(MARY_ANN, <<-1986.20, -526.22, 11>>)
SET_ENTITY_HEADING(MARY_ANN, 58.26)
OPEN_SEQUENCE_TASK(seq)
TASK_FOLLOW_WAYPOINT_RECORDING(NULL, sFANATIC_ROUTE, GET_MARY_ANNS_NEXT_WAYPOINT(), EWAYPOINT_DEFAULT | EWAYPOINT_VEHICLES_USE_AI_SLOWDOWN | EWAYPOINT_ALLOW_STEERING_AROUND_PEDS, -1)
TASK_PLAY_ANIM(null, "move_f@runner", "idle", SLOW_BLEND_IN, SLOW_BLEND_OUT, -1, AF_LOOPING)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(MARY_ANN, seq)
CLEAR_SEQUENCE_TASK(seq)
FORCE_PED_MOTION_STATE(MARY_ANN, MS_ON_FOOT_RUN, true, FAUS_CUTSCENE_EXIT )
ENDIF
TASK_LOOK_AT_ENTITY(MARY_ANN, PLAYER_PED_ID(), -1)
OPEN_SEQUENCE_TASK(seq)
TASK_FOLLOW_NAV_MESH_TO_COORD(NULL, vPos_FinishLine, 1, DEFAULT_TIME_BEFORE_WARP, 0.5, ENAV_DEFAULT)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(PLAYER_PED_ID(), seq)
CLEAR_SEQUENCE_TASK(seq)
FORCE_PED_MOTION_STATE(PLAYER_PED_ID(), MS_ON_FOOT_RUN, TRUE, FAUS_DEFAULT)
REQUEST_ANIM_DICT("rcmfanatic1out_of_breath")
WHILE NOT HAS_ANIM_DICT_LOADED("rcmfanatic1out_of_breath")
DEBUG_PRINTSTRING("Loading ANIMS")
WAIT(0)
ENDWHILE
b_TIRED_ANIM_PLAYING = FALSE
SET_EVERYONE_IGNORE_PLAYER(PLAYER_ID(), TRUE)
ELSE
REQUEST_ANIM_DICT("rcmfanatic1out_of_breath")
WHILE NOT HAS_ANIM_DICT_LOADED("rcmfanatic1out_of_breath")
DEBUG_PRINTSTRING("Loading ANIMS")
WAIT(0)
ENDWHILE
ENDIF
IF NOT DOES_ENTITY_EXIST(MAS_BIKE)
REQUEST_MODEL(MARYSBIKEMODEL)
WHILE NOT HAS_MODEL_LOADED(MARYSBIKEMODEL)
DEBUG_PRINTSTRING("Loading MARYSBIKE MODEL")
WAIT(0)
ENDWHILE
MAS_BIKE = CREATE_VEHICLE(MARYSBIKEMODEL, MAS_BIKE_POS, MAS_BIKE_DIR)
SET_MODEL_AS_NO_LONGER_NEEDED(MARYSBIKEMODEL)
ENDIF
INT p
FOR p = 0 TO 3
IF IS_PED_UNINJURED(OtherJoggers[p].thisIndex)
IF IS_PED_IN_MELEE_COMBAT(OtherJoggers[p].thisIndex)
OR IS_PED_RESPONDING_TO_EVENT(OtherJoggers[p].thisIndex, EVENT_PED_TO_CHASE)
OR IS_PED_RESPONDING_TO_EVENT(OtherJoggers[p].thisIndex, EVENT_MELEE_ACTION)
CLEAR_PED_TASKS(OtherJoggers[p].thisIndex)
OPEN_SEQUENCE_TASK(seq)
TASK_TURN_PED_TO_FACE_ENTITY(NULL, PLAYER_PED_ID())
TASK_PAUSE(NULL, 2000)
TASK_WANDER_STANDARD(NULL)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(OtherJoggers[p].thisIndex, seq)
CLEAR_SEQUENCE_TASK(seq)
SAFE_RELEASE_PED(OtherJoggers[p].thisIndex)
ENDIF
ENDIF
ENDFOR
myCam = CAM_TARGET_PLAYER
stageStage = SS_STAGE
BREAK
CASE SS_STAGE
DEAL_WITH_THE_TWO_FINAL_PEDS()
RC_DISABLE_CONTROL_ACTIONS_FOR_LEAD_IN() // Disable these actions while we're playing the outro
DISABLE_CELLPHONE_THIS_FRAME_ONLY() // Disable the phone too
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_COVER) // Make the player unable to get into cover
SWITCH cutsceneStage
CASE CS_WAIT_FOR_ANN
IF b_ScriptedEnding
IF GET_SCRIPT_TASK_STATUS(PLAYER_PED_ID(), SCRIPT_TASK_PERFORM_SEQUENCE) = FINISHED_TASK
IF b_TIRED_ANIM_PLAYING = FALSE
OPEN_SEQUENCE_TASK(seq)
TASK_PLAY_ANIM(NULL, "rcmfanatic1out_of_breath", "base", NORMAL_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_LOOPING)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(PLAYER_PED_ID(), seq)
CLEAR_SEQUENCE_TASK(seq)
b_TIRED_ANIM_PLAYING = TRUE
ENDIF
ENDIF
IF IS_ENTITY_AT_COORD(MARY_ANN, vPos_FinishLine, <<5,5,3>>)
AND b_TIRED_ANIM_PLAYING = TRUE
IF finishReason = FINISHED_BY_STEROIDS
dialogueOptionFinish = "FAN1_DONE_2"
ELIF finishReason = FINISHED_BY_SHORTCUT
dialogueOptionFinish = "FAN1_DONE_3"
ENDIF
IF CREATE_MULTIPART_CONVERSATION_WITH_4_LINES(MyLocalPedStruct, "FAN1AU",
"FAN1_DONE", "FAN1_DONE_1",
"FAN1_DONE", dialogueOptionFinish,
"FAN1_DONE", "FAN1_DONE_4",
"FAN1_DONE", "FAN1_DONE_5", CONV_PRIORITY_MEDIUM)
cutsceneStage = CS_MARY_ANN_LEAVES
ENDIF
ENDIF
ELSE
// Keep looping this to make sure Michael's playing his out of breath anims
DEAL_WITH_MICHAEL_OUT_OF_BREATH()
INT i
IF IS_ENTITY_ALIVE(MARY_ANN)
WAYPOINT_RECORDING_GET_CLOSEST_WAYPOINT(sFANATIC_ROUTE, GET_ENTITY_COORDS(MARY_ANN), i)
IF i >=125
OPEN_SEQUENCE_TASK(seq)
TASK_PLAY_ANIM(NULL, "rcmfanatic1", "jogging_up", NORMAL_BLEND_IN, FAST_BLEND_OUT, -1, AF_USE_KINEMATIC_PHYSICS)
TASK_PLAY_ANIM(NULL, "rcmfanatic1", "jogging_on_spot", FAST_BLEND_IN, SLOW_BLEND_OUT, -1, AF_LOOPING|AF_USE_KINEMATIC_PHYSICS)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(MARY_ANN, seq)
TASK_LOOK_AT_ENTITY(MARY_ANN, PLAYER_PED_ID(), -1)
IF finishReason = FINISHED_BY_STEROIDS
dialogueOptionFinish = "FAN1_DONE_2"
ELIF finishReason = FINISHED_BY_SHORTCUT
dialogueOptionFinish = "FAN1_DONE_3"
ENDIF
IF CREATE_MULTIPART_CONVERSATION_WITH_4_LINES(MyLocalPedStruct, "FAN1AU",
"FAN1_DONE", "FAN1_DONE_1",
"FAN1_DONE", dialogueOptionFinish,
"FAN1_DONE", "FAN1_DONE_4",
"FAN1_DONE", "FAN1_DONE_5", CONV_PRIORITY_MEDIUM)
REPLAY_RECORD_BACK_FOR_TIME(10.0, 10.0, REPLAY_IMPORTANCE_LOW)
cutsceneStage = CS_MARY_ANN_LEAVES
TASK_LOOK_AT_ENTITY(PLAYER_PED_ID(), MARY_ANN, 4000)
cutsceneStage = CS_MARY_ANN_LEAVES
ENDIF
ENDIF
ENDIF
ENDIF
BREAK
CASE CS_MARY_ANN_LEAVES
IF b_ScriptedEnding
switch myCam
CASE CAM_TARGET_PLAYER
IF GET_CURRENT_SCRIPTED_CONVERSATION_LINE() > 2
DETACH_CAM(camCutsceneStart)
STOP_CAM_POINTING(camCutsceneStart)
SET_CAM_PARAMS(camCutsceneStart,<<-2008.2262, -508.2978, 12.2798>>, <<-9.0657, -0.0000, -70.4730>>, 50.0)
myCam = CAM_MARY_ANN_LEAVES
ENDIF
BREAK
CASE CAM_MARY_ANN_LEAVES
IF IS_VEHICLE_OK(MAS_BIKE)
OPEN_SEQUENCE_TASK(seq)
TASK_LOOK_AT_ENTITY(NULL, MAS_BIKE, -1)
//TASK_PLAY_ANIM(NULL, "rcmfanatic1", "jogging_exit", FAST_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_TAG_SYNC_OUT|AF_USE_KINEMATIC_PHYSICS)
TASK_FOLLOW_NAV_MESH_TO_COORD(NULL, <<-2003.36, -503.77, 10.48>>, PEDMOVEBLENDRATIO_RUN, DEFAULT, 1.0, ENAV_NO_STOPPING|ENAV_DONT_AVOID_PEDS|ENAV_SUPPRESS_EXACT_STOP)
TASK_ENTER_VEHICLE(NULL, MAS_BIKE, DEFAULT_TIME_BEFORE_WARP, VS_DRIVER, 1)
TASK_CLEAR_LOOK_AT(NULL)
TASK_LOOK_AT_ENTITY(NULL, PLAYER_PED_ID(), 2000)
TASK_VEHICLE_DRIVE_TO_COORD(NULL, MAS_BIKE, <<-2014.96, -455.47, 10.48>>, 10, DRIVINGSTYLE_NORMAL, MARYSBIKEMODEL, DF_SteerAroundStationaryCars, 3, 50)
TASK_VEHICLE_DRIVE_WANDER(NULL, MAS_BIKE, 10, DRIVINGMODE_AVOIDCARS_STOPFORPEDS_OBEYLIGHTS)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(MARY_ANN, seq)
CLEAR_SEQUENCE_TASK(seq)
SET_PED_KEEP_TASK(MARY_ANN, TRUE)
SET_ANIM_LOOPED(PLAYER_PED_ID(), FALSE)
OPEN_SEQUENCE_TASK(seq)
TASK_PLAY_ANIM(NULL, "rcmfanatic1out_of_breath", "base", NORMAL_BLEND_IN, NORMAL_BLEND_OUT, -1)
TASK_LOOK_AT_ENTITY(NULL, MARY_ANN, -1)
TASK_TURN_PED_TO_FACE_COORD(NULL, <<-2000.81, -496.56, 10.56>>)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(PLAYER_PED_ID(), seq)
CLEAR_SEQUENCE_TASK(seq)
ENDIF
cutsceneStage = CS_SAY_FINAL_LINE
BREAK
ENDSWITCH
ELSE
DEAL_WITH_MICHAEL_OUT_OF_BREATH()
DEAL_WITH_MARY_ANN_FACING_PLAYER() // Keep Mary Ann facing the player while this is playing out
IF GET_CURRENT_SCRIPTED_CONVERSATION_LINE() > 2
IF NOT b_PlayerOnMAsBike
IF IS_VEHICLE_OK(MAS_BIKE)
OPEN_SEQUENCE_TASK(seq)
TASK_CLEAR_LOOK_AT(NULL)
TASK_LOOK_AT_ENTITY(NULL, MAS_BIKE, -1)
//TASK_PLAY_ANIM(NULL, "rcmfanatic1", "jogging_exit", SLOW_BLEND_IN, FAST_BLEND_OUT, -1, AF_TAG_SYNC_OUT|AF_USE_KINEMATIC_PHYSICS)
TASK_FOLLOW_NAV_MESH_TO_COORD(NULL, <<-2003.36, -503.77, 10.48>>, PEDMOVEBLENDRATIO_RUN, DEFAULT, 1.0, ENAV_NO_STOPPING|ENAV_DONT_AVOID_PEDS)
TASK_ENTER_VEHICLE(NULL, MAS_BIKE, DEFAULT_TIME_BEFORE_WARP, VS_DRIVER, PEDMOVEBLENDRATIO_RUN)
TASK_CLEAR_LOOK_AT(NULL)
TASK_LOOK_AT_ENTITY(NULL, PLAYER_PED_ID(), 2000)
TASK_VEHICLE_DRIVE_TO_COORD(NULL, MAS_BIKE, <<-2018.17, -461.00, 10.56>>, 10, DRIVINGSTYLE_NORMAL, MARYSBIKEMODEL, DF_SteerAroundStationaryCars, 3, 50)
TASK_VEHICLE_DRIVE_TO_COORD(NULL, MAS_BIKE, <<-2014.96, -455.47, 10.48>>, 10, DRIVINGSTYLE_NORMAL, MARYSBIKEMODEL, DF_SteerAroundStationaryCars, 3, 50)
TASK_VEHICLE_DRIVE_WANDER(NULL, MAS_BIKE, 10, DRIVINGMODE_AVOIDCARS_STOPFORPEDS_OBEYLIGHTS)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(MARY_ANN, seq)
CLEAR_SEQUENCE_TASK(seq)
SET_PED_KEEP_TASK(MARY_ANN, TRUE)
ENDIF
ELSE
OPEN_SEQUENCE_TASK(seq)
TASK_CLEAR_LOOK_AT(NULL)
TASK_LOOK_AT_ENTITY(NULL, PLAYER_PED_ID(), 2000)
TASK_FOLLOW_NAV_MESH_TO_COORD(NULL, <<-1954.10, -450.90, 16.77>>, PEDMOVEBLENDRATIO_RUN, DEFAULT_TIME_BEFORE_WARP)
TASK_WANDER_STANDARD(NULL)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(MARY_ANN, seq)
CLEAR_SEQUENCE_TASK(seq)
SET_PED_KEEP_TASK(MARY_ANN, TRUE)
ENDIF
TASK_LOOK_AT_ENTITY(PLAYER_PED_ID(), MARY_ANN, 6000)
cutsceneStage = CS_SAY_FINAL_LINE
ENDIF
ENDIF
BREAK
CASE CS_SAY_FINAL_LINE
IF b_ScriptedEnding
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF NOT IS_ENTITY_AT_ENTITY(PLAYER_PED_ID(), MARY_ANN, <<5,5,3>>)
cutsceneStage = CS_CUTSCENE_ENDS
ENDIF
ENDIF
ELSE
DEAL_WITH_MICHAEL_OUT_OF_BREATH()
IF b_PlayerOnMAsBike
IF NOT b_MaryAnnFinalOrdersGiven
IF IS_ENTITY_ALIVE(MARY_ANN)
CLEAR_PED_TASKS(MARY_ANN)
OPEN_SEQUENCE_TASK(seq)
TASK_CLEAR_LOOK_AT(NULL)
TASK_FOLLOW_NAV_MESH_TO_COORD(NULL, <<-1954.10, -450.90, 16.77>>, PEDMOVEBLENDRATIO_RUN, DEFAULT_TIME_BEFORE_WARP)
TASK_WANDER_STANDARD(NULL)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(MARY_ANN, seq)
CLEAR_SEQUENCE_TASK(seq)
SET_PED_KEEP_TASK(MARY_ANN, TRUE)
b_MaryAnnFinalOrdersGiven = TRUE
ENDIF
ENDIF
ENDIF
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF NOT IS_ENTITY_AT_ENTITY(PLAYER_PED_ID(), MARY_ANN, <<5,5,3>>)
cutsceneStage = CS_CUTSCENE_ENDS
ENDIF
ENDIF
ENDIF
BREAK
CASE CS_CUTSCENE_ENDS
IF b_ScriptedEnding
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF NOT IS_ENTITY_AT_ENTITY(PLAYER_PED_ID(), MARY_ANN, <<5,5,3>>)
CLEAR_PED_TASKS(PLAYER_PED_ID())
TASK_CLEAR_LOOK_AT(PLAYER_PED_ID())
SET_GAMEPLAY_CAM_RELATIVE_HEADING()
RENDER_SCRIPT_CAMS(FALSE, TRUE)
RC_END_CUTSCENE_MODE()
Script_Passed()
ENDIF
ENDIF
ELSE
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF NOT IS_ENTITY_AT_ENTITY(PLAYER_PED_ID(), MARY_ANN, <<5,5,3>>)
TASK_CLEAR_LOOK_AT(PLAYER_PED_ID())
//CLEAR_PED_TASKS(PLAYER_PED_ID())
TASK_PLAY_ANIM(PLAYER_PED_ID(), "rcmfanatic1out_of_breath", "p_zero_tired_exit", INSTANT_BLEND_IN, REALLY_SLOW_BLEND_OUT, -1, AF_SECONDARY|AF_UPPERBODY)
FORCE_PED_AI_AND_ANIMATION_UPDATE(PLAYER_PED_ID())
Script_Passed()
ENDIF
ENDIF
ENDIF
BREAK
ENDSWITCH
IF b_ScriptedEnding
IF IS_CUTSCENE_SKIP_BUTTON_JUST_PRESSED_WITH_DELAY()
CLEAR_PED_TASKS(PLAYER_PED_ID())
TASK_CLEAR_LOOK_AT(PLAYER_PED_ID())
SET_GAMEPLAY_CAM_RELATIVE_HEADING()
RENDER_SCRIPT_CAMS(FALSE, FALSE)
RC_END_CUTSCENE_MODE()
INSTANTLY_FILL_VEHICLE_POPULATION()
Script_Passed()
ENDIF
ELSE
// Do Mary Ann checks here
IF IS_ENTITY_ALIVE(MARY_ANN)
CHECK_IF_MARY_ANN_IS_INJURED_KILLED_OR_SCARED()
CHECK_IF_PLAYER_IS_IN_A_VEHICLE()
// If the player gets too far away after the convo starts, kill the convo, make Mary Ann go away
IF cutsceneStage > CS_WAIT_FOR_ANN
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), MARY_ANN) > 15
// If the player's too far away and they're NOT on the bike...
IF NOT b_PlayerOnMAsBike
// ... and Mary Ann isn't in the bike herself...
IF NOT IS_PED_IN_ANY_VEHICLE(MARY_ANN, TRUE)
// ... make her go away!
IF cutsceneStage <= CS_MARY_ANN_LEAVES
IF IS_VEHICLE_OK(MAS_BIKE)
OPEN_SEQUENCE_TASK(seq)
TASK_LOOK_AT_ENTITY(NULL, MAS_BIKE, -1)
TASK_ENTER_VEHICLE(NULL, MAS_BIKE, DEFAULT_TIME_BEFORE_WARP, VS_DRIVER, 1)
TASK_CLEAR_LOOK_AT(NULL)
TASK_LOOK_AT_ENTITY(NULL, PLAYER_PED_ID(), 2000)
TASK_VEHICLE_DRIVE_TO_COORD(NULL, MAS_BIKE, <<-2018.17, -461.00, 10.56>>, 10, DRIVINGSTYLE_NORMAL, MARYSBIKEMODEL, DF_SteerAroundStationaryCars, 3, 50)
TASK_VEHICLE_DRIVE_TO_COORD(NULL, MAS_BIKE, <<-2024.98, -479.55, 10.57>>, 10, DRIVINGSTYLE_NORMAL, MARYSBIKEMODEL, DF_SteerAroundStationaryCars, 3, 50)
TASK_VEHICLE_DRIVE_WANDER(NULL, MAS_BIKE, 10, DRIVINGMODE_AVOIDCARS_STOPFORPEDS_OBEYLIGHTS)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(MARY_ANN, seq)
CLEAR_SEQUENCE_TASK(seq)
SET_PED_KEEP_TASK(MARY_ANN, TRUE)
ENDIF
ENDIF
ENDIF
ELSE
// The player's on her bike, so make Mary Ann run away instead
IF NOT b_MaryAnnFinalOrdersGiven
IF IS_ENTITY_ALIVE(MARY_ANN)
CLEAR_PED_TASKS(MARY_ANN)
OPEN_SEQUENCE_TASK(seq)
TASK_CLEAR_LOOK_AT(NULL)
TASK_FOLLOW_NAV_MESH_TO_COORD(NULL, <<-1954.10, -450.90, 16.77>>, PEDMOVEBLENDRATIO_RUN, DEFAULT_TIME_BEFORE_WARP)
TASK_WANDER_STANDARD(NULL)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(MARY_ANN, seq)
CLEAR_SEQUENCE_TASK(seq)
SET_PED_KEEP_TASK(MARY_ANN, TRUE)
b_MaryAnnFinalOrdersGiven = TRUE
ENDIF
ENDIF
ENDIF
// Kill the convo regardless of what Mary Ann is doing
KILL_ANY_CONVERSATION()
cutsceneStage = CS_CUTSCENE_ENDS
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
BREAK
ENDSWITCH
ENDPROC
PROC LOST_RACE()
SWITCH stageStage
CASE SS_SETUP
DEBUG_PRINTSTRING("In setup for Lost Race")
// remove blips
SAFE_REMOVE_BLIP(FANATIC_BLIP)
SAFE_REMOVE_BLIP(DESTINATION_BLIP)
SAFE_REMOVE_BLIP(NEXT_DESTINATION_BLIP)
DELETE_CHECKPOINT(checkPoint)
BOOL bWhichConv // Use a random bool to determine which losing convo for Mary Ann to play
bWhichConv = GET_RANDOM_BOOL()
IF MADialogueState = MA_WITHIN_TALKING_RANGE
IF bWhichConv = TRUE
CREATE_CONVERSATION(MyLocalPedStruct, "FAN1AU", "FAN1_LOSE", CONV_PRIORITY_HIGH)
DEBUG_PRINTSTRING("Doing 'FAN1_LOSE'")
ELSE
CREATE_CONVERSATION(MyLocalPedStruct, "FAN1AU", "FAN1_LOSE2", CONV_PRIORITY_HIGH)
DEBUG_PRINTSTRING("Doing 'FAN1_LOSE2'")
ENDIF
ENDIF
OPEN_SEQUENCE_TASK(seq)
TASK_LOOK_AT_ENTITY(null, PLAYER_PED_ID(), -1)
TASK_PLAY_ANIM(null, "rcmfanatic1celebrate", "celebrate", SLOW_BLEND_IN, FAST_BLEND_OUT, -1, AF_EXIT_AFTER_INTERRUPTED|AF_USE_KINEMATIC_PHYSICS|AF_TAG_SYNC_IN)
TASK_PLAY_ANIM(null, "move_f@runner", "idle", FAST_BLEND_IN, SLOW_BLEND_OUT, -1, AF_LOOPING|AF_EXIT_AFTER_INTERRUPTED|AF_USE_KINEMATIC_PHYSICS)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(MARY_ANN, seq)
CLEAR_SEQUENCE_TASK(seq)
DEBUG_PRINTSTRING("Going into loop for Lost Race")
stageStage = SS_STAGE
BREAK
CASE SS_STAGE
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
DEBUG_PRINTSTRING("No conversation going in Lost Race, failing properly now")
TRIGGER_MUSIC_EVENT("RC6A_FAIL")
failReason = FAIL_SHE_BEAT_YOU_TO_BIKE
stageStage = SS_SETUP
missionstage = MS_FAIL_WAIT_FOR_FADE
ENDIF
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE: Main process to handle mission failure and the fade out
PROC FAIL_WAIT_FOR_FADE()
SWITCH stageStage
CASE SS_SETUP
CLEAR_PRINTS()
CLEAR_HELP()
IF FailReason <> FAIL_FANATIC_SCARED
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
DEBUG_PRINTSTRING("Killing conversation in fail state")
KILL_FACE_TO_FACE_CONVERSATION_DO_NOT_FINISH_LAST_LINE()
ENDIF
ELSE
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF CREATE_CONVERSATION(MyLocalPedStruct, "FAN1AU", "FAN1_AGGRO", CONV_PRIORITY_VERY_HIGH)
DEBUG_PRINTSTRING("Playing aggro convo with subs")
ENDIF
ELSE
DEBUG_PRINTSTRING("Convo already active when failing for scaring Mary Ann - playing without subs asap?")
KILL_ANY_CONVERSATION()
ADD_NON_CRITICAL_STANDARD_CONVERSATION_TO_BUFFER(MyLocalPedStruct, "FAN1AU", "FAN1_AGGRO", CONV_PRIORITY_HIGH)
ENDIF
ENDIF
// remove blips
SAFE_REMOVE_BLIP(FANATIC_BLIP)
SAFE_REMOVE_BLIP(DESTINATION_BLIP)
SAFE_REMOVE_BLIP(NEXT_DESTINATION_BLIP)
DELETE_CHECKPOINT(checkPoint)
// handle Mary Ann
IF FailReason = FAIL_FANATIC_INJURED
OR FailReason = FAIL_FANATIC_KILLED
OR FailReason = FAIL_FANATIC_SCARED
IF IS_ENTITY_ALIVE(MARY_ANN)
TASK_SMART_FLEE_PED(MARY_ANN, PLAYER_PED_ID(), 80, -1)
ENDIF
ENDIF
STRING fText
SWITCH FailReason
CASE FAIL_FANATIC_KILLED
fText = "FATIC1_F8"
BREAK
CASE FAIL_FANATIC_SCARED
fText = "FATIC1_F2"
BREAK
CASE FAIL_FANATIC_INJURED
fText = "FATIC1_F1"
BREAK
CASE FAIL_IN_CAR
fText = "FATIC1_F5"
BREAK
CASE FAIL_YOU_DIDNT_KEEP_UP
fText = "FATIC1_F3"
BREAK
CASE FAIL_SHE_BEAT_YOU_TO_BIKE
fText = "FATIC1_F7"
BREAK
CASE FAIL_LEFT_RACE
fText = "FATIC1_F6"
BREAK
DEFAULT
BREAK
ENDSWITCH
IF NOT IS_STRING_NULL_OR_EMPTY(fText)
Random_Character_Failed_With_Reason(fText)
ELSE
Random_Character_Failed()
ENDIF
stageStage = SS_STAGE
BREAK
CASE SS_STAGE
IF GET_MISSION_FLOW_SAFE_TO_CLEANUP()
// 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)
//MISSION_FLOW_SET_FAIL_WARP_LOCATION(<< -1860.4117, -416.5467, 44.9804 >>, 143.1230)
//SET_REPLAY_DECLINED_VEHICLE_WARP_LOCATION(<< -1856.55, -413.59, 45.32 >>, -120.328)
// finished fading out
DELETE_EVERYTHING()
TURN_ROADS_ON()
RESET_PLAYER_HAS_CHANGE_CLOTHES_ON_MISSION(CHAR_MICHAEL, bHasChanged)
Script_Cleanup()
ELSE
// not finished fading out
// you may want to handle dialogue etc here.
ENDIF
BREAK
ENDSWITCH
ENDPROC
// ===========================================================================================================
// Script Loop
// ===========================================================================================================
SCRIPT(g_structRCScriptArgs sRCLauncherDataIn)
sRCLauncherDataLocal = sRCLauncherDataIn
RC_TakeEntityOwnership(sRCLauncherDataLocal)
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("RC6A_FAIL")
Random_Character_Failed()
Script_Cleanup()
ENDIF
IF Is_Replay_In_Progress() // Set up the initial scene for replays
OR IS_REPEAT_PLAY_ACTIVE()
g_bSceneAutoTrigger = TRUE
eInitialSceneStage = IS_REQUEST_SCENE
WHILE NOT SetupScene_FANATIC_1(sRCLauncherDataLocal)
WAIT(0)
ENDWHILE
g_bSceneAutoTrigger = FALSE
ENDIF
DISABLE_CHEAT(CHEAT_TYPE_FAST_RUN, TRUE)
MARY_ANN = sRCLauncherDataLocal.pedID[0]
bHasChanged = GET_PLAYER_HAS_CHANGE_CLOTHES_ON_MISSION(CHAR_MICHAEL)
#IF IS_DEBUG_BUILD
IF NOT DOES_WIDGET_GROUP_EXIST(widgetGroup)
widgetGroup= START_WIDGET_GROUP("Fanatic 1 widgets")
ADD_WIDGET_FLOAT_SLIDER("Maximum MBR rate increase", fMBRMax, 1.01, 1.15, 0.005)
ADD_WIDGET_FLOAT_SLIDER("Maximum MBR speed", fMBR_MaxRunSpeed, 2.5, 3.0, 0.01)
ADD_WIDGET_INT_SLIDER("Mary Ann sprint length (ms)", iSprintLength, 500, 5000, 100)
ADD_WIDGET_INT_SLIDER("Mary Ann sprint cooldown delay (ms)", iSprintDelay, 500, 10000, 100)
ADD_WIDGET_BOOL("TTY Toggle - Print Mission Debug Info", bDebug_PrintToTTY)
ADD_WIDGET_BOOL("TTY Toggle - Print Mary Ann Speed debug", bDebug_SpeedDebug)
ADD_WIDGET_FLOAT_READ_ONLY("Player sprint time remaining: ", fPlayerSprintRemaining)
STOP_WIDGET_GROUP()
ENDIF
#ENDIF
REGISTER_SCRIPT_WITH_AUDIO()
IF IS_REPLAY_IN_PROGRESS()
OR IS_REPEAT_PLAY_ACTIVE()
CPRINTLN(DEBUG_MISSION, "Fanatic 1 *** Replay/repeat play IS in progress, doing INIT() now")
RC_SET_ENTITY_PROOFS_FOR_CUTSCENE(sRCLauncherDataLocal, FALSE)
IF IS_ENTITY_ALIVE(MARY_ANN)
SET_ENTITY_PROOFS(MARY_ANN, FALSE, FALSE, FALSE, FALSE, FALSE)
ENDIF
START_REPLAY_SETUP(<<-1878.2344, -439.6985, 45.0299>>, 241.0468)
INIT()
IF NOT IS_REPEAT_PLAY_ACTIVE() // Play the intro if we do a repeat play
SWITCH GET_REPLAY_MID_MISSION_STAGE()
CASE CP_AFTER_MOCAP
CPRINTLN(DEBUG_MISSION, "Fanatic 1 *** Replay/retry active, not a repeat play, skipping intro")
JUMP_TO_STAGE(DEBUG_TO_START)
BREAK
ENDSWITCH
ELSE
IF IS_REPLAY_IN_PROGRESS()
SWITCH GET_REPLAY_MID_MISSION_STAGE()
CASE CP_AFTER_MOCAP
CPRINTLN(DEBUG_MISSION, "Fanatic 1 *** Replay/retry active, is also a repeat play, skipping intro")
JUMP_TO_STAGE(DEBUG_TO_START)
BREAK
ENDSWITCH
ELSE
CPRINTLN(DEBUG_MISSION, "Fanatic 1 *** Replay/retry NOT active, but is repeat play, playing intro")
JUMP_TO_STAGE(DEBUG_TO_INTRO)
ENDIF
ENDIF
ELSE
CPRINTLN(DEBUG_MISSION, "Fanatic 1 *** Replay IS NOT in progress, proceeding normally")
ENDIF
// Loop within here until the mission passes or fails
WHILE(TRUE)
REPLAY_CHECK_FOR_EVENT_THIS_FRAME("SF_EDM")
WAIT(0)
UPDATE_MISSION_NAME_DISPLAYING(sRCLauncherDataLocal.sIntroCutscene, TRUE)
CHECK_FAIL_POSSIBILITIES()
DEAL_WITH_THE_RACE_TRACKING()
HANDLE_GLOBAL_STAMINA_HELP()
IF missionStage <> MS_LEADIN
AND missionStage <> MS_CUTSCENE
AND missionStage <> MS_FAIL_WAIT_FOR_FADE
AND missionStage <> MS_LOST_RACE
IF missionStage <> MS_END_CUTSCENE
CHECK_PLAYER_COLLISIONS()
ELSE
// Stop the heartbeat audio from playing during the end cutscene if you ride away
//STOP_SOUND(iHeartbeatAudioID)
ENDIF
DEAL_WITH_MARY_ANN()
TRY_OVERTAKE_LINE()
ELIF missionStage = MS_LEADIN
// Disable controls and exit current vehicle
RC_PLAYER_TRIGGER_SCENE_LOCK_IN()
ELIF missionStage = MS_CUTSCENE
IF IS_ENTITY_ALIVE(MARY_ANN)
SET_PED_MAX_MOVE_BLEND_RATIO(MARY_ANN, 2.3)
ENDIF
ENDIF
SWITCH missionStage
CASE MS_LEADIN
LEADIN()
BREAK
CASE MS_CUTSCENE
INTRO_CUTSCENE()
BREAK
CASE MS_START_RUNNING
START_RUNNING()
BREAK
CASE MS_ROAD_RUNNING_SECTION
ROAD_RUNNING_SECTION()
BREAK
CASE MS_STEPS_DOWN
STEPS_DOWN()
BREAK
CASE MS_SPRINT_TO_FINISH
SPRINT_TO_FINISH()
BREAK
CASE MS_DEBUG_NEAR_FINISH_LINE
DEBUG_NEAR_FINISH_LINE()
BREAK
CASE MS_PLAYER_IN_VEHICLE
STAGE_PLAYER_IN_VEHICLE()
BREAK
CASE MS_END_CUTSCENE
END_CUTSCENE()
BREAK
CASE MS_LOST_RACE
LOST_RACE()
BREAK
CASE MS_FAIL_WAIT_FOR_FADE
FAIL_WAIT_FOR_FADE()
BREAK
ENDSWITCH
#IF IS_DEBUG_BUILD
DEBUG_Check_Debug_Keys()
#ENDIF
ENDWHILE
// Script should never reach here. Always terminate with cleanup function.
ENDSCRIPT