// Includes USING "rage_builtins.sch" USING "globals.sch" USING "brains.sch" USING "common_Races.sch" USING "flow_public_core.sch" USING "commands_script.sch" USING "commands_misc.sch" USING "flow_help_public.sch" USING "menu_public.sch" USING "rc_launcher_public.sch" USING "PM_MissionCreator_Public.sch" USING "load_queue_public.sch" #IF IS_DEBUG_BUILD USING "COMMANDS_DEBUG.sch" USING "debug_Races.sch" #ENDIF // ***************************************************************************************** // ***************************************************************************************** // ***************************************************************************************** // // MISSION NAME : launcher_Racing.sc // AUTHOR : David Roberts // DESCRIPTION : Launcher script for the ambient street and sea races // // ***************************************************************************************** // ***************************************************************************************** // ***************************************************************************************** // Enums ENUM RACE_LAUNCHER_STATE STATE_INACTIVE, STATE_WAIT_FOR_TRIGGER, STATE_RACE_MENU, STATE_LAUNCH_RACE ENDENUM ENUM CHALLENGER_GREETING_STATE CGS_INIT = 0, CGS_FACING_PLAYER, CGS_FACING_PLAYER_WAIT, CGS_CHALLENGING_PLAYER, CGS_GREETING_PLAYER, CGS_GREETING_PLAYER_WAIT ENDENUM ENUM RACE_MENU_STATE MENU_INIT, MENU_UPDATE, MENU_CLEANUP ENDENUM ENUM RACE_VEHICLE_TYPE RVT_OK, RVT_COP, RVT_NOT_SUITABLE ENDENUM // Constants CONST_FLOAT WORLD_POINT_COORD_TOLERANCE 1.0 // Used to obtain race location CONST_INT ACTIVATION_RANGE 20 // Context interaction range CONST_INT VEHICLE_DAMAGE_LIMIT 200 // Minimum amount of health allowed for vehicle CONST_INT CROWD_SIZE 7 // Maximum number of crowd peds CONST_INT LINEUP_SIZE 3 // Launcher info RACE_LAUNCHER_STATE eState // Launcher state RACE_DATA raceData // Race information VECTOR vInCoords // World point coord BOOL bDisplayHelp // Manages help text BOOL bHintCamReady = TRUE // Manages hint cam BOOL bCreatedAreaBlocks = FALSE // Remember when we've created pathing blocks so we can clean them up. // Use a timer to ensure that help text isn't cleared before it's been onscreen for at least a second INT iHelpTextTimer CONST_INT MIN_HELP_TEXT_TIME 1000 // Race menu RACE_MENU_STATE eRaceMenu // Menu state INT iCurrentMenuItem INT iMenuInputTimer BOOL bLaunchRace BOOL bPlayOnline BOOL bRadioSwitchDisabled //BOOL bAnchored = FALSE BOOL bStartPedSixTurning = TRUE // Race initial scene PED_INDEX piCrowd[CROWD_SIZE] // Crowd ped info VEHICLE_INDEX viCar PED_INDEX piDriver VECTOR vCarPos FLOAT fCarFoc VEHICLE_INDEX viCar2 VECTOR vCarPos2 FLOAT fCarFoc2 VECTOR vLineupPos[LINEUP_SIZE] FLOAT fLineupFoc[LINEUP_SIZE] VECTOR offset_pos[CROWD_SIZE] FLOAT offset_heading[CROWD_SIZE] VEHICLE_INDEX viLineup[LINEUP_SIZE] PED_INDEX piLineup[LINEUP_SIZE] // Crowd setup MODEL_NAMES ePedModel[CROWD_SIZE] MODEL_NAMES eCarModel MODEL_NAMES eCarModel2 = FELTZER2 STRING sAnimDict STRING sAnimName[CROWD_SIZE] BOOL bReleaseModels = TRUE /*INT iSyncedSceneOne INT iSyncedSceneTwo*/ BOOL bTriggeredMenu = FALSE CHALLENGER_GREETING_STATE eChallengerState = CGS_INIT BOOL bSaidSecondSpeech = FALSE BOOL bSaidThirdSpeech = FALSE structTimer greetTimer // The min and max coordinates used to turn off ped paths around the start of the race VECTOR vMinRaceArea = <<0,0,0>> VECTOR vMaxRaceArea = <<1,1,1>> // Disable road nodes near the race start VECTOR vRaceRoadPos1 = <<0,0,0>> VECTOR vRaceRoadPos2 = <<0,0,0>> FLOAT fRaceRoadWidth = 0 SCENARIO_BLOCKING_INDEX sbiRaceStart SCENARIO_BLOCKING_INDEX sbiStreetRaceTwo LoadQueueMedium sLoadQueue // =========================================================================================================== // Helper functions // =========================================================================================================== /// PURPOSE: /// Preloads or releases vehicle models needed for the AI races /// PARAMS: /// bRequest - Requests the models if this is true, releases them if it's false PROC REQUEST_RIVAL_MODELS(BOOL bRequest = TRUE) IF bRequest // Set vehicle models SWITCH raceData.eRaceTrack CASE STREET_RACE_01 // South Los Santos CASE STREET_RACE_02 // City Circuit CASE STREET_RACE_04 // Airport CASE STREET_RACE_05 // Freeway LOAD_QUEUE_MEDIUM_ADD_MODEL(sLoadQueue, BANSHEE) LOAD_QUEUE_MEDIUM_ADD_MODEL(sLoadQueue, FELTZER2) LOAD_QUEUE_MEDIUM_ADD_MODEL(sLoadQueue, SENTINEL) // REQUEST_MODEL(BANSHEE) // REQUEST_MODEL(FELTZER2) // REQUEST_MODEL(SENTINEL) BREAK CASE STREET_RACE_06 // Vespucci Canals LOAD_QUEUE_MEDIUM_ADD_MODEL(sLoadQueue, BATI) LOAD_QUEUE_MEDIUM_ADD_MODEL(sLoadQueue, RUFFIAN) // REQUEST_MODEL(BATI) // REQUEST_MODEL(RUFFIAN) BREAK CASE SEA_RACE_01 // North Coast CASE SEA_RACE_02 // South Coast CASE SEA_RACE_03 // Raton Canyon CASE SEA_RACE_04 // Los Santos LOAD_QUEUE_MEDIUM_ADD_MODEL(sLoadQueue, SEASHARK) // REQUEST_MODEL(SEASHARK) BREAK ENDSWITCH ELSE SET_LOAD_QUEUE_MEDIUM_AS_NO_LONGER_NEEDED(sLoadQueue) // Release vehicle models // SWITCH raceData.eRaceTrack // CASE STREET_RACE_01 // South Los Santos // CASE STREET_RACE_02 // City Circuit // CASE STREET_RACE_04 // Airport // CASE STREET_RACE_05 // Freeway // SET_MODEL_AS_NO_LONGER_NEEDED(BANSHEE) // SET_MODEL_AS_NO_LONGER_NEEDED(FELTZER2) // SET_MODEL_AS_NO_LONGER_NEEDED(SENTINEL) // BREAK // CASE STREET_RACE_06 // Vespucci Canals // SET_MODEL_AS_NO_LONGER_NEEDED(BATI) // SET_MODEL_AS_NO_LONGER_NEEDED(RUFFIAN) // BREAK // CASE SEA_RACE_01 // North Coast // CASE SEA_RACE_02 // South Coast // CASE SEA_RACE_03 // Raton Canyon // CASE SEA_RACE_04 // Los Santos // SET_MODEL_AS_NO_LONGER_NEEDED(SEASHARK) // BREAK // ENDSWITCH ENDIF ENDPROC // =========================================================================================================== // Launcher cleanup // =========================================================================================================== PROC SCRIPT_CLEANUP(BOOL bStartedRace = TRUE) CPRINTLN(DEBUG_MISSION, "Race Launcher: SCRIPT CLEANUP") // Remove debug widget #IF IS_DEBUG_BUILD CLEANUP_RACE_WIDGET() IF g_RaceLaunchedFromDebug = TRUE CPRINTLN(DEBUG_MISSION, "Race Launcher Cleanup: Triggered from debug menu") g_RaceLaunchedFromDebug = FALSE ENDIF #ENDIF // Remove the initial scene peds IF NOT bHintCamReady STOP_GAMEPLAY_HINT() bHintCamReady = TRUE ENDIF INT iIndex = 0 REPEAT CROWD_SIZE iIndex IF IS_ENTITY_ALIVE(piCrowd[iIndex]) CLEAR_PED_TASKS(piCrowd[iIndex]) TASK_WANDER_STANDARD(piCrowd[iIndex]) SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(piCrowd[iIndex], FALSE) SET_PED_AS_NO_LONGER_NEEDED(piCrowd[iIndex]) ENDIF ENDREPEAT iIndex = 0 REPEAT LINEUP_SIZE iIndex IF IS_ENTITY_ALIVE(piLineup[iIndex]) IF IS_ENTITY_ALIVE(viLineup[iIndex]) CLEAR_PED_TASKS(piLineup[iIndex]) IF IS_THIS_MODEL_A_BOAT(GET_ENTITY_MODEL(viLineup[iIndex])) SET_BOAT_ANCHOR(viLineup[iIndex], FALSE) ENDIF TASK_VEHICLE_DRIVE_WANDER(piLineup[iIndex],viLineup[iIndex],20,DRIVINGMODE_AVOIDCARS_STOPFORPEDS_OBEYLIGHTS) SET_PED_KEEP_TASK(piLineup[iIndex],TRUE) SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(piLineup[iIndex], FALSE) SET_PED_AS_NO_LONGER_NEEDED(piLineup[iIndex]) SET_VEHICLE_AS_NO_LONGER_NEEDED(viLineup[iIndex]) ENDIF ENDIF ENDREPEAT IF IS_ENTITY_ALIVE(piDriver) IF IS_ENTITY_ALIVE(viCar) CLEAR_PED_TASKS(piDriver) SET_PED_COMBAT_ATTRIBUTES(piDriver, CA_USE_VEHICLE,True) TASK_VEHICLE_DRIVE_WANDER(piDriver, viCar,15,DRIVINGMODE_AVOIDCARS_STOPFORPEDS_OBEYLIGHTS) SET_PED_KEEP_TASK(piDriver,TRUE) SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(piDriver, FALSE) SET_PED_AS_NO_LONGER_NEEDED(piDriver) SET_VEHICLE_AS_NO_LONGER_NEEDED(viCar) ENDIF ENDIF IF IS_ENTITY_ALIVE(viCar2) SET_VEHICLE_AS_NO_LONGER_NEEDED(viCar2) ENDIF // Cleanup blips SWITCH raceData.eRaceTrack // Sea Races CASE SEA_RACE_01 SET_STATIC_BLIP_ACTIVE_STATE(STATIC_BLIP_MINIGAME_SEA_RACE1, FALSE) SET_BIT(g_savedGlobals.sSeaRaceData.iRaceLeaveArea, ENUM_TO_INT(SEA_RACE_EAST)) BREAK CASE SEA_RACE_02 SET_STATIC_BLIP_ACTIVE_STATE(STATIC_BLIP_MINIGAME_SEA_RACE2, FALSE) SET_BIT(g_savedGlobals.sSeaRaceData.iRaceLeaveArea, ENUM_TO_INT(SEA_RACE_NORTH)) BREAK CASE SEA_RACE_03 SET_STATIC_BLIP_ACTIVE_STATE(STATIC_BLIP_MINIGAME_SEA_RACE3, FALSE) SET_BIT(g_savedGlobals.sSeaRaceData.iRaceLeaveArea, ENUM_TO_INT(SEA_RACE_CANYON)) BREAK CASE SEA_RACE_04 SET_STATIC_BLIP_ACTIVE_STATE(STATIC_BLIP_MINIGAME_SEA_RACE4, FALSE) SET_BIT(g_savedGlobals.sSeaRaceData.iRaceLeaveArea, ENUM_TO_INT(SEA_RACE_CITY)) BREAK // Street Races CASE STREET_RACE_01 SET_STATIC_BLIP_ACTIVE_STATE(STATIC_BLIP_MINIGAME_STREET_RACE1, FALSE) SET_BIT(g_savedGlobals.sStreetRaceData.iRaceLeaveArea, ENUM_TO_INT(STREET_RACE_LOS_SANTOS)) BREAK CASE STREET_RACE_02 SET_STATIC_BLIP_ACTIVE_STATE(STATIC_BLIP_MINIGAME_STREET_RACE2, FALSE) SET_BIT(g_savedGlobals.sStreetRaceData.iRaceLeaveArea, ENUM_TO_INT(STREET_RACE_CITY_CIRCUIT)) BREAK CASE STREET_RACE_04 SET_STATIC_BLIP_ACTIVE_STATE(STATIC_BLIP_MINIGAME_STREET_RACE4, FALSE) SET_BIT(g_savedGlobals.sStreetRaceData.iRaceLeaveArea, ENUM_TO_INT(STREET_RACE_AIRPORT)) BREAK CASE STREET_RACE_05 SET_STATIC_BLIP_ACTIVE_STATE(STATIC_BLIP_MINIGAME_STREET_RACE5, FALSE) SET_BIT(g_savedGlobals.sStreetRaceData.iRaceLeaveArea, ENUM_TO_INT(STREET_RACE_FREEWAY)) BREAK CASE STREET_RACE_06 SET_STATIC_BLIP_ACTIVE_STATE(STATIC_BLIP_MINIGAME_STREET_RACE6, FALSE) SET_BIT(g_savedGlobals.sStreetRaceData.iRaceLeaveArea, ENUM_TO_INT(STREET_RACE_VESPUCCI_CANALS)) BREAK ENDSWITCH // Clear help text IF bDisplayHelp CLEAR_HELP() ENDIF SET_RADIO_STATION_MUSIC_ONLY(GET_RADIO_STATION_NAME(ENUM_TO_INT(RADIO_GENRE_DANCE)), FALSE) // Script has terminated with flow help disabled IF bRadioSwitchDisabled // Ensure player can use radio SET_USER_RADIO_CONTROL_ENABLED(TRUE) ENDIF IF bTriggeredMenu AND NOT bStartedRace PLAYER_INDEX piPlayer = GET_PLAYER_INDEX() IF IS_PLAYER_PLAYING(piPlayer) IF NOT IS_PLAYER_CONTROL_ON(piPlayer) SET_PLAYER_CONTROL(piPlayer, TRUE) ENDIF ENDIF ENDIF IF NOT bStartedRace REQUEST_RIVAL_MODELS(FALSE) ENDIF // Restore ped paths IF bCreatedAreaBlocks SET_PED_PATHS_BACK_TO_ORIGINAL(vMinRaceArea, vMaxRaceArea, TRUE) SET_ROADS_BACK_TO_ORIGINAL_IN_ANGLED_AREA(vRaceRoadPos1, vRaceRoadPos2, fRaceRoadWidth) bCreatedAreaBlocks = FALSE ENDIF // Turn off parking scenarios SET_SCENARIO_TYPE_ENABLED("WORLD_VEHICLE_PARK_PERPENDICULAR_NOSE_IN", TRUE) SET_SCENARIO_TYPE_ENABLED("WORLD_VEHICLE_PARK_PARALLEL", TRUE) IF raceData.eRaceTrack = STREET_RACE_02 REMOVE_SCENARIO_BLOCKING_AREA(sbiStreetRaceTwo) ENDIF IF raceData.eRaceType = RACETYPE_BIKE OR raceData.eRaceType = RACETYPE_CAR REMOVE_SCENARIO_BLOCKING_AREA(sbiRaceStart) ELSE SET_PED_CONFIG_FLAG(PLAYER_PED_ID(), PCF_ForceDirectEntry, FALSE) ENDIF CLEANUP_LOAD_QUEUE_MEDIUM(sLoadQueue) // Terminate script TERMINATE_THIS_THREAD() ENDPROC // =========================================================================================================== // Functions // =========================================================================================================== /// PURPOSE: Check if a specific race track has been unlocked yet. FUNC BOOL IS_RACE_UNLOCKED(RACE_TRACK_ID paramRaceID) SWITCH paramRaceID CASE STREET_RACE_01 RETURN IS_BIT_SET(g_savedGlobals.sStreetRaceData.iRaceUnlocked, ENUM_TO_INT(STREET_RACE_LOS_SANTOS)) BREAK CASE STREET_RACE_02 RETURN IS_BIT_SET(g_savedGlobals.sStreetRaceData.iRaceUnlocked, ENUM_TO_INT(STREET_RACE_CITY_CIRCUIT)) BREAK CASE STREET_RACE_04 RETURN IS_BIT_SET(g_savedGlobals.sStreetRaceData.iRaceUnlocked, ENUM_TO_INT(STREET_RACE_AIRPORT)) BREAK CASE STREET_RACE_05 RETURN IS_BIT_SET(g_savedGlobals.sStreetRaceData.iRaceUnlocked, ENUM_TO_INT(STREET_RACE_FREEWAY)) BREAK CASE STREET_RACE_06 RETURN IS_BIT_SET(g_savedGlobals.sStreetRaceData.iRaceUnlocked, ENUM_TO_INT(STREET_RACE_VESPUCCI_CANALS)) BREAK ENDSWITCH RETURN FALSE ENDFUNC /// PURPOSE: Clears help when the player goes out of activation range or has the cellphone up PROC MANAGE_RACE_HELP() // Help message was displayed.. IF bDisplayHelp AND GET_GAME_TIMER() > iHelpTextTimer CLEAR_HELP() bDisplayHelp = FALSE ENDIF ENDPROC /// PURPOSE: /// Checks if the player has threatened the launch scene peds in any way /// RETURNS: /// TRUE if the player has been threatening FUNC BOOL PLAYER_THREATENED_LAUNCH_SCENE() INT iIndex // Make scene peds flee when the player is wanted IF IS_PLAYER_WANTED_LEVEL_GREATER(PLAYER_ID(), 0) RETURN TRUE ENDIF // Sea races have more limited initial scenes IF raceData.eRaceType = RACETYPE_SEA FOR iIndex = 0 TO COUNT_OF(piLineup) - 1 IF DOES_ENTITY_EXIST(piLineup[iIndex]) IF IS_PED_INJURED(piLineup[iIndex]) RETURN TRUE ELIF HAS_PLAYER_THREATENED_PED(piLineup[iIndex]) OR IS_PED_BEING_JACKED(piLineup[iIndex]) RETURN TRUE ENDIF ENDIF IF DOES_ENTITY_EXIST(viLineup[iIndex]) IF IS_ENTITY_DEAD(viLineup[iIndex]) RETURN TRUE ELIF HAS_ENTITY_BEEN_DAMAGED_BY_ENTITY(viLineup[iIndex], PLAYER_PED_ID()) AND GET_ENTITY_HEALTH(viLineup[iIndex]) < 900 RETURN TRUE ENDIF ENDIF ENDFOR IF DOES_ENTITY_EXIST(viCar) IF IS_ENTITY_DEAD(viCar) RETURN TRUE ELIF HAS_ENTITY_BEEN_DAMAGED_BY_ENTITY(viCar, PLAYER_PED_ID()) AND GET_ENTITY_HEALTH(viCar) < 900 RETURN TRUE ENDIF ENDIF RETURN FALSE ENDIF IF IS_ENTITY_IN_RANGE_COORDS(PLAYER_PED_ID(),vInCoords, 50) AND IS_PED_SHOOTING(PLAYER_PED_ID()) RETURN TRUE ENDIF IF DOES_ENTITY_EXIST(piDriver) IF IS_PED_INJURED(piDriver) RETURN TRUE ELIF HAS_PLAYER_THREATENED_PED(piDriver) RETURN TRUE ELIF IS_PED_BEING_JACKED(piDriver) SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(piDriver, FALSE) RETURN TRUE ENDIF ENDIF IF DOES_ENTITY_EXIST(viCar) IF IS_ENTITY_DEAD(viCar) RETURN TRUE ELIF IS_PED_IN_VEHICLE(PLAYER_PED_ID(), viCar, TRUE) OR HAS_ENTITY_BEEN_DAMAGED_BY_ENTITY(viCar, PLAYER_PED_ID()) RETURN TRUE ENDIF ENDIF IF DOES_ENTITY_EXIST(viCar2) IF IS_ENTITY_DEAD(viCar2) RETURN TRUE ELIF IS_PED_IN_VEHICLE(PLAYER_PED_ID(), viCar2, TRUE) OR HAS_ENTITY_BEEN_DAMAGED_BY_ENTITY(viCar2, PLAYER_PED_ID()) RETURN TRUE ENDIF ENDIF FOR iIndex = 0 TO COUNT_OF(ePedModel) - 1 IF DOES_ENTITY_EXIST(piCrowd[iIndex]) IF IS_PED_INJURED(piCrowd[iIndex]) RETURN TRUE ELIF HAS_PLAYER_THREATENED_PED(piCrowd[iIndex]) RETURN TRUE ENDIF ENDIF ENDFOR RETURN FALSE ENDFUNC /// PURPOSE: Can race be triggered at current time of day FUNC BOOL IS_RACE_ALLOWED_FOR_TIME_OF_DAY() // Sea Races currently not restricted by time IF raceData.eRaceType = RACETYPE_SEA RETURN TRUE ELIF raceData.eRaceType = RACETYPE_BIKE OR raceData.eRaceType = RACETYPE_CAR // Check current time of day IF GET_CLOCK_HOURS() >= MIN_STREET_RACE_HOUR OR GET_CLOCK_HOURS() < MAX_STREET_RACE_HOUR RETURN TRUE ELSE RETURN FALSE ENDIF ENDIF RETURN TRUE ENDFUNC /// PURPOSE: /// Checks if the leave area bit has been set for this race /// RETURNS: /// TRUE if the bit has been set FUNC BOOL IS_LEAVE_AREA_BIT_SET() SWITCH raceData.eRaceTrack // Sea Races CASE SEA_RACE_01 RETURN IS_BIT_SET(g_savedGlobals.sSeaRaceData.iRaceLeaveArea, ENUM_TO_INT(SEA_RACE_EAST)) BREAK CASE SEA_RACE_02 RETURN IS_BIT_SET(g_savedGlobals.sSeaRaceData.iRaceLeaveArea, ENUM_TO_INT(SEA_RACE_NORTH)) BREAK CASE SEA_RACE_03 RETURN IS_BIT_SET(g_savedGlobals.sSeaRaceData.iRaceLeaveArea, ENUM_TO_INT(SEA_RACE_CANYON)) BREAK CASE SEA_RACE_04 RETURN IS_BIT_SET(g_savedGlobals.sSeaRaceData.iRaceLeaveArea, ENUM_TO_INT(SEA_RACE_CITY)) BREAK // Street Races CASE STREET_RACE_01 RETURN IS_BIT_SET(g_savedGlobals.sStreetRaceData.iRaceLeaveArea, ENUM_TO_INT(STREET_RACE_LOS_SANTOS)) BREAK CASE STREET_RACE_02 RETURN IS_BIT_SET(g_savedGlobals.sStreetRaceData.iRaceLeaveArea, ENUM_TO_INT(STREET_RACE_CITY_CIRCUIT)) BREAK CASE STREET_RACE_04 RETURN IS_BIT_SET(g_savedGlobals.sStreetRaceData.iRaceLeaveArea, ENUM_TO_INT(STREET_RACE_AIRPORT)) BREAK CASE STREET_RACE_05 RETURN IS_BIT_SET(g_savedGlobals.sStreetRaceData.iRaceLeaveArea, ENUM_TO_INT(STREET_RACE_FREEWAY)) BREAK CASE STREET_RACE_06 RETURN IS_BIT_SET(g_savedGlobals.sStreetRaceData.iRaceLeaveArea, ENUM_TO_INT(STREET_RACE_VESPUCCI_CANALS)) BREAK ENDSWITCH RETURN FALSE ENDFUNC /// PURPOSE: /// Check if there are any reasons why the races cannot be launced /// RETURNS: /// TRUE if no conditions to not launch were found FUNC BOOL IS_RACE_ALLOWED_TO_LAUNCH() IF IS_CURRENTLY_ON_MISSION_TO_TYPE(MISSION_TYPE_MINIGAME) CPRINTLN(DEBUG_MISSION, "Currently on minigame") RETURN FALSE ENDIF IF IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_FRIEND_ACTIVITY) OR IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_FRIEND_ACTIVITY_WITH_MG) CPRINTLN(DEBUG_MISSION, "Currently on friend activity") RETURN FALSE ENDIF IF g_bMissionOverStatTrigger CPRINTLN(DEBUG_MISSION, "g_bMissionOverStatTrigger = TRUE") RETURN FALSE ENDIF // Check if the player has to leave the area IF IS_LEAVE_AREA_BIT_SET() CPRINTLN(DEBUG_MISSION, "Leave area bit has been set") RETURN FALSE ENDIF // Racing is only available for Franklin IF (raceData.eRaceType <> RACETYPE_SEA) AND (GET_CURRENT_PLAYER_PED_ENUM() <> CHAR_FRANKLIN) CPRINTLN(DEBUG_MISSION, "Player is not Franklin") RETURN FALSE ENDIF IF IS_STUNT_JUMP_IN_PROGRESS() CPRINTLN(DEBUG_MISSION, "Stunt jump in progress") RETURN FALSE ENDIF // If the player isn't in the driver's seat they're either on the bus tour or getting a taxi ride so don't offer the race IF IS_PED_UNINJURED(PLAYER_PED_ID()) AND IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID()) VEHICLE_INDEX viPlayer = GET_PLAYERS_LAST_VEHICLE() IF IS_VEHICLE_OK(viPlayer) AND IS_PED_SITTING_IN_VEHICLE(PLAYER_PED_ID(), viPlayer) AND NOT IS_PED_SITTING_IN_VEHICLE_SEAT(PLAYER_PED_ID(), viPlayer, VS_DRIVER) AND GET_ENTITY_MODEL(viPlayer) <> TAXI CPRINTLN(DEBUG_MISSION, "Player is on the tour bus") RETURN FALSE ENDIF ENDIF // Need to move race track over to use global enums // Post-lockdown! SWITCH raceData.eRaceTrack // Street Races CASE STREET_RACE_01 IF g_bStreetRaceTimeout[0] CPRINTLN(DEBUG_MISSION, "Race is currently timed out...") RETURN FALSE ENDIF BREAK CASE STREET_RACE_02 IF g_bStreetRaceTimeout[1] CPRINTLN(DEBUG_MISSION, "Race is currently timed out...") RETURN FALSE ENDIF BREAK CASE STREET_RACE_04 IF g_bStreetRaceTimeout[2] CPRINTLN(DEBUG_MISSION, "Race is currently timed out...") RETURN FALSE ENDIF BREAK CASE STREET_RACE_05 IF g_bStreetRaceTimeout[3] CPRINTLN(DEBUG_MISSION, "Race is currently timed out...") RETURN FALSE ENDIF BREAK CASE STREET_RACE_06 IF g_bStreetRaceTimeout[4] CPRINTLN(DEBUG_MISSION, "Race is currently timed out...") RETURN FALSE ENDIF BREAK // Sea Races CASE SEA_RACE_01 IF g_bSeaRaceTimeout[0] CPRINTLN(DEBUG_MISSION, "Race is currently timed out...") RETURN FALSE ENDIF BREAK CASE SEA_RACE_02 IF g_bSeaRaceTimeout[1] CPRINTLN(DEBUG_MISSION, "Race is currently timed out...") RETURN FALSE ENDIF BREAK CASE SEA_RACE_03 IF g_bSeaRaceTimeout[2] CPRINTLN(DEBUG_MISSION, "Race is currently timed out...") RETURN FALSE ENDIF BREAK CASE SEA_RACE_04 IF g_bSeaRaceTimeout[3] CPRINTLN(DEBUG_MISSION, "Race is currently timed out...") RETURN FALSE ENDIF BREAK ENDSWITCH // Race has elapsed allowedtime IF NOT IS_RACE_ALLOWED_FOR_TIME_OF_DAY() CPRINTLN(DEBUG_MISSION, "Race is not allowed at this time of day") INT iIndex SEQUENCE_INDEX siWander FOR iIndex = 0 TO COUNT_OF(ePedModel) - 1 IF IS_PED_UNINJURED(piCrowd[iIndex]) OPEN_SEQUENCE_TASK(siWander) TASK_PAUSE(NULL, iIndex*100) TASK_WANDER_STANDARD(NULL) CLOSE_SEQUENCE_TASK(siWander) TASK_PERFORM_SEQUENCE(piCrowd[iIndex], siWander) ENDIF ENDFOR FOR iIndex = 0 TO COUNT_OF(piLineup) - 1 IF IS_PED_UNINJURED(piLineup[iIndex]) OPEN_SEQUENCE_TASK(siWander) TASK_PAUSE(NULL, iIndex*110) IF IS_VEHICLE_OK(viLineup[iIndex]) AND IS_PED_IN_VEHICLE(piLineup[iIndex], viLineup[iIndex]) TASK_VEHICLE_DRIVE_WANDER(NULL, viLineup[iIndex], 30, DRIVINGMODE_AVOIDCARS_OBEYLIGHTS) ELSE TASK_WANDER_STANDARD(NULL) ENDIF CLOSE_SEQUENCE_TASK(siWander) TASK_PERFORM_SEQUENCE(piLineup[iIndex], siWander) ENDIF ENDFOR IF IS_PED_UNINJURED(piDriver) IF IS_VEHICLE_OK(viCar) AND IS_PED_IN_VEHICLE(piDriver, viCar) TASK_VEHICLE_DRIVE_WANDER(piDriver, viCar, 30, DRIVINGMODE_AVOIDCARS_OBEYLIGHTS) ELSE TASK_WANDER_STANDARD(piDriver) ENDIF ENDIF RETURN FALSE ENDIF // Don't offer the race if the player has been aggressive towards the launch scene peds // Make launch scene peds flee in this case IF PLAYER_THREATENED_LAUNCH_SCENE() CPRINTLN(DEBUG_MISSION, "Player threatened the launch scene") SEQUENCE_INDEX siLeave INT iIndex FOR iIndex = 0 TO COUNT_OF(ePedModel) - 1 IF IS_PED_UNINJURED(piCrowd[iIndex]) OPEN_SEQUENCE_TASK(siLeave) TASK_PAUSE(NULL, iIndex*50) TASK_SMART_FLEE_PED(NULL, PLAYER_PED_ID(), 500, -1) CLOSE_SEQUENCE_TASK(siLeave) IF iIndex % 2 = 0 MAKE_PED_SCREAM(piCrowd[iIndex]) ENDIF TASK_PERFORM_SEQUENCE(piCrowd[iIndex], siLeave) ENDIF ENDFOR FOR iIndex = 0 TO COUNT_OF(piLineup) - 1 IF IS_VEHICLE_OK(viLineup[iIndex]) AND raceData.eRaceType = RACETYPE_SEA SET_BOAT_ANCHOR(viLineup[iIndex], FALSE) ENDIF IF IS_PED_UNINJURED(piLineup[iIndex]) OPEN_SEQUENCE_TASK(siLeave) TASK_PAUSE(NULL, iIndex*60) IF IS_VEHICLE_OK(viLineup[iIndex]) AND IS_PED_IN_VEHICLE(piLineup[iIndex], viLineup[iIndex]) TASK_VEHICLE_DRIVE_WANDER(NULL, viLineup[iIndex], 50, DRIVINGMODE_AVOIDCARS_RECKLESS) ELSE TASK_SMART_FLEE_PED(NULL, PLAYER_PED_ID(), 500, -1) ENDIF CLOSE_SEQUENCE_TASK(siLeave) TASK_PERFORM_SEQUENCE(piLineup[iIndex], siLeave) IF iIndex % 2 = 0 MAKE_PED_SCREAM(piLineup[iIndex]) ENDIF ENDIF ENDFOR IF IS_VEHICLE_OK(viCar) AND raceData.eRaceType = RACETYPE_SEA SET_BOAT_ANCHOR(viCar, FALSE) ENDIF IF IS_PED_UNINJURED(piDriver) IF IS_VEHICLE_OK(viCar) AND IS_PED_IN_VEHICLE(piDriver, viCar) TASK_VEHICLE_DRIVE_WANDER(piDriver, viCar, 50, DRIVINGMODE_AVOIDCARS_RECKLESS) ELSE TASK_SMART_FLEE_PED(piDriver, PLAYER_PED_ID(), 500, -1) ENDIF ENDIF // Need to move race track over to use global enums // Post-lockdown! SWITCH raceData.eRaceTrack // Street Races CASE STREET_RACE_01 g_bStreetRaceTimeout[0] = TRUE g_iStreetRaceCooldown[0] = GET_GAME_TIMER() BREAK CASE STREET_RACE_02 g_bStreetRaceTimeout[1] = TRUE g_iStreetRaceCooldown[1] = GET_GAME_TIMER() BREAK CASE STREET_RACE_04 g_bStreetRaceTimeout[2] = TRUE g_iStreetRaceCooldown[2] = GET_GAME_TIMER() BREAK CASE STREET_RACE_05 g_bStreetRaceTimeout[3] = TRUE g_iStreetRaceCooldown[3] = GET_GAME_TIMER() BREAK CASE STREET_RACE_06 g_bStreetRaceTimeout[4] = TRUE g_iStreetRaceCooldown[4] = GET_GAME_TIMER() BREAK // Sea Races CASE SEA_RACE_01 g_bSeaRaceTimeout[0] = TRUE g_iSeaRaceCooldown[0] = GET_GAME_TIMER() BREAK CASE SEA_RACE_02 g_bSeaRaceTimeout[1] = TRUE g_iSeaRaceCooldown[1] = GET_GAME_TIMER() BREAK CASE SEA_RACE_03 g_bSeaRaceTimeout[2] = TRUE g_iSeaRaceCooldown[2] = GET_GAME_TIMER() BREAK CASE SEA_RACE_04 g_bSeaRaceTimeout[3] = TRUE g_iSeaRaceCooldown[3] = GET_GAME_TIMER() BREAK ENDSWITCH CPRINTLN(DEBUG_MISSION, "Race timeout activated!") RETURN FALSE ENDIF RETURN TRUE ENDFUNC /// PURPOSE: Is the player within activation range of the race start point? FUNC BOOL IS_PLAYER_IN_RACE_ACTIVATION_RANGE() IF IS_PLAYER_PLAYING(PLAYER_ID()) INT iActivationRange = ACTIVATION_RANGE IF raceData.eRaceType = RACETYPE_SEA iActivationRange = ACTIVATION_RANGE*2 ENDIF IF GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()),vInCoords) < iActivationRange AND GET_INTERIOR_FROM_ENTITY(PLAYER_PED_ID()) = NULL // Kill this if the player enters a shop RETURN TRUE ENDIF ENDIF RETURN FALSE ENDFUNC /// PURPOSE: Is the player in a suitable race car //FUNC BOOL IS_PLAYER_IN_SUITABLE_RACE_CAR() FUNC RACE_VEHICLE_TYPE IS_PLAYER_IN_SUITABLE_RACE_CAR() IF IS_PLAYER_PLAYING(PLAYER_ID()) IF DOES_ENTITY_EXIST(sPlayerVehicle.vehPlayerVehicle) // Get model name of player vehicle MODEL_NAMES vehModel = GET_ENTITY_MODEL(sPlayerVehicle.vehPlayerVehicle) // General checks IF IS_MODEL_POLICE_VEHICLE(vehModel) RETURN RVT_COP ENDIF // these vehicles aren't covered by the IS_MODEL_POLICE_VEHICLE function IF vehModel = POLICE4 OR vehModel = POLICEOLD1 OR vehModel = POLICEOLD2 OR vehModel = FBI OR vehModel = FBI2 OR vehModel = LGUARD OR vehModel = SHERIFF OR vehModel = SHERIFF2 OR vehModel = PRANGER OR vehModel = AMBULANCE OR vehModel = FIRETRUK RETURN RVT_COP ENDIF IF IS_THIS_MODEL_A_BIKE(vehModel) OR IS_THIS_MODEL_A_BOAT(vehModel) OR IS_THIS_MODEL_A_HELI(vehModel) OR IS_THIS_MODEL_A_PLANE(vehModel) RETURN RVT_NOT_SUITABLE ENDIF // Race blacklist INT iIndex MODEL_NAMES mBlacklist[83] mBlacklist[0] = AMBULANCE mBlacklist[1] = BENSON mBlacklist[2] = BIFF mBlacklist[3] = BUS mBlacklist[4] = FIRETRUK mBlacklist[5] = FORKLIFT mBlacklist[6] = MULE mBlacklist[7] = MULE2 mBlacklist[8] = PACKER mBlacklist[9] = PHANTOM mBlacklist[10] = MOWER mBlacklist[11] = STOCKADE mBlacklist[12] = SQUALO mBlacklist[13] = MAVERICK mBlacklist[14] = POLMAV mBlacklist[15] = AIRTUG mBlacklist[16] = BOXVILLE3 mBlacklist[17] = ANNIHILATOR mBlacklist[18] = DINGHY mBlacklist[19] = DUMMY_MODEL_FOR_SCRIPT mBlacklist[20] = RIPLEY mBlacklist[21] = TRASH mBlacklist[22] = BURRITO mBlacklist[23] = PONY mBlacklist[24] = SPEEDO mBlacklist[25] = MARQUIS mBlacklist[26] = SANCHEZ mBlacklist[27] = AIRTUG mBlacklist[28] = TACO mBlacklist[29] = BARRACKS mBlacklist[30] = ROMERO mBlacklist[31] = BLAZER mBlacklist[32] = BLAZER2 mBlacklist[33] = BODHI2 mBlacklist[34] = BOXVILLE2 mBlacklist[35] = BULLDOZER mBlacklist[36] = CADDY mBlacklist[37] = CADDY2 mBlacklist[38] = CAMPER mBlacklist[39] = TIPTRUCK mBlacklist[40] = TOURBUS mBlacklist[41] = TOWTRUCK mBlacklist[42] = TOWTRUCK2 mBlacklist[43] = TRACTOR mBlacklist[44] = TRACTOR2 mBlacklist[45] = UTILLITRUCK mBlacklist[46] = UTILLITRUCK2 mBlacklist[47] = UTILLITRUCK3 mBlacklist[48] = RATLOADER mBlacklist[49] = DLOADER mBlacklist[50] = DOCKTUG mBlacklist[51] = DUMP mBlacklist[52] = GBURRITO mBlacklist[53] = HANDLER mBlacklist[54] = HAULER mBlacklist[55] = JOURNEY mBlacklist[56] = RENTALBUS mBlacklist[57] = MIXER mBlacklist[58] = RHINO mBlacklist[59] = CUTTER mBlacklist[60] = POUNDER mBlacklist[61] = TIPTRUCK2 mBlacklist[62] = MIXER2 mBlacklist[63] = RUBBLE mBlacklist[64] = SCRAP mBlacklist[65] = ARMYTANKER mBlacklist[66] = BARRACKS2 mBlacklist[67] = AIRBUS mBlacklist[68] = COACH mBlacklist[69] = PBUS mBlacklist[70] = RIOT mBlacklist[71] = DUMMY_MODEL_FOR_SCRIPT mBlacklist[72] = STOCKADE3 mBlacklist[73] = FLATBED mBlacklist[74] = BOXVILLE mBlacklist[75] = BURRITO2 mBlacklist[76] = BURRITO3 mBlacklist[77] = BURRITO4 mBlacklist[78] = RUMPO mBlacklist[79] = SPEEDO2 mBlacklist[80] = DUMMY_MODEL_FOR_SCRIPT mBlacklist[81] = BLIMP mBlacklist[82] = BLIMP2 REPEAT COUNT_OF(mBlacklist) iIndex IF vehModel = mBlacklist[iIndex] //RETURN FALSE RETURN RVT_NOT_SUITABLE ENDIF ENDREPEAT ENDIF ENDIF //RETURN TRUE RETURN RVT_OK ENDFUNC /// PURPOSE: Is the player in a vehicle and in the air FUNC BOOL IS_PLAYER_AIRBORNE() IF IS_PLAYER_PLAYING(PLAYER_ID()) // Is the player in a vehicle IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID()) // Get vehicle index VEHICLE_INDEX viVehicle = GET_VEHICLE_PED_IS_USING(PLAYER_PED_ID()) // Are we in the air? IF IS_ENTITY_ALIVE(viVehicle) IF IS_ENTITY_IN_AIR(viVehicle) IF raceData.eRaceType = RACETYPE_SEA AND IS_ENTITY_IN_WATER(viVehicle) RETURN FALSE ENDIF RETURN TRUE ELSE RETURN FALSE ENDIF ENDIF ENDIF ENDIF RETURN FALSE ENDFUNC /// PURPOSE: Is the player on a motorbike (not bicycle or quad bike) FUNC RACE_VEHICLE_TYPE IS_PLAYER_ON_SUITABLE_RACE_BIKE() IF IS_PLAYER_PLAYING(PLAYER_ID()) IF DOES_ENTITY_EXIST(sPlayerVehicle.vehPlayerVehicle) MODEL_NAMES model = GET_ENTITY_MODEL(sPlayerVehicle.vehPlayerVehicle) IF model = POLICEB RETURN RVT_COP ENDIF IF IS_THIS_MODEL_A_BIKE(model) AND NOT IS_THIS_MODEL_A_BICYCLE(model) RETURN RVT_OK ENDIF ENDIF ENDIF RETURN RVT_NOT_SUITABLE ENDFUNC /// PURPOSE: Is the player in a race suitable sea vehicle FUNC BOOL IS_PLAYER_IN_SUITABLE_SEA_VEHICLE() IF IS_PLAYER_PLAYING(PLAYER_ID()) IF DOES_ENTITY_EXIST(sPlayerVehicle.vehPlayerVehicle) MODEL_NAMES model = GET_ENTITY_MODEL(sPlayerVehicle.vehPlayerVehicle) IF model = SEASHARK OR model = SEASHARK2 RETURN TRUE ENDIF ENDIF ENDIF RETURN FALSE ENDFUNC /// PURPOSE: Checks valid vehicle for car or bike race FUNC BOOL IS_PLAYER_IN_SUITABLE_VEHICLE_FOR_RACE() RACE_VEHICLE_TYPE rvtCheck SWITCH raceData.eRaceType CASE RACETYPE_BIKE rvtCheck = IS_PLAYER_ON_SUITABLE_RACE_BIKE() IF rvtCheck = RVT_COP // "Can't enter a street race in an emergency vehicle." DISPLAY_RACE_HELP("STREET_NA_COP") RETURN FALSE ELIF rvtCheck = RVT_NOT_SUITABLE // "You need a motorbike in order to enter this Street Race." DISPLAY_RACE_HELP("STREET_NA_BIKE") RETURN FALSE ENDIF BREAK CASE RACETYPE_CAR rvtCheck = IS_PLAYER_IN_SUITABLE_RACE_CAR() IF rvtCheck = RVT_COP // "Can't enter a street race in an emergency vehicle." DISPLAY_RACE_HELP("STREET_NA_COP") RETURN FALSE ELIF rvtCheck = RVT_NOT_SUITABLE // "You need a car in order to enter this Street Race." DISPLAY_RACE_HELP("STREET_NA_CAR") RETURN FALSE ENDIF BREAK CASE RACETYPE_SEA IF NOT IS_PLAYER_IN_SUITABLE_SEA_VEHICLE() // "You need a suitable vehicle in order to enter this Sea Race." STRING sSeaMsg IF IS_VEHICLE_OK(viCar) sSeaMsg = "SEA_NA_VEH" ELSE sSeaMsg = "SEA_NA_VEH2" ENDIF DISPLAY_RACE_HELP(sSeaMsg) RETURN FALSE ENDIF BREAK ENDSWITCH RETURN TRUE ENDFUNC FUNC BOOL PLAYERS_TYRES_BURST() MODEL_NAMES vehModel = GET_ENTITY_MODEL(sPlayerVehicle.vehPlayerVehicle) IF IS_THIS_MODEL_A_BIKE(vehModel) IF IS_VEHICLE_TYRE_BURST(sPlayerVehicle.vehPlayerVehicle, SC_WHEEL_BIKE_FRONT) OR IS_VEHICLE_TYRE_BURST(sPlayerVehicle.vehPlayerVehicle, SC_WHEEL_BIKE_REAR) RETURN TRUE ENDIF ELIF IS_THIS_MODEL_A_CAR(vehModel) IF IS_VEHICLE_TYRE_BURST(sPlayerVehicle.vehPlayerVehicle, SC_WHEEL_CAR_FRONT_LEFT) OR IS_VEHICLE_TYRE_BURST(sPlayerVehicle.vehPlayerVehicle, SC_WHEEL_CAR_FRONT_RIGHT) OR IS_VEHICLE_TYRE_BURST(sPlayerVehicle.vehPlayerVehicle, SC_WHEEL_CAR_REAR_LEFT) OR IS_VEHICLE_TYRE_BURST(sPlayerVehicle.vehPlayerVehicle, SC_WHEEL_CAR_REAR_RIGHT) RETURN TRUE ENDIF ENDIF RETURN FALSE ENDFUNC PROC DISPLAY_NEED_VEHICLE_HELP() IF raceData.eRaceType = RACETYPE_SEA // "You need a suitable vehicle in order to enter this Sea Race" STRING sSeaMsg IF IS_VEHICLE_OK(viCar) sSeaMsg = "SEA_NA_VEH" ELSE sSeaMsg = "SEA_NA_VEH2" ENDIF IF NOT IS_THIS_HELP_MESSAGE_BEING_DISPLAYED(sSeaMsg) PRINT_HELP_FOREVER(sSeaMsg) bDisplayHelp = TRUE iHelpTextTimer = GET_GAME_TIMER() + MIN_HELP_TEXT_TIME ENDIF ELIF raceData.eRaceType = RACETYPE_BIKE // "A motorbike is needed to enter this street race IF NOT IS_THIS_HELP_MESSAGE_BEING_DISPLAYED("STREET_NA_BIKE") PRINT_HELP_FOREVER("STREET_NA_BIKE") bDisplayHelp = TRUE iHelpTextTimer = GET_GAME_TIMER() + MIN_HELP_TEXT_TIME ENDIF ELSE // "You need a car in order to enter this Street Race." IF NOT IS_THIS_HELP_MESSAGE_BEING_DISPLAYED("STREET_NA_CAR") PRINT_HELP_FOREVER("STREET_NA_CAR") bDisplayHelp = TRUE iHelpTextTimer = GET_GAME_TIMER() + MIN_HELP_TEXT_TIME ENDIF ENDIF ENDPROC /// PURPOSE: Checks global flags to see whether race script can be launched FUNC BOOL CAN_PLAYER_LAUNCH_RACE() IF IS_PLAYER_PLAYING(PLAYER_ID()) // Is the player airborne in a vehicle? IF IS_PLAYER_AIRBORNE() RETURN FALSE ENDIF // Check for race entry fee IF GET_TOTAL_CASH(GET_CURRENT_PLAYER_PED_ENUM()) < raceData.iRaceFee IF raceData.eRaceType = RACETYPE_SEA // "You can't afford to enter this Sea Race. You need $ in order to participate in this race." DISPLAY_RACE_HELP_WITH_NUMBER("SEA_NA_CASH", raceData.iRaceFee) ELSE // "You can't afford to enter this Street Race... DISPLAY_RACE_HELP_WITH_NUMBER("STREET_NA_CASH", raceData.iRaceFee) ENDIF bDisplayHelp = TRUE iHelpTextTimer = GET_GAME_TIMER() + MIN_HELP_TEXT_TIME RETURN FALSE ENDIF // Is the player in a vehicle IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID()) // Get vehicle index SAFE_RELEASE_VEHICLE(sPlayerVehicle.vehPlayerVehicle) sPlayerVehicle.vehPlayerVehicle = GET_VEHICLE_PED_IS_USING(PLAYER_PED_ID()) // Check for correct type of vehicle IF NOT IS_PLAYER_IN_SUITABLE_VEHICLE_FOR_RACE() bDisplayHelp = TRUE iHelpTextTimer = GET_GAME_TIMER() + MIN_HELP_TEXT_TIME RETURN FALSE ELIF ((GET_ENTITY_HEALTH(sPlayerVehicle.vehPlayerVehicle) <= VEHICLE_DAMAGE_LIMIT) OR IS_ENTITY_ON_FIRE(sPlayerVehicle.vehPlayerVehicle)) OR PLAYERS_TYRES_BURST() // "Your vehicle is too damaged to race." DISPLAY_RACE_HELP("RACE_VehDmg") bDisplayHelp = TRUE iHelpTextTimer = GET_GAME_TIMER() + MIN_HELP_TEXT_TIME RETURN FALSE ELIF GET_PED_IN_VEHICLE_SEAT(sPlayerVehicle.vehPlayerVehicle, VS_DRIVER) <> PLAYER_PED_ID() // Player has taken a taxi ride to the race start DISPLAY_NEED_VEHICLE_HELP() RETURN FALSE ELSE // Races cannot be triggered when phone is onscreen IF IS_PHONE_ONSCREEN() OR GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(HASH("appInternet")) > 0 MANAGE_RACE_HELP() RETURN FALSE ENDIF // Otherwise we are ok to launch.. SWITCH raceData.eRaceType CASE RACETYPE_BIKE DISPLAY_RACE_HELP_WITH_NUMBER("STREET_PLAY_B", raceData.iRaceFee) BREAK CASE RACETYPE_CAR DISPLAY_RACE_HELP_WITH_NUMBER("STREET_PLAY_C", raceData.iRaceFee) BREAK CASE RACETYPE_SEA DISPLAY_RACE_HELP("SEA_PLAY") BREAK ENDSWITCH bDisplayHelp = TRUE iHelpTextTimer = GET_GAME_TIMER() RETURN TRUE ENDIF ELSE SAFE_RELEASE_VEHICLE(sPlayerVehicle.vehPlayerVehicle) DISPLAY_NEED_VEHICLE_HELP() RETURN FALSE ENDIF ENDIF RETURN FALSE ENDFUNC /// PURPOSE: Requests candidate ID and asks permission to launch script FUNC BOOL RACE_REQUEST_PERMISSION_TO_RUN() // Get mission candidate ID m_enumMissionCandidateReturnValue allowLaunch = Request_Mission_Launch(raceData.iCandidateID, MCTID_MUST_LAUNCH, MISSION_TYPE_MINIGAME) #IF IS_DEBUG_BUILD IF (allowLaunch = MCRET_DENIED) PRINTLN("DENIED - Another mission must have launched, Street Race should terminate...") ENDIF IF (allowLaunch = MCRET_PROCESSING) PRINTLN("PROCESSING - Race should keep trying...") ENDIF IF (allowLaunch = MCRET_ACCEPTED) PRINTLN("ACCEPTED - Race must run because it now has control of the IS_CURRENTLY_ON_MISSION_TO_TYPE() flag...") ENDIF #ENDIF IF NOT (allowLaunch = MCRET_ACCEPTED) // DENIED or still PROCESSING. RETURN FALSE ENDIF RETURN TRUE ENDFUNC /// PURPOSE: Launch race script PROC SAFE_REQUEST_AND_LAUNCH_RACE() // Request and load race script CPRINTLN(DEBUG_MISSION, "Race Launcher: Requesting mission race script...") IF NOT IS_REPEAT_PLAY_ACTIVE() REQUEST_SCRIPT("mission_Race") WHILE NOT HAS_SCRIPT_LOADED("mission_Race") REQUEST_SCRIPT("mission_Race") WAIT(0) ENDWHILE // Start script and terminate launcher CPRINTLN(DEBUG_MISSION, "Race Launcher: Starting mission race script...") START_NEW_SCRIPT_WITH_ARGS("mission_Race", raceData, SIZE_OF(raceData), MISSION_STACK_SIZE) ELSE CPRINTLN(DEBUG_MISSION, "Race Launcher: Skipped launching mission race script as a repeat play was activated.") ENDIF SET_SCRIPT_AS_NO_LONGER_NEEDED("mission_Race") SCRIPT_CLEANUP() ENDPROC /// PURPOSE: /// Launches a single player instance of the race PROC DO_RACE_LAUNCH_SP() CPRINTLN(DEBUG_MISSION, "Race Launcher: DO_RACE_LAUNCH_SP") // Reset candidate ID raceData.iCandidateID = NO_CANDIDATE_ID IF IS_PED_UNINJURED(PLAYER_PED_ID()) IF NOT IS_PED_WEARING_HELMET(PLAYER_PED_ID()) SET_PED_HELMET(PLAYER_PED_ID(), FALSE) ENDIF ENDIF // Request permission to launch race WHILE NOT RACE_REQUEST_PERMISSION_TO_RUN() WAIT(0) ENDWHILE // Deduct race fee IF raceData.eRaceType <> RACETYPE_SEA DEBIT_BANK_ACCOUNT(GET_CURRENT_PLAYER_PED_ENUM(), BAAC_UNLOGGED_SMALL_ACTION, raceData.iRaceFee) //WAIT(2000) INT iWaitTime = GET_GAME_TIMER() + 1500 VEHICLE_INDEX viPlayer = GET_PLAYERS_LAST_VEHICLE() IF IS_VEHICLE_OK(viPlayer) WHILE NOT BRING_VEHICLE_TO_HALT_AND_DISABLE_VEH_CONTROLS(viPlayer, 3.0, 2) // Reduce stopping distance to reduce chance of player hitting the initial scene peds B* 1510355 OR GET_GAME_TIMER() < iWaitTime WAIT(0) ENDWHILE /*ELSE WAIT(1500)*/ ENDIF //WAIT(1500) //ANIMPOSTFX_PLAY("SwitchSceneNeutral", 0, TRUE) // Disable player control PLAYER_INDEX pId = GET_PLAYER_INDEX() IF IS_PLAYER_PLAYING(pId) SET_PLAYER_CONTROL(pId, FALSE) ENDIF //WAIT(500) /*iWaitTime = GET_GAME_TIMER() + 500 WHILE NOT BRING_VEHICLE_TO_HALT_AND_DISABLE_VEH_CONTROLS(viPlayer, DEFAULT_VEH_STOPPING_DISTANCE, 2) OR GET_GAME_TIMER() < iWaitTime WAIT(0) ENDWHILE*/ ENDIF // Launch the race SAFE_REQUEST_AND_LAUNCH_RACE() ENDPROC /// PURPOSE: /// Notify systems that we want to launch a MP PROC DO_RACE_LAUNCH_MP() CPRINTLN(DEBUG_MISSION, "Race Launcher: DO_RACE_LAUNCH_MP") // Call MP commands to launch FM SET_PAUSE_MENU_WARP_FROM_MODE(GAMEMODE_SP) SET_PAUSE_MENU_WARP_TO_MODE(GAMEMODE_FM) SET_PAUSE_MENU_WARP_TO_VECTOR(vInCoords) SET_PAUSE_MENU_REQUESTING_A_WARP() // Setup globals g_FMSP_Race_Data.bActive = TRUE g_FMSP_Race_Data.iRaceID = ENUM_TO_INT(raceData.eRaceTrack) g_FMSP_Race_Data.sUserID = GET_CLOUD_ID() g_FMSP_Race_Data.sFilename = GET_RACE_FILENAME(raceData.eRaceTrack) g_FMSP_Race_Data.vLocation = vInCoords g_Private_ReturningFromActivitySession = TRUE // Output MP globals #IF IS_DEBUG_BUILD OUTPUT_MP_GLOBALS_TO_TTY() #ENDIF SCRIPT_CLEANUP() ENDPROC /// PURPOSE: Determine which race is associated with this world point PROC GET_RACE_LOCATION() /************************************* STREET RACES **********************************/ // South Los Santos IF ARE_VECTORS_ALMOST_EQUAL(GET_STATIC_BLIP_POSITION(STATIC_BLIP_MINIGAME_STREET_RACE1), vInCoords, WORLD_POINT_COORD_TOLERANCE) CPRINTLN(DEBUG_MISSION, "Race Launcher: South Los Santos") raceData.eRaceTrack = STREET_RACE_01 raceData.eRaceType = RACETYPE_CAR raceData.iRaceFee = 100 raceData.iSaveSlot = 20 // City circuit ELIF ARE_VECTORS_ALMOST_EQUAL(GET_STATIC_BLIP_POSITION(STATIC_BLIP_MINIGAME_STREET_RACE2), vInCoords, WORLD_POINT_COORD_TOLERANCE) CPRINTLN(DEBUG_MISSION, "Race Launcher: City Circuit") raceData.eRaceTrack = STREET_RACE_02 raceData.eRaceType = RACETYPE_CAR raceData.iRaceFee = 500 raceData.iSaveSlot = 18 // Airport ELIF ARE_VECTORS_ALMOST_EQUAL(GET_STATIC_BLIP_POSITION(STATIC_BLIP_MINIGAME_STREET_RACE4), vInCoords, WORLD_POINT_COORD_TOLERANCE) CPRINTLN(DEBUG_MISSION, "Race Launcher: Airport") raceData.eRaceTrack = STREET_RACE_04 raceData.eRaceType = RACETYPE_CAR raceData.iRaceFee = 1000 raceData.iSaveSlot = 2 // Freeway ELIF ARE_VECTORS_ALMOST_EQUAL(GET_STATIC_BLIP_POSITION(STATIC_BLIP_MINIGAME_STREET_RACE5), vInCoords, WORLD_POINT_COORD_TOLERANCE) CPRINTLN(DEBUG_MISSION, "Race Launcher: Freeway") raceData.eRaceTrack = STREET_RACE_05 raceData.eRaceType = RACETYPE_CAR raceData.iRaceFee = 1250 raceData.iSaveSlot = 4 // Vespucci Canals ELIF ARE_VECTORS_ALMOST_EQUAL(GET_STATIC_BLIP_POSITION(STATIC_BLIP_MINIGAME_STREET_RACE6), vInCoords, WORLD_POINT_COORD_TOLERANCE) CPRINTLN(DEBUG_MISSION, "Race Launcher: Vespucci Canals") raceData.eRaceTrack = STREET_RACE_06 raceData.eRaceType = RACETYPE_BIKE raceData.iRaceFee = 1500 raceData.iSaveSlot = 5 /************************************* SEA RACES **********************************/ // North Coast ELIF ARE_VECTORS_ALMOST_EQUAL(GET_STATIC_BLIP_POSITION(STATIC_BLIP_MINIGAME_SEA_RACE1), vInCoords, WORLD_POINT_COORD_TOLERANCE) CPRINTLN(DEBUG_MISSION, "Race Launcher: North Coast)") raceData.eRaceTrack = SEA_RACE_01 raceData.eRaceType = RACETYPE_SEA raceData.iRaceFee = 0 raceData.iSaveSlot = 16 // East Coast ELIF ARE_VECTORS_ALMOST_EQUAL(GET_STATIC_BLIP_POSITION(STATIC_BLIP_MINIGAME_SEA_RACE2), vInCoords, WORLD_POINT_COORD_TOLERANCE) CPRINTLN(DEBUG_MISSION, "Race Launcher: South Coast") raceData.eRaceTrack = SEA_RACE_02 raceData.eRaceType = RACETYPE_SEA raceData.iRaceFee = 0 raceData.iSaveSlot = 13 // Raton Canyon ELIF ARE_VECTORS_ALMOST_EQUAL(GET_STATIC_BLIP_POSITION(STATIC_BLIP_MINIGAME_SEA_RACE3), vInCoords, WORLD_POINT_COORD_TOLERANCE) CPRINTLN(DEBUG_MISSION, "Race Launcher: Raton Canyon") raceData.eRaceTrack = SEA_RACE_03 raceData.eRaceType = RACETYPE_SEA raceData.iRaceFee = 0 raceData.iSaveSlot = 15 raceData.bP2P = TRUE // Los Santos ELIF ARE_VECTORS_ALMOST_EQUAL(GET_STATIC_BLIP_POSITION(STATIC_BLIP_MINIGAME_SEA_RACE4), vInCoords, WORLD_POINT_COORD_TOLERANCE) CPRINTLN(DEBUG_MISSION, "Race Launcher: Los Santos") raceData.eRaceTrack = SEA_RACE_04 raceData.eRaceType = RACETYPE_SEA raceData.iSaveSlot = 24 raceData.iRaceFee = 0 raceData.bP2P = TRUE ELSE CPRINTLN(DEBUG_MISSION, "Race Launcher: No Race Found") SCRIPT_CLEANUP(FALSE) ENDIF ENDPROC /// PURPOSE: /// Checks if the initial scene should be created - if we're debug skipping here or the player is more than 100 metres away /// RETURNS: /// TRUE if we're OK to create the initial scene FUNC BOOL ALLOW_INITIAL_SCENE() IF NOT IS_RACE_ALLOWED_FOR_TIME_OF_DAY() RETURN FALSE ENDIF #IF IS_DEBUG_BUILD IF g_RaceLaunchedFromDebug = TRUE RETURN TRUE ENDIF #ENDIF IF IS_PED_UNINJURED(PLAYER_PED_ID()) IF NOT IS_ENTITY_IN_RANGE_COORDS(PLAYER_PED_ID(), vCarPos, 100.0) OR IS_SCREEN_FADED_OUT() RETURN TRUE ENDIF ENDIF RETURN FALSE ENDFUNC /// PURPOSE: /// Sets up the values needed to create the initial scene PROC SETUP_INITIAL_SCENE() IF raceData.eRaceType = RACETYPE_BIKE OR raceData.eRaceType = RACETYPE_CAR CPRINTLN(DEBUG_MISSION, "Race Launcher: Creating initial scene: Is a car or bike race") SWITCH raceData.eRaceTrack // South Los Santos CASE STREET_RACE_01 vCarPos = <<-158.67, -1555.16, 34.63>> fCarFoc = 187.71 vCarPos2 = <<-155.15, -1550.83, 34.53>> fCarFoc2 = 213.13 // min and max coords for the race area vMinRaceArea = <<-68.878784,-1818.902710,24.553106>> vMaxRaceArea = <<-56.009800,-1807.028687,27.854170>> // Offsets offset_pos[0] = <<-157.19, -1555.36, 35.07>> offset_pos[1] = <<-157.04, -1557.57, 35.11>> offset_pos[2] = <<-159.83, -1557.39, 34.96>> offset_pos[3] = <<-156.64, -1551.96, 34.92>> offset_pos[4] = <<-156.25, -1552.58, 34.93>> offset_pos[5] = <<-153.23, -1553.05, 34.93>> offset_pos[6] = <<-155.30, -1556.41, 35.13>> offset_heading [0] = 101.91//16.54 offset_heading [1] = 38.48//-141.52 offset_heading [2] = -36.70 offset_heading [3] = -52.93 offset_heading [4] = -75.07 offset_heading [5] = 33.13 offset_heading [6] = -170.02 BREAK // City Circuit CASE STREET_RACE_02 vCarPos = <<368.72, 294.06, 102.96>> fCarFoc = 25.17 vCarPos2 = <<373.71, 290.72, 102.89>> fCarFoc2 = 33.24 // min and max coords for the race area vMinRaceArea = <<-523.549683,262.298553,80.019905>> vMaxRaceArea = <<-509.101349,272.478027,86.177132>> // Offsets offset_pos[0] = <<367.24, 293.81, 103.41>> offset_pos[1] = <<368.73, 296.89, 103.41>> offset_pos[2] = <<366.94, 296.34, 103.43>> offset_pos[3] = <<375.21, 291.85, 103.25>> offset_pos[4] = <<374.81, 292.47, 103.26>> offset_pos[5] = <<371.51, 291.85, 103.31>> offset_pos[6] = <<373.86, 296.30, 103.31>> offset_heading [0] = -64.83 offset_heading [1] = -163.04 offset_heading [2] = -118.77 offset_heading [3] = 127.18 offset_heading [4] = 105.04 offset_heading [5] = -146.75 offset_heading [6] = 10.11 BREAK // Airport CASE STREET_RACE_04 vCarPos = <<-807.98, -2555.14, 13.34>> fCarFoc = 3.35 vCarPos2 = <<-810.10, -2560.85, 13.38>>//<<-809.86, -2560.89, 13.38>> fCarFoc2 = 43.57 // min and max coords for the race area vMinRaceArea = <<-1000.758545,-2436.091797,17.169464>> vMaxRaceArea = <<-986.739929,-2424.869873,22.169460>> // Offsets offset_pos[0] = <<-809.45, -2554.82, 13.76>> offset_pos[1] = <<-808.47, -2552.43, 13.76>> offset_pos[2] = <<-806.32, -2552.87, 13.76>> offset_pos[3] = <<-808.59, -2559.50, 13.76>> offset_pos[4] = <<-809.10, -2558.97, 13.76>> offset_pos[5] = <<-812.82, -2559.48, 13.76>> offset_pos[6] = <<-810.72, -2555.37, 13.76>> offset_heading [0] = -86.65 offset_heading [1] = -130.05 offset_heading [2] = 150.04 offset_heading [3] = 137.51 offset_heading [4] = 115.37 offset_heading [5] = -136.43 offset_heading [6] = 20.43 BREAK // Freeway CASE STREET_RACE_05 vCarPos = <<778.59, -1160.20, 28.35>> fCarFoc = 302.47 vCarPos2 = <<778.47, -1164.01, 28.25>> fCarFoc2 = 287.97 // min and max coords for the race area vMinRaceArea = <<-1000.758545,-2436.091797,17.169464>> vMaxRaceArea = <<-986.739929,-2424.869873,22.169460>> // Offsets offset_pos[0] = <<778.16, -1158.78, 28.88>> offset_pos[1] = <<780.82, -1158.10, 28.73>> offset_pos[2] = <<781.52, -1158.81, 28.70>> offset_pos[3] = <<779.16, -1165.74, 28.72>> offset_pos[4] = <<779.86, -1165.52, 28.72>> offset_pos[5] = <<780.75, -1161.99, 28.65>> offset_pos[6] = <<783.80, -1165.61, 28.74>> offset_heading [0] = -147.53 offset_heading [1] = 171.51 offset_heading [2] = 104.94 offset_heading [3] = 21.91 offset_heading [4] = -0.22 offset_heading [5] = 107.91 offset_heading [6] = -95.23 BREAK // Vespucci Canals CASE STREET_RACE_06 vCarPos = <<-1066.59, -1151.04, 1.71>> fCarFoc = 258.32 // Offsets offset_pos[0] = <<-1065.07, -1151.02, 2.16>> offset_pos[1] = <<-1065.35, -1149.36, 2.16>> offset_pos[2] = <<-1067.13, -1151.68, 2.16>> offset_pos[3] = <<-1066.30, -1149.38, 2.16>> offset_pos[4] = <<-1066.01, -1152.26, 2.16>> offset_heading [0] = 75.06 offset_heading [1] = 134.25 offset_heading [2] = -52.71 offset_heading [3] = -93.39 offset_heading [4] = -141.52 // min and max coords for the race area vMinRaceArea = <<-1265.744385,-1057.199219,5.410841>> vMaxRaceArea = <<-1258.678955,-1049.919067,9.443882>> BREAK ENDSWITCH SETUP_ROAD_BLOCKING(raceData.eRaceTrack, vRaceRoadPos1, vRaceRoadPos2, fRaceRoadWidth) ePedModel[0] = A_F_Y_Hipster_02 ePedModel[1] = A_M_Y_Hipster_02 ePedModel[2] = A_M_Y_Hipster_02 ePedModel[3] = A_F_Y_Hipster_02 ePedModel[4] = A_M_Y_Hipster_02 ePedModel[5] = A_M_Y_Hipster_02 ePedModel[6] = A_M_Y_Hipster_02 // Animations IF raceData.eRaceType = RACETYPE_BIKE sAnimDict = "random@street_race" sAnimName[0] = "_car_b_chatting_female" sAnimName[1] = "_car_b_chatting_male" sAnimName[2] = "_car_b_chatting_male" sAnimName[3] = "_car_b_chatting_female" sAnimName[4] = "_car_b_lookout" ELSE sAnimDict = "random@street_race" sAnimName[0] = "_car_a_flirt_girl" sAnimName[1] = "_car_a_gawker_male_a" sAnimName[2] = "_car_a_gawker_male_b" sAnimName[3] = "_car_b_chatting_female" sAnimName[4] = "_car_b_chatting_male" sAnimName[5] = "_car_b_driver" sAnimName[6] = "_car_b_lookout" // REQUEST_MODEL(eCarModel2) LOAD_QUEUE_MEDIUM_ADD_MODEL(sLoadQueue, eCarModel2) ENDIF eCarModel = GET_MODEL_NAME_BASED_OFF_RACE_TYPE(raceData.eRaceType) // Request ped models INT iIndex FOR iIndex = 0 TO COUNT_OF(ePedModel) - 1 // REQUEST_MODEL(ePedModel[iIndex]) LOAD_QUEUE_MEDIUM_ADD_MODEL(sLoadQueue, ePedModel[iIndex]) ENDFOR // REQUEST_MODEL(eCarModel) LOAD_QUEUE_MEDIUM_ADD_MODEL(sLoadQueue, eCarModel) // Request animations // REQUEST_ANIM_DICT(sAnimDict) LOAD_QUEUE_MEDIUM_ADD_ANIM_DICT(sLoadQueue, sAnimDict) // stop other peds walking through the area SET_PED_PATHS_IN_AREA(vMinRaceArea, vMaxRaceArea, FALSE) SET_ROADS_IN_ANGLED_AREA(vRaceRoadPos1, vRaceRoadPos2, fRaceRoadWidth, FALSE, FALSE) bCreatedAreaBlocks = TRUE ELIF raceData.eRaceType = RACETYPE_SEA CPRINTLN(DEBUG_MISSION, "Race Launcher: Creating initial scene: Is a sea race") SWITCH raceData.eRaceTrack // North Coast CASE SEA_RACE_01 vCarPos = <<3066.63, 650.90, 0.17>> fCarFoc = 351.81 vLineupPos[0] = <<3073.57, 648.09, 0.01>> fLineupFoc[0] = 5.72 vLineupPos[1] = <<3071.53, 648.79, -0.09>> fLineupFoc[1] = 351.33 vLineupPos[2] = <<3068.73, 645.53, -0.07>> fLineupFoc[2] = 348.18 BREAK // East coast CASE SEA_RACE_02 vCarPos = <<3462.11, 5192.15, -0.04>> fCarFoc = 222.90 vLineupPos[0] = <<3456.64, 5195.91, 0.12>> fLineupFoc[0] = 211.54 vLineupPos[1] = <<3453.19, 5192.84, -0.17>> fLineupFoc[1] = 201.55 vLineupPos[2] = <<3451.06, 5189.43, -0.30>> fLineupFoc[2] = 221.55 BREAK // Raton Canyon CASE SEA_RACE_03 vCarPos = <<194.64, 3621.27, 29.91>>//<<145.66, 3455.27, 29.93>> fCarFoc = 163.95//154.48 vLineupPos[0] = <<198.62, 3620.46, 29.91>>//<<149.65, 3453.45, 29.90>> fLineupFoc[0] = 175.40//164.07 vLineupPos[1] = <<202.78, 3619.69, 29.87>>//<<153.37, 3452.00, 29.90>> fLineupFoc[1] = 163.69//152.39 vLineupPos[2] = <<210.14, 3618.88, 29.87>>//<<157.20, 3449.60, 29.99>> fLineupFoc[2] = 175.31//140.07 BREAK // Los Santos CASE SEA_RACE_04 vCarPos = <<627.58, -2138.06, -0.07>> fCarFoc = 180.09 vLineupPos[0] = <<643.09, -2146.11, -0.09>> fLineupFoc[0] = 143.89 vLineupPos[1] = <<638.21, -2145.30, -0.10>> fLineupFoc[1] = 172.41 vLineupPos[2] = <<633.56, -2143.83, -0.04>> fLineupFoc[2] = 191.97 BREAK ENDSWITCH eCarModel = SEASHARK // REQUEST_MODEL(eCarModel) // REQUEST_MODEL(A_M_Y_Jetski_01) LOAD_QUEUE_MEDIUM_ADD_MODEL(sLoadQueue, eCarModel) LOAD_QUEUE_MEDIUM_ADD_MODEL(sLoadQueue, A_M_Y_Jetski_01) ENDIF ENDPROC /// PURPOSE: /// Creates the initial scene PROC CREATE_INITIAL_SCENE() IF HAS_LOAD_QUEUE_MEDIUM_LOADED(sLoadQueue) IF raceData.eRaceType = RACETYPE_CAR IF ALLOW_INITIAL_SCENE() IF NOT DOES_ENTITY_EXIST(viCar) IF HAS_MODEL_LOADED(eCarModel) AND HAS_MODEL_LOADED(eCarModel) CPRINTLN(DEBUG_MISSION, "Race Launcher: Creating initial scene: Creating vehicle") //Create vehicle... viCar = CREATE_VEHICLE(eCarModel, vCarPos, fCarFoc) IF CAN_CREATE_RANDOM_PED(RPM_MALE_PED) AND CAN_CREATE_RANDOM_DRIVER() piDriver = CREATE_RANDOM_PED_AS_DRIVER(viCar) TASK_VEHICLE_TEMP_ACTION(piDriver, viCar, TEMPACT_WAIT, 99999999) SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(piDriver, TRUE) SET_PED_KEEP_TASK(piDriver, TRUE) ENDIF SET_VEHICLE_ON_GROUND_PROPERLY(viCar) SET_VEHICLE_ENGINE_ON(viCar, TRUE, TRUE) SET_VEHICLE_RADIO_ENABLED(viCar, TRUE) SET_VEHICLE_RADIO_LOUD(viCar, TRUE) SET_RADIO_STATION_MUSIC_ONLY(GET_RADIO_STATION_NAME(ENUM_TO_INT(RADIO_GENRE_DANCE)), TRUE) SET_VEH_RADIO_STATION(viCar, GET_RADIO_STATION_NAME(ENUM_TO_INT(RADIO_GENRE_DANCE))) SET_VEHICLE_NOT_STEALABLE_AMBIENTLY(viCar, FALSE) SET_MODEL_AS_NO_LONGER_NEEDED(eCarModel) WAIT(0) ENDIF ENDIF IF NOT DOES_ENTITY_EXIST(viCar2) IF HAS_MODEL_LOADED(eCarModel2) CPRINTLN(DEBUG_MISSION, "Race Launcher: Creating initial scene: Creating vehicle") //Create vehicle... viCar2 = CREATE_VEHICLE(eCarModel2, vCarPos2, fCarFoc2) SET_VEHICLE_ENGINE_ON(viCar2, FALSE, TRUE) SET_VEHICLE_RADIO_ENABLED(viCar2, TRUE) SET_VEHICLE_RADIO_LOUD(viCar2, TRUE) SET_VEHICLE_ON_GROUND_PROPERLY(viCar2) SET_RADIO_STATION_MUSIC_ONLY(GET_RADIO_STATION_NAME(ENUM_TO_INT(RADIO_GENRE_DANCE)), TRUE) SET_VEH_RADIO_STATION(viCar2, GET_RADIO_STATION_NAME(ENUM_TO_INT(RADIO_GENRE_DANCE))) SET_VEHICLE_NOT_STEALABLE_AMBIENTLY(viCar2, FALSE) SET_MODEL_AS_NO_LONGER_NEEDED(eCarModel2) WAIT(0) ENDIF ENDIF // Wait for models and animations to load IF HAS_ANIM_DICT_LOADED(sAnimDict) IF bReleaseModels INT iIndex FOR iIndex = 0 TO COUNT_OF(ePedModel) - 1 // Play animation and look towards player when the ped has been created IF DOES_ENTITY_EXIST(piCrowd[iIndex]) IF NOT IS_ENTITY_DEAD(piCrowd[iIndex]) AND NOT IsPedPerformingTask(piCrowd[iIndex], SCRIPT_TASK_PLAY_ANIM) //SET_ENTITY_COORDS_NO_OFFSET(piCrowd[iIndex], offset_pos[iIndex]) TASK_PLAY_ANIM(piCrowd[iIndex], sAnimDict, sAnimName[iIndex], INSTANT_BLEND_IN, INSTANT_BLEND_OUT, -1, AF_LOOPING) SET_PED_KEEP_TASK(piCrowd[iIndex], TRUE) // Release model //SET_MODEL_AS_NO_LONGER_NEEDED(ePedModel[iIndex]) ENDIF ELSE // Ped hasn't been created yet, let's create him! IF HAS_MODEL_LOADED(ePedModel[iIndex]) CPRINTLN(DEBUG_MISSION, "Race Launcher: Creating initial scene: Creating peds") piCrowd[iIndex] = CREATE_PED(PEDTYPE_SPECIAL, ePedModel[iIndex], offset_pos[iIndex], offset_heading[iIndex]) SET_ENTITY_COORDS_NO_OFFSET(piCrowd[iIndex], offset_pos[iIndex]) SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(piCrowd[iIndex], TRUE) TASK_PLAY_ANIM(piCrowd[iIndex], sAnimDict, sAnimName[iIndex], INSTANT_BLEND_IN, INSTANT_BLEND_OUT, -1, AF_LOOPING) SET_PED_KEEP_TASK(piCrowd[iIndex], TRUE) ENDIF ENDIF ENDFOR IF IS_PED_UNINJURED(piCrowd[0]) AND IS_PED_UNINJURED(piCrowd[1]) AND IS_PED_UNINJURED(piCrowd[2]) AND IS_PED_UNINJURED(piCrowd[3]) AND IS_PED_UNINJURED(piCrowd[4]) AND IS_PED_UNINJURED(piCrowd[5]) AND IS_PED_UNINJURED(piCrowd[6]) AND IS_VEHICLE_OK(viCar) AND IS_VEHICLE_OK(viCar2) /*iSyncedSceneOne = CREATE_SYNCHRONIZED_SCENE(GET_WORLD_POSITION_OF_ENTITY_BONE(viCar, GET_ENTITY_BONE_INDEX_BY_NAME(viCar, "chassis_dummy")),GET_ENTITY_ROTATION(viCar)) SET_SYNCHRONIZED_SCENE_LOOPED(iSyncedSceneOne,TRUE) SET_SYNCHRONIZED_SCENE_HOLD_LAST_FRAME(iSyncedSceneOne,FALSE) //ATTACH_SYNCHRONIZED_SCENE_TO_ENTITY(iSyncedSceneOne, viCar, GET_ENTITY_BONE_INDEX_BY_NAME(viCar, "chassis_dummy")) iSyncedSceneTwo = CREATE_SYNCHRONIZED_SCENE(GET_WORLD_POSITION_OF_ENTITY_BONE(viCar2, GET_ENTITY_BONE_INDEX_BY_NAME(viCar2, "chassis_dummy")),GET_ENTITY_ROTATION(viCar2)) SET_SYNCHRONIZED_SCENE_LOOPED(iSyncedSceneTwo,TRUE) SET_SYNCHRONIZED_SCENE_HOLD_LAST_FRAME(iSyncedSceneTwo,FALSE) //ATTACH_SYNCHRONIZED_SCENE_TO_ENTITY(iSyncedSceneTwo, viCar2, GET_ENTITY_BONE_INDEX_BY_NAME(viCar2, "chassis_dummy")) TASK_SYNCHRONIZED_SCENE(piCrowd[0], iSyncedSceneOne, sAnimDict, sAnimName[0], INSTANT_BLEND_IN, SLOW_BLEND_OUT, SYNCED_SCENE_USE_PHYSICS, RBF_PLAYER_IMPACT) TASK_SYNCHRONIZED_SCENE(piCrowd[1], iSyncedSceneOne, sAnimDict, sAnimName[1], INSTANT_BLEND_IN, SLOW_BLEND_OUT, SYNCED_SCENE_USE_PHYSICS, RBF_PLAYER_IMPACT) TASK_SYNCHRONIZED_SCENE(piCrowd[2], iSyncedSceneOne, sAnimDict, sAnimName[2], INSTANT_BLEND_IN, SLOW_BLEND_OUT, SYNCED_SCENE_USE_PHYSICS, RBF_PLAYER_IMPACT) TASK_SYNCHRONIZED_SCENE(piCrowd[3], iSyncedSceneTwo, sAnimDict, sAnimName[3], INSTANT_BLEND_IN, SLOW_BLEND_OUT, SYNCED_SCENE_USE_PHYSICS, RBF_PLAYER_IMPACT) TASK_SYNCHRONIZED_SCENE(piCrowd[4], iSyncedSceneTwo, sAnimDict, sAnimName[4], INSTANT_BLEND_IN, SLOW_BLEND_OUT, SYNCED_SCENE_USE_PHYSICS, RBF_PLAYER_IMPACT) TASK_SYNCHRONIZED_SCENE(piCrowd[5], iSyncedSceneTwo, sAnimDict, sAnimName[5], INSTANT_BLEND_IN, SLOW_BLEND_OUT, SYNCED_SCENE_USE_PHYSICS, RBF_PLAYER_IMPACT) TASK_SYNCHRONIZED_SCENE(piCrowd[6], iSyncedSceneTwo, sAnimDict, sAnimName[6], INSTANT_BLEND_IN, NORMAL_BLEND_OUT, SYNCED_SCENE_USE_PHYSICS, RBF_PLAYER_IMPACT) TASK_LOOK_AT_ENTITY(piCrowd[6], PLAYER_PED_ID(), -1, SLF_WHILE_NOT_IN_FOV, SLF_LOOKAT_VERY_HIGH)*/ bStartPedSixTurning = TRUE FOR iIndex = 0 TO COUNT_OF(ePedModel) - 1 SET_MODEL_AS_NO_LONGER_NEEDED(ePedModel[iIndex]) ENDFOR bReleaseModels = FALSE ENDIF ENDIF ENDIF ENDIF ELIF raceData.eRaceType = RACETYPE_BIKE IF ALLOW_INITIAL_SCENE() IF NOT DOES_ENTITY_EXIST(viCar) IF HAS_MODEL_LOADED(eCarModel) CPRINTLN(DEBUG_MISSION, "Race Launcher: Creating initial scene: Creating vehicle") //Create vehicle... viCar = CREATE_VEHICLE(eCarModel, vCarPos, fCarFoc) IF CAN_CREATE_RANDOM_PED(RPM_DONT_CARE) AND CAN_CREATE_RANDOM_BIKE_RIDER() piDriver = CREATE_RANDOM_PED_AS_DRIVER(viCar) TASK_VEHICLE_TEMP_ACTION(piDriver, viCar, TEMPACT_WAIT, 99999999) SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(piDriver, TRUE) SET_PED_KEEP_TASK(piDriver, TRUE) ENDIF SET_VEHICLE_ENGINE_ON(viCar, TRUE, TRUE) SET_VEHICLE_RADIO_ENABLED(viCar, TRUE) SET_VEHICLE_RADIO_LOUD(viCar, TRUE) SET_RADIO_STATION_MUSIC_ONLY(GET_RADIO_STATION_NAME(ENUM_TO_INT(RADIO_GENRE_DANCE)), TRUE) SET_VEH_RADIO_STATION(viCar, GET_RADIO_STATION_NAME(ENUM_TO_INT(RADIO_GENRE_DANCE))) SET_VEHICLE_NOT_STEALABLE_AMBIENTLY(viCar, FALSE) SET_MODEL_AS_NO_LONGER_NEEDED(eCarModel) ENDIF ENDIF // Wait for models and animations to load IF HAS_ANIM_DICT_LOADED(sAnimDict) IF bReleaseModels INT iIndex FOR iIndex = 0 TO COUNT_OF(ePedModel) - 3 // Only creating five peds for the bike race // Play animation and look towards player when the ped has been created IF DOES_ENTITY_EXIST(piCrowd[iIndex]) IF NOT IS_ENTITY_DEAD(piCrowd[iIndex]) AND NOT IsPedPerformingTask(piCrowd[iIndex], SCRIPT_TASK_PLAY_ANIM) SET_ENTITY_COORDS_NO_OFFSET(piCrowd[iIndex], offset_pos[iIndex]) IF iIndex <> 2 AND iIndex <> 3 TASK_PLAY_ANIM(piCrowd[iIndex], sAnimDict, sAnimName[iIndex], INSTANT_BLEND_IN, INSTANT_BLEND_OUT, -1, AF_LOOPING) ELSE TASK_PLAY_ANIM(piCrowd[iIndex], sAnimDict, sAnimName[iIndex], INSTANT_BLEND_IN, INSTANT_BLEND_OUT, -1, AF_LOOPING, 0.5) ENDIF SET_PED_KEEP_TASK(piCrowd[iIndex], TRUE) ENDIF ELSE // Ped hasn't been created yet, let's create him! IF HAS_MODEL_LOADED(ePedModel[iIndex]) CPRINTLN(DEBUG_MISSION, "Race Launcher: Creating initial scene: Creating peds") piCrowd[iIndex] = CREATE_PED(PEDTYPE_SPECIAL, ePedModel[iIndex], offset_pos[iIndex], offset_heading[iIndex]) SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(piCrowd[iIndex], TRUE) ENDIF ENDIF ENDFOR IF IS_PED_UNINJURED(piCrowd[0]) AND IS_PED_UNINJURED(piCrowd[1]) AND IS_PED_UNINJURED(piCrowd[2]) AND IS_PED_UNINJURED(piCrowd[3]) AND IS_PED_UNINJURED(piCrowd[4]) TASK_LOOK_AT_ENTITY(piCrowd[4], PLAYER_PED_ID(), -1, SLF_WHILE_NOT_IN_FOV, SLF_LOOKAT_VERY_HIGH) FOR iIndex = 0 TO COUNT_OF(ePedModel) - 1 // Only five peds but seven models were loaded... SET_MODEL_AS_NO_LONGER_NEEDED(ePedModel[iIndex]) ENDFOR bReleaseModels = FALSE ENDIF ENDIF ENDIF ENDIF ELIF raceData.eRaceType = RACETYPE_SEA IF ALLOW_INITIAL_SCENE() IF NOT DOES_ENTITY_EXIST(viCar) CPRINTLN(DEBUG_MISSION,"Creating spare seashark") IF HAS_MODEL_LOADED(eCarModel) CPRINTLN(DEBUG_MISSION, "Race Launcher: Creating initial scene: Creating vehicle") //Create vehicle... viCar = CREATE_VEHICLE(eCarModel, vCarPos, fCarFoc) //ACTIVATE_PHYSICS(viCar) SET_VEHICLE_ON_GROUND_PROPERLY(viCar) SET_BOAT_LOW_LOD_ANCHOR_DISTANCE(viCar,0) //SET_BOAT_REMAINS_ANCHORED_WHILE_PLAYER_IS_DRIVER(viCar,TRUE) SET_BOAT_REMAINS_ANCHORED_WHILE_PLAYER_IS_DRIVER(viCar,FALSE) SET_FORCE_LOW_LOD_ANCHOR_MODE(viCar,FALSE) IF CAN_ANCHOR_BOAT_HERE(viCar) SET_BOAT_ANCHOR(viCar,TRUE) ENDIF SET_VEHICLE_ENGINE_ON(viCar, FALSE, TRUE) //bAnchored = TRUE ENDIF ENDIF INT i_index = 0 REPEAT LINEUP_SIZE i_index IF DOES_ENTITY_EXIST(viLineup[i_index]) IF DOES_ENTITY_EXIST(piLineup[i_index]) IF NOT IS_PED_INJURED(piLineup[i_index]) AND IS_VEHICLE_OK(viLineup[i_index]) IF IS_VEHICLE_SEAT_FREE(viLineup[i_index]) SET_PED_INTO_VEHICLE(piLineup[i_index], viLineup[i_index]) ENDIF ENDIF ELSE IF IS_VEHICLE_OK(viLineup[i_index]) AND HAS_MODEL_LOADED(A_M_Y_Jetski_01) piLineup[i_index] = CREATE_PED_INSIDE_VEHICLE(viLineup[i_index], PEDTYPE_SPECIAL, A_M_Y_Jetski_01) SET_PED_DIES_IN_WATER(piLineup[i_index], FALSE) SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(piLineup[i_index], TRUE) ENDIF ENDIF ELSE IF HAS_MODEL_LOADED(eCarModel) viLineup[i_index] = CREATE_VEHICLE(eCarModel, vLineupPos[i_index], fLineupFoc[i_index]) SET_VEHICLE_ON_GROUND_PROPERLY(viLineup[i_index]) SET_BOAT_LOW_LOD_ANCHOR_DISTANCE(viLineup[i_index],0) SET_BOAT_REMAINS_ANCHORED_WHILE_PLAYER_IS_DRIVER(viLineup[i_index],TRUE) SET_FORCE_LOW_LOD_ANCHOR_MODE(viLineup[i_index],TRUE) IF CAN_ANCHOR_BOAT_HERE(viLineup[i_index]) SET_BOAT_ANCHOR(viLineup[i_index],TRUE) ENDIF SET_VEHICLE_ENGINE_ON(viLineup[i_index], FALSE, TRUE) ENDIF ENDIF ENDREPEAT IF DOES_ENTITY_EXIST(viCar) AND DOES_ENTITY_EXIST(viLineup[0]) AND DOES_ENTITY_EXIST(viLineup[1]) AND DOES_ENTITY_EXIST(viLineup[2]) SET_MODEL_AS_NO_LONGER_NEEDED(eCarModel) ENDIF IF DOES_ENTITY_EXIST(piLineup[0]) AND DOES_ENTITY_EXIST(piLineup[1]) AND DOES_ENTITY_EXIST(piLineup[2]) SET_MODEL_AS_NO_LONGER_NEEDED(A_M_Y_Jetski_01) ENDIF SET_PED_CONFIG_FLAG(PLAYER_PED_ID(), PCF_ForceDirectEntry, TRUE) ENDIF ENDIF ENDIF ENDPROC // =========================================================================================================== // States // =========================================================================================================== /// PURPOSE: Basic launcher setup PROC RACELAUNCH_INIT() // Launcher init eState = STATE_INACTIVE bDisplayHelp = FALSE bLaunchRace = FALSE bPlayOnline = FALSE // Menu setup eRaceMenu = MENU_INIT iCurrentMenuItem = 0 iMenuInputTimer = 0 // Pre-load models for the race REQUEST_RIVAL_MODELS() // Turn off parking scenarios SET_SCENARIO_TYPE_ENABLED("WORLD_VEHICLE_PARK_PERPENDICULAR_NOSE_IN", FALSE) SET_SCENARIO_TYPE_ENABLED("WORLD_VEHICLE_PARK_PARALLEL", FALSE) IF raceData.eRaceTrack = STREET_RACE_02 sbiStreetRaceTwo = ADD_SCENARIO_BLOCKING_AREA_FROM_POSITION_AND_RADIUS(<<374.008331,279.591919,102.330574>>, 40.0) CLEAR_AREA_OF_VEHICLES(<<374.008331,279.591919,102.330574>>, 25.0) ENDIF IF raceData.eRaceType = RACETYPE_BIKE OR raceData.eRaceType = RACETYPE_CAR sbiRaceStart = ADD_SCENARIO_BLOCKING_AREA_FROM_POSITION_AND_RADIUS(vInCoords, 60.0) ENDIF // Create debug widgets #IF IS_DEBUG_BUILD SETUP_RACE_WIDGET(raceData) #ENDIF ENDPROC PROC HANDLE_HINT_CAM(INT iChallengeGuy) IF IS_PLAYER_PLAYING(PLAYER_ID()) AND NOT IS_PLAYER_IN_FIRST_PERSON_CAMERA() IF IS_PED_UNINJURED(piCrowd[iChallengeGuy]) IF bHintCamReady AND GET_ENTITY_SPEED(PLAYER_PED_ID()) < 20 SET_GAMEPLAY_ENTITY_HINT(piCrowd[iChallengeGuy], <<0,0,0>>) bHintCamReady = FALSE ENDIF ENDIF ENDIF ENDPROC PROC RACELAUNCH_HANDLE_GREETING(INT iChallengeGuy) IF NOT IS_ENTITY_DEAD( piCrowd[iChallengeGuy] ) AND NOT IS_ENTITY_DEAD( PLAYER_PED_ID() ) SWITCH eChallengerState CASE CGS_INIT IF VDIST2( GET_ENTITY_COORDS( piCrowd[iChallengeGuy] ), GET_ENTITY_COORDS( PLAYER_PED_ID() ) ) < 8*8 bSaidSecondSpeech = FALSE bSaidThirdSpeech = FALSE CPRINTLN( DEBUG_OR_RACES, "Moving from LGS_INIT to LGS_FACING_PLAYER" ) eChallengerState = CGS_FACING_PLAYER ENDIF BREAK CASE CGS_FACING_PLAYER SEQUENCE_INDEX siChallenge OPEN_SEQUENCE_TASK(siChallenge) TASK_LOOK_AT_ENTITY(NULL, PLAYER_PED_ID(), -1) TASK_TURN_PED_TO_FACE_ENTITY(NULL, PLAYER_PED_ID()) // TASK_TURN_PED_TO_FACE_ENTITY(NULL, PLAYER_PED_ID(), -1) // TASK_PLAY_ANIM(NULL, "random@street_race", "_streetracer_challenge") // TASK_PLAY_ANIM(NULL, "random@street_race", "_streetracer_wait_loop", NORMAL_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_DEFAULT | AF_LOOPING | AF_NOT_INTERRUPTABLE) CLOSE_SEQUENCE_TASK(siChallenge) TASK_PERFORM_SEQUENCE(piCrowd[iChallengeGuy], siChallenge) CLEAR_SEQUENCE_TASK(siChallenge) CPRINTLN( DEBUG_OR_RACES, "Moving from LGS_FACING_PLAYER to LGS_FACING_PLAYER_WAIT" ) eChallengerState = CGS_FACING_PLAYER_WAIT BREAK CASE CGS_FACING_PLAYER_WAIT IF GET_SCRIPT_TASK_STATUS(piCrowd[iChallengeGuy], SCRIPT_TASK_PERFORM_SEQUENCE) <> PERFORMING_TASK OR IS_PED_FACING_PED(piCrowd[iChallengeGuy], PLAYER_PED_ID(), 20.0) TASK_TURN_PED_TO_FACE_ENTITY(piCrowd[iChallengeGuy], PLAYER_PED_ID(), -1) IF NOT bSaidThirdSpeech PLAY_PED_AMBIENT_SPEECH_WITH_VOICE(piCrowd[iChallengeGuy], "PRERACE_CHAT", "A_M_Y_RACER_01_WHITE_MINI_01", SPEECH_PARAMS_FORCE_SHOUTED_CRITICAL) ELSE PLAY_PED_AMBIENT_SPEECH_WITH_VOICE(piCrowd[iChallengeGuy], "PRERACE_TAUNT", "A_M_Y_RACER_01_WHITE_MINI_01", SPEECH_PARAMS_FORCE_SHOUTED_CRITICAL) ENDIF //PLAY_SINGLE_LINE_FROM_CONVERSATION( dialoguePedsStruct, "SPR_OR", "OR_LAUNCH", "OR_LAUNCH_2", CONV_PRIORITY_LOW ) CPRINTLN( DEBUG_OR_RACES, "Moving from LGS_FACING_PLAYER_WAIT to LGS_GREETING_PLAYER" ) eChallengerState = CGS_CHALLENGING_PLAYER ENDIF BREAK CASE CGS_CHALLENGING_PLAYER IF NOT IS_AMBIENT_SPEECH_PLAYING(piCrowd[iChallengeGuy]) RESTART_TIMER_NOW( greetTimer ) TASK_PLAY_ANIM(piCrowd[iChallengeGuy], "random@street_race", "_streetracer_wait_loop", SLOW_BLEND_IN, SLOW_BLEND_OUT, -1, AF_DEFAULT | AF_LOOPING | AF_NOT_INTERRUPTABLE) eChallengerState = CGS_GREETING_PLAYER ENDIF BREAK CASE CGS_GREETING_PLAYER IF VDIST2( GET_ENTITY_COORDS( piCrowd[iChallengeGuy] ), GET_ENTITY_COORDS( PLAYER_PED_ID() ) ) > 15*15 eChallengerState = CGS_INIT ENDIF IF GET_TIMER_IN_SECONDS(greetTimer) >= 5.0 AND NOT bSaidSecondSpeech bSaidSecondSpeech = TRUE eChallengerState = CGS_FACING_PLAYER ELIF GET_TIMER_IN_SECONDS(greetTimer) >= 10.0 AND NOT bSaidThirdSpeech bSaidThirdSpeech = TRUE eChallengerState = CGS_FACING_PLAYER ENDIF BREAK CASE CGS_GREETING_PLAYER_WAIT BREAK ENDSWITCH ENDIF ENDPROC /// PURPOSE: /// Checks for the player pressing the context button to trigger the race PROC RACELAUNCH_WAIT_FOR_TRIGGER() // Is the player within range and is allowed to start race IF IS_PLAYER_IN_RACE_ACTIVATION_RANGE() IF CAN_PLAYER_LAUNCH_RACE() // Make the lookout guy challenge the player INT iChallengeGuy = 6 IF raceData.eRaceType = RACETYPE_BIKE iChallengeGuy = 4 ENDIF HANDLE_HINT_CAM(iChallengeGuy) IF IS_PED_UNINJURED(piCrowd[iChallengeGuy]) IF bStartPedSixTurning //IS_ENTITY_PLAYING_ANIM(piCrowd[6], sAnimDict, "_car_b_lookout") IF IS_ENTITY_PLAYING_ANIM(piCrowd[iChallengeGuy], sAnimDict, sAnimName[iChallengeGuy]) STOP_ANIM_TASK(piCrowd[iChallengeGuy], sAnimDict, sAnimName[iChallengeGuy]) /*ELSE STOP_SYNCHRONIZED_ENTITY_ANIM(piCrowd[iChallengeGuy], NORMAL_BLEND_OUT, TRUE)*/ ENDIF //CLEAR_PED_TASKS_IMMEDIATELY(piCrowd[iChallengeGuy]) // SEQUENCE_INDEX siChallenge // OPEN_SEQUENCE_TASK(siChallenge) // TASK_TURN_PED_TO_FACE_ENTITY(NULL, PLAYER_PED_ID()) // TASK_PLAY_ANIM(NULL, sAnimDict, "_streetracer_challenge") // TASK_PLAY_ANIM(NULL, sAnimDict, "_streetracer_wait_loop", NORMAL_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_DEFAULT | AF_LOOPING | AF_NOT_INTERRUPTABLE) // CLOSE_SEQUENCE_TASK(siChallenge) // TASK_PERFORM_SEQUENCE(piCrowd[iChallengeGuy], siChallenge) // CLEAR_SEQUENCE_TASK(siChallenge) // FORCE_PED_AI_AND_ANIMATION_UPDATE(piCrowd[iChallengeGuy], TRUE) // PLAY_PED_AMBIENT_SPEECH_WITH_VOICE(piCrowd[iChallengeGuy], "PRERACE_TAUNT", "A_M_Y_RACER_01_WHITE_MINI_01", SPEECH_PARAMS_FORCE_SHOUTED_CRITICAL) // CPRINTLN(DEBUG_MISSION, "Triggered Ped ", iChallengeGuy, " turning to the player") // bStartPedSixTurning = FALSE RACELAUNCH_HANDLE_GREETING(iChallengeGuy) ENDIF ENDIF /*IF bHintCamReady IF IS_PED_UNINJURED(piCrowd[6]) SET_GAMEPLAY_ENTITY_HINT(piCrowd[6], <<0,0,0>>) bHintCamReady = FALSE ENDIF ENDIF*/ // Pressed context button to enter SP/MP race menu SET_INPUT_EXCLUSIVE(PLAYER_CONTROL, INPUT_CONTEXT) //IF IS_CONTROL_JUST_PRESSED(PLAYER_CONTROL, INPUT_CONTEXT) IF IS_CONTROL_JUST_RELEASED(PLAYER_CONTROL, INPUT_CONTEXT) // Important, need to enable control in the cleanup only if the player cleans up from inside the menu bTriggeredMenu = TRUE CLEAR_HELP(TRUE) // Player is online /* IF IS_PLAYER_ONLINE() AND NETWORK_HAVE_ONLINE_PRIVILEGES() CPRINTLN(DEBUG_MISSION, "Race Launcher: Player is online...") PLAYER_INDEX pId = GET_PLAYER_INDEX() SET_EVERYONE_IGNORE_PLAYER(pId, TRUE) SET_PLAYER_CONTROL(pId, FALSE) SET_SCRIPTS_SAFE_FOR_CUTSCENE(TRUE) eState = STATE_RACE_MENU ELSE */ CPRINTLN(DEBUG_MISSION, "Race Launcher: Player is offline...") eState = STATE_LAUNCH_RACE //ENDIF ENDIF ELSE IF NOT bHintCamReady STOP_GAMEPLAY_HINT() bHintCamReady = TRUE ENDIF ENDIF ELSE MANAGE_RACE_HELP() IF NOT bHintCamReady STOP_GAMEPLAY_HINT() bHintCamReady = TRUE ENDIF ENDIF // remove anchor from seashark if this is a sea race /*IF bAnchored AND raceData.eRaceType = RACETYPE_SEA //CPRINTLN(DEBUG_MISSION, "seashark is anchored") IF IS_PED_IN_VEHICLE(PLAYER_PED_ID(), viCar) CPRINTLN(DEBUG_MISSION, "Player is in seashark") SET_BOAT_ANCHOR(viCar, FALSE) bAnchored = FALSE ENDIF ENDIF*/ ENDPROC /// PURPOSE: /// Creates the SP/MP menu PROC BUILD_RACE_MENU() CPRINTLN(DEBUG_MISSION, "Race Launcher: Building Race Menu...") CLEAR_MENU_DATA() SET_MENU_ITEM_LAYOUT(MENU_ITEM_TEXT) SET_MENU_ITEM_JUSTIFICATION(FONT_LEFT) // Set menu title IF raceData.eRaceType = RACETYPE_SEA SET_MENU_TITLE("SEA_MENU") ELSE SET_MENU_TITLE("STREET_MENU") ENDIF // Add menu options ADD_MENU_ITEM_TEXT(0, "RACES_OPT_SP") ADD_MENU_ITEM_TEXT(1, "RACES_OPT_MP") // Add help text ADD_MENU_HELP_KEY_INPUT( INPUT_FRONTEND_ACCEPT, "ITEM_SELECT") ADD_MENU_HELP_KEY_INPUT( INPUT_FRONTEND_CANCEL, "ITEM_EXIT") ADD_MENU_HELP_KEY_GROUP( INPUTGROUP_FRONTEND_GENERIC_UD, "ITEM_SCROLL") // Initialise first option SET_TOP_MENU_ITEM(0) SET_CURRENT_MENU_ITEM(0) iCurrentMenuItem = 0 ENDPROC /// PURPOSE: /// Detects player input and updates race menu FUNC BOOL PROCESS_RACE_MENU() // Grab the current analogue stick positions INT iLeftX, iLeftY, iRightX, iRightY GET_CONTROL_VALUE_OF_ANALOGUE_STICKS(iLeftX, iLeftY, iRightX, iRightY) // Only allow menu to use these inputs SET_INPUT_EXCLUSIVE(FRONTEND_CONTROL, INPUT_FRONTEND_ACCEPT) SET_INPUT_EXCLUSIVE(FRONTEND_CONTROL, INPUT_FRONTEND_CANCEL) SET_INPUT_EXCLUSIVE(FRONTEND_CONTROL, INPUT_FRONTEND_UP) SET_INPUT_EXCLUSIVE(FRONTEND_CONTROL, INPUT_FRONTEND_DOWN) // When using the analogue stick, wait for the timer to pass or the analogue stick // to be reset before we can use the stick again. IF iMenuInputTimer != 0 IF (TIMERA() > 800) OR ((iLeftY > -64) AND (iLeftY < 64) AND (iLeftX > -64) AND (iLeftX < 64)) iMenuInputTimer = 0 ELSE iLeftX = 0 iLeftY = 0 ENDIF ENDIF BOOL bUp = ((iLeftY < -64) OR IS_CONTROL_JUST_PRESSED(FRONTEND_CONTROL, INPUT_FRONTEND_UP)) BOOL bDown = ((iLeftY > 64) OR IS_CONTROL_JUST_PRESSED(FRONTEND_CONTROL, INPUT_FRONTEND_DOWN)) BOOL bAccept = (IS_CONTROL_JUST_PRESSED(FRONTEND_CONTROL, INPUT_FRONTEND_ACCEPT)) BOOL bCancel = (IS_CONTROL_JUST_PRESSED(FRONTEND_CONTROL, INPUT_FRONTEND_CANCEL)) BOOL bUsingLeftStick = ((iLeftY < -64) OR (iLeftY > 64)) // Handle user input... IF bAccept // Check for SP/MP IF iCurrentMenuItem = 1 bPlayOnline = TRUE ELSE bPlayOnline = FALSE ENDIF // Launch race bLaunchRace = TRUE RETURN TRUE ELIF bCancel // Return to gameplay bTriggeredMenu = FALSE bLaunchRace = FALSE RETURN TRUE ELSE // Update menu position IF bDown // Menu down IF (iCurrentMenuItem = 0) iCurrentMenuItem = 1 ELIF iCurrentMenuItem = 0 ENDIF ELIF bUp // Menu up IF (iCurrentMenuItem = 1) iCurrentMenuItem = 0 ELIF iCurrentMenuItem = 1 ENDIF ENDIF // Current menu item needs to be updated IF bDown OR bUp // Require the analogue stick to be reset IF bUsingLeftStick SETTIMERA(0) iMenuInputTimer = 1 ENDIF // Set new menu item SET_CURRENT_MENU_ITEM(iCurrentMenuItem) ENDIF ENDIF DRAW_MENU() RETURN FALSE ENDFUNC /// PURPOSE: /// Handles the player selecting whether to trigger the race in SP or multiplayer PROC RACELAUNCH_UPDATE_RACE_MENU() SWITCH eRaceMenu CASE MENU_INIT IF LOAD_MENU_ASSETS() CLEAR_HELP(TRUE) // Setup race menu BUILD_RACE_MENU() // Stop the player being able to change radio station SET_USER_RADIO_CONTROL_ENABLED(FALSE) bRadioSwitchDisabled = TRUE // Init vars bLaunchRace = FALSE bPlayOnline = FALSE eRaceMenu = MENU_UPDATE ENDIF BREAK CASE MENU_UPDATE IF PROCESS_RACE_MENU() eRaceMenu = MENU_CLEANUP ENDIF BREAK CASE MENU_CLEANUP // Cleanup race menu PLAYER_INDEX pID pId = GET_PLAYER_INDEX() SET_EVERYONE_IGNORE_PLAYER(pId, FALSE) SET_PLAYER_CONTROL(pId, TRUE) SET_SCRIPTS_SAFE_FOR_CUTSCENE(FALSE) CLEANUP_MENU_ASSETS() eRaceMenu = MENU_INIT // Launch race or return to gameplay IF bLaunchRace eState = STATE_LAUNCH_RACE ELSE // Allow the player to change radio station SET_USER_RADIO_CONTROL_ENABLED(TRUE) eState = STATE_WAIT_FOR_TRIGGER ENDIF BREAK ENDSWITCH ENDPROC /// PURPOSE: /// Loads mission script for single player or updates globals for MP PROC RACELAUNCH_LAUNCH_RACE() IF NOT bPlayOnline DO_RACE_LAUNCH_SP() ELSE DO_RACE_LAUNCH_MP() ENDIF ENDPROC /// Main script thread SCRIPT(coords_struct in_coords) // Launcher priority for streaming requests SET_THIS_IS_A_TRIGGER_SCRIPT(TRUE) // Get world point info for street race vInCoords = in_coords.vec_coord[0] CPRINTLN(DEBUG_MISSION, "Race Launcher: Activated at location ", vInCoords) // 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|FORCE_CLEANUP_FLAG_REPEAT_PLAY)) CPRINTLN(DEBUG_MISSION, "Race Launcher: FORCE_CLEANUP [TERMINATING]") SCRIPT_CLEANUP(FALSE) ENDIF // Detect whether we have launched from debug #IF IS_DEBUG_BUILD // Wait for game flow to update IF g_flowUnsaved.bUpdatingGameflow WAIT(0) ENDIF // Notify that we have launched from the debug menu IF g_RaceLaunchedFromDebug = TRUE CPRINTLN(DEBUG_MISSION, "Race Launcher: Triggered from debug menu") ENDIF #ENDIF // Establish race info from world point GET_RACE_LOCATION() // Have races been unlocked? SWITCH raceData.eRaceType CASE RACETYPE_BIKE CASE RACETYPE_CAR // Have races been unlocked in flow? IF NOT GET_MISSION_FLOW_BITSET_BIT_STATE(FLOWBITSET_MINIGAME_ACTIVE, ENUM_TO_INT(MINIGAME_STREET_RACES)) CPRINTLN(DEBUG_MISSION, "Race Launcher: Street Races aren't unlocked in flow yet. Cleaning up.") SCRIPT_CLEANUP(FALSE) ELSE CPRINTLN(DEBUG_MISSION, "Race Launcher: Street Races unlocked in flow. Allowing to proceed.") ENDIF // Has this specific race been unlocked yet? IF NOT IS_RACE_UNLOCKED(raceData.eRaceTrack) CPRINTLN(DEBUG_MISSION, "Race Launcher: This race hasn't been unlocked yet. Cleaning up.") SCRIPT_CLEANUP(FALSE) ENDIF BREAK CASE RACETYPE_SEA // Have races been unlocked in flow? IF NOT GET_MISSION_FLOW_BITSET_BIT_STATE(FLOWBITSET_MINIGAME_ACTIVE, ENUM_TO_INT(MINIGAME_SEA_RACES)) CPRINTLN(DEBUG_MISSION, "Race Launcher: Sea Races aren't unlocked in flow yet. Cleaning up.") SCRIPT_CLEANUP(FALSE) ELSE CPRINTLN(DEBUG_MISSION, "Race Launcher: Sea Races unlocked in flow. Allowing to proceed.") ENDIF BREAK CASE RACETYPE_UNDEFINED // Have races been unlocked in flow? CPRINTLN(DEBUG_MISSION, "Race Launcher: Undefined race type. Cleaning up.") SCRIPT_CLEANUP(FALSE) BREAK ENDSWITCH // Initial setup. CPRINTLN(DEBUG_MISSION, "Race Launcher: Initialising...") RACELAUNCH_INIT() // Check conditions for racing not being allowed to launch and exit early if found IF NOT IS_RACE_ALLOWED_TO_LAUNCH() CPRINTLN(DEBUG_MISSION, "Race Launcher: Races not allowed to launch") SCRIPT_CLEANUP(FALSE) ELSE CPRINTLN(DEBUG_MISSION, "Race Launcher: Races allowed to launch") ENDIF // Create initial scene CPRINTLN(DEBUG_MISSION, "Race Launcher: Creating initial scene...") SETUP_INITIAL_SCENE() // Main loop WHILE (TRUE) UPDATE_LOAD_QUEUE_MEDIUM(sLoadQueue) // Check conditions for racing not being allowed to launch, exit if not IF IS_RACE_ALLOWED_TO_LAUNCH() // Check debug widgets #IF IS_DEBUG_BUILD MAINTAIN_RACE_WIDGET(raceData) #ENDIF // Are we still within range of this launcher? IF IS_WORLD_POINT_WITHIN_BRAIN_ACTIVATION_RANGE() //HANDLE_HINT_CAM() SWITCH eState CASE STATE_INACTIVE eState = STATE_WAIT_FOR_TRIGGER BREAK // Has player entered race corona? CASE STATE_WAIT_FOR_TRIGGER CREATE_INITIAL_SCENE() RACELAUNCH_WAIT_FOR_TRIGGER() BREAK // Player is selecting CASE STATE_RACE_MENU RACELAUNCH_UPDATE_RACE_MENU() BREAK // Player is selecting CASE STATE_LAUNCH_RACE RACELAUNCH_LAUNCH_RACE() BREAK ENDSWITCH ELSE CPRINTLN(DEBUG_MISSION, "Race Launcher: Player out of range.") SCRIPT_CLEANUP(FALSE) ENDIF ELSE CPRINTLN(DEBUG_MISSION, "Race Launcher: Races not allowed to launch") SCRIPT_CLEANUP(FALSE) ENDIF WAIT(0) ENDWHILE ENDSCRIPT