3654 lines
121 KiB
Python
Executable File
3654 lines
121 KiB
Python
Executable File
// *****************************************************************************************
|
|
// *****************************************************************************************
|
|
// *****************************************************************************************
|
|
//
|
|
// MISSION NAME : Fanatic2.sc
|
|
// AUTHOR : Kev Edwards (originally)/Ian Gander (June '12 onwards)
|
|
// DESCRIPTION : Downhill bike race within a time limit
|
|
//
|
|
// *****************************************************************************************
|
|
// *****************************************************************************************
|
|
// *****************************************************************************************
|
|
|
|
//Compile out Title Update changes to header functions.
|
|
//Must be before includes.
|
|
//CONST_INT USE_TU_CHANGES 0 // Removed by Kenneth R.
|
|
|
|
USING "rage_builtins.sch"
|
|
USING "globals.sch"
|
|
USING "cutscene_public.sch"
|
|
USING "commands_cutscene.sch"
|
|
USING "commands_entity.sch"
|
|
USING "commands_script.sch"
|
|
USING "commands_vehicle.sch"
|
|
USING "script_player.sch"
|
|
USING "randomChar_public.sch"
|
|
USING "script_races.sch"
|
|
USING "dialogue_public.sch"
|
|
USING "shared_hud_displays.sch"
|
|
USING "RC_Helper_Functions.sch"
|
|
USING "CompletionPercentage_public.sch"
|
|
USING "chase_hint_cam.sch" CHASE_HINT_CAM_STRUCT localChaseHintCamStruct
|
|
USING "RC_Threat_public.sch"
|
|
USING "RC_Setup_public.sch"
|
|
USING "initial_scenes_fanatic.sch"
|
|
USING "rgeneral_include.sch"
|
|
USING "commands_recording.sch"
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
USING "select_mission_stage.sch"
|
|
#ENDIF
|
|
|
|
// Enums
|
|
ENUM MISSION_STAGE
|
|
stateNULL,
|
|
stateInit,
|
|
stateIntro,
|
|
stateCountdown,
|
|
stateRace,
|
|
stateOutro,
|
|
stateResult,
|
|
stateMissionPassed,
|
|
stateMissionFailed
|
|
ENDENUM
|
|
|
|
ENUM FAILED_REASON
|
|
FAILED_GENERIC = 0,
|
|
FAILED_BIKE_DESTROYED,
|
|
FAILED_LEFT_BEHIND,
|
|
FAILED_WOMAN_DIED,
|
|
FAILED_WOMAN_HURT,
|
|
FAILED_WOMAN_SCARED,
|
|
FAILED_LEFT_BIKE,
|
|
FAILED_PUSHED_WOMAN,
|
|
FAILED_LOST_RACE,
|
|
FAILED_ABANDONED,
|
|
FAILED_MISSED_CHECK
|
|
ENDENUM
|
|
|
|
ENUM RACE_LENGTH
|
|
RACE_SHORT,
|
|
RACE_LONGA,
|
|
RACE_LONGB
|
|
ENDENUM
|
|
|
|
ENUM FAN2_CONV_STATE
|
|
FAN2_CONV_STATE_FREE,
|
|
FAN2_CONV_STATE_START,
|
|
FAN2_CONV_STATE_BANTER_PLAYING,
|
|
FAN2_CONV_STATE_BANTER_PAUSED,
|
|
FAN2_CONV_STATE_PUSHWARNING,
|
|
FAN2_CONV_STATE_OVERTAKE,
|
|
FAN2_CONV_STATE_ONELINER,
|
|
FAN2_CONV_STATE_ROADRAGE,
|
|
FAN2_CONV_STATE_TOOFAR,
|
|
FAN2_CONV_STATE_END
|
|
ENDENUM
|
|
|
|
|
|
ENUM BANTER_STATE
|
|
BANTER_WAIT,
|
|
BANTER_ACT
|
|
ENDENUM
|
|
|
|
ENUM RECOVER_STATE
|
|
RECOVER_WAIT,
|
|
RECOVER_NEEDED,
|
|
RECOVER_RECOVERING
|
|
ENDENUM
|
|
|
|
RACE_LENGTH raceLength = RACE_LONGA
|
|
|
|
// Variables etc
|
|
MISSION_STAGE missionStage = stateInit // Used to track what mission stage we are at
|
|
MISSION_STAGE missionStageSkip = stateNULL
|
|
|
|
FAILED_REASON failedReason = FAILED_GENERIC
|
|
|
|
MODEL_NAMES cyclistModel = U_M_Y_CYCLIST_01
|
|
|
|
FAN2_CONV_STATE ConvState = FAN2_CONV_STATE_START
|
|
BANTER_STATE BanterState = BANTER_WAIT
|
|
RECOVER_STATE RecoverState = RECOVER_WAIT
|
|
INT iRecoverTimer
|
|
|
|
CONST_INT CP_START 0
|
|
|
|
CONST_FLOAT MA_CHECKPOINTSIZE 6.0
|
|
|
|
CONST_INT MARY_ANN_ID 0
|
|
CONST_INT MARY_ANN_FRIEND_ID 1
|
|
CONST_INT PLAYER_BIKE_ID 0
|
|
CONST_INT MARY_ANN_BIKE_ID 1
|
|
|
|
CONST_INT MAX_CHECKPOINTS 27
|
|
|
|
CONST_FLOAT START_SPEED 3.5
|
|
|
|
BOOL bInitStage = TRUE
|
|
BOOL bCleanupStage = FALSE
|
|
BOOL bDoneMissionSetup = FALSE
|
|
BOOL bDebugPrintBikePlaybackSpeed = FALSE
|
|
BOOL bDoBikeExit = FALSE
|
|
BOOL bDoneTrevExit = FALSE
|
|
BOOL bDoneTrevCelebrate = FALSE
|
|
BOOL bDoneLeadInConv = FALSE
|
|
|
|
REL_GROUP_HASH relGroupPlayer
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
CONST_INT MAX_SKIP_MENU_LENGTH 5
|
|
MissionStageMenuTextStruct mSkipMenu[MAX_SKIP_MENU_LENGTH]
|
|
BOOL bAllowDebugSkipForward = TRUE
|
|
BOOL bDebug_PrintToTTY = TRUE
|
|
WIDGET_GROUP_ID widgetGroup
|
|
#ENDIF
|
|
|
|
//CAMERA_INDEX camCutscene
|
|
INT iCutsceneStage
|
|
INT iFailStage = 0
|
|
INT iPushTimer
|
|
INT iHonkTimer
|
|
//INT block_time
|
|
|
|
INT iFadeTimer
|
|
|
|
int iClosestWaypoint // Constantly updated with the closest waypoint to Mary Ann
|
|
INT iRecoverWaypoint // Used to know which waypoint to recover to
|
|
|
|
SCENARIO_BLOCKING_INDEX mScenarioBlocker
|
|
|
|
CONST_INT NUM_BIKES 2
|
|
VEHICLE_INDEX vehBike[NUM_BIKES]
|
|
BLIP_INDEX blipBike
|
|
MODEL_NAMES modelPlayerBike
|
|
VECTOR vLongRaceStart[NUM_BIKES]
|
|
FLOAT fLongRaceStart[NUM_BIKES]
|
|
VECTOR vLongRaceEnd[NUM_BIKES]
|
|
FLOAT fLongRaceEnd[NUM_BIKES]
|
|
BOOL bPlayerIsOnBike
|
|
|
|
BLIP_INDEX opponentBlip
|
|
CONST_FLOAT LOST_RANGE 230.0
|
|
|
|
INT start_time
|
|
INT finish_time
|
|
RACER_INFO_STRUCT playerInfo
|
|
RACE_INFO_STRUCT raceInfo
|
|
|
|
CONST_INT NUM_ROAD_RAGE_CONVERSATIONS 5
|
|
structPedsForConversation sRoadRageConversation
|
|
STRING sRoadRageConversationString[NUM_ROAD_RAGE_CONVERSATIONS]
|
|
BOOL bPlayedRoadRageConversation[NUM_ROAD_RAGE_CONVERSATIONS]
|
|
INT iRoadRageConversationsPlayed
|
|
|
|
int iBanterTimer
|
|
int iBanterSequence
|
|
|
|
CONST_INT NUM_WOMAN_CONVERSATIONS 4
|
|
structPedsForConversation sWomanConversation
|
|
STRING sWomanConversationString[NUM_WOMAN_CONVERSATIONS]
|
|
INT iWomanConversationsPlayed
|
|
|
|
CONST_INT NUM_WOMAN_BEHIND_ONELINERS 4
|
|
int iWomanBehindOnelinersPlayed
|
|
|
|
CONST_INT NUM_WOMAN_AHEAD_ONELINERS 4
|
|
int iWomanAheadOnelinersPlayed
|
|
|
|
CONST_INT NUM_TREVOR_ONELINERS 6
|
|
int iTrevorOnelinersPlayed
|
|
|
|
CONST_INT NUM_OVERTAKE_LINES 4
|
|
INT iOverTakeLinesPlayed
|
|
INT iConversationGapTimer
|
|
|
|
BOOL bDoMaryAnnOneliner
|
|
BOOL bOvertakeOccurred = FALSE
|
|
INT iOvertakeSpamTimer
|
|
BOOL bPlayedStartConv = FALSE
|
|
BOOL bPlayedPushConv = FALSE
|
|
BOOL bPlayedOvertakeLine = FALSE
|
|
BOOL bPlayedBanterOneliner = FALSE
|
|
BOOL bStartEndConv = FALSE
|
|
|
|
structPedsForConversation sOutroConversation
|
|
//STRING sOutroConverationString
|
|
|
|
INT iIntroStage = 0
|
|
BOOL bIntroSkipped = FALSE
|
|
BOOL bIntroSkippedWhile = FALSE
|
|
//BOOL bDoneTrevExit = FALSE
|
|
BOOL bUsedSkip = FALSE
|
|
BOOL bSkipToEnd = FALSE
|
|
BOOL bUsedCheckpoints = FALSE
|
|
BOOL bReleaseMAEarly = FALSE
|
|
|
|
int iCountdown
|
|
|
|
INT iRacePos
|
|
BOOL bFinishedRace
|
|
BOOL bLostRace = FALSE
|
|
INT iWomanNextCheckpoint
|
|
|
|
BOOL bDisplayedGetBackOnBike
|
|
|
|
BOOL bPlayedFinalConv = FALSE
|
|
BOOL bFinalConvWinning = FALSE
|
|
bool bRoadRagePlaying
|
|
BOOL bGivePushWarning
|
|
|
|
BOOL bStartedCyclist = FALSE
|
|
BOOL bStartedDrivers = FALSE
|
|
|
|
SCENARIO_BLOCKING_INDEX sbiDeerArea
|
|
|
|
VEHICLE_INDEX viDriver
|
|
VEHICLE_INDEX viDriverCop
|
|
VEHICLE_INDEX viCyclist
|
|
PED_INDEX piDriver
|
|
PED_INDEX piDriverCop
|
|
PED_INDEX piJogger1
|
|
PED_INDEX piJogger2
|
|
PED_INDEX piCyclist
|
|
|
|
BOOL bDoneFailDialogue
|
|
|
|
SEQUENCE_INDEX seq
|
|
|
|
FLOAT fHintFov = 30.0
|
|
FLOAT fHintFollow = 0.35
|
|
FLOAT fHintPitchOrbit = 0.000
|
|
FLOAT fHintSide = 0.05
|
|
FLOAT fHintVert = -0.050
|
|
|
|
INT iPushInTimer
|
|
|
|
//BOOL bDoneFakeCheck = FALSE
|
|
//CHECKPOINT_INDEX fakeFirstCheck
|
|
|
|
// The Random Character - sRCLauncherDataLocal.pedID[MARY_ANN_ID]
|
|
g_structRCScriptArgs sRCLauncherDataLocal
|
|
|
|
//PURPOSE: Print debug string to Rag.
|
|
PROC RCM_DEBUG_PRINT(STRING s)
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
IF bDebug_PrintToTTY
|
|
CPRINTLN(DEBUG_MISSION, s)
|
|
ENDIF
|
|
#ENDIF
|
|
|
|
// Stop release compile error
|
|
s = s
|
|
|
|
ENDPROC
|
|
|
|
//PURPOSE: Print debug string with int to Rag.
|
|
PROC RCM_DEBUG_PRINTINT(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 debug string with float to Rag.
|
|
PROC RCM_DEBUG_PRINTFLOAT(STRING s, FLOAT f)
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
IF bDebug_PrintToTTY
|
|
CPRINTLN(DEBUG_MISSION, s, f)
|
|
ENDIF
|
|
#ENDIF
|
|
|
|
// Stop release compile error
|
|
s = s
|
|
f = f
|
|
ENDPROC
|
|
|
|
//PURPOSE: Print debug string with float to Rag.
|
|
PROC RCM_DEBUG_PRINTVEC(STRING s, VECTOR v)
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
IF bDebug_PrintToTTY
|
|
CPRINTLN(DEBUG_MISSION, s, "<<", v, ">>")
|
|
ENDIF
|
|
#ENDIF
|
|
|
|
// Stop release compile error
|
|
s = s
|
|
v = v
|
|
ENDPROC
|
|
|
|
//PURPOSE: Print debug output text for the bike speed to RAG.
|
|
PROC RCM_DEBUG_PRINTBIKESPEED(string s1, float f1, string s2, float f2, string s3, float f3)
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
IF bDebug_PrintToTTY
|
|
CPRINTLN(DEBUG_MISSION, s1, f1, s2, f2, s3, f3)
|
|
ENDIF
|
|
#ENDIF
|
|
|
|
// Stop release compile error
|
|
s1 = s1
|
|
f1 = f1
|
|
s2 = s2
|
|
f2 = f2
|
|
s3 = s3
|
|
f3 = f3
|
|
ENDPROC
|
|
|
|
//PURPOSE: Check whether a particular conversation root is playing.
|
|
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: Checks whether the player has touched any of the flight controls.
|
|
//RETURNS: TRUE if any player flight input is detected, FALSE otherwise.
|
|
FUNC BOOL HAS_PLAYER_TOUCHED_STEERING_CONTROLS()
|
|
IF IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_VEH_MOVE_LR)
|
|
OR IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_VEH_MOVE_UD) // Leave old inputs, just in case
|
|
OR IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_VEH_HANDBRAKE)
|
|
OR IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_VEH_DUCK)
|
|
OR IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_VEH_JUMP)
|
|
OR IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_VEH_BRAKE)
|
|
RCM_DEBUG_PRINT("*** Player input detected")
|
|
RETURN TRUE
|
|
ENDIF
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
//PURPOSE: Handles initialising the current missionStage.
|
|
FUNC BOOL RCM_INIT_STAGE()
|
|
|
|
IF bInitStage = TRUE
|
|
bInitStage = FALSE
|
|
RETURN TRUE
|
|
ELSE
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
ENDFUNC
|
|
|
|
//PURPOSE: Use anywhere in the current missionStage loop to advance to the next missionStage.
|
|
PROC RCM_ADVANCE_STAGE()
|
|
|
|
bCleanupStage = TRUE
|
|
|
|
ENDPROC
|
|
|
|
//PURPOSE: Handles cleaning up the current missionStage, resetting flags and incrementing missionStage.
|
|
FUNC BOOL RCM_CLEANUP_STAGE()
|
|
|
|
IF bCleanupStage = TRUE
|
|
CLEAR_HELP(TRUE)
|
|
bInitStage = TRUE
|
|
bCleanupStage = FALSE
|
|
IF missionStageSkip = stateNULL
|
|
missionStage = INT_TO_ENUM(MISSION_STAGE, ENUM_TO_INT(missionStage) + 1)
|
|
ELSE
|
|
missionStage = missionStageSkip
|
|
ENDIF
|
|
missionStageSkip = stateNULL
|
|
RETURN TRUE
|
|
ELSE
|
|
#IF IS_DEBUG_BUILD
|
|
bAllowDebugSkipForward = TRUE
|
|
#ENDIF
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
ENDFUNC
|
|
|
|
//PURPOSE: Returns true if player ped exists and is alive.
|
|
FUNC BOOL RCM_IS_PLAYER_OK()
|
|
|
|
IF DOES_ENTITY_EXIST(PLAYER_PED_ID())
|
|
IF NOT IS_ENTITY_DEAD(PLAYER_PED_ID())
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
|
|
ENDFUNC
|
|
|
|
//PURPOSE: Generates the race information prior to the mission starting
|
|
PROC RCM_SETUP_RACE_INFO()
|
|
playerInfo.raceVehicle = vehBike[PLAYER_BIKE_ID]
|
|
playerInfo.racer = PLAYER_PED_ID()
|
|
RCM_DEBUG_PRINT("Setting up race info")
|
|
raceInfo.chosenCourse = RACE_COURSE_RC_FANATIC2ALT
|
|
GENERATE_RACE_INFO(raceInfo)
|
|
ENDPROC
|
|
|
|
|
|
//PURPOSE: Safely remove all blips in this mission.
|
|
PROC RCM_REMOVE_ALL_BLIPS()
|
|
|
|
SAFE_REMOVE_BLIP(blipBike)
|
|
SAFE_REMOVE_BLIP(opponentBlip)
|
|
|
|
ENDPROC
|
|
|
|
//PURPOSE: Safely spawn a vehicle.
|
|
PROC RCM_SPAWN_VEHICLE(VEHICLE_INDEX &vehIndex, MODEL_NAMES eModel, VECTOR vStart, FLOAT fStart = 0.0, INT iColour = -1, FLOAT fDirt = 0.0)
|
|
|
|
IF NOT DOES_ENTITY_EXIST(vehIndex)
|
|
IF HAS_MODEL_LOADED(eModel)
|
|
vehIndex = CREATE_VEHICLE(eModel, vStart, fStart)
|
|
IF iColour >= 0
|
|
SET_VEHICLE_COLOUR_COMBINATION(vehIndex, iColour)
|
|
ENDIF
|
|
SET_VEHICLE_DIRT_LEVEL(vehIndex, fDirt)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
//PURPOSE: Safely remove all vehicles in this mission.
|
|
PROC RCM_REMOVE_ALL_VEHICLES(BOOL bForceDelete = FALSE)
|
|
|
|
INT i = 0
|
|
REPEAT NUM_BIKES i
|
|
IF NOT bForceDelete
|
|
SAFE_RELEASE_VEHICLE(vehBike[i])
|
|
ELSE
|
|
SAFE_DELETE_VEHICLE(vehBike[i])
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
IF NOT bForceDelete
|
|
SAFE_RELEASE_VEHICLE(viDriver)
|
|
SAFE_RELEASE_VEHICLE(viDriverCop)
|
|
SAFE_RELEASE_VEHICLE(viCyclist)
|
|
ELSE
|
|
SAFE_DELETE_VEHICLE(viDriver)
|
|
SAFE_DELETE_VEHICLE(viDriverCop)
|
|
SAFE_DELETE_VEHICLE(viCyclist)
|
|
ENDIF
|
|
RCM_DEBUG_PRINT("Removed all vehicles")
|
|
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Removes the checkpoints and blips from the minimap/world
|
|
PROC RCM_REMOVE_RACE_BLIPS()
|
|
|
|
SAFE_REMOVE_BLIP(playerInfo.checkBlip)
|
|
DELETE_CHECKPOINT(playerInfo.checkPoint)
|
|
|
|
SAFE_REMOVE_BLIP(playerInfo.nextCheckBlip)
|
|
|
|
ENDPROC
|
|
|
|
//PURPOSE: Safely remove or delete a ped.
|
|
PROC RCM_REMOVE_PED(PED_INDEX &ped, BOOL bForceDelete = FALSE)
|
|
|
|
IF bForceDelete
|
|
SAFE_DELETE_PED(ped)
|
|
ELSE
|
|
SAFE_RELEASE_PED(ped)
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
//PURPOSE: Safely remove all peds in this mission.
|
|
PROC RCM_REMOVE_ALL_PEDS(BOOL bForceDelete = FALSE)
|
|
|
|
RCM_REMOVE_PED(sRCLauncherDataLocal.pedID[MARY_ANN_ID], bForceDelete)
|
|
RCM_REMOVE_PED(piDriver, bForceDelete)
|
|
RCM_REMOVE_PED(piJogger1, bForceDelete)
|
|
RCM_REMOVE_PED(piJogger2, bForceDelete)
|
|
RCM_REMOVE_PED(piDriverCop, bForceDelete)
|
|
RCM_REMOVE_PED(piCyclist, bForceDelete)
|
|
RCM_DEBUG_PRINT("Removed all peds")
|
|
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Reset the bools and timer for the conversations back to the default state
|
|
PROC RCM_RESET_CONVERSATIONS()
|
|
|
|
KILL_FACE_TO_FACE_CONVERSATION_DO_NOT_FINISH_LAST_LINE()
|
|
|
|
iBanterTimer = GET_GAME_TIMER()
|
|
iOvertakeSpamTimer = GET_GAME_TIMER()
|
|
iConversationGapTimer = GET_GAME_TIMER()
|
|
|
|
bOvertakeOccurred = FALSE
|
|
bPlayedStartConv = FALSE
|
|
bPlayedPushConv = FALSE
|
|
bPlayedOvertakeLine = FALSE
|
|
bPlayedBanterOneliner = FALSE
|
|
bStartEndConv = FALSE
|
|
bRoadRagePlaying = FALSE
|
|
bGivePushWarning = FALSE
|
|
|
|
ConvState = FAN2_CONV_STATE_START
|
|
|
|
BanterState = BANTER_WAIT
|
|
|
|
iWomanAheadOnelinersPlayed = 0
|
|
iWomanBehindOnelinersPlayed = 0
|
|
iWomanConversationsPlayed = 0
|
|
iTrevorOnelinersPlayed = 0
|
|
iBanterSequence = 0
|
|
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Cleanup the bools and timer for the conversations so they restart properly, but keep current progress
|
|
PROC RCM_CLEANUP_CONVERSATIONS()
|
|
|
|
KILL_FACE_TO_FACE_CONVERSATION_DO_NOT_FINISH_LAST_LINE()
|
|
|
|
iBanterTimer = GET_GAME_TIMER()
|
|
iOvertakeSpamTimer = GET_GAME_TIMER()
|
|
iConversationGapTimer = GET_GAME_TIMER()
|
|
|
|
BanterState = BANTER_WAIT
|
|
|
|
bOvertakeOccurred = FALSE
|
|
bPlayedStartConv = FALSE
|
|
bPlayedPushConv = FALSE
|
|
bPlayedOvertakeLine = FALSE
|
|
bPlayedBanterOneliner = FALSE
|
|
bStartEndConv = FALSE
|
|
bRoadRagePlaying = FALSE
|
|
bGivePushWarning = FALSE
|
|
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Reset the bikes at the start of the race
|
|
PROC RESET_BIKES()
|
|
|
|
RCM_DEBUG_PRINT("Resetting bikes...")
|
|
INT i
|
|
REPEAT NUM_BIKES i
|
|
IF IS_VEHICLE_OK(vehBike[i])
|
|
SET_ENTITY_COORDS(vehBike[i], vLongRaceStart[i])
|
|
SET_ENTITY_HEADING(vehBike[i], fLongRaceStart[i])
|
|
SET_VEHICLE_ON_GROUND_PROPERLY(vehBike[i])
|
|
RCM_DEBUG_PRINTINT("Bike exists, set coords/heading: ", i)
|
|
// IF i = PLAYER_BIKE_ID
|
|
// AND NOT IS_PED_IN_VEHICLE(PLAYER_PED_ID(), vehBike[PLAYER_BIKE_ID])
|
|
// RCM_DEBUG_PRINT("Putting Trevor on bike...")
|
|
// SET_PED_INTO_VEHICLE(PLAYER_PED_ID(), vehBike[PLAYER_BIKE_ID])
|
|
// //TASK_WARP_PED_INTO_VEHICLE(PLAYER_PED_ID(), vehBike[PLAYER_BIKE_ID], VS_DRIVER)
|
|
// SIMULATE_PLAYER_INPUT_GAIT(PLAYER_ID(), PEDMOVE_RUN)
|
|
// ENDIF
|
|
ELSE
|
|
RCM_SPAWN_VEHICLE(vehBike[i], modelPlayerBike, vLongRaceStart[i], fLongRaceStart[i], i)
|
|
RCM_DEBUG_PRINTINT("Bike doesn't exist, recreate: ", i)
|
|
SET_VEHICLE_ON_GROUND_PROPERLY(vehBike[i])
|
|
IF i = PLAYER_BIKE_ID
|
|
AND NOT IS_PED_IN_VEHICLE(PLAYER_PED_ID(), vehBike[PLAYER_BIKE_ID])
|
|
IF NOT IS_REPLAY_BEING_SET_UP()
|
|
RCM_DEBUG_PRINT("Putting Trevor on bike...")
|
|
SET_PED_INTO_VEHICLE(PLAYER_PED_ID(), vehBike[PLAYER_BIKE_ID])
|
|
//TASK_WARP_PED_INTO_VEHICLE(PLAYER_PED_ID(), vehBike[PLAYER_BIKE_ID], VS_DRIVER)
|
|
SIMULATE_PLAYER_INPUT_GAIT(PLAYER_ID(), PEDMOVE_RUN)
|
|
ENDIF
|
|
ELIF i = MARY_ANN_BIKE_ID
|
|
IF IS_AUDIO_SCENE_ACTIVE("FANATIC_MIX_SCENE")
|
|
ADD_ENTITY_TO_AUDIO_MIX_GROUP(vehBike[MARY_ANN_BIKE_ID],"FANATIC_MIX_MARY_BIKE")
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Resets Mary Ann to the start position on the top of the hill and sets her going. NOT safe, do death checks before this!
|
|
PROC RESET_MARY_ANN()
|
|
CLEAR_PED_TASKS(sRCLauncherDataLocal.pedID[MARY_ANN_ID])
|
|
IF IS_VEHICLE_OK(vehBike[MARY_ANN_BIKE_ID])
|
|
IF NOT IS_PED_IN_VEHICLE(sRCLauncherDataLocal.pedID[MARY_ANN_ID], vehBike[MARY_ANN_BIKE_ID])
|
|
SET_PED_INTO_VEHICLE(sRCLauncherDataLocal.pedID[MARY_ANN_ID], vehBike[MARY_ANN_BIKE_ID])
|
|
ENDIF
|
|
IF bIntroSkipped
|
|
OR IS_REPLAY_IN_PROGRESS()
|
|
// If we've skipped the intro (or retrying after a fail), place Mary Ann ahead a little bit to simulate the delay we otherwise miss
|
|
SET_PED_COORDS_KEEP_VEHICLE(sRCLauncherDataLocal.pedID[MARY_ANN_ID], << 845.9933, 1274.4996, 358.8672 >>)
|
|
SET_ENTITY_HEADING(sRCLauncherDataLocal.pedID[MARY_ANN_ID], 229.7011)
|
|
ELSE
|
|
SET_PED_COORDS_KEEP_VEHICLE(sRCLauncherDataLocal.pedID[MARY_ANN_ID], << 831.5367, 1275.3864, 359.3159 >>)
|
|
SET_ENTITY_HEADING(sRCLauncherDataLocal.pedID[MARY_ANN_ID], 273.46)
|
|
ENDIF
|
|
IF NOT IS_WAYPOINT_PLAYBACK_GOING_ON_FOR_VEHICLE(vehBike[MARY_ANN_BIKE_ID])
|
|
TASK_VEHICLE_FOLLOW_WAYPOINT_RECORDING(sRCLauncherDataLocal.pedID[MARY_ANN_ID], vehBike[MARY_ANN_BIKE_ID], "Fan2_BikeRoute", DRIVINGMODE_AVOIDCARS_RECKLESS,
|
|
0, EWAYPOINT_START_FROM_CLOSEST_POINT)
|
|
ENDIF
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Place Mary Ann's knocked-out friend on the ground
|
|
PROC RCM_PLACE_KNOCKED_OUT_FRIEND()
|
|
|
|
IF IS_ENTITY_ALIVE(sRCLauncherDataLocal.pedID[MARY_ANN_FRIEND_ID])
|
|
FORCE_PED_MOTION_STATE(sRCLauncherDataLocal.pedID[MARY_ANN_FRIEND_ID], MS_DO_NOTHING, FALSE, FAUS_DEFAULT)
|
|
TASK_PLAY_ANIM(sRCLauncherDataLocal.pedID[MARY_ANN_FRIEND_ID], "rcm_fanatic2", "ef_2_rcm_cyclist_punched_out", NORMAL_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_LOOPING|AF_NOT_INTERRUPTABLE)
|
|
FLOAT newZ
|
|
VECTOR vNewPos
|
|
GET_GROUND_Z_FOR_3D_COORD(GET_ENTITY_COORDS(sRCLauncherDataLocal.pedID[MARY_ANN_FRIEND_ID]), newZ)
|
|
vNewPos = GET_ENTITY_COORDS(sRCLauncherDataLocal.pedID[MARY_ANN_FRIEND_ID])
|
|
vNewPos.z = newZ
|
|
SAFE_TELEPORT_ENTITY(sRCLauncherDataLocal.pedID[MARY_ANN_FRIEND_ID], vNewPos, GET_ENTITY_HEADING(sRCLauncherDataLocal.pedID[MARY_ANN_FRIEND_ID]))
|
|
SET_PED_KEEP_TASK(sRCLauncherDataLocal.pedID[MARY_ANN_FRIEND_ID], TRUE)
|
|
SET_MODEL_AS_NO_LONGER_NEEDED(cyclistModel)
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Stop any conversation is one is ongoing
|
|
/// PARAMS:
|
|
/// bDoNotFinishLastLine - If true, kill any playing line mid-sentence
|
|
PROC RCM_STOP_ANY_ACTIVE_CONVERSATION(BOOL bDoNotFinishLastLine = TRUE)
|
|
|
|
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
|
|
IF bDoNotFinishLastLine
|
|
KILL_FACE_TO_FACE_CONVERSATION_DO_NOT_FINISH_LAST_LINE()
|
|
ELSE
|
|
KILL_ANY_CONVERSATION()
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Main mission script cleanup
|
|
PROC Script_Cleanup()
|
|
|
|
// Ensure launcher is cleaned up
|
|
RC_CLEANUP_LAUNCHER()
|
|
|
|
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
|
|
KILL_FACE_TO_FACE_CONVERSATION_DO_NOT_FINISH_LAST_LINE()
|
|
ENDIF
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
IF DOES_WIDGET_GROUP_EXIST(widgetGroup)
|
|
DELETE_WIDGET_GROUP(widgetGroup)
|
|
ENDIF
|
|
#ENDIF
|
|
|
|
IF IS_VEHICLE_OK(vehBike[MARY_ANN_BIKE_ID])
|
|
MODIFY_VEHICLE_TOP_SPEED(vehBike[MARY_ANN_BIKE_ID], 0.0) // Resets top speed back to default
|
|
ENDIF
|
|
|
|
// If the mission was triggered then additional mission cleanup will be required.
|
|
IF (Random_Character_Cleanup_If_Triggered())
|
|
PRINTSTRING("...Random Character Script was triggered so additional cleanup required") PRINTNL()
|
|
ENDIF
|
|
|
|
IF IS_AUDIO_SCENE_ACTIVE("FANATIC_MIX_SCENE")
|
|
IF DOES_ENTITY_EXIST(vehBike[MARY_ANN_BIKE_ID])
|
|
REMOVE_ENTITY_FROM_AUDIO_MIX_GROUP(vehBike[MARY_ANN_BIKE_ID])
|
|
ENDIF
|
|
STOP_AUDIO_SCENE("FANATIC_MIX_SCENE")
|
|
ENDIF
|
|
|
|
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
|
|
TASK_CLEAR_LOOK_AT(PLAYER_PED_ID())
|
|
ENDIF
|
|
|
|
IF IS_ENTITY_ALIVE(sRCLauncherDataLocal.pedID[MARY_ANN_ID])
|
|
TASK_CLEAR_LOOK_AT(sRCLauncherDataLocal.pedID[MARY_ANN_ID])
|
|
ENDIF
|
|
|
|
FORCE_RENDER_IN_GAME_UI(FALSE)
|
|
|
|
REMOVE_PED_FOR_DIALOGUE(sRoadRageConversation, 0)
|
|
REMOVE_PED_FOR_DIALOGUE(sWomanConversation, 0)
|
|
REMOVE_PED_FOR_DIALOGUE(sWomanConversation, 1)
|
|
RCM_REMOVE_RACE_BLIPS()
|
|
RCM_REMOVE_ALL_BLIPS()
|
|
RCM_REMOVE_ALL_PEDS(FALSE)
|
|
RCM_REMOVE_ALL_VEHICLES(FALSE)
|
|
|
|
SET_ROADS_BACK_TO_ORIGINAL_IN_ANGLED_AREA(<<864.302063,1274.851807,361.473602>>, <<393.978210,1197.083862,224.314072>>, 176.0)
|
|
REMOVE_SCENARIO_BLOCKING_AREA(sbiDeerArea)
|
|
REMOVE_SCENARIO_BLOCKING_AREA(mScenarioBlocker)
|
|
|
|
//Cleanup the scene created by the launcher
|
|
//RC_CleanupSceneEntities(sRCLauncherDataLocal, FALSE)
|
|
|
|
TERMINATE_THIS_THREAD()
|
|
|
|
ENDPROC
|
|
|
|
PROC Script_Passed()
|
|
|
|
Random_Character_Passed(CP_RAND_C_FAN2)
|
|
ADD_CONTACT_TO_PHONEBOOK(CHAR_MARY_ANN, TREVOR_BOOK)
|
|
Script_Cleanup()
|
|
|
|
ENDPROC
|
|
/// PURPOSE:
|
|
/// Delete every entity from the world
|
|
PROC DeleteEverything()
|
|
|
|
// Killing any convo since we're going to delete Mary Ann now
|
|
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
|
|
KILL_ANY_CONVERSATION()
|
|
ENDIF
|
|
|
|
|
|
SAFE_DELETE_PED(sRCLauncherDataLocal.pedID[MARY_ANN_ID])
|
|
|
|
SAFE_DELETE_PED(piJogger1)
|
|
|
|
SAFE_DELETE_PED(piJogger2)
|
|
|
|
SAFE_DELETE_PED(piDriver)
|
|
|
|
SAFE_DELETE_VEHICLE(viDriver)
|
|
|
|
SAFE_DELETE_PED(piCyclist)
|
|
|
|
SAFE_DELETE_VEHICLE(viCyclist)
|
|
|
|
SAFE_DELETE_VEHICLE(vehBike[MARY_ANN_BIKE_ID])
|
|
|
|
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Main mission failed fade state
|
|
PROC MS_FAILED()
|
|
|
|
SWITCH iFailStage
|
|
CASE 0
|
|
RCM_REMOVE_ALL_BLIPS()
|
|
RCM_REMOVE_RACE_BLIPS()
|
|
|
|
RCM_STOP_ANY_ACTIVE_CONVERSATION()
|
|
|
|
CLEAR_PRINTS()
|
|
|
|
// set if there is any fail dialogue to play
|
|
bDoneFailDialogue = TRUE
|
|
IF failedReason = FAILED_WOMAN_SCARED
|
|
bDoneFailDialogue = FALSE
|
|
ENDIF
|
|
STRING sFailReason
|
|
|
|
SWITCH failedReason
|
|
CASE FAILED_GENERIC
|
|
RCM_DEBUG_PRINT("MISSION_FAILED reason=FAILED_GENERIC")
|
|
BREAK
|
|
CASE FAILED_BIKE_DESTROYED
|
|
sFailReason = "FAN2_F1" // ~r~The bike was destroyed.
|
|
RCM_DEBUG_PRINT("MISSION_FAILED reason=FAILED_BIKE_DESTROYED")
|
|
BREAK
|
|
CASE FAILED_LEFT_BEHIND
|
|
sFailReason = "FAN2_F2" // ~r~You fell too far behind.
|
|
RCM_DEBUG_PRINT("MISSION_FAILED reason=FAILED_OUT_OF_TIME")
|
|
BREAK
|
|
CASE FAILED_WOMAN_DIED
|
|
sFailReason = "FAN2_F3" // ~r~Mary Ann died.
|
|
RCM_DEBUG_PRINT("MISSION_FAILED reason=FAILED_WOMAN_DIED")
|
|
BREAK
|
|
CASE FAILED_WOMAN_HURT
|
|
sFailReason = "FAN2_F4" // ~r~Mary Ann was hurt.
|
|
RCM_DEBUG_PRINT("MISSION_FAILED reason=FAILED_WOMAN_HURT")
|
|
BREAK
|
|
CASE FAILED_WOMAN_SCARED
|
|
sFailReason = "FAN2_F5" // ~r~Mary Ann was scared off.
|
|
RCM_DEBUG_PRINT("MISSION_FAILED reason=FAILED_WOMAN_SCARED")
|
|
BREAK
|
|
CASE FAILED_LEFT_BIKE
|
|
sFailReason = "FAN2_F6" // ~r~You wandered too far from the bike.
|
|
RCM_STOP_ANY_ACTIVE_CONVERSATION()
|
|
RCM_DEBUG_PRINT("MISSION_FAILED reason=FAILED_LEFT_BIKE")
|
|
BREAK
|
|
CASE FAILED_PUSHED_WOMAN
|
|
sFailReason = "FAN2_F7" // ~r~You pushed Mary Ann.
|
|
RCM_STOP_ANY_ACTIVE_CONVERSATION()
|
|
RCM_DEBUG_PRINT("MISSION_FAILED reason=FAILED_PUSHED_WOMAN")
|
|
BREAK
|
|
CASE FAILED_LOST_RACE
|
|
sFailReason = "FAN2_F8" // ~r~You lost the race.
|
|
RCM_STOP_ANY_ACTIVE_CONVERSATION()
|
|
RCM_DEBUG_PRINT("MISSION_FAILED reason=FAILED_LOST_RACE")
|
|
BREAK
|
|
CASE FAILED_ABANDONED
|
|
sFailReason = "FAN2_F9" // ~r~You abandoned the race.
|
|
RCM_STOP_ANY_ACTIVE_CONVERSATION()
|
|
RCM_DEBUG_PRINT("MISSION_FAILED reason=FAILED_ABANDONED_RACE")
|
|
BREAK
|
|
CASE FAILED_MISSED_CHECK
|
|
sFailReason = "FAN2_F10" // ~r~A checkpoint was missed.
|
|
RCM_STOP_ANY_ACTIVE_CONVERSATION()
|
|
RCM_DEBUG_PRINT("MISSION_FAILED reason=FAILED_ABANDONED_RACE")
|
|
BREAK
|
|
ENDSWITCH
|
|
|
|
IF failedReason = 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(<< 822.7919, 1278.0978, 359.4304 >>, 105.0195)
|
|
//SET_REPLAY_DECLINED_VEHICLE_WARP_LOCATION(<<823.432, 1280.526, 359.923>>, -90.133)
|
|
|
|
|
|
DeleteEverything()
|
|
|
|
Script_Cleanup()
|
|
ELSE
|
|
// not finished fading out
|
|
// you may want to handle dialogue etc here.
|
|
IF bDoneFailDialogue = FALSE
|
|
IF failedReason = FAILED_WOMAN_SCARED
|
|
bDoneFailDialogue = CREATE_CONVERSATION(sWomanConversation, "FAN2AU", "FAN2_SCARED", CONV_PRIORITY_HIGH, DO_NOT_DISPLAY_SUBTITLES)
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
//PURPOSE: Mission is failed.
|
|
PROC RCM_MISSION_FAILED(FAILED_REASON reason = FAILED_GENERIC)
|
|
|
|
TRIGGER_MUSIC_EVENT("FANATIC2_FAIL")
|
|
failedReason = reason
|
|
missionStage = stateMissionFailed
|
|
|
|
ENDPROC
|
|
|
|
//PURPOSE: Set up mission prior to going into any mission states
|
|
PROC RCM_MISSION_SETUP()
|
|
|
|
RCM_DEBUG_PRINT("MISSION_SETUP")
|
|
REQUEST_ADDITIONAL_TEXT("FATIC2", MISSION_TEXT_SLOT)
|
|
WHILE NOT HAS_ADDITIONAL_TEXT_LOADED(MISSION_TEXT_SLOT)
|
|
RCM_DEBUG_PRINT("Loading text")
|
|
WAIT(0)
|
|
ENDWHILE
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
mSkipMenu[0].sTxtLabel = "Intro"
|
|
mSkipMenu[1].sTxtLabel = "Race start"
|
|
mSkipMenu[2].sTxtLabel = "Skip to checkpoint 11"
|
|
mSkipMenu[3].sTxtLabel = "Skip to checkpoint 22"
|
|
mSkipMenu[4].sTxtLabel = "End race"
|
|
#ENDIF
|
|
|
|
bStartedCyclist = FALSE
|
|
|
|
modelPlayerBike = SCORCHER
|
|
|
|
sRoadRageConversationString[0] = "FAN2_RANT1"
|
|
sRoadRageConversationString[1] = "FAN2_RANT2"
|
|
sRoadRageConversationString[2] = "FAN2_RANT3"
|
|
sRoadRageConversationString[3] = "FAN2_RANT4"
|
|
sRoadRageConversationString[4] = "FAN2_RANT5"
|
|
sWomanConversationString[0] = "FAN2_FEM1"
|
|
|
|
// There's not normally enough time to play the 4th conversation - so swap the order of FEM3 and FEM4 around if it's a replay so there's a chance to hear FEM4
|
|
IF IS_REPLAY_IN_PROGRESS()
|
|
IF IS_OUTFIT_SUITABLE_FOR_FANATIC_MISSION(2)
|
|
sWomanConversationString[2] = "FAN2_FEM4B"
|
|
ELSE
|
|
sWomanConversationString[2] = "FAN2_FEM4A"
|
|
ENDIF
|
|
sWomanConversationString[3] = "FAN2_FEM3"
|
|
ELSE
|
|
IF IS_OUTFIT_SUITABLE_FOR_FANATIC_MISSION(2)
|
|
sWomanConversationString[3] = "FAN2_FEM4B"
|
|
ELSE
|
|
sWomanConversationString[3] = "FAN2_FEM4A"
|
|
ENDIF
|
|
sWomanConversationString[2] = "FAN2_FEM3"
|
|
ENDIF
|
|
|
|
// Set up specific dialogue if the player's in the right outfit
|
|
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
|
|
IF IS_OUTFIT_SUITABLE_FOR_FANATIC_MISSION(2)
|
|
sWomanConversationString[1] = "FAN2_FEM2B"
|
|
ELSE
|
|
sWomanConversationString[1] = "FAN2_FEM2A"
|
|
ENDIF
|
|
ENDIF
|
|
|
|
vLongRaceStart[0] = << 808.8217, 1276.9392, 359.4989 >>
|
|
fLongRaceStart[0] = 261.78
|
|
vLongRaceStart[1] = << 820.96, 1274.52, 359.47 >>
|
|
fLongRaceStart[1] = 268.5713
|
|
|
|
vLongRaceEnd[0] = << 280.9698, 948.4752, 209.7963 >>
|
|
fLongRaceEnd[0] = 167.6198
|
|
vLongRaceEnd[1] = << 284.93, 968.38, 210.09 >>
|
|
fLongRaceEnd[1] = 167.6198
|
|
|
|
SET_ROADS_IN_ANGLED_AREA(<<864.302063,1274.851807,361.473602>>, <<393.978210,1197.083862,224.314072>>, 176.0, FALSE, FALSE)
|
|
sbiDeerArea = ADD_SCENARIO_BLOCKING_AREA(<<379.31, 1017.51, 218.82>>, <<419.57, 1062.59, 247.17>>)
|
|
|
|
RCM_DEBUG_PRINT("Finished mission setup.")
|
|
|
|
ENDPROC
|
|
|
|
//PURPOSE: Check if all the assets for the required mission stage have been loaded.
|
|
FUNC BOOL HAVE_ASSETS_FOR_MISSION_STAGE_LOADED(MISSION_STAGE currentStage)
|
|
|
|
BOOL bAssetsLoaded = FALSE
|
|
|
|
SWITCH currentStage
|
|
|
|
CASE stateIntro
|
|
REQUEST_MODEL(modelPlayerBike)
|
|
REQUEST_MODEL(cyclistModel)
|
|
IF HAS_MODEL_LOADED(modelPlayerBike)
|
|
AND HAS_MODEL_LOADED(cyclistModel)
|
|
RCM_DEBUG_PRINT("All assets loaded.")
|
|
bAssetsLoaded = TRUE
|
|
ELSE
|
|
RCM_DEBUG_PRINT("Still loading assets.")
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE stateCountdown
|
|
REQUEST_MODEL(modelPlayerBike)
|
|
REQUEST_MODEL(TRIBIKE)
|
|
REQUEST_MODEL(S_M_Y_Cop_01)
|
|
REQUEST_MODEL(A_F_Y_Runner_01)
|
|
REQUEST_MODEL(A_M_Y_Runner_01)
|
|
REQUEST_WAYPOINT_RECORDING("Fan2_BikeRoute")
|
|
REQUEST_VEHICLE_RECORDING(500, "Fan2_Cyclist")
|
|
REQUEST_WAYPOINT_RECORDING("Fan2_Jogger1")
|
|
REQUEST_WAYPOINT_RECORDING("Fan2_Jogger2")
|
|
REQUEST_ANIM_DICT("rcm_fanatic2")
|
|
REQUEST_ANIM_DICT("rcmfanatic2")
|
|
|
|
IF HAS_VEHICLE_RECORDING_BEEN_LOADED(500, "Fan2_Cyclist")
|
|
AND GET_IS_WAYPOINT_RECORDING_LOADED("Fan2_BikeRoute")
|
|
AND GET_IS_WAYPOINT_RECORDING_LOADED("Fan2_Jogger1")
|
|
AND GET_IS_WAYPOINT_RECORDING_LOADED("Fan2_Jogger2")
|
|
and HAS_MODEL_LOADED(modelPlayerBike)
|
|
and HAS_MODEL_LOADED(TRIBIKE)
|
|
and HAS_MODEL_LOADED(S_M_Y_Cop_01)
|
|
and HAS_MODEL_LOADED(A_F_Y_Runner_01)
|
|
and HAS_MODEL_LOADED(A_M_Y_Runner_01)
|
|
AND HAS_ANIM_DICT_LOADED("rcm_fanatic2")
|
|
AND HAS_ANIM_DICT_LOADED("rcmfanatic2")
|
|
bAssetsLoaded = TRUE
|
|
ELSE
|
|
RCM_DEBUG_PRINT("Still loading assets.")
|
|
ENDIF
|
|
BREAK
|
|
|
|
ENDSWITCH
|
|
|
|
RETURN bAssetsLoaded
|
|
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Jump to a particular point during the race
|
|
/// PARAMS:
|
|
/// iStage - The stage of the race we wish to jump to
|
|
PROC JUMP_TO_STAGE(int iStage)
|
|
RC_START_Z_SKIP()
|
|
RCM_DEBUG_PRINTINT("Jumping to stage: ", iStage)
|
|
RecoverState = RECOVER_WAIT // Reset just in case
|
|
IF iStage = 0
|
|
playerInfo.raceVehicle = vehBike[PLAYER_BIKE_ID]
|
|
playerInfo.racer = PLAYER_PED_ID()
|
|
playerInfo.currentCheck = 1
|
|
playerInfo.nextCheck = 2
|
|
missionStageSkip = stateInit
|
|
IF IS_ENTITY_ALIVE(vehBike[MARY_ANN_BIKE_ID])
|
|
AND IS_ENTITY_ALIVE(sRCLauncherDataLocal.pedID[MARY_ANN_ID])
|
|
IF IS_WAYPOINT_PLAYBACK_GOING_ON_FOR_VEHICLE(vehBike[MARY_ANN_BIKE_ID])
|
|
CLEAR_PED_TASKS(sRCLauncherDataLocal.pedID[MARY_ANN_ID])
|
|
ENDIF
|
|
ENDIF
|
|
TRIGGER_MUSIC_EVENT("FANATIC2_STOP")
|
|
RCM_DEBUG_PRINT("Doing music trigger stop")
|
|
IF IS_AUDIO_SCENE_ACTIVE("FANATIC_MIX_SCENE")
|
|
REMOVE_ENTITY_FROM_AUDIO_MIX_GROUP(vehBike[MARY_ANN_BIKE_ID])
|
|
STOP_AUDIO_SCENE("FANATIC_MIX_SCENE")
|
|
ENDIF
|
|
RCM_DEBUG_PRINT("Reset bikes from JUMP_TO_STAGE(0)")
|
|
RCM_RESET_CONVERSATIONS()
|
|
RESET_BIKES()
|
|
SET_PLAYER_CHECKPOINTS_AND_BLIPS(playerInfo, raceInfo)
|
|
bStartedCyclist = FALSE
|
|
bDoBikeExit = FALSE
|
|
RCM_ADVANCE_STAGE()
|
|
ELIF iStage = 1
|
|
RCM_DEBUG_PRINT("Reset bikes from JUMP_TO_STAGE(1)")
|
|
RESET_BIKES()
|
|
raceInfo.sourcePos = vLongRaceStart[0]
|
|
raceInfo.sourceHeading = fLongRaceStart[0]
|
|
playerInfo.raceVehicle = vehBike[PLAYER_BIKE_ID]
|
|
playerInfo.racer = PLAYER_PED_ID()
|
|
playerInfo.currentCheck = 1
|
|
playerInfo.nextCheck = 2
|
|
missionStageSkip = stateCountdown
|
|
WHILE NOT HAVE_ASSETS_FOR_MISSION_STAGE_LOADED(stateCountdown)
|
|
WAIT(0) //Load in race assets now before skipping ahead
|
|
ENDWHILE
|
|
WHILE IS_CUTSCENE_ACTIVE()
|
|
STOP_CUTSCENE()
|
|
WAIT(0)
|
|
ENDWHILE
|
|
IF NOT IS_PED_IN_VEHICLE(PLAYER_PED_ID(), vehBike[PLAYER_BIKE_ID])
|
|
RCM_DEBUG_PRINT("Putting Trevor on bike...")
|
|
SET_PED_INTO_VEHICLE(PLAYER_PED_ID(), vehBike[PLAYER_BIKE_ID])
|
|
ENDIF
|
|
RCM_PLACE_KNOCKED_OUT_FRIEND()
|
|
RCM_RESET_CONVERSATIONS()
|
|
IF IS_ENTITY_ALIVE(vehBike[MARY_ANN_BIKE_ID])
|
|
AND IS_ENTITY_ALIVE(sRCLauncherDataLocal.pedID[MARY_ANN_ID])
|
|
RESET_MARY_ANN()
|
|
ENDIF
|
|
SET_PLAYER_CHECKPOINTS_AND_BLIPS(playerInfo, raceInfo)
|
|
bStartedCyclist = FALSE
|
|
RCM_ADVANCE_STAGE()
|
|
ELIF iStage = 2
|
|
playerInfo.raceVehicle = vehBike[PLAYER_BIKE_ID]
|
|
playerInfo.racer = PLAYER_PED_ID()
|
|
playerInfo.currentCheck = 11
|
|
playerInfo.nextCheck = 12
|
|
WHILE NOT HAVE_ASSETS_FOR_MISSION_STAGE_LOADED(stateCountdown)
|
|
WAIT(0) //Load in race assets now before skipping ahead
|
|
ENDWHILE
|
|
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
|
|
SET_PED_COORDS_KEEP_VEHICLE(PLAYER_PED_ID(), << 438.3714, 1292.8068, 269.9339 >>)
|
|
SET_ENTITY_HEADING(PLAYER_PED_ID(), 24)
|
|
ENDIF
|
|
IF IS_VEHICLE_OK(vehBike[MARY_ANN_BIKE_ID])
|
|
AND IS_ENTITY_ALIVE(sRCLauncherDataLocal.pedID[MARY_ANN_ID])
|
|
IF NOT IS_PED_IN_VEHICLE(sRCLauncherDataLocal.pedID[MARY_ANN_ID], vehBike[MARY_ANN_BIKE_ID])
|
|
SET_PED_INTO_VEHICLE(sRCLauncherDataLocal.pedID[MARY_ANN_ID], vehBike[MARY_ANN_BIKE_ID])
|
|
ENDIF
|
|
SET_PED_COORDS_KEEP_VEHICLE(sRCLauncherDataLocal.pedID[MARY_ANN_ID], << 449.6093, 1261.4745, 272.4526 >>)
|
|
SET_ENTITY_HEADING(sRCLauncherDataLocal.pedID[MARY_ANN_ID], 13.4976)
|
|
IF NOT IS_PLAYBACK_GOING_ON_FOR_VEHICLE(vehBike[MARY_ANN_BIKE_ID])
|
|
TASK_VEHICLE_FOLLOW_WAYPOINT_RECORDING(sRCLauncherDataLocal.pedID[MARY_ANN_ID], vehBike[MARY_ANN_BIKE_ID], "Fan2_BikeRoute", DRIVINGMODE_AVOIDCARS_RECKLESS,
|
|
0, EWAYPOINT_START_FROM_CLOSEST_POINT)
|
|
ENDIF
|
|
ENDIF
|
|
RCM_CLEANUP_CONVERSATIONS()
|
|
SET_PLAYER_CHECKPOINTS_AND_BLIPS(playerInfo, raceInfo)
|
|
bStartedCyclist = FALSE
|
|
iWomanNextCheckpoint = 12
|
|
ELIF iStage = 3
|
|
playerInfo.raceVehicle = vehBike[PLAYER_BIKE_ID]
|
|
playerInfo.racer = PLAYER_PED_ID()
|
|
playerInfo.currentCheck = 22
|
|
playerInfo.nextCheck = 23
|
|
WHILE NOT HAVE_ASSETS_FOR_MISSION_STAGE_LOADED(stateCountdown)
|
|
WAIT(0) //Load in race assets now before skipping ahead
|
|
ENDWHILE
|
|
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
|
|
SET_PED_COORDS_KEEP_VEHICLE(PLAYER_PED_ID(), << 272.8283, 1261.0051, 232.5672 >>)
|
|
SET_ENTITY_HEADING(PLAYER_PED_ID(), 122.43)
|
|
ENDIF
|
|
IF IS_VEHICLE_OK(vehBike[MARY_ANN_BIKE_ID])
|
|
AND IS_ENTITY_ALIVE(sRCLauncherDataLocal.pedID[MARY_ANN_ID])
|
|
IF NOT IS_PED_IN_VEHICLE(sRCLauncherDataLocal.pedID[MARY_ANN_ID], vehBike[MARY_ANN_BIKE_ID])
|
|
SET_PED_INTO_VEHICLE(sRCLauncherDataLocal.pedID[MARY_ANN_ID], vehBike[MARY_ANN_BIKE_ID])
|
|
ENDIF
|
|
SET_PED_COORDS_KEEP_VEHICLE(sRCLauncherDataLocal.pedID[MARY_ANN_ID], << 295.4509, 1244.0754, 233.5478 >>)
|
|
SET_ENTITY_HEADING(sRCLauncherDataLocal.pedID[MARY_ANN_ID], 43.0307)
|
|
IF NOT IS_PLAYBACK_GOING_ON_FOR_VEHICLE(vehBike[MARY_ANN_BIKE_ID])
|
|
TASK_VEHICLE_FOLLOW_WAYPOINT_RECORDING(sRCLauncherDataLocal.pedID[MARY_ANN_ID], vehBike[MARY_ANN_BIKE_ID], "Fan2_BikeRoute", DRIVINGMODE_AVOIDCARS_RECKLESS,
|
|
0, EWAYPOINT_START_FROM_CLOSEST_POINT)
|
|
ENDIF
|
|
ENDIF
|
|
RCM_CLEANUP_CONVERSATIONS()
|
|
SET_PLAYER_CHECKPOINTS_AND_BLIPS(playerInfo, raceInfo)
|
|
iWomanNextCheckpoint = 23
|
|
ELIF iStage = 4
|
|
IF IS_ENTITY_ALIVE(vehBike[MARY_ANN_BIKE_ID])
|
|
IF IS_WAYPOINT_PLAYBACK_GOING_ON_FOR_VEHICLE(vehBike[MARY_ANN_BIKE_ID])
|
|
CLEAR_PED_TASKS(sRCLauncherDataLocal.pedID[MARY_ANN_ID])
|
|
ENDIF
|
|
ENDIF
|
|
|
|
INT i
|
|
REPEAT NUM_BIKES i
|
|
IF IS_VEHICLE_OK(vehBike[i])
|
|
SET_ENTITY_COORDS(vehBike[i], vLongRaceEnd[i])
|
|
SET_ENTITY_HEADING(vehBike[i], fLongRaceEnd[i])
|
|
SET_VEHICLE_ON_GROUND_PROPERLY(vehBike[i])
|
|
RCM_DEBUG_PRINTINT("Bike exists, set coords/heading: ", i)
|
|
ELSE
|
|
RCM_SPAWN_VEHICLE(vehBike[i], modelPlayerBike, vLongRaceEnd[i], fLongRaceEnd[i], i)
|
|
SET_VEHICLE_ON_GROUND_PROPERLY(vehBike[i])
|
|
RCM_DEBUG_PRINTINT("Bike doesn't exist, recreate: ", i)
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
|
|
AND IS_VEHICLE_OK(vehBike[PLAYER_BIKE_ID])
|
|
IF NOT IS_PED_IN_VEHICLE(PLAYER_PED_ID(), vehBike[PLAYER_BIKE_ID])
|
|
SET_PED_INTO_VEHICLE(PLAYER_PED_ID(), vehBike[PLAYER_BIKE_ID])
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF IS_VEHICLE_OK(vehBike[MARY_ANN_BIKE_ID])
|
|
AND IS_ENTITY_ALIVE(sRCLauncherDataLocal.pedID[MARY_ANN_ID])
|
|
CLEAR_PED_TASKS(sRCLauncherDataLocal.pedID[MARY_ANN_ID])
|
|
IF NOT IS_PED_IN_VEHICLE(sRCLauncherDataLocal.pedID[MARY_ANN_ID], vehBike[MARY_ANN_BIKE_ID])
|
|
SET_PED_INTO_VEHICLE(sRCLauncherDataLocal.pedID[MARY_ANN_ID], vehBike[MARY_ANN_BIKE_ID])
|
|
ENDIF
|
|
ENDIF
|
|
|
|
missionStageSkip = stateOutro
|
|
bSkipToEnd = TRUE
|
|
|
|
WAIT(1000)
|
|
|
|
RCM_ADVANCE_STAGE()
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
//PURPOSE: Deal with stage skipping forwards to a later point in the race.
|
|
PROC Script_SkipStageForward()
|
|
|
|
SWITCH missionStage
|
|
|
|
CASE stateIntro
|
|
WHILE IS_CUTSCENE_ACTIVE()
|
|
STOP_CUTSCENE()
|
|
WAIT(0)
|
|
ENDWHILE
|
|
JUMP_TO_STAGE(1)
|
|
BREAK
|
|
CASE stateRace
|
|
IF playerInfo.currentCheck < 11
|
|
JUMP_TO_STAGE(2)
|
|
ELIF playerInfo.currentCheck < 22
|
|
JUMP_TO_STAGE(3)
|
|
ELSE
|
|
JUMP_TO_STAGE(4)
|
|
ENDIF
|
|
BREAK
|
|
|
|
ENDSWITCH
|
|
|
|
ENDPROC
|
|
|
|
//PURPOSE: Deal with stage skipping back to an earlier point in the race.
|
|
PROC Script_SkipStageBack()
|
|
|
|
SWITCH missionStage
|
|
|
|
CASE stateRace
|
|
IF playerInfo.currentCheck > 23
|
|
JUMP_TO_STAGE(3)
|
|
ELIF playerInfo.currentCheck > 12
|
|
JUMP_TO_STAGE(2)
|
|
ELIF playerInfo.currentCheck > 2
|
|
JUMP_TO_STAGE(1)
|
|
ELSE
|
|
JUMP_TO_STAGE(0)
|
|
ENDIF
|
|
BREAK
|
|
|
|
ENDSWITCH
|
|
|
|
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
|
|
|
|
//PURPOSE: Death checks for any mission critical entities.
|
|
PROC RCM_DEATH_CHECKS()
|
|
|
|
IF missionStage = stateRace
|
|
IF NOT IS_VEHICLE_OK(vehBike[PLAYER_BIKE_ID])
|
|
RCM_MISSION_FAILED(FAILED_BIKE_DESTROYED)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF NOT bReleaseMAEarly
|
|
// If the player wins by a large margin, we delete Mary Ann from the mission to simulate her being so far away she's just given up
|
|
// If we do that, we set this bool to true so the mission doesn't fail for Mary Ann being "dead" while Trevor's line is playing
|
|
IF NOT IS_ENTITY_ALIVE(sRCLauncherDataLocal.pedID[MARY_ANN_ID])
|
|
RCM_MISSION_FAILED(FAILED_WOMAN_DIED)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF IS_ENTITY_ALIVE(sRCLauncherDataLocal.pedID[MARY_ANN_ID])
|
|
IF HAS_ENTITY_BEEN_DAMAGED_BY_ENTITY(sRCLauncherDataLocal.pedID[MARY_ANN_ID], PLAYER_PED_ID())
|
|
IF HAS_PED_BEEN_DAMAGED_BY_WEAPON(sRCLauncherDataLocal.pedID[MARY_ANN_ID], WEAPONTYPE_INVALID, GENERALWEAPON_TYPE_ANYWEAPON)
|
|
if HAS_PLAYER_THREATENED_PED(piJogger1) OR HAS_PLAYER_THREATENED_PED(piJogger2)
|
|
IF IS_PED_UNINJURED(piJogger1) AND IS_PED_UNINJURED(piJogger2)
|
|
TASK_SMART_FLEE_PED(piJogger1, PLAYER_PED_ID(), 100, -1)
|
|
TASK_SMART_FLEE_PED(piJogger2, PLAYER_PED_ID(), 100, -1)
|
|
ENDIF
|
|
SAFE_RELEASE_PED(piJogger1)
|
|
SAFE_RELEASE_PED(piJogger2)
|
|
ENDIF
|
|
RCM_MISSION_FAILED(FAILED_WOMAN_HURT)
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
if IS_PLAYER_SHOOTING_NEAR_PED(sRCLauncherDataLocal.pedID[MARY_ANN_ID])
|
|
//CLEAR_PED_TASKS_IMMEDIATELY(sRCLauncherDataLocal.pedID[MARY_ANN_ID])
|
|
SET_PED_KEEP_TASK(sRCLauncherDataLocal.pedID[MARY_ANN_ID], true)
|
|
SET_PED_FLEE_ATTRIBUTES(sRCLauncherDataLocal.pedID[MARY_ANN_ID], FA_USE_VEHICLE, TRUE)
|
|
TASK_SMART_FLEE_PED(sRCLauncherDataLocal.pedID[MARY_ANN_ID], PLAYER_PED_ID(), 100, -1)
|
|
if HAS_PLAYER_THREATENED_PED(piJogger1) OR HAS_PLAYER_THREATENED_PED(piJogger2)
|
|
IF IS_PED_UNINJURED(piJogger1) AND IS_PED_UNINJURED(piJogger2)
|
|
TASK_SMART_FLEE_PED(piJogger1, PLAYER_PED_ID(), 100, -1)
|
|
TASK_SMART_FLEE_PED(piJogger2, PLAYER_PED_ID(), 100, -1)
|
|
ENDIF
|
|
SAFE_RELEASE_PED(piJogger1)
|
|
SAFE_RELEASE_PED(piJogger2)
|
|
ENDIF
|
|
RCM_MISSION_FAILED(FAILED_WOMAN_SCARED)
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
//PURPOSE: Check for Forced Pass or Fail
|
|
PROC DEBUG_Check_Debug_Keys()
|
|
#IF IS_DEBUG_BUILD
|
|
IF missionStage <> stateMissionFailed
|
|
// Check for Pass
|
|
IF (IS_KEYBOARD_KEY_JUST_PRESSED(KEY_S))
|
|
WAIT_FOR_CUTSCENE_TO_STOP()
|
|
CLEAR_PRINTS()
|
|
TRIGGER_MUSIC_EVENT("FANATIC2_STOP")
|
|
RCM_DEBUG_PRINT("Doing music trigger stop")
|
|
Script_Passed()
|
|
ENDIF
|
|
|
|
// Check for Fail
|
|
IF (IS_KEYBOARD_KEY_JUST_PRESSED(KEY_F))
|
|
WAIT_FOR_CUTSCENE_TO_STOP()
|
|
CLEAR_PRINTS()
|
|
RCM_MISSION_FAILED()
|
|
ENDIF
|
|
|
|
// Check for Skips
|
|
IF (IS_KEYBOARD_KEY_JUST_PRESSED(KEY_J))
|
|
IF bAllowDebugSkipForward = TRUE
|
|
bUsedSkip = TRUE
|
|
bUsedCheckpoints = TRUE
|
|
Script_SkipStageForward()
|
|
ENDIF
|
|
ENDIF
|
|
IF (IS_KEYBOARD_KEY_JUST_PRESSED(KEY_P))
|
|
bUsedSkip = TRUE
|
|
bUsedCheckpoints = TRUE
|
|
bPlayedFinalConv = FALSE
|
|
Script_SkipStageBack()
|
|
ENDIF
|
|
|
|
INT iNewStage
|
|
IF LAUNCH_MISSION_STAGE_MENU(mSkipMenu, iNewStage)
|
|
bUsedSkip = TRUE
|
|
bUsedCheckpoints = TRUE
|
|
RCM_DEBUG_PRINT("Doing z-skip!")
|
|
JUMP_TO_STAGE(iNewStage)
|
|
ENDIF
|
|
ENDIF
|
|
#ENDIF
|
|
|
|
ENDPROC
|
|
|
|
|
|
/// PURPOSE:
|
|
/// Run the intro cutscene
|
|
PROC RUN_CUTSCENE()
|
|
IF IS_ENTITY_ALIVE(sRCLauncherDataLocal.pedID[MARY_ANN_ID])
|
|
REGISTER_ENTITY_FOR_CUTSCENE(sRCLauncherDataLocal.pedID[MARY_ANN_ID], "Mary_Ann", CU_ANIMATE_EXISTING_SCRIPT_ENTITY)
|
|
//SET_PED_COMPONENT_VARIATION(sRCLauncherDataLocal.pedID[MARY_ANN_ID], INT_TO_ENUM(PED_COMPONENT, 4), 1, 0)
|
|
ENDIF
|
|
IF IS_ENTITY_ALIVE(sRCLauncherDataLocal.pedID[MARY_ANN_FRIEND_ID])
|
|
REGISTER_ENTITY_FOR_CUTSCENE(sRCLauncherDataLocal.pedID[MARY_ANN_FRIEND_ID], "MaryAnnes_Friend", CU_ANIMATE_EXISTING_SCRIPT_ENTITY, A_M_Y_CYCLIST_01)
|
|
ELSE
|
|
sRCLauncherDataLocal.pedID[MARY_ANN_FRIEND_ID] = CREATE_PED(PEDTYPE_MISSION, cyclistModel, <<808.43, 1279.16, 360.48>>, -79.11)
|
|
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(sRCLauncherDataLocal.pedID[MARY_ANN_FRIEND_ID], TRUE)
|
|
SET_PED_COMPONENT_VARIATION(sRCLauncherDataLocal.pedID[MARY_ANN_FRIEND_ID], PED_COMP_TORSO, 1, 2)
|
|
SET_PED_COMPONENT_VARIATION(sRCLauncherDataLocal.pedID[MARY_ANN_FRIEND_ID], PED_COMP_LEG, 1, 0)
|
|
SET_PED_PROP_INDEX(sRCLauncherDataLocal.pedID[MARY_ANN_FRIEND_ID], ANCHOR_HEAD, 0)
|
|
REGISTER_ENTITY_FOR_CUTSCENE(sRCLauncherDataLocal.pedID[MARY_ANN_FRIEND_ID], "MaryAnnes_Friend", CU_ANIMATE_EXISTING_SCRIPT_ENTITY, A_M_Y_CYCLIST_01)
|
|
ENDIF
|
|
|
|
IF DOES_OBJECT_OF_TYPE_EXIST_AT_COORDS(<<801.714844,1270.138306,359.285522>>, 6.0, prop_facgate_03_l)
|
|
SET_STATE_OF_CLOSEST_DOOR_OF_TYPE(prop_facgate_03_l, <<801.714844,1270.138306,359.285522>>, TRUE, 0.0)
|
|
RCM_DEBUG_PRINT("Fanatic2: Gate 1 Closed")
|
|
ENDIF
|
|
|
|
IF DOES_OBJECT_OF_TYPE_EXIST_AT_COORDS(<<802.919495, 1280.919678, 360.727234>>, 6.0, prop_facgate_03_r)
|
|
SET_STATE_OF_CLOSEST_DOOR_OF_TYPE(prop_facgate_03_r, <<802.919495, 1280.919678, 360.727234>>, TRUE, 0.0)
|
|
RCM_DEBUG_PRINT("Fanatic2:Gate 2 Closed")
|
|
ENDIF
|
|
|
|
// Clear area here instead of mission init, otherwise taxi might get cleared (B*1980643)
|
|
CLEAR_ANGLED_AREA_OF_VEHICLES(<<864.302063,1274.851807,361.473602>>, <<393.978210,1197.083862,224.314072>>, 176.0)
|
|
CLEAR_ANGLED_AREA_OF_VEHICLES(<<878.295532,1291.727783,355.536591>>, <<817.823486,1271.438599,362.973633>>, 12.75)
|
|
|
|
INT i = 0
|
|
REPEAT NUM_BIKES i
|
|
RCM_SPAWN_VEHICLE(vehBike[i], modelPlayerBike, vLongRaceStart[i], fLongRaceStart[i], i)
|
|
IF IS_VEHICLE_OK(vehBike[i])
|
|
IF i = 0
|
|
// SET_ENTITY_COORDS(vehBike[PLAYER_BIKE_ID], <<808.35, 1277.20, 360.15>>)
|
|
// SET_ENTITY_HEADING(vehBike[PLAYER_BIKE_ID], 216.50)
|
|
// SET_VEHICLE_ON_GROUND_PROPERLY(vehBike[PLAYER_BIKE_ID])
|
|
REGISTER_ENTITY_FOR_CUTSCENE(vehBike[PLAYER_BIKE_ID], "Players_Bike", CU_ANIMATE_EXISTING_SCRIPT_ENTITY, DUMMY_MODEL_FOR_SCRIPT, CEO_IS_CASCADE_SHADOW_FOCUS_ENTITY_DURING_EXIT)
|
|
ELSE
|
|
// SET_ENTITY_COORDS(vehBike[MARY_ANN_BIKE_ID], <<807.89, 1275.73, 360.18>>)
|
|
// SET_ENTITY_HEADING(vehBike[MARY_ANN_BIKE_ID], 208.20)
|
|
// SET_VEHICLE_ON_GROUND_PROPERLY(vehBike[MARY_ANN_BIKE_ID])
|
|
REGISTER_ENTITY_FOR_CUTSCENE(vehBike[MARY_ANN_BIKE_ID], "MaryAnnes_Bike", CU_ANIMATE_EXISTING_SCRIPT_ENTITY)
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
bIntroSkipped = FALSE // Reset tracking bool
|
|
RC_CLEANUP_LAUNCHER()
|
|
START_CUTSCENE(CUTSCENE_PLAYER_EXITS_IN_A_VEHICLE)
|
|
SET_VEHICLE_MODEL_PLAYER_WILL_EXIT_SCENE(modelPlayerBike)
|
|
WAIT(0)
|
|
RESOLVE_VEHICLES_INSIDE_ANGLED_AREA_WITH_SIZE_LIMIT(<<803.136292,1275.784546,357.813049>>, <<862.741150,1287.390747,365.551422>>, 40.75,
|
|
<< 836.74, 1284.85, 359.59 >>, 102.86, GET_DEFAULT_ALLOWABLE_VEHICLE_SIZE_VECTOR())
|
|
RC_START_CUTSCENE_MODE(<< 807.57, 1275.24, 359.47 >>, TRUE, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT)
|
|
RCM_DEBUG_PRINT("Starting cutscene...")
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Main initialisation stage for the mission
|
|
PROC MS_INIT()
|
|
|
|
IF RCM_INIT_STAGE()
|
|
|
|
RCM_DEBUG_PRINT("Init MS_INIT")
|
|
#IF IS_DEBUG_BUILD
|
|
IF NOT DOES_WIDGET_GROUP_EXIST(widgetGroup)
|
|
widgetGroup= START_WIDGET_GROUP("Fanatic 2 widgets")
|
|
ADD_WIDGET_BOOL("TTY Toggle - Print Mission Debug Info", bDebug_PrintToTTY)
|
|
ADD_WIDGET_BOOL("Opponent bike speed debug", bDebugPrintBikePlaybackSpeed)
|
|
STOP_WIDGET_GROUP()
|
|
ENDIF
|
|
#ENDIF
|
|
|
|
IF Is_Replay_In_Progress()
|
|
START_REPLAY_SETUP(<<815.2971, 1277.6364, 359.4897>>, 274.5829)
|
|
ELSE
|
|
IF NOT IS_GAMEPLAY_HINT_ACTIVE()
|
|
IF IS_ENTITY_ALIVE(sRCLauncherDataLocal.pedID[MARY_ANN_ID])
|
|
SET_GAMEPLAY_ENTITY_HINT(sRCLauncherDataLocal.pedID[MARY_ANN_ID], <<0,0,0>>, TRUE, 30000)
|
|
SET_GAMEPLAY_HINT_FOV(fHintFov)
|
|
SET_GAMEPLAY_HINT_FOLLOW_DISTANCE_SCALAR(fHintFollow)
|
|
SET_GAMEPLAY_HINT_BASE_ORBIT_PITCH_OFFSET(fHintPitchOrbit)
|
|
SET_GAMEPLAY_HINT_CAMERA_RELATIVE_SIDE_OFFSET(fHintSide)
|
|
SET_GAMEPLAY_HINT_CAMERA_RELATIVE_VERTICAL_OFFSET(fHintVert)
|
|
SET_GAMEPLAY_HINT_CAMERA_BLEND_TO_FOLLOW_PED_MEDIUM_VIEW_MODE(TRUE)
|
|
iPushInTimer = GET_GAME_TIMER()
|
|
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
|
|
TASK_FOLLOW_TO_OFFSET_OF_ENTITY(PLAYER_PED_ID(), sRCLauncherDataLocal.pedID[MARY_ANN_ID], <<0,0,0>>, PEDMOVEBLENDRATIO_WALK)
|
|
ENDIF
|
|
ENDIF
|
|
ELSE
|
|
STOP_GAMEPLAY_HINT_BEING_CANCELLED_THIS_UPDATE(TRUE)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF bDoneMissionSetup = FALSE
|
|
RCM_MISSION_SETUP()
|
|
ENDIF
|
|
WHILE NOT HAVE_ASSETS_FOR_MISSION_STAGE_LOADED(stateIntro)
|
|
WAIT(0)
|
|
ENDWHILE
|
|
|
|
IF IS_ENTITY_ALIVE(sRCLauncherDataLocal.pedID[MARY_ANN_ID])
|
|
SET_PED_RELATIONSHIP_GROUP_HASH(sRCLauncherDataLocal.pedID[MARY_ANN_ID], relGroupPlayer)
|
|
SET_PED_CONFIG_FLAG(sRCLauncherDataLocal.pedID[MARY_ANN_ID], PCF_KeepRelationshipGroupAfterCleanUp, TRUE)
|
|
ENDIF
|
|
|
|
ADD_PED_FOR_DIALOGUE(sRoadRageConversation, ENUM_TO_INT(CHAR_TREVOR), PLAYER_PED_ID(), "TREVOR")
|
|
ADD_PED_FOR_DIALOGUE(sWomanConversation, ENUM_TO_INT(CHAR_TREVOR), PLAYER_PED_ID(), "TREVOR")
|
|
ADD_PED_FOR_DIALOGUE(sWomanConversation, 3, sRCLauncherDataLocal.pedID[MARY_ANN_ID], "MARYANN")
|
|
ADD_PED_FOR_DIALOGUE(sOutroConversation, ENUM_TO_INT(CHAR_TREVOR), PLAYER_PED_ID(), "TREVOR")
|
|
ADD_PED_FOR_DIALOGUE(sOutroConversation, 3, sRCLauncherDataLocal.pedID[MARY_ANN_ID], "MARYANN")
|
|
|
|
RCM_DEBUG_PRINT("Running MS_INIT")
|
|
|
|
ELSE
|
|
|
|
IF NOT Is_Replay_In_Progress()
|
|
OR bUsedCheckpoints = TRUE
|
|
|
|
IF NOT IS_GAMEPLAY_HINT_ACTIVE()
|
|
IF IS_ENTITY_ALIVE(sRCLauncherDataLocal.pedID[MARY_ANN_ID])
|
|
SET_GAMEPLAY_ENTITY_HINT(sRCLauncherDataLocal.pedID[MARY_ANN_ID], <<0,0,0>>, TRUE, 30000)
|
|
SET_GAMEPLAY_HINT_FOV(fHintFov)
|
|
SET_GAMEPLAY_HINT_FOLLOW_DISTANCE_SCALAR(fHintFollow)
|
|
SET_GAMEPLAY_HINT_BASE_ORBIT_PITCH_OFFSET(fHintPitchOrbit)
|
|
SET_GAMEPLAY_HINT_CAMERA_RELATIVE_SIDE_OFFSET(fHintSide)
|
|
SET_GAMEPLAY_HINT_CAMERA_RELATIVE_VERTICAL_OFFSET(fHintVert)
|
|
SET_GAMEPLAY_HINT_CAMERA_BLEND_TO_FOLLOW_PED_MEDIUM_VIEW_MODE(TRUE)
|
|
iPushInTimer = GET_GAME_TIMER()
|
|
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
|
|
TASK_FOLLOW_TO_OFFSET_OF_ENTITY(PLAYER_PED_ID(), sRCLauncherDataLocal.pedID[MARY_ANN_ID], <<0,0,0>>, PEDMOVEBLENDRATIO_WALK)
|
|
ENDIF
|
|
ENDIF
|
|
ELSE
|
|
STOP_GAMEPLAY_HINT_BEING_CANCELLED_THIS_UPDATE(TRUE)
|
|
ENDIF
|
|
|
|
IF NOT HAS_CUTSCENE_LOADED()
|
|
RC_REQUEST_CUTSCENE("ef_2_rcm")
|
|
IF CAN_REQUEST_ASSETS_FOR_CUTSCENE_ENTITY()
|
|
RCM_DEBUG_PRINT("Trying to set Mary Ann component variation")
|
|
SET_CUTSCENE_PED_COMPONENT_VARIATION_FROM_PED("Mary_Ann", sRCLauncherDataLocal.pedID[MARY_ANN_ID])
|
|
ENDIF
|
|
RCM_DEBUG_PRINT("Requesting cutscene...")
|
|
ELSE
|
|
IF (GET_GAME_TIMER() - iPushInTimer) > 3000
|
|
RCM_DEBUG_PRINT("Cutscene loaded & timer expired, moving on...")
|
|
RCM_ADVANCE_STAGE()
|
|
ELSE
|
|
RCM_DEBUG_PRINT("Waiting for focus push timer...")
|
|
|
|
IF iPushInTimer > 1000
|
|
IF NOT bDoneLeadInConv
|
|
IF CREATE_CONVERSATION(sWomanConversation, "FAN2AU", "FAN2_AMB", CONV_PRIORITY_MEDIUM)
|
|
bDoneLeadInConv = TRUE
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
|
|
AND IS_ENTITY_ALIVE(sRCLauncherDataLocal.pedID[MARY_ANN_ID])
|
|
IF GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), sRCLauncherDataLocal.pedID[MARY_ANN_ID]) < 6.0
|
|
RCM_DEBUG_PRINT("Trevor got too close to Mary Ann, breaking out of focus push and playing intro")
|
|
RCM_ADVANCE_STAGE()
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ELSE
|
|
RCM_DEBUG_PRINT("Replay detected, skipping cutscene init...")
|
|
// Clear area here instead of mission init, otherwise taxi might get cleared (B*1980643)
|
|
CLEAR_ANGLED_AREA_OF_VEHICLES(<<864.302063,1274.851807,361.473602>>, <<393.978210,1197.083862,224.314072>>, 176.0)
|
|
CLEAR_ANGLED_AREA_OF_VEHICLES(<<878.295532,1291.727783,355.536591>>, <<817.823486,1271.438599,362.973633>>, 12.75)
|
|
RCM_ADVANCE_STAGE()
|
|
ENDIF
|
|
|
|
ENDIF
|
|
|
|
IF RCM_CLEANUP_STAGE()
|
|
|
|
RCM_DEBUG_PRINT("Cleaned up MS_INIT")
|
|
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Do Mary Ann's exit actions when the cutscene ends
|
|
PROC DO_MARY_ANN_EXIT()
|
|
IF CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY("Mary_Ann", IG_MARYANN)
|
|
IF IS_ENTITY_ALIVE(sRCLauncherDataLocal.pedID[MARY_ANN_ID])
|
|
RCM_DEBUG_PRINT("Setting exit state for Mary Ann")
|
|
IF IS_VEHICLE_OK(vehBike[MARY_ANN_BIKE_ID])
|
|
RESET_MARY_ANN()
|
|
FORCE_PED_MOTION_STATE(sRCLauncherDataLocal.pedID[MARY_ANN_ID], MS_DO_NOTHING, FALSE, FAUS_CUTSCENE_EXIT)
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Do Trevor's exit actions when the cutscene ends
|
|
FUNC BOOL DO_TREVOR_EXIT()
|
|
IF CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY("Trevor")
|
|
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
|
|
RCM_DEBUG_PRINT("Setting exit state for Trevor")
|
|
IF IS_VEHICLE_OK(vehBike[PLAYER_BIKE_ID])
|
|
IF NOT IS_PED_IN_VEHICLE(PLAYER_PED_ID(), vehBike[PLAYER_BIKE_ID])
|
|
RCM_DEBUG_PRINT("Putting Trevor on bike")
|
|
SET_PED_INTO_VEHICLE(PLAYER_PED_ID(), vehBike[PLAYER_BIKE_ID])
|
|
//TASK_WARP_PED_INTO_VEHICLE(PLAYER_PED_ID(), vehBike[PLAYER_BIKE_ID], VS_DRIVER)
|
|
ENDIF
|
|
IF bIntroSkipped
|
|
SET_GAMEPLAY_CAM_RELATIVE_PITCH()
|
|
SET_GAMEPLAY_CAM_RELATIVE_HEADING()
|
|
ENDIF
|
|
ENDIF
|
|
bDoneTrevExit = TRUE
|
|
SET_PED_RESET_FLAG(PLAYER_PED_ID(), PRF_PreventGoingIntoStillInVehicleState, TRUE)
|
|
FORCE_PED_MOTION_STATE(PLAYER_PED_ID(), MS_DO_NOTHING, FALSE, FAUS_CUTSCENE_EXIT)
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Do the bike actions for exiting the cutscene (also from a replay when the cutscene isn't active)
|
|
PROC DO_BIKE_EXIT()
|
|
IF CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY("Players_Bike")
|
|
RCM_DEBUG_PRINT("Setting exit state for bike")
|
|
IF IS_VEHICLE_OK(vehBike[PLAYER_BIKE_ID])
|
|
AND IS_ENTITY_ALIVE(PLAYER_PED_ID())
|
|
RCM_DEBUG_PRINTFLOAT("Bike speed on exit: ", GET_ENTITY_SPEED(vehBike[PLAYER_BIKE_ID]))
|
|
bDoBikeExit = TRUE
|
|
SET_VEHICLE_FORWARD_SPEED(vehBike[PLAYER_BIKE_ID], START_SPEED)
|
|
|
|
// IF HAS_VEHICLE_RECORDING_BEEN_LOADED(500, "Fan2_TrevExitRec")
|
|
// AND NOT IS_PLAYBACK_GOING_ON_FOR_VEHICLE(vehBike[PLAYER_BIKE_ID])
|
|
// //AND IS_PED_IN_VEHICLE(PLAYER_PED_ID(),vehBike[PLAYER_BIKE_ID])
|
|
// RCM_DEBUG_PRINT("Doing bike exit playback")
|
|
// START_PLAYBACK_RECORDED_VEHICLE(vehBike[PLAYER_BIKE_ID], 500, "Fan2_TrevExitRec")
|
|
// FORCE_PLAYBACK_RECORDED_VEHICLE_UPDATE(vehBike[PLAYER_BIKE_ID])
|
|
// ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
PROC CHECK_EXIT_STATES()
|
|
|
|
DO_MARY_ANN_EXIT()
|
|
|
|
IF CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY("MaryAnnes_Friend")
|
|
// Set friend in knocked out pose here when available - until then, delete
|
|
RCM_PLACE_KNOCKED_OUT_FRIEND()
|
|
ENDIF
|
|
|
|
DO_BIKE_EXIT()
|
|
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Main loop for the intro cutscene stage
|
|
PROC MS_INTRO()
|
|
|
|
INT i = 0
|
|
|
|
IF RCM_INIT_STAGE()
|
|
|
|
RCM_DEBUG_PRINT("Init MS_INTRO")
|
|
WHILE NOT HAVE_ASSETS_FOR_MISSION_STAGE_LOADED(stateIntro)
|
|
WAIT(0)
|
|
ENDWHILE
|
|
|
|
IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID(), TRUE)
|
|
TASK_LEAVE_ANY_VEHICLE(PLAYER_PED_ID(), DEFAULT, ECF_DONT_WAIT_FOR_VEHICLE_TO_STOP|ECF_WARP_PED)
|
|
ENDIF
|
|
|
|
iIntroStage = 0
|
|
bIntroSkipped = FALSE
|
|
bIntroSkippedWhile = FALSE
|
|
bUsedSkip = FALSE
|
|
// bDoneTrevExit = FALSE
|
|
SET_CUTSCENE_FADE_VALUES(FALSE, FALSE, FALSE, FALSE) // Reset to default when skipping back to the intro
|
|
|
|
IF NOT Is_Replay_In_Progress()
|
|
OR bUsedCheckpoints = TRUE
|
|
WHILE NOT RC_IS_CUTSCENE_OK_TO_START()
|
|
WAIT(0)
|
|
ENDWHILE
|
|
|
|
raceInfo.sourcePos = vLongRaceStart[0]
|
|
raceInfo.sourceHeading = fLongRaceStart[0]
|
|
playerInfo.raceVehicle = vehBike[PLAYER_BIKE_ID]
|
|
playerInfo.racer = PLAYER_PED_ID()
|
|
playerInfo.currentCheck = 1
|
|
playerInfo.nextCheck = 2
|
|
RCM_SETUP_RACE_INFO()
|
|
FORCE_RENDER_IN_GAME_UI(TRUE)
|
|
|
|
RUN_CUTSCENE()
|
|
|
|
REPLAY_START_EVENT(REPLAY_IMPORTANCE_LOW)
|
|
STOP_GAMEPLAY_HINT()
|
|
ENDIF
|
|
|
|
RCM_DEBUG_PRINT("Running MS_INTRO")
|
|
|
|
ELSE
|
|
|
|
HIDE_STREET_AND_CAR_NAMES_THIS_FRAME()
|
|
|
|
IF Is_Replay_In_Progress()
|
|
AND bUsedCheckpoints = FALSE
|
|
RCM_DEBUG_PRINT("Replay detected, skipping Intro state...")
|
|
WHILE NOT HAVE_ASSETS_FOR_MISSION_STAGE_LOADED(stateCountdown)
|
|
WAIT(0) //Load in race assets now before skipping ahead
|
|
ENDWHILE
|
|
bUsedSkip = TRUE
|
|
|
|
// Generate the bikes now so we can use them for setting up the race infO
|
|
RCM_DEBUG_PRINT("Reset bikes from MS_INTRO skip")
|
|
RESET_BIKES()
|
|
raceInfo.sourcePos = vLongRaceStart[0]
|
|
raceInfo.sourceHeading = fLongRaceStart[0]
|
|
playerInfo.raceVehicle = vehBike[PLAYER_BIKE_ID]
|
|
playerInfo.racer = PLAYER_PED_ID()
|
|
playerInfo.currentCheck = 1
|
|
playerInfo.nextCheck = 2
|
|
RCM_SETUP_RACE_INFO()
|
|
RCM_PLACE_KNOCKED_OUT_FRIEND()
|
|
iFadeTimer = GET_GAME_TIMER()
|
|
JUMP_TO_STAGE(1)
|
|
ELSE
|
|
|
|
|
|
IF WAS_CUTSCENE_SKIPPED()
|
|
RCM_DEBUG_PRINT("Detected the cutscene was skipped!! Do our own fade...")
|
|
SET_GAMEPLAY_CAM_RELATIVE_HEADING()
|
|
SET_GAMEPLAY_CAM_RELATIVE_PITCH()
|
|
SET_CUTSCENE_FADE_VALUES(FALSE, FALSE, TRUE, FALSE)
|
|
bIntroSkipped = TRUE
|
|
iIntroStage = 1
|
|
ENDIF
|
|
|
|
IF IS_CUTSCENE_PLAYING()
|
|
IF GET_CUTSCENE_TIME() > 64000
|
|
RUN_PLAYER_CHECKPOINTS_AND_BLIPS(playerInfo, raceInfo, FALSE)
|
|
RCM_DEBUG_PRINT("Running checkpoints during intro now")
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF iIntroStage = 0
|
|
|
|
WHILE NOT HAVE_ASSETS_FOR_MISSION_STAGE_LOADED(stateCountdown)
|
|
WAIT(0) //Load in race assets while the cutscene is playing to speed things up
|
|
|
|
IF IS_CUTSCENE_SKIP_BUTTON_JUST_PRESSED()
|
|
RCM_DEBUG_PRINT("Cutscene skipped in while!!")
|
|
IF bIntroSkipped = FALSE
|
|
IF IS_CUTSCENE_ACTIVE()
|
|
STOP_CUTSCENE()
|
|
ENDIF
|
|
bIntroSkipped = TRUE
|
|
iFadeTimer = GET_GAME_TIMER()
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF WAS_CUTSCENE_SKIPPED()
|
|
RCM_DEBUG_PRINT("Detected the cutscene was skipped!! Do our own fade... (in while)")
|
|
SET_CUTSCENE_FADE_VALUES(FALSE, FALSE, TRUE, FALSE)
|
|
SET_GAMEPLAY_CAM_RELATIVE_HEADING()
|
|
SET_GAMEPLAY_CAM_RELATIVE_PITCH()
|
|
SET_CUTSCENE_FADE_VALUES(FALSE, FALSE, TRUE, FALSE)
|
|
bIntroSkipped = TRUE
|
|
iIntroStage = 1
|
|
ENDIF
|
|
|
|
CHECK_EXIT_STATES()
|
|
|
|
DO_TREVOR_EXIT()
|
|
|
|
ENDWHILE
|
|
|
|
SET_GAMEPLAY_CAM_RELATIVE_HEADING()
|
|
SET_GAMEPLAY_CAM_RELATIVE_PITCH()
|
|
|
|
CHECK_EXIT_STATES()
|
|
|
|
IF DO_TREVOR_EXIT()
|
|
iIntroStage = 1
|
|
ENDIF
|
|
|
|
ELIF iIntroStage = 1
|
|
|
|
CHECK_EXIT_STATES()
|
|
|
|
DO_TREVOR_EXIT()
|
|
|
|
IF bDoneTrevExit
|
|
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
|
|
SET_PED_RESET_FLAG(PLAYER_PED_ID(), PRF_PreventGoingIntoStillInVehicleState, TRUE)
|
|
RCM_DEBUG_PRINT("Setting PRF_PreventGoingIntoStillInVehicleState on Trevor")
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF bDoBikeExit
|
|
IF IS_VEHICLE_OK(vehBike[PLAYER_BIKE_ID])
|
|
SET_VEHICLE_FORWARD_SPEED(vehBike[PLAYER_BIKE_ID], START_SPEED)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF bIntroSkipped
|
|
IF NOT bIntroSkippedWhile
|
|
RCM_DEBUG_PRINT("Doing out-of-loop Z-skip")
|
|
iFadeTimer = GET_GAME_TIMER()
|
|
SAFE_FADE_SCREEN_OUT_TO_BLACK(DEFAULT, FALSE)
|
|
WHILE (GET_GAME_TIMER() - iFadeTimer) < 750
|
|
WAIT(0)
|
|
RCM_DEBUG_PRINT("In fade out wait...")
|
|
// If we're waiting for the fade, keep doing the rolling start
|
|
CHECK_EXIT_STATES()
|
|
DO_TREVOR_EXIT()
|
|
IF IS_SCREEN_FADED_OUT()
|
|
IF IS_VEHICLE_OK(vehBike[PLAYER_BIKE_ID])
|
|
SET_VEHICLE_FORWARD_SPEED(vehBike[PLAYER_BIKE_ID], START_SPEED)
|
|
ENDIF
|
|
ENDIF
|
|
ENDWHILE
|
|
iFadeTimer = GET_GAME_TIMER() // Reset timer to use it again for the fade in
|
|
bIntroSkippedWhile = TRUE // Stop this looping over and over
|
|
ENDIF
|
|
RCM_PLACE_KNOCKED_OUT_FRIEND() // Just to ensure he's placed if the exit state is missed
|
|
// This is an attempt to stop #354555
|
|
// This is TERRIBLE. I feel like a CRIMINAL.
|
|
ENDIF
|
|
|
|
IF NOT IS_CUTSCENE_PLAYING()
|
|
REPLAY_STOP_EVENT()
|
|
REPLAY_RECORD_BACK_FOR_TIME(0.0, 10.0, REPLAY_IMPORTANCE_LOW)
|
|
#IF IS_DEBUG_BUILD
|
|
bAllowDebugSkipForward = FALSE // Prevents J skipping through an extra state
|
|
#ENDIF
|
|
|
|
// This is still needed while 1028909 is an issue
|
|
// 551021 needs fixing first, then 864739 needs looked at
|
|
// IF NOT bUsedSkip
|
|
// RCM_DEBUG_PRINT("Reset bikes from MS_INTRO loop")
|
|
// RESET_BIKES() // Don't reset the bikes if we've used a debug skip
|
|
// ENDIF
|
|
|
|
// CLEAR_AREA_OF_VEHICLES(<<820.66, 1275.33, 359.48>>, 14.0)
|
|
// CLEAR_AREA_OF_VEHICLES(<<839.00, 1277.36, 359.11>>, 14.0)
|
|
CLEAR_AREA_OF_VEHICLES(<<850.99, 1284.06, 358.39>>, 14.0)
|
|
CLEAR_AREA_OF_VEHICLES(<<856.54, 1270.78, 358.24>>, 14.0)
|
|
CLEAR_AREA_OF_VEHICLES(<<850.71, 1256.57, 356.34>>, 14.0)
|
|
CLEAR_AREA_OF_VEHICLES(<<840.86, 1245.39, 352.97>>, 14.0)
|
|
|
|
IF NOT bIntroSkipped
|
|
RC_END_CUTSCENE_MODE()
|
|
ENDIF
|
|
|
|
IF IS_VEHICLE_OK(vehBike[PLAYER_BIKE_ID])
|
|
IF RCM_IS_PLAYER_OK()
|
|
bDoBikeExit = TRUE
|
|
SET_VEHICLE_FORWARD_SPEED(vehBike[PLAYER_BIKE_ID], START_SPEED)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
RC_SET_ENTITY_PROOFS_FOR_CUTSCENE(sRCLauncherDataLocal, FALSE)
|
|
REPEAT NUM_BIKES i
|
|
IF IS_ENTITY_ALIVE(vehBike[i])
|
|
SET_ENTITY_PROOFS(vehBike[i], FALSE, FALSE, FALSE, FALSE, FALSE)
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
RCM_ADVANCE_STAGE()
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF RCM_CLEANUP_STAGE()
|
|
RUN_PLAYER_CHECKPOINTS_AND_BLIPS(playerInfo, raceInfo) // Keep the checkpoint onscreen during the blend
|
|
RCM_DEBUG_PRINT("Cleaned up MS_INTRO")
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
|
|
/// PURPOSE:
|
|
/// Control function for the cop and car being chased up the mountain roughly midway through the race
|
|
PROC RCM_DRIVE_PAST_PLAYER()
|
|
|
|
IF NOT Is_Replay_In_Progress()
|
|
if IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<435.162811,1275.777466,269.505432>>, <<455.596619,1285.541504,278.748474>>, 8.500000)
|
|
|
|
IF bStartedDrivers = FALSE
|
|
// We're only going to create the Driver and Cop the moment they're supposed to be triggered
|
|
// Otherwise, you could bike off a cliff and see them waiting on the road
|
|
// (You'll then fail the mission, but you'd still 'see the strings' so to speak)
|
|
|
|
REQUEST_MODEL(Penumbra)
|
|
REQUEST_MODEL(POLICE3)
|
|
REQUEST_VEHICLE_RECORDING(500, "Fan2_Driver")
|
|
REQUEST_VEHICLE_RECORDING(500, "Fan2_DriverCop")
|
|
|
|
IF HAS_MODEL_LOADED(Penumbra)
|
|
and HAS_MODEL_LOADED(POLICE3)
|
|
AND HAS_VEHICLE_RECORDING_BEEN_LOADED(500, "Fan2_Driver")
|
|
AND HAS_VEHICLE_RECORDING_BEEN_LOADED(500, "Fan2_DriverCop")
|
|
RCM_SPAWN_VEHICLE(viDriver, PENUMBRA, << 543.5132, 1022.7282, 216.7213 >>)
|
|
IF NOT IS_ENTITY_ALIVE(piDriver) AND IS_VEHICLE_OK(viDriver)
|
|
IF IS_VEHICLE_SEAT_FREE(viDriver)
|
|
piDriver = CREATE_PED_INSIDE_VEHICLE(viDriver, PEDTYPE_MISSION, A_M_Y_Runner_01)
|
|
RCM_DEBUG_PRINT("Created car.")
|
|
ENDIF
|
|
ENDIF
|
|
SET_MODEL_AS_NO_LONGER_NEEDED(PENUMBRA)
|
|
SET_MODEL_AS_NO_LONGER_NEEDED(A_M_Y_Runner_01)
|
|
|
|
RCM_SPAWN_VEHICLE(viDriverCop, POLICE3, << 537.1293, 1009.8887, 214.4232 >>)
|
|
IF NOT IS_ENTITY_ALIVE(piDriverCop) AND IS_VEHICLE_OK(viDriverCop)
|
|
IF IS_VEHICLE_SEAT_FREE(viDriverCop)
|
|
piDriverCop = CREATE_PED_INSIDE_VEHICLE(viDriverCop, PEDTYPE_COP, S_M_Y_Cop_01)
|
|
RCM_DEBUG_PRINT("Created cop car.")
|
|
ENDIF
|
|
ENDIF
|
|
SET_MODEL_AS_NO_LONGER_NEEDED(POLICE3)
|
|
SET_MODEL_AS_NO_LONGER_NEEDED(S_M_Y_Cop_01)
|
|
|
|
if IS_VEHICLE_OK(viDriver)
|
|
IF NOT IS_PLAYBACK_GOING_ON_FOR_VEHICLE(viDriver)
|
|
START_PLAYBACK_RECORDED_VEHICLE(viDriver, 500, "Fan2_Driver")
|
|
ENDIF
|
|
ENDIF
|
|
if IS_VEHICLE_OK(viDriverCop)
|
|
IF NOT IS_PLAYBACK_GOING_ON_FOR_VEHICLE(viDriverCop)
|
|
START_PLAYBACK_RECORDED_VEHICLE(viDriverCop, 500, "Fan2_DriverCop")
|
|
SET_VEHICLE_SIREN(viDriverCop, TRUE)
|
|
ENDIF
|
|
ENDIF
|
|
bStartedDrivers = TRUE // Stop trying to create the drivers
|
|
ENDIF
|
|
ENDIF
|
|
ELSE // If the vehicles have started playback and the player has passed the trigger zone, modify their playback speed
|
|
IF IS_VEHICLE_OK(viDriver)
|
|
IF IS_PLAYBACK_GOING_ON_FOR_VEHICLE(viDriver)
|
|
SET_PLAYBACK_SPEED(viDriver, 1.20)
|
|
ENDIF
|
|
ENDIF
|
|
IF IS_VEHICLE_OK(viDriverCop)
|
|
IF IS_PLAYBACK_GOING_ON_FOR_VEHICLE(viDriverCop)
|
|
SET_PLAYBACK_SPEED(viDriverCop, 1.30)
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Control function for the two joggers by the Vinewood sign
|
|
PROC RCM_JOG_PAST_PLAYER()
|
|
|
|
IF raceLength = RACE_LONGA OR raceLength = RACE_LONGB
|
|
if IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<838.825256,1255.184814,352.553162>>, <<871.473328,1263.308228,364.424377>>, 30.250000)
|
|
IF NOT IS_ENTITY_ALIVE(piJogger1)
|
|
AND HAS_MODEL_LOADED(A_F_Y_Runner_01)
|
|
piJogger1 = CREATE_PED(PEDTYPE_MISSION, A_F_Y_Runner_01, <<590.1751, 1203.1410, 307.6940>>, 293.40)
|
|
RCM_DEBUG_PRINT("Created jogger 1")
|
|
SET_MODEL_AS_NO_LONGER_NEEDED(A_F_Y_Runner_01)
|
|
ELSE
|
|
IF NOT IS_WAYPOINT_PLAYBACK_GOING_ON_FOR_PED(piJogger1)
|
|
TASK_FOLLOW_WAYPOINT_RECORDING(piJogger1, "Fan2_Jogger1")
|
|
ELSE
|
|
IF GET_PED_WAYPOINT_PROGRESS(piJogger1) > 93
|
|
RCM_DEBUG_PRINT("Released jogger 1 (waypoint > 93)")
|
|
SAFE_RELEASE_PED(piJogger1)
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF NOT IS_ENTITY_ALIVE(piJogger2)
|
|
AND HAS_MODEL_LOADED(A_M_Y_Runner_01)
|
|
piJogger2 = CREATE_PED(PEDTYPE_MISSION, A_M_Y_Runner_01, <<592.1368, 1200.9105, 307.7926>>, 286.58)
|
|
RCM_DEBUG_PRINT("Created jogger 2")
|
|
IF IS_REPLAY_IN_PROGRESS() // If we're on a replay, we can release this model now as it's not used for the car chase sequence
|
|
SET_MODEL_AS_NO_LONGER_NEEDED(A_M_Y_Runner_01)
|
|
ENDIF
|
|
ELSE
|
|
IF NOT IS_WAYPOINT_PLAYBACK_GOING_ON_FOR_PED(piJogger2)
|
|
TASK_FOLLOW_WAYPOINT_RECORDING(piJogger2, "Fan2_Jogger2")
|
|
ELSE
|
|
IF GET_PED_WAYPOINT_PROGRESS(piJogger2) > 93
|
|
RCM_DEBUG_PRINT("Released jogger 2 (waypoint > 93)")
|
|
SAFE_RELEASE_PED(piJogger2)
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ELSE
|
|
IF IS_ENTITY_ALIVE(piJogger1)
|
|
IF IS_WAYPOINT_PLAYBACK_GOING_ON_FOR_PED(piJogger1)
|
|
IF GET_PED_WAYPOINT_PROGRESS(piJogger1) > 93
|
|
SAFE_RELEASE_PED(piJogger1)
|
|
RCM_DEBUG_PRINT("Released jogger 1 (waypoint > 93)")
|
|
ELIF GET_PED_WAYPOINT_PROGRESS(piJogger1) > 51
|
|
IF GET_DISTANCE_BETWEEN_ENTITIES(piJogger1, PLAYER_PED_ID()) > 70
|
|
SAFE_RELEASE_PED(piJogger1)
|
|
RCM_DEBUG_PRINT("Released jogger 1 (distance > 70)")
|
|
ENDIF
|
|
ENDIF
|
|
ELSE
|
|
SAFE_RELEASE_PED(piJogger1)
|
|
RCM_DEBUG_PRINT("Released jogger 1 (no waypoint playback)")
|
|
ENDIF
|
|
ELSE
|
|
SAFE_RELEASE_PED(piJogger1)
|
|
ENDIF
|
|
|
|
IF IS_ENTITY_ALIVE(piJogger2)
|
|
IF IS_WAYPOINT_PLAYBACK_GOING_ON_FOR_PED(piJogger2)
|
|
IF GET_PED_WAYPOINT_PROGRESS(piJogger2) > 93
|
|
SAFE_RELEASE_PED(piJogger2)
|
|
RCM_DEBUG_PRINT("Released jogger 2 (waypoint > 93)")
|
|
ELIF GET_PED_WAYPOINT_PROGRESS(piJogger2) > 51
|
|
IF GET_DISTANCE_BETWEEN_ENTITIES(piJogger2, PLAYER_PED_ID()) > 70
|
|
SAFE_RELEASE_PED(piJogger2)
|
|
RCM_DEBUG_PRINT("Released jogger 2 (distance > 70)")
|
|
ENDIF
|
|
ENDIF
|
|
ELSE
|
|
SAFE_RELEASE_PED(piJogger2)
|
|
RCM_DEBUG_PRINT("Released jogger 2 (no waypoint playback)")
|
|
ENDIF
|
|
ELSE
|
|
SAFE_RELEASE_PED(piJogger2)
|
|
ENDIF
|
|
|
|
if HAS_PLAYER_THREATENED_PED(piJogger1) OR HAS_PLAYER_THREATENED_PED(piJogger2)
|
|
IF IS_PED_UNINJURED(piJogger1) AND IS_PED_UNINJURED(piJogger2)
|
|
TASK_SMART_FLEE_PED(piJogger1, PLAYER_PED_ID(), 100, -1)
|
|
TASK_SMART_FLEE_PED(piJogger2, PLAYER_PED_ID(), 100, -1)
|
|
ENDIF
|
|
SAFE_RELEASE_PED(piJogger1)
|
|
SAFE_RELEASE_PED(piJogger2)
|
|
RCM_DEBUG_PRINT("Released joggers 1 & 2 (threatened)")
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Control function for the cyclist on the forest path during the second half of the race
|
|
PROC RCM_CYCLE_PAST_PLAYER()
|
|
|
|
IF raceLength = RACE_LONGA OR raceLength = RACE_LONGB
|
|
if IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<458.592285,1066.150757,232.179642>>, <<428.820862,1059.496948,241.894241>>, 9.750000)
|
|
AND NOT bStartedCyclist
|
|
REQUEST_MODEL(A_M_Y_Cyclist_01)
|
|
IF HAS_MODEL_LOADED(A_M_Y_Cyclist_01)
|
|
if IS_VEHICLE_OK(viCyclist)
|
|
IF NOT IS_PLAYBACK_GOING_ON_FOR_VEHICLE(viCyclist)
|
|
START_PLAYBACK_RECORDED_VEHICLE(viCyclist, 500, "Fan2_Cyclist")
|
|
FORCE_PLAYBACK_RECORDED_VEHICLE_UPDATE(viCyclist)
|
|
RCM_DEBUG_PRINT("Playing cyclist")
|
|
bStartedCyclist = TRUE
|
|
ENDIF
|
|
ELSE
|
|
RCM_SPAWN_VEHICLE(viCyclist, TRIBIKE, << 292.3295, 1244.0404, 234.0005 >>)
|
|
IF NOT IS_ENTITY_ALIVE(piCyclist) AND IS_VEHICLE_OK(viCyclist)
|
|
IF IS_VEHICLE_SEAT_FREE(viCyclist)
|
|
piCyclist = CREATE_PED_INSIDE_VEHICLE(viCyclist, PEDTYPE_MISSION, A_M_Y_Cyclist_01)
|
|
RCM_DEBUG_PRINT("Created cyclist.")
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
IF IS_VEHICLE_OK(viCyclist) AND IS_ENTITY_ALIVE(piCyclist)
|
|
IF bStartedCyclist
|
|
SET_MODEL_AS_NO_LONGER_NEEDED(A_M_Y_Cyclist_01)
|
|
IF NOT IS_PLAYBACK_GOING_ON_FOR_VEHICLE(viCyclist)
|
|
SAFE_RELEASE_PED(piCyclist)
|
|
SAFE_RELEASE_VEHICLE(viCyclist)
|
|
RCM_DEBUG_PRINT("Killing cyclist")
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
IF IS_ENTITY_ALIVE(piCyclist)
|
|
if HAS_PLAYER_THREATENED_PED(piCyclist)
|
|
TASK_SMART_FLEE_PED(piCyclist, PLAYER_PED_ID(), 200, -1)
|
|
SAFE_RELEASE_PED(piCyclist)
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Make any vehicles close to the front of the player's bike honk their horn at them
|
|
PROC RCM_HONK_NEAR_PLAYER()
|
|
|
|
VECTOR vOffset
|
|
VEHICLE_INDEX vIdx
|
|
|
|
IF RCM_IS_PLAYER_OK()
|
|
IF IS_VEHICLE_OK(vehBike[PLAYER_BIKE_ID]) AND IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
|
|
IF GET_ENTITY_SPEED(PLAYER_PED_ID()) > 5
|
|
vOffset = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()), <<0,6,0>>)
|
|
//DRAW_DEBUG_SPHERE(vOffset, 8, 0, 0, 255, 125)
|
|
if (GET_GAME_TIMER() - iHonkTimer) > 4000
|
|
//RCM_DEBUG_PRINT("HONKING: Checking for vehicle...")
|
|
vIdx = GET_CLOSEST_VEHICLE(vOffset, 8, DUMMY_MODEL_FOR_SCRIPT, 2) // 2 = Return mission vehicles
|
|
if vIdx <> NULL
|
|
RCM_DEBUG_PRINT("HONKING: Entity exists!")
|
|
if not IS_VEHICLE_MODEL(vIdx, SCORCHER)
|
|
AND NOT IS_VEHICLE_MODEL(vIdx, TRIBIKE)
|
|
AND NOT IS_VEHICLE_SEAT_FREE(vIdx)
|
|
START_VEHICLE_HORN(vIdx, 4000)
|
|
RCM_DEBUG_PRINT("Honking!")
|
|
IF IS_PED_UNINJURED(PLAYER_PED_ID())
|
|
TASK_LOOK_AT_ENTITY(PLAYER_PED_ID(), vIdx, 3000)
|
|
ENDIF
|
|
iHonkTimer = GET_GAME_TIMER()
|
|
ENDIF
|
|
ENDIF
|
|
|
|
vIdx = GET_CLOSEST_VEHICLE(vOffset, 8, DUMMY_MODEL_FOR_SCRIPT, 4) // 4 = Return random vehicles
|
|
if vIdx <> NULL
|
|
RCM_DEBUG_PRINT("HONKING: Entity exists!")
|
|
if not IS_VEHICLE_MODEL(vIdx, SCORCHER)
|
|
AND NOT IS_VEHICLE_MODEL(vIdx, TRIBIKE)
|
|
AND NOT IS_VEHICLE_SEAT_FREE(vIdx)
|
|
START_VEHICLE_HORN(vIdx, 4000)
|
|
RCM_DEBUG_PRINT("Honking!")
|
|
IF IS_PED_UNINJURED(PLAYER_PED_ID())
|
|
TASK_LOOK_AT_ENTITY(PLAYER_PED_ID(), vIdx, 3000)
|
|
ENDIF
|
|
iHonkTimer = GET_GAME_TIMER()
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Update the checks to make sure the player is still on their bike, and display God text where needed
|
|
PROC RCM_CHECK_PLAYER_ON_BIKE()
|
|
|
|
IF RCM_IS_PLAYER_OK()
|
|
IF IS_VEHICLE_OK(vehBike[PLAYER_BIKE_ID])
|
|
IF bPlayerIsOnBike = TRUE
|
|
IF NOT IS_PED_IN_VEHICLE(PLAYER_PED_ID(), vehBike[PLAYER_BIKE_ID])
|
|
IF NOT DOES_BLIP_EXIST(blipBike)
|
|
blipBike = CREATE_VEHICLE_BLIP(vehBike[PLAYER_BIKE_ID])
|
|
ENDIF
|
|
IF bDisplayedGetBackOnBike = FALSE
|
|
PRINT_NOW("FATIC2_1", DEFAULT_GOD_TEXT_TIME, 1) // Get on the ~b~bike.
|
|
bDisplayedGetBackOnBike = TRUE
|
|
ENDIF
|
|
bPlayerIsOnBike = FALSE
|
|
ENDIF
|
|
ELSE
|
|
IF IS_PED_IN_VEHICLE(PLAYER_PED_ID(), vehBike[PLAYER_BIKE_ID])
|
|
CLEAR_PRINTS()
|
|
SAFE_REMOVE_BLIP(blipBike)
|
|
bPlayerIsOnBike = TRUE
|
|
ENDIF
|
|
IF IS_VEHICLE_OK(vehBike[PLAYER_BIKE_ID])
|
|
IF GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), vehBike[PLAYER_BIKE_ID]) > 40.0
|
|
RCM_MISSION_FAILED(FAILED_LEFT_BIKE)
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Manage playing the final race-ending dialogue as the player reaches the finish line
|
|
PROC RCM_MANAGE_PENULTIMATE_CONVERSATION()
|
|
|
|
IF playerInfo.currentCheck >= MAX_CHECKPOINTS-1
|
|
IF bStartEndConv = FALSE
|
|
KILL_ANY_CONVERSATION()
|
|
bStartEndConv = TRUE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
|
|
/// PURPOSE:
|
|
/// Work out if Trevor should play a line of Road Rage dialogue, and play one if able
|
|
/// PARAMS:
|
|
/// KillExistingConvo - End any ongoing conversation before trying to play a road rage line
|
|
PROC RCM_TRY_ROAD_RAGE_CONVERSATION()
|
|
|
|
IF iRoadRageConversationsPlayed < NUM_ROAD_RAGE_CONVERSATIONS
|
|
IF bRoadRagePlaying = FALSE
|
|
VECTOR vOffset
|
|
VEHICLE_INDEX vIdx
|
|
|
|
IF RCM_IS_PLAYER_OK()
|
|
IF GET_ENTITY_SPEED(PLAYER_PED_ID()) > 5
|
|
vOffset = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()), <<0,8,0>>)
|
|
IF IS_ANY_VEHICLE_NEAR_POINT(vOffset, 3.5)
|
|
vIdx = GET_CLOSEST_VEHICLE(vOffset, 3.5, DUMMY_MODEL_FOR_SCRIPT, 2) // 2 = Return mission vehicles
|
|
if vIdx <> NULL
|
|
if not IS_VEHICLE_MODEL(vIdx, SCORCHER)
|
|
OR NOT IS_VEHICLE_MODEL(vIdx, TRIBIKE)
|
|
bRoadRagePlaying = TRUE
|
|
iConversationGapTimer = GET_GAME_TIMER()
|
|
ENDIF
|
|
ENDIF
|
|
|
|
vIdx = GET_CLOSEST_VEHICLE(vOffset, 3.5, DUMMY_MODEL_FOR_SCRIPT, 4) // 4 = Return random vehicles
|
|
if vIdx <> NULL
|
|
if not IS_VEHICLE_MODEL(vIdx, SCORCHER)
|
|
OR NOT IS_VEHICLE_MODEL(vIdx, TRIBIKE)
|
|
bRoadRagePlaying = TRUE
|
|
iConversationGapTimer = GET_GAME_TIMER()
|
|
// If banter is paused, kill it early - we'll play road rage instead and forget about it
|
|
IF ConvState = FAN2_CONV_STATE_BANTER_PAUSED
|
|
OR ConvState = FAN2_CONV_STATE_TOOFAR
|
|
KILL_ANY_CONVERSATION()
|
|
ConvState = FAN2_CONV_STATE_FREE
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
|
|
/// PURPOSE:
|
|
/// Try to set up either a banter conversation or a one-liner.
|
|
/// Is a state machine that waits for 4 seconds to pass before trying to do either of those.
|
|
/// The sequence of conversations that are triggered is set up specifically here.
|
|
PROC RCM_TRY_BANTER_OR_ONELINERS()
|
|
|
|
SWITCH BanterState
|
|
CASE BANTER_WAIT
|
|
if (GET_GAME_TIMER() - iBanterTimer) > 10000
|
|
BanterState = BANTER_ACT
|
|
ENDIF
|
|
BREAK
|
|
CASE BANTER_ACT
|
|
SWITCH iBanterSequence
|
|
CASE 0
|
|
ConvState = FAN2_CONV_STATE_BANTER_PLAYING
|
|
BREAK
|
|
CASE 1
|
|
ConvState = FAN2_CONV_STATE_ONELINER
|
|
BREAK
|
|
CASE 2
|
|
ConvState = FAN2_CONV_STATE_BANTER_PLAYING
|
|
BREAK
|
|
CASE 3
|
|
ConvState = FAN2_CONV_STATE_ONELINER
|
|
BREAK
|
|
CASE 4
|
|
ConvState = FAN2_CONV_STATE_BANTER_PLAYING
|
|
BREAK
|
|
CASE 5
|
|
ConvState = FAN2_CONV_STATE_ONELINER
|
|
BREAK
|
|
CASE 6
|
|
ConvState = FAN2_CONV_STATE_BANTER_PLAYING
|
|
BREAK
|
|
DEFAULT
|
|
ConvState = FAN2_CONV_STATE_ONELINER
|
|
BREAK
|
|
ENDSWITCH
|
|
iBanterSequence++
|
|
BREAK
|
|
ENDSWITCH
|
|
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Keep trying to do the given road rage conversation index
|
|
/// PARAMS:
|
|
/// i - the road rage conversation index we want to try and play
|
|
/// RETURNS:
|
|
/// TRUE if the conversation launches, FALSE if not
|
|
FUNC BOOL DO_ROAD_RAGE(int i)
|
|
|
|
IF bPlayedRoadRageConversation[i] = FALSE
|
|
IF CREATE_CONVERSATION(sRoadRageConversation, "FAN2AU", sRoadRageConversationString[i], CONV_PRIORITY_HIGH)
|
|
bPlayedRoadRageConversation[i] = TRUE
|
|
iRoadRageConversationsPlayed++
|
|
RCM_DEBUG_PRINTINT("iRoadRageConversationsPlayed = ", iRoadRageConversationsPlayed)
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// A large state machine that controls all of the conversations during the race!
|
|
/// Starts off in FAN2_CONV_STATE_START by default - the very first line Trevor says as the race starts.
|
|
/// Then cycles between FAN2_CONV_STATE_FREE to various other states.
|
|
/// The exception to this is FAN2_CONV_STATE_END - it stays there as we're about to finish the race
|
|
PROC RCM_MANAGE_CONVERSATIONS()
|
|
|
|
FLOAT fDist
|
|
|
|
SWITCH ConvState
|
|
// Line by Trevor at very start of race
|
|
CASE FAN2_CONV_STATE_START
|
|
IF bPlayedStartConv = FALSE
|
|
IF NOT IS_MESSAGE_BEING_DISPLAYED()
|
|
OR GET_PROFILE_SETTING(PROFILE_DISPLAY_SUBTITLES) = 0
|
|
IF CREATE_CONVERSATION(sWomanConversation, "FAN2AU", "FAN2_START", CONV_PRIORITY_HIGH)
|
|
RCM_DEBUG_PRINT("*** Doing start conversation")
|
|
bPlayedStartConv = TRUE
|
|
ENDIF
|
|
ENDIF
|
|
ELSE
|
|
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
|
|
RCM_DEBUG_PRINT("*** Start conversation over, conv state free")
|
|
iBanterTimer = GET_GAME_TIMER()
|
|
ConvState = FAN2_CONV_STATE_FREE
|
|
ENDIF
|
|
ENDIF
|
|
BREAK
|
|
|
|
// No conversation is ongoing, try various conditions in case we can do one
|
|
// If we get too far away from Mary Ann (>30m), stop any conversations from firing, but otherwise...
|
|
// See if we have to start the penultimate conversation (FAN2_CONV_STATE_END)...
|
|
// Then check if we need to make Mary Ann give a push warning (FAN2_CONV_STATE_PUSHWARNING)...
|
|
// Then see if we need to try and make Mary Ann react to Trevor overtaking (FAN2_CONV_STATE_OVERTAKE)...
|
|
// If we don't need to do any of these, then try and see if we can do either a banter conversation or a one-liner
|
|
CASE FAN2_CONV_STATE_FREE
|
|
IF RCM_IS_PLAYER_OK()
|
|
IF IS_ENTITY_ALIVE(sRCLauncherDataLocal.pedID[MARY_ANN_ID])
|
|
fDist = GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), GET_ENTITY_COORDS(sRCLauncherDataLocal.pedID[MARY_ANN_ID]))
|
|
IF bRoadRagePlaying // Do road rage if trying, regardless of distance between Mary Ann and Trevor
|
|
RCM_DEBUG_PRINT("*** Starting road rage")
|
|
ConvState = FAN2_CONV_STATE_ROADRAGE
|
|
ELIF fDist > 30 // Set conv status as too far if over 30m apart
|
|
RCM_DEBUG_PRINT("*** Too far apart (>30m) to do anything with a conversation")
|
|
ConvState = FAN2_CONV_STATE_TOOFAR
|
|
ELSE
|
|
IF NOT IS_MESSAGE_BEING_DISPLAYED()
|
|
OR GET_PROFILE_SETTING(PROFILE_DISPLAY_SUBTITLES) = 0
|
|
IF bStartEndConv
|
|
RCM_DEBUG_PRINT("*** Starting end conversation routine")
|
|
ConvState = FAN2_CONV_STATE_END
|
|
ELIF bGivePushWarning
|
|
RCM_DEBUG_PRINT("*** Starting push warning")
|
|
ConvState = FAN2_CONV_STATE_PUSHWARNING
|
|
ELIF bOvertakeOccurred
|
|
RCM_DEBUG_PRINT("*** Starting overtake routine")
|
|
ConvState = FAN2_CONV_STATE_OVERTAKE
|
|
ELSE
|
|
RCM_TRY_BANTER_OR_ONELINERS()
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
BREAK
|
|
|
|
// Hang about here and keep checking to see if we're close enough to try doing conversations again
|
|
CASE FAN2_CONV_STATE_TOOFAR
|
|
IF RCM_IS_PLAYER_OK()
|
|
IF IS_ENTITY_ALIVE(sRCLauncherDataLocal.pedID[MARY_ANN_ID])
|
|
fDist = GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), GET_ENTITY_COORDS(sRCLauncherDataLocal.pedID[MARY_ANN_ID]))
|
|
IF fDist <= 30 // Set conv status as too far if over 30m apart
|
|
RCM_DEBUG_PRINT("*** Close enough (<=30m) to do a conversation")
|
|
ConvState = FAN2_CONV_STATE_FREE
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
BREAK
|
|
|
|
// Near the last checkpoint, do the final line(s)
|
|
CASE FAN2_CONV_STATE_END
|
|
IF NOT bPlayedFinalConv
|
|
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
|
|
IF iRacePos = 1
|
|
IF CREATE_CONVERSATION(sRoadRageConversation, "FAN2AU", "FAN2_WINNING", CONV_PRIORITY_HIGH)
|
|
bPlayedFinalConv = TRUE
|
|
bFinalConvWinning = TRUE
|
|
RCM_DEBUG_PRINT("*** Trevor saying FAN2_WINNING")
|
|
ENDIF
|
|
ELSE
|
|
IF CREATE_CONVERSATION(sRoadRageConversation, "FAN2AU", "FAN2_LOSING", CONV_PRIORITY_HIGH)
|
|
bPlayedFinalConv = TRUE
|
|
RCM_DEBUG_PRINT("*** Trevor saying FAN2_LOSING")
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ELSE
|
|
IF bFinalConvWinning = TRUE // The convo played was the winning one
|
|
IF iRacePos = 2 // If the player gets overtaken by Mary Ann after this...
|
|
IF IS_ENTITY_ALIVE(sRCLauncherDataLocal.pedID[MARY_ANN_ID])
|
|
RCM_DEBUG_PRINT("*** Mary Ann passed player after saying 'WINNING' line...")
|
|
PLAY_PED_AMBIENT_SPEECH_WITH_VOICE(sRCLauncherDataLocal.pedID[MARY_ANN_ID], "FAN2_BQAA", "MARYANN", SPEECH_PARAMS_FORCE_FRONTEND)
|
|
// I think this will make her just go to the last checkpoint
|
|
TASK_DRIVE_BY(sRCLauncherDataLocal.pedID[MARY_ANN_ID], PLAYER_PED_ID(), NULL, <<0,0,0>>, 50, 100, TRUE, FIRING_PATTERN_FULL_AUTO)
|
|
bFinalConvWinning = FALSE // Stop trying to do this
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
BREAK
|
|
|
|
// Do a push warning line from Mary Ann
|
|
CASE FAN2_CONV_STATE_PUSHWARNING
|
|
IF bPlayedPushConv = FALSE
|
|
IF CREATE_CONVERSATION(sWomanConversation, "FAN2AU", "FAN2_PUSH", CONV_PRIORITY_HIGH)
|
|
RCM_DEBUG_PRINT("*** Done a push warning")
|
|
bPlayedPushConv = TRUE
|
|
ENDIF
|
|
ELSE
|
|
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
|
|
RCM_DEBUG_PRINT("*** Push warning over, conv state free")
|
|
bGivePushWarning = FALSE
|
|
bPlayedPushConv = FALSE
|
|
iPushTimer = GET_GAME_TIMER()
|
|
ConvState = FAN2_CONV_STATE_FREE
|
|
ENDIF
|
|
ENDIF
|
|
BREAK
|
|
|
|
// Do an overtake reaction line from Mary Ann
|
|
CASE FAN2_CONV_STATE_OVERTAKE
|
|
IF bPlayedOvertakeLine = FALSE
|
|
// If the player overtakes Mary Ann while another conversation is happening, it'll try playing an overtake line when it finishes
|
|
// This will sound weird, so we'll only play the overtake line if less than a second has passed between overtaking and trying to say the line
|
|
IF (GET_GAME_TIMER() - iConversationGapTimer) < 750
|
|
IF iRacePos = 1 // If Trevor has overtaken Mary Ann...
|
|
IF iOverTakeLinesPlayed < NUM_OVERTAKE_LINES
|
|
IF CREATE_CONVERSATION(sWomanConversation, "FAN2AU", "FAN2_OVERT", CONV_PRIORITY_HIGH)
|
|
RCM_DEBUG_PRINT("*** Doing overtake line")
|
|
bPlayedOvertakeLine = TRUE
|
|
iOverTakeLinesPlayed++
|
|
ENDIF
|
|
ELSE
|
|
// We've played all the available overtake lines and don't want to repeat, so just set the conv status back to free
|
|
RCM_DEBUG_PRINT("*** All overtake lines played!")
|
|
bOvertakeOccurred = FALSE
|
|
ConvState = FAN2_CONV_STATE_FREE
|
|
ENDIF
|
|
ELSE // iRacePos = 2
|
|
// We don't want a line when Mary Ann overtakes Trevor, so just reset the conv status back to free
|
|
RCM_DEBUG_PRINT("*** Tried to do overtake line when Mary Ann passed Trevor!")
|
|
bOvertakeOccurred = FALSE
|
|
ConvState = FAN2_CONV_STATE_FREE
|
|
ENDIF
|
|
ELSE
|
|
RCM_DEBUG_PRINT("*** Too much time passed between overtake and a free spot in the conversation; skipping...")
|
|
bOvertakeOccurred = FALSE
|
|
ConvState = FAN2_CONV_STATE_FREE
|
|
ENDIF
|
|
ELSE
|
|
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
|
|
RCM_DEBUG_PRINT("*** Overtake line over, conv state free")
|
|
bOvertakeOccurred = FALSE
|
|
bPlayedOvertakeLine = FALSE
|
|
iOvertakeSpamTimer = GET_GAME_TIMER()
|
|
ConvState = FAN2_CONV_STATE_FREE
|
|
ENDIF
|
|
ENDIF
|
|
BREAK
|
|
|
|
// Try and do a road rage conversation if a car honks at Trevor during a free moment
|
|
CASE FAN2_CONV_STATE_ROADRAGE
|
|
// If the time elapsed from triggering the road rage convo and actually being able to do it is too large, don't bother, it'll sound odd
|
|
IF (GET_GAME_TIMER() - iConversationGapTimer) < 1000
|
|
INT i
|
|
i = GET_RANDOM_INT_IN_RANGE(0, NUM_ROAD_RAGE_CONVERSATIONS)
|
|
IF DO_ROAD_RAGE(i)
|
|
RCM_DEBUG_PRINT("*** Did a road rage line")
|
|
bRoadRagePlaying = FALSE
|
|
ConvState = FAN2_CONV_STATE_FREE
|
|
ENDIF
|
|
ELSE
|
|
RCM_DEBUG_PRINT("*** Too long between trying to trigger road rage and free moment in conversation, skipping...")
|
|
bRoadRagePlaying = FALSE
|
|
ConvState = FAN2_CONV_STATE_FREE
|
|
ENDIF
|
|
BREAK
|
|
|
|
// Trying to play a banter conversation
|
|
CASE FAN2_CONV_STATE_BANTER_PLAYING
|
|
IF bPlayedBanterOneliner = FALSE
|
|
IF iWomanConversationsPlayed < NUM_WOMAN_CONVERSATIONS
|
|
IF RCM_IS_PLAYER_OK()
|
|
IF IS_ENTITY_ALIVE(sRCLauncherDataLocal.pedID[MARY_ANN_ID])
|
|
IF CREATE_CONVERSATION(sWomanConversation, "FAN2AU", sWomanConversationString[iWomanConversationsPlayed], CONV_PRIORITY_HIGH)
|
|
RCM_DEBUG_PRINTINT("*** Started banter conversation #", iWomanConversationsPlayed+1)
|
|
bPlayedBanterOneliner = TRUE
|
|
iWomanConversationsPlayed++
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ELSE
|
|
RCM_DEBUG_PRINT("*** Tried to play more banter than convos available... not good!")
|
|
bPlayedBanterOneliner = FALSE
|
|
iBanterTimer = GET_GAME_TIMER()
|
|
BanterState = BANTER_WAIT
|
|
ConvState = FAN2_CONV_STATE_FREE
|
|
ENDIF
|
|
ELSE
|
|
// If the conversation ends, set status back to free
|
|
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
|
|
RCM_DEBUG_PRINT("*** Finished banter!")
|
|
bPlayedBanterOneliner = FALSE
|
|
iBanterTimer = GET_GAME_TIMER()
|
|
BanterState = BANTER_WAIT
|
|
ConvState = FAN2_CONV_STATE_FREE
|
|
// But if Mary Ann and Trevor get too far apart, pause the banter to resume it later
|
|
ELSE
|
|
IF RCM_IS_PLAYER_OK()
|
|
IF IS_ENTITY_ALIVE(sRCLauncherDataLocal.pedID[MARY_ANN_ID])
|
|
fDist = GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), GET_ENTITY_COORDS(sRCLauncherDataLocal.pedID[MARY_ANN_ID]))
|
|
IF fDist > 30 // Set conv status paused if over 30m apart
|
|
OR NOT IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID(), TRUE) // or if the player comes off their bike
|
|
RCM_DEBUG_PRINT("*** Paused banter!")
|
|
PAUSE_SCRIPTED_CONVERSATION(TRUE)
|
|
ConvState = FAN2_CONV_STATE_BANTER_PAUSED
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
BREAK
|
|
|
|
// Banter conversation is ongoing, but paused - keep checking if we can unpause it
|
|
CASE FAN2_CONV_STATE_BANTER_PAUSED
|
|
IF RCM_IS_PLAYER_OK()
|
|
IF IS_ENTITY_ALIVE(sRCLauncherDataLocal.pedID[MARY_ANN_ID])
|
|
fDist = GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), GET_ENTITY_COORDS(sRCLauncherDataLocal.pedID[MARY_ANN_ID]))
|
|
IF fDist <= 30 // Resume the conversation if they're close enough again
|
|
AND IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID(), TRUE)
|
|
RCM_DEBUG_PRINT("*** Unpaused banter!")
|
|
RESTART_SCRIPTED_CONVERSATION()
|
|
ConvState = FAN2_CONV_STATE_BANTER_PLAYING
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
BREAK
|
|
|
|
// Play a one-liner comment from either character
|
|
CASE FAN2_CONV_STATE_ONELINER
|
|
IF bPlayedBanterOneliner = FALSE
|
|
bDoMaryAnnOneliner = GET_RANDOM_BOOL()
|
|
// If bDoMaryAnnOneliner = true, do one of Mary Ann's lines - otherwise, do one of Trevor's
|
|
IF bDoMaryAnnOneliner
|
|
// If the player's ahead, do one of Mary Ann's "behind" one liners
|
|
IF iRacePos = 1
|
|
IF iWomanBehindOnelinersPlayed < NUM_WOMAN_BEHIND_ONELINERS
|
|
IF CREATE_CONVERSATION(sWomanConversation, "FAN2AU", "FAN2_BEHIND", CONV_PRIORITY_HIGH)
|
|
RCM_DEBUG_PRINT("*** Doing Behind line")
|
|
iWomanBehindOnelinersPlayed++
|
|
bPlayedBanterOneliner = TRUE
|
|
ENDIF
|
|
ELSE
|
|
RCM_DEBUG_PRINT("*** Tried doing a Behind one-liner, but have run out!")
|
|
iBanterTimer = GET_GAME_TIMER()
|
|
BanterState = BANTER_WAIT
|
|
ConvState = FAN2_CONV_STATE_FREE
|
|
ENDIF
|
|
// Otherwise, she's ahead, so do one of those instead
|
|
ELSE
|
|
IF iWomanAheadOnelinersPlayed < NUM_WOMAN_AHEAD_ONELINERS
|
|
IF CREATE_CONVERSATION(sWomanConversation, "FAN2AU", "FAN2_AHEAD", CONV_PRIORITY_HIGH)
|
|
RCM_DEBUG_PRINT("*** Doing Ahead line")
|
|
iWomanAheadOnelinersPlayed++
|
|
bPlayedBanterOneliner = TRUE
|
|
ENDIF
|
|
ELSE
|
|
RCM_DEBUG_PRINT("*** Tried doing an Ahead one-liner, but have run out!")
|
|
iBanterTimer = GET_GAME_TIMER()
|
|
BanterState = BANTER_WAIT
|
|
ConvState = FAN2_CONV_STATE_FREE
|
|
ENDIF
|
|
ENDIF
|
|
ELSE
|
|
IF iTrevorOnelinersPlayed < NUM_TREVOR_ONELINERS
|
|
IF CREATE_CONVERSATION(sWomanConversation, "FAN2AU", "FAN2_TREV1L", CONV_PRIORITY_HIGH)
|
|
RCM_DEBUG_PRINT("*** Doing Trevor one-liner")
|
|
iTrevorOnelinersPlayed++
|
|
bPlayedBanterOneliner = TRUE
|
|
ENDIF
|
|
ELSE
|
|
RCM_DEBUG_PRINT("*** Tried doing a Trevor one-liner, but have run out!")
|
|
iBanterTimer = GET_GAME_TIMER()
|
|
BanterState = BANTER_WAIT
|
|
ConvState = FAN2_CONV_STATE_FREE
|
|
ENDIF
|
|
ENDIF
|
|
ELSE
|
|
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
|
|
RCM_DEBUG_PRINT("*** Oneliner over, conv state free")
|
|
bPlayedBanterOneliner = FALSE
|
|
iBanterTimer = GET_GAME_TIMER()
|
|
BanterState = BANTER_WAIT
|
|
ConvState = FAN2_CONV_STATE_FREE
|
|
ENDIF
|
|
ENDIF
|
|
BREAK
|
|
ENDSWITCH
|
|
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Manage Mary Ann's bike speed during the race using rubber-banding
|
|
PROC RCM_MANAGE_BIKE_SPEED()
|
|
|
|
FLOAT fDist
|
|
FLOAT fPlaybackModifier
|
|
|
|
IF RCM_IS_PLAYER_OK()
|
|
IF IS_VEHICLE_OK(vehBike[MARY_ANN_BIKE_ID])
|
|
|
|
fDist = GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), GET_ENTITY_COORDS(vehBike[MARY_ANN_BIKE_ID]))
|
|
IF fDist > 60
|
|
fDist = 60
|
|
ENDIF
|
|
fPlaybackModifier = (fDist / 50) * 1.6
|
|
IF IS_WAYPOINT_PLAYBACK_GOING_ON_FOR_VEHICLE(vehBike[MARY_ANN_BIKE_ID])
|
|
// We get the nearest waypoint to the opponent's current position...
|
|
int iCurrWaypoint
|
|
|
|
WAYPOINT_RECORDING_GET_CLOSEST_WAYPOINT("Fan2_BikeRoute", GET_ENTITY_COORDS(vehBike[MARY_ANN_BIKE_ID]), iCurrWaypoint)
|
|
// ... and then dial-down the speed of that waypoint to set the opponent's rubber-banded speed
|
|
float fPlaybackSpd = WAYPOINT_RECORDING_GET_SPEED_AT_POINT("Fan2_BikeRoute", iCurrWaypoint)
|
|
// Going to globally increase the playback speed because it's too slow by default
|
|
FLOAT fGlobalIncrease
|
|
// IF iCurrWaypoint > 150
|
|
// fGlobalIncrease = 3.8 // Go a little slower on the final stretch to give the player more of a chance
|
|
// ELSE
|
|
fGlobalIncrease = 4.8
|
|
// ENDIF
|
|
fPlaybackSpd = fPlaybackSpd + fGlobalIncrease
|
|
// The ratio modifier is by default calculated for on-foot speeds at 0.2, 0.3, etc
|
|
// Here, we want it to apply to vehicle values, between 2.0, 3.0, etc - so multiply by 10
|
|
IF iRacePos = 2
|
|
fPlaybackSpd = (fPlaybackSpd - fPlaybackModifier - 0.5) // If player is behind, decrease speed/do nothing
|
|
ELSE
|
|
fPlaybackSpd = (fPlaybackSpd + fPlaybackModifier + 2.0) // If player is ahead, increase speed
|
|
ENDIF
|
|
IF bDebugPrintBikePlaybackSpeed = TRUE
|
|
RCM_DEBUG_PRINTBIKESPEED("Player fDist=", fDist, " fPlaybackModifier=", fPlaybackModifier, " Final fPlaybackSpeed=", fPlaybackSpd)
|
|
IF IS_ENTITY_ALIVE(sRCLauncherDataLocal.pedID[MARY_ANN_ID])
|
|
RCM_DEBUG_PRINTFLOAT("Actual opponent speed= ", GET_ENTITY_SPEED(sRCLauncherDataLocal.pedID[MARY_ANN_ID]))
|
|
ENDIF
|
|
ENDIF
|
|
|
|
VEHICLE_WAYPOINT_PLAYBACK_OVERRIDE_SPEED(vehBike[MARY_ANN_BIKE_ID], fPlaybackSpd)
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Enable the hint camera during the race when Mary Ann is close enough to Trevor
|
|
PROC RCM_DO_HINT_CAM()
|
|
|
|
IF IS_VEHICLE_OK(vehBike[MARY_ANN_BIKE_ID])
|
|
IF GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), GET_ENTITY_COORDS(vehBike[MARY_ANN_BIKE_ID])) <= 50
|
|
IF iRacePos = 2 // Only enable when behind
|
|
CONTROL_VEHICLE_CHASE_HINT_CAM_IN_VEHICLE(localChaseHintCamStruct, vehBike[MARY_ANN_BIKE_ID])
|
|
ELSE
|
|
KILL_CHASE_HINT_CAM(localChaseHintCamStruct)
|
|
ENDIF
|
|
ELSE
|
|
KILL_CHASE_HINT_CAM(localChaseHintCamStruct)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
FUNC INT GET_WAYPOINT_FOR_CHECKPOINT(INT iCheckpoint)
|
|
|
|
SWITCH iCheckpoint
|
|
CASE 0
|
|
CASE 1
|
|
CASE 2
|
|
RETURN 10
|
|
BREAK
|
|
CASE 3
|
|
RETURN 17
|
|
BREAK
|
|
CASE 4
|
|
RETURN 22
|
|
BREAK
|
|
CASE 5
|
|
RETURN 29
|
|
BREAK
|
|
CASE 6
|
|
RETURN 37
|
|
BREAK
|
|
CASE 7
|
|
RETURN 43
|
|
BREAK
|
|
CASE 8
|
|
RETURN 50
|
|
BREAK
|
|
CASE 9
|
|
RETURN 58
|
|
BREAK
|
|
CASE 10
|
|
RETURN 67
|
|
BREAK
|
|
CASE 11
|
|
RETURN 77
|
|
BREAK
|
|
CASE 12
|
|
RETURN 81
|
|
BREAK
|
|
CASE 13
|
|
RETURN 90
|
|
BREAK
|
|
CASE 14
|
|
RETURN 101
|
|
BREAK
|
|
CASE 15
|
|
RETURN 110
|
|
BREAK
|
|
CASE 16
|
|
RETURN 116
|
|
BREAK
|
|
CASE 17
|
|
RETURN 121
|
|
BREAK
|
|
CASE 18
|
|
RETURN 124
|
|
BREAK
|
|
CASE 19
|
|
RETURN 129
|
|
BREAK
|
|
CASE 20
|
|
RETURN 137
|
|
BREAK
|
|
CASE 21
|
|
RETURN 144
|
|
BREAK
|
|
CASE 22
|
|
RETURN 151
|
|
BREAK
|
|
CASE 23
|
|
RETURN 157
|
|
BREAK
|
|
CASE 24
|
|
RETURN 167
|
|
BREAK
|
|
CASE 25
|
|
RETURN 176
|
|
BREAK
|
|
CASE 26
|
|
RETURN 184
|
|
BREAK
|
|
DEFAULT
|
|
RETURN 0
|
|
BREAK
|
|
ENDSWITCH
|
|
|
|
RETURN 0
|
|
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// If Mary Ann gets knocked off course, this should set her next checkpoint correctly so the race still tracks as it should
|
|
/// PARAMS:
|
|
/// iNewWaypoint - The waypoint Mary Ann's been teleported too
|
|
PROC SET_RECOVERED_CHECKPOINT(int iNewWaypoint)
|
|
|
|
if iNewWaypoint <= 10
|
|
iWomanNextCheckpoint = 2
|
|
ELIF iNewWaypoint <= 17
|
|
iWomanNextCheckpoint = 3
|
|
ELIF iNewWaypoint <= 22
|
|
iWomanNextCheckpoint = 4
|
|
ELIF iNewWaypoint <= 29
|
|
iWomanNextCheckpoint = 5
|
|
ELIF iNewWaypoint <= 37
|
|
iWomanNextCheckpoint = 6
|
|
ELIF iNewWaypoint <= 43
|
|
iWomanNextCheckpoint = 7
|
|
ELIF iNewWaypoint <= 50
|
|
iWomanNextCheckpoint = 8
|
|
ELIF iNewWaypoint <= 58
|
|
iWomanNextCheckpoint = 9
|
|
ELIF iNewWaypoint <= 67
|
|
iWomanNextCheckpoint = 10
|
|
ELIF iNewWaypoint <= 77
|
|
iWomanNextCheckpoint = 11
|
|
ELIF iNewWaypoint <= 81
|
|
iWomanNextCheckpoint = 12
|
|
ELIF iNewWaypoint <= 90
|
|
iWomanNextCheckpoint = 13
|
|
ELIF iNewWaypoint <= 101
|
|
iWomanNextCheckpoint = 14
|
|
ELIF iNewWaypoint <= 110
|
|
iWomanNextCheckpoint = 15
|
|
ELIF iNewWaypoint <= 116
|
|
iWomanNextCheckpoint = 16
|
|
ELIF iNewWaypoint <= 121
|
|
iWomanNextCheckpoint = 17
|
|
ELIF iNewWaypoint <= 124
|
|
iWomanNextCheckpoint = 18
|
|
ELIF iNewWaypoint <= 129
|
|
iWomanNextCheckpoint = 19
|
|
ELIF iNewWaypoint <= 137
|
|
iWomanNextCheckpoint = 20
|
|
ELIF iNewWaypoint <= 144
|
|
iWomanNextCheckpoint = 21
|
|
ELIF iNewWaypoint <= 151
|
|
iWomanNextCheckpoint = 22
|
|
ELIF iNewWaypoint <= 157
|
|
iWomanNextCheckpoint = 23
|
|
ELIF iNewWaypoint <= 167
|
|
iWomanNextCheckpoint = 24
|
|
ELIF iNewWaypoint <= 176
|
|
iWomanNextCheckpoint = 25
|
|
ELIF iNewWaypoint <= 184
|
|
iWomanNextCheckpoint = 26
|
|
ENDIF
|
|
|
|
RCM_DEBUG_PRINTINT("*** Recovery race checkpoint for Mary Ann set to: ", iWomanNextCheckpoint)
|
|
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Keep track of Mary Ann's checkpoint progress during the race
|
|
PROC RCM_UPDATE_WOMAN_CHECKPOINTS()
|
|
|
|
FLOAT fDistPlayer, fDistWoman
|
|
|
|
IF IS_ENTITY_AT_COORD(sRCLauncherDataLocal.pedID[MARY_ANN_ID], raceInfo.checkPos[iWomanNextCheckpoint], <<MA_CHECKPOINTSIZE, MA_CHECKPOINTSIZE, MA_CHECKPOINTSIZE>>, FALSE)
|
|
iWomanNextCheckpoint++
|
|
RCM_DEBUG_PRINTINT("Next Mary Ann checkpoint: ", iWomanNextCheckpoint)
|
|
//RCM_DEBUG_PRINTINT("Current closest WP:", iClosestWaypoint)
|
|
IF iWomanNextCheckpoint = 22
|
|
SET_DRIVE_TASK_DRIVING_STYLE(sRCLauncherDataLocal.pedID[MARY_ANN_ID], ENUM_TO_INT(DRIVINGMODE_AVOIDCARS_RECKLESS))
|
|
RCM_DEBUG_PRINT("Also setting Mary Ann to never go offroad")
|
|
ENDIF
|
|
ENDIF
|
|
IF iWomanNextCheckpoint >= MAX_CHECKPOINTS // Woman has finished so stop any further checking
|
|
iRacePos = 2
|
|
bLostRace = TRUE
|
|
RCM_DEBUG_PRINT("You lost!")
|
|
ELSE
|
|
// If Mary Ann misses a checkpoint, this should recover her
|
|
IF iWomanNextCheckpoint > 2
|
|
IF (GET_WAYPOINT_FOR_CHECKPOINT(iWomanNextCheckpoint)+10) < (iClosestWaypoint)
|
|
RCM_DEBUG_PRINTINT("iWomanNextCheckpoint+10 is ", (iWomanNextCheckpoint+10))
|
|
RCM_DEBUG_PRINTINT("but iClosestWaypoint is ", iClosestWaypoint)
|
|
RCM_DEBUG_PRINT("Re-setting Mary Ann's current checkpoint...")
|
|
SET_RECOVERED_CHECKPOINT(iClosestWaypoint)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF iWomanNextCheckpoint > playerInfo.currentCheck
|
|
IF iRacePos != 2
|
|
iRacePos = 2
|
|
ENDIF
|
|
ELIF iWomanNextCheckpoint < playerInfo.currentCheck
|
|
IF iRacePos != 1
|
|
iRacePos = 1
|
|
IF (GET_GAME_TIMER() - iOvertakeSpamTimer) > 3000
|
|
bOvertakeOccurred = TRUE
|
|
iConversationGapTimer = GET_GAME_TIMER()
|
|
ENDIF
|
|
ENDIF
|
|
ELSE
|
|
IF RCM_IS_PLAYER_OK()
|
|
fDistPlayer = GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), raceInfo.checkPos[playerInfo.currentCheck])
|
|
ENDIF
|
|
IF IS_ENTITY_ALIVE(sRCLauncherDataLocal.pedID[MARY_ANN_ID])
|
|
fDistWoman = GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(sRCLauncherDataLocal.pedID[MARY_ANN_ID]), raceInfo.checkPos[iWomanNextCheckpoint])
|
|
ENDIF
|
|
IF fDistPlayer > fDistWoman
|
|
IF iRacePos != 2
|
|
iRacePos = 2
|
|
ENDIF
|
|
ELSE
|
|
IF iRacePos != 1
|
|
iRacePos = 1
|
|
IF (GET_GAME_TIMER() - iOvertakeSpamTimer) > 3000
|
|
bOvertakeOccurred = TRUE
|
|
iConversationGapTimer = GET_GAME_TIMER()
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Handle ending the race early and failing the mission when this is called
|
|
PROC RCM_END_RACE_EARLY()
|
|
|
|
if bLostRace
|
|
//RCM_MISSION_FAILED(FAILED_LOST_RACE)
|
|
RCM_ADVANCE_STAGE() // Go to Outro
|
|
ELSE
|
|
// Fail the race if the player gets too far away
|
|
IF iRacePos = 2
|
|
IF RCM_IS_PLAYER_OK()
|
|
IF IS_ENTITY_ALIVE(sRCLauncherDataLocal.pedID[MARY_ANN_ID])
|
|
if GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), GET_ENTITY_COORDS(sRCLauncherDataLocal.pedID[MARY_ANN_ID])) > LOST_RANGE
|
|
RCM_MISSION_FAILED(FAILED_LEFT_BEHIND)
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
if GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), raceInfo.checkPos[playerInfo.currentCheck]) > 130
|
|
IF playerInfo.currentCheck+1 <= raceInfo.totalChecks // Make sure we don't go array out of bounds if the player is abandoning the race at the last checkpoint
|
|
IF GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), raceInfo.checkPos[playerInfo.currentCheck+1]) < 100
|
|
RCM_MISSION_FAILED(FAILED_MISSED_CHECK)
|
|
ELSE
|
|
RCM_MISSION_FAILED(FAILED_ABANDONED)
|
|
ENDIF
|
|
ELSE
|
|
RCM_MISSION_FAILED(FAILED_ABANDONED)
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
PROC RECOVER_FROM_PUSH()
|
|
|
|
// I'd rather have these in the appropriate parts of the recover functionality, but the compiler doesn't like them being defined in a switch... oh well...
|
|
VECTOR vWaypointTeleTo
|
|
VECTOR vWaypointTeleNext
|
|
FLOAT fOldSpeed
|
|
|
|
SWITCH RecoverState
|
|
CASE RECOVER_WAIT
|
|
// Do nothing - CHECK_PUSHING() will change this if it's needed
|
|
BREAK
|
|
CASE RECOVER_NEEDED
|
|
WAYPOINT_RECORDING_GET_COORD("Fan2_BikeRoute", iRecoverWaypoint, vWaypointTeleTo)
|
|
IF IS_VEHICLE_OK(vehBike[MARY_ANN_BIKE_ID])
|
|
IF GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(vehBike[MARY_ANN_BIKE_ID]), vWaypointTeleTo) < 2.0
|
|
RCM_DEBUG_PRINTINT("*** Mary Ann seems to have got herself back on track, carrying on as normal from #", iRecoverWaypoint)
|
|
SET_RECOVERED_CHECKPOINT(iRecoverWaypoint)
|
|
RecoverState = RECOVER_WAIT
|
|
ENDIF
|
|
// Recover when we can't see Mary Ann or if 2.5 seconds pass after she's been pushed off-course
|
|
IF (NOT IS_SPHERE_VISIBLE(GET_ENTITY_COORDS(vehBike[MARY_ANN_BIKE_ID]), 3)
|
|
AND NOT IS_SPHERE_VISIBLE(vWaypointTeleTo, 3))
|
|
OR (GET_GAME_TIMER() - iRecoverTimer) > 2500
|
|
RecoverState = RECOVER_RECOVERING
|
|
ENDIF
|
|
ENDIF
|
|
BREAK
|
|
CASE RECOVER_RECOVERING
|
|
WAYPOINT_RECORDING_GET_COORD("Fan2_BikeRoute", iRecoverWaypoint, vWaypointTeleTo)
|
|
WAYPOINT_RECORDING_GET_COORD("Fan2_BikeRoute", iRecoverWaypoint+1, vWaypointTeleNext)
|
|
|
|
IF IS_VEHICLE_OK(vehBike[MARY_ANN_BIKE_ID])
|
|
AND IS_ENTITY_ALIVE(sRCLauncherDataLocal.pedID[MARY_ANN_ID])
|
|
fOldSpeed = GET_ENTITY_SPEED(sRCLauncherDataLocal.pedID[MARY_ANN_ID])
|
|
SET_ENTITY_COORDS(vehBike[MARY_ANN_BIKE_ID], vWaypointTeleTo)
|
|
SET_ENTITY_HEADING_FACE_COORDS(vehBike[MARY_ANN_BIKE_ID], vWaypointTeleNext) // Face next checkpoint
|
|
IF NOT IS_PED_IN_VEHICLE(sRCLauncherDataLocal.pedID[MARY_ANN_ID], vehBike[MARY_ANN_BIKE_ID])
|
|
SET_PED_INTO_VEHICLE(sRCLauncherDataLocal.pedID[MARY_ANN_ID], vehBike[MARY_ANN_BIKE_ID])
|
|
ENDIF
|
|
TASK_VEHICLE_FOLLOW_WAYPOINT_RECORDING(sRCLauncherDataLocal.pedID[MARY_ANN_ID], vehBike[MARY_ANN_BIKE_ID], "Fan2_BikeRoute", DRIVINGMODE_AVOIDCARS_RECKLESS, 0,
|
|
EWAYPOINT_START_FROM_CLOSEST_POINT)
|
|
SET_VEHICLE_FORWARD_SPEED(vehBike[MARY_ANN_BIKE_ID], fOldSpeed)
|
|
RCM_DEBUG_PRINTINT("*** Teleported Mary Ann to waypoint ", iRecoverWaypoint)
|
|
SET_RECOVERED_CHECKPOINT(iRecoverWaypoint)
|
|
RecoverState = RECOVER_WAIT
|
|
ENDIF
|
|
BREAK
|
|
ENDSWITCH
|
|
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Check for the player trying to push Mary Ann off the track and fail if she actually goes off one of the cliffs
|
|
PROC RCM_CHECK_PUSHING()
|
|
IF NOT bGivePushWarning
|
|
IF (GET_GAME_TIMER() - iPushTimer) > 3000
|
|
IF IS_VEHICLE_OK(vehBike[PLAYER_BIKE_ID]) AND IS_VEHICLE_OK(vehBike[MARY_ANN_BIKE_ID])
|
|
IF IS_ENTITY_TOUCHING_ENTITY(vehBike[PLAYER_BIKE_ID], vehBike[MARY_ANN_BIKE_ID])
|
|
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
|
|
bGivePushWarning = TRUE
|
|
INFORM_STAT_SYSTEM_OF_BOOL_STAT_HAPPENED(FA2_BUMPED_INTO_MARY_ANN)
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF IS_VEHICLE_OK(vehBike[PLAYER_BIKE_ID]) AND IS_VEHICLE_OK(vehBike[MARY_ANN_BIKE_ID])
|
|
IF IS_ENTITY_TOUCHING_ENTITY(vehBike[PLAYER_BIKE_ID], vehBike[MARY_ANN_BIKE_ID])
|
|
VECTOR pushDir = -GET_OFFSET_FROM_ENTITY_GIVEN_WORLD_COORDS(vehBike[MARY_ANN_BIKE_ID], GET_ENTITY_COORDS(PLAYER_PED_ID()))
|
|
APPLY_FORCE_TO_ENTITY(vehBike[PLAYER_BIKE_ID], APPLY_TYPE_IMPULSE, pushDir, <<0,0,0>>, 0, FALSE, FALSE, TRUE)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF IS_VEHICLE_OK(vehBike[MARY_ANN_BIKE_ID])
|
|
IF IS_WAYPOINT_PLAYBACK_GOING_ON_FOR_VEHICLE(vehBike[MARY_ANN_BIKE_ID])
|
|
WAYPOINT_RECORDING_GET_CLOSEST_WAYPOINT("Fan2_BikeRoute", GET_ENTITY_COORDS(vehBike[MARY_ANN_BIKE_ID]), iClosestWaypoint)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF IS_VEHICLE_OK(vehBike[MARY_ANN_BIKE_ID])
|
|
AND RecoverState != RECOVER_NEEDED
|
|
// Vinewood sign hillside
|
|
IF IS_ENTITY_IN_ANGLED_AREA(vehBike[MARY_ANN_BIKE_ID], <<797.198792,1150.204712,297.759247>>, <<636.304688,1194.311279,323.591858>>, 33.75)
|
|
OR IS_ENTITY_IN_ANGLED_AREA(vehBike[MARY_ANN_BIKE_ID], <<529.257446,1137.587402,244.045837>>, <<636.878784,1189.193604,321.858551>>, 33.75)
|
|
OR IS_ENTITY_IN_ANGLED_AREA(vehBike[MARY_ANN_BIKE_ID], <<595.232422,1124.200073,260.294556>>, <<497.323914,1209.940552,306.278442>>, 30.75)
|
|
OR IS_ENTITY_IN_ANGLED_AREA(vehBike[MARY_ANN_BIKE_ID], <<510.078430,1209.081177,266.611572>>, <<446.286285,1214.469727,295.925415>>, 30.75)
|
|
OR IS_ENTITY_IN_ANGLED_AREA(vehBike[MARY_ANN_BIKE_ID], <<433.502319,1264.279175,259.039734>>, <<440.984833,1213.486572,275.721893>>, 18.0)
|
|
OR IS_ENTITY_IN_ANGLED_AREA(vehBike[MARY_ANN_BIKE_ID], <<436.522522,1281.198608,263.654968>>, <<435.094818,1271.009155,277.885498>>, 11.5)
|
|
OR IS_ENTITY_IN_ANGLED_AREA(vehBike[MARY_ANN_BIKE_ID], <<441.861053,1238.899902,260.414825>>, <<458.780121,1220.360718,283.416473>>, 11.5)
|
|
// Second dirt path leading to forest
|
|
OR IS_ENTITY_IN_ANGLED_AREA(vehBike[MARY_ANN_BIKE_ID], <<451.618958,1060.920654,212.001404>>, <<434.743774,1015.888184,251.338745>>, 14.0)
|
|
OR IS_ENTITY_IN_ANGLED_AREA(vehBike[MARY_ANN_BIKE_ID], <<442.671234,1022.329163,210.537384>>, <<387.165100,1018.869751,244.841858>>, 14.0)
|
|
// Forest area
|
|
OR IS_ENTITY_IN_ANGLED_AREA(vehBike[MARY_ANN_BIKE_ID], <<374.609375,1002.934387,187.244186>>, <<353.487640,1095.726318,253.139267>>, 14.0)
|
|
OR IS_ENTITY_IN_ANGLED_AREA(vehBike[MARY_ANN_BIKE_ID], <<362.522095,1059.685425,209.332779>>, <<302.626556,1158.892700,250.179825>>, 14.0)
|
|
OR IS_ENTITY_IN_ANGLED_AREA(vehBike[MARY_ANN_BIKE_ID], <<279.92, 1234.31 ,209.726959>>, <<305.605835,1150.026855,246.750626>>, 15.0)
|
|
RecoverState = RECOVER_NEEDED
|
|
IF IS_WAYPOINT_PLAYBACK_GOING_ON_FOR_VEHICLE(vehBike[MARY_ANN_BIKE_ID])
|
|
WAYPOINT_RECORDING_GET_CLOSEST_WAYPOINT("Fan2_BikeRoute", GET_ENTITY_COORDS(vehBike[MARY_ANN_BIKE_ID]), iRecoverWaypoint)
|
|
ENDIF
|
|
iRecoverTimer = GET_GAME_TIMER()
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// Keep checking if we need to recover from a push
|
|
RECOVER_FROM_PUSH()
|
|
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Give the player a verbal warning from Mary Ann about pushing her if able
|
|
/// This needs to repeat until the warning has actually been given, since it takes a while for the conversation to build
|
|
PROC RCM_DO_PUSH_WARNING()
|
|
IF bGivePushWarning
|
|
IF CREATE_CONVERSATION(sWomanConversation, "FAN2AU", "FAN2_PUSH", CONV_PRIORITY_HIGH)
|
|
bGivePushWarning = FALSE
|
|
iPushTimer = GET_GAME_TIMER()
|
|
ENDIF
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Handle changing around Mary Ann's AI style during the race
|
|
/// This exists to try and solve B*595794, to make Mary Ann smash through the joggers instead of trying to avoid them and getting knocked off the cliff
|
|
PROC RCM_HANDLE_MARY_ANN_AI_STYLE()
|
|
|
|
IF IS_ENTITY_ALIVE(sRCLauncherDataLocal.pedID[MARY_ANN_ID])
|
|
// IF IS_ENTITY_IN_ANGLED_AREA(sRCLauncherDataLocal.pedID[MARY_ANN_ID], <<720.957031,1197.793579,324.516602>>, <<722.723145,1212.702637,328.908997>>, 2.000000)
|
|
// RCM_DEBUG_PRINT("*** Setting Mary Ann to PloughThrough")
|
|
// SET_DRIVE_TASK_DRIVING_STYLE(sRCLauncherDataLocal.pedID[MARY_ANN_ID], ENUM_TO_INT(DRIVINGMODE_PLOUGHTHROUGH))
|
|
// ENDIF
|
|
|
|
IF IS_ENTITY_IN_ANGLED_AREA(sRCLauncherDataLocal.pedID[MARY_ANN_ID], <<591.093323,1192.419312,305.529022>>, <<585.452881,1205.725464,311.526031>>, 2.000000)
|
|
RCM_DEBUG_PRINT("*** Setting Mary Ann to AvoidCars_Reckless (if this works)")
|
|
SET_DRIVE_TASK_DRIVING_STYLE(sRCLauncherDataLocal.pedID[MARY_ANN_ID], ENUM_TO_INT(DRIVINGMODE_AVOIDCARS_RECKLESS))
|
|
ENDIF
|
|
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Main Countdown state loop
|
|
PROC MS_COUNTDOWN()
|
|
|
|
INT i
|
|
|
|
IF RCM_INIT_STAGE()
|
|
|
|
HIDE_STREET_AND_CAR_NAMES_THIS_FRAME()
|
|
|
|
RCM_DEBUG_PRINT("Init MS_COUNTDOWN")
|
|
FORCE_RENDER_IN_GAME_UI(FALSE)
|
|
|
|
raceInfo.sourcePos = vLongRaceStart[0]
|
|
raceInfo.sourceHeading = fLongRaceStart[0]
|
|
playerInfo.currentCheck = 1
|
|
playerInfo.nextCheck = 2
|
|
|
|
RCM_RESET_CONVERSATIONS()
|
|
|
|
IF bUsedSkip
|
|
or bIntroSkipped
|
|
RCM_DEBUG_PRINT("Doing Countdown init reset...")
|
|
//RESET_BIKES()
|
|
RESET_MARY_ANN()
|
|
SET_GAMEPLAY_CAM_RELATIVE_PITCH()
|
|
SET_GAMEPLAY_CAM_RELATIVE_HEADING()
|
|
RC_END_CUTSCENE_MODE()
|
|
ENDIF
|
|
|
|
RCM_SETUP_RACE_INFO()
|
|
|
|
IF IS_VEHICLE_OK(vehBike[PLAYER_BIKE_ID])
|
|
IF RCM_IS_PLAYER_OK()
|
|
bDoBikeExit = TRUE
|
|
SET_VEHICLE_FORWARD_SPEED(vehBike[PLAYER_BIKE_ID], START_SPEED)
|
|
ENDIF
|
|
ELSE
|
|
RCM_DEBUG_PRINT("No bike in MS_COUNTDOWN init?")
|
|
ENDIF
|
|
|
|
IF bDoneTrevExit
|
|
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
|
|
SET_PED_RESET_FLAG(PLAYER_PED_ID(), PRF_PreventGoingIntoStillInVehicleState, TRUE)
|
|
RCM_DEBUG_PRINT("Setting PRF_PreventGoingIntoStillInVehicleState on Trevor")
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF IS_VEHICLE_OK(vehBike[MARY_ANN_BIKE_ID])
|
|
IF IS_ENTITY_ALIVE(sRCLauncherDataLocal.pedID[MARY_ANN_ID])
|
|
SET_PED_CAN_BE_KNOCKED_OFF_VEHICLE(sRCLauncherDataLocal.pedID[MARY_ANN_ID], KNOCKOFFVEHICLE_NEVER)
|
|
SET_ENTITY_CAN_BE_DAMAGED(vehBike[MARY_ANN_BIKE_ID], FALSE)
|
|
SET_VEHICLE_DOORS_LOCKED(vehBike[MARY_ANN_BIKE_ID], VEHICLELOCK_LOCKOUT_PLAYER_ONLY)
|
|
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(sRCLauncherDataLocal.pedID[MARY_ANN_ID], TRUE)
|
|
SET_ENTITY_LOAD_COLLISION_FLAG(sRCLauncherDataLocal.pedID[MARY_ANN_ID], TRUE)
|
|
SET_DRIVER_RACING_MODIFIER(sRCLauncherDataLocal.pedID[MARY_ANN_ID], 1.0)
|
|
MODIFY_VEHICLE_TOP_SPEED(vehBike[MARY_ANN_BIKE_ID], 125.0)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF bIntroSkipped
|
|
OR IS_REPLAY_IN_PROGRESS()
|
|
iWomanNextCheckpoint = 2 // Start opponent from checkpoint 2 as the extra distance when skipping the intro makes her skip 1
|
|
ELSE
|
|
iWomanNextCheckpoint = 1 // Start opponent from checkpoint 1 normally as the rolling start recording doesn't take us through 0
|
|
ENDIF
|
|
|
|
iRacePos = 2
|
|
bPlayerIsOnBike = TRUE
|
|
iRoadRageConversationsPlayed = 0
|
|
iWomanConversationsPlayed = 0
|
|
i = 0
|
|
REPEAT NUM_ROAD_RAGE_CONVERSATIONS i
|
|
bPlayedRoadRageConversation[i] = FALSE
|
|
ENDREPEAT
|
|
|
|
IF DOES_OBJECT_OF_TYPE_EXIST_AT_COORDS(<<801.714844,1270.138306,359.285522>>, 6.0, prop_fnclink_03gate1)
|
|
RCM_DEBUG_PRINT("Unlock gate 1.")
|
|
SET_STATE_OF_CLOSEST_DOOR_OF_TYPE(prop_fnclink_03gate1, <<801.714844,1270.138306,359.285522>>, FALSE, 0.0)
|
|
ENDIF
|
|
IF DOES_OBJECT_OF_TYPE_EXIST_AT_COORDS(<<802.921814,1281.675049,359.296234>>, 6.0, prop_fnclink_03gate1)
|
|
RCM_DEBUG_PRINT("Unlock gate 2.")
|
|
SET_STATE_OF_CLOSEST_DOOR_OF_TYPE(prop_fnclink_03gate1, <<802.921814,1281.675049,359.296234>>, FALSE, 0.0)
|
|
ENDIF
|
|
|
|
IF bUsedSkip
|
|
TRIGGER_MUSIC_EVENT("FANATIC2_RESTART1")
|
|
ELSE
|
|
TRIGGER_MUSIC_EVENT("FANATIC2_START")
|
|
ENDIF
|
|
|
|
IF NOT IS_AUDIO_SCENE_ACTIVE("FANATIC_MIX_SCENE")
|
|
START_AUDIO_SCENE("FANATIC_MIX_SCENE")
|
|
IF IS_ENTITY_ALIVE(sRCLauncherDataLocal.pedID[MARY_ANN_ID])
|
|
ADD_ENTITY_TO_AUDIO_MIX_GROUP(sRCLauncherDataLocal.pedID[MARY_ANN_ID],"FANATIC_MIX_MARY_ANNE")
|
|
ENDIF
|
|
IF IS_ENTITY_ALIVE(vehBike[MARY_ANN_BIKE_ID])
|
|
RCM_DEBUG_PRINT("Trying to add Mary Ann's bike to mix group...")
|
|
ADD_ENTITY_TO_AUDIO_MIX_GROUP(vehBike[MARY_ANN_BIKE_ID],"FANATIC_MIX_MARY_BIKE")
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// If we're in a replay, fade the screen in now
|
|
IF IS_REPLAY_IN_PROGRESS()
|
|
SETTIMERA(0)
|
|
IF IS_REPLAY_BEING_SET_UP()
|
|
END_REPLAY_SETUP(vehBike[PLAYER_BIKE_ID])
|
|
ENDIF
|
|
WHILE TIMERA() < 750 // Game timer is paused during replays, use TimerA instead!
|
|
WAIT(0)
|
|
RCM_DEBUG_PRINT("In fade in wait...")
|
|
// If we're waiting for the fade, keep doing the rolling start
|
|
IF IS_VEHICLE_OK(vehBike[PLAYER_BIKE_ID])
|
|
SET_VEHICLE_FORWARD_SPEED(vehBike[PLAYER_BIKE_ID], START_SPEED)
|
|
ENDIF
|
|
ENDWHILE
|
|
RC_END_Z_SKIP()
|
|
ELSE
|
|
IF bIntroSkipped
|
|
WHILE (GET_GAME_TIMER() - iFadeTimer) < 1250
|
|
WAIT(0)
|
|
RCM_DEBUG_PRINT("In fade wait...")
|
|
// If we're waiting for the fade, keep doing the rolling start
|
|
IF IS_VEHICLE_OK(vehBike[PLAYER_BIKE_ID])
|
|
SET_VEHICLE_FORWARD_SPEED(vehBike[PLAYER_BIKE_ID], START_SPEED)
|
|
ENDIF
|
|
ENDWHILE
|
|
SAFE_FADE_SCREEN_IN_FROM_BLACK(DEFAULT, FALSE)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF bUsedSkip
|
|
or bIntroSkipped
|
|
bIntroSkipped = FALSE
|
|
bUsedSkip = FALSE
|
|
bPlayedFinalConv = FALSE
|
|
SAFE_DELETE_PED(piJogger1) // Deleting the joggers so we see them again if we've skipped back to the start of the race
|
|
SAFE_DELETE_PED(piJogger2) // if the player's skipped the intro, they won't exist yet anyway, so this is safe...
|
|
ENDIF
|
|
|
|
RESET_PLAYER_STAMINA(PLAYER_ID())
|
|
|
|
PRINT_NOW("FAN2_OBJ", DEFAULT_GOD_TEXT_TIME, 1)
|
|
|
|
start_time = GET_GAME_TIMER()
|
|
iCountdown = GET_GAME_TIMER()
|
|
|
|
RCM_DEBUG_PRINT("Running MS_COUNTDOWN")
|
|
|
|
ELSE
|
|
|
|
//HIDE_HUD_AND_RADAR_THIS_FRAME()
|
|
HIDE_STREET_AND_CAR_NAMES_THIS_FRAME()
|
|
SET_FAR_RIGHT_TITLE_POSITION_HUD_THIS_FRAME()
|
|
DRAW_RACE_HUD((GET_GAME_TIMER() - start_time), "", -1, -1, "", iRacePos, 2)
|
|
RUN_PLAYER_CHECKPOINTS_AND_BLIPS(playerInfo, raceInfo)
|
|
RCM_DEATH_CHECKS()
|
|
RCM_DO_HINT_CAM()
|
|
RCM_UPDATE_WOMAN_CHECKPOINTS() // Need to start checking this now because Mary-Ann goes through a checkpoint in the rolling start
|
|
|
|
IF bDoBikeExit
|
|
RCM_DEBUG_PRINT("Continuing push")
|
|
IF IS_VEHICLE_OK(vehBike[PLAYER_BIKE_ID])
|
|
SET_VEHICLE_FORWARD_SPEED(vehBike[PLAYER_BIKE_ID], START_SPEED)
|
|
ENDIF
|
|
IF HAS_PLAYER_TOUCHED_STEERING_CONTROLS()
|
|
bDoBikeExit = FALSE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF (GET_GAME_TIMER() - iCountdown) > 2000
|
|
IF IS_VEHICLE_OK(vehBike[PLAYER_BIKE_ID])
|
|
IF IS_PLAYBACK_GOING_ON_FOR_VEHICLE(vehBike[PLAYER_BIKE_ID])
|
|
STOP_PLAYBACK_RECORDED_VEHICLE(vehBike[PLAYER_BIKE_ID])
|
|
SET_PLAYER_CONTROL(PLAYER_ID(), TRUE)
|
|
RCM_ADVANCE_STAGE()
|
|
ELSE // Just in case...
|
|
SET_PLAYER_CONTROL(PLAYER_ID(), TRUE)
|
|
RCM_ADVANCE_STAGE()
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ENDIF
|
|
|
|
IF RCM_CLEANUP_STAGE()
|
|
|
|
RCM_DEBUG_PRINT("Cleaned up MS_COUNTDOWN")
|
|
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Main race loop for the mission
|
|
PROC MS_RACE()
|
|
|
|
INT i
|
|
|
|
IF RCM_INIT_STAGE()
|
|
|
|
// Carry on drawing the race HUD and running checkpoints during the init frame
|
|
SET_FAR_RIGHT_TITLE_POSITION_HUD_THIS_FRAME()
|
|
DRAW_RACE_HUD((GET_GAME_TIMER() - start_time), "", -1, -1, "", iRacePos, 2)
|
|
RUN_PLAYER_CHECKPOINTS_AND_BLIPS(playerInfo, raceInfo)
|
|
|
|
RCM_DEBUG_PRINT("Init MS_RACE")
|
|
i = 0
|
|
REPEAT NUM_BIKES i
|
|
IF IS_VEHICLE_OK(vehBike[i])
|
|
FREEZE_ENTITY_POSITION(vehBike[i], FALSE)
|
|
ENDIF
|
|
ENDREPEAT
|
|
bFinishedRace = FALSE
|
|
bDisplayedGetBackOnBike = FALSE
|
|
iPushTimer = GET_GAME_TIMER()
|
|
iHonkTimer = GET_GAME_TIMER()
|
|
|
|
RCM_DEBUG_PRINT("Run MS_RACE")
|
|
|
|
ELSE
|
|
IF bUsedSkip
|
|
RC_END_Z_SKIP()
|
|
bUsedSkip = FALSE
|
|
ENDIF
|
|
SET_FAR_RIGHT_TITLE_POSITION_HUD_THIS_FRAME()
|
|
DRAW_RACE_HUD((GET_GAME_TIMER() - start_time), "", -1, -1, "", iRacePos, 2)
|
|
RCM_DEATH_CHECKS()
|
|
IF bFinishedRace = FALSE
|
|
|
|
// 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
|
|
|
|
RUN_PLAYER_CHECKPOINTS_AND_BLIPS(playerInfo, raceInfo)
|
|
RCM_UPDATE_WOMAN_CHECKPOINTS()
|
|
RCM_CHECK_PLAYER_ON_BIKE()
|
|
RCM_HONK_NEAR_PLAYER()
|
|
RCM_DRIVE_PAST_PLAYER()
|
|
RCM_JOG_PAST_PLAYER()
|
|
RCM_CYCLE_PAST_PLAYER()
|
|
RCM_END_RACE_EARLY()
|
|
RCM_HANDLE_MARY_ANN_AI_STYLE()
|
|
RCM_DO_HINT_CAM()
|
|
IF bPlayerIsOnBike = TRUE
|
|
MANAGE_SLIDY_BLIP_FOR_ENTITY(opponentBlip, sRCLauncherDataLocal.pedID[MARY_ANN_ID], TRUE)
|
|
UPDATE_CHASE_BLIP(opponentBlip, sRCLauncherDataLocal.pedID[MARY_ANN_ID], LOST_RANGE, 0.8)
|
|
ELSE
|
|
SAFE_REMOVE_BLIP(opponentBlip)
|
|
ENDIF
|
|
IF bPlayerIsOnBike = TRUE
|
|
RCM_MANAGE_PENULTIMATE_CONVERSATION()
|
|
RCM_TRY_ROAD_RAGE_CONVERSATION()
|
|
RCM_CHECK_PUSHING()
|
|
ENDIF
|
|
|
|
RCM_MANAGE_CONVERSATIONS()
|
|
|
|
RCM_MANAGE_BIKE_SPEED()
|
|
IF playerInfo.racerStatus = RACER_STATUS_FINISHED
|
|
|
|
INT piR, piG, piB, piA
|
|
GET_HUD_COLOUR(HUD_COLOUR_WHITE, piR, piG, piB, piA)
|
|
PrevAlpha = 180
|
|
VECTOR tempPos = <<279.85, 946.37, 209.82>>
|
|
tempPos += <<0,0,7.5>>
|
|
playerInfo.PrevCheckpoint = CREATE_CHECKPOINT(CHECKPOINT_RACE_GROUND_FLAG, tempPos, <<279.85, 946.37, 209.82>>, 20, PiR, PiG, PiB, PrevAlpha)
|
|
SET_CHECKPOINT_CYLINDER_HEIGHT(playerInfo.PrevCheckpoint,3.0,3.0,100)
|
|
SET_CHECKPOINT_RGBA(playerInfo.PrevCheckpoint, PiR, PiG, PiB, PrevAlpha)
|
|
SET_CHECKPOINT_RGBA2(playerInfo.PrevCheckpoint, PiR, PiG, PiB, PrevAlpha)
|
|
|
|
bFinishedRace = TRUE
|
|
finish_time = GET_GAME_TIMER()
|
|
IF IS_VEHICLE_OK(vehBike[MARY_ANN_BIKE_ID])
|
|
IF IS_WAYPOINT_PLAYBACK_GOING_ON_FOR_VEHICLE(vehBike[MARY_ANN_BIKE_ID])
|
|
REMOVE_WAYPOINT_RECORDING("Fan2_BikeRoute")
|
|
BRING_VEHICLE_TO_HALT(vehBike[MARY_ANN_BIKE_ID], 4.0, 1)
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ELSE
|
|
IF IS_VEHICLE_OK(vehBike[PLAYER_BIKE_ID])
|
|
if not IS_PED_IN_VEHICLE(PLAYER_PED_ID(), vehBike[PLAYER_BIKE_ID])
|
|
bFinishedRace = FALSE // If player has got off the bike, go back to the race and make sure it's definitely ended
|
|
ELSE
|
|
TRIGGER_MUSIC_EVENT("FANATIC2_STOP")
|
|
RCM_DEBUG_PRINT("Doing music trigger stop")
|
|
BRING_VEHICLE_TO_HALT_AND_DISABLE_VEH_CONTROLS(vehBike[PLAYER_BIKE_ID], 10, 1, 0.3)
|
|
RCM_DEBUG_PRINTINT("Total race time: ", (finish_time - start_time))
|
|
IF (finish_time - start_time) <= 102000 // Race time 1:42, 102,000 seconds!
|
|
INFORM_STAT_SYSTEM_OF_BOOL_STAT_HAPPENED(FA2_QUICK_WIN)
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
RCM_ADVANCE_STAGE()
|
|
ENDIF
|
|
|
|
ENDIF
|
|
|
|
IF RCM_CLEANUP_STAGE()
|
|
|
|
RCM_STOP_ANY_ACTIVE_CONVERSATION(FALSE)
|
|
RCM_DEBUG_PRINT("Cleaned up MS_RACE")
|
|
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
PROC MS_OUTRO()
|
|
|
|
IF playerInfo.PrevCheckpoint != NULL
|
|
PrevAlpha -= 25
|
|
IF PrevAlpha > 0
|
|
INT piR, piG, piB, piA
|
|
GET_HUD_COLOUR(HUD_COLOUR_WHITE, piR, piG, piB, piA)
|
|
SET_CHECKPOINT_RGBA(playerInfo.PrevCheckpoint, piR, piG, piB, PrevAlpha)
|
|
SET_CHECKPOINT_RGBA2(playerInfo.PrevCheckpoint, piR, piG, piB, PrevAlpha)
|
|
ELSE
|
|
DELETE_CHECKPOINT(playerInfo.PrevCheckpoint)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF RCM_INIT_STAGE()
|
|
|
|
RCM_DEBUG_PRINT("Init MS_OUTRO")
|
|
|
|
IF bUsedSkip
|
|
RC_END_Z_SKIP()
|
|
bUsedSkip = FALSE
|
|
ENDIF
|
|
|
|
bDoneTrevCelebrate = FALSE
|
|
|
|
RCM_REMOVE_RACE_BLIPS()
|
|
RCM_REMOVE_ALL_BLIPS()
|
|
|
|
REPLAY_RECORD_BACK_FOR_TIME(10.0, 15.0, REPLAY_IMPORTANCE_LOW)
|
|
|
|
RCM_DEBUG_PRINT("Running MS_OUTRO")
|
|
|
|
ELSE
|
|
|
|
IF NOT bLostRace
|
|
SWITCH iCutsceneStage
|
|
|
|
CASE 0
|
|
IF IS_ENTITY_ALIVE(sRCLauncherDataLocal.pedID[MARY_ANN_ID])
|
|
RCM_REMOVE_ALL_BLIPS()
|
|
RCM_REMOVE_RACE_BLIPS()
|
|
IF GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), sRCLauncherDataLocal.pedID[MARY_ANN_ID]) > 80
|
|
IF CREATE_CONVERSATION(sOutroConversation, "FAN2AU", "FAN2_BIGWIN", CONV_PRIORITY_HIGH)
|
|
RCM_DEBUG_PRINT("Player won by large margin")
|
|
RCM_REMOVE_ALL_BLIPS()
|
|
RCM_REMOVE_RACE_BLIPS()
|
|
SAFE_RELEASE_PED(sRCLauncherDataLocal.pedID[MARY_ANN_ID])
|
|
bReleaseMAEarly = TRUE
|
|
WAIT(500)
|
|
iCutsceneStage++
|
|
ENDIF
|
|
ELIF CREATE_CONVERSATION(sOutroConversation, "FAN2AU", "FAN2_WIN", CONV_PRIORITY_HIGH)
|
|
RCM_DEBUG_PRINT("Player won normally")
|
|
IF IS_ENTITY_ALIVE(PLAYER_PED_ID()) AND IS_ENTITY_ALIVE(sRCLauncherDataLocal.pedID[MARY_ANN_ID])
|
|
TASK_LOOK_AT_ENTITY(PLAYER_PED_ID(),sRCLauncherDataLocal.pedID[MARY_ANN_ID], -1, SLF_WHILE_NOT_IN_FOV|SLF_WIDEST_PITCH_LIMIT|SLF_WIDEST_YAW_LIMIT, SLF_LOOKAT_VERY_HIGH)
|
|
TASK_LOOK_AT_ENTITY(sRCLauncherDataLocal.pedID[MARY_ANN_ID], PLAYER_PED_ID(), -1, SLF_WHILE_NOT_IN_FOV, SLF_LOOKAT_VERY_HIGH)
|
|
CLEAR_PED_TASKS(sRCLauncherDataLocal.pedID[MARY_ANN_ID])
|
|
ENDIF
|
|
iCutsceneStage++
|
|
ENDIF
|
|
ELSE
|
|
RCM_DEBUG_PRINT("Mary Ann not found in the outro?!")
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE 1
|
|
IF NOT bReleaseMAEarly
|
|
IF IS_ENTITY_ALIVE(sRCLauncherDataLocal.pedID[MARY_ANN_ID]) AND IS_VEHICLE_OK(vehBike[MARY_ANN_BIKE_ID])
|
|
IF NOT IS_VEHICLE_STOPPED(vehBike[MARY_ANN_BIKE_ID])
|
|
RCM_DEBUG_PRINT("Bringing Mary Ann to a halt...")
|
|
BRING_VEHICLE_TO_HALT(vehBike[MARY_ANN_BIKE_ID], 2.0, 1)
|
|
ELSE
|
|
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
|
|
IF NOT bDoneTrevCelebrate
|
|
IF IS_VEHICLE_OK(vehBike[PLAYER_BIKE_ID])
|
|
IF NOT IS_VEHICLE_STOPPED(vehBike[PLAYER_BIKE_ID])
|
|
BRING_VEHICLE_TO_HALT_AND_DISABLE_VEH_CONTROLS(vehBike[PLAYER_BIKE_ID], 10, 1, 0.3)
|
|
ELSE
|
|
IF IS_PED_IN_VEHICLE(PLAYER_PED_ID(), vehBike[PLAYER_BIKE_ID])
|
|
TASK_PLAY_ANIM(PLAYER_PED_ID(), "rcmfanatic2", "celebrate_a", DEFAULT, DEFAULT, -1, AF_UPPERBODY)
|
|
bDoneTrevCelebrate = TRUE
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
IF GET_CURRENT_SCRIPTED_CONVERSATION_LINE() > 3
|
|
|
|
IF IS_VEHICLE_OK(vehBike[MARY_ANN_BIKE_ID])
|
|
MODIFY_VEHICLE_TOP_SPEED(vehBike[MARY_ANN_BIKE_ID], 0.0) // Resets top speed back to default
|
|
ENDIF
|
|
|
|
// If Mary Ann's overshot the toilet shed, don't do the first drive-to (B*1316809)
|
|
IF IS_ENTITY_IN_ANGLED_AREA(sRCLauncherDataLocal.pedID[MARY_ANN_ID], <<282.217926,954.202698,209.251694>>, <<279.217010,937.984924,213.628647>>, 14.0)
|
|
OPEN_SEQUENCE_TASK(seq)
|
|
TASK_VEHICLE_DRIVE_TO_COORD(NULL, vehBike[MARY_ANN_BIKE_ID], << 262.37, 961.25, 209.75 >>, 13, DRIVINGSTYLE_NORMAL, modelPlayerBike, DRIVINGMODE_AVOIDCARS, 5, 50)
|
|
TASK_VEHICLE_DRIVE_WANDER(NULL, vehBike[MARY_ANN_BIKE_ID], 16, DRIVINGMODE_STOPFORCARS)
|
|
CLOSE_SEQUENCE_TASK(seq)
|
|
TASK_PERFORM_SEQUENCE(sRCLauncherDataLocal.pedID[MARY_ANN_ID], seq)
|
|
CLEAR_SEQUENCE_TASK(seq)
|
|
iCutsceneStage++
|
|
ELSE
|
|
OPEN_SEQUENCE_TASK(seq)
|
|
TASK_VEHICLE_DRIVE_TO_COORD(NULL, vehBike[MARY_ANN_BIKE_ID], << 281.59, 951.66, 209.85 >>, 7, DRIVINGSTYLE_NORMAL, modelPlayerBike, DRIVINGMODE_PLOUGHTHROUGH, 3, 50)
|
|
TASK_VEHICLE_DRIVE_TO_COORD(NULL, vehBike[MARY_ANN_BIKE_ID], << 262.37, 961.25, 209.75 >>, 13, DRIVINGSTYLE_NORMAL, modelPlayerBike, DRIVINGMODE_AVOIDCARS, 5, 50)
|
|
TASK_VEHICLE_DRIVE_WANDER(NULL, vehBike[MARY_ANN_BIKE_ID], 16, DRIVINGMODE_STOPFORCARS)
|
|
CLOSE_SEQUENCE_TASK(seq)
|
|
TASK_PERFORM_SEQUENCE(sRCLauncherDataLocal.pedID[MARY_ANN_ID], seq)
|
|
CLEAR_SEQUENCE_TASK(seq)
|
|
iCutsceneStage++
|
|
ENDIF
|
|
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ELSE
|
|
IF NOT bDoneTrevCelebrate
|
|
IF IS_VEHICLE_OK(vehBike[PLAYER_BIKE_ID])
|
|
IF NOT IS_VEHICLE_STOPPED(vehBike[PLAYER_BIKE_ID])
|
|
BRING_VEHICLE_TO_HALT_AND_DISABLE_VEH_CONTROLS(vehBike[PLAYER_BIKE_ID], 10, 1, 0.3)
|
|
ELSE
|
|
TASK_PLAY_ANIM(PLAYER_PED_ID(), "rcmfanatic2", "celebrate_a", DEFAULT, DEFAULT, -1, AF_UPPERBODY)
|
|
bDoneTrevCelebrate = TRUE
|
|
iCutsceneStage++
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE 2
|
|
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
|
|
RCM_ADVANCE_STAGE()
|
|
ENDIF
|
|
BREAK
|
|
|
|
ENDSWITCH
|
|
ELSE
|
|
SWITCH iCutsceneStage
|
|
CASE 0
|
|
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
|
|
KILL_ANY_CONVERSATION()
|
|
iCutsceneStage++
|
|
ELSE
|
|
iCutsceneStage++
|
|
ENDIF
|
|
BREAK
|
|
CASE 1
|
|
IF GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), sRCLauncherDataLocal.pedID[MARY_ANN_ID]) < 25
|
|
IF IS_PED_UNINJURED(sRCLauncherDataLocal.pedID[MARY_ANN_ID])
|
|
AND IS_VEHICLE_OK(vehBike[MARY_ANN_BIKE_ID])
|
|
IF NOT IS_VEHICLE_STOPPED(vehBike[MARY_ANN_BIKE_ID])
|
|
RCM_DEBUG_PRINT("Bringing Mary Ann to a halt...")
|
|
BRING_VEHICLE_TO_HALT(vehBike[MARY_ANN_BIKE_ID], 2.0, 1)
|
|
ELIF CREATE_CONVERSATION(sWomanConversation, "FAN2AU", "FAN2_MAWIN", CONV_PRIORITY_HIGH)
|
|
// Play Mary Ann's winning animations here
|
|
TASK_PLAY_ANIM(sRCLauncherDataLocal.pedID[MARY_ANN_ID], "rcmfanatic2", "celebrate_b", DEFAULT, DEFAULT, -1, AF_UPPERBODY)
|
|
TASK_LOOK_AT_ENTITY(PLAYER_PED_ID(),sRCLauncherDataLocal.pedID[MARY_ANN_ID], -1, SLF_WHILE_NOT_IN_FOV, SLF_LOOKAT_VERY_HIGH)
|
|
TASK_LOOK_AT_ENTITY(sRCLauncherDataLocal.pedID[MARY_ANN_ID], PLAYER_PED_ID(), -1, SLF_WHILE_NOT_IN_FOV, SLF_LOOKAT_VERY_HIGH)
|
|
iCutsceneStage++
|
|
WAIT(0) // Just wait a frame to ensure the convo starts
|
|
ENDIF
|
|
ENDIF
|
|
ELSE
|
|
RCM_MISSION_FAILED(FAILED_LOST_RACE)
|
|
ENDIF
|
|
BREAK
|
|
CASE 2
|
|
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
|
|
RCM_MISSION_FAILED(FAILED_LOST_RACE)
|
|
ENDIF
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF RCM_CLEANUP_STAGE()
|
|
|
|
RCM_STOP_ANY_ACTIVE_CONVERSATION()
|
|
RCM_DEBUG_PRINT("Cleaned up MS_OUTRO")
|
|
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Main loop to handle the end of the race
|
|
PROC MS_RESULT()
|
|
|
|
IF RCM_INIT_STAGE()
|
|
|
|
RCM_DEBUG_PRINT("Init MS_RESULT")
|
|
IF IS_ENTITY_ALIVE(sRCLauncherDataLocal.pedID[MARY_ANN_ID])
|
|
AND IS_VEHICLE_OK(vehBike[MARY_ANN_BIKE_ID])
|
|
SET_PED_CAN_BE_KNOCKED_OFF_VEHICLE(sRCLauncherDataLocal.pedID[MARY_ANN_ID], KNOCKOFFVEHICLE_DEFAULT)
|
|
SET_ENTITY_CAN_BE_DAMAGED(vehBike[MARY_ANN_BIKE_ID], TRUE)
|
|
SET_VEHICLE_DOORS_LOCKED(vehBike[MARY_ANN_BIKE_ID], VEHICLELOCK_UNLOCKED)
|
|
ENDIF
|
|
|
|
RCM_DEBUG_PRINT("Running MS_RESULT")
|
|
|
|
ELSE
|
|
|
|
IF bLostRace = FALSE
|
|
or bSkipToEnd
|
|
RCM_ADVANCE_STAGE()
|
|
ELSE
|
|
RCM_MISSION_FAILED(FAILED_LOST_RACE)
|
|
ENDIF
|
|
|
|
ENDIF
|
|
|
|
IF RCM_CLEANUP_STAGE()
|
|
|
|
RCM_DEBUG_PRINT("Cleaned up MS_RESULT")
|
|
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
// ===========================================================================================================
|
|
// Script Loop
|
|
// ===========================================================================================================
|
|
|
|
SCRIPT(g_structRCScriptArgs sRCLauncherDataIn)
|
|
|
|
sRCLauncherDataLocal = sRCLauncherDataIn
|
|
RC_TakeEntityOwnership(sRCLauncherDataLocal)
|
|
|
|
SET_MISSION_FLAG(TRUE)
|
|
|
|
// Setup callback when player is killed, arrested or goes to multiplayer
|
|
IF (HAS_FORCE_CLEANUP_OCCURRED(DEFAULT_FORCE_CLEANUP_FLAGS|FORCE_CLEANUP_FLAG_DEBUG_MENU))
|
|
PRINT_LAUNCHER_DEBUG("Force cleanup [TERMINATING]")
|
|
TRIGGER_MUSIC_EVENT("FANATIC2_FAIL")
|
|
Random_Character_Failed()
|
|
Script_Cleanup()
|
|
ENDIF
|
|
|
|
IF Is_Replay_In_Progress() // Set up the initial scene for replays
|
|
OR IS_REPEAT_PLAY_ACTIVE()
|
|
g_bSceneAutoTrigger = TRUE
|
|
eInitialSceneStage = IS_REQUEST_SCENE
|
|
WHILE NOT SetupScene_FANATIC_2(sRCLauncherDataLocal)
|
|
WAIT(0)
|
|
ENDWHILE
|
|
RC_SET_ENTITY_PROOFS_FOR_CUTSCENE(sRCLauncherDataLocal, FALSE)
|
|
g_bSceneAutoTrigger = FALSE
|
|
ENDIF
|
|
|
|
vehBike[PLAYER_BIKE_ID] = sRCLauncherDataLocal.vehID[0]
|
|
vehBike[MARY_ANN_BIKE_ID] = sRCLauncherDataLocal.vehID[1]
|
|
|
|
mScenarioBlocker = Fan2_Scenario_Blocker()
|
|
CLEAR_AREA_OF_PEDS(<<816.30, 1275.61, 359.50>>, 75.0)
|
|
|
|
IF IS_PED_UNINJURED(PLAYER_PED_ID())
|
|
relGroupPlayer = GET_PED_RELATIONSHIP_GROUP_HASH(PLAYER_PED_ID())
|
|
ENDIF
|
|
|
|
// Loop within here until the mission passes or fails
|
|
WHILE(TRUE)
|
|
|
|
REPLAY_CHECK_FOR_EVENT_THIS_FRAME("SF_EDT")
|
|
|
|
WAIT(0)
|
|
|
|
UPDATE_MISSION_NAME_DISPLAYING(sRCLauncherDataLocal.sIntroCutscene, TRUE)
|
|
|
|
RCM_DEATH_CHECKS()
|
|
|
|
HANDLE_GLOBAL_STAMINA_HELP()
|
|
|
|
SWITCH missionStage
|
|
|
|
CASE stateInit
|
|
MS_INIT()
|
|
BREAK
|
|
|
|
CASE stateIntro
|
|
MS_INTRO()
|
|
BREAK
|
|
|
|
CASE stateCountdown
|
|
MS_COUNTDOWN()
|
|
BREAK
|
|
|
|
CASE stateRace
|
|
MS_RACE()
|
|
BREAK
|
|
|
|
CASE stateOutro
|
|
MS_OUTRO()
|
|
BREAK
|
|
|
|
CASE stateResult
|
|
MS_RESULT()
|
|
BREAK
|
|
|
|
CASE stateMissionPassed
|
|
Script_Passed()
|
|
BREAK
|
|
|
|
CASE stateMissionFailed
|
|
MS_FAILED()
|
|
BREAK
|
|
|
|
ENDSWITCH
|
|
|
|
DEBUG_Check_Debug_Keys()
|
|
|
|
ENDWHILE
|
|
|
|
// Script should never reach here. Always terminate with cleanup function.
|
|
ENDSCRIPT
|
|
|