2516 lines
81 KiB
Python
Executable File
2516 lines
81 KiB
Python
Executable File
// 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
|