// ***************************************************************************************** // ***************************************************************************************** // ***************************************************************************************** // // SCRIPT NAME : tri_gate.sch // AUTHOR : Nicholas Zippmann // DESCRIPTION : Single Player Races - Gate procs/functions file // // ***************************************************************************************** // ***************************************************************************************** // ***************************************************************************************** USING "tri_Head.sch" USING "tri_Helpers.sch" USING "stunt_plane_public.sch" USING "chase_hint_cam.sch" USING "script_oddjob_funcs.sch" // ----------------------------------- // SETUP PROCS/FUNCTIONS // ----------------------------------- PROC TRI_Gate_Init(TRI_GATE_STRUCT& sGate) CDEBUG1LN(DEBUG_TRIATHLON, "[TRI_Gate_Init] Procedure called.") sGate.vPos = TRI_Master.vDefRcrPos sGate.fRadius = TRI_GATE_CHKPNT_SCL sGate.eChkpntType = TRI_CHKPT_OFFROAD_DEFAULT sGate.fHeightCheck = TRI_GATE_HEIGHT_CHECK // To Fix Bug # 666112 - DS sGate.bIsFading = FALSE ENDPROC PROC TRI_Gate_Setup(TRI_GATE_STRUCT& sGate, VECTOR vPos, FLOAT fRadius, TRI_RACE_CHECKPOINT_TYPE eChkpntType, BOOL bPlaySound = TRUE) //DEBUG_MESSAGE("TRI_Gate_Setup") sGate.vPos = vPos sGate.fRadius = fRadius sGate.eChkpntType = eChkpntType IF bPlaySound SET_TRI_GATE_FLAG(sGate,TRI_RACE_GATE_FLAG_PLAY_SOUND) ENDIF ENDPROC PROC TRI_Gate_Set_Condition_Flag(TRI_GATE_STRUCT& sGate, ENUM_TO_INT iFlag) SET_BITMASK_AS_ENUM(sGate.iGateFlags, iFlag) ENDPROC PROC TRI_Gate_Clear_Condition_Flag(TRI_GATE_STRUCT& sGate, ENUM_TO_INT iFlag) CLEAR_BITMASK_AS_ENUM(sGate.iGateFlags, iFlag) ENDPROC FUNC BOOL TRI_Gate_Check_Condition_Flag(TRI_GATE_STRUCT& sGate, ENUM_TO_INT iFlag) RETURN IS_BITMASK_AS_ENUM_SET(sGate.iGateFlags, iFlag) ENDFUNC // ----------------------------------- // CREATION PROCS/FUNCTIONS // ----------------------------------- FUNC BOOL TRI_Gate_Blip_Create(TRI_GATE_STRUCT& sGate, BLIP_SPRITE eBlipSprite = RADAR_TRACE_INVALID, FLOAT fScale = 1.0, INT iCurGate = -1, INT iNumGates = -1) //DEBUG_MESSAGE("TRI_Gate_Blip_Create") IF NOT TRI_Blip_Coord_Create(sGate.Blip, sGate.vPos, eBlipSprite, fScale, iCurGate, iNumGates) DEBUG_MESSAGE("TRI_Gate_Blip_Create: Failed to create gate blip!") RETURN FALSE ENDIF RETURN TRUE ENDFUNC PROC TRI_Gate_Blip_Destroy(TRI_GATE_STRUCT& sGate) //DEBUG_MESSAGE("TRI_Gate_Blip_Destroy") TRI_Blip_Destroy(sGate.Blip) ENDPROC FUNC BOOL TRI_Gate_Chkpnt_Create(VECTOR vPrevGate, TRI_GATE_STRUCT& sGate, VECTOR vPointAt, FLOAT fScale = TRI_GATE_CHKPNT_SCL) //DEBUG_MESSAGE("TRI_Gate_Chkpnt_Create") //IF NOT TRI_Chkpnt_Create(sGate.Chkpnt, sGate.eChkpntType, sGate.vPos, vPointAt, fScale) IF NOT TRI_Chkpnt_Create(vPrevGate, sGate, vPointAt, fScale) DEBUG_MESSAGE("TRI_Gate_Chkpnt_Create: Failed to create gate checkpoint!") RETURN FALSE ENDIF RETURN TRUE ENDFUNC PROC TRI_Gate_Chkpnt_Destroy(TRI_GATE_STRUCT& sGate) //DEBUG_MESSAGE("TRI_Gate_Chkpnt_Destroy") TRI_Chkpnt_Destroy(sGate.Chkpnt) ENDPROC // DEBUG DRAW FUNCTION FOR GATE CLEARING (STUNT PLANE RACES) PROC DRAW_STUNT_TARGET(VECTOR vCenter, VECTOR vOrtho, FLOAT fSmallRadius, FLOAT fLargeRadius) SCRIPT_ASSERT("Running Draw Stunt Target") VECTOR vVertices[16] VECTOR vRight = CROSS_PRODUCT(vOrtho, <<0,0,1>>) VECTOR vSmallProj = fSmallRadius * vRight VECTOR vLargeProj = fLargeRadius * vRight INT iInnerVert, iOuterVert INT i // Determine horizontal crosshair verts. vVertices[ 0] = vCenter + vSmallProj vVertices[ 4] = vCenter - vSmallProj vVertices[ 8] = vCenter + vLargeProj vVertices[12] = vCenter - vLargeProj VECTOR vUp = CROSS_PRODUCT(vOrtho, vRight) vSmallProj = fSmallRadius * vUp vLargeProj = fLargeRadius * vUp // Determine vertical crosshair verts. vVertices[ 2] = vCenter + vSmallProj vVertices[ 6] = vCenter - vSmallProj vVertices[10] = vCenter + vLargeProj vVertices[14] = vCenter - vLargeProj vSmallProj = GET_VECTOR_OF_LENGTH((vRight + vUp) / 2.0, fSmallRadius) vLargeProj = GET_VECTOR_OF_LENGTH((vRight + vUp) / 2.0, fLargeRadius) // Determine vertical vert set 1. vVertices[ 1] = vCenter + vSmallProj vVertices[ 5] = vCenter - vSmallProj vVertices[ 9] = vCenter + vLargeProj vVertices[13] = vCenter - vLargeProj vSmallProj -= vRight * (fSmallRadius * 1.414) vLargeProj -= vRight * (fLargeRadius * 1.414) // Determine vertical vert set 2. vVertices[ 3] = vCenter + vSmallProj vVertices[ 7] = vCenter - vSmallProj vVertices[11] = vCenter + vLargeProj vVertices[15] = vCenter - vLargeProj // Draw the shape. REPEAT 8 i // Draw the radial line. DRAW_DEBUG_LINE(vCenter, vVertices[i+8], 127, 0, 0, 255) IF i = 7 iInnerVert = 0 iOuterVert = 8 ELSE iInnerVert = i + 1 iOuterVert = i + 9 ENDIF // Draw the inner & outer lines. DRAW_DEBUG_LINE(vVertices[i ], vVertices[iInnerVert], 0, 200, 0, 255) DRAW_DEBUG_LINE(vVertices[i+8], vVertices[iOuterVert], 0, 0, 200, 255) ENDREPEAT ENDPROC PROC DRAW_ENTITY_AXES(ENTITY_INDEX myIndex, FLOAT fscale) VECTOR vFront, vSide, vUp, vPos GET_ENTITY_MATRIX(myIndex, vFront, vSide, vUp, vPos) DRAW_DEBUG_LINE(vPos, vPos + fScale * vSide, 255, 0, 0, 255) DRAW_DEBUG_LINE(vPos, vPos + fScale * vFront, 255, 0, 0, 255) DRAW_DEBUG_LINE(vPos, vPos + fScale * vUp, 255, 0, 0, 255) ENDPROC // ----------------------------------- // HELPER PROCS/FUNCTIONS // ----------------------------------- /// PURPOSE: /// Tracks when a racer ped has crossed a checkpoint. /// PARAMS: /// race - A reference to a struct containing all race data. /// GateCur - The current checkpoint. /// Driver - The ped being checked against the current checkpoint. /// iRacerIndex - The index of the racer (ped+vehicle) in the racer array. /// RETURNS: /// FUNC TRI_RACE_GATE_STATUS TRI_CHECK_RACER_GATE_STATUS(TRI_RACE_STRUCT &race, TRI_GATE_STRUCT& GateCur, PED_INDEX Driver, INT iRacerIndex) #IF NOT DEFINED(bAudioPlayedLastGate) BOOL bAudioPlayedLastGate bAudioPlayedLastGate = bAudioPlayedLastGate #ENDIF IF IS_ENTITY_DEAD(Driver) // No need to go through the logic below. The driver is dead, so the driver's gate status is invalid. RETURN TRI_RACE_GATE_STATUS_INVALID ENDIF CONST_FLOAT fInnerRadius 110.0 //squared CONST_FLOAT fOutterRadius 900.0 //squared // Ensure the player meets the requirements of the current race leg when trying to cross a gate. IF (GateCur.eChkpntType = TRI_CHKPT_TRI_BIKE) OR (GateCur.eChkpntType = TRI_CHKPT_TRI_SECOND_TRANS) // Require the player to be in a vehicle when clearing bike gates. IF NOT IS_PED_IN_ANY_VEHICLE(Driver) IF (GateCur.eChkpntType = TRI_CHKPT_TRI_SECOND_TRANS AND NOT IS_PED_RAGDOLL(Driver)) OR GateCur.eChkpntType <> TRI_CHKPT_TRI_SECOND_TRANS RETURN TRI_RACE_GATE_STATUS_INVALID ENDIF ELSE // The player is in a vehicle, so check if the vehicle is a tribike. IF NOT ( IS_PED_IN_MODEL(Driver, TRIBIKE) OR IS_PED_IN_MODEL(Driver, TRIBIKE2) OR IS_PED_IN_MODEL(Driver, TRIBIKE3) ) RETURN TRI_RACE_GATE_STATUS_INVALID ENDIF ENDIF ELSE // Require the player to be out of a vehicle when clearing swim and run gates. IF IS_PED_IN_ANY_VEHICLE(Driver) OR IS_PED_GETTING_INTO_A_VEHICLE(Driver) RETURN TRI_RACE_GATE_STATUS_INVALID ENDIF ENDIF // Variables used in the swim gate check below (CASE TRI_CHKPT_TRI_SWIM). VECTOR vBuoy VECTOR vRacerPos VECTOR vBuoyToGate VECTOR vBuoyToRacer FLOAT fDot // Since there are different types of race legs and gates, check the type of the current gate to appropriately check its status. SWITCH GateCur.eChkpntType // LAST GATE: These gates are angled areas so their orientation can be lined up with that of the race path. CASE TRI_CHKPT_TRI_FINISH SWITCH INT_TO_ENUM(TRIATHLON_RACE_INDEX, TRI_Master.iRaceCur) CASE TRIATHLON_RACE_ALAMO_SEA IF IS_ENTITY_IN_ANGLED_AREA(Driver, << 1753.24, 3895.40, 33.82 >>, << 1762.06, 3900.40, 40.81 >>, 9.7) IF Driver <> PLAYER_PED_ID() IF Race.Racer[iRacerIndex].iRank = 1 ADD_TRI_NEWS_EVENT( TRNE_NPC_WON_RACE ) ENDIF ENDIF KILL_RACE_HINT_CAM(localChaseHintCamStruct) RETURN TRI_RACE_GATE_STATUS_PASS ENDIF BREAK CASE TRIATHLON_RACE_VESPUCCI IF IS_ENTITY_IN_ANGLED_AREA(Driver, << -1327.06, -1041.91, 6.40 >>, << -1336.80, -1047.55, 13.47 >>, 9.7) IF Driver <> PLAYER_PED_ID() IF Race.Racer[iRacerIndex].iRank = 1 ADD_TRI_NEWS_EVENT( TRNE_NPC_WON_RACE ) ENDIF ENDIF KILL_RACE_HINT_CAM(localChaseHintCamStruct) RETURN TRI_RACE_GATE_STATUS_PASS ENDIF BREAK CASE TRIATHLON_RACE_IRONMAN IF IS_ENTITY_IN_ANGLED_AREA(Driver, << -2298.94, 459.13, 173.47 >>, << -2310.46, 460.32, 180.47 >>, 9.7) // Ironman IF Driver <> PLAYER_PED_ID() IF Race.Racer[iRacerIndex].iRank = 1 ADD_TRI_NEWS_EVENT( TRNE_NPC_WON_RACE ) ENDIF ENDIF KILL_RACE_HINT_CAM(localChaseHintCamStruct) RETURN TRI_RACE_GATE_STATUS_PASS ENDIF BREAK ENDSWITCH BREAK // BIKE-TO-RUN GATE: These gates are angled areas so their orientation can be lined up with that of the race path. CASE TRI_CHKPT_TRI_SECOND_TRANS SWITCH INT_TO_ENUM(TRIATHLON_RACE_INDEX, TRI_Master.iRaceCur) CASE TRIATHLON_RACE_ALAMO_SEA IF IS_ENTITY_IN_ANGLED_AREA(Driver, << 1974.43, 3887.36, 31.35 >>, << 1961.63, 3879.74, 38.30 >>, 18.0) IF Driver <> PLAYER_PED_ID() IF Race.Racer[iRacerIndex].iRank = 1 ADD_TRI_NEWS_EVENT( TRNE_NPC_WON_BIKE ) ENDIF ENDIF RETURN TRI_RACE_GATE_STATUS_PASS ENDIF BREAK CASE TRIATHLON_RACE_VESPUCCI IF IS_ENTITY_IN_ANGLED_AREA(Driver, << -1172.74, -844.98, 13.36 >>, << -1166.32, -856.93, 20.16 >>, 18.0) IF Driver <> PLAYER_PED_ID() IF Race.Racer[iRacerIndex].iRank = 1 ADD_TRI_NEWS_EVENT( TRNE_NPC_WON_BIKE ) ENDIF ENDIF RETURN TRI_RACE_GATE_STATUS_PASS ENDIF BREAK CASE TRIATHLON_RACE_IRONMAN IF IS_ENTITY_IN_ANGLED_AREA(Driver, << -1283.32, 274.68, 63.78 >>, << -1275.79, 283.86, 70.86 >>, 12.0) // Ironman IF Driver <> PLAYER_PED_ID() IF Race.Racer[iRacerIndex].iRank = 1 ADD_TRI_NEWS_EVENT( TRNE_NPC_WON_BIKE ) ENDIF ENDIF RETURN TRI_RACE_GATE_STATUS_PASS ENDIF BREAK ENDSWITCH BREAK // SWIM GATE CASE TRI_CHKPT_TRI_SWIM vBuoy = GET_ENTITY_COORDS(race.objSwimLegBuoys[race.Racer[iRacerIndex].iGateCur]) vRacerPos = GET_ENTITY_COORDS(Driver) vBuoyToGate = GateCur.vPos - vBuoy vBuoyToRacer = vRacerPos - vBuoy fDot = DOT_PRODUCT(vBuoyToGate, vBuoyToRacer) IF (IS_ENTITY_AT_COORD(Driver, GateCur.vPos, <>) AND fDot >= 0) IF (Driver = PLAYER_PED_ID()) KILL_RACE_HINT_CAM(localChaseHintCamStruct) // do gate clear audio here: IF IS_TRI_GATE_FLAG_SET( GateCur,TRI_RACE_GATE_FLAG_PLAY_SOUND) PLAY_SOUND_FRONTEND(-1, STUNT_PLANE_SFX_CHECKPOINT_CLEAR, "HUD_MINI_GAME_SOUNDSET") ENDIF ENDIF RETURN TRI_RACE_GATE_STATUS_PASS ENDIF BREAK // DEFAULT: All other gates not handled above. DEFAULT IF IS_ENTITY_AT_COORD(Driver, GateCur.vPos, <>) IF (Driver = PLAYER_PED_ID()) KILL_RACE_HINT_CAM(localChaseHintCamStruct) // do gate clear audio here: IF IS_TRI_GATE_FLAG_SET( GateCur,TRI_RACE_GATE_FLAG_PLAY_SOUND) PLAY_SOUND_FRONTEND(-1, STUNT_PLANE_SFX_CHECKPOINT_CLEAR, "HUD_MINI_GAME_SOUNDSET") ENDIF ELSE IF GateCur.eChkpntType = TRI_CHKPT_TRI_FIRST_TRANS IF Driver <> PLAYER_PED_ID() IF Race.Racer[iRacerIndex].iRank = 1 ADD_TRI_NEWS_EVENT( TRNE_NPC_WON_SWIM ) ENDIF ENDIF ENDIF ENDIF RETURN TRI_RACE_GATE_STATUS_PASS ENDIF BREAK ENDSWITCH RETURN TRI_RACE_GATE_STATUS_INVALID ENDFUNC #IF IS_DEBUG_BUILD PROC TRI_Race_Gate_Draw_Marker_Type(MARKER_TYPE MarkerType, VECTOR scrVecPosition, VECTOR scrVecDirection, BOOL bIsActive, FLOAT fDefScale) FLOAT fScale = 0.7 FLOAT fMarkerHeight = fDefScale INT iMarkerRed = 0 INT iMarkerGreen = 0 INT iMarkerBlue = 0 IF biSActive fScale = 1.0 iMarkerRed = 255 fMarkerHeight *= 3 ELSE iMarkerRed = 254 iMarkerGreen = 207 iMarkerBlue = 12 ENDIF SWITCH MarkerType CASE MARKER_ARROW DRAW_MARKER(MarkerType, scrVecPosition, scrVecDirection, <<0,0,90>>, <>*fScale, iMarkerRed, iMarkerGreen, iMarkerBlue, 100, FALSE, TRUE) BREAK CASE MARKER_FLAG DRAW_MARKER(MarkerType, scrVecPosition, scrVecDirection, <<0,0,0>>, <>*fScale, iMarkerRed, iMarkerGreen, iMarkerBlue, 100, FALSE, FALSE) BREAK CASE MARKER_CYLINDER DRAW_MARKER(MarkerType, scrVecPosition, scrVecDirection, <<0,0,0>>, <>*fScale, iMarkerRed, iMarkerGreen, iMarkerBlue, 100) BREAK CASE MARKER_RING DRAW_MARKER(MarkerType, scrVecPosition, scrVecDirection, <<0,-45,0>>, <>*fScale, iMarkerRed, iMarkerGreen, iMarkerBlue, 100, FALSE, TRUE) BREAK CASE MARKER_PLANE DRAW_MARKER(MarkerType, scrVecPosition, scrVecDirection, <<0,0,0>>, <>*fScale, iMarkerRed, iMarkerGreen, iMarkerBlue, 100, FALSE, TRUE) BREAK DEFAULT DEBUG_MESSAGE("TRI_Race_Gate_Draw_Marker_Type: bad MarkerType") BREAK ENDSWITCH ENDPROC PROC TRI_Race_Gate_Draw_Marker(TRI_GATE_STRUCT& GateCur, VECTOR vMarkerDir, BOOL bIsActive = TRUE) SWITCH GateCur.eChkpntType CASE TRI_CHKPT_OFFROAD_DEFAULT TRI_Race_Gate_Draw_Marker_Type(MARKER_ARROW, GateCur.vPos, vMarkerDir, bIsActive, TRI_GATE_CHKPNT_OFFROAD_ARROW_SCL) TRI_Race_Gate_Draw_Marker_Type(MARKER_CYLINDER, GateCur.vPos, vMarkerDir, bIsActive, TRI_GATE_CHKPNT_OFFROAD_CYLINDER_SCL) BREAK CASE TRI_CHKPT_OFFROAD_FINISH TRI_Race_Gate_Draw_Marker_Type(MARKER_FLAG, GateCur.vPos, vMarkerDir, bIsActive, TRI_GATE_CHKPNT_OFFROAD_FLAG_SCL) TRI_Race_Gate_Draw_Marker_Type(MARKER_CYLINDER, GateCur.vPos, vMarkerDir, bIsActive, TRI_GATE_CHKPNT_OFFROAD_CYLINDER_SCL) BREAK CASE TRI_CHKPT_STUNT_DEFAULT TRI_Race_Gate_Draw_Marker_Type(MARKER_RING, GateCur.vPos, vMarkerDir, bIsActive, TRI_GATE_CHKPNT_STUNT_RING_SCL) TRI_Race_Gate_Draw_Marker_Type(MARKER_PLANE, GateCur.vPos, vMarkerDir, bIsActive, TRI_GATE_CHKPNT_STUNT_PLANE_SCL) BREAK CASE TRI_CHKPT_STUNT_FINISH TRI_Race_Gate_Draw_Marker_Type(MARKER_FLAG, GateCur.vPos, vMarkerDir, bIsActive, TRI_GATE_CHKPNT_STUNT_FLAG_SCL) TRI_Race_Gate_Draw_Marker_Type(MARKER_PLANE, GateCur.vPos, vMarkerDir, bIsActive, TRI_GATE_CHKPNT_STUNT_PLANE_SCL) BREAK CASE TRI_CHKPT_TRI_SWIM TRI_Race_Gate_Draw_Marker_Type(MARKER_ARROW, GateCur.vPos, vMarkerDir, bIsActive, TRI_GATE_CHKPNT_TRI_ARROW_SCL) BREAK CASE TRI_CHKPT_TRI_BIKE TRI_Race_Gate_Draw_Marker_Type(MARKER_ARROW, GateCur.vPos, vMarkerDir, bIsActive, TRI_GATE_CHKPNT_TRI_ARROW_SCL) TRI_Race_Gate_Draw_Marker_Type(MARKER_CYLINDER, GateCur.vPos, vMarkerDir, bIsActive, TRI_GATE_CHKPNT_TRI_CYLINDER_SCL) BREAK CASE TRI_CHKPT_TRI_RUN TRI_Race_Gate_Draw_Marker_Type(MARKER_ARROW, GateCur.vPos, vMarkerDir, bIsActive, TRI_GATE_CHKPNT_TRI_ARROW_SCL) TRI_Race_Gate_Draw_Marker_Type(MARKER_CYLINDER, GateCur.vPos, vMarkerDir, bIsActive, TRI_GATE_CHKPNT_TRI_CYLINDER_SCL) BREAK CASE TRI_CHKPT_TRI_FINISH TRI_Race_Gate_Draw_Marker_Type(MARKER_FLAG, GateCur.vPos, vMarkerDir, bIsActive, TRI_GATE_CHKPNT_TRI_FLAG_SCL) TRI_Race_Gate_Draw_Marker_Type(MARKER_CYLINDER, GateCur.vPos, vMarkerDir, bIsActive, TRI_GATE_CHKPNT_TRI_CYLINDER_SCL) BREAK CASE TRI_CHKPT_TRI_FIRST_TRANS TRI_Race_Gate_Draw_Marker_Type(MARKER_FLAG, GateCur.vPos, vMarkerDir, bIsActive, TRI_GATE_CHKPNT_TRI_FLAG_SCL) TRI_Race_Gate_Draw_Marker_Type(MARKER_CYLINDER, GateCur.vPos, vMarkerDir, bIsActive, TRI_GATE_CHKPNT_TRI_CYLINDER_SCL) BREAK CASE TRI_CHKPT_TRI_SECOND_TRANS TRI_Race_Gate_Draw_Marker_Type(MARKER_FLAG, GateCur.vPos, vMarkerDir, bIsActive, TRI_GATE_CHKPNT_TRI_FLAG_SCL) TRI_Race_Gate_Draw_Marker_Type(MARKER_CYLINDER, GateCur.vPos, vMarkerDir, bIsActive, TRI_GATE_CHKPNT_TRI_CYLINDER_SCL) BREAK DEFAULT DEBUG_MESSAGE("TRI_Race_Gate_Draw_Marker: bad eChkpntType") BREAK ENDSWITCH ENDPROC PROC TRI_Race_Gate_Draw_All_Inactive_Markers(TRI_RACE_STRUCT& Race, INT iSelected) //DEBUG_MESSAGE("TRI_Race_Gate_Draw_All_Markers") INT iGate REPEAT Race.iGateCnt iGate IF (iGate < (TRI_GATE_MAX - 2)) IF (iSelected != iGate) AND ((iSelected+1) != iGate) AND (iGate <= (iSelected+31)) AND (iGate >= (iSelected-30)) DRAW_MARKER(MARKER_CYLINDER, Race.sGate[iGate].vPos, <<0,0,0>>, <<0,0,0>>, <<10, 10, 30>>, 254, 207, 12, 100) ENDIF ENDIF IF NOT DOES_BLIP_EXIST(Race.sGate[iGate].Blip) BLIP_SPRITE eBlipSprite = RADAR_TRACE_OBJECTIVE_BLUE IF (iGate = (Race.iGateCnt - 1)) eBlipSprite = RADAR_TRACE_RACEFLAG ENDIF TRI_Blip_Coord_Create(Race.sGate[iGate].Blip, Race.sGate[iGate].vPos, eBlipSprite, TRI_GATE_BLIPNXT_SCL, iGate, Race.iGateCnt) SET_BLIP_PRIORITY(Race.sGate[iGate].Blip, BLIPPRIORITY_HIGHEST) ENDIF ENDREPEAT ENDPROC PROC TRI_Race_Gate_Create_Custom_GPS_Route(TRI_RACE_STRUCT& Race) //DEBUG_MESSAGE("TRI_Race_Gate_Draw_All_Markers") CLEAR_GPS_CUSTOM_ROUTE() START_GPS_CUSTOM_ROUTE(HUD_COLOUR_YELLOW, TRUE, FALSE) INT iGate REPEAT Race.iGateCnt iGate ADD_POINT_TO_GPS_CUSTOM_ROUTE(Race.sGate[iGate].vPos) ENDREPEAT SET_GPS_CUSTOM_ROUTE_RENDER(TRUE, 18, 30) ENDPROC #ENDIF // END OF FILE! DO NOT ADD ANYTHING BELOW THIS LINE!