Files
gtav-src/script/dev_ng/singleplayer/include/private/Ambient/script_RACES.sch
T
2025-09-29 00:52:08 +02:00

1589 lines
57 KiB
Scheme
Executable File

USING "commands_audio.sch"
USING "commands_camera.sch"
USING "commands_graphics.sch"
USING "commands_hud.sch"
USING "commands_misc.sch"
USING "commands_script.sch"
USING "commands_task.sch"
USING "commands_fire.sch"
USING "model_enums.sch"
USING "rage_builtins.sch"
USING "script_player.sch"
USING "shared_hud_displays.sch"
USING "ambience_run_checks.sch"
// Race ENUMs
ENUM RACE_COURSE
RACE_COURSE_NONE,
RACE_COURSE_MT_BIKE1,
RACE_COURSE_RC_FANATIC2,
RACE_COURSE_RC_FANATIC2ALT,
RACE_COURSE_RC_FANATIC2ALTB,
RACE_COURSE_RC_EXTREME1,
RACE_COURSE_END
ENDENUM
ENUM RACE_VEHICLE_CLASS
RACE_VEHICLE_CLASS_NONE,
RACE_VEHICLE_CLASS_RC,
RACE_VEHICLE_CLASS_RC_CHECKS,
RACE_VEHICLE_CLASS_RALLY,
RACE_VEHICLE_CLASS_MOTORBIKES,
RACE_VEHICLE_CLASS_MUSCLE_CARS,
RACE_VEHICLE_CLASS_SUPER_CARS,
RACE_VEHICLE_CLASS_CURRENT,
RACE_VEHICLE_CLASS_MOUNTAIN_BIKE,
RACE_VEHICLE_CLASS_END
ENDENUM
ENUM RACER_STATUS
RACER_STATUS_DEAD,
RACER_STATUS_WINNING,
RACER_STATUS_LOSING,
RACER_STATUS_WON,
RACER_STATUS_LOST,
RACER_STATUS_FINISHED,
RACER_STATUS_END
ENDENUM
ENUM RACE_GRID_FLYBY_STYLE
RG_FLYBY_NONE,
RG_FLYBY_LEFT_FRONT_TO_BACK,
RG_FLYBY_RIGHT_FRONT_TO_BACK,
RG_FLYBY_CENTRE_FRONT_TO_BACK,
RG_FLYBY_LEFT_BACK_TO_FRONT,
RG_FLYBY_RIGHT_BACK_TO_FRONT,
RG_FLYBY_CENTRE_BACK_TO_FRONT,
RG_FLYBY_DRAG_BACK_TO_FRONT,
RG_FLYBY_END
ENDENUM
STRUCT RACE_INFO_STRUCT
// Position & heading from which the race is generated
VECTOR sourcePos
FLOAT sourceHeading
// Checkpoint positions
VECTOR checkPos[40]
//AI straight line Distance
FLOAT straightLineDist
// Number of checkpoints
INT totalChecks
// Number of laps
INT totalLaps
// Number of racers
INT totalRacers
// Player's start position
// VECTOR playerPos
// Buddy's start position
// VECTOR buddyPos
// FLOAT buddyHeading
// Taxi Drop off position
// VECTOR taxiPos
// Chosen course
RACE_COURSE chosenCourse
// String to print in console
// TEXT_LABEL_31 raceName
// Vehicle CLass
RACE_VEHICLE_CLASS raceCLass
CAMERA_INDEX raceSourceCam
CAMERA_INDEX raceDestCam
ENDSTRUCT
//Checkpoint size
FLOAT checkSize = 20.0
INT prevAlpha
CONST_INT TOTAL_NUMBER_OF_RACERS 8
STRUCT RACER_INFO_STRUCT
PED_INDEX racer
// MODEL_NAMES pedModel
VEHICLE_INDEX raceVehicle
// MODEL_NAMES vehicleModel
// BLIP_INDEX racerBlip
// BLIP_INDEX raceVehicleBlip
BLIP_INDEX checkBlip
BLIP_INDEX nextCheckBlip
CHECKPOINT_INDEX checkPoint
CHECKPOINT_INDEX PrevCheckPoint
VECTOR racerPos
// FLOAT racerHeading
INT currentCheck
INT nextCheck
INT currentLap
FLOAT currentSpeed
FLOAT distanceToNextCheck
RACER_STATUS racerStatus
ENDSTRUCT
FUNC BOOL IS_A_RACE_MISSION_SCRIPT_RUNNING()
IF GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(HASH("sp_races")) = 1
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
FUNC BOOL IS_PLAYER_ABLE_TO_DRIVE_CURRENT_VEHICLE()
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
IF IS_VEHICLE_DRIVEABLE(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()))
AND NOT IS_ENTITY_ON_FIRE(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()))
IF NOT IS_VEHICLE_MODEL(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()), FORKLIFT)
IF GET_PED_IN_VEHICLE_SEAT(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID())) = PLAYER_PED_ID()
RETURN TRUE
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
FUNC MODEL_NAMES GENERATE_RANDOM_MODEL_FROM_RACE_CLASS(RACE_VEHICLE_CLASS vehicleClass)
MODEL_NAMES vehicleModels[24]
INT TOTAL_MODELS_IN_CLASS = 0
SWITCH vehicleClass
CASE RACE_VEHICLE_CLASS_MOTORBIKES
vehicleModels[0] = SANCHEZ
vehicleModels[1] = SANCHEZ
TOTAL_MODELS_IN_CLASS = 2
BREAK
CASE RACE_VEHICLE_CLASS_MUSCLE_CARS
vehicleModels[0] = SULTAN // Sultan isn't a muscle car
TOTAL_MODELS_IN_CLASS = 7
BREAK
CASE RACE_VEHICLE_CLASS_RALLY
vehicleModels[0] = TAILGATER
TOTAL_MODELS_IN_CLASS = 1
BREAK
CASE RACE_VEHICLE_CLASS_SUPER_CARS
vehicleModels[0] = INFERNUS
TOTAL_MODELS_IN_CLASS = 1
BREAK
CASE RACE_VEHICLE_CLASS_RC
//vehicleModels[0] = RCBANDITO
///vehicleModels[1] = RCBANDITO
TOTAL_MODELS_IN_CLASS = 2
BREAK
ENDSWITCH
RETURN vehicleModels[GET_RANDOM_INT_IN_RANGE(0, TOTAL_MODELS_IN_CLASS)]
ENDFUNC
PROC ASSIGN_RACE_CHECKPOINT(RACE_INFO_STRUCT &raceInfo, VECTOR checkPosition)
raceInfo.checkPos[raceInfo.totalChecks] = checkPosition
raceInfo.totalChecks++
ENDPROC
PROC GENERATE_RACE_INFO(RACE_INFO_STRUCT &raceInfo)
raceInfo.totalChecks = 0
IF raceInfo.chosenCourse = RACE_COURSE_NONE
SCRIPT_ASSERT("GENERATE_RACE_INFO. raceInfo.chosenCourse = RACE_COURSE_NONE. Choose a course prior to generating info.")
ENDIF
SWITCH raceInfo.chosenCourse
CASE RACE_COURSE_MT_BIKE1
raceInfo.raceCLass = RACE_VEHICLE_CLASS_MOUNTAIN_BIKE
// raceInfo.raceName = "RR_RC_BS"
raceInfo.sourcePos = << -331.1481, 4753.7290, 227.6643 >>
raceInfo.sourceHeading = 229.0
raceInfo.totalRacers = 2
ASSIGN_RACE_CHECKPOINT(raceInfo, <<-329.1481, 4749.7290, 228.6643>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<-291.5515, 4691.3052, 235.7776 >> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<-310.1067, 4684.8662, 246.5917 >> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<-415.3808, 4672.3550, 253.3204 >> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<-430.9800, 4707.3994, 253.2198 >> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<-447.7660, 4737.7837, 244.1033 >> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<-502.0252, 4732.6729, 239.5285 >> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<-579.2366, 4750.3970, 211.4045>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<-622.6068, 4716.0449, 225.8445 >> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<-672.1638, 4728.6938, 238.2206 >> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<-736.2177, 4783.1631, 226.5020 >> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<-795.5958, 4867.9976, 255.8227>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<-855.1999, 4865.0620, 289.7517 >> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<-876.2197, 4796.1655, 298.3487 >> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<-944.4310, 4773.4795, 284.3422 >> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<-1026.6361, 4834.1626, 255.4192>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<-1070.0287, 4825.0630, 231.3936 >> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<-1089.9250, 4804.0610, 216.7211 >> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<-1279.2612, 4841.3320, 151.8451 >> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<-1375.7675, 4798.2275, 126.2156>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<-1467.2419, 4803.9292, 81.1326 >> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<-1485.8629, 4750.4497, 58.8107 >> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<-1541.9647, 4738.9575, 50.8111 >> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<-1581.1320, 4839.4600, 52.7062 >> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<-1494.7415, 4971.1670, 46.7483 >> )
raceInfo.totalLaps = 0
raceInfo.straightLineDist = 15
// raceInfo.taxiPos = << -329.4604, 4752.3691, 228.0300 >>
// raceInfo.buddyPos = << -329.4604, 4752.3691, 228.0300 >>
// raceInfo.buddyHeading = 275
BREAK
CASE RACE_COURSE_RC_FANATIC2
raceInfo.raceCLass = RACE_VEHICLE_CLASS_MOUNTAIN_BIKE
// raceInfo.raceName = "RC_FAN2"
raceInfo.sourcePos = << 376.5668, 1058.3768, 236.1919 >>
raceInfo.sourceHeading = 2.9613
raceInfo.totalRacers = 1
ASSIGN_RACE_CHECKPOINT(raceInfo, <<374.2899, 1074.4827, 235.7123>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<362.0448, 1110.6335, 235.1055>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<319.5104, 1161.1849, 235.4029>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<300.0755, 1237.2719, 234.0581>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<269.5442, 1263.0739, 232.5312>> )
//ASSIGN_RACE_CHECKPOINT(raceInfo, <<258.5526, 1218.9199, 228.3669>> )
// Alternate route starts here
ASSIGN_RACE_CHECKPOINT(raceInfo, <<240.08, 1180.87, 224.46>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<214.48, 1216.27, 224.59>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<183.42, 1205.29, 224.59>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<188.68, 1187.18, 224.59>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<198.22, 1180.16, 226.01>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<203.38, 1121.57, 224.59>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<260.94, 1135.36, 220.60>> )
//ASSIGN_RACE_CHECKPOINT(raceInfo, <<271.5604, 1140.6415, 220.7155>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<290.6088, 1094.6976, 215.5821>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<309.9068, 1019.8271, 209.4761>> )
raceInfo.totalLaps = 0
raceInfo.straightLineDist = 15
// raceInfo.taxiPos = << 376.5668, 1058.3768, 236.1919 >>
// raceInfo.buddyPos = << 376.5668, 1058.3768, 236.1919 >>
// raceInfo.buddyHeading = 0
BREAK
CASE RACE_COURSE_RC_FANATIC2ALT
raceInfo.raceCLass = RACE_VEHICLE_CLASS_MOUNTAIN_BIKE
// raceInfo.raceName = "RC_FAN2A"
raceInfo.sourcePos = << 857.7981, 1278.2418, 358.1998 >>
raceInfo.sourceHeading = 152.4354
raceInfo.totalRacers = 1
// Start of long race
ASSIGN_RACE_CHECKPOINT(raceInfo, <<827.49, 1278.53, 359.37>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<846.14, 1276.50, 358.83>> )
//ASSIGN_RACE_CHECKPOINT(raceInfo, <<852.6194, 1265.3116, 357.7758>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<835.8340, 1244.0568, 351.7520>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<799.0862, 1223.3503, 340.1938>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<741.2345, 1201.0686, 325.2563>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<676.7847, 1219.0261, 322.9875>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<624.7384, 1217.0782, 315.5874>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<566.5258, 1191.4326, 301.3754>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<519.7023, 1226.5149, 290.0847>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<469.1648, 1233.8317, 277.0887>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<439.77, 1292.51, 270.32>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<407.94, 1253.81, 258.00>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<409.55, 1205.16, 249.29>> ) //12
ASSIGN_RACE_CHECKPOINT(raceInfo, <<422.5302, 1114.8162, 233.0>> ) //Foot of hill - 13
ASSIGN_RACE_CHECKPOINT(raceInfo, <<436.9201, 1045.1660, 235.1103>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<406.2167, 1031.1447, 236.0167>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<380.8393, 1048.0707, 236.4371>> )
// Start of short race
ASSIGN_RACE_CHECKPOINT(raceInfo, <<374.2899, 1074.4827, 235.7123>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<362.0448, 1110.6335, 235.1055>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<319.5104, 1161.1849, 235.4029>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<300.0755, 1237.2719, 234.0581>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<267.55, 1261.09, 232.0>> ) // coming off of forest path
ASSIGN_RACE_CHECKPOINT(raceInfo, <<252.79, 1238.97, 230.0>> ) // into turn
//ASSIGN_RACE_CHECKPOINT(raceInfo, <<248.64, 1214.70, 228.14>> ) // first proper cpt on 2nd road - 22
ASSIGN_RACE_CHECKPOINT(raceInfo, <<268.05, 1137.00, 220.53>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<307.27, 1050.44, 210.96>> )
//ASSIGN_RACE_CHECKPOINT(raceInfo, <<306.41, 1012.17, 209.52>> ) // At junction
ASSIGN_RACE_CHECKPOINT(raceInfo, <<298.58, 989.24, 209.66>> )
//ASSIGN_RACE_CHECKPOINT(raceInfo, <<284.01, 966.09, 210.14>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<279.85, 946.37, 209.82>> )
raceInfo.totalLaps = 0
raceInfo.straightLineDist = 15
// raceInfo.taxiPos = << 822.8073, 1278.0714, 359.4283 >>
// raceInfo.buddyPos = << 857.7981, 1278.2418, 358.1998 >>
// raceInfo.buddyHeading = 0
BREAK
CASE RACE_COURSE_RC_FANATIC2ALTB
raceInfo.raceCLass = RACE_VEHICLE_CLASS_MOUNTAIN_BIKE
// raceInfo.raceName = "RC_FAN2B"
raceInfo.sourcePos = << 857.7981, 1278.2418, 358.1998 >>
raceInfo.sourceHeading = 152.4354
raceInfo.totalRacers = 1
// Start of long race
ASSIGN_RACE_CHECKPOINT(raceInfo, <<827.49, 1278.53, 359.37>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<850.14, 1280.21, 358.57>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<852.6194, 1265.3116, 357.7758>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<835.8340, 1244.0568, 351.7520>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<799.0862, 1223.3503, 340.1938>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<741.2345, 1201.0686, 325.2563>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<676.7847, 1219.0261, 322.9875>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<624.7384, 1217.0782, 315.5874>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<566.5258, 1191.4326, 301.3754>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<519.7023, 1226.5149, 290.0847>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<469.1648, 1233.8317, 277.0887>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<445.0087, 1295.1957, 271.5344>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<411.0428, 1234.2543, 254.5870>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<438.20, 1112.65, 231.80>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<500.16, 1096.98, 229.77>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<532.43, 1064.83, 223.78>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<533.50, 1027.03, 216.61>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<491.57, 968.53, 204.70>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<462.99, 893.08, 197.09>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<416.58, 894.30, 198.00>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<399.39, 933.08, 201.46>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<377.99, 993.49, 207.88>> )
ASSIGN_RACE_CHECKPOINT(raceInfo, <<328.88, 1007.05, 209.52>> )
// ASSIGN_RACE_CHECKPOINT(raceInfo, <<422.5302, 1114.8162, 233.2663>> )
// ASSIGN_RACE_CHECKPOINT(raceInfo, <<436.9201, 1045.1660, 235.1103>> )
// ASSIGN_RACE_CHECKPOINT(raceInfo, <<406.2167, 1031.1447, 236.0167>> )
// ASSIGN_RACE_CHECKPOINT(raceInfo, <<380.8393, 1048.0707, 236.4371>> )
// // Start of short race
// ASSIGN_RACE_CHECKPOINT(raceInfo, <<374.2899, 1074.4827, 235.7123>> )
// ASSIGN_RACE_CHECKPOINT(raceInfo, <<362.0448, 1110.6335, 235.1055>> )
// ASSIGN_RACE_CHECKPOINT(raceInfo, <<319.5104, 1161.1849, 235.4029>> )
// ASSIGN_RACE_CHECKPOINT(raceInfo, <<300.0755, 1237.2719, 234.0581>> )
// ASSIGN_RACE_CHECKPOINT(raceInfo, <<269.5442, 1263.0739, 232.5312>> )
// ASSIGN_RACE_CHECKPOINT(raceInfo, <<258.5526, 1218.9199, 228.3669>> )
// ASSIGN_RACE_CHECKPOINT(raceInfo, <<271.5604, 1140.6415, 220.7155>> )
// ASSIGN_RACE_CHECKPOINT(raceInfo, <<290.6088, 1094.6976, 215.5821>> )
// ASSIGN_RACE_CHECKPOINT(raceInfo, <<309.9068, 1019.8271, 209.4761>> )
raceInfo.totalLaps = 0
// raceInfo.taxiPos = << 822.8073, 1278.0714, 359.4283 >>
raceInfo.straightLineDist = 15
//raceInfo.buddyPos = << 857.7981, 1278.2418, 358.1998 >>
//raceInfo.buddyHeading = 0
BREAK
CASE RACE_COURSE_RC_EXTREME1
raceInfo.raceCLass = RACE_VEHICLE_CLASS_MOUNTAIN_BIKE
// raceInfo.raceName = "RC_EXT1"
raceInfo.sourcePos = << 500.6770, 5598.2622, 794.8943 >>
raceInfo.sourceHeading = 156.5849
raceInfo.totalRacers = 2
ASSIGN_RACE_CHECKPOINT(raceInfo, <<481.4428, 5521.1191, 771.8>>)
ASSIGN_RACE_CHECKPOINT(raceInfo, <<435.2, 5507.4, 743.7>>)
ASSIGN_RACE_CHECKPOINT(raceInfo, <<380.6, 5498.7, 713.3>>)
ASSIGN_RACE_CHECKPOINT(raceInfo, <<349.6, 5447.3, 675.5>>)
ASSIGN_RACE_CHECKPOINT(raceInfo, <<312.5256, 5385.5020, 642.6>>)
ASSIGN_RACE_CHECKPOINT(raceInfo, <<276.9, 5347.8, 630.6>>)
ASSIGN_RACE_CHECKPOINT(raceInfo, <<226.4586, 5295.5039, 618.1>>)
ASSIGN_RACE_CHECKPOINT(raceInfo, <<231.5871, 5249.3643, 600.8>>)
ASSIGN_RACE_CHECKPOINT(raceInfo, <<201.4, 5247.7, 590.0>>)
ASSIGN_RACE_CHECKPOINT(raceInfo, <<172.3, 5203.5, 570.0>>)
ASSIGN_RACE_CHECKPOINT(raceInfo, <<145.6254, 5185.0322, 551.3>>)
ASSIGN_RACE_CHECKPOINT(raceInfo, <<130.1801, 5224.4473, 541.8>>)
ASSIGN_RACE_CHECKPOINT(raceInfo, <<113.3, 5174.3, 526.5>>)
ASSIGN_RACE_CHECKPOINT(raceInfo, <<113.9507, 5107.9199, 509.5>>)
ASSIGN_RACE_CHECKPOINT(raceInfo, <<88.1, 5073.2, 491.5>>)
ASSIGN_RACE_CHECKPOINT(raceInfo, <<89.5557, 5017.5713, 460.8>>)
ASSIGN_RACE_CHECKPOINT(raceInfo, <<30.4282, 5050.1685, 454.2>>)
ASSIGN_RACE_CHECKPOINT(raceInfo, <<7.4203, 5010.6812, 443.9>>)
ASSIGN_RACE_CHECKPOINT(raceInfo, <<-46.7, 5005.9, 408.6>>)
ASSIGN_RACE_CHECKPOINT(raceInfo, <<-65.7, 4955.6, 392.4>>)
ASSIGN_RACE_CHECKPOINT(raceInfo, <<-131.1, 4919.0, 353.3>>)
ASSIGN_RACE_CHECKPOINT(raceInfo, <<-184.3982, 4900.4634, 329.1>>)
ASSIGN_RACE_CHECKPOINT(raceInfo, <<-271.4, 4916.4, 290.0>>)
ASSIGN_RACE_CHECKPOINT(raceInfo, <<-304.0, 4950.3, 261.0>>)
ASSIGN_RACE_CHECKPOINT(raceInfo, <<-335.4192, 4997.4253, 220.3>>)
ASSIGN_RACE_CHECKPOINT(raceInfo, <<-366.6329, 4919.2505, 196.0>>) // iCurrentBikeRaceConversation (in Extreme1.sc) gets set to 2 here
ASSIGN_RACE_CHECKPOINT(raceInfo, <<-460.1884, 4883.4795, 186.7>>)
ASSIGN_RACE_CHECKPOINT(raceInfo, <<-544.8522, 4874.6475, 167.6>>)
ASSIGN_RACE_CHECKPOINT(raceInfo, <<-573.7510, 4893.3311, 168.5>>)
ASSIGN_RACE_CHECKPOINT(raceInfo, <<-590.3, 4962.9, 156.5>>)
ASSIGN_RACE_CHECKPOINT(raceInfo, <<-625.4877, 5013.7354, 143.4>>)
ASSIGN_RACE_CHECKPOINT(raceInfo, <<-634.5757, 5056.1675, 142.8>>)
ASSIGN_RACE_CHECKPOINT(raceInfo, <<-706.3599, 5069.9321, 140.4>>)
ASSIGN_RACE_CHECKPOINT(raceInfo, <<-762.2672, 5126.6323, 135.7>>)
ASSIGN_RACE_CHECKPOINT(raceInfo, <<-764.7, 5192.5, 111.5>>)
ASSIGN_RACE_CHECKPOINT(raceInfo, <<-789.0667, 5263.0425, 88.1>>)
ASSIGN_RACE_CHECKPOINT(raceInfo, <<-849.2, 5259.7, 86>>)
raceInfo.totalLaps = 0
raceInfo.straightLineDist = 15
// raceInfo.taxiPos = << -329.4604, 4752.3691, 228.0300 >>
// raceInfo.buddyPos = << -329.4604, 4752.3691, 228.0300 >>
// raceInfo.buddyHeading = 275
BREAK
ENDSWITCH
ENDPROC
FUNC VECTOR GET_RACER_GRID_POSITION(RACER_INFO_STRUCT &racerInfo, RACE_INFO_STRUCT raceInfo, INT &gridNumber)
INT gridRow
VECTOR sideOffset, behindOffset
FLOAT vehLength = 3.0
FLOAT vehWidth = 1.0
FLOAT scaleSide, scaleBehind
racerInfo.racerPos.z = 0.0
// raceInfo.sourcePos
// Generate offset multipliers from race source heading
sideOffset.x = -1.0 * SIN(raceInfo.sourceHeading+90.0)
sideOffset.y = COS(raceInfo.sourceHeading+90.0)
behindOffset.x = -1.0 * SIN(raceInfo.sourceHeading+180.0)
behindOffset.y = COS(raceInfo.sourceHeading+180.0)
// Get X Offset
gridRow = gridNumber / 2
IF gridRow * 2 = gridNumber
scaleSide = (vehWidth+GET_RANDOM_FLOAT_IN_RANGE(0.0, 0.7))
ELSE
scaleSide = (-vehWidth+GET_RANDOM_FLOAT_IN_RANGE(0.0, 0.7))
ENDIF
IF gridNumber = TOTAL_NUMBER_OF_RACERS-1
scaleSide = (-vehWidth+0.5)
ENDIF
// Get Y offset
scaleBehind = (vehLength+GET_RANDOM_FLOAT_IN_RANGE(-1.0, 1.0))
scaleBehind += TO_FLOAT(gridRow) * (2 * vehLength)
// Get world coordinates for offsets
racerInfo.racerPos.x = (scaleSide * sideOffset.x) + (scaleBehind * behindOffset.x)
racerInfo.racerPos.y = (scaleSide * sideOffset.y) + (scaleBehind * behindOffset.y)
racerInfo.racerPos += raceInfo.sourcePos
RETURN racerInfo.racerPos
ENDFUNC
FUNC BOOL IS_PED_IN_ACCEPTABLE_RACE_VEHICLE(RACER_INFO_STRUCT &playerRacer, RACE_VEHICLE_CLASS vehicleClass)
IF NOT IS_ENTITY_DEAD(playerRacer.raceVehicle)
IF IS_PED_IN_VEHICLE(playerRacer.racer, playerRacer.raceVehicle)
IF vehicleClass = RACE_VEHICLE_CLASS_MOTORBIKES
IF NOT IS_PED_ON_ANY_BIKE(playerRacer.racer)
RETURN FALSE
ELSE
RETURN TRUE
ENDIF
ELSE
IF IS_VEHICLE_MODEL(playerRacer.raceVehicle, FBI)
OR IS_VEHICLE_MODEL(playerRacer.raceVehicle, FIRETRUK)
OR IS_VEHICLE_MODEL(playerRacer.raceVehicle, POLICE)
RETURN FALSE
ELSE
RETURN TRUE
ENDIF
ENDIF
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
PROC START_RACE_GRID_FLYBY(RACE_GRID_FLYBY_STYLE &flybyStyle, RACER_INFO_STRUCT &racerInfo[], RACE_INFO_STRUCT &raceInfo)
VECTOR sourceCamPos
VECTOR sourceCamTarget
VECTOR destCamPos
VECTOR destCamTarget
VECTOR sourceMod
INT postion11 = TOTAL_NUMBER_OF_RACERS-1
INT postion10 = TOTAL_NUMBER_OF_RACERS-3
INT position8 = TOTAL_NUMBER_OF_RACERS-4
INT position9 = TOTAL_NUMBER_OF_RACERS-3
INT temp2 = 2
RACER_INFO_STRUCT tempRacerInfo
IF flybyStyle <> RG_FLYBY_NONE
SWITCH flybyStyle
CASE RG_FLYBY_LEFT_FRONT_TO_BACK
sourceCamPos = racerInfo[1].racerPos
sourceCamTarget = racerInfo[2].racerPos
destCamPos = racerInfo[postion11].racerPos
destCamTarget = racerInfo[position8].racerPos
sourceMod = sourceCamPos - sourceCamTarget
sourceCamPos += sourceMod
destCamPos += sourceMod
sourceMod = racerInfo[position9].racerPos - racerInfo[postion11].racerPos
destCamPos += sourceMod
sourceCamPos.z += 1.0
destCamPos.z += 2.0
BREAK
CASE RG_FLYBY_RIGHT_FRONT_TO_BACK
sourceCamPos = racerInfo[2].racerPos
sourceCamTarget = racerInfo[1].racerPos
destCamPos = racerInfo[position8].racerPos
destCamTarget = racerInfo[postion11].racerPos
sourceMod = sourceCamPos - sourceCamTarget
sourceCamPos += sourceMod
destCamPos += sourceMod
sourceMod = racerInfo[position8].racerPos - racerInfo[postion10].racerPos
destCamPos += sourceMod
sourceCamPos.z += 3.0
destCamPos.z += 4.0
BREAK
CASE RG_FLYBY_CENTRE_FRONT_TO_BACK
sourceCamPos = raceInfo.sourcePos
sourceMod = racerInfo[2].racerPos - racerInfo[0].racerPos
sourceCamTarget = sourceCamPos + sourceMod
sourceCamTarget += sourceMod
sourceCamTarget += sourceMod
sourceCamTarget += sourceMod
destCamPos = sourceCamTarget
sourceCamTarget += sourceMod
sourceCamTarget += sourceMod
sourceCamTarget += sourceMod
destCamTarget = sourceCamTarget
sourceCamTarget.z += 1.0
destCamTarget.z += 1.5
sourceCamPos.z += 1.0
destCamPos.z += 2.5
BREAK
CASE RG_FLYBY_LEFT_BACK_TO_FRONT
destCamPos = racerInfo[1].racerPos
destCamTarget = racerInfo[2].racerPos
sourceCamPos = racerInfo[postion11].racerPos
sourceCamTarget = racerInfo[position8].racerPos
sourceMod = sourceCamPos - sourceCamTarget
sourceCamPos += sourceMod
destCamPos += sourceMod
sourceMod = racerInfo[position9].racerPos - racerInfo[postion11].racerPos
destCamPos += sourceMod
sourceCamPos.z += 1.0
destCamPos.z += 2.0
BREAK
CASE RG_FLYBY_RIGHT_BACK_TO_FRONT
destCamPos = racerInfo[2].racerPos
destCamTarget = racerInfo[1].racerPos
sourceCamPos = racerInfo[position8].racerPos
sourceCamTarget= racerInfo[postion11].racerPos
sourceMod = sourceCamPos - sourceCamTarget
sourceCamPos += sourceMod
destCamPos += sourceMod
sourceMod = racerInfo[position8].racerPos - racerInfo[postion10].racerPos
destCamPos += sourceMod
sourceCamPos.z += 3.0
destCamPos.z += 4.0
BREAK
CASE RG_FLYBY_CENTRE_BACK_TO_FRONT
destCamPos = raceInfo.sourcePos
sourceMod = racerInfo[2].racerPos - racerInfo[0].racerPos
sourceCamTarget = destCamPos + sourceMod
sourceCamTarget += sourceMod
sourceCamTarget += sourceMod
sourceCamTarget += sourceMod
sourceCamPos = sourceCamTarget
sourceCamTarget += sourceMod
sourceCamTarget += sourceMod
sourceCamTarget += sourceMod
destCamTarget = sourceCamTarget
sourceCamTarget.z += 1.0
destCamTarget.z += 1.5
sourceCamPos.z += 2.5
destCamPos.z += 1.0
BREAK
CASE RG_FLYBY_DRAG_BACK_TO_FRONT
destCamPos = raceInfo.sourcePos
sourceMod = GET_RACER_GRID_POSITION(tempRacerInfo, raceInfo, temp2) - racerInfo[0].racerPos
sourceCamTarget = destCamPos + sourceMod
sourceCamTarget += sourceMod
sourceCamTarget += sourceMod
sourceCamTarget += sourceMod
sourceCamPos = sourceCamTarget
sourceCamTarget += sourceMod
sourceCamTarget += sourceMod
sourceCamTarget += sourceMod
destCamTarget = sourceCamTarget
sourceCamTarget.z += 1.0
destCamTarget.z += 1.5
sourceCamPos.z += 2.5
destCamPos.z += 1.0
BREAK
ENDSWITCH
IF NOT DOES_CAM_EXIST(raceInfo.raceSourceCam)
raceInfo.raceSourceCam = CREATE_CAM_WITH_PARAMS("DEFAULT_SCRIPTED_CAMERA", sourceCamPos, sourceCamPos, 30)
POINT_CAM_AT_COORD(raceInfo.raceSourceCam, sourceCamTarget)
raceInfo.raceDestCam = CREATE_CAM_WITH_PARAMS("DEFAULT_SCRIPTED_CAMERA", destCamPos, destCamPos, 30)
POINT_CAM_AT_COORD(raceInfo.raceDestCam, destCamTarget)
SET_CAM_ACTIVE_WITH_INTERP(raceInfo.raceDestCam, raceInfo.raceSourceCam, 7500, GRAPH_TYPE_SIN_ACCEL_DECEL, GRAPH_TYPE_LINEAR)
ENDIF
ENDIF
ENDPROC
FUNC RACE_GRID_FLYBY_STYLE RANDOM_RG_FLYBY_STYLE()
RACE_GRID_FLYBY_STYLE returnedStyle
SWITCH GET_RANDOM_INT_IN_RANGE(1, 6)
CASE 1
returnedStyle = RG_FLYBY_LEFT_FRONT_TO_BACK
BREAK
CASE 2
returnedStyle = RG_FLYBY_RIGHT_FRONT_TO_BACK
BREAK
CASE 3
returnedStyle = RG_FLYBY_CENTRE_FRONT_TO_BACK
BREAK
CASE 4
returnedStyle = RG_FLYBY_LEFT_BACK_TO_FRONT
BREAK
CASE 5
returnedStyle = RG_FLYBY_RIGHT_BACK_TO_FRONT
BREAK
CASE 6
returnedStyle = RG_FLYBY_CENTRE_BACK_TO_FRONT
BREAK
ENDSWITCH
//// Global checked to allow for the initial race to have an intro cutscene - negating the need for a flyby.
// IF g_roadRashRacesWon = 0
// returnedStyle = RG_FLYBY_NONE
// ENDIF
RETURN returnedStyle
ENDFUNC
FUNC BOOL HAS_RACE_GRID_FLYBY_FINISHED(RACE_GRID_FLYBY_STYLE flybyStyle, RACE_INFO_STRUCT &raceInfo)
IF flybyStyle <> RG_FLYBY_NONE
IF DOES_CAM_EXIST(raceInfo.raceSourceCam)
IF NOT IS_CAM_INTERPOLATING(raceInfo.raceSourceCam)
// OR IS_CUTSCENE_SKIP_BUTTON_JUST_PRESSED()
IF DOES_CAM_EXIST(raceInfo.raceSourceCam)
SET_CAM_ACTIVE (raceInfo.raceSourceCam, FALSE)
DESTROY_CAM(raceInfo.raceSourceCam)
ENDIF
IF DOES_CAM_EXIST(raceInfo.raceDestCam)
SET_CAM_ACTIVE (raceInfo.raceDestCam, FALSE)
DESTROY_CAM(raceInfo.raceDestCam)
SET_GAMEPLAY_CAM_RELATIVE_HEADING(0.0)
ENDIF
RETURN TRUE
ENDIF
ENDIF
ELSE
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
FUNC BOOL HAS_RACE_COUNTDOWN_AND_FLYBY_FINISHED(INT &raceCount, INT &countdownStart, INT &countdownEnd, RACE_GRID_FLYBY_STYLE flybyStyle, RACER_INFO_STRUCT &racerInfo[], RACE_INFO_STRUCT &raceInfo)
CONST_INT raceFour 4
CONST_INT raceThree 3
CONST_INT raceTwo 2
CONST_INT raceOne 1
CONST_INT raceGo 0
FLOAT textX = 0.5
FLOAT textY = 0.5
SWITCH raceCount
CASE raceFour
IF countdownEnd < (countdownStart + 3000)
START_RACE_GRID_FLYBY(flybyStyle, racerInfo, raceInfo)
countdownEnd = GET_GAME_TIMER()
CLEAR_PRINTS()
ELSE
IF HAS_RACE_GRID_FLYBY_FINISHED(flybyStyle, raceInfo)
//PRINT_WITH_NUMBER_BIG("NUMBER", 3, 1100, 1)
DISPLAY_TEXT_WITH_NUMBER(textX, textY, "NUMBER", 3)
PLAY_SOUND_FRONTEND(-1, "3_2_1", "HUD_MINI_GAME_SOUNDSET")
countdownStart = GET_GAME_TIMER()
raceCount = (raceThree)
ENDIF
ENDIF
BREAK
CASE raceThree
IF countdownEnd < (countdownStart + 1000)
DISPLAY_TEXT_WITH_NUMBER(textX, textY, "NUMBER", 3)
countdownEnd = GET_GAME_TIMER()
ELSE
//PRINT_WITH_NUMBER_BIG("NUMBER", 2, 1100, 1)
DISPLAY_TEXT_WITH_NUMBER(textX, textY, "NUMBER", 2)
PLAY_SOUND_FRONTEND(-1, "3_2_1", "HUD_MINI_GAME_SOUNDSET")
countdownStart = GET_GAME_TIMER()
raceCount = (raceTwo)
ENDIF
BREAK
CASE raceTwo
IF countdownEnd < (countdownStart + 1000)
DISPLAY_TEXT_WITH_NUMBER(textX, textY, "NUMBER", 2)
countdownEnd = GET_GAME_TIMER()
ELSE
//PRINT_WITH_NUMBER_BIG("NUMBER", 1, 1100, 1)
DISPLAY_TEXT_WITH_NUMBER(textX, textY, "NUMBER", 1)
PLAY_SOUND_FRONTEND(-1, "3_2_1", "HUD_MINI_GAME_SOUNDSET")
countdownStart = GET_GAME_TIMER()
raceCount = (raceOne)
ENDIF
BREAK
CASE raceOne
IF countdownEnd < (countdownStart + 1000)
DISPLAY_TEXT_WITH_NUMBER(textX, textY, "NUMBER", 1)
countdownEnd = GET_GAME_TIMER()
ELSE
//PRINT_WITH_NUMBER_BIG("GO", 3, 1100, 1)
DISPLAY_TEXT(textX, textY, "GOBR")
PLAY_SOUND_FRONTEND(-1, "GO", "HUD_MINI_GAME_SOUNDSET")
countdownStart = GET_GAME_TIMER()
raceCount = (raceGo)
ENDIF
BREAK
CASE raceGo
RETURN TRUE
BREAK
ENDSWITCH
RETURN FALSE
ENDFUNC
FUNC BOOL HAS_RACER_ABANDONED_RACE_VEHICLE(RACER_INFO_STRUCT &playerRacer, RACE_VEHICLE_CLASS vehicleClass, int &iRaceTimer, int &iTimeStamp, int iTimeLimit)
INT iTimeDiff
INT iCountdownTime
INT iPrintTime
IF IS_PED_IN_ACCEPTABLE_RACE_VEHICLE(playerRacer, vehicleClass)
iTimeStamp = iRaceTimer
ELSE
iTimeDiff = iRaceTimer - iTimeStamp
iCountdownTime = iTimeLimit - iTimeDiff
iPrintTime = iCountdownTime / 1000
IF iPrintTime > 0
ADD_NEXT_MESSAGE_TO_PREVIOUS_BRIEFS(false)
iPrintTime = iCountdownTime / 1000
IF iPrintTime < 11
// IF playerRacer.raceVehicleBlip = null
// IF vehicleClass <> RACE_VEHICLE_CLASS_MOTORBIKES
// IF iPrintTime = 1
// PRINT_WITH_NUMBER_NOW("RACEOUTCAR", iPrintTime, 250, 1)
// ELSE
// PRINT_WITH_NUMBER_NOW("RACEOUTCARs", iPrintTime, 250, 1)
// ENDIF
// ELSE
// IF iPrintTime = 1
// PRINT_WITH_NUMBER_NOW("RACEOUTBIK", iPrintTime, 250, 1)
// ELSE
// PRINT_WITH_NUMBER_NOW("RACEOUTBIKs", iPrintTime, 250, 1)
// ENDIF
// ENDIF
// ELSE
IF vehicleClass <> RACE_VEHICLE_CLASS_MOTORBIKES
IF iPrintTime = 1
PRINT_WITH_NUMBER_NOW("RACEOUTCARBLIP", iCountdownTime / 1000, 250, 1)
ELSE
PRINT_WITH_NUMBER_NOW("RACEOUTCARBLIPS", iCountdownTime / 1000, 250, 1)
ENDIF
ELSE
IF iPrintTime = 1
PRINT_WITH_NUMBER_NOW("RACEOUTBIKBLIP", iCountdownTime / 1000, 250, 1)
ELSE
PRINT_WITH_NUMBER_NOW("RACEOUTBIKBLIPS", iCountdownTime / 1000, 250, 1)
ENDIF
ENDIF
// ENDIF
ENDIF
ELSE
RETURN TRUE
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
FUNC BOOL HAS_RACER_HIT_CHECK(RACER_INFO_STRUCT &racerInfo, RACE_INFO_STRUCT &raceInfo)
IF raceInfo.raceCLass = RACE_VEHICLE_CLASS_RC_CHECKS
OR raceInfo.raceCLass = RACE_VEHICLE_CLASS_RC
checkSize = LOCATE_SIZE_ON_FOOT_ONLY
ELSE
IF raceInfo.chosenCourse = RACE_COURSE_RC_EXTREME1
checkSize = LOCATE_SIZE_ANY_MEANS+2 // B*1531743 Increase radius for Extreme1 race
ELSE
checkSize = LOCATE_SIZE_ANY_MEANS
ENDIF
ENDIF
IF racerInfo.currentCheck > -1
IF IS_ENTITY_AT_COORD(racerInfo.racer, raceInfo.checkPos[racerInfo.currentCheck], <<checkSize, checkSize, checkSize>>, FALSE)
RETURN TRUE
ENDIF
ELSE
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
FUNC CHECKPOINT_TYPE GET_CHECKPOINT_TYPE(INT iCheckNum, RACE_INFO_STRUCT &raceInfo)
VECTOR pos, pos2, pos3
VECTOR vec1, vec2
FLOAT fReturnAngle
FLOAT fChevron1 = 180.0
FLOAT fChevron2 = 140.0
FLOAT fChevron3 = 80.0
pos = raceInfo.checkPos[iCheckNum]
IF iCheckNum+1 = raceInfo.totalChecks - 1
pos2 = raceInfo.checkPos[0]
ELSE
pos2 = raceInfo.checkPos[iCheckNum + 1]
ENDIF
IF iCheckNum - 1 >= 0
pos3 = raceInfo.checkPos[iCheckNum-1]
ENDIF
vec1 = pos3 - pos
vec2 = pos2 - pos
fReturnAngle = GET_ANGLE_BETWEEN_2D_VECTORS(vec1.x, vec1.y, vec2.x, vec2.y)
IF fReturnAngle > 180
fReturnAngle = (360.0 - fReturnAngle)
ENDIF
IF fReturnAngle < fChevron3
RETURN CHECKPOINT_RACE_GROUND_CHEVRON_3
ELIF fReturnAngle < fChevron2
RETURN CHECKPOINT_RACE_GROUND_CHEVRON_2
ELIF fReturnAngle < fChevron1
RETURN CHECKPOINT_RACE_GROUND_CHEVRON_1
ELSE
RETURN CHECKPOINT_RACE_GROUND_CHEVRON_1
ENDIF
RETURN CHECKPOINT_RACE_GROUND_CHEVRON_1
ENDFUNC
FUNC HUD_COLOURS GET_CHECKPOINT_COLOUR(CHECKPOINT_TYPE cpType)
// IF cpType = CHECKPOINT_RACE_GROUND_CHEVRON_3
// RETURN HUD_COLOUR_YELLOWDARK
// ELIF cpType = CHECKPOINT_RACE_GROUND_CHEVRON_2
// RETURN HUD_COLOUR_YELLOW
// ELSE
// RETURN HUD_COLOUR_YELLOWLIGHT
// ENDIF
// Returning YELLOWDARK for all checkpoints (B*1454575)
cpType = cpType // Compile fix, no point changing the function because this won't stay...
RETURN HUD_COLOUR_YELLOWDARK
ENDFUNC
PROC SET_PLAYER_CHECKPOINTS_AND_BLIPS(RACER_INFO_STRUCT &playerInfo, RACE_INFO_STRUCT &raceInfo)
VECTOR tempPos
FLOAT fBlipScale = 0.7
FLOAT fCheckSize = 7.5*2*0.66
BOOL bDrawNextBlip = TRUE
// Get checkpoint arrow
CHECKPOINT_TYPE checkArrow = GET_CHECKPOINT_TYPE(playerInfo.currentCheck, raceInfo)
CHECKPOINT_TYPE checkFlag = CHECKPOINT_RACE_GROUND_FLAG
// Get checkpoint colour
INT iR, iG, iB, iA
GET_HUD_COLOUR(GET_CHECKPOINT_COLOUR(checkArrow), iR, iG, iB, iA)
IF DOES_BLIP_EXIST(playerInfo.checkBlip)
REMOVE_BLIP(playerInfo.checkBlip)
DELETE_CHECKPOINT(playerInfo.checkPoint)
INT piR, piG, piB, piA
GET_HUD_COLOUR(HUD_COLOUR_WHITE, piR, piG, piB, piA)
PrevAlpha = 180
tempPos = raceInfo.checkPos[playerInfo.currentCheck-1]
tempPos += <<0,0,7.5>>
IF playerInfo.currentCheck = (raceInfo.totalChecks - 1)
playerInfo.PrevCheckpoint = CREATE_CHECKPOINT(checkFlag, tempPos, raceInfo.checkPos[playerInfo.currentCheck], fCheckSize, PiR, PiG, PiB, PrevAlpha)
SET_CHECKPOINT_CYLINDER_HEIGHT(playerInfo.PrevCheckpoint,3.0,3.0,100)
SET_CHECKPOINT_RGBA(playerInfo.PrevCheckpoint, PiR, PiG, PiB, PrevAlpha)
SET_CHECKPOINT_RGBA2(playerInfo.PrevCheckpoint, PiR, PiG, PiB, PrevAlpha)
ELSE
playerInfo.PrevCheckpoint = CREATE_CHECKPOINT(GET_CHECKPOINT_TYPE(playerInfo.currentCheck-1, raceInfo), tempPos, raceInfo.checkPos[playerInfo.currentCheck], fCheckSize, PiR, PiG, PiB, PrevAlpha)
SET_CHECKPOINT_CYLINDER_HEIGHT(playerInfo.PrevCheckpoint,3.0,3.0,100)
SET_CHECKPOINT_RGBA(playerInfo.PrevCheckpoint, PiR, PiG, PiB, PrevAlpha)
SET_CHECKPOINT_RGBA2(playerInfo.PrevCheckpoint, PiR, PiG, PiB, PrevAlpha)
ENDIF
ENDIF
// Current checkpoint
IF NOT DOES_BLIP_EXIST(playerInfo.checkBlip)
// Blip checkpoint
playerInfo.checkBlip = ADD_BLIP_FOR_COORD(raceInfo.checkPos[playerInfo.currentCheck])
SET_BLIP_DISPLAY(playerInfo.checkBlip, DISPLAY_BLIP)
SET_BLIP_NAME_FROM_TEXT_FILE(playerInfo.checkBlip, "BLIP_CPOINT")
SET_BLIP_SCALE(playerInfo.checkBlip, 1.2)
SHOW_HEIGHT_ON_BLIP(playerInfo.checkBlip, FALSE)
// Values taken from multiplayer/single player street races
tempPos = raceInfo.checkPos[playerInfo.currentCheck]
tempPos += <<0,0,7.5>>
IF playerInfo.currentCheck = (raceInfo.totalChecks - 1)
// Final checkpoint
IF playerInfo.currentLap = raceInfo.totalLaps
playerInfo.checkPoint = CREATE_CHECKPOINT(checkFlag, tempPos, raceInfo.checkPos[playerInfo.currentCheck], fCheckSize, iR, iG, iB)
GET_HUD_COLOUR(HUD_COLOUR_YELLOWLIGHT, iR, iG, iB, iA)
SET_CHECKPOINT_RGBA(playerInfo.checkPoint, iR, iG, iB, iA)
GET_HUD_COLOUR(HUD_COLOUR_NORTH_BLUE, iR, iG, iB, iA)
SET_CHECKPOINT_RGBA2(playerInfo.checkPoint, iR, iG, iB, iA)
SET_CHECKPOINT_CYLINDER_HEIGHT(playerInfo.checkPoint,3.0,3.0,100)
FLOAT fDis = GET_DISTANCE_BETWEEN_COORDS(raceInfo.checkPos[playerInfo.currentCheck],GET_ENTITY_COORDS(PLAYER_PED_ID(), FALSE))
IF playerInfo.checkPoint != NULL // Make sure the checkpoint exists first
IF playerInfo.distanceToNextCheck > 100.0
iA = 200
GET_HUD_COLOUR(HUD_COLOUR_YELLOWLIGHT, iR, iG, iB, iA)
SET_CHECKPOINT_RGBA(playerInfo.checkPoint, iR, iG, iB, iA)
GET_HUD_COLOUR(HUD_COLOUR_NORTH_BLUE, iR, iG, iB, iA)
SET_CHECKPOINT_RGBA2(playerInfo.checkPoint, iR, iG, iB, iA)
ELSE
GET_HUD_COLOUR(HUD_COLOUR_YELLOWLIGHT, iR, iG, iB, iA)
iA = ROUND(fDis*2)
SET_CHECKPOINT_RGBA(playerInfo.checkPoint, iR, iG, iB, iA)
GET_HUD_COLOUR(HUD_COLOUR_NORTH_BLUE, iR, iG, iB, iA)
iA = ROUND(fDis*2)
SET_CHECKPOINT_RGBA2(playerInfo.checkPoint, iR, iG, iB, iA)
ENDIF
ENDIF
SET_BLIP_SPRITE(playerInfo.checkBlip, RADAR_TRACE_RACEFLAG)
bDrawNextBlip = FALSE
ELSE
// Next lap
playerInfo.checkPoint = CREATE_CHECKPOINT(checkFlag, tempPos, raceInfo.checkPos[0], fCheckSize, iR, iG, iB, iA)
GET_HUD_COLOUR(HUD_COLOUR_YELLOWLIGHT, iR, iG, iB, iA)
SET_CHECKPOINT_RGBA(playerInfo.checkPoint, iR, iG, iB, iA)
GET_HUD_COLOUR(HUD_COLOUR_NORTH_BLUE, iR, iG, iB, iA)
SET_CHECKPOINT_RGBA2(playerInfo.checkPoint, iR, iG, iB, iA)
SET_CHECKPOINT_CYLINDER_HEIGHT(playerInfo.checkPoint,3.0,3.0,100)
FLOAT fDis = GET_DISTANCE_BETWEEN_COORDS(raceInfo.checkPos[playerInfo.currentCheck],GET_ENTITY_COORDS(PLAYER_PED_ID(), FALSE))
IF playerInfo.checkPoint != NULL // Make sure the checkpoint exists first
IF playerInfo.distanceToNextCheck > 100.0
iA = 200
GET_HUD_COLOUR(HUD_COLOUR_YELLOWLIGHT, iR, iG, iB, iA)
SET_CHECKPOINT_RGBA(playerInfo.checkPoint, iR, iG, iB, iA)
GET_HUD_COLOUR(HUD_COLOUR_NORTH_BLUE, iR, iG, iB, iA)
SET_CHECKPOINT_RGBA2(playerInfo.checkPoint, iR, iG, iB, iA)
ELSE
GET_HUD_COLOUR(HUD_COLOUR_YELLOWLIGHT, iR, iG, iB, iA)
iA = ROUND(fDis*2)
SET_CHECKPOINT_RGBA(playerInfo.checkPoint, iR, iG, iB, iA)
GET_HUD_COLOUR(HUD_COLOUR_NORTH_BLUE, iR, iG, iB, iA)
iA = ROUND(fDis*2)
SET_CHECKPOINT_RGBA2(playerInfo.checkPoint, iR, iG, iB, iA)
ENDIF
ENDIF
ENDIF
ELSE
playerInfo.checkPoint = CREATE_CHECKPOINT(checkArrow, tempPos, raceInfo.checkPos[(playerInfo.currentCheck+1)], fCheckSize, iR, iG, iB, 150)
GET_HUD_COLOUR(HUD_COLOUR_YELLOWLIGHT, iR, iG, iB, iA)
SET_CHECKPOINT_RGBA(playerInfo.checkPoint, iR, iG, iB, iA)
GET_HUD_COLOUR(HUD_COLOUR_NORTH_BLUE, iR, iG, iB, iA)
SET_CHECKPOINT_RGBA2(playerInfo.checkPoint, iR, iG, iB, iA)
SET_CHECKPOINT_CYLINDER_HEIGHT(playerInfo.checkPoint,3.0,3.0,100)
FLOAT fDis = GET_DISTANCE_BETWEEN_COORDS(raceInfo.checkPos[playerInfo.currentCheck],GET_ENTITY_COORDS(PLAYER_PED_ID(), FALSE))
IF playerInfo.checkPoint != NULL // Make sure the checkpoint exists first
IF playerInfo.distanceToNextCheck > 100.0
iA = 200
SET_CHECKPOINT_RGBA(playerInfo.checkPoint, iR, iG, iB, iA)
GET_HUD_COLOUR(HUD_COLOUR_YELLOWLIGHT, iR, iG, iB, iA)
SET_CHECKPOINT_RGBA(playerInfo.checkPoint, iR, iG, iB, iA)
GET_HUD_COLOUR(HUD_COLOUR_NORTH_BLUE, iR, iG, iB, iA)
SET_CHECKPOINT_RGBA2(playerInfo.checkPoint, iR, iG, iB, iA)
ELSE
GET_HUD_COLOUR(HUD_COLOUR_YELLOWLIGHT, iR, iG, iB, iA)
iA = ROUND(fDis*2)
SET_CHECKPOINT_RGBA(playerInfo.checkPoint, iR, iG, iB, iA)
GET_HUD_COLOUR(HUD_COLOUR_NORTH_BLUE, iR, iG, iB, iA)
iA = ROUND(fDis*2)
SET_CHECKPOINT_RGBA2(playerInfo.checkPoint, iR, iG, iB, iA)
ENDIF
ENDIF
ENDIF
ENDIF
// Next checkpoint
IF DOES_BLIP_EXIST(playerInfo.nextCheckBlip)
REMOVE_BLIP(playerInfo.nextCheckBlip)
ENDIF
IF bDrawNextBlip
IF NOT DOES_BLIP_EXIST(playerInfo.nextCheckBlip)
IF playerInfo.nextCheck < (raceInfo.totalChecks - 1)
playerInfo.nextCheckBlip = ADD_BLIP_FOR_COORD(raceInfo.checkPos[playerInfo.nextCheck])
SET_BLIP_DISPLAY(playerInfo.nextCheckBlip, DISPLAY_BLIP)
SET_BLIP_SCALE(playerInfo.nextCheckBlip, fBlipScale)
SHOW_HEIGHT_ON_BLIP(playerInfo.nextCheckBlip, FALSE)
SET_BLIP_NAME_FROM_TEXT_FILE(playerInfo.nextCheckBlip, "BLIP_CPOINT")
ELSE
IF playerInfo.nextCheck = (raceInfo.totalChecks - 1)
IF playerInfo.currentLap = raceInfo.totalLaps
playerInfo.nextCheckBlip = ADD_BLIP_FOR_COORD(raceInfo.checkPos[playerInfo.nextCheck])
SET_BLIP_SPRITE(playerInfo.nextCheckBlip, RADAR_TRACE_RACEFLAG)
SET_BLIP_DISPLAY(playerInfo.nextCheckBlip, DISPLAY_BLIP)
SET_BLIP_SCALE(playerInfo.nextCheckBlip, 1.2) // Final blip should be 1.2 scale
SHOW_HEIGHT_ON_BLIP(playerInfo.nextCheckBlip, FALSE)
SET_BLIP_NAME_FROM_TEXT_FILE(playerInfo.nextCheckBlip, "BLIP_CPOINT")
ELSE
playerInfo.nextCheckBlip = ADD_BLIP_FOR_COORD(raceInfo.checkPos[playerInfo.nextCheck])
SET_BLIP_DISPLAY(playerInfo.nextCheckBlip, DISPLAY_BLIP)
SET_BLIP_SCALE(playerInfo.nextCheckBlip, fBlipScale)
SHOW_HEIGHT_ON_BLIP(playerInfo.nextCheckBlip, FALSE)
SET_BLIP_NAME_FROM_TEXT_FILE(playerInfo.nextCheckBlip, "BLIP_CPOINT")
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDPROC
FUNC BOOL RUN_PLAYER_CHECKPOINTS_AND_BLIPS(RACER_INFO_STRUCT &playerInfo, RACE_INFO_STRUCT &raceInfo, BOOL bOnlyIfInVehicle = TRUE)
IF IS_PED_IN_ACCEPTABLE_RACE_VEHICLE(playerInfo, raceInfo.raceClass) // Vehicle class shouldn't be hard wired.
OR bOnlyIfInVehicle = FALSE
IF playerInfo.PrevCheckpoint != NULL
PrevAlpha -= 25
IF PrevAlpha > 0
INT piR, piG, piB, piA
GET_HUD_COLOUR(HUD_COLOUR_WHITE, piR, piG, piB, piA)
SET_CHECKPOINT_RGBA(playerInfo.PrevCheckpoint, piR, piG, piB, PrevAlpha)
SET_CHECKPOINT_RGBA2(playerInfo.PrevCheckpoint, piR, piG, piB, PrevAlpha)
ELSE
DELETE_CHECKPOINT(playerInfo.PrevCheckpoint)
ENDIF
ENDIF
IF HAS_RACER_HIT_CHECK(playerInfo, raceInfo)
IF playerInfo.currentCheck < (raceInfo.totalChecks - 1)
playerInfo.currentCheck++
IF playerInfo.nextCheck = (raceInfo.totalChecks-1)
IF playerInfo.currentLap < raceInfo.totalLaps
playerInfo.nextCheck = 0
ENDIF
ELSE
playerInfo.nextCheck++
ENDIF
SET_PLAYER_CHECKPOINTS_AND_BLIPS(playerInfo, raceInfo)
PLAY_SOUND_FRONTEND(-1, "CHECKPOINT_NORMAL", "HUD_MINI_GAME_SOUNDSET", FALSE)
RETURN TRUE
ELSE
IF playerInfo.currentLap < raceInfo.totalLaps
playerInfo.currentCheck = 0
playerInfo.nextCheck = 1
playerInfo.currentLap++
SET_PLAYER_CHECKPOINTS_AND_BLIPS(playerInfo, raceInfo)
// Play the checkpoint lap sound?
PLAY_SOUND_FRONTEND(-1, "CHECKPOINT_NORMAL", "HUD_MINI_GAME_SOUNDSET", FALSE)
RETURN TRUE
ELSE
IF DOES_BLIP_EXIST(playerInfo.checkBlip)
playerInfo.racerStatus = RACER_STATUS_FINISHED
REMOVE_BLIP(playerInfo.checkBlip)
DELETE_CHECKPOINT(playerInfo.checkPoint)
PLAY_SOUND_FRONTEND(-1, "CHECKPOINT_NORMAL", "HUD_MINI_GAME_SOUNDSET", FALSE)
ENDIF
ENDIF
ENDIF
ELSE
IF NOT DOES_BLIP_EXIST(playerInfo.checkBlip)
SET_PLAYER_CHECKPOINTS_AND_BLIPS(playerInfo, raceInfo)
ENDIF
ENDIF
CHECKPOINT_TYPE checkArrow = GET_CHECKPOINT_TYPE(playerInfo.currentCheck, raceInfo)
// Get checkpoint colour
INT iR, iG, iB, iA
GET_HUD_COLOUR(GET_CHECKPOINT_COLOUR(checkArrow), iR, iG, iB, iA)
// Do alpha fade of current checkpoint as player gets closer to it
playerInfo.distanceToNextCheck = VDIST(GET_ENTITY_COORDS(playerInfo.racer), raceInfo.checkPos[playerInfo.currentCheck])
IF playerInfo.checkPoint != NULL // Make sure the checkpoint exists first
IF playerInfo.distanceToNextCheck > 100.0
GET_HUD_COLOUR(HUD_COLOUR_YELLOWLIGHT, iR, iG, iB, iA)
iA = 240
SET_CHECKPOINT_RGBA(playerInfo.checkPoint, iR, iG, iB, iA)
GET_HUD_COLOUR(HUD_COLOUR_NORTH_BLUE, iR, iG, iB, iA)
iA = 240
SET_CHECKPOINT_RGBA2(playerInfo.checkPoint, iR, iG, iB, iA)
ELSE
GET_HUD_COLOUR(HUD_COLOUR_YELLOWLIGHT, iR, iG, iB, iA)
iA = ROUND(playerInfo.distanceToNextCheck*2.4)
IF iA < 60
iA = 60
ENDIF
SET_CHECKPOINT_RGBA(playerInfo.checkPoint, iR, iG, iB, iA)
GET_HUD_COLOUR(HUD_COLOUR_NORTH_BLUE, iR, iG, iB, iA)
iA = ROUND(playerInfo.distanceToNextCheck*2.4)
IF iA < 60
iA = 60
ENDIF
SET_CHECKPOINT_RGBA2(playerInfo.checkPoint, iR, iG, iB, iA)
ENDIF
ENDIF
ELSE
IF DOES_BLIP_EXIST(playerInfo.checkBlip)
REMOVE_BLIP(playerInfo.checkBlip)
DELETE_CHECKPOINT(playerInfo.checkPoint)
ENDIF
IF DOES_BLIP_EXIST(playerInfo.nextCheckBlip)
REMOVE_BLIP(playerInfo.nextCheckBlip)
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
PROC RACER_SPEED_UP(RACER_INFO_STRUCT &thisRacer)
FLOAT speedAdjustment = 0.2 //* (g_roadRashRacesWon+1) // Speed adjustment based on number of races won
IF speedAdjustment > 2.0
speedAdjustment = 2.0
ENDIF
IF thisRacer.racer <> PLAYER_PED_ID()
IF NOT IS_ENTITY_DEAD(thisRacer.racer)
AND NOT IS_ENTITY_DEAD(thisRacer.raceVehicle)
IF thisRacer.currentSpeed < 50.0
IF IS_PED_IN_VEHICLE(thisRacer.racer, thisRacer.raceVehicle)
IF GET_SCRIPT_TASK_STATUS (thisRacer.racer, SCRIPT_TASK_VEHICLE_DRIVE_TO_COORD) = PERFORMING_TASK
thisRacer.currentSpeed += 0.2
SET_DRIVE_TASK_CRUISE_SPEED(thisRacer.racer, thisRacer.currentSpeed)
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDPROC
PROC RACER_SLOW_DOWN(RACER_INFO_STRUCT &thisRacer)
IF thisRacer.racer <> PLAYER_PED_ID()
IF NOT IS_ENTITY_DEAD(thisRacer.racer)
AND NOT IS_ENTITY_DEAD(thisRacer.raceVehicle)
IF thisRacer.currentSpeed > 25.0
IF IS_PED_IN_VEHICLE(thisRacer.racer, thisRacer.raceVehicle)
IF GET_SCRIPT_TASK_STATUS (thisRacer.racer, SCRIPT_TASK_VEHICLE_DRIVE_TO_COORD) = PERFORMING_TASK
thisRacer.currentSpeed -= 0.005
SET_DRIVE_TASK_CRUISE_SPEED(thisRacer.racer, thisRacer.currentSpeed)
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDPROC
FUNC BOOL IS_RACER_HEADING_ACCEPTABLE_FOR_RACE_START(RACER_INFO_STRUCT &playerRacer, RACE_INFO_STRUCT &raceInfo)
FLOAT upperHeadingLimit = 15.0
FLOAT lowerHeadingLimit = 15.0
IF NOT IS_ENTITY_DEAD(playerRacer.raceVehicle)
lowerHeadingLimit = raceInfo.sourceHeading - lowerHeadingLimit
IF lowerHeadingLimit < 0.0
lowerHeadingLimit += 360.0
ENDIF
upperHeadingLimit = raceInfo.sourceHeading + 15.0
IF upperHeadingLimit >= 360.0
upperHeadingLimit -= 360.0
ENDIF
IF upperHeadingLimit > lowerHeadingLimit
IF GET_ENTITY_HEADING(playerRacer.raceVehicle) < upperHeadingLimit
AND GET_ENTITY_HEADING(playerRacer.raceVehicle) > lowerHeadingLimit
RETURN TRUE
ELSE
RETURN FALSE
ENDIF
ELSE
IF GET_ENTITY_HEADING(playerRacer.raceVehicle) < upperHeadingLimit
OR GET_ENTITY_HEADING(playerRacer.raceVehicle) > lowerHeadingLimit
RETURN TRUE
ELSE
RETURN FALSE
ENDIF
ENDIF
ELSE
RETURN FALSE
ENDIF
ENDFUNC
FUNC INT GET_RACE_POSITION(RACER_INFO_STRUCT &playerRacer, RACER_INFO_STRUCT &otherRacers[], RACE_INFO_STRUCT &raceInfo)
INT racePosition = (raceInfo.totalRacers -1)
INT i
REPEAT (raceInfo.totalRacers-1) i
// printDebugStringAndInt("playerRacer.currentLap = ", playerRacer.currentLap)
// printDebugString("\n")
// printDebugStringAndInt("playerRacer.currentCheck = ", playerRacer.currentCheck)
// printDebugString("\n")
// printDebugStringAndFloat("playerRacer.distanceToNextCheck = ", playerRacer.distanceToNextCheck)
// printDebugString("\n")
//
// printDebugStringAndInt("otherRacers[", i)
// printDebugStringAndInt("].currentLap = ", otherRacers[i].currentLap)
// printDebugString("\n")
// printDebugStringAndInt("otherRacers[", i)
// printDebugStringAndInt("].currentCheck = ", otherRacers[i].currentCheck)
// printDebugString("\n")
// printDebugStringAndFloat("otherRacers[i].distanceToNextCheck = ", otherRacers[i].distanceToNextCheck)
// printDebugString("\n")
IF playerRacer.currentLap = otherRacers[i].currentLap
IF playerRacer.currentCheck = otherRacers[i].currentCheck
IF playerRacer.distanceToNextCheck < otherRacers[i].distanceToNextCheck
IF racePosition > 0
racePosition--
RACER_SPEED_UP(otherRacers[i])
ENDIF
ELSE
RACER_SLOW_DOWN(otherRacers[i])
ENDIF
ELSE
IF playerRacer.currentCheck > otherRacers[i].currentCheck
IF racePosition > 0
racePosition--
RACER_SPEED_UP(otherRacers[i])
ENDIF
ELSE
RACER_SLOW_DOWN(otherRacers[i])
ENDIF
ENDIF
ELSE
IF playerRacer.currentLap > otherRacers[i].currentLap
IF racePosition > 0
racePosition--
RACER_SPEED_UP(otherRacers[i])
ENDIF
ELSE
//IF racePosition > 0
RACER_SLOW_DOWN(otherRacers[i])
//ENDIF
ENDIF
ENDIF
ENDREPEAT
RETURN racePosition
ENDFUNC
PROC RUN_AI_RACERS(RACER_INFO_STRUCT &playerRacer, RACER_INFO_STRUCT &racerInfo[], RACE_INFO_STRUCT &raceInfo)
INT i
INT thisCheckpoint
REPEAT raceInfo.totalRacers i
IF NOT IS_PED_INJURED(racerInfo[i].racer)
IF IS_VEHICLE_DRIVEABLE(racerInfo[i].raceVehicle)
IF IS_PED_IN_VEHICLE(racerInfo[i].racer, racerInfo[i].raceVehicle)
IF HAS_RACER_HIT_CHECK(racerInfo[i], raceInfo)
IF playerRacer.racer <> racerInfo[i].racer
IF racerInfo[i].currentCheck < (raceInfo.totalChecks - 1)
racerInfo[i].currentCheck++
ELSE
IF racerInfo[i].currentLap < raceInfo.totalLaps
racerInfo[i].currentLap++
racerInfo[i].currentCheck = 0
ELSE
IF racerInfo[i].currentLap = raceInfo.totalLaps
racerInfo[i].racerStatus = RACER_STATUS_FINISHED
ENDIF
ENDIF
ENDIF
IF GET_SCRIPT_TASK_STATUS(racerInfo[i].racer, SCRIPT_TASK_PLAY_ANIM) = FINISHED_TASK
thisCheckpoint = racerInfo[i].currentCheck
TASK_VEHICLE_DRIVE_TO_COORD(racerInfo[i].racer, racerInfo[i].raceVehicle, raceInfo.checkPos[thisCheckpoint],
racerInfo[i].currentSpeed, DRIVINGSTYLE_RACING, DUMMY_MODEL_FOR_SCRIPT, DRIVINGMODE_PLOUGHTHROUGH, checkSize, raceInfo.straightLineDist)
ENDIF
ENDIF
ELSE
thisCheckpoint = racerInfo[i].currentCheck
ENDIF
ELSE
IF playerRacer.racer <> racerInfo[i].racer
IF NOT IS_ENTITY_ON_SCREEN(racerInfo[i].racer)AND NOT IS_ENTITY_ON_SCREEN(racerInfo[i].raceVehicle)
IF NOT IS_SPHERE_VISIBLE(GET_ENTITY_COORDS(racerInfo[i].racer), 50)
SET_PED_INTO_VEHICLE(racerInfo[i].racer, racerInfo[i].raceVehicle)
ENDIF
ELSE
IF NOT IS_PED_GETTING_INTO_A_VEHICLE(racerInfo[i].racer)
IF GET_SCRIPT_TASK_STATUS(racerInfo[i].racer, SCRIPT_TASK_ENTER_VEHICLE) = FINISHED_TASK
TASK_ENTER_VEHICLE(racerInfo[i].racer, racerInfo[i].raceVehicle)
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
racerInfo[i].distanceToNextCheck = VDIST(GET_ENTITY_COORDS(racerInfo[i].racer), raceInfo.checkPos[thisCheckpoint])
ENDIF
ENDREPEAT
ENDPROC
FUNC BOOL IS_RACER_WARPING_DISTANCE_BEHIND(RACER_INFO_STRUCT &playerRacer, RACER_INFO_STRUCT &aiRacer, RACE_INFO_STRUCT &raceInfo)
INT checkDiff
IF playerRacer.currentLap = aiRacer.currentLap
IF playerRacer.currentCheck > aiRacer.currentCheck
checkDiff = playerRacer.currentCheck - aiRacer.currentCheck
IF checkDiff > 1
RETURN TRUE
ENDIF
ENDIF
ELIF playerRacer.currentLap > aiRacer.currentLap
IF aiRacer.currentCheck = (raceInfo.totalChecks - 1)
IF playerRacer.currentCheck > 0
RETURN TRUE
ENDIF
ELSE
RETURN TRUE
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
PROC WARP_AI_RACERS_IF_FALLING_BEHIND(RACER_INFO_STRUCT &playerRacer, RACER_INFO_STRUCT &racerInfo[], RACE_INFO_STRUCT &raceInfo)
INT i
INT nextCheckpoint
INT thisCheckpoint
FLOAT tempZ
VECTOR vTemp
REPEAT raceInfo.totalRacers i
IF NOT IS_PED_INJURED(racerInfo[i].racer)
IF racerInfo[i].racer <> playerRacer.racer
IF GET_SCRIPT_TASK_STATUS(racerInfo[i].racer, SCRIPT_TASK_VEHICLE_DRIVE_TO_COORD) = FINISHED_TASK
IF GET_SCRIPT_TASK_STATUS(racerInfo[i].racer, SCRIPT_TASK_PLAY_ANIM) = FINISHED_TASK
thisCheckpoint = racerInfo[i].currentCheck
IF IS_PED_IN_ANY_VEHICLE(racerInfo[i].racer)
IF IS_VEHICLE_DRIVEABLE(racerInfo[i].raceVehicle)
TASK_VEHICLE_DRIVE_TO_COORD(racerInfo[i].racer, racerInfo[i].raceVehicle, raceInfo.checkPos[thisCheckpoint], racerInfo[i].currentSpeed, DRIVINGSTYLE_RACING, DUMMY_MODEL_FOR_SCRIPT, DRIVINGMODE_PLOUGHTHROUGH, checkSize, raceInfo.straightLineDist)
ELSE
TASK_VEHICLE_DRIVE_TO_COORD(racerInfo[i].racer, NULL, raceInfo.checkPos[thisCheckpoint], racerInfo[i].currentSpeed, DRIVINGSTYLE_RACING, DUMMY_MODEL_FOR_SCRIPT, DRIVINGMODE_PLOUGHTHROUGH, checkSize, raceInfo.straightLineDist)
ENDIF
ENDIF
ENDIF
ENDIF
IF IS_RACER_WARPING_DISTANCE_BEHIND(playerRacer, racerInfo[i], raceInfo)
thisCheckpoint = racerInfo[i].currentCheck
IF thisCheckpoint < (raceInfo.totalChecks-1)
nextCheckpoint = (thisCheckpoint+1)
ELSE
nextCheckpoint = 0
ENDIF
IF NOT IS_ENTITY_ON_SCREEN(racerInfo[i].racer)
IF NOT IS_SPHERE_VISIBLE(raceInfo.checkPos[thisCheckpoint], 25)
IF NOT IS_POINT_OBSCURED_BY_A_MISSION_ENTITY(raceInfo.checkPos[thisCheckpoint], <<5,5,5>>)
IF NOT IS_ENTITY_AT_COORD(playerRacer.racer, raceInfo.checkPos[thisCheckpoint], <<15,15,15>>)
IF NOT IS_PED_RAGDOLL(racerInfo[i].racer)
GET_GROUND_Z_FOR_3D_COORD(<<raceInfo.checkPos[thisCheckpoint].x, raceInfo.checkPos[thisCheckpoint].y, (raceInfo.checkPos[thisCheckpoint].z+1.0)>>, tempZ)
vTemp = raceInfo.checkPos[nextCheckpoint] - raceInfo.checkPos[thisCheckpoint]
SET_ENTITY_HEADING(racerInfo[i].racer, GET_HEADING_FROM_VECTOR_2D (vTemp.x, vTemp.y))
vTemp = <<raceInfo.checkPos[thisCheckpoint].x, raceInfo.checkPos[thisCheckpoint].y, tempZ>>
/*SET_ENTITY_COORDS*/ SET_PED_COORDS_KEEP_VEHICLE(racerInfo[i].racer, vTemp)
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDREPEAT
ENDPROC
//FUNC BOOL CHOOSE_SUITABLE_RACE_COURSE(RACE_INFO_STRUCT &raceInfo)
// INT i
// BOOL positionChosen = FALSE
// RACE_INFO_STRUCT tempInfo
// RACE_COURSE raceCourse[13]
// raceCourse[0] = RACE_COURSE_MT_BIKE1
//
//
// VECTOR playerPos
// FLOAT storedDistance = 99999999999999.0
// STRING g_sSelectedRaceName = "RR_RC_BS"
// IF NOT IS_PED_INJURED(PLAYER_PED_ID())
// playerPos = GET_ENTITY_COORDS(PLAYER_PED_ID())
// ENDIF
//
// IF raceInfo.chosenCourse <> RACE_COURSE_NONE
// GENERATE_RACE_INFO(raceInfo)
// positionChosen = TRUE
// ELSE
// REPEAT 1 i
// tempInfo.chosenCourse = raceCourse[i]
// GENERATE_RACE_INFO(tempInfo)
// IF IS_A_RACE_MISSION_SCRIPT_RUNNING()
// IF ARE_STRINGS_EQUAL(g_sSelectedRaceName, tempInfo.raceName)
// AND VDIST(tempInfo.taxiPos, playerPos) < 25.0
// raceInfo = tempInfo
// raceInfo.chosenCourse = raceCourse[i]
// positionChosen = TRUE
// ENDIF
// ELSE
// IF ARE_STRINGS_EQUAL(g_sSelectedRaceName, tempInfo.raceName)
// // AND NOT IS_BIT_SET(friendRacesWonBitSet, ENUM_TO_INT(raceCourse[i]))
// raceInfo = tempInfo
// raceInfo.chosenCourse = raceCourse[i]
// storedDistance = VDIST(tempInfo.taxiPos, playerPos)
// positionChosen = TRUE
// ELSE
// IF VDIST(tempInfo.taxiPos, playerPos) < storedDistance // What if too close to the last race start?
// // IF NOT IS_BIT_SET(friendRacesWonBitSet, ENUM_TO_INT(raceCourse[i]))
// // raceInfo = tempInfo
// // raceInfo.chosenCourse = raceCourse[i]
// // storedDistance = VDIST(tempInfo.taxiPos, playerPos)
// // positionChosen = TRUE
// // ELIF g_roadRashRacesWon = g_totalRoadRashRaces
// // raceInfo = tempInfo
// // raceInfo.chosenCourse = raceCourse[i]
// // storedDistance = VDIST(tempInfo.taxiPos, playerPos)
// // positionChosen = TRUE
// // ENDIF
// ENDIF
// ENDIF
// ENDIF
// ENDREPEAT
// ENDIF
//
// IF positionChosen
// RETURN TRUE
// ENDIF
// RETURN FALSE
//ENDFUNC
//FUNC VECTOR RACE_TAXI_POSITION()
// RACE_INFO_STRUCT tempInfo
// IF CHOOSE_SUITABLE_RACE_COURSE(tempInfo)
//// g_sSelectedRaceName = tempInfo.raceName
// RETURN tempInfo.taxiPos
// ENDIF
// RETURN <<0.0, 0.0, 0.0>>
//ENDFUNC
//
//FUNC FLOAT RACE_TAXI_HEADING()
// RACE_INFO_STRUCT tempInfo
// IF CHOOSE_SUITABLE_RACE_COURSE(tempInfo)
//// g_sSelectedRaceName = tempInfo.raceName
// RETURN tempInfo.sourceHeading
// ENDIF
// RETURN -1.0
//ENDFUNC
PROC DRAW_RACE_POSITION(INT racePosition, INT totalRacers)
IF totalRacers > 1
DISPLAY_TEXT_WITH_2_NUMBERS(0.080, 0.580, "RACE_POS", racePosition, totalRacers)
ENDIF
ENDPROC
PROC DRAW_RACE_LAP_COUNTER(INT currentLap, INT totalLaps)
IF totalLaps > 1
DISPLAY_TEXT_WITH_2_NUMBERS(0.080, 0.680, "RACE_LAP", currentLap, totalLaps)
ENDIF
ENDPROC
PROC DRAW_RACE_TIME(INT iRaceTime, BOOL bFlash = FALSE)
INT iR, iG, iB, iA
INT iSeconds, iMilliseconds
iSeconds = iRaceTime/1000
iMilliseconds = iRaceTime - (iSeconds*1000)
IF iSeconds < 5
GET_HUD_COLOUR(HUD_COLOUR_RED, iR, iG, iB, iA)
SET_TEXT_COLOUR(iR, iG, iB, iA)
ENDIF
IF bFlash
GET_HUD_COLOUR(HUD_COLOUR_YELLOW, iR, iG, iB, iA)
SET_TEXT_COLOUR(iR, iG, iB, iA)
ENDIF
iSeconds = iRaceTime/1000
DISPLAY_TEXT_WITH_2_NUMBERS(0.080, 0.680, "RACE_TIME", iSeconds, iMilliseconds)
ENDPROC
FUNC INT GIVE_RACE_TIME_BONUS(INT &iTimeRemaining, INT iTimeGiven)
iTimeRemaining += iTimeGiven
RETURN iTimeRemaining
ENDFUNC
//
//PROC DRAW_RACE_TIMER(INT raceTimer, BOOL countUp = TRUE)
//
//ENDPROC
//PROC DRAW_RACE_WIN_SPLASH()
//PROC DRAW_RACE_LOSE_SPLASH()