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

5355 lines
187 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 "select_mission_stage.sch"
USING "RC_Helper_Functions.sch"
USING "drunk_public.sch"
USING "commands_ped.sch"
USING "script_ped.sch"
USING "shared_hud_displays.sch"
USING "cellphone_public.sch"
USING "dialogue_public.sch"
USING "CompletionPercentage_public.sch"
USING "RC_Threat_public.sch"
USING "RC_Area_public.sch"
USING "RC_Setup_public.sch"
USING "initial_scenes_fanatic.sch"
USING "rgeneral_include.sch"
USING "cheat_controller_public.sch"
USING "commands_recording.sch"
// *****************************************************************************************
// *****************************************************************************************
// *****************************************************************************************
//
// MISSION NAME : Fanatic3.sc
// AUTHOR : Ian Gander
// DESCRIPTION : Franklin meets Mary-Ann on a beach, and after some flirting,
// she challenges him to a triathalon of swimming, cycling and
// jogging
//
// *****************************************************************************************
// *****************************************************************************************
g_structRCScriptArgs sRCLauncherDataLocal
ENUM MISSION_STAGE
MS_LEADIN = -1,
MS_INTRO = 0,
MS_SWIM = 1,
MS_TO_BIKE = 2,
MS_BIKE = 3,
MS_OFF_BIKE = 4,
MS_RUN = 5,
MS_DONE = 6,
MS_FAILED = 7,
MS_LOST
ENDENUM
ENUM SUB_STATE
SS_INIT = 0,
SS_RUNNING = 1,
SS_CLEANUP = 2
ENDENUM
ENUM FAILED_REASON
FAILED_GENERIC = 0,
FAILED_BIKE_DESTROYED,
FAILED_YOURBIKE_DESTROYED,
FAILED_OUT_OF_TIME,
FAILED_LOST_RACE,
FAILED_WOMAN_DIED,
FAILED_WOMAN_HURT,
FAILED_WOMAN_SCARED,
FAILED_LEFT_BIKE,
FAILED_LEFT_AREA
ENDENUM
MISSION_STAGE missionStage = MS_LEADIN
MISSION_STAGE opponentStage
SUB_STATE subState = SS_INIT
// Checkpoints
CONST_INT CP_SWIM 0
CONST_INT CP_BIKE 1
CONST_INT CP_JOG 2
CONST_INT CP_OUTRO 3
MODEL_NAMES bike_model = scorcher
MODEL_NAMES DOG_MODEL = A_C_RETRIEVER // Not sure if the dog model is final, so this'll make it easy to change
VEHICLE_INDEX bike_vehicle
VEHICLE_INDEX opponent_bike_vehicle
VEHICLE_INDEX players_bike = NULL
VEHICLE_INDEX opponent_goto_bike
VEHICLE_INDEX opponent_car
VEHICLE_INDEX bad_driver_car
VEHICLE_INDEX picniccar2
VEHICLE_INDEX EndingBikeMA
VECTOR vEndingBikeMASpawn = <<87.438637,7032.115234,12.044374>>
FLOAT fEndingBikeMASpawn = 151.459
PED_INDEX bad_driver_ped
PED_INDEX fence_worker
PED_INDEX binoculars_guy
PED_INDEX chinups_guy
PED_INDEX stretching_woman
PED_INDEX running_dog
PED_INDEX dog_owner
OBJECT_INDEX binocs
CONST_INT MAX_SWIM_POSITIONS 7
CONST_INT MAX_BIKE_POSITIONS 11
CONST_INT MAX_RUN_POSITIONS 11
VECTOR SWIM_POSITIONS[MAX_SWIM_POSITIONS]
VECTOR BIKE_POSITIONS[MAX_BIKE_POSITIONS]
VECTOR RUN_POSITIONS[MAX_RUN_POSITIONS]
VECTOR vSwimSkip = << -909.0488, 6142.6167, 4.2883 >>
VECTOR vBikeSkip = << -673.7409, 6138.0962, 1.0698 >>
VECTOR vJogSkip = << 51.9898, 6768.9653, 19.7661 >>
VECTOR vOutroSkip = << 64.17, 7048.68, 15.61 >>
FLOAT fSwimSkip = 270.65
FLOAT fBikeSkip = 264.38
FLOAT fJogSkip = 313.15
FLOAT fOutroSkip = 195.495
VECTOR opponent_pos
CHECKPOINT_INDEX checkpoint
CHECKPOINT_INDEX PrevCheckpoint
INT iPrevAlpha = 180
BLIP_INDEX blip
BLIP_INDEX nextblip
BLIP_INDEX additional_blip
BLIP_INDEX opponent_blip
int iStopTime
INT iPushTime
INT current_max_positions
INT current_position
INT current_opponent_position
INT current_opponent_max_positions
INT race_pos = 1
Bool won_last_stage = FALSE
HUD_COLOURS currentCPColour // Have to stick this here for the checkpoint reload
PED_INDEX opponent
STRING sOpponentWaypointName
CONST_FLOAT RACING_MODIFIER 0.5
BOOL bDoMAIntroBoost = FALSE
INT iMAIntroBoostTimer = -1
CONST_INT INTRO_BOOST_TIME 5000
int iPushStage = 0
int iBinocStage = 0
int iStretchStage = 0
int iChinupStage = 0
int iOwnerStage = 0
int iOutroStage = 0
int iFailStage = 0
FAILED_REASON FailReason = FAILED_GENERIC
int iOutroTimer
int iTrashTalkTimer
INT iCutsceneStage = 0
BOOL race_won = FALSE
BOOL intro_requested = FALSE
BOOL intro_playing = FALSE
BOOL bIntroSkipped = FALSE
//BOOL boat_launched = FALSE
//BOOL jetski_conv_launched = FALSE
//BOOL maryann_jetski_conv_launched = FALSE
BOOL get_back_on_said = FALSE
BOOL bike_around_trail_said = FALSE
BOOL bad_driver_launched = FALSE
BOOL bMADoingJump = FALSE
BOOL bMAJumpFailed = false
BOOL bMAPlayerFailComment = TRUE // True by default - we turn it false if the player fails the jump, so then the dialogue can be played
BOOL bCheated = FALSE
BOOL bDoneSwimDialogue = FALSE
BOOL bTrashTalkActive = FALSE
BOOL bGivePushWarning = FALSE
BOOL bZSkipActive = FALSE // Used for covering up the forced-run if the player skips the cutscene
BOOL bAbandonmentWarning = FALSE
BOOL bDebugRubberBanding = FALSE
BOOL bLoadedBike = false
BOOL bLoadedRun = false
BOOL bSkipped = FALSE
BOOL bConvoPaused = FALSE
//BOOL bCheat1Said = FALSE
BOOL bCheat2Said = FALSE
BOOL bCheat3Said = FALSE
BOOL bMissedCheckWarning = FALSE
BOOL bCheatReload = FALSE
BOOL bMaryAnnInFinalArea = FALSE
BOOL bOutroMALeave = FALSE
VECTOR vRoadDisableAA1 = <<-222.053223,6535.530273,2.351944>>
VECTOR vRoadDisableAA2 = <<-638.4162, 6057.3403,26.191582>>
FLOAT fRoadDisableAA = 176.25
REL_GROUP_HASH RelGroupBuddy
BOOL bLeadInConv = FALSE
FLOAT fHintFov = 30.0
FLOAT fHintFollow = 0.35
FLOAT fHintPitchOrbit = 0.000
FLOAT fHintSide = 0.10
FLOAT fHintVert = 0.075 //-0.050
// start_time - used to track the time at which the race started
// race_timer - the eventual total elapsed race time that is displayed
// replay_timer_addition - used to add any previous time that was accrued in previous attempts at the mission, if starting from a replay
INT start_time
int race_timer
int replay_timer_addition = 0
SEQUENCE_INDEX seq
BOOL bReplayTrackOn = FALSE
STRUCT SMACK_TALK
BOOL already_said
STRING ConvRoot
ENDSTRUCT
#IF IS_DEBUG_BUILD
MissionStageMenuTextStruct s_skip_menu[5]
INT menu_option
BOOL bDebug_PrintToTTY = TRUE
WIDGET_GROUP_ID widgetGroup
#ENDIF
CONST_INT MAX_SMACK_TALK 3
SMACK_TALK smack[5][MAX_SMACK_TALK]
structPedsForConversation conversation
structPedsForConversation conv_frank
TEST_POLY innerBounds
TEST_POLY MaryAnnBikeBounds
// Replay consistency constant
CONST_INT F3_CHECKPOINT_TIME 0
/// PURPOSE:
/// Print a string
/// PARAMS:
/// s - the string
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, then an int
/// PARAMS:
/// s - The string
/// i - The int
PROC DEBUG_PRINTSTRINGINT(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:
/// Print a string, then a float
/// PARAMS:
/// s - The string
/// f - The float
PROC DEBUG_PRINTSTRINGF(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:
/// Checks whether a given conversation root is the one currently playing
/// PARAMS:
/// RootToCheck - The name of the root we want to check
/// RETURNS:
/// True if the root we're searching for is the root currently playing, false otherwise
FUNC BOOL IS_THIS_CONVERSATION_ROOT_PLAYING(STRING RootToCheck)
TEXT_LABEL_23 blah
blah = GET_CURRENTLY_PLAYING_STANDARD_CONVERSATION_ROOT()
IF ARE_STRINGS_EQUAL(blah,RootToCheck)
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// Set the mission as failed and start running the failed state
/// PARAMS:
/// Reason - The reason we're failing for
PROC MISSION_FAILED(FAILED_REASON Reason = FAILED_GENERIC)
DEBUG_PRINTSTRING("MISSION_FAILED CALLED!")
SWITCH Reason
CASE FAILED_GENERIC
DEBUG_PRINTSTRING("MISSION_FAILED reason=FAILED_GENERIC")
BREAK
CASE FAILED_BIKE_DESTROYED
DEBUG_PRINTSTRING("MISSION_FAILED reason=FAILED_BIKE_DESTROYED")
BREAK
CASE FAILED_YOURBIKE_DESTROYED
DEBUG_PRINTSTRING("MISSION_FAILED reason=FAILED_BIKE_DESTROYED")
BREAK
CASE FAILED_OUT_OF_TIME
DEBUG_PRINTSTRING("MISSION_FAILED reason=FAILED_OUT_OF_TIME")
BREAK
CASE FAILED_LOST_RACE
DEBUG_PRINTSTRING("MISSION_FAILED reason=FAILED_LOST_RACE")
BREAK
CASE FAILED_WOMAN_DIED
DEBUG_PRINTSTRING("MISSION_FAILED reason=FAILED_WOMAN_DIED")
BREAK
CASE FAILED_WOMAN_HURT
DEBUG_PRINTSTRING("MISSION_FAILED reason=FAILED_WOMAN_HURT")
BREAK
CASE FAILED_WOMAN_SCARED
DEBUG_PRINTSTRING("MISSION_FAILED reason=FAILED_WOMAN_SCARED")
BREAK
CASE FAILED_LEFT_AREA
DEBUG_PRINTSTRING("MISSION_FAILED reason=FAILED_LEFT_AREA")
BREAK
ENDSWITCH
FailReason = Reason
missionStage = MS_FAILED
ENDPROC
// *******************************************
// Mary-Ann AI brain
// *******************************************
/// PURPOSE:
/// Load the waypoint recordings for Mary Ann's bike section
/// RETURNS:
/// True when the recordings have loaded, false otherwise
FUNC BOOL ma_pLoadBikeRecs()
IF NOT GET_IS_WAYPOINT_RECORDING_LOADED("Fan3_pedBike")
OR NOT GET_IS_WAYPOINT_RECORDING_LOADED("Fan3_pedBikePanic")
OR NOT GET_IS_WAYPOINT_RECORDING_LOADED("Fan3_pedBikePrep")
OR NOT HAS_VEHICLE_RECORDING_BEEN_LOADED(500, "Fan3_MaryAnnBikeJump")
DEBUG_PRINTSTRING("Waiting for Mary Ann's bike recordings to load")
REQUEST_WAYPOINT_RECORDING("Fan3_pedBike")
REQUEST_WAYPOINT_RECORDING("Fan3_pedBikePanic")
REQUEST_WAYPOINT_RECORDING("Fan3_pedBikePrep")
REQUEST_VEHICLE_RECORDING(500, "Fan3_MaryAnnBikeJump")
RETURN FALSE
ENDIF
RETURN TRUE
ENDFUNC
/// PURPOSE:
/// Load the waypoint recording for Mary Ann's jogging section
/// RETURNS:
/// True when the recording has loaded, false otherwise
FUNC BOOL ma_pLoadJogRecs()
IF NOT GET_IS_WAYPOINT_RECORDING_LOADED("fan3_pedJog")
DEBUG_PRINTSTRING("Requesting Mary Ann's jog waypoint recording")
REQUEST_WAYPOINT_RECORDING("fan3_pedJog")
RETURN FALSE
ENDIF
RETURN TRUE
ENDFUNC
/// PURPOSE:
/// Track and check for player failing the bridge jump, and make Mary Ann comment if appropriate
PROC ma_pCommentOnPlayerJumpFail()
// If the player is in here, they've failed the bridge jump, so we want to try and do the convo
if IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<-151.029358,6589.512207,7.479042>>, <<-164.083267,6577.416016,9.015114>>, 6.000000)
bMAPlayerFailComment = FALSE
DEBUG_PRINTSTRING("*** Detected player failed bridge jump")
ENDIF
// If the player has failed the jump, is in the area below the bridge and Mary Ann is close enough, do the convo
IF NOT bMAPlayerFailComment
if IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<-149.377747,6592.477539,1.723418>>, <<-167.096405,6574.677246,7.915183>>, 21.250000)
IF GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), opponent) < 30
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF CREATE_CONVERSATION(conversation, "FAN3AUD", "FAN3_JMPFAIL", CONV_PRIORITY_MEDIUM, DO_NOT_DISPLAY_SUBTITLES)
bMAPlayerFailComment = TRUE //Convo's been launched, stop trying to do it
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Checks the area below the broken bridge jump for Mary Ann for if she fails it during the bike section.
/// If so, switches her to the backup waypoint recording to make her proceed via the beach
PROC ma_pCheckJumpSwitch()
IF IS_VEHICLE_OK(opponent_goto_bike)
AND IS_ENTITY_ALIVE(opponent)
IF NOT bMAJumpFailed
if IS_ENTITY_IN_ANGLED_AREA(opponent_goto_bike, <<-149.377747,6592.477539,1.723418>>, <<-167.096405,6574.677246,5.515183>>, 21.250000)
bMAJumpFailed = TRUE
DEBUG_PRINTSTRING("*** Mary Ann has fallen below the bridge, switching waypoint recording...")
IF IS_WAYPOINT_PLAYBACK_GOING_ON_FOR_VEHICLE(opponent_goto_bike)
sOpponentWaypointName = "Fan3_pedBikePanic"
REMOVE_WAYPOINT_RECORDING("Fan3_pedBike")
TASK_VEHICLE_FOLLOW_WAYPOINT_RECORDING(opponent, opponent_goto_bike, sOpponentWaypointName, DRIVINGMODE_AVOIDCARS, 0, EWAYPOINT_START_FROM_CLOSEST_POINT)
ENDIF
ENDIF
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Grab Mary Ann from the initial scene struct into the local ped index, and set relationships up
PROC ma_pCreate()
IF IS_ENTITY_ALIVE(sRCLauncherDataLocal.pedID[0])
opponent = sRCLauncherDataLocal.pedID[0]
SET_PED_FLEE_ATTRIBUTES(opponent, FA_USE_VEHICLE, TRUE)
ADD_RELATIONSHIP_GROUP("Buddy", RelGroupBuddy)
SET_PED_RELATIONSHIP_GROUP_HASH(opponent, RelGroupBuddy)
SET_RELATIONSHIP_BETWEEN_GROUPS(ACQUAINTANCE_TYPE_PED_LIKE, RelGroupBuddy, RELGROUPHASH_PLAYER)
SET_RELATIONSHIP_BETWEEN_GROUPS(ACQUAINTANCE_TYPE_PED_LIKE, RELGROUPHASH_PLAYER, RelGroupBuddy)
SET_DRIVER_RACING_MODIFIER(opponent, RACING_MODIFIER)
ELSE
REQUEST_MODEL(IG_MARYANN)
WHILE NOT HAS_MODEL_LOADED(IG_MARYANN)
WAIT(0)
ENDWHILE
opponent = CREATE_PED(PEDTYPE_MISSION, IG_MARYANN, <<809.66, 1279.76, 360.49>>, 122.53)
SET_PED_FLEE_ATTRIBUTES(opponent, FA_USE_VEHICLE, TRUE)
ADD_RELATIONSHIP_GROUP("Buddy", RelGroupBuddy)
SET_PED_RELATIONSHIP_GROUP_HASH(opponent, RelGroupBuddy)
SET_RELATIONSHIP_BETWEEN_GROUPS(ACQUAINTANCE_TYPE_PED_LIKE, RelGroupBuddy, RELGROUPHASH_PLAYER)
SET_RELATIONSHIP_BETWEEN_GROUPS(ACQUAINTANCE_TYPE_PED_LIKE, RELGROUPHASH_PLAYER, RelGroupBuddy)
SET_DRIVER_RACING_MODIFIER(opponent, RACING_MODIFIER)
ENDIF
opponentStage = MS_INTRO
ENDPROC
/// PURPOSE:
/// Set Mary Ann and other various peds to flee, then fail the mission for scaring her
PROC ma_pAggroFail()
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
KILL_FACE_TO_FACE_CONVERSATION_DO_NOT_FINISH_LAST_LINE()
ADD_NON_CRITICAL_STANDARD_CONVERSATION_TO_BUFFER(conversation, "FAN3AUD", "FAN3_SCARED", CONV_PRIORITY_VERY_HIGH, DO_NOT_DISPLAY_SUBTITLES)
ELSE
CREATE_CONVERSATION(conversation, "FAN3AUD", "FAN3_SCARED", CONV_PRIORITY_VERY_HIGH, DO_NOT_DISPLAY_SUBTITLES)
ENDIF
SAFE_REMOVE_BLIP(opponent_blip)
SET_PED_KEEP_TASK(opponent, true)
IF IS_PED_IN_ANY_VEHICLE(opponent)
TASK_VEHICLE_MISSION_PED_TARGET(opponent, GET_VEHICLE_PED_IS_IN(opponent), PLAYER_PED_ID(), MISSION_FLEE, 30, DRIVINGMODE_AVOIDCARS, 100, 0.1, TRUE)
SET_PED_FLEE_ATTRIBUTES(opponent, FA_USE_VEHICLE, TRUE)
DEBUG_PRINTSTRING("Setting Mary Ann Use Vehicle flee attribute")
ELSE
TASK_SMART_FLEE_PED(opponent, PLAYER_PED_ID(), 100, -1)
ENDIF
IF IS_ENTITY_ALIVE(binoculars_guy)
SET_PED_FLEE_ATTRIBUTES(binoculars_guy, FA_USE_VEHICLE | FA_DISABLE_HANDS_UP, TRUE)
SET_PED_KEEP_TASK(opponent, true)
TASK_SMART_FLEE_PED(opponent, PLAYER_PED_ID(), 100, -1)
endif
//PRINT_NOW("FATIC3_13", DEFAULT_GOD_TEXT_TIME, 1) //You scared Mary Ann.
MISSION_FAILED(FAILED_WOMAN_SCARED)
ENDPROC
/// PURPOSE:
/// If able, make Mary Ann warn the player about pushing her while on the bike, and fail the mission on the third push
PROC ma_pGivePushWarning() // This needs to repeat until the warning has been given, since it takes AGES for the conversation to build
IF bGivePushWarning
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
KILL_FACE_TO_FACE_CONVERSATION_DO_NOT_FINISH_LAST_LINE()
ELSE
IF opponentStage = MS_BIKE
OR opponentStage = MS_TO_BIKE
SWITCH iPushStage
CASE 0
IF PLAY_SINGLE_LINE_FROM_CONVERSATION(conversation, "FAN3AUD", "FAN3_PUSH", "FAN3_PUSH_1", CONV_PRIORITY_HIGH)
iPushStage++
bGivePushWarning = FALSE
DEBUG_PRINTSTRING("Push warning given: 1...")
iPushTime = GET_GAME_TIMER() // Reset the timer
ENDIF
BREAK
CASE 1
IF PLAY_SINGLE_LINE_FROM_CONVERSATION(conversation, "FAN3AUD", "FAN3_PUSH", "FAN3_PUSH_2", CONV_PRIORITY_HIGH)
iPushStage++
bGivePushWarning = FALSE
DEBUG_PRINTSTRING("Push warning given: 2...")
iPushTime = GET_GAME_TIMER() // Reset the timer
ENDIF
BREAK
CASE 2
DEBUG_PRINTSTRING("Push warning given: 3, you fail...")
ma_pAggroFail()
BREAK
ENDSWITCH
ELIF opponentStage = MS_SWIM
SWITCH iPushStage
CASE 0
CASE 1
CASE 2
IF CREATE_CONVERSATION(conversation, "FAN3AUD", "FAN3_IMP", CONV_PRIORITY_MEDIUM)
bGivePushWarning = FALSE
DEBUG_PRINTSTRINGINT("Swim push warning given: ", iPushStage)
iPushTime = GET_GAME_TIMER() // Reset the timer
iPushStage++
ENDIF
BREAK
ENDSWITCH
ENDIF
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Check for any aggro against Mary Ann from the player, and call ma_pAggroFail() if so
PROC ma_pCheckAggro()
IF IS_ENTITY_ALIVE(opponent)
if IS_PLAYER_SHOOTING_NEAR_PED(opponent)
OR IS_BULLET_IN_AREA(GET_ENTITY_COORDS(opponent), 40, FALSE)
OR HAS_ENTITY_BEEN_DAMAGED_BY_ENTITY(opponent, PLAYER_PED_ID())
ma_pAggroFail()
ENDIF
// The melee check has to be separate since it's a horrible nested thing
IF GET_DISTANCE_BETWEEN_PEDS(PLAYER_PED_ID(), opponent) < 1
IF IS_PED_IN_MELEE_COMBAT(PLAYER_PED_ID())
// If the player is <1m from Mary Ann and is melee'ing, assume they're trying to hit Mary Ann and scare her off
// I'm not mad keen on this solution, but I'm not sure how else to handle it...
ma_pAggroFail()
ENDIF
ENDIF
IF opponentStage = MS_BIKE
OR opponentStage = MS_TO_BIKE
IF NOT IS_POINT_IN_POLY_2D(MaryAnnBikeBounds, GET_ENTITY_COORDS(opponent))
DEBUG_PRINTSTRING("Mary Ann not detected in race area! Failing the mission for this!!")
ma_pAggroFail() // Mary Ann has left the bike route area and is likely in a spot she can't recover from
ENDIF
IF NOT bGivePushWarning
IF IS_VEHICLE_OK(players_bike) AND IS_VEHICLE_OK(opponent_goto_bike)
IF IS_ENTITY_TOUCHING_ENTITY(players_bike, opponent_goto_bike)
OR IS_ENTITY_TOUCHING_ENTITY(PLAYER_PED_ID(), opponent_goto_bike)
IF IS_ENTITY_TOUCHING_ENTITY(players_bike, opponent_goto_bike)
DEBUG_PRINTSTRING("Player's bike touched Mary Ann's bike!")
ENDIF
IF IS_ENTITY_TOUCHING_ENTITY(PLAYER_PED_ID(), opponent_goto_bike)
DEBUG_PRINTSTRING("The player touched Mary Ann's bike!")
ENDIF
IF (GET_GAME_TIMER() - iPushTime) > 2000
bGivePushWarning = TRUE // Activates the push dialogue/check
ENDIF
ENDIF
ENDIF
ENDIF
ELIF opponentStage = MS_SWIM
IF NOT bGivePushWarning // Reuse the push warning stuff as it's fairly good
IF IS_ENTITY_TOUCHING_ENTITY(PLAYER_PED_ID(), opponent)
AND race_pos = 1
DEBUG_PRINTSTRING("The player touched Mary Ann's during swim!")
IF (GET_GAME_TIMER() - iPushTime) > 2000
bGivePushWarning = TRUE // Activates the push dialogue/check
ENDIF
ENDIF
ENDIF
ENDIF
if race_pos = 2
if GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), GET_ENTITY_COORDS(opponent)) >= 300
//PRINT_NOW("FATIC3_16", DEFAULT_GOD_TEXT_TIME, 1) //You fell too far behind.
MISSION_FAILED(FAILED_OUT_OF_TIME)
ENDIF
//DEBUG_PRINTSTRINGF("Distance:", GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), GET_ENTITY_COORDS(opponent)))
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Give Mary Ann the very first task she needs when starting a new stage during the race (incl. getting on and off the bike)
/// PARAMS:
/// currentStage - The stage we want to call the first task for
PROC ma_pGiveFirstTask(MISSION_STAGE currentStage)
// The first task given to the opponent when switching to a new stage
current_opponent_position = 0
SWITCH currentStage
CASE MS_SWIM
current_opponent_max_positions = MAX_SWIM_POSITIONS
IF IS_ENTITY_ALIVE(opponent)
TASK_GO_STRAIGHT_TO_COORD(opponent, (SWIM_POSITIONS[current_opponent_position]), PEDMOVE_RUN, DEFAULT_TIME_BEFORE_WARP)
ENDIF
BREAK
CASE MS_TO_BIKE
IF IS_ENTITY_ALIVE(bike_vehicle) AND IS_ENTITY_ALIVE(opponent_bike_vehicle)
IF IS_VEHICLE_SEAT_FREE(opponent_bike_vehicle, VS_DRIVER)
opponent_goto_bike = opponent_bike_vehicle
ELIF IS_VEHICLE_SEAT_FREE(bike_vehicle, VS_DRIVER)
opponent_goto_bike = bike_vehicle
ELSE
SCRIPT_ASSERT("Both bikes are full?")
ENDIF
IF IS_ENTITY_ALIVE(opponent)
TASK_ENTER_VEHICLE(opponent, opponent_goto_bike, DEFAULT_TIME_BEFORE_WARP, VS_DRIVER, PEDMOVE_SPRINT)
ENDIF
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF race_pos = 1 // If the player is currently leading the race
CREATE_CONVERSATION(conversation, "FAN3AUD", "FAN3_SWIMWIN", CONV_PRIORITY_MEDIUM, DO_NOT_DISPLAY_SUBTITLES)
ELSE
CREATE_CONVERSATION(conversation, "FAN3AUD", "FAN3_SWIMLOS", CONV_PRIORITY_MEDIUM, DO_NOT_DISPLAY_SUBTITLES)
ENDIF
ENDIF
iPushTime = GET_GAME_TIMER()
iPushStage = 0
ENDIF
BREAK
CASE MS_BIKE
current_opponent_max_positions = MAX_BIKE_POSITIONS
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF NOT IS_MESSAGE_BEING_DISPLAYED()
OR GET_PROFILE_SETTING(PROFILE_DISPLAY_SUBTITLES) = 0
CREATE_CONVERSATION(conversation, "FAN3AUD", "FAN3_RUNTO", CONV_PRIORITY_MEDIUM, DISPLAY_SUBTITLES)
ELSE
CREATE_CONVERSATION(conversation, "FAN3AUD", "FAN3_RUNTO", CONV_PRIORITY_MEDIUM, DO_NOT_DISPLAY_SUBTITLES)
ENDIF
ENDIF
ma_pLoadBikeRecs()
BREAK
CASE MS_OFF_BIKE
IF IS_ENTITY_ALIVE(opponent) AND IS_VEHICLE_OK(opponent_goto_bike)
IF IS_WAYPOINT_PLAYBACK_GOING_ON_FOR_VEHICLE(opponent_goto_bike)
REMOVE_WAYPOINT_RECORDING("Fan3_pedBike")
REMOVE_WAYPOINT_RECORDING("Fan3_pedBikePanic")
ENDIF
IF IS_PED_IN_VEHICLE(opponent, opponent_goto_bike)
BRING_VEHICLE_TO_HALT(opponent_goto_bike, 5, 10)
TASK_LEAVE_ANY_VEHICLE(opponent)
ENDIF
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF race_pos = 1 // If the player is currently leading the race
CREATE_CONVERSATION(conversation, "FAN3AUD", "FAN3_BIKEWIN", CONV_PRIORITY_MEDIUM, DO_NOT_DISPLAY_SUBTITLES)
ELSE
CREATE_CONVERSATION(conversation, "FAN3AUD", "FAN3_BIKELOS", CONV_PRIORITY_MEDIUM, DO_NOT_DISPLAY_SUBTITLES)
ENDIF
ENDIF
ENDIF
BREAK
CASE MS_RUN
current_opponent_max_positions = MAX_RUN_POSITIONS
ma_pLoadJogRecs()
BREAK
CASE MS_FAILED
BREAK
DEFAULT
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE:
/// Switch Mary Ann to a new state during the race, then call ma_pGiveFirstTask() to set her going
/// Note: does not teleport her, must be done before this is called if used for a skip!
/// PARAMS:
/// newStage - The stage we want Mary Ann to switch to
PROC ma_pSwitchState(MISSION_STAGE newStage)
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
KILL_ANY_CONVERSATION()
ENDIF
IF newStage <> opponentStage
opponentStage = newStage
ma_pGiveFirstTask(newStage)
ELIF bSkipped = TRUE
ma_pGiveFirstTask(newStage) //If we're currently skipping back to the start of the current stage, retask Mary Ann
ENDIF
bConvoPaused = FALSE
ENDPROC
/// PURPOSE:
/// If Mary Ann falls too far behind in the bike race, secretly teleport her ahead a bit
PROC ma_pCheckForTeleport()
IF opponentStage = MS_BIKE
AND missionStage = MS_BIKE
IF race_pos = 1 // If the player is ahead
IF IS_ENTITY_ALIVE(opponent)
AND IS_ENTITY_ALIVE(PLAYER_PED_ID())
IF ARE_STRINGS_EQUAL(sOpponentWaypointName, "Fan3_pedBike")
// Getting the player's current closest waypoint now to use in the IF check...
int iCurrPlayerWaypoint
WAYPOINT_RECORDING_GET_CLOSEST_WAYPOINT(sOpponentWaypointName, GET_ENTITY_COORDS(PLAYER_PED_ID()), iCurrPlayerWaypoint)
IF GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), GET_ENTITY_COORDS(opponent)) > 65 // If player is >65m ahead...
AND iCurrPlayerWaypoint > 26 // ... and past the 26th waypoint...
AND IS_WAYPOINT_PLAYBACK_GOING_ON_FOR_VEHICLE(opponent_goto_bike) // ... and if Mary Ann is doing a waypoint recording
IF IS_ENTITY_ALIVE(opponent_goto_bike)
// Get the nearest waypoints to Mary Ann
int iCurrOpponentWaypoint
IF IS_WAYPOINT_PLAYBACK_GOING_ON_FOR_VEHICLE(opponent_goto_bike)
WAYPOINT_RECORDING_GET_CLOSEST_WAYPOINT(sOpponentWaypointName, GET_ENTITY_COORDS(opponent_goto_bike), iCurrOpponentWaypoint)
WAYPOINT_RECORDING_GET_CLOSEST_WAYPOINT(sOpponentWaypointName, GET_ENTITY_COORDS(PLAYER_PED_ID()), iCurrPlayerWaypoint)
ENDIF
// We want to teleport Mary Ann about 5 waypoints behind the player, so let's take that amount off of the player's nearest WP
iCurrPlayerWaypoint -= 5
// And we need that waypoint's vector, and the vector of the next one
VECTOR vWaypointDestCoord
VECTOR vWayPointDestNextCoord
WAYPOINT_RECORDING_GET_COORD(sOpponentWaypointName, iCurrPlayerWaypoint, vWaypointDestCoord)
WAYPOINT_RECORDING_GET_COORD(sOpponentWaypointName, iCurrPlayerWaypoint+1, vWayPointDestNextCoord)
// Only teleport if we can't see the old AND the new locations
IF NOT IS_SPHERE_VISIBLE(GET_ENTITY_COORDS(opponent), 3)
AND NOT IS_SPHERE_VISIBLE(vWaypointDestCoord, 3)
FLOAT fOldSpeed = GET_ENTITY_SPEED(opponent)
SET_ENTITY_COORDS(opponent_goto_bike, vWaypointDestCoord)
SET_ENTITY_HEADING_FACE_COORDS(opponent_goto_bike, vWayPointDestNextCoord) // Face next checkpoint
IF NOT IS_PED_IN_VEHICLE(opponent, opponent_goto_bike)
SET_PED_INTO_VEHICLE(opponent, opponent_goto_bike)
ENDIF
TASK_VEHICLE_FOLLOW_WAYPOINT_RECORDING(opponent, opponent_goto_bike, sOpponentWaypointName, DRIVINGMODE_AVOIDCARS|DF_SteerAroundPeds, 0,
EWAYPOINT_START_FROM_CLOSEST_POINT|EWAYPOINT_VEHICLES_USE_AI_SLOWDOWN)
SET_VEHICLE_FORWARD_SPEED(opponent_goto_bike, fOldSpeed)
DEBUG_PRINTSTRINGINT("*** Teleported Mary Ann to waypoint ", iCurrPlayerWaypoint)
// Now we need to make sure she's not skipped over a checkpoint during the teleport...
IF iCurrPlayerWaypoint < 14
current_opponent_position = 0 // Mary Ann is before the first checkpoint (will this even get called?)
ELIF iCurrPlayerWaypoint < 26
current_opponent_position = 1 // Just before the second CP...
ELIF iCurrPlayerWaypoint < 35
current_opponent_position = 2 // and so on...
ELIF iCurrPlayerWaypoint < 45
current_opponent_position = 3 // ... so Mary Ann should hit the checkpoints ahead of these waypoints
ELIF iCurrPlayerWaypoint < 53
current_opponent_position = 4 // ... and her checkpoint counter will increment right after the teleport
ELIF iCurrPlayerWaypoint < 60
current_opponent_position = 5 // ... in theory
ELIF iCurrPlayerWaypoint < 68
current_opponent_position = 6 // Hey, if you're reading this, that means I checked it in because it worked
ELIF iCurrPlayerWaypoint < 79
current_opponent_position = 7
ELIF iCurrPlayerWaypoint < 98
current_opponent_position = 8
ELIF iCurrPlayerWaypoint < 135
current_opponent_position = 9
ELSE
// No idea where Mary Ann is, so let's just put her here
current_opponent_position = 9
ENDIF
// If Mary Ann was on the beach panic route, she won't get teleported
ELSE
DEBUG_PRINTSTRING("*** Trying to teleport, but points are visible!!")
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDPROC
FLOAT fPriorSpeed
PROC ma_pDoBridgeJump(int iCurrWaypoint = 0)
CONST_FLOAT BRIDGE_BOOST_SPEED 20.0
IF IS_ENTITY_ALIVE(opponent_goto_bike)
IF IS_WAYPOINT_PLAYBACK_GOING_ON_FOR_VEHICLE(opponent_goto_bike)
// When we get to waypoint 7 in the jump prep waypoint recording, transition Mary Ann to the vehicle recording for the actual jump
IF iCurrWaypoint >= 7
// This is for if I need to re-record the jump recording, leave commented out for release builds!
// IF NOT IS_RECORDING_GOING_ON_FOR_VEHICLE(opponent_goto_bike)
// START_RECORDING_VEHICLE(opponent_goto_bike, 500, "Fan3_MaryAnnBikeJump", TRUE)
// ENDIF
IF NOT IS_PLAYBACK_USING_AI_GOING_ON_FOR_VEHICLE(opponent_goto_bike)
AND NOT IS_PLAYBACK_GOING_ON_FOR_VEHICLE(opponent_goto_bike)
DEBUG_PRINTSTRING("******* USING RECORDING NOW")
bMADoingJump = TRUE
// Uses AI to smoothly transition from the waypoint playback position to the exact recorded position needed for the jump
START_PLAYBACK_RECORDED_VEHICLE_USING_AI(opponent_goto_bike, 500, "Fan3_MaryAnnBikeJump", BRIDGE_BOOST_SPEED+1.0, DRIVINGMODE_PLOUGHTHROUGH)
SET_PLAYBACK_TO_USE_AI_TRY_TO_REVERT_BACK_LATER(opponent_goto_bike, 1250, DRIVINGMODE_PLOUGHTHROUGH, TRUE)
ENDIF
ENDIF
//***************
// Everything down here in this section is used for re-recording the jump vehicle recording and won't affect normal gameplay
//***************
// If the prior speed is 0 (basically if we haven't done it yet), get Mary Ann's current speed this frame
IF fPriorSpeed = 0.0
fPriorSpeed = GET_ENTITY_SPEED(opponent)
ENDIF
// The waypoint #'s will probably have to change if the jump prep waypoint rec changes
// It's a vehicle boost so Mary Ann can actually make the jump
IF iCurrWaypoint >= 7
AND iCurrWaypoint <= 16
float fPlaybackSpd = fPriorSpeed + 0.1
IF fPlaybackSpd > BRIDGE_BOOST_SPEED
fPlaybackSpd = BRIDGE_BOOST_SPEED
ENDIF
fPriorSpeed = fPlaybackSpd
//DEBUG_PRINTSTRINGF("Mary Ann bridge boost: setting fPlaybackSpd to ", fPlaybackSpd)
//DEBUG_PRINTSTRINGF("Actual entity speed is ", GET_ENTITY_SPEED(opponent))
//SET_VEHICLE_FORWARD_SPEED(opponent_goto_bike, fPlaybackSpd)
//VEHICLE_WAYPOINT_PLAYBACK_OVERRIDE_SPEED(opponent_goto_bike, fPlaybackSpd)
ENDIF
// Stop recording once we've reached waypoint 20 in the jump prep waypoint rec
IF iCurrWaypoint >= 20
DEBUG_PRINTSTRING("******* SWITCHING BACK TO WAYPOINT")
// IF IS_RECORDING_GOING_ON_FOR_VEHICLE(opponent_goto_bike)
// DEBUG_PRINTSTRING("******* STOPPING RECORDING")
// STOP_RECORDING_VEHICLE(opponent_goto_bike)
// ENDIF
IF IS_PLAYBACK_GOING_ON_FOR_VEHICLE(opponent_goto_bike)
DEBUG_PRINTSTRING("******* STOPPING PLAYBACK")
STOP_PLAYBACK_RECORDED_VEHICLE(opponent_goto_bike)
ENDIF
sOpponentWaypointName = "Fan3_pedBike"
TASK_VEHICLE_FOLLOW_WAYPOINT_RECORDING(opponent, opponent_goto_bike, sOpponentWaypointName, DRIVINGMODE_AVOIDCARS|DF_SteerAroundPeds, 0,
EWAYPOINT_START_FROM_CLOSEST_POINT|EWAYPOINT_VEHICLES_USE_AI_SLOWDOWN)
bMADoingJump = FALSE
ENDIF
ELSE
// If we're here, Mary Ann's doing the bridge jump via vehicle recording and we need to switch her back to waypoint when appropriate
WAYPOINT_RECORDING_GET_CLOSEST_WAYPOINT(sOpponentWaypointName, GET_ENTITY_COORDS(opponent_goto_bike), iCurrWaypoint)
DEBUG_PRINTSTRINGINT("DOING RECORDING, CLOSEST WP IS: ", iCurrWaypoint)
IF iCurrWaypoint >= 20
DEBUG_PRINTSTRING("******* SWITCHING BACK TO WAYPOINT")
IF IS_PLAYBACK_GOING_ON_FOR_VEHICLE(opponent_goto_bike)
or IS_PLAYBACK_USING_AI_GOING_ON_FOR_VEHICLE(opponent_goto_bike)
DEBUG_PRINTSTRING("******* STOPPING PLAYBACK")
STOP_PLAYBACK_RECORDED_VEHICLE(opponent_goto_bike)
ENDIF
// Retask to use the full route again - back to the rubber banding function!
sOpponentWaypointName = "Fan3_pedBike"
TASK_VEHICLE_FOLLOW_WAYPOINT_RECORDING(opponent, opponent_goto_bike, sOpponentWaypointName, DRIVINGMODE_AVOIDCARS|DF_SteerAroundPeds, 0,
EWAYPOINT_START_FROM_CLOSEST_POINT|EWAYPOINT_VEHICLES_USE_AI_SLOWDOWN)
bMADoingJump = FALSE
ENDIF
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Rubber band Mary Ann's speed during all stages of the race
PROC ma_pRubberBanding()
float fDist
float fRatioModifier
float fMoveRatio = 2.0
fDist = GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), GET_ENTITY_COORDS(opponent))
IF fDist > 45
fDist = 45
ENDIF
fRatioModifier = (fDist / 100)
IF race_pos = 2 // If player is in second place...
IF opponentStage = MS_SWIM
IF IS_ENTITY_ALIVE(opponent)
fMoveRatio = fMoveRatio - fRatioModifier // Reduce opponent speed
SET_PED_DESIRED_MOVE_BLEND_RATIO(opponent, fMoveRatio + 0.2) // Slow her down just a little bit for swimming
IF bDebugRubberBanding
//DEBUG_PRINTSTRINGINT("race_pos:", race_pos)
DEBUG_PRINTSTRINGF("fDist is", fDist)
DEBUG_PRINTSTRINGF("Setting fMoveRatio to", fMoveRatio)
ENDIF
ENDIF
ELIF opponentStage = MS_RUN
IF IS_ENTITY_ALIVE(opponent)
fMoveRatio = fMoveRatio - fRatioModifier // Reduce opponent speed
fMoveRatio += 0.5
IF IS_WAYPOINT_PLAYBACK_GOING_ON_FOR_PED(opponent)
WAYPOINT_PLAYBACK_OVERRIDE_SPEED(opponent, fMoveRatio)
ENDIF
IF bDebugRubberBanding
//DEBUG_PRINTSTRINGINT("race_pos:", race_pos)
DEBUG_PRINTSTRINGF("fDist is", fDist)
DEBUG_PRINTSTRINGF("Setting fMoveRatio to", fMoveRatio)
ENDIF
ENDIF
ELIF opponentStage = MS_BIKE
// As Mary Ann gets closer to Franklin, the amount we're pulling her back by decreases until it's basically nil and then there's basically no rubber banding
// If the distance is <5m, can it to that so we're always slowing her down a little bit
IF fDist < 5
fDist = 5
fRatioModifier = (fDist / 100)
ENDIF
IF IS_ENTITY_ALIVE(opponent_goto_bike)
IF GET_IS_WAYPOINT_RECORDING_LOADED("Fan3_pedBike")
AND GET_IS_WAYPOINT_RECORDING_LOADED("Fan3_pedBikePrep")
IF IS_WAYPOINT_PLAYBACK_GOING_ON_FOR_VEHICLE(opponent_goto_bike)
// We get the nearest waypoint to the opponent's current position...
int iCurrWaypoint
WAYPOINT_RECORDING_GET_CLOSEST_WAYPOINT(sOpponentWaypointName, GET_ENTITY_COORDS(opponent_goto_bike), iCurrWaypoint)
// ... and then dial-down the speed of that waypoint to set the opponent's rubber-banded speed
// If Mary Ann is around the bridge, let her get up to the recorded speed so she makes the jump - otherwise, rubber band her
IF ARE_STRINGS_EQUAL(sOpponentWaypointName, "Fan3_pedBike")
IF iCurrWaypoint < 98
OR iCurrWaypoint >= 107
float fPlaybackSpd = WAYPOINT_RECORDING_GET_SPEED_AT_POINT(sOpponentWaypointName, iCurrWaypoint)
// The ratio modifier is by default calculated for on-foot speeds at 0.2, 0.3, etc, for the other two sections
// Here, we want it to apply to vehicle values, between 2.0, 3.0, etc - so multiply by 10
fRatioModifier = (fRatioModifier * 10)
fPlaybackSpd = ((fPlaybackSpd - fRatioModifier) - 7.5)
IF bDebugRubberBanding
DEBUG_PRINTSTRINGF("fRatioModifier is ", fRatioModifier)
DEBUG_PRINTSTRINGF("Setting fPlaybackSpd to ", fPlaybackSpd)
DEBUG_PRINTSTRINGF("Actual entity speed is ", GET_ENTITY_SPEED(opponent))
//DEBUG_PRINTSTRINGF("Distance is ", GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), GET_ENTITY_COORDS(opponent)))
ENDIF
VEHICLE_WAYPOINT_PLAYBACK_OVERRIDE_SPEED(opponent_goto_bike, fPlaybackSpd)
ENDIF
IF iCurrWaypoint > 93
AND iCurrWaypoint < 98
DEBUG_PRINTSTRING("**** SWITCHING TO JUMP PREP")
sOpponentWaypointName = "Fan3_pedBikePrep"
TASK_VEHICLE_FOLLOW_WAYPOINT_RECORDING(opponent, opponent_goto_bike, sOpponentWaypointName, DRIVINGMODE_PLOUGHTHROUGH, 0,
EWAYPOINT_START_FROM_CLOSEST_POINT|EWAYPOINT_VEHICLES_USE_AI_SLOWDOWN)
ENDIF
ELSE
ma_pDoBridgeJump(iCurrWaypoint)
ENDIF
ELSE
ma_pDoBridgeJump()
ENDIF
ENDIF
ENDIF
ENDIF
ELSE // Player is in first place
IF opponentStage = MS_SWIM
IF IS_ENTITY_ALIVE(opponent)
fMoveRatio = fMoveRatio + fRatioModifier // Increase opponent speed
fMoveRatio+=0.9
IF fMoveRatio > 3.0
fMoveRatio = 3.0 // Cap the ratio to 3.0, because it's the max
ENDIF
SET_PED_DESIRED_MOVE_BLEND_RATIO(opponent, fMoveRatio)
IF bDebugRubberBanding
DEBUG_PRINTSTRINGF("fDist is ", fDist)
DEBUG_PRINTSTRINGF("Setting fMoveRatio to ", fMoveRatio)
DEBUG_PRINTSTRINGF("Actual speed is ", GET_ENTITY_SPEED(opponent))
ENDIF
ENDIF
ELIF opponentStage = MS_RUN
fMoveRatio = fMoveRatio + fRatioModifier // Increase opponent speed
fMoveRatio += 0.4 // Add extra speed for the running section
// If Mary Ann is 3m or less behind you, give her some extra speed so she doesn't hang back if you're just jogging
IF fDist <= 3.0
fMoveRatio += 0.12
ENDIF
IF fMoveRatio > 3.0
fMoveRatio = 3.0 // Cap the ratio to 3.0, because it's the max
ENDIF
IF IS_WAYPOINT_PLAYBACK_GOING_ON_FOR_PED(opponent)
WAYPOINT_PLAYBACK_OVERRIDE_SPEED(opponent, fMoveRatio)
ENDIF
IF bDebugRubberBanding
DEBUG_PRINTSTRINGF("fDist is ", fDist)
DEBUG_PRINTSTRINGF("Setting fMoveRatio to ", fMoveRatio)
DEBUG_PRINTSTRINGF("Actual speed is ", GET_ENTITY_SPEED(opponent))
ENDIF
ELIF opponentStage = MS_BIKE
IF IS_ENTITY_ALIVE(opponent_goto_bike)
IF IS_WAYPOINT_PLAYBACK_GOING_ON_FOR_VEHICLE(opponent_goto_bike)
// We get the nearest waypoint to the opponent's current position...
int iCurrWaypoint
WAYPOINT_RECORDING_GET_CLOSEST_WAYPOINT(sOpponentWaypointName, GET_ENTITY_COORDS(opponent_goto_bike), iCurrWaypoint)
// ... and then dial-up the speed of that waypoint to set the opponent's rubber-banded speed
IF ARE_STRINGS_EQUAL(sOpponentWaypointName, "Fan3_pedBike")
IF iCurrWaypoint < 98
OR iCurrWaypoint >= 107
float fPlaybackSpd = WAYPOINT_RECORDING_GET_SPEED_AT_POINT(sOpponentWaypointName, iCurrWaypoint)
// The ratio modifier is calculated for on-foot speeds at 0.2, 0.3, etc, for the other two sections
// Here, we want it to apply to vehicle values, between 2.0, 3.0, etc - so multiply by 10
fRatioModifier = (fRatioModifier * 10)
fPlaybackSpd = ((fPlaybackSpd + fRatioModifier) + 3.0)
IF bDebugRubberBanding
//DEBUG_PRINTSTRINGINT("race_pos:", race_pos)
DEBUG_PRINTSTRINGF("fRatioModifier is ", fRatioModifier)
DEBUG_PRINTSTRINGF("Setting fPlaybackSpd to ", fPlaybackSpd)
DEBUG_PRINTSTRINGF("Actual entity speed is ", GET_ENTITY_SPEED(opponent))
//DEBUG_PRINTSTRINGF("Distance is ", GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), GET_ENTITY_COORDS(opponent)))
ENDIF
VEHICLE_WAYPOINT_PLAYBACK_OVERRIDE_SPEED(opponent_goto_bike, fPlaybackSpd)
ENDIF
IF iCurrWaypoint > 93
AND iCurrWaypoint < 98
DEBUG_PRINTSTRING("**** SWITCHING TO JUMP PREP")
sOpponentWaypointName = "Fan3_pedBikePrep"
TASK_VEHICLE_FOLLOW_WAYPOINT_RECORDING(opponent, opponent_goto_bike, sOpponentWaypointName, DRIVINGMODE_PLOUGHTHROUGH|DF_SteerAroundPeds, 0,
EWAYPOINT_START_FROM_CLOSEST_POINT|EWAYPOINT_VEHICLES_USE_AI_SLOWDOWN)
ENDIF
ELSE
ma_pDoBridgeJump(iCurrWaypoint)
ENDIF
ELSE
ma_pDoBridgeJump()
ENDIF
ENDIF
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Actions that are called every frame or when the opponent's current checkpoint is updated, depending on the current stage
PROC ma_pPerformAction()
SWITCH opponentStage
CASE MS_SWIM
TASK_GO_STRAIGHT_TO_COORD(opponent, (SWIM_POSITIONS[current_opponent_position]), PEDMOVE_SPRINT, DEFAULT_TIME_BEFORE_WARP, DEFAULT_NAVMESH_RADIUS)//, ENAV_NO_STOPPING)
DEBUG_PRINTSTRINGINT("*** Updating Mary Ann swimming task to pos", current_opponent_position)
BREAK
CASE MS_TO_BIKE
// None - already told to go to bike
BREAK
CASE MS_BIKE
IF IS_ENTITY_ALIVE(opponent) AND IS_VEHICLE_OK(opponent_goto_bike)
IF NOT IS_WAYPOINT_PLAYBACK_GOING_ON_FOR_VEHICLE(opponent_goto_bike)
AND bMADoingJump = FALSE
IF current_opponent_position > 2
// This is to fix 739591, where Mary Ann gets herself into a position where she finishes the waypoint recording,
// but has missed a checkpoint along the way and thus never hits the final one, so ma_pDoCheckpoints() never returns true...
DEBUG_PRINTSTRING("*** Mary Ann has missed a position but reached the end of the bike route!!")
DEBUG_PRINTSTRING("*** Changing position to 11 so the check returns true...")
current_opponent_position = MAX_BIKE_POSITIONS
ENDIF
DEBUG_PRINTSTRING("*** Mary Ann: Doing start of bike section setup")
sOpponentWaypointName = "Fan3_pedBike"
SET_VEHICLE_DOORS_LOCKED(opponent_goto_bike, VEHICLELOCK_LOCKOUT_PLAYER_ONLY)
SET_ENTITY_CAN_BE_DAMAGED(opponent_goto_bike, FALSE)
TASK_VEHICLE_FOLLOW_WAYPOINT_RECORDING(opponent, opponent_goto_bike, sOpponentWaypointName, DRIVINGMODE_AVOIDCARS|DF_SteerAroundPeds, 0,
EWAYPOINT_START_FROM_CLOSEST_POINT|EWAYPOINT_VEHICLES_USE_AI_SLOWDOWN)
SAFE_REMOVE_BLIP(additional_blip)
ENDIF
ENDIF
BREAK
CASE MS_OFF_BIKE
IF IS_PED_SITTING_IN_VEHICLE(opponent, opponent_goto_bike)
BRING_VEHICLE_TO_HALT(opponent_goto_bike, 5, 10)
TASK_LEAVE_ANY_VEHICLE(opponent)
ENDIF
// Repeatedly try and get Mary Ann off her bike if she's STILL in it
BREAK
CASE MS_RUN
IF IS_ENTITY_ALIVE(opponent)
IF NOT IS_WAYPOINT_PLAYBACK_GOING_ON_FOR_PED(opponent)
DEBUG_PRINTSTRING("*** Telling Mary Ann to play waypoint recording")
TASK_FOLLOW_WAYPOINT_RECORDING(opponent, "fan3_pedJog")
ENDIF
ENDIF
BREAK
CASE MS_FAILED
BREAK
DEFAULT
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE:
/// Continually check for Mary Ann hitting her current checkpoint along the route, updating as she goes, before returning true when she's reached the final
/// one for that leg of the race
/// PARAMS:
/// vCheckpoints - The checkpoint array we're checking
/// RETURNS:
/// True when Mary Ann has reached the final checkpoint on the current leg of the race
/// False otherwise
FUNC BOOL ma_pDoCheckpoints(VECTOR &vCheckpoints[])
IF IS_ENTITY_ALIVE(opponent)
IF current_opponent_position < current_opponent_max_positions
VECTOR vOpponentPos = GET_ENTITY_COORDS(opponent)
FLOAT fDist = GET_DISTANCE_BETWEEN_COORDS(vOpponentPos, vCheckpoints[current_opponent_position])
IF fDist < 6
current_opponent_position++
DEBUG_PRINTSTRINGINT("*** UPDATED Mary Ann position = ", current_opponent_position)
IF current_opponent_position >= current_opponent_max_positions
DEBUG_PRINTSTRING("*** Mary Ann position >= max positions")
RETURN TRUE
ENDIF
if opponentStage = MS_SWIM // Only care about clearing tasks and refreshing task during swimming
If current_opponent_position <> current_opponent_max_positions
CLEAR_PED_TASKS(opponent)
DEBUG_PRINTSTRING("*** Clearing Mary Ann tasks (ma_pDoCheckpoints())")
ma_pPerformAction()
ELSE
DEBUG_PRINTSTRING("*** Mary Ann position = max position and she is stuck... this wasn't caught by the previous check?!")
ENDIF
ENDIF
ENDIF
ELIF current_opponent_position >= current_opponent_max_positions
DEBUG_PRINTSTRING("*** Mary Ann's checkpoints have been manipulated by some sort of fix before being checked")
DEBUG_PRINTSTRING("... and she should finish the race without hitting the final checkpoint")
RETURN TRUE
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// Continually check for Mary Ann finishing the swim section of the race, then switch her to get on a bike
PROC ma_pDoSwimTask()
IF ma_pDoCheckpoints(SWIM_POSITIONS)
DEBUG_PRINTSTRING("*** Mary Ann swim complete")
ma_pSwitchState(MS_TO_BIKE)
ENDIF
IF current_opponent_position >= 6
IF IS_ENTITY_ALIVE(opponent)
SET_PED_MIN_MOVE_BLEND_RATIO(opponent, PEDMOVEBLENDRATIO_RUN)
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Continually check Mary Ann is in a bike, and switch her to doing the bike race section when she's in it
/// Before that, keep checking whether the seat on the bike she's going for is free (in case the player nicks it), and make her go to the other bike if needed
PROC ma_pDoToBikeTask()
IF IS_ENTITY_ALIVE(opponent) AND IS_VEHICLE_OK(opponent_goto_bike)
IF IS_PED_IN_VEHICLE(opponent, opponent_goto_bike)
// Add bike to audio scene now Mary Ann is on it
IF IS_AUDIO_SCENE_ACTIVE("FANATIC_MIX_SCENE")
IF DOES_ENTITY_EXIST(opponent_goto_bike)
DEBUG_PRINTSTRING("Adding Mary Ann's bike to mix group!")
ADD_ENTITY_TO_AUDIO_MIX_GROUP(opponent_goto_bike,"FANATIC_MIX_MARY_BIKE")
ENDIF
ENDIF
//MODIFY_VEHICLE_TOP_SPEED(opponent_goto_bike, 110.0)
ma_pSwitchState(MS_BIKE)
ELSE // Check whether player has got on Mary-Ann's bike in the meantime
IF IS_PED_IN_VEHICLE(PLAYER_PED_ID(), opponent_goto_bike, TRUE)
IF opponent_goto_bike = opponent_bike_vehicle
opponent_goto_bike = bike_vehicle
CLEAR_PED_TASKS_IMMEDIATELY(opponent)
DEBUG_PRINTSTRING("*** Clearing Mary Ann tasks (ma_pDoToBikeTask())")
IF IS_ENTITY_ALIVE(opponent_goto_bike) AND IS_ENTITY_ALIVE(opponent)
DEBUG_PRINTSTRING("Making Mary Ann use default player's bike")
TASK_ENTER_VEHICLE(opponent, opponent_goto_bike, DEFAULT_TIME_BEFORE_WARP, VS_DRIVER, PEDMOVE_SPRINT)
ENDIF
ELIF opponent_goto_bike = bike_vehicle
opponent_goto_bike = opponent_bike_vehicle
CLEAR_PED_TASKS_IMMEDIATELY(opponent)
DEBUG_PRINTSTRING("*** Clearing Mary Ann tasks (ma_pDoToBikeTask())")
IF IS_ENTITY_ALIVE(opponent_goto_bike) AND IS_ENTITY_ALIVE(opponent)
DEBUG_PRINTSTRING("Making Mary Ann use default opponent bike")
TASK_ENTER_VEHICLE(opponent, opponent_goto_bike, DEFAULT_TIME_BEFORE_WARP, VS_DRIVER, PEDMOVE_SPRINT)
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Continually check for Mary Ann finishing the bike section of the race, then switch her to get off the bike
/// Meanwhile, check to see if she failed the broken bridge jump
PROC ma_pDoBikeTask()
IF ma_pLoadBikeRecs()
IF ma_pDoCheckpoints(BIKE_POSITIONS)
ma_pSwitchState(MS_OFF_BIKE)
ELSE
ma_pCommentOnPlayerJumpFail()
//ma_pCheckJumpSwitch()
ma_pPerformAction()
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Continually check for Mary Ann not being on her bike, and switch her to the jogging section when she's off
PROC ma_pDoOffBikeTask()
IF IS_ENTITY_ALIVE(opponent) AND IS_VEHICLE_OK(opponent_goto_bike)
IF NOT IS_PED_IN_VEHICLE(opponent, opponent_goto_bike)
ma_pSwitchState(MS_RUN)
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Continually check for Mary Ann finishing the jogging section of the race, then switch her to the 'done' state
PROC ma_pDoJogTask()
IF ma_pLoadJogRecs()
IF ma_pDoCheckpoints(RUN_POSITIONS)
ma_pSwitchState(MS_DONE)
ELSE
ma_pPerformAction()
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Called to update Mary Ann every frame, to monitor checkpoints, rubber banding, aggro checks, tasks during the race sections, etc
PROC ma_pUpdate()
ma_pCheckAggro()
ma_pGivePushWarning()
MANAGE_SLIDY_BLIP_FOR_ENTITY(opponent_blip, opponent, TRUE)
SWITCH opponentStage
CASE MS_SWIM
ma_pDoSwimTask()
ma_pRubberBanding()
BREAK
CASE MS_TO_BIKE
ma_pDoToBikeTask()
BREAK
CASE MS_BIKE
ma_pDoBikeTask()
ma_pRubberBanding()
ma_pCheckForTeleport()
BREAK
CASE MS_OFF_BIKE
ma_pDoOffBikeTask()
BREAK
CASE MS_RUN
ma_pDoJogTask()
ma_pRubberBanding()
BREAK
CASE MS_DONE
IF not race_won // If player hasn't already won the race, then fail the mission
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
KILL_ANY_CONVERSATION()
ENDIF
IF CREATE_CONVERSATION(conversation, "FAN3AUD", "FAN3_MAWIN", CONV_PRIORITY_HIGH)
missionStage = MS_LOST // Set the player into the pre-mission-fail lost state
subState = SS_INIT
DELETE_CHECKPOINT(checkpoint)
SAFE_REMOVE_BLIP(blip)
SAFE_REMOVE_BLIP(nextblip)
ma_pSwitchState(MS_LOST)
ENDIF
ENDIF
BREAK
CASE MS_LOST
BREAK
CASE MS_FAILED
BREAK
DEFAULT
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE:
/// Deals with Mary Ann for stage skipping (teleporting, switching state, etc)
/// Called AFTER we set what mission state we want to go to
PROC ma_pSkip()
SWITCH missionStage
CASE MS_INTRO
IF IS_ENTITY_ALIVE(opponent)
CLEAR_PED_TASKS_IMMEDIATELY(opponent)
DEBUG_PRINTSTRING("*** Clearing Mary Ann tasks (ma_pSkip())")
SET_ENTITY_COORDS(opponent, << -910.3204, 6144.2480, 4.2755 >>)
SET_ENTITY_HEADING(opponent, 312.68)
SAFE_REMOVE_BLIP(opponent_blip)
ma_pSwitchState(MS_INTRO)
ENDIF
BREAK
CASE MS_SWIM
IF IS_ENTITY_ALIVE(opponent)
CLEAR_PED_TASKS_IMMEDIATELY(opponent)
DEBUG_PRINTSTRING("*** Clearing Mary Ann tasks (ma_pSkip() CASE MS_SWIM)")
SET_ENTITY_COORDS(opponent, <<-903.2273, 6142.6387, 4.1911>>, TRUE, TRUE)
SET_ENTITY_HEADING(opponent, 264.8848)
SAFE_REMOVE_BLIP(opponent_blip)
ma_pSwitchState(MS_SWIM)
ENDIF
BREAK
CASE MS_TO_BIKE
FALLTHRU
CASE MS_BIKE
IF IS_ENTITY_ALIVE(opponent)
CLEAR_PED_TASKS_IMMEDIATELY(opponent)
DEBUG_PRINTSTRING("*** Clearing Mary Ann tasks (ma_pSkip() CASE MS_BIKE)")
SET_ENTITY_COORDS(opponent, << -674.4872, 6134.1387, 1.0720 >>)
SET_ENTITY_HEADING(opponent, 259.44)
SAFE_REMOVE_BLIP(opponent_blip)
ma_pSwitchState(MS_TO_BIKE)
ENDIF
BREAK
CASE MS_OFF_BIKE
FALLTHRU
CASE MS_RUN
opponent_goto_bike = opponent_bike_vehicle // Reassigning this for the skip to ensure Mary Ann progress if we skip the bike section
IF IS_ENTITY_ALIVE(opponent)
CLEAR_PED_TASKS_IMMEDIATELY(opponent)
DEBUG_PRINTSTRING("*** Clearing Mary Ann tasks (ma_pSkip() CASE MS_RUN)")
SET_ENTITY_COORDS(opponent, << 51.1448, 6773.2119, 19.2801 >>)
SET_ENTITY_HEADING(opponent, 313.1460)
//FORCE_PED_MOTION_STATE(opponent, MS_ON_FOOT_RUN, FALSE, FAUS_DEFAULT)
SAFE_REMOVE_BLIP(opponent_blip)
ma_pSwitchState(MS_RUN)
ENDIF
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE:
/// Do the race logic for the mission, keeping track of where Mary Ann and the player are and setting the race position accordingly
/// Also dealing with the race HUD, including the timer
PROC m_pDoRaceLogic()
//INT total_stage
VECTOR player_pos = GET_ENTITY_COORDS(PLAYER_PED_ID())
if DOES_ENTITY_EXIST(opponent)
if not IS_ENTITY_DEAD(opponent)
opponent_pos = GET_ENTITY_COORDS(opponent)
ENDIF
ENDIF
FLOAT player_distance
FLOAT opponent_distance
IF ENUM_TO_INT(missionStage) <> ENUM_TO_INT(MS_FAILED) // Don't run this stuff if we've just failed the mission
OR NOT IS_SCREEN_FADED_OUT()
IF ENUM_TO_INT(missionStage) < ENUM_TO_INT(MS_TO_BIKE)
//total_stage = current_position
IF current_position < 7
player_distance = GET_DISTANCE_BETWEEN_COORDS(player_pos, SWIM_POSITIONS[current_position])
ELIF current_position = 7
player_distance = GET_DISTANCE_BETWEEN_COORDS(player_pos, SWIM_POSITIONS[6])
ENDIF
ELIF ENUM_TO_INT(missionStage) < ENUM_TO_INT(MS_OFF_BIKE)
//total_stage = MAX_SWIM_POSITIONS + current_position
IF current_position < 11
player_distance = GET_DISTANCE_BETWEEN_COORDS(player_pos, BIKE_POSITIONS[current_position])
ELIF current_position = 11
player_distance = GET_DISTANCE_BETWEEN_COORDS(player_pos, BIKE_POSITIONS[10])
ENDIF
ELIF (ENUM_TO_INT(missionStage) = ENUM_TO_INT(MS_OFF_BIKE))
OR (ENUM_TO_INT(missionStage) = ENUM_TO_INT(MS_RUN))
//total_stage = MAX_SWIM_POSITIONS + MAX_BIKE_POSITIONS + current_position
IF current_position < MAX_RUN_POSITIONS
player_distance = GET_DISTANCE_BETWEEN_COORDS(player_pos, RUN_POSITIONS[current_position])
ELIF current_position = MAX_RUN_POSITIONS
player_distance = GET_DISTANCE_BETWEEN_COORDS(player_pos, RUN_POSITIONS[current_position-1])
ENDIF
ELSE // Not in any of the race stages - failed? Let's spit out a debug print...
DEBUG_PRINTSTRING("Trying to update the race logic when not in a race stage? Mission failed just now?")
ENDIF
IF ENUM_TO_INT(opponentStage) < ENUM_TO_INT(MS_TO_BIKE)
opponent_distance = GET_DISTANCE_BETWEEN_COORDS(opponent_pos, SWIM_POSITIONS[current_opponent_position])
ELIF ENUM_TO_INT(opponentStage) < ENUM_TO_INT(MS_OFF_BIKE)
IF current_opponent_position < 11
opponent_distance = GET_DISTANCE_BETWEEN_COORDS(opponent_pos, BIKE_POSITIONS[current_opponent_position])
ELIF current_opponent_position = 11
opponent_distance = GET_DISTANCE_BETWEEN_COORDS(opponent_pos, BIKE_POSITIONS[10])
ENDIF
ELIF opponentStage <> MS_DONE
opponent_distance = GET_DISTANCE_BETWEEN_COORDS(opponent_pos, RUN_POSITIONS[current_opponent_position])
ENDIF
IF NOT race_won
IF ENUM_TO_INT(missionStage) < ENUM_TO_INT(opponentStage)
// If the player has gone from BIKE -> TO_BIKE because of getting off the bike for some reason, ignore changing the race pos,
// use the current_position checks before instead
// Otherwise the mission fails when Mary Ann is far behind you because you're suddenly 'last' - should fix #1085937
// Shouldn't really be an issue when Mary Ann works correctly
race_pos = 2
ELIF ENUM_TO_INT(missionStage) > ENUM_TO_INT(opponentStage)
race_pos = 1
ELSE
IF current_position < current_opponent_position
race_pos = 2
ELIF current_position > current_opponent_position
race_pos = 1
ELSE
IF player_distance < opponent_distance
race_pos = 1
ELSE
race_pos = 2
ENDIF
ENDIF
ENDIF
ENDIF
// Race timer is calculated by taking the start time away from the current game timer (as normal), then adding on any extra from prior replays
race_timer = (GET_GAME_TIMER() - start_time) + replay_timer_addition
// Add +1 for the current/total checkpoints so we start on CP 1 and there are 30 total
//DRAW_BIG_DOUBLE_SCORE_HUD(total_stage+1, MAX_SWIM_POSITIONS+MAX_BIKE_POSITIONS+MAX_RUN_POSITIONS+1, "FATIC3_CP", HUD_COLOUR_YELLOW)
SET_FAR_RIGHT_TITLE_POSITION_HUD_THIS_FRAME()
DRAW_RACE_HUD(race_timer, "", -1, -1, "", race_pos, 2, "")
ENDIF
ENDPROC
PROC ma_pDoIntroBoost()
IF bDoMAIntroBoost
AND IS_ENTITY_ALIVE(opponent)
IF (GET_GAME_TIMER() - iMAIntroBoostTimer) <= INTRO_BOOST_TIME
//DEBUG_PRINTSTRING("Doing Mary Ann intro boost")
SET_PED_MIN_MOVE_BLEND_RATIO(opponent, 3.0)
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Get an offset number for the current stage - used in calculating which smack talk dialogue to perform depending on whether the player won or lost a stage
/// PARAMS:
/// stage - The stage we're checking
/// RETURNS:
/// An appropriate offset value used for the smack[] array
FUNC INT GET_OFFSET_FROM_MISSION_STAGE(MISSION_STAGE stage)
INT return_offset
IF (stage = MS_SWIM)
return_offset = 0
ELIF (stage = MS_TO_BIKE)
return_offset = -1
ELIF (stage = MS_BIKE)
return_offset = 1
ELIF (stage = MS_OFF_BIKE)
return_offset = -1
ELSE
return_offset = 3
ENDIF
return return_offset
ENDFUNC
/// PURPOSE: Works out which checkpoint type is needed based upon angle between checkpoints
FUNC CHECKPOINT_TYPE GET_RACE_CHECKPOINT_TYPE(INT iCheckNum, VECTOR& checkpoints[])
VECTOR pos, pos2, pos3
VECTOR vec1, vec2
FLOAT fReturnAngle
FLOAT fChevron1 = 180.0
FLOAT fChevron2 = 140.0
FLOAT fChevron3 = 80.0
pos = checkpoints[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 = current_max_positions-1)
SWITCH missionStage
CASE MS_SWIM
RETURN CHECKPOINT_RACE_GROUND_FLAG
BREAK
CASE MS_BIKE
RETURN CHECKPOINT_RACE_GROUND_FLAG
BREAK
CASE MS_RUN
RETURN CHECKPOINT_RACE_GROUND_FLAG
BREAK
ENDSWITCH
ELSE
// Otherwise, we need to do the angle shit
// If this is the first checkpoint, we need to check the PREVIOUS array for the 'before' CP
// But if this is the swimming array then...
// Whatever, I'll just use Franklin's starting position since it's behind that one and it makes sense
IF iCheckNum = 0
SWITCH missionStage
CASE MS_SWIM
pos3 = <<64.1700, 7048.6797, 15.6112>> // Franklin's rough start position after the cutscene
BREAK
CASE MS_BIKE
pos3 = SWIM_POSITIONS[MAX_SWIM_POSITIONS-1] // Final swim CP
BREAK
CASE MS_RUN
pos3 = BIKE_POSITIONS[MAX_BIKE_POSITIONS-1] // Final bike CP
BREAK
ENDSWITCH
// And the next CP is just the... next one
pos2 = checkpoints[iCheckNum + 1]
ELSE
// The checkpoint is neither first nor last, wooo, straightforward
pos3 = checkpoints[iCheckNum - 1]
pos2 = checkpoints[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
SWITCH missionStage
CASE MS_SWIM
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
BREAK
CASE MS_TO_BIKE
FALLTHRU
CASE MS_BIKE
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
BREAK
CASE MS_RUN
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
BREAK
ENDSWITCH
// 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
// RETURN HUD_COLOUR_YELLOW
// ELIF cpType = CHECKPOINT_RACE_GROUND_FLAG
// RETURN HUD_COLOUR_YELLOW
// ELSE
// RETURN HUD_COLOUR_YELLOWLIGHT
// ENDIF
// Returning YELLOWDARK for all checkpoints (B*1454575)
cpType = cpType // Compile fix - no point changing the function because this will change back
RETURN HUD_COLOUR_YELLOWLIGHT
ENDFUNC
/// PURPOSE:
/// Remove both race checkpoint blips from the map
PROC REMOVE_BLIP_IF_EXISTS()
SAFE_REMOVE_BLIP(blip)
SAFE_REMOVE_BLIP(nextblip)
ENDPROC
/// PURPOSE:
/// Delete the existing checkpoint halo
PROC REMOVE_CHECKPOINT_IF_EXISTS()
DELETE_CHECKPOINT(checkpoint)
ENDPROC
/// PURPOSE:
/// Main mission cleanup function
PROC MISSION_CLEANUP()
// Ensure launcher is terminated
RC_CLEANUP_LAUNCHER()
IF (Random_Character_Cleanup_If_Triggered())
PRINTSTRING("...Random Character Script was triggered so additional cleanup required") PRINTNL()
ENDIF
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
KILL_ANY_CONVERSATION()
ENDIF
SAFE_REMOVE_BLIP(opponent_blip)
REMOVE_BLIP_IF_EXISTS()
REMOVE_CHECKPOINT_IF_EXISTS()
IF IS_ENTITY_ALIVE(opponent)
IF IS_VEHICLE_OK(EndingBikeMA)
IF NOT IS_PED_IN_VEHICLE(opponent, EndingBikeMA)
OPEN_SEQUENCE_TASK(seq)
TASK_ENTER_VEHICLE(null, EndingBikeMA, DEFAULT_TIME_BEFORE_WARP, VS_DRIVER, PEDMOVE_WALK)
TASK_GO_TO_COORD_ANY_MEANS(null, <<253.0988, 6751.9966, 14.2161>>, 1.0, NULL)
TASK_VEHICLE_DRIVE_WANDER(null, EndingBikeMA, 15, DRIVINGMODE_AVOIDCARS_STOPFORPEDS_OBEYLIGHTS)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(opponent, seq)
CLEAR_SEQUENCE_TASK(seq)
ENDIF
ELSE
// Wander on foot if the bike's fucked
TASK_WANDER_STANDARD(opponent, GET_ENTITY_HEADING(opponent))
ENDIF
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(opponent, TRUE)
SAFE_RELEASE_VEHICLE(EndingBikeMA)
ENDIF
IF IS_AUDIO_SCENE_ACTIVE("FANATIC_MIX_SCENE")
IF DOES_ENTITY_EXIST(opponent_goto_bike)
REMOVE_ENTITY_FROM_AUDIO_MIX_GROUP(opponent_goto_bike)
ENDIF
IF DOES_ENTITY_EXIST(opponent)
REMOVE_ENTITY_FROM_AUDIO_MIX_GROUP(opponent)
ENDIF
STOP_AUDIO_SCENE("FANATIC_MIX_SCENE")
ENDIF
SAFE_RELEASE_PED(bad_driver_ped)
SAFE_RELEASE_PED(fence_worker)
SAFE_RELEASE_VEHICLE(bad_driver_car)
IF IS_ENTITY_ALIVE(binoculars_guy)
SET_PED_FLEE_ATTRIBUTES(binoculars_guy, FA_USE_VEHICLE, TRUE)
SET_PED_KEEP_TASK(binoculars_guy, true)
IF IS_ENTITY_ALIVE(picniccar2) AND IS_ENTITY_ALIVE(PLAYER_PED_ID())
OPEN_SEQUENCE_TASK(seq)
TASK_ENTER_VEHICLE(NULL, picniccar2, DEFAULT_TIME_BEFORE_WARP, VS_DRIVER, PEDMOVEBLENDRATIO_SPRINT, ECF_JACK_ANYONE)
TASK_SMART_FLEE_PED(NULL, PLAYER_PED_ID(), 100, -1)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(binoculars_guy, seq)
CLEAR_SEQUENCE_TASK(seq)
ENDIF
SAFE_RELEASE_PED(binoculars_guy)
ENDIF
SAFE_RELEASE_PED(stretching_woman)
SAFE_RELEASE_PED(chinups_guy)
SAFE_RELEASE_VEHICLE(picniccar2)
SET_PLAYER_CONTROL(PLAYER_ID(), TRUE)
SAFE_RELEASE_PED(opponent, TRUE, TRUE)
TRIGGER_MUSIC_EVENT("FANATIC2_STOP")
SET_ALL_VEHICLE_GENERATORS_ACTIVE_IN_AREA(<<129.221359,6658.974609,30.177034>>, <<140.878265,6646.863281,36.364159>>, TRUE)
SET_ALL_VEHICLE_GENERATORS_ACTIVE_IN_AREA(<<-191.098450,6550.963867,10.097297>>, <<-199.409927,6542.312012,11.097295>>, TRUE)
SET_ALL_VEHICLE_GENERATORS_ACTIVE_IN_AREA(<<-226.3857, 6498.8770, 9.2147>>, <<-173.1313, 6595.7710, 20.7218>>, TRUE)
SET_ROADS_BACK_TO_ORIGINAL_IN_ANGLED_AREA(vRoadDisableAA1, vRoadDisableAA2, fRoadDisableAA)
SET_WANTED_LEVEL_MULTIPLIER(1.0)
IF GET_IS_WAYPOINT_RECORDING_LOADED("fanatic3_assist")
USE_WAYPOINT_RECORDING_AS_ASSISTED_MOVEMENT_ROUTE("fanatic3_assist", FALSE)
REMOVE_WAYPOINT_RECORDING("fanatic3_assist")
ENDIF
IF GET_IS_WAYPOINT_RECORDING_LOADED("fan3_pedJog")
REMOVE_WAYPOINT_RECORDING("fan3_pedJog")
ENDIF
IF GET_IS_WAYPOINT_RECORDING_LOADED("Fan3_jetskiRoute")
REMOVE_WAYPOINT_RECORDING("Fan3_jetskiRoute")
ENDIF
DISABLE_CHEAT(CHEAT_TYPE_FAST_RUN, FALSE)
DISABLE_CHEAT(CHEAT_TYPE_FAST_SWIM, FALSE)
DISABLE_CELLPHONE(FALSE)
TERMINATE_THIS_THREAD()
ENDPROC
/// PURPOSE:
/// Main mission passed function
PROC MISSION_PASSED()
//race_won = TRUE
IF bCheated = FALSE
INFORM_STAT_SYSTEM_OF_BOOL_STAT_HAPPENED(FA3_SHORTCUT_USED)
ENDIF
SET_MULTIHEAD_SAFE(FALSE) //Deactivate blinders
REMOVE_BLIP_IF_EXISTS()
REMOVE_CHECKPOINT_IF_EXISTS()
Random_Character_Passed(CP_RAND_C_FAN3)
ADD_CONTACT_TO_PHONEBOOK(CHAR_MARY_ANN, FRANKLIN_BOOK)
MISSION_CLEANUP()
ENDPROC
/// PURPOSE:
/// Delete every entity and blip in the mission
PROC DeleteEverything()
SAFE_REMOVE_BLIP(opponent_blip)
SAFE_REMOVE_BLIP(blip)
SAFE_REMOVE_BLIP(additional_blip)
SAFE_REMOVE_BLIP(nextblip)
DELETE_CHECKPOINT(checkpoint)
SAFE_DELETE_VEHICLE(opponent_car)
SAFE_DELETE_PED(bad_driver_ped)
SAFE_DELETE_PED(fence_worker)
SAFE_DELETE_VEHICLE(bad_driver_car)
SAFE_DELETE_VEHICLE(picniccar2)
SAFE_DELETE_PED(binoculars_guy)
SAFE_DELETE_PED(opponent)
SAFE_DELETE_VEHICLE(bike_vehicle)
SAFE_DELETE_VEHICLE(opponent_bike_vehicle)
ENDPROC
/// 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
CAMERA_INDEX chase_cam
/// PURPOSE:
/// Get the script ready to start the scriped cutscene
PROC CUTSCENE_START()
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
CLEAR_PED_TASKS(PLAYER_PED_ID())
FORCE_PED_MOTION_STATE(PLAYER_PED_ID(), MS_ON_FOOT_IDLE, TRUE, FAUS_DEFAULT)
ENDIF
RESOLVE_VEHICLES_INSIDE_ANGLED_AREA_WITH_SIZE_LIMIT(<<62.860977,7052.178711,21.198898>>, <<67.866425,7037.953125,12.469742>>, 13.0, <<84.29, 7038.63, 12.66>>, 267.13,
GET_DEFAULT_ALLOWABLE_VEHICLE_SIZE_VECTOR())
RC_START_CUTSCENE_MODE(<< 200.53, 6626.14, 30.56 >>, DEFAULT, DEFAULT, FALSE, DEFAULT, DEFAULT, FALSE)
ENDPROC
/// PURPOSE:
/// Get the script ready to end the scripted cutscene
PROC CUTSCENE_END(BOOL skipped = FALSE)
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
KILL_ANY_CONVERSATION()
ENDIF
IF bOutroMALeave = FALSE
IF IS_ENTITY_ALIVE(opponent)
AND IS_VEHICLE_OK(EndingBikeMA)
OPEN_SEQUENCE_TASK(seq)
TASK_ENTER_VEHICLE(NULL, EndingBikeMA)
TASK_VEHICLE_MISSION_COORS_TARGET(NULL, EndingBikeMA, <<104.65, 7003.12, 6.43>>, MISSION_GOTO, 10.0, DRIVINGMODE_PLOUGHTHROUGH, 1.0, -1)
TASK_VEHICLE_DRIVE_WANDER(NULL, EndingBikeMA, 15.0, DRIVINGMODE_AVOIDCARS_STOPFORPEDS_OBEYLIGHTS)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(opponent, seq)
CLEAR_SEQUENCE_TASK(seq)
TASK_CLEAR_LOOK_AT(opponent)
FORCE_PED_MOTION_STATE(opponent, MS_ON_FOOT_RUN, FALSE, FAUS_DEFAULT)
ENDIF
ENDIF
IF IS_ENTITY_ALIVE(opponent)
SET_PED_CAN_BE_KNOCKED_OFF_VEHICLE(opponent, KNOCKOFFVEHICLE_DEFAULT)
ENDIF
IF skipped = FALSE
STOP_RENDERING_SCRIPT_CAMS_USING_CATCH_UP()
ELSE
RENDER_SCRIPT_CAMS(FALSE, FALSE, 0)
SET_GAMEPLAY_CAM_RELATIVE_PITCH(0.0)
SET_GAMEPLAY_CAM_RELATIVE_HEADING(0.0)
ENDIF
SET_PLAYER_CONTROL(PLAYER_ID(), TRUE)
FREEZE_ENTITY_POSITION(PLAYER_PED_ID(), FALSE)
//CLEAR_PED_TASKS(PLAYER_PED_ID())
TASK_CLEAR_LOOK_AT(PLAYER_PED_ID())
REMOVE_ANIM_DICT("rcmfanatic1out_of_breath")
SAFE_RELEASE_PED(opponent)
SAFE_RELEASE_VEHICLE(EndingBikeMA)
RC_END_CUTSCENE_MODE()
SAFE_FADE_SCREEN_IN_FROM_BLACK()
ENDPROC
/// PURPOSE:
/// Do the scripted cutscene outro, controlling cameras, conversations, and animations
PROC DO_OUTRO()
// Realtime controllable end sequence
// 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
//
// SWITCH iOutroStage
// CASE 0
// REQUEST_ANIM_DICT("rcmfanatic3leadinoutef_3_mcs_1")
// IF HAS_ANIM_DICT_LOADED("rcmfanatic3leadinoutef_3_mcs_1")
// iOutroStage++
// ENDIF
//
// BREAK
// CASE 1
// int i
// IF IS_ENTITY_ALIVE(opponent)
// WAYPOINT_RECORDING_GET_CLOSEST_WAYPOINT("Fan3_PedJog", GET_ENTITY_COORDS(opponent), i)
// ENDIF
// IF i >= 199
// OPEN_SEQUENCE_TASK(seq)
// TASK_PLAY_ANIM(NULL, "rcmfanatic3leadinoutef_3_mcs_1", "leadout_ef_3_mcs_maryann", SLOW_BLEND_IN, SLOW_BLEND_OUT, -1, AF_DEFAULT, 0.142)
// CLOSE_SEQUENCE_TASK(seq)
// TASK_PERFORM_SEQUENCE(opponent, seq)
// CLEAR_SEQUENCE_TASK(seq)
// bMaryAnnInFinalArea = TRUE
// iOutroStage++
// ELIF i>= 194
// OPEN_SEQUENCE_TASK(seq)
// TASK_PLAY_ANIM(NULL, "rcmfanatic3leadinoutef_3_mcs_1", "leadout_ef_3_mcs_maryann", FAST_BLEND_IN, SLOW_BLEND_OUT, -1, AF_DEFAULT)
// CLOSE_SEQUENCE_TASK(seq)
// TASK_PERFORM_SEQUENCE(opponent, seq)
// CLEAR_SEQUENCE_TASK(seq)
// iOutroStage++
// ENDIF
// BREAK
// CASE 2
// IF bMaryAnnInFinalArea = FALSE
// WAIT(1000)
// ENDIF
// iOutroStage++
// BREAK
// CASE 3
// ADD_PED_FOR_DIALOGUE(conversation, ENUM_TO_INT(CHAR_FRANKLIN) , PLAYER_PED_ID(), "FRANKLIN")
// ADD_PED_FOR_DIALOGUE(conversation, 3 , opponent , "MARYANN")
// IF CREATE_CONVERSATION(conversation, "FAN3AUD", "FAN3_2", CONV_PRIORITY_MEDIUM)
// TASK_LOOK_AT_ENTITY(PLAYER_PED_ID(), opponent, -1)
// TASK_LOOK_AT_ENTITY(opponent, PLAYER_PED_ID(), -1, SLF_EXTEND_PITCH_LIMIT|SLF_EXTEND_YAW_LIMIT)
// iOutroStage++
// ENDIF
// BREAK
// CASE 4
// IF IS_ENTITY_ALIVE(opponent)
// IF NOT IS_ENTITY_PLAYING_ANIM(opponent, "rcmfanatic3leadinoutef_3_mcs_1", "leadout_ef_3_mcs_maryann")
// IF bOutroMALeave = FALSE
// IF IS_VEHICLE_OK(EndingBikeMA)
// OPEN_SEQUENCE_TASK(seq)
// TASK_FOLLOW_NAV_MESH_TO_COORD(NULL, GET_ENTITY_COORDS(EndingBikeMA), PEDMOVEBLENDRATIO_RUN, DEFAULT, 1.0, ENAV_NO_STOPPING|ENAV_DONT_AVOID_PEDS)
// TASK_ENTER_VEHICLE(null, EndingBikeMA)
// CLOSE_SEQUENCE_TASK(seq)
// TASK_PERFORM_SEQUENCE(opponent, seq)
// CLEAR_SEQUENCE_TASK(seq)
// bOutroMALeave = TRUE
// ENDIF
// ENDIF
// ELSE
// IF GET_ENTITY_ANIM_CURRENT_TIME(opponent, "rcmfanatic3leadinoutef_3_mcs_1", "leadout_ef_3_mcs_maryann") >= 0.98
// IF bOutroMALeave = FALSE
// IF IS_VEHICLE_OK(EndingBikeMA)
// OPEN_SEQUENCE_TASK(seq)
// TASK_FOLLOW_NAV_MESH_TO_COORD(NULL, GET_ENTITY_COORDS(EndingBikeMA), PEDMOVEBLENDRATIO_RUN, DEFAULT, 1.0, ENAV_NO_STOPPING|ENAV_DONT_AVOID_PEDS)
// TASK_ENTER_VEHICLE(null, EndingBikeMA)
// CLOSE_SEQUENCE_TASK(seq)
// TASK_PERFORM_SEQUENCE(opponent, seq)
// CLEAR_SEQUENCE_TASK(seq)
// bOutroMALeave = TRUE
// ENDIF
// ENDIF
// ENDIF
// ENDIF
// ENDIF
// IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
// CUTSCENE_END()
// MISSION_PASSED()
// ENDIF
// BREAK
// ENDSWITCH
// Scripted cutscene sequence
SWITCH iOutroStage
CASE 0
DEBUG_PRINTSTRING("WAITING FOR OUTRO ASSETS")
REQUEST_ANIM_DICT("rcmfanatic3leadinoutef_3_mcs_1")
bOutroMALeave = FALSE
bMaryAnnInFinalArea = FALSE
IF HAS_ANIM_DICT_LOADED("rcmfanatic3leadinoutef_3_mcs_1")
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
KILL_FACE_TO_FACE_CONVERSATION_DO_NOT_FINISH_LAST_LINE()
ENDIF
SAFE_DELETE_VEHICLE(EndingBikeMA)
IF NOT IS_VEHICLE_OK(EndingBikeMA)
SAFE_DELETE_VEHICLE(EndingBikeMA)
EndingBikeMA = CREATE_VEHICLE(scorcher, vEndingBikeMASpawn, fEndingBikeMASpawn)
SET_VEHICLE_ON_GROUND_PROPERLY(EndingBikeMA)
ELSE
SET_ENTITY_COORDS(EndingBikeMA, vEndingBikeMASpawn)
SET_ENTITY_HEADING(EndingBikeMA, fEndingBikeMASpawn)
SET_VEHICLE_ON_GROUND_PROPERLY(EndingBikeMA)
ENDIF
// IF IS_ENTITY_ALIVE(opponent)
// IF IS_ENTITY_IN_ANGLED_AREA(opponent, <<61.838440,7052.195801,19.092598>>, <<66.701202,7032.781738,11.118760>>, 14.00)
// bMaryAnnInFinalArea = TRUE
// DEBUG_PRINTSTRING("Mary Ann's in area")
// ELSE
// DEBUG_PRINTSTRING("Mary Ann's not in area")
// ENDIF
// ELSE
// DEBUG_PRINTSTRING("Mary Ann's not alive?!")
// ENDIF
iOutroStage++
DEBUG_PRINTSTRING("DOING OUTRO")
ENDIF
BREAK
CASE 1
chase_cam = CREATE_CAM_WITH_PARAMS("DEFAULT_ANIMATED_CAMERA", <<71.2335, 7032.0923, 25.1157>>, <<-2.4036, -0.0000, 17.3552>>, 25, FALSE)
// SET_CAM_COORD(chase_cam, <<71.2335, 7032.0923, 25.1157>>)
// SET_CAM_ROT(chase_cam, <<-2.4036, -0.0000, 17.3552>>)
// SET_CAM_FOV(chase_cam, 25.000000)
// SET_CAM_ACTIVE(chase_cam, TRUE)
iOutroStage++
CLEAR_AREA_OF_PEDS(GET_ENTITY_COORDS(PLAYER_PED_ID(), FALSE), 25.0) // for B*1978412
DEBUG_PRINTSTRING("Going to case 2")
BREAK
CASE 2
IF IS_ENTITY_ALIVE(opponent)
CLEAR_PED_TASKS(opponent)
DEBUG_PRINTSTRING("*** Clearing Mary Ann tasks (Cutscene)")
IF bMaryAnnInFinalArea
SET_ENTITY_COORDS(opponent, << 64.0768, 7045.1631, 14.9558 >>)
SET_ENTITY_HEADING(opponent, 70.469)
ELSE
SET_ENTITY_COORDS(opponent, << 65.61, 7038.87, 13.69 >>)
SET_ENTITY_HEADING(opponent, 13.469)
ENDIF
IF bMaryAnnInFinalArea
OPEN_SEQUENCE_TASK(seq)
TASK_PLAY_ANIM(NULL, "rcmfanatic3leadinoutef_3_mcs_1", "leadout_ef_3_mcs_maryann", NORMAL_BLEND_IN, SLOW_BLEND_OUT, -1, AF_DEFAULT, 0.164)
CLOSE_SEQUENCE_TASK(seq)
ELSE
OPEN_SEQUENCE_TASK(seq)
TASK_PLAY_ANIM(NULL, "rcmfanatic3leadinoutef_3_mcs_1", "leadout_ef_3_mcs_maryann", NORMAL_BLEND_IN, SLOW_BLEND_OUT, -1)
CLOSE_SEQUENCE_TASK(seq)
ENDIF
TASK_PERFORM_SEQUENCE(opponent, seq)
CLEAR_SEQUENCE_TASK(seq)
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
CLEAR_PED_TASKS(PLAYER_PED_ID())
SET_PED_STEALTH_MOVEMENT(PLAYER_PED_ID(), FALSE) // Get player out of stealth if they're in it (#1070718)
SET_PED_MAX_MOVE_BLEND_RATIO(PLAYER_PED_ID(), 0)
//FORCE_PED_MOTION_STATE(PLAYER_PED_ID(), MS_ON_FOOT_IDLE, TRUE, FAUS_DEFAULT, TRUE)
SAFE_TELEPORT_ENTITY(PLAYER_PED_ID(), vOutroSkip, fOutroSkip, TRUE)
SET_PLAYER_CONTROL(PLAYER_ID(), FALSE)
//FREEZE_ENTITY_POSITION(PLAYER_PED_ID(), TRUE)
ENDIF
PLAY_CAM_ANIM(chase_cam, "leadout_ef_3_mcs_maryann_cam", "rcmfanatic3leadinoutef_3_mcs_1", GET_ENTITY_COORDS(opponent), GET_ENTITY_ROTATION(opponent))
SET_CAM_ACTIVE(chase_cam, TRUE)
ENDIF
REPLAY_START_EVENT(REPLAY_IMPORTANCE_LOW)
CUTSCENE_START()
RENDER_SCRIPT_CAMS(TRUE, FALSE)
SAFE_FADE_SCREEN_IN_FROM_BLACK(500, FALSE)
//SET_CAM_PARAMS(chase_cam, <<78.8691, 7035.9004, 19.6013>>, <<-10.0271, -0.0066, 51.8204>>, 25.0, 3000)
ADD_PED_FOR_DIALOGUE(conversation, ENUM_TO_INT(CHAR_FRANKLIN) , PLAYER_PED_ID(), "FRANKLIN")
ADD_PED_FOR_DIALOGUE(conversation, 3 , opponent , "MARYANN")
TASK_LOOK_AT_ENTITY(PLAYER_PED_ID(), opponent, -1)
WAIT(1000)
IF CREATE_CONVERSATION(conversation, "FAN3AUD", "FAN3_2", CONV_PRIORITY_HIGH)
iOutroTimer = GET_GAME_TIMER()
iOutroStage++
DEBUG_PRINTSTRING("Going to case 3")
ENDIF
BREAK
CASE 3
IF (GET_GAME_TIMER() - iOutroTimer) < 3000
IF IS_CUTSCENE_SKIP_BUTTON_JUST_PRESSED_WITH_DELAY()
SAFE_FADE_SCREEN_OUT_TO_BLACK()
IF IS_ENTITY_ALIVE(opponent)
CLEAR_PED_TASKS(opponent)
ENDIF
RENDER_SCRIPT_CAMS(FALSE, FALSE)
SET_GAMEPLAY_CAM_RELATIVE_PITCH(0.0)
SET_GAMEPLAY_CAM_RELATIVE_HEADING(0.0)
DEBUG_PRINTSTRING("Intro skip case 3")
WAIT(750)
CUTSCENE_END(TRUE)
MISSION_PASSED()
ENDIF
ELSE
//behind winner
//SET_CAM_COORD(chase_cam,<<61.6170, 7053.4175, 17.8992>>)
//SET_CAM_ROT(chase_cam, <<-12.1134, -0.0000, -159.1954>>)
//SET_CAM_FOV(chase_cam, 15.5)
iOutroTimer = GET_GAME_TIMER()
iOutroStage++
DEBUG_PRINTSTRING("Going to case 4")
ENDIF
BREAK
CASE 4
IF (GET_GAME_TIMER() - iOutroTimer) < 10000
IF IS_CUTSCENE_SKIP_BUTTON_JUST_PRESSED_WITH_DELAY()
SAFE_FADE_SCREEN_OUT_TO_BLACK()
IF IS_ENTITY_ALIVE(opponent)
CLEAR_PED_TASKS(opponent)
ENDIF
RENDER_SCRIPT_CAMS(FALSE, FALSE)
SET_GAMEPLAY_CAM_RELATIVE_PITCH(0.0)
SET_GAMEPLAY_CAM_RELATIVE_HEADING(0.0)
DEBUG_PRINTSTRING("Intro skip case 4")
WAIT(750)
CUTSCENE_END(TRUE)
MISSION_PASSED()
ENDIF
ELSE
//SET_CAM_COORD(chase_cam, <<65.5304, 7054.8721, 18.8393>>)
//SET_CAM_ROT(chase_cam, <<-16.6934, 0.0000, 178.1698>>)
//SET_CAM_FOV(chase_cam, 35.0)
iOutroStage++
DEBUG_PRINTSTRING("Going to case 5")
ENDIF
BREAK
CASE 5
IF IS_SCRIPTED_CONVERSATION_ONGOING()
IF IS_CUTSCENE_SKIP_BUTTON_JUST_PRESSED_WITH_DELAY()
SAFE_FADE_SCREEN_OUT_TO_BLACK()
IF IS_ENTITY_ALIVE(opponent)
CLEAR_PED_TASKS(opponent)
ENDIF
RENDER_SCRIPT_CAMS(FALSE, FALSE)
SET_GAMEPLAY_CAM_RELATIVE_PITCH(0.0)
SET_GAMEPLAY_CAM_RELATIVE_HEADING(0.0)
DEBUG_PRINTSTRING("Intro skip case 5")
WAIT(750)
CUTSCENE_END(TRUE)
MISSION_PASSED()
ENDIF
IF IS_ENTITY_ALIVE(opponent)
IF IS_ENTITY_PLAYING_ANIM(opponent, "rcmfanatic3leadinoutef_3_mcs_1", "leadout_ef_3_mcs_maryann")
IF GET_ENTITY_ANIM_CURRENT_TIME(opponent, "rcmfanatic3leadinoutef_3_mcs_1", "leadout_ef_3_mcs_maryann") >= 0.90
//SET_CAM_COORD(chase_cam, <<62.4712, 7051.8481, 18.3172>>)
//SET_CAM_ROT(chase_cam, <<-13.8410, -0.0000, -152.9137>>)
//SET_CAM_FOV(chase_cam, 40.0)
//SET_CAM_PARAMS(chase_cam, <<62.5742, 7051.6470, 19.2351>>, <<-13.8410, -0.0000, -152.9137>>, 40.0, 5000, GRAPH_TYPE_LINEAR, GRAPH_TYPE_LINEAR)
iOutroStage++
DEBUG_PRINTSTRING("Going to case 6")
ENDIF
IF GET_ENTITY_ANIM_CURRENT_TIME(opponent, "rcmfanatic3leadinoutef_3_mcs_1", "leadout_ef_3_mcs_maryann") >= 0.98
IF bOutroMALeave = FALSE
IF IS_VEHICLE_OK(EndingBikeMA)
OPEN_SEQUENCE_TASK(seq)
TASK_GO_STRAIGHT_TO_COORD(NULL, GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(EndingBikeMA, <<-2.5, 0, 0>>), PEDMOVEBLENDRATIO_RUN, DEFAULT, DEFAULT)
//TASK_FOLLOW_NAV_MESH_TO_COORD(NULL, GET_ENTITY_COORDS(EndingBikeMA), PEDMOVEBLENDRATIO_RUN, DEFAULT, 1.0, ENAV_NO_STOPPING|ENAV_DONT_AVOID_PEDS)
TASK_ENTER_VEHICLE(null, EndingBikeMA)
TASK_VEHICLE_MISSION_COORS_TARGET(NULL, EndingBikeMA, <<104.65, 7003.12, 6.43>>, MISSION_GOTO, 10.0, DRIVINGMODE_PLOUGHTHROUGH, 1.0, -1)
TASK_VEHICLE_DRIVE_WANDER(NULL, EndingBikeMA, 15.0, DRIVINGMODE_AVOIDCARS_STOPFORPEDS_OBEYLIGHTS)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(opponent, seq)
FORCE_PED_AI_AND_ANIMATION_UPDATE(opponent, TRUE)
CLEAR_SEQUENCE_TASK(seq)
bOutroMALeave = TRUE
ENDIF
ENDIF
ENDIF
ELSE
IF bOutroMALeave = FALSE
IF IS_VEHICLE_OK(EndingBikeMA)
OPEN_SEQUENCE_TASK(seq)
TASK_GO_STRAIGHT_TO_COORD(NULL, GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(EndingBikeMA, <<-2.5, 0, 0>>), PEDMOVEBLENDRATIO_RUN, DEFAULT, DEFAULT)
//TASK_FOLLOW_NAV_MESH_TO_COORD(NULL, GET_ENTITY_COORDS(EndingBikeMA), PEDMOVEBLENDRATIO_RUN, DEFAULT, 1.0, ENAV_NO_STOPPING|ENAV_DONT_AVOID_PEDS)
TASK_ENTER_VEHICLE(null, EndingBikeMA)
TASK_VEHICLE_MISSION_COORS_TARGET(NULL, EndingBikeMA, <<104.65, 7003.12, 6.43>>, MISSION_GOTO, 10.0, DRIVINGMODE_PLOUGHTHROUGH, 1.0, -1)
TASK_VEHICLE_DRIVE_WANDER(NULL, EndingBikeMA, 15.0, DRIVINGMODE_AVOIDCARS_STOPFORPEDS_OBEYLIGHTS)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(opponent, seq)
FORCE_PED_AI_AND_ANIMATION_UPDATE(opponent, TRUE)
CLEAR_SEQUENCE_TASK(seq)
bOutroMALeave = TRUE
ENDIF
ENDIF
ENDIF
ENDIF
ELSE
CUTSCENE_END()
REPLAY_STOP_EVENT()
MISSION_PASSED()
ENDIF
BREAK
CASE 6
IF IS_SCRIPTED_CONVERSATION_ONGOING()
IF IS_CUTSCENE_SKIP_BUTTON_JUST_PRESSED_WITH_DELAY()
SAFE_FADE_SCREEN_OUT_TO_BLACK()
IF IS_ENTITY_ALIVE(opponent)
CLEAR_PED_TASKS(opponent)
ENDIF
RENDER_SCRIPT_CAMS(FALSE, FALSE)
SET_GAMEPLAY_CAM_RELATIVE_PITCH(0.0)
SET_GAMEPLAY_CAM_RELATIVE_HEADING(0.0)
DEBUG_PRINTSTRING("Intro skip case 6")
WAIT(750)
CUTSCENE_END(TRUE)
MISSION_PASSED()
ENDIF
IF IS_ENTITY_ALIVE(opponent)
IF NOT IS_ENTITY_PLAYING_ANIM(opponent, "rcmfanatic3leadinoutef_3_mcs_1", "leadout_ef_3_mcs_maryann")
IF bOutroMALeave = FALSE
IF IS_VEHICLE_OK(EndingBikeMA)
OPEN_SEQUENCE_TASK(seq)
TASK_GO_STRAIGHT_TO_COORD(NULL, <<86.60, 7032.51, 11.35>>, PEDMOVEBLENDRATIO_RUN, DEFAULT, DEFAULT, 1.5)
//TASK_FOLLOW_NAV_MESH_TO_COORD(NULL, GET_ENTITY_COORDS(EndingBikeMA), PEDMOVEBLENDRATIO_RUN, DEFAULT, 1.0, ENAV_NO_STOPPING|ENAV_DONT_AVOID_PEDS)
TASK_ENTER_VEHICLE(null, EndingBikeMA)
TASK_VEHICLE_MISSION_COORS_TARGET(NULL, EndingBikeMA, <<104.65, 7003.12, 6.43>>, MISSION_GOTO, 10.0, DRIVINGMODE_PLOUGHTHROUGH, 1.0, -1)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(opponent, seq)
FORCE_PED_AI_AND_ANIMATION_UPDATE(opponent, TRUE)
CLEAR_SEQUENCE_TASK(seq)
bOutroMALeave = TRUE
ENDIF
ENDIF
ELSE
IF GET_ENTITY_ANIM_CURRENT_TIME(opponent, "rcmfanatic3leadinoutef_3_mcs_1", "leadout_ef_3_mcs_maryann") >= 0.98
IF bOutroMALeave = FALSE
IF IS_VEHICLE_OK(EndingBikeMA)
OPEN_SEQUENCE_TASK(seq)
TASK_GO_STRAIGHT_TO_COORD(NULL, <<86.60, 7032.51, 11.35>>, PEDMOVEBLENDRATIO_RUN, DEFAULT, DEFAULT, 1.5)
//TASK_FOLLOW_NAV_MESH_TO_COORD(NULL, GET_ENTITY_COORDS(EndingBikeMA), PEDMOVEBLENDRATIO_RUN, DEFAULT, 1.0, ENAV_NO_STOPPING|ENAV_DONT_AVOID_PEDS)
TASK_ENTER_VEHICLE(null, EndingBikeMA)
TASK_VEHICLE_MISSION_COORS_TARGET(NULL, EndingBikeMA, <<104.65, 7003.12, 6.43>>, MISSION_GOTO, 10.0, DRIVINGMODE_PLOUGHTHROUGH, 1.0, -1)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(opponent, seq)
FORCE_PED_AI_AND_ANIMATION_UPDATE(opponent, TRUE)
CLEAR_SEQUENCE_TASK(seq)
bOutroMALeave = TRUE
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ELSE
WAIT(500)
CUTSCENE_END()
MISSION_PASSED()
ENDIF
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE:
/// Main mission failed fade process
PROC FAILED()
SWITCH iFailStage
CASE 0
SAFE_REMOVE_BLIP(opponent_blip)
SAFE_REMOVE_BLIP(blip)
SAFE_REMOVE_BLIP(additional_blip)
SAFE_REMOVE_BLIP(nextblip)
DELETE_CHECKPOINT(checkpoint)
CLEAR_PRINTS()
TRIGGER_MUSIC_EVENT("FANATIC3_FAIL")
STRING sFailReason
SWITCH failReason
CASE FAILED_GENERIC
DEBUG_PRINTSTRING("MISSION_FAILED reason=FAILED_GENERIC")
BREAK
CASE FAILED_BIKE_DESTROYED
sFailReason = "FATIC3_11" // ~r~One of the bikes was wrecked.
DEBUG_PRINTSTRING("MISSION_FAILED reason=FAILED_BIKE_DESTROYED")
BREAK
CASE FAILED_YOURBIKE_DESTROYED
sFailReason = "FATIC3_YOURBIKE" // ~r~Your bike was wrecked.
DEBUG_PRINTSTRING("MISSION_FAILED reason=FAILED_BIKE_DESTROYED")
BREAK
CASE FAILED_OUT_OF_TIME
sFailReason = "FATIC3_16" // ~r~Mary-Ann left you behind.
DEBUG_PRINTSTRING("MISSION_FAILED reason=FAILED_OUT_OF_TIME")
BREAK
CASE FAILED_LOST_RACE
sFailReason = "FATIC3_8" // ~r~The opponent won the race.
DEBUG_PRINTSTRING("MISSION_FAILED reason=FAILED_LOST_RACE")
BREAK
CASE FAILED_WOMAN_DIED
sFailReason = "FATIC3_7" // ~r~The opponent was killed.
DEBUG_PRINTSTRING("MISSION_FAILED reason=FAILED_WOMAN_DIED")
BREAK
CASE FAILED_WOMAN_HURT
sFailReason = "FATIC3_10" // ~r~Mary Ann was hurt.
DEBUG_PRINTSTRING("MISSION_FAILED reason=FAILED_WOMAN_HURT")
BREAK
CASE FAILED_WOMAN_SCARED
sFailReason = "FATIC3_13" // ~r~Mary Ann was scared off.
DEBUG_PRINTSTRING("MISSION_FAILED reason=FAILED_WOMAN_SCARED")
BREAK
CASE FAILED_LEFT_AREA
sFailReason = "FATIC3_14" // ~r~You wandered too far from the race.
DEBUG_PRINTSTRING("MISSION_FAILED reason=FAILED_LEFT_AREA")
BREAK
ENDSWITCH
IF failReason = FAILED_GENERIC
Random_Character_Failed()
ELSE
Random_Character_Failed_With_Reason(sFailReason)
ENDIF
iFailStage = 1
BREAK
CASE 1
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(<< -922.8657, 6164.7632, 3.7645 >>, 195.2908)
//SET_REPLAY_DECLINED_VEHICLE_WARP_LOCATION(<<-917.715, 6162.175, 4.250>>, 174.554)
DeleteEverything()
MISSION_CLEANUP()
ELSE
// not finished fading out
// you may want to handle dialogue etc here.
ENDIF
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE:
/// Create a line of checkpoints, given an array of coords and number of points we want in this line
/// Used for the swim section, as manually placing checkpoints would be reasonably difficult
/// PARAMS:
/// v1 - The start of the checkpoint line
/// v2 - The end of the checkpoint line
/// checkpoints - The checkpoint coord array we want to make a line from
/// number_of_points - The amount of checkpoints we want in this line
PROC CREATE_CHECKPOINT_LINE(VECTOR v1, VECTOR v2, VECTOR& checkpoints[], INT number_of_points)
INT i = 0
VECTOR diff = v2 - v1
diff /= TO_FLOAT(number_of_points-1)
REPEAT number_of_points i
checkpoints[i] = v1 + (diff * TO_FLOAT(i))
ENDREPEAT
ENDPROC
PROC SPAWN_CHECKPOINT(VECTOR& checkpoints[])
IF (current_position = (current_max_positions - 1))
currentCPColour = GET_RACE_CHECKPOINT_COLOUR(GET_RACE_CHECKPOINT_TYPE(current_position, checkpoints))
INT iR, iG, iB, iA
GET_HUD_COLOUR(currentCPColour, iR, iG, iB, iA)
SWITCH missionStage
CASE MS_SWIM
checkpoint = CREATE_CHECKPOINT(CHECKPOINT_RACE_GROUND_FLAG, checkpoints[current_position], BIKE_POSITIONS[0], 3.2, iR, iG, iB, iA)
BREAK
CASE MS_TO_BIKE
FALLTHRU // If we're here, the player has jumped off the bike before the final checkpoint and we're recreating it after he got back on
CASE MS_BIKE
checkpoint = CREATE_CHECKPOINT(CHECKPOINT_RACE_GROUND_FLAG, checkpoints[current_position]+<<0,0,2.0>>, RUN_POSITIONS[0], 3.2, iR, iG, iB, iA)
BREAK
CASE MS_RUN
checkpoint = CREATE_CHECKPOINT(CHECKPOINT_RACE_GROUND_FLAG, checkpoints[current_position]+<<0,0,0.1>>, checkpoints[current_position], 3.2, iR, iG, iB, iA)
BREAK
ENDSWITCH
SET_CHECKPOINT_CYLINDER_HEIGHT(checkpoint,1.6,1.6,100)
IF NOT IS_ENTITY_DEAD(PLAYER_PED_ID())
FLOAT fDis = GET_DISTANCE_BETWEEN_COORDS(checkpoints[current_position],GET_ENTITY_COORDS(PLAYER_PED_ID()))
IF checkpoint != NULL // Make sure the checkpoint exists first
IF fDis > 100.0
GET_HUD_COLOUR(HUD_COLOUR_YELLOWLIGHT, iR, iG, iB, iA)
iA = 240
SET_CHECKPOINT_RGBA(checkPoint, iR, iG, iB, iA)
GET_HUD_COLOUR(HUD_COLOUR_NORTH_BLUE, iR, iG, iB, iA)
iA = 240
SET_CHECKPOINT_RGBA2(checkPoint, iR, iG, iB, iA)
ELSE
GET_HUD_COLOUR(HUD_COLOUR_YELLOWLIGHT, iR, iG, iB, iA)
iA = ROUND(fDis*2.4)
IF iA < 60
iA = 60
ENDIF
SET_CHECKPOINT_RGBA(checkPoint, iR, iG, iB, iA)
GET_HUD_COLOUR(HUD_COLOUR_NORTH_BLUE, 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
// Otherwise, do a normal checkpoint
ELSE
currentCPColour = GET_RACE_CHECKPOINT_COLOUR(GET_RACE_CHECKPOINT_TYPE(current_position, checkpoints))
INT iR, iG, iB, iA
GET_HUD_COLOUR(currentCPColour, iR, iG, iB, iA)
IF missionStage = MS_SWIM
AND current_position = 0
// Hacky way to make the colour correct for the very first checkpoint
currentCPColour = GET_RACE_CHECKPOINT_COLOUR(CHECKPOINT_RACE_GROUND_CHEVRON_1)
GET_HUD_COLOUR(currentCPColour, iR, iG, iB, iA)
checkpoint = CREATE_CHECKPOINT(CHECKPOINT_RACE_GROUND_CHEVRON_1, checkpoints[current_position]+<<0,0,2.0>>, checkpoints[current_position+1], 3.2, iR, iG, iB, iA)
ELSE
currentCPColour = GET_RACE_CHECKPOINT_COLOUR(CHECKPOINT_RACE_GROUND_CHEVRON_1)
GET_HUD_COLOUR(currentCPColour, iR, iG, iB, iA)
checkpoint = CREATE_CHECKPOINT(GET_RACE_CHECKPOINT_TYPE(current_position, checkpoints), checkpoints[current_position]+<<0,0,1.7>>, checkpoints[current_position+1], 3.2, iR, iG, iB, iA)
ENDIF
GET_HUD_COLOUR(HUD_COLOUR_YELLOWLIGHT, iR, iG, iB, iA)
SET_CHECKPOINT_RGBA(checkPoint, iR, iG, iB, iA)
GET_HUD_COLOUR(HUD_COLOUR_NORTH_BLUE, iR, iG, iB, iA)
SET_CHECKPOINT_RGBA2(checkPoint, iR, iG, iB, iA)
SET_CHECKPOINT_CYLINDER_HEIGHT(checkpoint,1.6,1.6,100)
IF NOT IS_ENTITY_DEAD(PLAYER_PED_ID())
FLOAT fDis = GET_DISTANCE_BETWEEN_COORDS(checkpoints[current_position],GET_ENTITY_COORDS(PLAYER_PED_ID()))
IF checkpoint != NULL // Make sure the checkpoint exists first
IF fDis > 100.0
GET_HUD_COLOUR(HUD_COLOUR_YELLOWLIGHT, iR, iG, iB, iA)
iA = 240
SET_CHECKPOINT_RGBA(checkPoint, iR, iG, iB, iA)
GET_HUD_COLOUR(HUD_COLOUR_NORTH_BLUE, iR, iG, iB, iA)
iA = 240
SET_CHECKPOINT_RGBA2(checkPoint, iR, iG, iB, iA)
ELSE
GET_HUD_COLOUR(HUD_COLOUR_YELLOWLIGHT, iR, iG, iB, iA)
iA = ROUND(fDis*2.4.4)
IF iA < 60
iA = 60
ENDIF
SET_CHECKPOINT_RGBA(checkPoint, iR, iG, iB, iA)
GET_HUD_COLOUR(HUD_COLOUR_NORTH_BLUE, 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
ENDIF
ENDPROC
/// PURPOSE:
/// Create the very first blip in a given array of checkpoint coords with a special triathlon radar icon
/// PARAMS:
/// checkpoints - The checkpoint coord array
PROC CREATE_FIRST_BLIP(VECTOR& checkpoints[])
DEBUG_PRINTSTRING("*** Creating first blip")
blip = CREATE_COORD_BLIP(checkpoints[current_position], BLIPPRIORITY_MED, FALSE)
SET_BLIP_COLOUR(blip, BLIP_COLOUR_YELLOW)
SET_BLIP_SCALE(blip, 1.2)
SHOW_HEIGHT_ON_BLIP(blip, FALSE)
IF (current_position < (current_max_positions-1))
nextblip = CREATE_COORD_BLIP(checkpoints[current_position+1], BLIPPRIORITY_MED, FALSE)
SET_BLIP_COLOUR(nextblip, BLIP_COLOUR_YELLOW)
IF (current_position = (current_max_positions-2))
SET_BLIP_SCALE(nextblip, 1.2)
SET_BLIP_SPRITE(nextblip, RADAR_TRACE_RACEFLAG)
SHOW_HEIGHT_ON_BLIP(nextblip, FALSE)
ELSE
SET_BLIP_SCALE(nextblip, 0.7)
SHOW_HEIGHT_ON_BLIP(nextblip, FALSE)
ENDIF
ENDIF
DEBUG_PRINTSTRINGINT("***current_position: ", current_position)
SPAWN_CHECKPOINT(checkpoints)
ENDPROC
/// PURPOSE:
/// Reset both bikes to their starting location at the beginning of the bike section
PROC m_pResetBikes()
// Reset bike mix group entity in audio scene in case Mary Ann gets on a different bike after the reset
IF IS_VEHICLE_OK(opponent_goto_bike)
IF IS_AUDIO_SCENE_ACTIVE("FANATIC_MIX_SCENE")
REMOVE_ENTITY_FROM_AUDIO_MIX_GROUP(opponent_goto_bike)
ENDIF
ENDIF
IF IS_VEHICLE_OK(bike_vehicle) AND IS_VEHICLE_OK(opponent_bike_vehicle)
IF IS_PLAYBACK_GOING_ON_FOR_VEHICLE(bike_vehicle)
STOP_PLAYBACK_RECORDED_VEHICLE(bike_vehicle)
ENDIF
IF IS_PLAYBACK_GOING_ON_FOR_VEHICLE(opponent_bike_vehicle)
STOP_PLAYBACK_RECORDED_VEHICLE(opponent_bike_vehicle)
ENDIF
SET_ENTITY_COORDS(bike_vehicle, << -664.34, 6138.38, 1.20 >>)
SET_ENTITY_HEADING(bike_vehicle, 235)
SET_VEHICLE_DOORS_LOCKED(bike_vehicle, VEHICLELOCK_UNLOCKED)
SET_ENTITY_COORDS(opponent_bike_vehicle, << -664.32, 6133.73, 2.40 >>)
SET_ENTITY_HEADING(opponent_bike_vehicle, -84.69)
SET_VEHICLE_DOORS_LOCKED(opponent_bike_vehicle, VEHICLELOCK_UNLOCKED)
SET_VEHICLE_ON_GROUND_PROPERLY(bike_vehicle)
SET_VEHICLE_ON_GROUND_PROPERLY(opponent_bike_vehicle)
ELSE
IF NOT IS_VEHICLE_OK(bike_vehicle)
bike_vehicle = CREATE_VEHICLE(bike_model, << -664.34, 6138.38, 1.20 >>, 235)
SET_ENTITY_HEADING(bike_vehicle, 235)
SET_VEHICLE_COLOUR_COMBINATION(bike_vehicle, 1)
ENDIF
IF NOT IS_VEHICLE_OK(opponent_bike_vehicle)
opponent_bike_vehicle = CREATE_VEHICLE(bike_model, << -664.32, 6133.73, 2.40 >>, -84.69)
SET_ENTITY_HEADING(opponent_bike_vehicle, -84.69)
SET_VEHICLE_COLOUR_COMBINATION(opponent_bike_vehicle, 2)
ENDIF
SET_VEHICLE_ON_GROUND_PROPERLY(bike_vehicle)
SET_VEHICLE_ON_GROUND_PROPERLY(opponent_bike_vehicle)
ENDIF
// Reset vehicle indexes used for making Mary Ann go to the right bike
opponent_goto_bike = NULL
players_bike = NULL
ENDPROC
/// PURPOSE:
/// Sets up the smacktalk conversations, checkpoints, and Mary-Ann settings
PROC m_pInitialiseRace()
INT i
REPEAT MAX_SMACK_TALK i
smack[0][i].already_said = FALSE
smack[1][i].already_said = FALSE
smack[2][i].already_said = FALSE
ENDREPEAT
// Swimming
smack[0][0].ConvRoot = "FAN3_SW1"
smack[0][1].ConvRoot = "FAN3_SW2"
// Cycling - player lost swimming
smack[1][0].ConvRoot = "FAN3_1WON1"
smack[1][2].ConvRoot = "FAN3_GEN2"
// Cycling - player won swimming
smack[2][1].ConvRoot = "FAN3_1LOSS2"
smack[2][2].ConvRoot = "FAN3_GEN2"
// Running - player lost cycling
smack[3][1].ConvRoot = "FAN3_2WON2"
smack[3][2].ConvRoot = "FAN3_GEN3"
// Running - player won cycling
smack[4][0].ConvRoot = "FAN3_2LOSS1"
smack[4][2].ConvRoot = "FAN3_GEN3"
// Outfit specific variants
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
IF IS_OUTFIT_SUITABLE_FOR_FANATIC_MISSION(3)
smack[2][0].ConvRoot = "FAN3_1LOSS1B"
smack[1][1].ConvRoot = "FAN3_1WON2B"
smack[3][0].ConvRoot = "FAN3_2WON1B"
smack[4][1].ConvRoot = "FAN3_2LOSS2B"
ELSE
smack[2][0].ConvRoot = "FAN3_1LOSS1A"
smack[3][0].ConvRoot = "FAN3_2WON1A"
smack[1][1].ConvRoot = "FAN3_1WON2A"
smack[4][1].ConvRoot = "FAN3_2LOSS2A"
ENDIF
ENDIF
BIKE_POSITIONS[0] = << -624.82, 6164.18, 2.71 >>
BIKE_POSITIONS[1] = << -569.97, 6172.85, 5.51 >>
BIKE_POSITIONS[2] = << -510.38, 6213.40, 9.35 >>
BIKE_POSITIONS[3] = << -497.67, 6272.69, 10.60 >>
BIKE_POSITIONS[4] = << -476.6988, 6310.2969, 12.6412 >>
BIKE_POSITIONS[5] = << -452.44, 6356.24, 11.58 >>
BIKE_POSITIONS[6] = << -410.0162, 6381.5264, 13.0197 >>
BIKE_POSITIONS[7] = << -324.23, 6429.89, 11.94 >>
BIKE_POSITIONS[8] = << -197.2431, 6543.6426, 10.0969 >>
BIKE_POSITIONS[9] = << -5.04, 6728.77, 18.69 >>
BIKE_POSITIONS[10] = << 50.60, 6770.79, 19.50 >>
RUN_POSITIONS[0] = << 90.94, 6804.34, 18.40 >>
RUN_POSITIONS[1] = << 117.87, 6829.98, 15.70 >>
RUN_POSITIONS[2] = << 101.52, 6851.33, 14.67 >>
RUN_POSITIONS[3] = << 67.33, 6889.14, 12.48 >>
RUN_POSITIONS[4] = << 48.75, 6927.61, 13.21 >>
RUN_POSITIONS[5] = << 61.77, 6955.45, 10.81 >>
RUN_POSITIONS[6] = << 47.11, 6965.58, 9.81 >>
RUN_POSITIONS[7] = << 36.23, 6995.43, 7.34 >>
RUN_POSITIONS[8] = << 51.32, 7024.07, 8.87 >>
RUN_POSITIONS[9] = << 68.42, 7030.54, 11.75 >>
RUN_POSITIONS[10] = << 61.60, 7049.50, 15.45 >>
//RUN_POSITIONS[10] = << 65.36, 7047.99, 15.59 >> // For realtime version
OPEN_TEST_POLY(MaryAnnBikeBounds)
ADD_TEST_POLY_VERT(MaryAnnBikeBounds, <<-669.58, 6153.29, 0.45>>)
ADD_TEST_POLY_VERT(MaryAnnBikeBounds, <<-522.75, 6317.60, 9.79>>)
ADD_TEST_POLY_VERT(MaryAnnBikeBounds, <<-221.87, 6550.84, 8.87>>)
ADD_TEST_POLY_VERT(MaryAnnBikeBounds, <<-220.85, 6657.39, 0.47>>)
ADD_TEST_POLY_VERT(MaryAnnBikeBounds, <<-98.01, 6746.05, 0.66>>)
ADD_TEST_POLY_VERT(MaryAnnBikeBounds, <<82.53, 6814.59, 17.29>>) // end of coast-side boundary
ADD_TEST_POLY_VERT(MaryAnnBikeBounds, <<100.83, 6770.48, 28.49>>) // first point on Paleto Bay side boundary
ADD_TEST_POLY_VERT(MaryAnnBikeBounds, <<-346.80, 6373.35, 20.40>>)
ADD_TEST_POLY_VERT(MaryAnnBikeBounds, <<-464.00, 6242.33, 27.31>>)
ADD_TEST_POLY_VERT(MaryAnnBikeBounds, <<-478.26, 6133.85, 13.53>>)
ADD_TEST_POLY_VERT(MaryAnnBikeBounds, <<-632.49, 6112.85, 9.95>>)
ADD_TEST_POLY_VERT(MaryAnnBikeBounds, <<-679.62, 6097.66, 2.07>>)
ADD_TEST_POLY_VERT(MaryAnnBikeBounds, <<-721.78, 6112.86, -0.68>>)
CLOSE_TEST_POLY(MaryAnnBikeBounds)
CREATE_CHECKPOINT_LINE(<< -888.0333, 6142.6577, 2.3874 >>, << -679.05, 6139.86, 0.70 >>, SWIM_POSITIONS, MAX_SWIM_POSITIONS) //propr
bike_model = scorcher
sOpponentWaypointName = "Fan3_pedBike"
IF IS_REPLAY_IN_PROGRESS()
// Get the previously-accrued amount of time from the last play attempt to add on to the existing time
replay_timer_addition = g_replay.iReplayInt[F3_CHECKPOINT_TIME]
ENDIF
SET_ALL_VEHICLE_GENERATORS_ACTIVE_IN_AREA(<<-191.098450,6550.963867,10.097297>>, <<-199.409927,6542.312012,11.097295>>, FALSE)
SET_ALL_VEHICLE_GENERATORS_ACTIVE_IN_AREA(<<-226.3857, 6498.8770, 9.2147>>, <<-173.1313, 6595.7710, 20.7218>>, FALSE)
SET_ROADS_IN_ANGLED_AREA(vRoadDisableAA1, vRoadDisableAA2, fRoadDisableAA, FALSE, FALSE)
SET_WANTED_LEVEL_MULTIPLIER(0.1)
REQUEST_MODEL(bike_model)
REQUEST_ANIM_SET("FEMALE_FAST_RUNNER")
WHILE NOT HAS_MODEL_LOADED(bike_model)
OR NOT HAS_ANIM_SET_LOADED("FEMALE_FAST_RUNNER")
WAIT(0)
ENDWHILE
m_pResetBikes()
IF IS_ENTITY_ALIVE(opponent)
SET_PED_DIES_IN_WATER(opponent, FALSE)
SET_PED_PATH_PREFER_TO_AVOID_WATER(opponent, FALSE)
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(opponent, TRUE)
SET_ENTITY_ONLY_DAMAGED_BY_PLAYER(opponent, TRUE)
SET_PED_CAN_BE_TARGETTED(opponent, false)
SET_ENTITY_LOAD_COLLISION_FLAG(opponent, TRUE)
SET_PED_CAN_BE_KNOCKED_OFF_VEHICLE(opponent, KNOCKOFFVEHICLE_NEVER)
SET_PED_MOVEMENT_CLIPSET(opponent, "FEMALE_FAST_RUNNER")
SET_PED_CAN_RAGDOLL_FROM_PLAYER_IMPACT(opponent, FALSE)
//SET_DRIVER_RACING_MODIFIER(opponent, 0.1)
ENDIF
ENDPROC
/// PURPOSE:
/// Load all models and recordings we need for the swim section, and create entities as needed
PROC m_pLoadSwim()
ma_pSwitchState(MS_SWIM) // Do this here so Mary Ann continues to run after the cutscene
REQUEST_MODEL(bike_model)
//REQUEST_MODEL(boat_model_1)
//REQUEST_MODEL(A_M_Y_Jetski_01)
REQUEST_WAYPOINT_RECORDING("Fan3_RollingStart")
//REQUEST_WAYPOINT_RECORDING("Fan3_jetskiRoute")
//REQUEST_WAYPOINT_RECORDING("Fan3_jetskiRoute2")
REQUEST_ADDITIONAL_TEXT("FATIC3", MISSION_TEXT_SLOT)
WHILE NOT //HAS_MODEL_LOADED(boat_model_1)
//OR NOT HAS_MODEL_LOADED(A_M_Y_Jetski_01)
GET_IS_WAYPOINT_RECORDING_LOADED("Fan3_RollingStart")
//OR NOT GET_IS_WAYPOINT_RECORDING_LOADED("Fan3_jetskiRoute")
//OR NOT GET_IS_WAYPOINT_RECORDING_LOADED("Fan3_jetskiRoute2")
OR NOT HAS_ADDITIONAL_TEXT_LOADED(MISSION_TEXT_SLOT)
OR NOT HAS_MODEL_LOADED(bike_model)
ma_pDoIntroBoost()
DEBUG_PRINTSTRING("Waiting for swim assets...")
WAIT(0)
ENDWHILE
OPEN_TEST_POLY(innerBounds)
ADD_TEST_POLY_VERT(innerBounds, <<-911.33, 6156.95, 3.78>>)
ADD_TEST_POLY_VERT(innerBounds, <<-833.30, 6159.46, 1.19>>)
ADD_TEST_POLY_VERT(innerBounds, <<-712.84, 6161.51, 0.18>>)
ADD_TEST_POLY_VERT(innerBounds, <<-653.84, 6154.68, 1.39>>)
ADD_TEST_POLY_VERT(innerBounds, <<-651.92, 6134.70, 3.20>>)
ADD_TEST_POLY_VERT(innerBounds, <<-683.51, 6108.33, 1.60>>)
ADD_TEST_POLY_VERT(innerBounds, <<-922.48, 6125.13, 5.71>>)
CLOSE_TEST_POLY(innerBounds)
// SAFE_DELETE_PED(jetski_guy1)
// SAFE_DELETE_VEHICLE(jetski1)
//
// jetski1 = CREATE_VEHICLE(boat_model_1, <<-847.760010,6295.217773,-0.160587>>, -165.894836)
// IF IS_VEHICLE_OK(jetski1)
// SET_VEHICLE_DOORS_LOCKED(jetski1, VEHICLELOCK_LOCKOUT_PLAYER_ONLY)
// SET_ENTITY_LOAD_COLLISION_FLAG(jetski1, TRUE)
// ENDIF
//
// jetski_guy1 = CREATE_PED_INSIDE_VEHICLE(jetski1, PEDTYPE_MISSION, A_M_Y_Jetski_01)
//
// SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(jetski_guy1, TRUE)
//
// SAFE_DELETE_PED(jetski_guy2)
// SAFE_DELETE_VEHICLE(jetski2)
//
// jetski2 = CREATE_VEHICLE(boat_model_1, <<-864.4749, 6291.2881, -4.71977>>, 215.8633)
// IF IS_VEHICLE_OK(jetski2)
// SET_VEHICLE_DOORS_LOCKED(jetski2, VEHICLELOCK_LOCKOUT_PLAYER_ONLY)
// SET_ENTITY_LOAD_COLLISION_FLAG(jetski2, TRUE)
// ENDIF
//
// jetski_guy2 = CREATE_PED_INSIDE_VEHICLE(jetski2, PEDTYPE_MISSION, A_M_Y_Jetski_01)
//
// SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(jetski_guy2, TRUE)
//
// SET_MODEL_AS_NO_LONGER_NEEDED(boat_model_1)
// SET_MODEL_AS_NO_LONGER_NEEDED(A_M_Y_Jetski_01)
ADD_PED_FOR_DIALOGUE(conversation, ENUM_TO_INT(CHAR_FRANKLIN), PLAYER_PED_ID(), "FRANKLIN")
ADD_PED_FOR_DIALOGUE(conversation, 3, opponent, "MARYANN")
USE_WAYPOINT_RECORDING_AS_ASSISTED_MOVEMENT_ROUTE("Fan3_RollingStart", TRUE)
current_position = 0
current_max_positions = MAX_SWIM_POSITIONS
missionStage = MS_SWIM
CREATE_FIRST_BLIP(SWIM_POSITIONS)
IF NOT bSkipped
TRIGGER_MUSIC_EVENT("FANATIC3_START")
DEBUG_PRINTSTRING("Starting swim music")
ENDIF
intro_playing = FALSE
// boat_launched = FALSE
// jetski_conv_launched = FALSE
// maryann_jetski_conv_launched = FALSE
bDoneSwimDialogue = FALSE
iTrashTalkTimer = GET_GAME_TIMER()
IF NOT IS_REPLAY_BEING_SET_UP()
RC_END_CUTSCENE_MODE()
ENDIF
PRINT_NOW("FATIC3_1", DEFAULT_GOD_TEXT_TIME, 1) //Swim across the ~y~bay.
ENDPROC
/// PURPOSE:
/// Unload the peds from the swim section
PROC m_pUnloadSwim()
ENDPROC
/// PURPOSE:
/// Load all models and recordings we need for the bike section, and create entities as needed
/// RETURNS:
/// TRUE when all resources have loaded and been created, FALSE otherwise
FUNC BOOL m_pLoadBike()
REQUEST_MODEL(Patriot)
REQUEST_MODEL(A_F_M_KTown_02)
REQUEST_WAYPOINT_RECORDING("Fan3_baddriver")
REQUEST_VEHICLE_RECORDING(500, "Fan3_MaryAnnBikeJump")
REQUEST_WAYPOINT_RECORDING("Fan3_pedBike")
REQUEST_MODEL(S_M_M_DockWork_01)
REQUEST_ANIM_DICT("rcmfanatic3")
IF NOT HAS_MODEL_LOADED(Patriot)
OR NOT HAS_MODEL_LOADED(A_F_M_KTown_02)
OR NOT HAS_MODEL_LOADED(S_M_M_DockWork_01)
OR NOT GET_IS_WAYPOINT_RECORDING_LOADED("Fan3_baddriver")
OR NOT HAS_VEHICLE_RECORDING_BEEN_LOADED(500, "Fan3_MaryAnnBikeJump")
OR NOT GET_IS_WAYPOINT_RECORDING_LOADED("Fan3_pedBike")
OR NOT HAS_ANIM_DICT_LOADED("rcmfanatic3")
DEBUG_PRINTSTRING("Waiting for bike resources")
RETURN FALSE
ENDIF
SAFE_DELETE_VEHICLE(bad_driver_car)
bad_driver_car = CREATE_VEHICLE(Patriot, << -206.0824, 6557.3765, 11.0625 >>, 220.94)
SAFE_DELETE_PED(bad_driver_ped)
IF IS_VEHICLE_OK(bad_driver_car) AND NOT IS_ENTITY_ALIVE(bad_driver_ped)
bad_driver_ped = CREATE_PED_INSIDE_VEHICLE(bad_driver_car, PEDTYPE_MISSION, A_F_M_KTown_02)
ENDIF
SET_MODEL_AS_NO_LONGER_NEEDED(Patriot)
if IS_ENTITY_ALIVE(bad_driver_ped)
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(bad_driver_ped, TRUE)
ENDIF
SET_MODEL_AS_NO_LONGER_NEEDED(A_F_M_KTown_02)
SAFE_DELETE_PED(fence_worker)
fence_worker = CREATE_PED(PEDTYPE_MISSION, S_M_M_DockWork_01, << -185.1444, 6561.3379, 10.1026 >>, 310)
IF IS_ENTITY_ALIVE(fence_worker)
TASK_PLAY_ANIM(fence_worker, "rcmfanatic3", "KNEEL_IDLE_A", NORMAL_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_LOOPING)
ENDIF
SET_MODEL_AS_NO_LONGER_NEEDED(S_M_M_DockWork_01)
CLEAR_ANGLED_AREA_OF_VEHICLES(vRoadDisableAA1, vRoadDisableAA2, fRoadDisableAA) // Clear any ambient cars that've sneaked onto the road when they SHOULDN'T HAVE
OPEN_TEST_POLY(innerBounds)
ADD_TEST_POLY_VERT(innerBounds, <<-669.58, 6153.29, 0.45>>)
ADD_TEST_POLY_VERT(innerBounds, <<-522.75, 6317.60, 9.79>>)
ADD_TEST_POLY_VERT(innerBounds, <<-221.87, 6550.84, 8.87>>)
ADD_TEST_POLY_VERT(innerBounds, <<-220.85, 6657.39, 0.47>>)
ADD_TEST_POLY_VERT(innerBounds, <<-98.01, 6746.05, 0.66>>)
ADD_TEST_POLY_VERT(innerBounds, <<58.62, 6800.74, 19.35>>) // end of coast-side boundary
ADD_TEST_POLY_VERT(innerBounds, <<92.21, 6746.91, 37.55>>) // first point on Paleto Bay side boundary
ADD_TEST_POLY_VERT(innerBounds, <<-346.80, 6373.35, 20.40>>)
ADD_TEST_POLY_VERT(innerBounds, <<-464.00, 6242.33, 27.31>>)
ADD_TEST_POLY_VERT(innerBounds, <<-478.26, 6133.85, 13.53>>)
ADD_TEST_POLY_VERT(innerBounds, <<-632.49, 6112.85, 9.95>>)
ADD_TEST_POLY_VERT(innerBounds, <<-679.62, 6097.66, 2.07>>)
ADD_TEST_POLY_VERT(innerBounds, <<-721.78, 6112.86, -0.68>>)
CLOSE_TEST_POLY(innerBounds)
ADD_PED_FOR_DIALOGUE(conversation, ENUM_TO_INT(CHAR_FRANKLIN), PLAYER_PED_ID(), "FRANKLIN")
ADD_PED_FOR_DIALOGUE(conversation, 3, opponent, "MARYANN")
bMADoingJump = FALSE
IF NOT bSkipped
TRIGGER_MUSIC_EVENT("FANATIC3_CYCLE")
DEBUG_PRINTSTRING("Starting bike music")
ENDIF
RETURN TRUE
ENDFUNC
/// PURPOSE:
/// Unload all resources for the bike section
PROC m_pUnloadBike()
SAFE_RELEASE_PED(bad_driver_ped)
SAFE_RELEASE_PED(fence_worker)
SAFE_RELEASE_VEHICLE(bad_driver_car)
REMOVE_WAYPOINT_RECORDING("Fan3_baddriver")
REMOVE_ANIM_DICT("rcmfanatic3")
SET_ALL_VEHICLE_GENERATORS_ACTIVE_IN_AREA(<<-191.098450,6550.963867,10.097297>>, <<-199.409927,6542.312012,11.097295>>, TRUE)
SET_ALL_VEHICLE_GENERATORS_ACTIVE_IN_AREA(<<-226.3857, 6498.8770, 9.2147>>, <<-173.1313, 6595.7710, 20.7218>>, TRUE)
ENDPROC
/// PURPOSE:
/// Load all the resources for the jog section of the mission and create them
/// RETURNS:
/// TRUE when all resources have been loaded and created, FALSE otherwise
FUNC BOOL m_pLoadJog()
REQUEST_MODEL(BALLER)
REQUEST_MODEL(A_M_Y_BeachVesp_01)
REQUEST_MODEL(A_M_Y_MusclBeac_02)
REQUEST_MODEL(A_F_Y_Runner_01)
REQUEST_MODEL(DOG_MODEL)
REQUEST_MODEL(scorcher)
REQUEST_ANIM_DICT("rcmfanatic3")
REQUEST_ANIM_DICT("rcmfanatic1maryann_stretchidle_b")
REQUEST_WAYPOINT_RECORDING("fan3_pedJog")
REQUEST_WAYPOINT_RECORDING("fan3_dogroute")
REQUEST_WAYPOINT_RECORDING("fan3_ownerroute")
IF NOT HAS_ANIM_DICT_LOADED("rcmfanatic3")
OR NOT HAS_ANIM_DICT_LOADED("rcmfanatic1maryann_stretchidle_b")
OR NOT HAS_MODEL_LOADED(BALLER)
OR NOT HAS_MODEL_LOADED(scorcher)
OR NOT HAS_MODEL_LOADED(A_M_Y_BeachVesp_01)
OR NOT HAS_MODEL_LOADED(A_F_Y_Runner_01)
OR NOT HAS_MODEL_LOADED(DOG_MODEL)
OR NOT HAS_MODEL_LOADED(A_M_Y_MusclBeac_02)
OR NOT GET_IS_WAYPOINT_RECORDING_LOADED("fan3_pedJog")
OR NOT GET_IS_WAYPOINT_RECORDING_LOADED("fan3_dogroute")
OR NOT GET_IS_WAYPOINT_RECORDING_LOADED("fan3_ownerroute")
RETURN FALSE
ENDIF
iBinocStage = 0
iStretchStage = 0
iChinupStage = 0
iOwnerStage = 0
SAFE_DELETE_VEHICLE(picniccar2)
picniccar2 = CREATE_VEHICLE(BALLER, <<12.086388,6967.021484,10.150966>>, 0.588968)
if IS_VEHICLE_OK(picniccar2)
SET_VEHICLE_ON_GROUND_PROPERLY(picniccar2)
SET_VEHICLE_ENGINE_HEALTH(picniccar2, 400)
ENDIF
SAFE_DELETE_PED(binoculars_guy)
SAFE_DELETE_OBJECT(binocs)
binoculars_guy = CREATE_PED(PEDTYPE_MISSION, A_M_Y_BeachVesp_01, << 14.1481, 6966.5366, 9.4860 >>, 335.3788)
binocs = CREATE_OBJECT(PROP_BINOC_01, << 14.1481, 6966.5366, 9.4860 >>)
if IS_ENTITY_ALIVE(binoculars_guy)
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(binoculars_guy, true)
SET_PED_COMPONENT_VARIATION(binoculars_guy, INT_TO_ENUM(PED_COMPONENT, 0), 0, 0)
SET_PED_COMPONENT_VARIATION(binoculars_guy, INT_TO_ENUM(PED_COMPONENT, 2), 0, 0)
SET_PED_COMPONENT_VARIATION(binoculars_guy, INT_TO_ENUM(PED_COMPONENT, 3), 0, 0)
SET_PED_COMPONENT_VARIATION(binoculars_guy, INT_TO_ENUM(PED_COMPONENT, 4), 0, 0)
SET_PED_COMPONENT_VARIATION(binoculars_guy, INT_TO_ENUM(PED_COMPONENT, 8), 0, 0)
SET_PED_CAN_RAGDOLL(binoculars_guy, FALSE)
ATTACH_ENTITY_TO_ENTITY(binocs, binoculars_guy, GET_PED_BONE_INDEX(binoculars_guy, BONETAG_L_HAND), <<0.12,0,0.1>>, <<-22,90,-20>>, true)
TASK_PLAY_ANIM(binoculars_guy, "rcmfanatic3", "binoculars", NORMAL_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_LOOPING)
ADD_PED_FOR_DIALOGUE(conv_frank, 4, binoculars_guy, "FAN3BIRDWATCHER")
ENDIF
SAFE_DELETE_PED(chinups_guy)
chinups_guy = CREATE_PED(PEDTYPE_MISSION, A_M_Y_MusclBeac_02, <<64.7329, 6938.6245, 12.2245>>, 241.60)
if IS_ENTITY_ALIVE(chinups_guy)
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(chinups_guy, true)
SET_PED_COMPONENT_VARIATION(chinups_guy, INT_TO_ENUM(PED_COMPONENT, 0), 0, 0)
SET_PED_COMPONENT_VARIATION(chinups_guy, INT_TO_ENUM(PED_COMPONENT, 2), 0, 0)
SET_PED_COMPONENT_VARIATION(chinups_guy, INT_TO_ENUM(PED_COMPONENT, 3), 1, 1)
SET_PED_COMPONENT_VARIATION(chinups_guy, INT_TO_ENUM(PED_COMPONENT, 4), 0, 0)
SET_PED_COMPONENT_VARIATION(chinups_guy, INT_TO_ENUM(PED_COMPONENT, 8), 0, 0)
// SET_PED_CAN_RAGDOLL(chinups_guy, FALSE)
TASK_PLAY_ANIM(chinups_guy, "rcmfanatic3", "base", NORMAL_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_LOOPING)
// ADD_PED_FOR_DIALOGUE(conv_frank, 4, binoculars_guy, "FAN3BIRDWATCHER")
ENDIF
SAFE_DELETE_PED(stretching_woman)
stretching_woman = CREATE_PED(PEDTYPE_MISSION, A_F_Y_Runner_01, <<76.5829, 6957.7534, 10.3747>>, 30.24)
if IS_ENTITY_ALIVE(stretching_woman)
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(stretching_woman, true)
TASK_PLAY_ANIM(stretching_woman, "rcmfanatic1maryann_stretchidle_b", "idle_e", NORMAL_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_LOOPING)
ENDIF
SAFE_DELETE_PED(running_dog)
running_dog = CREATE_PED(PEDTYPE_MISSION, DOG_MODEL, <<114.038,6900.039,20.455>>, 56.723)
IF IS_ENTITY_ALIVE(running_dog)
SET_PED_DEFAULT_COMPONENT_VARIATION(running_dog)
ENDIF
SAFE_DELETE_PED(dog_owner)
// Do not create the dog owner ped here!
// She gets created in DO_OWNER_SCENE(), so the player can't (un)intentionally miss checkpoints
// and go to where she spawns to see her gawping in place waiting for the trigger
SAFE_DELETE_VEHICLE(EndingBikeMA)
EndingBikeMA = CREATE_VEHICLE(scorcher, vEndingBikeMASpawn, fEndingBikeMASpawn)
if IS_VEHICLE_OK(EndingBikeMA)
SET_VEHICLE_ON_GROUND_PROPERLY(EndingBikeMA)
ENDIF
SET_MODEL_AS_NO_LONGER_NEEDED(A_M_Y_Hiker_01)
SET_MODEL_AS_NO_LONGER_NEEDED(Patriot)
SET_MODEL_AS_NO_LONGER_NEEDED(A_M_Y_MusclBeac_02)
SET_MODEL_AS_NO_LONGER_NEEDED(DOG_MODEL)
SET_MODEL_AS_NO_LONGER_NEEDED(BALLER)
SET_MODEL_AS_NO_LONGER_NEEDED(PROP_BINOC_01)
SET_MODEL_AS_NO_LONGER_NEEDED(A_M_Y_Hiker_01)
OPEN_TEST_POLY(innerBounds)
ADD_TEST_POLY_VERT(innerBounds, <<42.25, 6775.99, 20.035>>)
ADD_TEST_POLY_VERT(innerBounds, <<70.90, 6811.02, 16.56>>)
ADD_TEST_POLY_VERT(innerBounds, <<30.55, 6908.24, 12.57>>)
ADD_TEST_POLY_VERT(innerBounds, <<17.22, 6966.57, 9.87>>)
ADD_TEST_POLY_VERT(innerBounds, <<42.16, 7088.71, 0.65>>)
ADD_TEST_POLY_VERT(innerBounds, <<133.71, 7050.03, 0.35>>)
ADD_TEST_POLY_VERT(innerBounds, <<119.44, 6923.47, 19.92>>)
ADD_TEST_POLY_VERT(innerBounds, <<144.19, 6821.13, 21.80>>)
ADD_TEST_POLY_VERT(innerBounds, <<128.37, 6764.95, 26.39>>)
ADD_TEST_POLY_VERT(innerBounds, <<49.68, 6736.11, 30.31>>)
CLOSE_TEST_POLY(innerBounds)
ADD_PED_FOR_DIALOGUE(conversation, ENUM_TO_INT(CHAR_FRANKLIN), PLAYER_PED_ID(), "FRANKLIN")
ADD_PED_FOR_DIALOGUE(conversation, 3, opponent, "MARYANN")
IF NOT bSkipped
TRIGGER_MUSIC_EVENT("FANATIC3_RUN")
DEBUG_PRINTSTRING("Starting run music")
ENDIF
RETURN TRUE
ENDFUNC
PROC m_pUnloadJog()
SAFE_RELEASE_VEHICLE(picniccar2)
SAFE_RELEASE_PED(binoculars_guy)
SAFE_RELEASE_OBJECT(binocs)
SAFE_RELEASE_PED(stretching_woman)
SAFE_RELEASE_PED(running_dog)
SAFE_RELEASE_PED(dog_owner)
SAFE_RELEASE_VEHICLE(EndingBikeMA)
SAFE_RELEASE_PED(chinups_guy)
ENDPROC
/// PURPOSE:
/// Keep track of and update the player's checkpoints one by one as they progress through the current race section
/// PARAMS:
/// checkpoints - The checkpoint coord array we're keeping track of at this time
/// RETURNS:
/// TRUE when the player has completed this section of the race, FALSE otherwise
FUNC BOOL DO_CHECKPOINT_UPDATES(VECTOR& checkpoints[])
VECTOR player_pos = GET_ENTITY_COORDS(PLAYER_PED_ID())
FLOAT dist = GET_DISTANCE_BETWEEN_COORDS(player_pos, checkpoints[current_position], FALSE)
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_MISSION, "Player: <<", GET_STRING_FROM_VECTOR(player_pos), ">> checkpoint: <<", GET_STRING_FROM_VECTOR(checkpoints[current_position]), ">> dist: ", dist)
#ENDIF
IF dist < 5.5
SAFE_REMOVE_BLIP(blip)
SAFE_REMOVE_BLIP(nextblip)
PLAY_SOUND_FRONTEND(-1, "CHECKPOINT_NORMAL", "HUD_MINI_GAME_SOUNDSET", FALSE)
IF checkpoint != NULL
DEBUG_PRINTSTRING("Create prev CP")
INT PreviR, PreviG, PreviB
GET_HUD_COLOUR(HUD_COLOUR_WHITE, PreviR, PreviG, PreviB, iPrevAlpha)
iPrevAlpha = 180
VECTOR tempPos = checkpoints[current_position]
SWITCH missionStage
CASE MS_SWIM
IF (current_position = (current_max_positions - 1))
tempPos +=<<0,0,1.7>>
ELSE
FLOAT fAdjust
IF current_position = 6
fAdjust = 1.5
ELSE
fAdjust = 0.4
ENDIF
tempPos +=<<0,0,fAdjust>>
ENDIF
BREAK
CASE MS_BIKE
IF (current_position = (current_max_positions - 1))
tempPos +=<<0,0,1.7>>
ELSE
tempPos +=<<0,0,2.0>>
ENDIF
BREAK
CASE MS_RUN
IF (current_position = (current_max_positions - 1))
tempPos +=<<0,0,1.7>>
ELSE
tempPos +=<<0,0,2.0>>
ENDIF
BREAK
ENDSWITCH
IF (current_position = (current_max_positions - 1))
VECTOR to_position = checkpoints[current_position]
PrevCheckpoint = CREATE_CHECKPOINT(CHECKPOINT_RACE_GROUND_FLAG, tempPos, to_position, 3.2, PreviR, PreviG, PreviB, iPrevAlpha)
ELSE
VECTOR to_position = checkpoints[current_position+1]
IF missionStage = MS_SWIM
AND current_position = 0
tempPos = checkpoints[current_position]+<<0,0,2.0>>
PrevCheckpoint = CREATE_CHECKPOINT(CHECKPOINT_RACE_GROUND_CHEVRON_1, tempPos, to_position, 3.2, PreviR, PreviG, PreviB, iPrevAlpha)
ELIF missionStage = MS_BIKE
AND current_position = 0
tempPos -=<<0,0,0.3>> // Bring this down to 1.7 to match, not 2.0
PrevCheckpoint = CREATE_CHECKPOINT(CHECKPOINT_RACE_GROUND_CHEVRON_2, tempPos, to_position, 3.2, PreviR, PreviG, PreviB, iPrevAlpha)
ELSE
PrevCheckpoint = CREATE_CHECKPOINT(GET_RACE_CHECKPOINT_TYPE(current_position, checkpoints), tempPos, to_position, 3.2, PreviR, PreviG, PreviB, iPrevAlpha)
ENDIF
ENDIF
SET_CHECKPOINT_RGBA(PrevCheckpoint, PreviR, PreviG, PreviB, iPrevAlpha)
SET_CHECKPOINT_RGBA2(PrevCheckpoint, PreviR,PreviG, PreviB, iPrevAlpha)
ENDIF
DELETE_CHECKPOINT(checkpoint)
current_position++
IF current_position = current_max_positions
return TRUE
ELSE
blip = CREATE_COORD_BLIP(checkpoints[current_position], BLIPPRIORITY_MED, FALSE)
SET_BLIP_COLOUR(blip, BLIP_COLOUR_YELLOW)
SET_BLIP_SCALE(blip, 1.2)
SHOW_HEIGHT_ON_BLIP(blip, FALSE)
IF (current_position = (current_max_positions-1)) // If it's the final blip, give it a flag sprite
SET_BLIP_SPRITE(blip, RADAR_TRACE_RACEFLAG)
ENDIF
IF (current_position < (current_max_positions-1))
nextblip = CREATE_COORD_BLIP(checkpoints[current_position+1], BLIPPRIORITY_MED, FALSE)
SET_BLIP_COLOUR(nextblip, BLIP_COLOUR_YELLOW)
IF (current_position = (current_max_positions-2))
SET_BLIP_SCALE(nextblip, 1.2)
SET_BLIP_SPRITE(nextblip, RADAR_TRACE_RACEFLAG)
SHOW_HEIGHT_ON_BLIP(nextblip, FALSE)
ELSE
SET_BLIP_SCALE(nextblip, 0.7)
SHOW_HEIGHT_ON_BLIP(nextblip, FALSE)
ENDIF
ENDIF
VECTOR to_position
// If this is the last checkpoint, do a checkpoint flag instead
IF (current_position = (current_max_positions - 1))
to_position = checkpoints[current_position]
currentCPColour = GET_RACE_CHECKPOINT_COLOUR(GET_RACE_CHECKPOINT_TYPE(current_position, checkpoints))
INT iR, iG, iB, iA
GET_HUD_COLOUR(currentCPColour, iR, iG, iB, iA)
SWITCH missionStage
CASE MS_SWIM
checkpoint = CREATE_CHECKPOINT(CHECKPOINT_RACE_GROUND_FLAG, checkpoints[current_position]+<<0,0,1.7>>, to_position, 3.2, iR, iG, iB, iA)
BREAK
CASE MS_BIKE
checkpoint = CREATE_CHECKPOINT(CHECKPOINT_RACE_GROUND_FLAG, checkpoints[current_position]+<<0,0,1.7>>, to_position, 3.2, iR, iG, iB, iA)
BREAK
CASE MS_RUN
checkpoint = CREATE_CHECKPOINT(CHECKPOINT_RACE_GROUND_FLAG, checkpoints[current_position]+<<0,0,1.7>>, to_position, 3.2, iR, iG, iB, iA)
BREAK
ENDSWITCH
GET_HUD_COLOUR(HUD_COLOUR_YELLOWLIGHT, iR, iG, iB, iA)
SET_CHECKPOINT_RGBA(checkPoint, iR, iG, iB, iA)
GET_HUD_COLOUR(HUD_COLOUR_NORTH_BLUE, iR, iG, iB, iA)
SET_CHECKPOINT_RGBA2(checkPoint, iR, iG, iB, iA)
SET_CHECKPOINT_CYLINDER_HEIGHT(checkpoint,1.6,1.6,100)
IF NOT IS_ENTITY_DEAD(PLAYER_PED_ID())
FLOAT fDis = GET_DISTANCE_BETWEEN_COORDS(checkpoints[current_position],GET_ENTITY_COORDS(PLAYER_PED_ID()))
IF checkpoint != NULL // Make sure the checkpoint exists first
IF fDis > 100.0
GET_HUD_COLOUR(HUD_COLOUR_YELLOWLIGHT, iR, iG, iB, iA)
iA = 240
SET_CHECKPOINT_RGBA(checkPoint, iR, iG, iB, iA)
GET_HUD_COLOUR(HUD_COLOUR_NORTH_BLUE, iR, iG, iB, iA)
iA = 240
SET_CHECKPOINT_RGBA2(checkPoint, iR, iG, iB, iA)
ELSE
GET_HUD_COLOUR(HUD_COLOUR_YELLOWLIGHT, iR, iG, iB, iA)
iA = ROUND(fDis*2.4)
IF iA < 60
iA = 60
ENDIF
SET_CHECKPOINT_RGBA(checkPoint, iR, iG, iB, iA)
GET_HUD_COLOUR(HUD_COLOUR_NORTH_BLUE, 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
// Otherwise, do a normal checkpoint
ELSE
currentCPColour = GET_RACE_CHECKPOINT_COLOUR(GET_RACE_CHECKPOINT_TYPE(current_position, checkpoints))
INT iR, iG, iB, iA
GET_HUD_COLOUR(currentCPColour, iR, iG, iB, iA)
to_position = checkpoints[current_position+1]
IF missionStage = MS_SWIM
// The swim checkpoints are autogenerated (see CREATE_CHECKPOINT_LINE()) and don't take into account that the sea is lower than the
// start and end positions of the autogen we've done - so we'll manually lower them by 2m to compensate
FLOAT fAdjust
IF current_position = 6
fAdjust = 1.5
ELSE
fAdjust = 0.4
ENDIF
checkpoint = CREATE_CHECKPOINT(GET_RACE_CHECKPOINT_TYPE(current_position, checkpoints), checkpoints[current_position]+<<0,0,fAdjust>>, to_position, 3.2, iR, iG, iB, iA)
ELIF missionStage = MS_BIKE
// Otherwise we'll use the checkpoint vecs as they are (because I've manually placed the bastards)
checkpoint = CREATE_CHECKPOINT(GET_RACE_CHECKPOINT_TYPE(current_position, checkpoints), checkpoints[current_position]+<<0,0,2.0>>, to_position, 3.2, iR, iG, iB, iA)
ELSE
// Otherwise we'll use the checkpoint vecs as they are (because I've manually placed the bastards)
checkpoint = CREATE_CHECKPOINT(GET_RACE_CHECKPOINT_TYPE(current_position, checkpoints), checkpoints[current_position]+<<0,0,2.0>>, to_position, 3.2, iR, iG, iB, iA)
ENDIF
GET_HUD_COLOUR(HUD_COLOUR_YELLOWLIGHT, iR, iG, iB, iA)
SET_CHECKPOINT_RGBA(checkPoint, iR, iG, iB, iA)
GET_HUD_COLOUR(HUD_COLOUR_NORTH_BLUE, iR, iG, iB, iA)
SET_CHECKPOINT_RGBA2(checkPoint, iR, iG, iB, iA)
SET_CHECKPOINT_CYLINDER_HEIGHT(checkpoint,1.6,1.6,100)
IF NOT IS_ENTITY_DEAD(PLAYER_PED_ID())
FLOAT fDis = GET_DISTANCE_BETWEEN_COORDS(checkpoints[current_position],GET_ENTITY_COORDS(PLAYER_PED_ID()))
IF checkpoint != NULL // Make sure the checkpoint exists first
IF fDis > 100.0
GET_HUD_COLOUR(HUD_COLOUR_YELLOWLIGHT, iR, iG, iB, iA)
iA = 240
SET_CHECKPOINT_RGBA(checkPoint, iR, iG, iB, iA)
GET_HUD_COLOUR(HUD_COLOUR_NORTH_BLUE, iR, iG, iB, iA)
iA = 240
SET_CHECKPOINT_RGBA2(checkPoint, iR, iG, iB, iA)
ELSE
GET_HUD_COLOUR(HUD_COLOUR_YELLOWLIGHT, iR, iG, iB, iA)
iA = ROUND(fDis*2.4)
IF iA < 60
iA = 60
ENDIF
SET_CHECKPOINT_RGBA(checkPoint, iR, iG, iB, iA)
GET_HUD_COLOUR(HUD_COLOUR_NORTH_BLUE, 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
ENDIF
ENDIF
ELSE
// CHECKPOINT ALPHA STUFF
currentCPColour = GET_RACE_CHECKPOINT_COLOUR(GET_RACE_CHECKPOINT_TYPE(current_position, checkpoints))
INT iR, iG, iB, iA
GET_HUD_COLOUR(currentCPColour, iR, iG, iB, iA)
IF NOT IS_ENTITY_DEAD(PLAYER_PED_ID())
FLOAT fDis = GET_DISTANCE_BETWEEN_COORDS(checkpoints[current_position],GET_ENTITY_COORDS(PLAYER_PED_ID()))
IF checkpoint != NULL // Make sure the checkpoint exists first
IF fDis > 100.0
GET_HUD_COLOUR(HUD_COLOUR_YELLOWLIGHT, iR, iG, iB, iA)
iA = 240
SET_CHECKPOINT_RGBA(checkPoint, iR, iG, iB, iA)
GET_HUD_COLOUR(HUD_COLOUR_NORTH_BLUE, iR, iG, iB, iA)
iA = 240
SET_CHECKPOINT_RGBA2(checkPoint, iR, iG, iB, iA)
ELSE
GET_HUD_COLOUR(HUD_COLOUR_YELLOWLIGHT, iR, iG, iB, iA)
iA = ROUND(fDis*2.4)
IF iA < 60
iA = 60
ENDIF
SET_CHECKPOINT_RGBA(checkPoint, iR, iG, iB, iA)
GET_HUD_COLOUR(HUD_COLOUR_NORTH_BLUE, 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
ENDIF
return FALSE
ENDFUNC
///// PURPOSE:
///// Handle the jetski pair at the start of the mission
//PROC DO_BOATS()
// SWITCH subState
// CASE SS_INIT
// IF NOT boat_launched
// if IS_ENTITY_ALIVE(jetski1) AND IS_ENTITY_ALIVE(jetski_guy1)
// IF NOT IS_WAYPOINT_PLAYBACK_GOING_ON_FOR_VEHICLE(jetski1)
// TASK_VEHICLE_FOLLOW_WAYPOINT_RECORDING(jetski_guy1, jetski1, "Fan3_jetskiRoute", DRIVINGMODE_AVOIDCARS_RECKLESS)
// ENDIF
// ENDIF
// if IS_ENTITY_ALIVE(jetski2) AND IS_ENTITY_ALIVE(jetski_guy2)
// IF NOT IS_WAYPOINT_PLAYBACK_GOING_ON_FOR_VEHICLE(jetski2)
// TASK_VEHICLE_FOLLOW_WAYPOINT_RECORDING(jetski_guy2, jetski2, "Fan3_jetskiRoute2", DRIVINGMODE_AVOIDCARS_RECKLESS)
// ENDIF
// ENDIF
// boat_launched = TRUE
// jetski_conv_launched = FALSE
// maryann_jetski_conv_launched = FALSE
// ENDIF
// BREAK
// CASE SS_RUNNING
// if IS_ENTITY_ALIVE(jetski1) AND IS_ENTITY_ALIVE(jetski_guy1)
// IF NOT IS_WAYPOINT_PLAYBACK_GOING_ON_FOR_VEHICLE(jetski1)
// DEBUG_PRINTSTRING("Letting go of jetski_guy1")
// SET_PED_KEEP_TASK(jetski_guy1, true)
// TASK_VEHICLE_MISSION_COORS_TARGET(jetski_guy1, jetski1, <<-1366.24, 6852.42, 0.82>>, MISSION_FLEE, 200.0, DRIVINGMODE_PLOUGHTHROUGH, -1, -1)
// SET_ENTITY_LOAD_COLLISION_FLAG(jetski1, FALSE)
// SAFE_RELEASE_PED(jetski_guy1)
// SAFE_RELEASE_VEHICLE(jetski1)
// REMOVE_WAYPOINT_RECORDING("Fan3_jetskiRoute")
// ENDIF
// ENDIF
// if IS_ENTITY_ALIVE(jetski2) AND IS_ENTITY_ALIVE(jetski_guy2)
// // If this jetski guy gets close to Franklin, have him say a comment
// IF NOT jetski_conv_launched
// IF GET_DISTANCE_BETWEEN_ENTITIES(jetski2, PLAYER_PED_ID()) < 13
// ADD_PED_FOR_DIALOGUE(conv_frank, 6, jetski_guy2, "Fan3_Jetski")
// IF CREATE_CONVERSATION(conv_frank, "FAN3AUD", "FAN3_JETSKI", CONV_PRIORITY_HIGH)
// jetski_conv_launched = TRUE
// TASK_DRIVE_BY(jetski_guy2, PLAYER_PED_ID(), NULL, <<0,0,0>>, 25, 100, TRUE, FIRING_PATTERN_FULL_AUTO)
// ENDIF
// ENDIF
// ENDIF
// IF NOT IS_WAYPOINT_PLAYBACK_GOING_ON_FOR_VEHICLE(jetski2)
// DEBUG_PRINTSTRING("Letting go of jetski_guy2")
// SET_PED_KEEP_TASK(jetski_guy2, true)
// TASK_VEHICLE_MISSION_COORS_TARGET(jetski_guy2, jetski2, <<-1366.24, 6852.42, 0.82>>, MISSION_FLEE, 200.0, DRIVINGMODE_PLOUGHTHROUGH, -1, -1)
// SET_ENTITY_LOAD_COLLISION_FLAG(jetski2, FALSE)
// SAFE_RELEASE_PED(jetski_guy2)
// SAFE_RELEASE_VEHICLE(jetski2)
// REMOVE_WAYPOINT_RECORDING("Fan3_jetskiRoute2")
// ENDIF
// IF jetski_conv_launched
// IF maryann_jetski_conv_launched = FALSE
// IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
// IF CREATE_CONVERSATION(conversation, "FAN3AUD", "FAN3_YELL", CONV_PRIORITY_HIGH)
// maryann_jetski_conv_launched = TRUE
// ENDIF
// ENDIF
// ENDIF
// ENDIF
// ENDIF
// BREAK
// ENDSWITCH
//ENDPROC
/// PURPOSE:
/// Handle the small conversation about the water being cold as Franklin gets out
PROC DO_EXIT_SWIM_DIALOGUE()
// Only try playing this after the 4th checkpoint - when we're waaaaaaayy out in the water and there's no chance of this triggering by mistake
IF current_position > 4
IF NOT bDoneSwimDialogue
IF NOT IS_PED_SWIMMING(PLAYER_PED_ID())
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF CREATE_CONVERSATION(conversation, "FAN3AUD", "FAN3_COLD", CONV_PRIORITY_HIGH)
bDoneSwimDialogue = TRUE
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Handle the bad driver on the wrong side of the road during the bike section
PROC DO_BAD_DRIVER()
if missionStage = MS_BIKE
if IS_VEHICLE_OK(bad_driver_car)
AND IS_ENTITY_ALIVE(bad_driver_ped)
if IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<-402.280090,6407.980957,9.086394>>, <<-382.600891,6364.856934,16.762478>>, 5.000000)
if not bad_driver_launched
DEBUG_PRINTSTRING("Starting bad driver")
SET_ENTITY_LOAD_COLLISION_FLAG(bad_driver_car, TRUE)
ADD_PED_FOR_DIALOGUE(conv_frank, ENUM_TO_INT(CHAR_FRANKLIN), PLAYER_PED_ID(), "FRANKLIN")
TASK_VEHICLE_FOLLOW_WAYPOINT_RECORDING(bad_driver_ped, bad_driver_car, "Fan3_baddriver", DRIVINGMODE_AVOIDCARS)
bad_driver_launched = TRUE
ENDIf
ELIF bad_driver_launched
IF GET_DISTANCE_BETWEEN_ENTITIES(bad_driver_car, PLAYER_PED_ID()) < 15.0
START_VEHICLE_HORN(bad_driver_car, 4000)
ENDIF
IF GET_DISTANCE_BETWEEN_ENTITIES(bad_driver_car, PLAYER_PED_ID()) < 6.0
DEBUG_PRINTSTRING("Play conversation")
if NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
CREATE_CONVERSATION(conv_frank, "FAN3AUD", "FAN3_SHOUT", CONV_PRIORITY_MEDIUM)
ENDIF
ENDIF
IF NOT IS_WAYPOINT_PLAYBACK_GOING_ON_FOR_VEHICLE(bad_driver_car)
DEBUG_PRINTSTRING("bad_driver_car no longer needed")
SET_ENTITY_LOAD_COLLISION_FLAG(bad_driver_car, FALSE)
SET_ENTITY_SHOULD_FREEZE_WAITING_ON_COLLISION(bad_driver_car, TRUE)
SAFE_RELEASE_VEHICLE(bad_driver_car)
bad_driver_launched = FALSE
ENDIF
ENDIF
ENDIF
ENDIF
ENDPROC
PROC START_CONVERSATION()
IF NOT IS_MESSAGE_BEING_DISPLAYED() // Only do conversation if no god text is being displayed
OR GET_PROFILE_SETTING(PROFILE_DISPLAY_SUBTITLES) = 0
INT rand
// There's only two conversations we can use in the swimming section, so do this
IF missionStage = MS_SWIM
rand = GET_RANDOM_INT_IN_RANGE(0, MAX_SMACK_TALK-1)
ELSE
rand = GET_RANDOM_INT_IN_RANGE(0, MAX_SMACK_TALK)
ENDIF
INT mission_offset = GET_OFFSET_FROM_MISSION_STAGE(missionStage)
IF NOT (mission_offset = -1)
if won_last_stage = TRUE
mission_offset++
// 0 = currently swimming
// 1 = currently cycling, lost swimming
// 2 = currently cycling, won swimming
// 3 = currently running, lost cycling
// 4 = currently running, won cycling
ENDIF
IF (smack[mission_offset][rand].already_said = FALSE)
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
ADD_PED_FOR_DIALOGUE(conversation, ENUM_TO_INT(CHAR_FRANKLIN), PLAYER_PED_ID(), "FRANKLIN")
ENDIF
IF IS_ENTITY_ALIVE(opponent)
ADD_PED_FOR_DIALOGUE(conversation, 3, opponent, "MARYANN")
ENDIF
CREATE_CONVERSATION(conversation, "FAN3AUD", smack[mission_offset][rand].ConvRoot, CONV_PRIORITY_MEDIUM)
smack[mission_offset][rand].already_said = TRUE
bTrashTalkActive = TRUE
iTrashTalkTimer = GET_GAME_TIMER()
DEBUG_PRINTSTRING("*** CREATING TRASH TALK")
ENDIF
ENDIF
ELSE
DEBUG_PRINTSTRING("*** Trying to start trash talk, but god text is preventing it")
ENDIF
ENDPROC
/// PURPOSE:
/// Handle the trash talk conversations between Franklin and Mary Ann during the race, including pausing in-progress convos for distance
PROC PROCESS_CONVERSATION()
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF bTrashTalkActive
bTrashTalkActive = FALSE
ENDIF
IF (GET_GAME_TIMER() - iTrashTalkTimer) > 13000
IF GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), opponent) < 30
AND (opponentStage = missionStage) //Make sure we are both on the same stage, as it makes more sense.
IF missionStage = MS_SWIM
IF IS_ENTITY_ALIVE(opponent)
// If we're in the swimming bit, make sure both Mary Ann and Franklin are swimming before trying to do trash talk
// The dialogue's written as if they're both in the water, so if one of them isn't, it'd sound weeeiird
IF IS_PED_SWIMMING(opponent)
AND IS_PED_SWIMMING(PLAYER_PED_ID())
START_CONVERSATION()
ENDIF
ENDIF
ELSE
START_CONVERSATION()
ENDIF
ENDIF
ENDIF
ELSE
IF IS_ENTITY_ALIVE(opponent)
IF NOT bConvoPaused
IF GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), opponent) > 40
AND NOT bad_driver_launched
AND bTrashTalkActive
PAUSE_SCRIPTED_CONVERSATION(TRUE)
DEBUG_PRINTSTRING("*** PAUSING TRASH TALK")
bConvoPaused = TRUE
ENDIF
ELSE
IF GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), opponent) < 30
RESTART_SCRIPTED_CONVERSATION()
DEBUG_PRINTSTRING("*** RESTARTING TRASH TALK")
bConvoPaused = FALSE
ENDIF
ENDIF
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Check whether the given model is a bike
/// PARAMS:
/// model - The model we're checking
/// RETURNS:
/// TRUE if the model is a bike, false otherwise
FUNC BOOL IS_MODEL_VALID_BIKE(MODEL_NAMES model)
IF model = BMX OR model = scorcher OR model = scorcher OR model = CRUISER
return TRUE
ENDIF
return FALSE
ENDFUNC
/// PURPOSE:
/// Check for the player cheating during the mission by getting in a car or something
PROC CHECK_PLAYER_CHEATING()
IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
VEHICLE_INDEX player_vehicle = GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID())
IF (missionStage = MS_TO_BIKE) OR (missionStage = MS_BIKE) OR (missionStage = MS_OFF_BIKE)
//Check that we aren't on another bike.
IF IS_MODEL_VALID_BIKE(GET_ENTITY_MODEL(player_vehicle))
EXIT
ENDIF
ENDIF
// To match the proper triathlon minigame/activity, we just force the player out of the vehicle instead of doing the cheat detection stuff
// I'm adding a little bit of dialogue for colour though
IF missionStage <> MS_FAILED
IF NOT IS_MODEL_VALID_BIKE(GET_ENTITY_MODEL(player_vehicle))
IF IS_ENTITY_ALIVE(opponent) AND IS_ENTITY_ALIVE(PLAYER_PED_ID())
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
AND NOT IS_PED_GETTING_INTO_A_VEHICLE(PLAYER_PED_ID()) // Only start playing after Franklin has finished getting into the vehicle
IF GET_DISTANCE_BETWEEN_PEDS(PLAYER_PED_ID(), opponent) < 20
CREATE_CONVERSATION(conversation, "FAN3AUD", "FAN3_CHEAT2", CONV_PRIORITY_HIGH)
ELSE
CREATE_CONVERSATION(conversation, "FAN3AUD", "FAN3_CHEAT1", CONV_PRIORITY_HIGH)
ENDIF
ENDIF
ENDIF
ENDIF
TASK_LEAVE_ANY_VEHICLE(PLAYER_PED_ID())
DEBUG_PRINTSTRING("Telling player to leave any vehicle...")
ENDIF
// Going to keep the Pauls old code that fails the mission anyway though. Just in case.
// JUST IN CASE.
// IF cheated_on_vehicle = NOT_CHEATED
// IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
// KILL_ANY_CONVERSATION()
// ENDIF
// SETTIMERA(0)
// MODEL_NAMES vehicle_model
// vehicle_model = GET_ENTITY_MODEL(player_vehicle)
// IF IS_MODEL_VALID_BIKE(vehicle_model)
// PRINT_NOW("FATIC3_4", DEFAULT_GOD_TEXT_TIME, 1)
// ELSE
// PRINT_NOW("FATIC3_5", DEFAULT_GOD_TEXT_TIME, 1)
// ENDIF
// cheated_on_vehicle = IN_CHEATING_VEHICLE
// ELIF cheated_on_vehicle = IN_CHEATING_VEHICLE
// IF TIMERA() > 5000
// IF IS_PED_SITTING_IN_ANY_VEHICLE(PLAYER_PED_ID())
// //You didn't get off the vehicle.
// cheated_on_vehicle = CHEATED_TOO_MUCH
// IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
// KILL_ANY_CONVERSATION()
// ENDIF
// PRINT_NOW("FATIC3_9", DEFAULT_GOD_TEXT_TIME, 1)
// MISSION_FAILED()
// ENDIF
// ENDIF
// ELIF cheated_on_vehicle = CHEATED
// IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
// KILL_ANY_CONVERSATION()
// ENDIF
// //You got back on after getting off a vehicle. YOU WERE WARNED!!!!
// cheated_on_vehicle = CHEATED_TOO_MUCH
// PRINT_NOW("FATIC3_9", DEFAULT_GOD_TEXT_TIME, 1)
// MISSION_FAILED()
// ENDIF
//
// ELSE
// IF cheated_on_vehicle = IN_CHEATING_VEHICLE
// CLEAR_PRINTS()
// cheated_on_vehicle = CHEATED
// ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Check the both bikes are alive and fail the mission if either are destroyed when they're needed
PROC CHECK_BIKES_ALIVE()
IF NOT IS_ENTITY_ALIVE(bike_vehicle) OR NOT IS_ENTITY_ALIVE(opponent_bike_vehicle)
//PRINT_NOW("FATIC3_11", 7500, 0) //One of the bikes was wrecked.
IF opponentStage >= MS_BIKE
MISSION_FAILED(FAILED_YOURBIKE_DESTROYED)
ELSE
MISSION_FAILED(FAILED_BIKE_DESTROYED)
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Make sure the player is within the currently-defined TEST_POLY area
/// Reminder: the TEST_POLY area is cleared and redefined at the start of each race stage because the mission area is so goddamn huge
PROC CHECK_PLAYER_IN_MISSION_AREA()
IF NOT IS_POINT_IN_POLY_2D(innerBounds, GET_ENTITY_COORDS(PLAYER_PED_ID()))
if bAbandonmentWarning
IF (GET_GAME_TIMER() - iStopTime) > 10000
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
KILL_FACE_TO_FACE_CONVERSATION_DO_NOT_FINISH_LAST_LINE()
ENDIF
//PRINT_NOW("FATIC3_14", DEFAULT_GOD_TEXT_TIME, 1) // You wandered too far from the race
bAbandonmentWarning = false
MISSION_FAILED(FAILED_LEFT_AREA)
ENDIF
ELSE
PRINT_NOW("FATIC3_15", 5000, 1) //Return to the ~y~race.
iStopTime = GET_GAME_TIMER()
bAbandonmentWarning = TRUE
ENDIF
EXIT
ELSE
if bAbandonmentWarning
iStopTime = 0
CLEAR_THIS_PRINT("FATIC3_15")
bAbandonmentWarning = FALSE
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Skip to the mission intro cutscene
PROC SKIP_TO_INTRO()
REMOVE_BLIP_IF_EXISTS()
REMOVE_CHECKPOINT_IF_EXISTS()
missionStage = MS_INTRO
subState = SS_INIT
DEBUG_PRINTSTRING("Skipping to intro")
current_opponent_position = 0
current_position = 0
current_max_positions = MAX_SWIM_POSITIONS
current_opponent_max_positions = MAX_SWIM_POSITIONS
TRIGGER_MUSIC_EVENT("FANATIC2_STOP")
iCutsceneStage = 0
intro_requested = FALSE
intro_playing = FALSE
bCheatReload = FALSE // Just in case
bDoMAIntroBoost = FALSE
iMAIntroBoostTimer = -1
SET_ENTITY_COORDS(PLAYER_PED_ID(), << -909.0488, 6142.6167, 4.2883 >>)
ma_pSkip()
RC_END_Z_SKIP()
ENDPROC
/// PURPOSE:
/// Skip to the start of the swim section
proc SKIP_TO_SWIM()
IF IS_CUTSCENE_ACTIVE()
STOP_CUTSCENE()
ENDIF
start_time = GET_GAME_TIMER() // Reset the race timer
REMOVE_BLIP_IF_EXISTS()
REMOVE_CHECKPOINT_IF_EXISTS()
IF IS_ENTITY_ALIVE(opponent)
SET_ENTITY_COORDS(opponent, <<-903.2273, 6142.6387, 4.1911>>, TRUE, TRUE)
SET_ENTITY_HEADING(opponent, 264.8848)
ENDIF
IF NOT IS_REPLAY_BEING_SET_UP()
SET_ENTITY_COORDS(PLAYER_PED_ID(), vSwimSkip)
SET_ENTITY_HEADING(PLAYER_PED_ID(), fSwimSkip)
WAIT_FOR_WORLD_TO_LOAD(GET_ENTITY_COORDS(PLAYER_PED_ID()))
ENDIF
TRIGGER_MUSIC_EVENT("FANATIC3_RESTART1")
DEBUG_PRINTSTRING("Skipping to swim")
missionStage = MS_SWIM
subState = SS_INIT
current_opponent_position = 0
current_position = 0
current_max_positions = MAX_SWIM_POSITIONS
current_opponent_max_positions = MAX_SWIM_POSITIONS
bZSkipActive = FALSE
bCheatReload = FALSE // Just in case
race_won = FALSE
bLoadedBike = FALSE
bLoadedRun = FALSE
bDoMAIntroBoost = TRUE
iMAIntroBoostTimer = GET_GAME_TIMER()
m_pUnloadJog()
m_pUnloadBike()
m_pLoadSwim()
m_pResetBikes()
ma_pSkip()
IF IS_REPLAY_BEING_SET_UP()
END_REPLAY_SETUP()
SIMULATE_PLAYER_INPUT_GAIT(PLAYER_ID(), PEDMOVEBLENDRATIO_RUN, 4000)
WAIT(500)
ENDIF
RC_END_Z_SKIP()
ENDPROC
/// PURPOSE:
/// Skip to the start of the bike section
PROC SKIP_TO_BIKE()
IF NOT IS_REPLAY_BEING_SET_UP()
SET_ENTITY_COORDS(PLAYER_PED_ID(), vBikeSkip)
SET_ENTITY_HEADING(PLAYER_PED_ID(), fBikeSkip)
WAIT_FOR_WORLD_TO_LOAD(GET_ENTITY_COORDS(PLAYER_PED_ID()))
ENDIF
TRIGGER_MUSIC_EVENT("FANATIC3_RESTART2")
start_time = GET_GAME_TIMER() // Reset the race timer
fPriorSpeed = 0.0 // Reset Mary Ann's speed boost value
IF NOT IS_REPLAY_BEING_SET_UP()
FORCE_PED_MOTION_STATE(PLAYER_PED_ID(), MS_ON_FOOT_RUN, FALSE, FAUS_DEFAULT)
SIMULATE_PLAYER_INPUT_GAIT(PLAYER_ID(), 2.0, 1200)
ENDIF
REMOVE_BLIP_IF_EXISTS()
REMOVE_CHECKPOINT_IF_EXISTS()
blip = CREATE_VEHICLE_BLIP(bike_vehicle)
missionStage = MS_TO_BIKE
subState = SS_INIT
opponent_goto_bike = opponent_bike_vehicle
current_position = 0
current_max_positions = MAX_BIKE_POSITIONS
IF NOT IS_ENTITY_ALIVE(bike_vehicle) OR NOT IS_ENTITY_ALIVE(opponent_bike_vehicle)
SCRIPT_ASSERT("No bike.")
ENDIF
bCheatReload = FALSE // Just in case
bGivePushWarning = FALSE
bLoadedBike = FALSE
bLoadedRun = FALSE
race_won = FALSE
iPushTime = 0
iPushStage = 0
bDoMAIntroBoost = FALSE
iMAIntroBoostTimer = -1
SET_REPLAY_MID_MISSION_STAGE_WITH_NAME(CP_BIKE, "Bike section")
//g_replay.iReplayInt[F3_CHECKPOINT_TIME] = race_timer
m_pUnloadSwim()
m_pUnloadJog()
WHILE NOT m_pLoadBike()
WAIT(0)
bLoadedBike = TRUE
ENDWHILE
m_pResetBikes()
ma_pSkip()
IF IS_REPLAY_BEING_SET_UP()
END_REPLAY_SETUP()
SIMULATE_PLAYER_INPUT_GAIT(PLAYER_ID(), 2.0, 1200)
FORCE_PED_MOTION_STATE(PLAYER_PED_ID(), MS_ON_FOOT_RUN, FALSE, FAUS_DEFAULT)
wait(1000)
ENDIF
RC_END_Z_SKIP()
CLEAR_PRINTS()
PRINT_NOW("FATIC3_2", DEFAULT_GOD_TEXT_TIME, 1) //Get on a ~b~bike.
//SET_STUNT_JUMPS_CAN_TRIGGER(FALSE)
ENDPROC
/// PURPOSE:
/// Skip to the start of the running section
PROC SKIP_TO_RUN()
REMOVE_BLIP_IF_EXISTS()
REMOVE_CHECKPOINT_IF_EXISTS()
IF NOT IS_REPLAY_BEING_SET_UP()
SET_ENTITY_COORDS(PLAYER_PED_ID(), vJogSkip)
SET_ENTITY_HEADING(PLAYER_PED_ID(), fJogSkip)
WAIT_FOR_WORLD_TO_LOAD(GET_ENTITY_COORDS(PLAYER_PED_ID()))
ENDIF
IF IS_ENTITY_ALIVE(opponent)
CLEAR_PED_TASKS_IMMEDIATELY(opponent)
DEBUG_PRINTSTRING("*** Clearing Mary Ann tasks (Run skip)")
ENDIF
TRIGGER_MUSIC_EVENT("FANATIC3_RESTART3")
start_time = GET_GAME_TIMER() // Reset the race timer
IF NOT IS_REPLAY_BEING_SET_UP()
FORCE_PED_MOTION_STATE(PLAYER_PED_ID(), MS_ON_FOOT_RUN, FALSE, FAUS_DEFAULT)
SIMULATE_PLAYER_INPUT_GAIT(PLAYER_ID(), 2.0, 2000)
ENDIF
missionStage = MS_OFF_BIKE
subState = SS_INIT
bCheatReload = FALSE // Just in case
race_won = FALSE
current_position = 0
current_max_positions = MAX_RUN_POSITIONS
m_pResetBikes() // Reset the bikes so I can safely reference them now...
// The bikes up behind the starting position so they're present if we retry from this point
IF IS_VEHICLE_OK(bike_vehicle)
SET_ENTITY_COORDS(bike_vehicle, <<49.016113,6771.453125,20.055803>>)
SET_ENTITY_HEADING(bike_vehicle, -62.490368)
ENDIF
IF IS_VEHICLE_OK(opponent_bike_vehicle)
SET_ENTITY_COORDS(opponent_bike_vehicle, <<52.37, 6767.48, 20.66>>)
SET_ENTITY_HEADING(opponent_bike_vehicle, 312.42)
ENDIF
SET_REPLAY_MID_MISSION_STAGE_WITH_NAME(CP_JOG, "Jog section", TRUE)
//g_replay.iReplayInt[F3_CHECKPOINT_TIME] = race_timer
bDoMAIntroBoost = FALSE
iMAIntroBoostTimer = -1
m_pUnloadBike()
m_pUnloadJog()
WHILE NOT m_pLoadJog()
OR NOT ma_pLoadJogRecs()
WAIT(0)
ENDWHILE
bSkipped = FALSE
ma_pSkip()
IF IS_REPLAY_BEING_SET_UP()
END_REPLAY_SETUP()
FORCE_PED_MOTION_STATE(PLAYER_PED_ID(), MS_ON_FOOT_RUN, FALSE, FAUS_DEFAULT)
SIMULATE_PLAYER_INPUT_GAIT(PLAYER_ID(), 2.0, 2000)
WAIT(1000)
ENDIF
RC_END_Z_SKIP()
ENDPROC
/// PURPOSE:
/// Skip to the outro sequence
PROC SKIP_TO_OUTRO()
REMOVE_BLIP_IF_EXISTS()
REMOVE_CHECKPOINT_IF_EXISTS()
CLEAR_PRINTS()
TRIGGER_MUSIC_EVENT("FANATIC2_STOP")
iOutroStage = 0
missionStage = MS_DONE
bCheatReload = FALSE // Just in case
WHILE NOT m_pLoadJog()
WAIT(0)
ENDWHILE
intro_playing = FALSE
bSkipped = FALSE
ma_pSkip()
IF IS_REPLAY_BEING_SET_UP()
END_REPLAY_SETUP()
ENDIF
ENDPROC
/// PURPOSE:
/// Skip one stage forwards in the race
PROC SKIP_FORWARD()
IF ENUM_TO_INT(missionStage) < ENUM_TO_INT(MS_SWIM)
SKIP_TO_SWIM()
ELIF ENUM_TO_INT(missionStage) < ENUM_TO_INT(MS_TO_BIKE)
SKIP_TO_BIKE()
ELIF ENUM_TO_INT(missionStage) < ENUM_TO_INT(MS_OFF_BIKE)
SKIP_TO_RUN()
ELSE
DEBUG_PRINTSTRING("Skipping to outro")
SKIP_TO_OUTRO()
ENDIF
ENDPROC
/// PURPOSE:
/// Skip one stage back in the race
PROC SKIP_BACK()
IF ENUM_TO_INT(missionStage) = ENUM_TO_INT(MS_DONE)
RENDER_SCRIPT_CAMS(FALSE, FALSE, 0)
CLEAR_PED_TASKS(PLAYER_PED_ID())
TASK_CLEAR_LOOK_AT(PLAYER_PED_ID())
REMOVE_ANIM_DICT("rcmfanatic1out_of_breath")
SET_GAMEPLAY_CAM_RELATIVE_PITCH(0.0)
RC_END_CUTSCENE_MODE()
SAFE_FADE_SCREEN_IN_FROM_BLACK()
SKIP_TO_RUN()
DEBUG_PRINTSTRING("Skipping to run")
ELIF ENUM_TO_INT(missionStage) = ENUM_TO_INT(MS_RUN)
OR ENUM_TO_INT(missionStage) = ENUM_TO_INT(MS_OFF_BIKE)
SKIP_TO_BIKE()
ELIF ENUM_TO_INT(missionStage) = ENUM_TO_INT(MS_BIKE)
OR ENUM_TO_INT(missionStage) = ENUM_TO_INT(MS_TO_BIKE)
SKIP_TO_SWIM()
ELIF ENUM_TO_INT(missionStage) = ENUM_TO_INT(MS_SWIM)
SKIP_TO_INTRO()
ENDIF
ENDPROC
/// PURPOSE:
/// Jump to a specific, given stage in the mission
/// PARAMS:
/// iNewStage - The stage int we want to jump to
/// bRepeatPlaySkip - Are we skipping for a repeat play (we usually aren't)
PROC JUMP_TO_STAGE(int iNewStage, BOOL bRepeatPlaySkip = FALSE)
IF missionStage = MS_DONE
RENDER_SCRIPT_CAMS(FALSE, FALSE, 0)
CLEAR_PED_TASKS(PLAYER_PED_ID())
TASK_CLEAR_LOOK_AT(PLAYER_PED_ID())
REMOVE_ANIM_DICT("rcmfanatic1out_of_breath")
SET_GAMEPLAY_CAM_RELATIVE_PITCH(0.0)
RC_END_CUTSCENE_MODE()
SAFE_FADE_SCREEN_IN_FROM_BLACK()
ENDIF
RESET_PLAYER_STAMINA(PLAYER_ID())
// If we're immediately skipping to a stage for a replay, don't call the Z skip function again, otherwise the screen will flicker
IF bRepeatPlaySkip = FALSE
RC_START_Z_SKIP()
ENDIF
bSkipped = true
IF iNewStage = 0
IF IS_AUDIO_SCENE_ACTIVE("FANATIC_MIX_SCENE")
IF IS_ENTITY_ALIVE(opponent)
REMOVE_ENTITY_FROM_AUDIO_MIX_GROUP(opponent)
ENDIF
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(opponent)
ADD_ENTITY_TO_AUDIO_MIX_GROUP(opponent,"FANATIC_MIX_MARY_ANNE")
ENDIF
ENDIF
ENDIF
IF iNewStage = 0
SKIP_TO_INTRO()
ELIF iNewStage = 1
WAIT_FOR_CUTSCENE_TO_STOP()
SKIP_TO_SWIM()
ELIF iNewStage = 2
WAIT_FOR_CUTSCENE_TO_STOP()
SKIP_TO_BIKE()
ELIF iNewStage = 3
WAIT_FOR_CUTSCENE_TO_STOP()
SKIP_TO_RUN()
ELIF iNewStage = 4
WAIT_FOR_CUTSCENE_TO_STOP()
SKIP_TO_OUTRO()
ENDIF
//WAIT(500)
ENDPROC
PROC m_pLeadIn()
// Disable controls and exit current vehicle
RC_PLAYER_TRIGGER_SCENE_LOCK_IN()
INT iReplayStage
SWITCH subState
CASE SS_INIT
DEBUG_PRINTSTRING("Doing leadin init")
IF Is_Replay_In_Progress()
AND NOT bSkipped
DEBUG_PRINTSTRING("Replay in progress - skipping leadin & cutscene and jumping to checkpointed stage...")
m_pInitialiseRace()
IF IS_ENTITY_ALIVE(opponent)
FREEZE_ENTITY_POSITION(opponent, FALSE)
ENDIF
iReplayStage = Get_Replay_Mid_Mission_Stage()
DEBUG_PRINTSTRINGINT("ReplayStage: ", iReplayStage)
IF g_bShitskipAccepted = TRUE
iReplayStage++ // player is skipping this stage
DEBUG_PRINTSTRINGINT("ReplayStage after shitskip: ", iReplayStage)
ENDIF
SWITCH iReplayStage
CASE CP_SWIM
IF Is_Replay_In_Progress()
START_REPLAY_SETUP(vSwimSkip, fSwimSkip)
ENDIF
JUMP_TO_STAGE(1, TRUE)
BREAK
CASE CP_BIKE
IF Is_Replay_In_Progress()
START_REPLAY_SETUP(vBikeSkip, fBikeSkip)
ENDIF
JUMP_TO_STAGE(2, TRUE)
BREAK
CASE CP_JOG
IF Is_Replay_In_Progress()
START_REPLAY_SETUP(vJogSkip, fJogSkip)
ENDIF
JUMP_TO_STAGE(3, TRUE)
BREAK
CASE CP_OUTRO
IF Is_Replay_In_Progress()
START_REPLAY_SETUP(vOutroSkip, fOutroSkip)
ENDIF
JUMP_TO_STAGE(4, TRUE)
BREAK
DEFAULT
SCRIPT_ASSERT("Replay in progress: Unknown checkpoint selected?")
BREAK
ENDSWITCH
ELIF IS_REPEAT_PLAY_ACTIVE()
DEBUG_PRINTSTRING("Skipping leadin because repeat play is active")
subState = SS_CLEANUP
ENDIF
REQUEST_ANIM_DICT("rcmfanatic3")
ADD_PED_FOR_DIALOGUE(conversation, ENUM_TO_INT(CHAR_FRANKLIN), PLAYER_PED_ID(), "FRANKLIN")
ADD_PED_FOR_DIALOGUE(conversation, 3, opponent, "MARYANN")
IF GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), opponent) <= 1.5
// 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")
subState = SS_CLEANUP
ENDIF
IF HAS_ANIM_DICT_LOADED("rcmfanatic3")
IF IS_ENTITY_ALIVE(opponent)
IF IS_ENTITY_PLAYING_ANIM(opponent, "rcmfanatic3", "ef_3_rcm_loop_maryann")
IF GET_ENTITY_ANIM_CURRENT_TIME(opponent, "rcmfanatic3", "ef_3_rcm_loop_maryann") <0.1
TASK_PLAY_ANIM(opponent, "rcmfanatic3", "ef_3_rcm_action_maryann", NORMAL_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_HOLD_LAST_FRAME)
FREEZE_ENTITY_POSITION(opponent, FALSE)
REMOVE_CUTSCENE()
REQUEST_CUTSCENE_WITH_PLAYBACK_LIST("EF_3_RCM_CONCAT", CS_SECTION_2) // Request the concatinated version of the cutscene for the leadin instead
intro_requested = TRUE // Don't try to request the cutscene anymore
IF NOT IS_GAMEPLAY_HINT_ACTIVE()
IF IS_ENTITY_ALIVE(opponent)
SET_GAMEPLAY_ENTITY_HINT(opponent, <<0,0,-0.5>>, TRUE, 30000)
IF GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), opponent) <= 7.0
DEBUG_PRINTSTRING("Using FOV 40 instead")
fHintFov = 40
ENDIF
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)
ENDIF
ELSE
STOP_GAMEPLAY_HINT_BEING_CANCELLED_THIS_UPDATE(TRUE)
ENDIF
SET_SCRIPTS_SAFE_FOR_CUTSCENE(TRUE,DEFAULT,FALSE)
DEBUG_PRINTSTRING("Done Mary Ann leadin anim")
subState = SS_RUNNING
ENDIF
ELSE
//Fix for B*2185316, was changing subState to SS_CLEANUP here when retrying mission then going into MS_SWIM and immediately cleaning up
IF missionStage = MS_LEADIN
DEBUG_PRINTSTRING("Mary Ann not in leadin loop, starting cutscene early")
subState = SS_CLEANUP
ELSE
DEBUG_PRINTSTRING("Mary Ann not in leadin loop, but not in leadin stage, not doing anything!")
ENDIF
ENDIF
ENDIF
ENDIF
BREAK
CASE SS_RUNNING
IF IS_PED_UNINJURED(opponent)
IF IS_ENTITY_PLAYING_ANIM(opponent, "rcmfanatic3", "ef_3_rcm_action_maryann")
IF NOT bLeadInConv
IF GET_ENTITY_ANIM_CURRENT_TIME(opponent, "rcmfanatic3", "ef_3_rcm_action_maryann") > 0.17
IF CREATE_CONVERSATION(conversation, "FAN3AUD", "FAN3_LDI", CONV_PRIORITY_HIGH)
bLeadInConv = TRUE
ENDIF
ENDIF
ENDIF
IF NOT IS_GAMEPLAY_HINT_ACTIVE()
IF IS_ENTITY_ALIVE(opponent)
SET_GAMEPLAY_ENTITY_HINT(opponent, <<0,0,-0.5>>, TRUE, 30000)
IF GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), opponent) <= 7.0
DEBUG_PRINTSTRING("Using FOV 40 instead")
fHintFov = 40
ENDIF
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)
ENDIF
ELSE
STOP_GAMEPLAY_HINT_BEING_CANCELLED_THIS_UPDATE(TRUE)
ENDIF
IF GET_ENTITY_ANIM_CURRENT_TIME(opponent, "rcmfanatic3", "ef_3_rcm_action_maryann") > 0.90
FREEZE_ENTITY_POSITION(opponent, FALSE)
DEBUG_PRINTSTRING("Mary Ann leadin anim over")
subState = SS_CLEANUP
ENDIF
IF GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), opponent) <= 2.5
// Kill the leadin convo early if it's started
TASK_TURN_PED_TO_FACE_ENTITY(PLAYER_PED_ID(), opponent)
SET_PLAYER_CONTROL(PLAYER_ID(), FALSE)
DEBUG_PRINTSTRING("Player too close to Mary Ann, starting cutscene early")
ENDIF
ELSE
DEBUG_PRINTSTRING("Mary Ann not playing leadin anim anymore - skip to cutscene for safety")
subState = SS_CLEANUP
ENDIF
ENDIF
BREAK
CASE SS_CLEANUP
DEBUG_PRINTSTRING("Doing leadin cleanup")
subState = SS_INIT
missionStage = MS_INTRO
BREAK
ENDSWITCH
ENDPROC
FUNC BOOL DO_FRANKLIN_EXIT()
IF CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY("Franklin")
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
FORCE_PED_MOTION_STATE(PLAYER_PED_ID(), MS_ON_FOOT_RUN, FALSE, FAUS_CUTSCENE_EXIT)
SIMULATE_PLAYER_INPUT_GAIT(PLAYER_ID(), PEDMOVEBLENDRATIO_RUN, 5000)
DEBUG_PRINTSTRING("*** Forcing player's move state")
RETURN TRUE
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
PROC DO_MARY_ANN_EXIT()
IF CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY("Mary_Ann", IG_MARYANN)
IF IS_ENTITY_ALIVE(opponent)
//FORCE_PED_AI_AND_ANIMATION_UPDATE(opponent)
SET_PED_MIN_MOVE_BLEND_RATIO(opponent, 3.0)
FORCE_PED_MOTION_STATE(opponent, MS_ON_FOOT_SPRINT, FALSE, FAUS_CUTSCENE_EXIT)
TASK_GO_STRAIGHT_TO_COORD(opponent, (SWIM_POSITIONS[0]), PEDMOVE_RUN, DEFAULT_TIME_BEFORE_WARP)
iMAIntroBoostTimer = GET_GAME_TIMER()
bDoMAIntroBoost = TRUE
DEBUG_PRINTSTRING("*** Forcing opponent's move state")
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Main mission process for the initial cutscene stage
PROC INIT_MISSION()
bike_model = scorcher
IF Is_Replay_In_Progress()
AND NOT bSkipped
DEBUG_PRINTSTRING("Replay in progress - skipping cutscene and jumping to checkpointed stage...")
m_pInitialiseRace()
INT iReplayStage = Get_Replay_Mid_Mission_Stage()
DEBUG_PRINTSTRINGINT("ReplayStage: ", iReplayStage)
IF g_bShitskipAccepted = TRUE
iReplayStage++ // player is skipping this stage
DEBUG_PRINTSTRINGINT("ReplayStage after shitskip: ", iReplayStage)
ENDIF
SWITCH iReplayStage
CASE CP_SWIM
JUMP_TO_STAGE(1)
BREAK
CASE CP_BIKE
JUMP_TO_STAGE(2)
BREAK
CASE CP_JOG
JUMP_TO_STAGE(3)
BREAK
CASE CP_OUTRO
JUMP_TO_STAGE(4)
BREAK
DEFAULT
SCRIPT_ASSERT("Replay in progress: Unknown checkpoint selected?")
BREAK
ENDSWITCH
ELSE
if intro_playing = FALSE
IF intro_requested = FALSE
RC_REQUEST_CUTSCENE("ef_3_rcm_concat")
DEBUG_PRINTSTRING("Requesting cutscene...")
intro_requested = TRUE
ELSE
DEBUG_PRINTSTRING("Waiting for cutscene...")
ENDIF
IF CAN_REQUEST_ASSETS_FOR_CUTSCENE_ENTITY()
DEBUG_PRINTSTRING("Trying to set Mary Ann component variation")
IF IS_ENTITY_ALIVE(opponent)
SET_CUTSCENE_PED_COMPONENT_VARIATION_FROM_PED("Mary_Ann", opponent)
ENDIF
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
SET_CUTSCENE_PED_COMPONENT_VARIATION_FROM_PED("Franklin", PLAYER_PED_ID())
ENDIF
ENDIF
iCutsceneStage = 0
IF RC_IS_CUTSCENE_OK_TO_START()
m_pInitialiseRace()
IF IS_ENTITY_ALIVE(opponent)
REGISTER_ENTITY_FOR_CUTSCENE(opponent, "Mary_Ann", CU_ANIMATE_EXISTING_SCRIPT_ENTITY)
ENDIF
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
REGISTER_ENTITY_FOR_CUTSCENE(PLAYER_PED_ID(), "Franklin", CU_ANIMATE_EXISTING_SCRIPT_ENTITY)
ENDIF
// 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)
START_CUTSCENE()
WAIT(0)
RESOLVE_VEHICLES_INSIDE_ANGLED_AREA_WITH_SIZE_LIMIT(<<-921.506714,6138.839355,3.262831>>, <<-903.901855,6142.160156,9.201322>>, 14.5,
<< -913.52, 6151.76, 4.74 >>, 317.56, GET_DEFAULT_ALLOWABLE_VEHICLE_SIZE_VECTOR())
RESOLVE_VEHICLES_INSIDE_ANGLED_AREA_WITH_SIZE_LIMIT(<<-867.752686,6134.873535,-0.996085>>, <<-913.163574,6140.982910,7.133643>>, 13.5,
<< -913.52, 6151.76, 4.74 >>, 317.56, GET_DEFAULT_ALLOWABLE_VEHICLE_SIZE_VECTOR())
RC_START_CUTSCENE_MODE(<< -915.46, 6139.21, 4.52 >>, TRUE, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT)
DEBUG_PRINTSTRING("Starting cutscene...")
intro_playing = TRUE
//The cutscene is now running. We can load other assets.
ENDIF
ELSE
REQUEST_MODEL(bike_model)
REQUEST_WAYPOINT_RECORDING("Fan3_RollingStart")
REQUEST_ADDITIONAL_TEXT("FATIC3", MISSION_TEXT_SLOT)
IF iCutsceneStage = 0
SET_GAMEPLAY_CAM_RELATIVE_PITCH()
SET_GAMEPLAY_CAM_RELATIVE_HEADING()
IF WAS_CUTSCENE_SKIPPED()
DEBUG_PRINTSTRING("*** Cam exit state pitch/heading")
SET_GAMEPLAY_CAM_RELATIVE_PITCH()
SET_GAMEPLAY_CAM_RELATIVE_HEADING()
bIntroSkipped = TRUE
iCutsceneStage = 1
ENDIF
IF DO_FRANKLIN_EXIT()
iCutsceneStage = 1
ENDIF
DO_MARY_ANN_EXIT()
ma_pDoIntroBoost()
ELIF iCutsceneStage = 1
// In case if being missed
DO_MARY_ANN_EXIT()
ma_pDoIntroBoost()
// In case of skip?
DO_FRANKLIN_EXIT()
IF NOT IS_CUTSCENE_ACTIVE()
REPLAY_STOP_EVENT()
IF bIntroSkipped = TRUE
IF IS_ENTITY_ALIVE(opponent)
SET_ENTITY_COORDS(opponent, <<-903.2273, 6142.6387, 4.1911>>, TRUE, TRUE)
SET_ENTITY_HEADING(opponent, 264.8848)
ENDIF
IF NOT bZSkipActive
DEBUG_PRINTSTRING("*** Cutscene skip detected")
RC_START_Z_SKIP()
ma_pSwitchState(MS_SWIM)
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
SET_GAMEPLAY_CAM_RELATIVE_PITCH(0.0)
SET_GAMEPLAY_CAM_RELATIVE_HEADING(0.0)
ENDIF
bZSkipActive = TRUE
ENDIF
ENDIF
SET_REPLAY_MID_MISSION_STAGE_WITH_NAME(CP_SWIM, "Swim section") // Set the checkpoint
start_time = GET_GAME_TIMER() // Start the race timer
IF NOT IS_AUDIO_SCENE_ACTIVE("FANATIC_MIX_SCENE")
START_AUDIO_SCENE("FANATIC_MIX_SCENE")
IF IS_ENTITY_ALIVE(opponent)
ADD_ENTITY_TO_AUDIO_MIX_GROUP(opponent,"FANATIC_MIX_MARY_ANNE")
ENDIF
ENDIF
m_pLoadSwim()
ENDIF
ENDIF
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Main mission process for the swim section
PROC m_pSwim()
ma_pUpdate() // Update Mary Ann every frame
m_pDoRaceLogic()
PROCESS_CONVERSATION()
SWITCH subState
CASE SS_INIT
DEBUG_PRINTSTRING("DOING SWIM SETUP")
RC_SET_ENTITY_PROOFS_FOR_CUTSCENE(sRCLauncherDataLocal, FALSE)
CHECK_PLAYER_CHEATING()
CHECK_BIKES_ALIVE()
CHECK_PLAYER_IN_MISSION_AREA()
//DO_BOATS()
DO_EXIT_SWIM_DIALOGUE()
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
ADD_PED_FOR_DIALOGUE(conversation, ENUM_TO_INT(CHAR_FRANKLIN), PLAYER_PED_ID(), "FRANKLIN")
ENDIF
IF IS_ENTITY_ALIVE(opponent)
ADD_PED_FOR_DIALOGUE(conversation, 3, opponent, "MARYANN")
ENDIF
bSkipped = FALSE
SIMULATE_PLAYER_INPUT_GAIT(PLAYER_ID(), PEDMOVEBLENDRATIO_RUN, 4000)
ma_pDoIntroBoost()
RC_END_Z_SKIP(FALSE)
CREATE_CONVERSATION(conversation, "FAN3AUD", "FAN3_OPENER", CONV_PRIORITY_HIGH, DO_NOT_DISPLAY_SUBTITLES)
PRINT_NOW("FATIC3_1", DEFAULT_GOD_TEXT_TIME, 1) //Swim across the ~y~bay.
DEBUG_PRINTSTRING("DOING SWIM RUNNING")
REPLAY_RECORD_BACK_FOR_TIME(0.0, 15.0, REPLAY_IMPORTANCE_LOW)
subState = SS_RUNNING
BREAK
CASE SS_RUNNING
// 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
CHECK_PLAYER_CHEATING()
CHECK_BIKES_ALIVE()
CHECK_PLAYER_IN_MISSION_AREA()
//DO_BOATS()
DO_EXIT_SWIM_DIALOGUE()
ma_pDoIntroBoost()
IF PrevCheckpoint != NULL
//DEBUG_PRINTSTRING("Fade previous CP")
iPrevAlpha -= 25
INT PreviR, PreviG, PreviB, iA
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 (DO_CHECKPOINT_UPDATES(SWIM_POSITIONS))
subState = SS_CLEANUP
ENDIF
BREAK
CASE SS_CLEANUP
DEBUG_PRINTSTRING("DOING SWIM CLEANUP")
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF NOT IS_THIS_CONVERSATION_ROOT_PLAYING("FAN3_SWIMWIN")
OR NOT IS_THIS_CONVERSATION_ROOT_PLAYING("FAN3_SWIMLOS")
KILL_ANY_CONVERSATION()
// We want to kill any conversation that displays subtitles at this point, to ensure we always show the god text
// The two exceptions above are conversations that may be playing at this point that don't have subtitles, so we can ignore them
ENDIF
ENDIF
blip = CREATE_VEHICLE_BLIP(bike_vehicle)
current_position = 0
current_max_positions = MAX_BIKE_POSITIONS
IF DOES_ENTITY_EXIST(opponent_goto_bike)
PRINT_NOW("FATIC3_12", DEFAULT_GOD_TEXT_TIME, 1) //Get on the ~b~bike.
ELSE
PRINT_NOW("FATIC3_2", DEFAULT_GOD_TEXT_TIME, 1) //Get on a ~b~bike.
additional_blip = CREATE_VEHICLE_BLIP(opponent_bike_vehicle)
ENDIF
IF missionStage < opponentStage
DEBUG_PRINTSTRING("Player lost swimming")
won_last_stage = FALSE
ELSE
DEBUG_PRINTSTRING("Player won swimming")
won_last_stage = TRUE
ENDIF
SET_REPLAY_MID_MISSION_STAGE_WITH_NAME(CP_BIKE, "Bike section")
g_replay.iReplayInt[F3_CHECKPOINT_TIME] = race_timer
bLoadedBike = FALSE
subState = SS_INIT
missionStage = MS_TO_BIKE
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE:
/// Check for the player's bike being 'dead' or in the water
PROC CHECK_BIKE_IN_WATER()
IF DOES_ENTITY_EXIST(players_bike)
IF IS_ENTITY_DEAD(players_bike)
//IF IS_ENTITY_IN_WATER(players_bike)
//PRINT_NOW("FATIC3_11", DEFAULT_GOD_TEXT_TIME, 1)
IF opponentStage >= MS_BIKE
MISSION_FAILED(FAILED_YOURBIKE_DESTROYED)
ELSE
MISSION_FAILED(FAILED_BIKE_DESTROYED)
ENDIF
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Main mission process for the "get on a bike" section
PROC m_pToBike()
// Do all of these every frame
ma_pUpdate()
m_pDoRaceLogic()
PROCESS_CONVERSATION()
CHECK_PLAYER_CHEATING()
CHECK_BIKE_IN_WATER()
CHECK_BIKES_ALIVE()
CHECK_PLAYER_IN_MISSION_AREA()
//DO_BOATS()
DO_BAD_DRIVER()
IF PrevCheckpoint != NULL
//DEBUG_PRINTSTRING("Fade previous CP")
iPrevAlpha -= 25
INT PreviR, PreviG, PreviB, iA
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 subState
CASE SS_INIT
DEBUG_PRINTSTRING("DOING TO BIKE SETUP")
subState = SS_RUNNING
bMAJumpFailed = FALSE
bad_driver_launched = FALSE
bSkipped = FALSE
DEBUG_PRINTSTRING("DOING TO BIKE RUNNING")
BREAK
CASE SS_RUNNING
IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
players_bike = GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID())
IF (bike_vehicle = GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()))
OR (opponent_bike_vehicle = GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()))
SAFE_REMOVE_BLIP(blip)
SAFE_REMOVE_BLIP(additional_blip)
REPLAY_RECORD_BACK_FOR_TIME(5.0, 15.0, REPLAY_IMPORTANCE_LOW)
subState = SS_CLEANUP
ENDIF
ENDIF
BREAK
CASE SS_CLEANUP
DEBUG_PRINTSTRING("DOING TO BIKE CLEANUP")
if not bLoadedBike
m_pUnloadSwim()
IF m_pLoadBike()
DEBUG_PRINTSTRING("Loaded bike resources")
bLoadedBike = TRUE
ENDIF
ELSE
IF players_bike = NULL
players_bike = GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID())
ENDIF
CLEAR_THIS_PRINT("FATIC3_12")
if not bCheatReload
// Load bike stuff normally
CREATE_FIRST_BLIP(BIKE_POSITIONS)
ELSE
// The player has got off and then back on the bike, so blip up the last known checkpoint
blip = CREATE_COORD_BLIP(BIKE_POSITIONS[current_position], BLIPPRIORITY_MED, FALSE)
SET_BLIP_COLOUR(blip, BLIP_COLOUR_YELLOW)
IF (current_position = (current_max_positions-1)) // If it's the final blip, give it a flag sprite
SET_BLIP_SPRITE(blip, RADAR_TRACE_RACEFLAG)
ENDIF
IF (current_position = (current_max_positions-2))
nextblip = CREATE_COORD_BLIP(BIKE_POSITIONS[current_position+1], BLIPPRIORITY_MED, FALSE)
SET_BLIP_SCALE(nextblip, 1.2)
SET_BLIP_SPRITE(nextblip, RADAR_TRACE_RACEFLAG)
SHOW_HEIGHT_ON_BLIP(nextblip, FALSE)
ELIF (current_position < (current_max_positions-1))
nextblip = CREATE_COORD_BLIP(BIKE_POSITIONS[current_position+1], BLIPPRIORITY_MED, FALSE)
SET_BLIP_SCALE(nextblip, 0.7)
SHOW_HEIGHT_ON_BLIP(nextblip, FALSE)
ENDIF
bCheatReload = FALSE
SPAWN_CHECKPOINT(BIKE_POSITIONS) // Respawn the current bike checkpoint
ENDIF
IF bike_around_trail_said = FALSE
PRINT_NOW("FATIC3_3", DEFAULT_GOD_TEXT_TIME, 1) //Cycle around the ~y~trail.
bike_around_trail_said = TRUE
ENDIF
iTrashTalkTimer = GET_GAME_TIMER()
missionStage = MS_BIKE
subState = SS_INIT
ENDIF
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE:
/// Do a speed boost for the player as they approach the broken bridge jump, in case they're sliiiiightly going to miss it
/// This will increment the player's speed by 0.25 every frame when they go for the jump, if their current speed is between 15.0 and 18.5
PROC DO_JUMP_BOOST()
// Theoretical maximum: 21.74
IF IS_ENTITY_IN_ANGLED_AREA( PLAYER_PED_ID(), <<-158.218292,6583.302246,10.344661>>, <<-176.636276,6564.860840,17.576939>>, 6.000000)
IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
VEHICLE_INDEX player_vehicle = GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID())
IF IS_VEHICLE_OK(player_vehicle)
if GET_ENTITY_SPEED(player_vehicle) < 21.5
AND GET_ENTITY_SPEED(player_vehicle) > 15.0
FLOAT newSpeed = GET_ENTITY_SPEED(player_vehicle) + 0.25
DEBUG_PRINTSTRINGF("Speed now", newSpeed)
SET_VEHICLE_FORWARD_SPEED(player_vehicle, newSpeed)
ENDIF
ENDIF
ENDIF
ENDIF
ENDPROC
PROC CHECK_JUMP_REPLAY()
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
AND IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
IF IS_ENTITY_ALIVE(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()))
IF NOT bReplayTrackOn
IF IS_ENTITY_IN_ANGLED_AREA(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()), <<-162.930511,6574.679199,11.035428>>, <<-166.721405,6578.558594,15.140646>>, 3.50)
REPLAY_START_EVENT()
bReplayTrackOn = TRUE
DEBUG_PRINTSTRING("*** Started tracking jump replay")
ENDIF
ELSE
// If you hit the other side of the bridge, or the ground, or you somehow escape this huge 70m-wide box, stop tracking for replay
IF IS_ENTITY_IN_ANGLED_AREA(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()), <<-152.121078,6592.195313,8.325163>>, <<-149.194519,6588.718262,13.289552>>, 5.250000)
OR IS_ENTITY_IN_ANGLED_AREA(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()), <<-183.968750,6611.616211,-1.050815>>, <<-146.163025,6575.146973,7.485405>>, 46.500)
OR NOT IS_ENTITY_IN_ANGLED_AREA(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()), <<-182.590408,6607.473633,0.027168>>, <<-143.880035,6571.711914,37.029289>>, 70.75)
REPLAY_STOP_EVENT()
bReplayTrackOn = FALSE
DEBUG_PRINTSTRING("*** Stopped tracking jump replay")
ENDIF
ENDIF
ENDIF
ELSE
IF bReplayTrackOn
DEBUG_PRINTSTRING("*** Stopped tracking jump replay (player not in vehicle)")
bReplayTrackOn = FALSE
REPLAY_STOP_EVENT()
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Handle the dog owner who appears near the end of the race
PROC DO_OWNER_SCENE()
SWITCH iOwnerStage
CASE 0 // Spawn ped when at the right checkpoint
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
IF IS_ENTITY_IN_RANGE_COORDS(PLAYER_PED_ID(), <<52.11, 6965.68, 9.73>>, 5.0)
dog_owner = CREATE_PED(PEDTYPE_MISSION, A_F_Y_Runner_01, <<56.3978, 7015.1646, 8.8828>>, 101.1728)
SET_MODEL_AS_NO_LONGER_NEEDED(A_F_Y_Runner_01)
DEBUG_PRINTSTRING("*** Dog owner created")
iOwnerStage++
ENDIF
ENDIF
BREAK
CASE 1 // Start playing waypoint recording
IF IS_ENTITY_ALIVE(dog_owner)
IF NOT IS_WAYPOINT_PLAYBACK_GOING_ON_FOR_PED(dog_owner)
TASK_FOLLOW_WAYPOINT_RECORDING(dog_owner, "fan3_ownerroute")
DEBUG_PRINTSTRING("*** Dog owner playing back recording")
iOwnerStage++
ENDIF
ENDIF
BREAK
CASE 2 // Play dog conversation when close enough to Franklin
IF IS_ENTITY_ALIVE(dog_owner)
IF IS_WAYPOINT_PLAYBACK_GOING_ON_FOR_PED(dog_owner)
if GET_DISTANCE_BETWEEN_PEDS(PLAYER_PED_ID(), dog_owner) < 16
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
ADD_PED_FOR_DIALOGUE(conv_frank, 5, dog_owner, "FAN3DOGOWNER")
ADD_PED_FOR_DIALOGUE(conv_frank, ENUM_TO_INT(CHAR_FRANKLIN), PLAYER_PED_ID(), "FRANKLIN")
IF CREATE_CONVERSATION(conv_frank, "FAN3AUD", "FAN3_DOG", CONV_PRIORITY_MEDIUM)
TASK_LOOK_AT_ENTITY(dog_owner, PLAYER_PED_ID(), 6000)
TASK_LOOK_AT_ENTITY(PLAYER_PED_ID(), dog_owner, 6000)
iOwnerStage++
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
BREAK
CASE 3 // Carry on until the waypoint recording has finished
IF IS_ENTITY_ALIVE(dog_owner)
IF NOT IS_WAYPOINT_PLAYBACK_GOING_ON_FOR_PED(dog_owner)
iOwnerStage++
ENDIF
ENDIF
BREAK
CASE 4 // Remove from world
IF IS_ENTITY_ALIVE(dog_owner)
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED() // In case "FAN3_DSCARE" is queued when we get here
SET_PED_KEEP_TASK(dog_owner, TRUE)
SET_PED_AS_NO_LONGER_NEEDED(dog_owner)
ENDIF
ENDIF
BREAK
ENDSWITCH
// Aggro check
IF IS_ENTITY_ALIVE(dog_owner)
IF HAS_PLAYER_THREATENED_PED(dog_owner)
OR IS_PED_IN_COMBAT(dog_owner)
CLEAR_PED_TASKS(dog_owner)
TASK_SMART_FLEE_PED(dog_owner, PLAYER_PED_ID(), 100, -1)
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
// Only kill the convo and play the scared dialogue if the current convo is the owner asking Franklin about the dog
// Otherwise it doesn't make much sense, and trash talk should take priority anyway
TEXT_LABEL_23 RootCheck
RootCheck = GET_CURRENTLY_PLAYING_STANDARD_CONVERSATION_ROOT()
IF ARE_STRINGS_EQUAL(RootCheck,"FAN3_DOG")
KILL_FACE_TO_FACE_CONVERSATION_DO_NOT_FINISH_LAST_LINE()
ADD_PED_FOR_DIALOGUE(conv_frank, 5, dog_owner, "FAN3DOGOWNER")
ADD_PED_FOR_DIALOGUE(conv_frank, ENUM_TO_INT(CHAR_FRANKLIN), PLAYER_PED_ID(), "FRANKLIN")
ADD_NON_CRITICAL_STANDARD_CONVERSATION_TO_BUFFER(conv_frank, "FAN3AUD", "FAN3_DSCARE", CONV_PRIORITY_MEDIUM)
ENDIF
ELSE
ADD_PED_FOR_DIALOGUE(conv_frank, 5, dog_owner, "FAN3DOGOWNER")
ADD_PED_FOR_DIALOGUE(conv_frank, ENUM_TO_INT(CHAR_FRANKLIN), PLAYER_PED_ID(), "FRANKLIN")
CREATE_CONVERSATION(conv_frank, "FAN3AUD", "FAN3_DSCARE", CONV_PRIORITY_MEDIUM)
ENDIF
iOwnerStage = 4
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Handle setting the dog off running during the jog section
PROC DO_DOG_SCENE()
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
IF IS_ENTITY_IN_RANGE_COORDS(PLAYER_PED_ID(), RUN_POSITIONS[1], 5.0)
IF IS_ENTITY_ALIVE(running_dog)
IF NOT IS_WAYPOINT_PLAYBACK_GOING_ON_FOR_PED(running_dog)
TASK_FOLLOW_WAYPOINT_RECORDING(running_dog, "fan3_dogroute")
ENDIF
ENDIF
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Handle checking the chinups guy during the jog section for player aggro
PROC CHECK_CHINUPS_GUY()
IF IS_ENTITY_ALIVE(chinups_guy)
SWITCH iChinupStage
CASE 0
IF HAS_PLAYER_THREATENED_PED(chinups_guy)
CLEAR_PED_TASKS(chinups_guy)
TASK_SMART_FLEE_PED(chinups_guy, PLAYER_PED_ID(), 100, -1)
iChinupStage++
ENDIF
BREAK
DEFAULT
BREAK
ENDSWITCH
ENDIF
ENDPROC
/// PURPOSE:
/// Handle checking the chinups guy during the jog section for player aggro
PROC CHECK_STRETCHING_WOMAN()
IF IS_ENTITY_ALIVE(stretching_woman)
SWITCH iStretchStage
CASE 0
IF HAS_PLAYER_THREATENED_PED(stretching_woman)
CLEAR_PED_TASKS(stretching_woman)
TASK_SMART_FLEE_PED(stretching_woman, PLAYER_PED_ID(), 100, -1)
iStretchStage++
ENDIF
BREAK
DEFAULT
BREAK
ENDSWITCH
ENDIF
ENDPROC
/// PURPOSE:
/// Handle checking the binoculars birdwatcher type guy during the jog section for player aggro
PROC CHECK_BINOCS_GUY()
IF IS_ENTITY_ALIVE(binoculars_guy)
SWITCH iBinocStage
CASE 0
// Standard behaviour - flee if threatened
IF HAS_PLAYER_THREATENED_PED(binoculars_guy)
CLEAR_PED_TASKS(binoculars_guy)
SET_PED_FLEE_ATTRIBUTES(binoculars_guy, FA_USE_VEHICLE, TRUE)
SET_PED_KEEP_TASK(binoculars_guy, true)
IF DOES_ENTITY_EXIST(binocs)
DETACH_ENTITY(binocs)
ENDIF
PLAY_PED_AMBIENT_SPEECH(binoculars_guy, "GENERIC_CURSE_MED", SPEECH_PARAMS_FORCE_FRONTEND)
IF IS_VEHICLE_OK(picniccar2)
OPEN_SEQUENCE_TASK(seq)
TASK_ENTER_VEHICLE(NULL, picniccar2, DEFAULT_TIME_BEFORE_WARP, VS_DRIVER, PEDMOVEBLENDRATIO_SPRINT, ECF_JACK_ANYONE)
TASK_VEHICLE_MISSION_PED_TARGET(NULL, picniccar2,PLAYER_PED_ID(), MISSION_FLEE, 30, DRIVINGMODE_AVOIDCARS_RECKLESS, 300, 10)
//TASK_SMART_FLEE_PED(NULL, PLAYER_PED_ID(), 100, -1)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(binoculars_guy, seq)
CLEAR_SEQUENCE_TASK(seq)
DEBUG_PRINTSTRING("iBinocStage = 1")
iBinocStage = 1
ELIF NOT IS_VEHICLE_OK(picniccar2)
OPEN_SEQUENCE_TASK(seq)
TASK_SMART_FLEE_PED(NULL, PLAYER_PED_ID(), 100, -1)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(binoculars_guy, seq)
CLEAR_SEQUENCE_TASK(seq)
DEBUG_PRINTSTRING("iBinocStage = 2")
iBinocStage = 2
ENDIF
ENDIF
IF IS_ENTITY_ALIVE(picniccar2)
IF IS_PED_IN_VEHICLE(PLAYER_PED_ID(), picniccar2)
IF DOES_ENTITY_EXIST(binocs)
DETACH_ENTITY(binocs)
ENDIF
OPEN_SEQUENCE_TASK(seq)
TASK_SMART_FLEE_PED(NULL, PLAYER_PED_ID(), 100, -1)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(binoculars_guy, seq)
CLEAR_SEQUENCE_TASK(seq)
DEBUG_PRINTSTRING("iBinocStage = 2")
iBinocStage = 2
ENDIF
ENDIF
BREAK
CASE 1
// Guy is fleeing in a vehicle - get out and flee on foot if player steals vehicle or wrecks it
IF IS_VEHICLE_OK(picniccar2)
IF IS_PED_IN_VEHICLE(PLAYER_PED_ID(), picniccar2)
CLEAR_PED_TASKS(binoculars_guy)
SET_PED_FLEE_ATTRIBUTES(binoculars_guy, FA_USE_VEHICLE, FALSE)
SET_PED_KEEP_TASK(binoculars_guy, true)
OPEN_SEQUENCE_TASK(seq)
IF IS_PED_IN_VEHICLE(binoculars_guy, picniccar2)
TASK_LEAVE_ANY_VEHICLE(null, 0, ECF_DONT_CLOSE_DOOR | ECF_DONT_WAIT_FOR_VEHICLE_TO_STOP)
ENDIF
TASK_SMART_FLEE_PED(NULL, PLAYER_PED_ID(), 100, -1)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(binoculars_guy, seq)
CLEAR_SEQUENCE_TASK(seq)
DEBUG_PRINTSTRING("iBinocStage = 2")
iBinocStage = 2
ENDIF
ELSE
// Car is not drivable anymore, so flee on foot
CLEAR_PED_TASKS(binoculars_guy)
SET_PED_FLEE_ATTRIBUTES(binoculars_guy, FA_USE_VEHICLE, FALSE)
SET_PED_KEEP_TASK(binoculars_guy, true)
OPEN_SEQUENCE_TASK(seq)
IF IS_PED_IN_VEHICLE(binoculars_guy, picniccar2)
TASK_LEAVE_ANY_VEHICLE(null, 0, ECF_DONT_CLOSE_DOOR | ECF_DONT_WAIT_FOR_VEHICLE_TO_STOP)
ENDIF
TASK_SMART_FLEE_PED(NULL, PLAYER_PED_ID(), 100, -1)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(binoculars_guy, seq)
CLEAR_SEQUENCE_TASK(seq)
DEBUG_PRINTSTRING("Car wrecked - iBinocStage = 2")
iBinocStage = 2
ENDIF
IF GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), binoculars_guy) > 300
DEBUG_PRINTSTRING("iBinocStage = 3")
iBinocStage = 3
ENDIF
BREAK
CASE 2
// Guy is fleeing on foot
IF IS_ENTITY_ALIVE(binoculars_guy)
IF GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), binoculars_guy) > 100
DEBUG_PRINTSTRING("iBinocStage = 3")
iBinocStage = 3
ENDIF
ENDIF
BREAK
CASE 3
// Remove ped and vehicle now they're far enough away
SAFE_RELEASE_PED(binoculars_guy)
SAFE_RELEASE_VEHICLE(picniccar2)
BREAK
ENDSWITCH
ELIF IS_ENTITY_DEAD(binoculars_guy)
IF DOES_ENTITY_EXIST(binocs)
IF IS_ENTITY_ATTACHED(binocs)
DETACH_ENTITY(binocs)
ENDIF
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Main mission function for the bike section of the race
PROC m_pBike()
ma_pUpdate()
m_pDoRaceLogic()
IF PrevCheckpoint != NULL
//DEBUG_PRINTSTRING("Fade previous CP")
iPrevAlpha -= 25
INT PreviR, PreviG, PreviB, iA
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 subState
CASE SS_INIT
DEBUG_PRINTSTRING("DOING BIKE SETUP")
subState = SS_RUNNING
DEBUG_PRINTSTRING("DOING BIKE RUNNING")
BREAK
CASE SS_RUNNING
PROCESS_CONVERSATION()
CHECK_PLAYER_CHEATING()
CHECK_BIKE_IN_WATER()
CHECK_BIKES_ALIVE()
CHECK_PLAYER_IN_MISSION_AREA()
//DO_BOATS()
DO_BAD_DRIVER()
//DO_JUMP_BOOST()
CHECK_JUMP_REPLAY()
IF NOT IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
SAFE_REMOVE_BLIP(blip)
SAFE_REMOVE_BLIP(nextblip)
blip = CREATE_VEHICLE_BLIP(players_bike)
DELETE_CHECKPOINT(checkpoint)
IF get_back_on_said = FALSE
PRINT_NOW("FATIC3_BACKON", DEFAULT_GOD_TEXT_TIME, 1) //Get back on the ~b~bike.
get_back_on_said = TRUE
ENDIF
bCheatReload = TRUE // Mark that we're reloading the bike bit due to cheating (or getting off the bike)
missionStage = MS_TO_BIKE
subState = SS_INIT
ELSE
IF IS_THIS_PRINT_BEING_DISPLAYED("FATIC3_BACKON")
DEBUG_PRINTSTRING("Clearing 'FATIC3_BACKON' print")
CLEAR_PRINTS()
ENDIF
IF (DO_CHECKPOINT_UPDATES(BIKE_POSITIONS))
DEBUG_PRINTSTRING("Player finished bike section, going into cleanup")
subState = SS_CLEANUP
ENDIF
ENDIF
BREAK
CASE SS_CLEANUP
DEBUG_PRINTSTRING("DOING BIKE CLEANUP")
current_position = 0
current_max_positions = MAX_RUN_POSITIONS
bCheatReload = FALSE // Make sure we reset this
IF missionStage < opponentStage
DEBUG_PRINTSTRING("Player lost cycling")
won_last_stage = FALSE
ELSE
DEBUG_PRINTSTRING("Player won cycling")
won_last_stage = TRUE
ENDIF
SET_REPLAY_MID_MISSION_STAGE_WITH_NAME(CP_JOG, "Jog section")
g_replay.iReplayInt[F3_CHECKPOINT_TIME] = race_timer
missionStage = MS_OFF_BIKE
subState = SS_INIT
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE:
/// Main mission function for the "get off the bike" section
PROC m_pOffBike()
m_pDoRaceLogic()
ma_pUpdate()
PROCESS_CONVERSATION()
CHECK_PLAYER_CHEATING()
IF NOT bSkipped // If we've skipped to the running section, the bikes generally won't have been made and we don't care about them
//DEBUG_PRINTSTRING("checking bikes")
CHECK_BIKE_IN_WATER()
CHECK_BIKES_ALIVE()
ENDIF
CHECK_PLAYER_IN_MISSION_AREA()
//DO_BOATS()
DO_BAD_DRIVER()
IF PrevCheckpoint != NULL
//DEBUG_PRINTSTRING("Fade previous CP")
iPrevAlpha -= 25
INT PreviR, PreviG, PreviB, iA
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 subState
CASE SS_INIT
REPLAY_RECORD_BACK_FOR_TIME(5.0, 15.0, REPLAY_IMPORTANCE_LOW)
DEBUG_PRINTSTRING("DOING OFF BIKE SETUP")
subState = SS_RUNNING
DEBUG_PRINTSTRING("DOING OFF BIKE RUNNING")
BREAK
CASE SS_RUNNING
IF IS_PED_SITTING_IN_ANY_VEHICLE(PLAYER_PED_ID())
IF BRING_VEHICLE_TO_HALT_AND_DISABLE_VEH_CONTROLS(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()), 7, 10)
TASK_LEAVE_ANY_VEHICLE(PLAYER_PED_ID())
DEBUG_PRINTSTRING("Telling player to leave bike...")
ENDIF
ENDIF
IF NOT IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
IF NOT bLoadedRun
m_pUnloadBike()
IF m_pLoadJog()
bLoadedRun = TRUE
ENDIF
ELSE
subState = SS_CLEANUP
ENDIF
ENDIF
BREAK
CASE SS_CLEANUP
DEBUG_PRINTSTRING("DOING OFF BIKE CLEANUP")
current_max_positions = MAX_RUN_POSITIONS
CLEAR_PRINTS()
PRINT_NOW("FATIC3_6", DEFAULT_GOD_TEXT_TIME, 1) //Run along the ~y~route.
IF bCheatReload
// If we've come back here because the player cheated, we want to go back to the checkpoint we left off, so recreate it and its blip
// then reset the cheat 'flag'
blip = CREATE_COORD_BLIP(RUN_POSITIONS[current_position], BLIPPRIORITY_MED, FALSE)
SET_BLIP_COLOUR(blip, BLIP_COLOUR_YELLOW)
IF (current_position = (current_max_positions - 1))
currentCPColour = GET_RACE_CHECKPOINT_COLOUR(GET_RACE_CHECKPOINT_TYPE(current_position, RUN_POSITIONS))
INT iR, iG, iB, iA
GET_HUD_COLOUR(currentCPColour, iR, iG, iB, iA)
VECTOR to_position
to_position = RUN_POSITIONS[current_position]
checkpoint = CREATE_CHECKPOINT(CHECKPOINT_RACE_TRI_RUN_FLAG, RUN_POSITIONS[current_position]+<<0,0,0.1>>, to_position, 3.2, 254, 207, 12)
ELSE
currentCPColour = GET_RACE_CHECKPOINT_COLOUR(GET_RACE_CHECKPOINT_TYPE(current_position, RUN_POSITIONS))
INT iR, iG, iB, iA
GET_HUD_COLOUR(currentCPColour, iR, iG, iB, iA)
VECTOR to_position
to_position = RUN_POSITIONS[current_position+1]
checkpoint = CREATE_CHECKPOINT(GET_RACE_CHECKPOINT_TYPE(current_position, RUN_POSITIONS), RUN_POSITIONS[current_position], to_position, 3.2, 254, 207, 12)
ENDIF
bCheatReload = FALSE
ELSE
// Otherwise, do the first blip and reset the current checkpoint position
CREATE_FIRST_BLIP(RUN_POSITIONS)
current_position = 0
// Also, this is a horrible hack and I feel like a bad man for doing it
ENDIF
iTrashTalkTimer = GET_GAME_TIMER()
IF bSkipped
bSkipped = FALSE
ENDIF
missionStage = MS_RUN
subState = SS_INIT
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE:
/// Checks whether the player has used any of the shortcuts during the jog section, and plays a colour conversation if so
PROC CHECK_JOGGING_SHORTCUTS()
// IF IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<100.684044,6836.642090,14.557539>>, <<93.206673,6817.831543,19.754509>>, 11.000000)
// IF NOT bCheat1Said
// IF IS_ENTITY_ALIVE(opponent)
// IF GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), opponent) < 20
// IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
// KILL_ANY_CONVERSATION()
// ADD_NON_CRITICAL_STANDARD_CONVERSATION_TO_BUFFER(conversation, "FAN3AUD", "FAN3_JOGCH1", CONV_PRIORITY_HIGH)
// ELSE
// CREATE_CONVERSATION(conversation, "FAN3AUD", "FAN3_JOGCH1", CONV_PRIORITY_HIGH)
// ENDIF
// bCheat1Said = TRUE
// bConvoPaused = FALSE
// bCheated = TRUE
// ENDIF
// ENDIF
// ENDIF
IF IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<59.708908,6931.385742,10.608230>>, <<69.710922,6899.878418,15.374324>>, 11.000000)
IF NOT bCheat2Said
IF IS_ENTITY_ALIVE(opponent)
IF GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), opponent) < 20
IF g_savedGlobals.sRandomChars.g_bFanaticCheated = TRUE
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
KILL_ANY_CONVERSATION()
ADD_NON_CRITICAL_STANDARD_CONVERSATION_TO_BUFFER(conversation, "FAN3AUD", "FAN3_JOGCH2B", CONV_PRIORITY_HIGH)
ELSE
CREATE_CONVERSATION(conversation, "FAN3AUD", "FAN3_JOGCH2B", CONV_PRIORITY_HIGH)
ENDIF
ELSE
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
KILL_ANY_CONVERSATION()
ADD_NON_CRITICAL_STANDARD_CONVERSATION_TO_BUFFER(conversation, "FAN3AUD", "FAN3_JOGCH2A", CONV_PRIORITY_HIGH)
ELSE
CREATE_CONVERSATION(conversation, "FAN3AUD", "FAN3_JOGCH2A", CONV_PRIORITY_HIGH)
ENDIF
ENDIF
bCheat2Said = TRUE
bConvoPaused = FALSE
bCheated = TRUE
ENDIF
ENDIF
ENDIF
ELIF IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<42.007938,6994.049805,5.189813>>, <<51.558426,6969.847168,12.566551>>, 7.000000)
IF NOT bCheat3Said
IF IS_ENTITY_ALIVE(opponent)
IF GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), opponent) < 20
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
KILL_ANY_CONVERSATION()
ADD_NON_CRITICAL_STANDARD_CONVERSATION_TO_BUFFER(conversation, "FAN3AUD", "FAN3_JOGCH3", CONV_PRIORITY_HIGH)
ELSE
CREATE_CONVERSATION(conversation, "FAN3AUD", "FAN3_JOGCH3", CONV_PRIORITY_HIGH)
ENDIF
bCheat3Said = TRUE
bConvoPaused = FALSE
bCheated = TRUE
ENDIF
ENDIF
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Main mission function for the jogging section of the race
PROC m_pRun()
m_pDoRaceLogic()
ma_pUpdate()
PROCESS_CONVERSATION()
CHECK_JOGGING_SHORTCUTS()
CHECK_PLAYER_CHEATING()
CHECK_PLAYER_IN_MISSION_AREA()
CHECK_CHINUPS_GUY()
CHECK_STRETCHING_WOMAN()
CHECK_BINOCS_GUY()
DO_DOG_SCENE()
DO_OWNER_SCENE()
IF PrevCheckpoint != NULL
//DEBUG_PRINTSTRING("Fade previous CP")
iPrevAlpha -= 25
INT PreviR, PreviG, PreviB, iA
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 subState
CASE SS_INIT
DEBUG_PRINTSTRING("DOING RUN SETUP")
subState = SS_RUNNING
bMissedCheckWarning = FALSE
bSkipped = FALSE
REQUEST_ANIM_DICT("rcmfanatic3leadinoutef_3_mcs_1")
DEBUG_PRINTSTRING("DOING RUN RUNNING")
BREAK
CASE SS_RUNNING
IF GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), RUN_POSITIONS[current_position]) > 75
IF NOT bMissedCheckWarning
PRINT("FATIC3_15", DEFAULT_GOD_TEXT_TIME, 1) //Return to the ~y~race.
bMissedCheckWarning = TRUE
ENDIF
ELSE
bMissedCheckWarning = FALSE
ENDIF
IF (DO_CHECKPOINT_UPDATES(RUN_POSITIONS))
SET_PLAYER_CONTROL(PLAYER_ID(), FALSE, SPC_LEAVE_CAMERA_CONTROL_ON)
//CLEAR_PED_TASKS(PLAYER_PED_ID())
TASK_PLAY_ANIM(PLAYER_PED_ID(), "rcmfanatic3leadinoutef_3_mcs_1", "Fra_outofbreath_intro", REALLY_SLOW_BLEND_IN)
TRIGGER_MUSIC_EVENT("FANATIC2_STOP")
SET_MULTIHEAD_SAFE(TRUE) //Set multihead blinders on early
race_won = TRUE
subState = SS_CLEANUP
ENDIF
BREAK
CASE SS_CLEANUP
IF IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(), "rcmfanatic3leadinoutef_3_mcs_1", "Fra_outofbreath_intro")
IF GET_ENTITY_ANIM_CURRENT_TIME(PLAYER_PED_ID(), "rcmfanatic3leadinoutef_3_mcs_1", "Fra_outofbreath_intro") >= 0.90
DEBUG_PRINTSTRING("Player done lead-out info")
missionStage = MS_DONE
ENDIF
ELSE
DEBUG_PRINTSTRING("Player not playing anim, cut to outro")
missionStage = MS_DONE
ENDIF
BREAK
ENDSWITCH
ENDPROC
PROC m_pLost()
SWITCH subState
CASE SS_INIT
DEBUG_PRINTSTRING("DOING LOST SETUP")
// Do a Mary Ann winning anim here?
subState = SS_RUNNING
BREAK
CASE SS_RUNNING
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
subState = SS_CLEANUP
ELSE
DEBUG_PRINTSTRING("Waiting for Lost race convo to finish...")
ENDIF
BREAK
CASE SS_CLEANUP
MISSION_FAILED(FAILED_LOST_RACE)
BREAK
ENDSWITCH
ENDPROC
#IF IS_DEBUG_BUILD
/// PURPOSE: Check for Forced Pass or Fail
PROC DEBUG_Check_Debug_Keys()
IF missionStage <> MS_FAILED
IF IS_KEYBOARD_KEY_JUST_PRESSED(KEY_S)
bSkipped = TRUE
WAIT_FOR_CUTSCENE_TO_STOP()
CLEAR_PRINTS()
MISSION_PASSED()
ENDIF
IF IS_KEYBOARD_KEY_JUST_PRESSED(KEY_F)
bSkipped = TRUE
WAIT_FOR_CUTSCENE_TO_STOP()
CLEAR_PRINTS()
MISSION_FAILED()
ENDIF
IF IS_KEYBOARD_KEY_JUST_PRESSED(KEY_J)
bSkipped = TRUE
WAIT_FOR_CUTSCENE_TO_STOP()
RC_START_Z_SKIP()
SKIP_FORWARD()
ENDIF
IF IS_KEYBOARD_KEY_JUST_PRESSED(KEY_P)
bSkipped = TRUE
WAIT_FOR_CUTSCENE_TO_STOP()
RC_START_Z_SKIP()
SKIP_BACK()
ENDIF
IF LAUNCH_MISSION_STAGE_MENU(s_skip_menu, menu_option)
IF IS_ENTITY_ALIVE(opponent_bike_vehicle)
IF IS_PLAYBACK_GOING_ON_FOR_VEHICLE(opponent_bike_vehicle)
STOP_PLAYBACK_RECORDED_VEHICLE(opponent_bike_vehicle)
ENDIF
ENDIF
IF IS_ENTITY_ALIVE(bike_vehicle)
IF IS_PLAYBACK_GOING_ON_FOR_VEHICLE(bike_vehicle)
STOP_PLAYBACK_RECORDED_VEHICLE(bike_vehicle)
ENDIF
ENDIF
SET_PLAYER_CONTROL(PLAYER_ID(), TRUE)
JUMP_TO_STAGE(menu_option)
ENDIF
ENDIF
ENDPROC
#ENDIF
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]")
Random_Character_Failed()
MISSION_CLEANUP()
ENDIF
IF Is_Replay_In_Progress() // Set up the initial scene for replays
INT iReplayStage = Get_Replay_Mid_Mission_Stage()
IF g_bShitskipAccepted = TRUE
iReplayStage++ // player is skipping this stage
ENDIF
IF iReplayStage = CP_SWIM
g_bSceneAutoTrigger = TRUE
eInitialSceneStage = IS_REQUEST_SCENE
WHILE NOT SetupScene_FANATIC_3(sRCLauncherDataLocal)
WAIT(0)
ENDWHILE
g_bSceneAutoTrigger = FALSE
ENDIF
RC_SET_ENTITY_PROOFS_FOR_CUTSCENE(sRCLauncherDataLocal, FALSE)
ENDIF
ma_pCreate()
IF NOT IS_ENTITY_ALIVE(PLAYER_PED_ID())
SCRIPT_ASSERT("Player not alive.")
ENDIF
#IF IS_DEBUG_BUILD
s_skip_menu[0].sTxtLabel = "Intro"
s_skip_menu[0].bSelectable = true
s_skip_menu[1].sTxtLabel = "Swim section"
s_skip_menu[1].bSelectable = true
s_skip_menu[2].sTxtLabel = "Bike section"
s_skip_menu[2].bSelectable = true
s_skip_menu[3].sTxtLabel = "Jog section"
s_skip_menu[3].bSelectable = true
s_skip_menu[4].sTxtLabel = "Outro"
s_skip_menu[4].bSelectable = true
IF NOT DOES_WIDGET_GROUP_EXIST(widgetGroup)
widgetGroup= START_WIDGET_GROUP("Fanatic 3 widgets")
ADD_WIDGET_BOOL("TTY Toggle - Print Mission Debug Info", bDebug_PrintToTTY)
ADD_WIDGET_BOOL("Debug Mary Ann rubber banding", bDebugRubberBanding)
STOP_WIDGET_GROUP()
ENDIF
#ENDIF
DISABLE_CHEAT(CHEAT_TYPE_FAST_RUN, TRUE)
DISABLE_CHEAT(CHEAT_TYPE_FAST_SWIM, TRUE)
// Disable controls and exit current vehicle
RC_PLAYER_TRIGGER_SCENE_LOCK_IN()
WHILE(TRUE)
REPLAY_CHECK_FOR_EVENT_THIS_FRAME("SF_EDF")
WAIT(0)
UPDATE_MISSION_NAME_DISPLAYING(sRCLauncherDataLocal.sIntroCutscene, TRUE)
HANDLE_GLOBAL_STAMINA_HELP()
SWITCH missionStage
CASE MS_LEADIN
m_pLeadIn()
BREAK
CASE MS_INTRO
INIT_MISSION()
BREAK
CASE MS_SWIM
m_pSwim()
BREAK
CASE MS_TO_BIKE
m_pToBike()
BREAK
CASE MS_BIKE
m_pBike()
BREAK
CASE MS_OFF_BIKE
m_pOffBike()
BREAK
CASE MS_RUN
m_pRun()
BREAK
CASE MS_LOST
m_pLost()
BREAK
CASE MS_DONE
DO_OUTRO()
BREAK
CASE MS_FAILED
FAILED()
BREAK
ENDSWITCH
#IF IS_DEBUG_BUILD
DEBUG_Check_Debug_Keys()
#ENDIF
ENDWHILE
// Script should never reach here. Always terminate with cleanup function.
ENDSCRIPT