Files
2025-09-29 00:52:08 +02:00

2995 lines
88 KiB
Scheme
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// *****************************************************************************************
// *****************************************************************************************
// *****************************************************************************************
//
// SCRIPT NAME : TRI_Helpers.sch
// AUTHOR : Nicholas Zippmann
// DESCRIPTION : Single Player Races - Helper procs/functions file
//
// *****************************************************************************************
// *****************************************************************************************
// *****************************************************************************************
USING "event_public.sch"
USING "TRI_Head.sch"
USING "lineactivation.sch" // Include this so it compiles in release, for using GET_OFFSET_FROM_COORD_IN_WORLD_COORDS
USING "minigames_helpers.sch"
USING "script_camera.sch"
USING "tri_ai.sch"
CONST_INT MAX_DISTANCE_FROM_BIKE 5
CHASE_HINT_CAM_STRUCT localChaseHintCamStruct
CAMERA_INDEX camSynchScene
INT iSynchSceneIntro
#IF NOT DEFINED(TASK_TRI_RACER_TO_FOLLOW_RACE_COURSE)
PROC TASK_TRI_RACER_TO_FOLLOW_RACE_COURSE(TRI_RACE_STRUCT& Race, VECTOR vCurrentGatePos, INT iRacerIndex)
CPRINTLN(DEBUG_TRIATHLON, "[spr_helpers.sch->TASK_TRI_RACER_TO_FOLLOW_RACE_COURSE] Dummy procedure called.")
// Account for unreferenced variables.
Race.iGateCnt = Race.iGateCnt
vCurrentGatePos = vCurrentGatePos
iRacerIndex = iRacerIndex
ENDPROC
#ENDIF
ENUM TRI_GENERAL_BITS
TRI_SCORECARD_INIT = BIT0,
TRI_SCORECARD_STREAMED = BIT1,
TRI_PLAYED_STINGER = BIT2,
TRI_FORCE_GATE_ACTIVATION = BIT3,
TRI_FIRST_GATE_ACTIVATION = BIT4,
TRI_PRINTED_IDLE_WARNING = BIT5,
TRI_END_RETURN_TO_GAMPLAY_CAM = BIT6,
TRI_ENDSCREEN_READY = BIT7,
TRI_PLAYER_VEHICLE_SAVED =BIT8
ENDENUM
ENUM TRI_COUNTDOWN_STAGE
TRI_COUNTDOWN_STAGE_INIT,
TRI_COUNTDOWN_RUN,
TRI_COUNTDOWN_STAGE_WAIT
ENDENUM
/// PURPOSE: Bitfield enum for controlling help and objective prints
ENUM TRI_HELP_AND_OBJECTIVES
TRI_DIST_HELP = BIT0,
TRI_DAMG_HELP = BIT1,
TRI_WARN_HELP = BIT2,
TRI_FAIL_HELP = BIT3,
TRI_RETURN_WARN = BIT4,
TRI_RETURN_FAIL = BIT5,
TRI_RETURN_DES = BIT6,
TRI_EXIT_WARN = BIT7,
TRI_EXIT_FAIL = BIT8,
TRI_EXIT_FAIL2 = BIT9,
TRI_TXIT_WARN = BIT10,
TRI_TXIT_FAIL = BIT11,
TRI_MOVE_WARN = BIT12,
TRI_MOVE_FAIL = BIT13,
TRI_HELP_WANT = BIT14
ENDENUM
structTimer exitTimer
structTimer waterTimer
structTimer ExitVehicleTimer
INT iSPRGeneralBits
INT TRI_HELP_BIT
TRI_HINT_CAM_STRUCT TRI_HINT_CAM
COUNTDOWN_UI TRI_CountDownUI
TRI_COUNTDOWN_STAGE eCountdownStage = TRI_COUNTDOWN_STAGE_INIT
// -----------------------------------
// GLOBAL PROCS/FUNCTIONS
// -----------------------------------
PROC SET_TRI_SCENARIO_PAPARAZZI_PEDS()
CPRINTLN(DEBUG_TRIATHLON, "[tri_helpers.sch :: SET_TRI_SCENARIO_PAPARAZZI_PEDS] called")
PED_INDEX pedsNearby[30]
INT iNearbyPeds
SET_SCENARIO_PEDS_TO_BE_RETURNED_BY_NEXT_COMMAND(TRUE)
iNearbyPeds = GET_PED_NEARBY_PEDS(PLAYER_PED_ID(), pedsNearby)
CPRINTLN(DEBUG_TRIATHLON, "[tri_helpers.sch :: SET_TRI_SCENARIO_PAPARAZZI_PEDS] iNearbyPeds=", iNearbyPeds)
INT p=0
WHILE p < iNearbyPeds
IF DOES_ENTITY_EXIST(pedsNearby[p])
MODEL_NAMES eModel = GET_ENTITY_MODEL(pedsNearby[p])
IF eModel = A_M_M_PAPARAZZI_01 OR eModel = U_M_Y_PAPARAZZI
CPRINTLN(DEBUG_TRIATHLON, "[tri_helpers.sch :: SET_TRI_SCENARIO_PAPARAZZI_PEDS] Setting pedsNearby[", p, "] with new clipset")
IF NOT IS_PED_INJURED(pedsNearby[p])
#IF IS_DEBUG_BUILD
TEXT_LABEL_7 texPed = "ped_"
texPed += p
DEBUG_RECORD_SPHERE(texPed, GET_ENTITY_COORDS(pedsNearby[p]), 1.0, (<<0,0,1>>))
#ENDIF
SET_PED_WEAPON_MOVEMENT_CLIPSET(pedsNearby[p], "random@escape_paparazzi@standing@")
ENDIF
ENDIF
ENDIF
p++
ENDWHILE
ENDPROC
FUNC BOOL ORR_DOES_RACE_REQUIRE_MOTORCYCLE()
IF TRI_Master.eRaceType != TRI_RACE_TYPE_OFFROAD
RETURN FALSE
ENDIF
IF (TRI_Master.iRaceCur = 1
OR TRI_Master.iRaceCur = 4)
RETURN FALSE
ENDIF
RETURN TRUE
ENDFUNC
FUNC MODEL_NAMES ORR_GET_RANDOM_MOTORCYCLE_MODEL()
INT randInt = GET_RANDOM_INT_IN_RANGE(0, 10000) % 2
SWITCH (randInt)
CASE 0
RETURN A_M_Y_MOTOX_01
CASE 1
RETURN A_M_Y_MOTOX_02
DEFAULT
CDEBUG1LN(DEBUG_OR_RACES, "WARNING! Random motorcycle model returned default value")
RETURN A_M_Y_MOTOX_01
ENDSWITCH
ENDFUNC
FUNC INT TRI_Global_BestRank_Get(INT iRace)
INT iBestRank = 0
iBestRank = g_savedGlobals.sTriathlonData.iBestRank[iRace]
RETURN iBestRank
ENDFUNC
PROC TRI_Global_BestRank_Set(INT iRace, INT iBestRank)
CDEBUG2LN(DEBUG_TRIATHLON, "TRI_Global_BestRank_Set :: iRace=", iRace, ", iBestRank=", iBestRank)
g_savedGlobals.sTriathlonData.iBestRank[iRace] = iBestRank
ENDPROC
FUNC FLOAT TRI_Global_BestTime_Get(INT iRace)
FLOAT fBestTime
fBestTime = g_savedGlobals.sTriathlonData.fBestTime[iRace]
RETURN fBestTime
ENDFUNC
PROC TRI_Global_BestTime_Set(INT iRace, FLOAT fBestTime)
g_savedGlobals.sTriathlonData.fBestTime[iRace] = fBestTime
ENDPROC
// -----------------------------------
// DEBUG PROCS/FUNCTIONS
// -----------------------------------
PROC TRI_Racer_DebugPrint(TRI_RACER_STRUCT& Racer)
//DEBUG_MESSAGE("TRI_Racer_DebugPrint")
PRINTSTRING("DRIVER: ")
PRINTINT(NATIVE_TO_INT(Racer.Driver))
PRINTSTRING(" ")
IF DOES_ENTITY_EXIST(Racer.Driver)
PRINTSTRING("DOES EXIST & ")
IF NOT IS_ENTITY_DEAD(Racer.Driver)
PRINTSTRING("IS ALIVE")
ELSE
PRINTSTRING("ISN'T ALIVE")
ENDIF
ELSE
PRINTSTRING("DOESN'T EXIST")
ENDIF
PRINTNL()
PRINTSTRING("VEHICLE: ")
PRINTINT(NATIVE_TO_INT(Racer.Vehicle))
PRINTSTRING(" ")
IF DOES_ENTITY_EXIST(Racer.Vehicle)
PRINTSTRING("DOES EXIST & ")
IF NOT IS_ENTITY_DEAD(Racer.Vehicle)
PRINTSTRING("IS ALIVE")
ELSE
PRINTSTRING("ISN'T ALIVE")
ENDIF
ELSE
PRINTSTRING("DOESN'T EXIST")
ENDIF
PRINTNL()
ENDPROC
// -----------------------------------
// SCENE PROCS/FUNCTIONS
// -----------------------------------
FUNC BOOL TRI_ACTIVATE_INTRO_SKY_CAM(CAMERA_INDEX &camTriSky, VECTOR vEndPos, VECTOR vEndRot)
UNUSED_PARAMETER( vEndPos )
UNUSED_PARAMETER( vEndRot )
IF NOT DOES_CAM_EXIST(camTriSky)
CPRINTLN(DEBUG_TRIATHLON, "[tri_helpers.sch::TRI_ACTIVATE_INTRO_SKY_CAM] intro cam set")
// VECTOR vStartPos, vStartRot
// vStartPos = GET_GAMEPLAY_CAM_COORD()
// vStartRot = GET_GAMEPLAY_CAM_ROT()
//camTriSky = CREATE_CAMERA_WITH_PARAMS(CAMTYPE_SCRIPTED, vEndPos, vEndRot, 50, TRUE)
//RENDER_SCRIPT_CAMS( TRUE, FALSE, 0 )
//SET_CAM_PARAMS(camTriSky, vEndPos, vEndRot, 50, 2700)
//SET_CAM_ACTIVE( camTriSky, TRUE )
//RENDER_SCRIPT_CAMS(TRUE, TRUE)
//UNUSED_PARAMETER(vEndPos)
//UNUSED_PARAMETER(vEndRot)
VECTOR vSceneLoc, vSceneOrient
//
// SWITCH eCurrentTriRace
// CASE TRIATHLON_RACE_ALAMO_SEA
// vSceneLoc = <<2424.7747, 4284.3188, 34.5886>>
// vSceneOrient = <<0.0, 0.0, 257.9987>>
// BREAK
// CASE TRIATHLON_RACE_VESPUCCI
// vSceneLoc = <<-1231.6990, -2049.9199, 12.8787>>
// vSceneOrient = <<0.0, 0.0, 254.8048>>
// BREAK
// CASE TRIATHLON_RACE_IRONMAN
// vSceneLoc = <<1593.2665, 3812.9990, 33.4477>>
// vSceneOrient = <<0.0, 0.0, 209.8786>>
// BREAK
// ENDSWITCH
SET_ENTITY_AS_MISSION_ENTITY(Tri_Master.oTable, TRUE, TRUE)
vSceneLoc = GET_ENTITY_COORDS(Tri_Master.oTable, FALSE)
vSceneOrient = <<0.0, 0.0, GET_ENTITY_HEADING(Tri_Master.oTable)>>
UNUSED_PARAMETER( camSynchScene )
iSynchSceneIntro = CREATE_SYNCHRONIZED_SCENE( vSceneLoc, vSceneOrient )
camTriSky = CREATE_CAM("DEFAULT_ANIMATED_CAMERA", FALSE)
SET_CAM_ACTIVE( camTriSky, TRUE )
RENDER_SCRIPT_CAMS( TRUE, FALSE )
PLAY_SYNCHRONIZED_CAM_ANIM( camTriSky, iSynchSceneIntro, "_table_sign_in_cam", "mini@triathlonintro" )
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
TASK_SYNCHRONIZED_SCENE( PLAYER_PED_ID(), iSynchSceneIntro, "mini@triathlonintro", "_table_sign_in_michael", INSTANT_BLEND_IN, INSTANT_BLEND_OUT )
// Ensure the player isn't holding a weapon at the start of the race.
SET_CURRENT_PED_WEAPON(PLAYER_PED_ID(), WEAPONTYPE_UNARMED)
// NOTE: This looks odd, but at the time it was necessary to avoid the player still
// showing the weapon on his hand despite not being equipped.
SET_PED_CURRENT_WEAPON_VISIBLE(PLAYER_PED_ID(), FALSE)
SET_PED_CURRENT_WEAPON_VISIBLE(PLAYER_PED_ID(), TRUE)
ENDIF
IF NOT IS_PED_INJURED(Tri_Master.pedTableGuy)
CLEAR_PED_TASKS_IMMEDIATELY(Tri_Master.pedTableGuy)
TASK_SYNCHRONIZED_SCENE(Tri_Master.pedTableGuy, iSynchSceneIntro, "mini@triathlonintro", "_table_sign_in_ped", INSTANT_BLEND_IN, INSTANT_BLEND_OUT)
FORCE_PED_AI_AND_ANIMATION_UPDATE( Tri_Master.pedTableGuy )
ENDIF
PLAY_SYNCHRONIZED_ENTITY_ANIM( Tri_Master.oClipboard, iSynchSceneIntro, "_table_sign_in_clipboard", "mini@triathlonintro", 1/*INSTANT_BLEND_IN*/ )
FORCE_ENTITY_AI_AND_ANIMATION_UPDATE( Tri_Master.oClipboard )
DISPLAY_RADAR(FALSE)
TEXT_LABEL_23 tlConvo
IF GET_CURRENT_PLAYER_PED_ENUM() = CHAR_MICHAEL
tlConvo = "MGTR_introM"
ELIF GET_CURRENT_PLAYER_PED_ENUM() = CHAR_FRANKLIN
tlConvo = "MGTR_introF"
ELIF GET_CURRENT_PLAYER_PED_ENUM() = CHAR_TREVOR
tlConvo = "MGTR_introT"
ENDIF
FLOAT fRand
fRand = GET_RANDOM_FLOAT_IN_RANGE(0, 3000)
IF fRand < 1000
tlConvo += "2"
ELIF fRand < 2000
tlConvo += "3"
ENDIF
ADD_PED_FOR_DIALOGUE(TriDialog.convoStruct, 3, Tri_Master.pedTableGuy, "TRIRACER1")
CREATE_CONVERSATION(TriDialog.convoStruct, "mgtraud", tlConvo, CONV_PRIORITY_VERY_HIGH)
RETURN TRUE
ELIF NOT IS_CAM_INTERPOLATING(camTriSky)
CPRINTLN(DEBUG_TRIATHLON, "[tri_helpers.sch::TRI_ACTIVATE_INTRO_SKY_CAM] intro cam finished interp")
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
FUNC BOOL TRI_FadeIn_Safe(INT iTime)
//DEBUG_MESSAGE("TRI_FadeIn_Safe")
IF IS_SCREEN_FADED_OUT()
DO_SCREEN_FADE_IN(iTime)
ELIF IS_SCREEN_FADED_IN()
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
FUNC BOOL TRI_FadeOut_Safe(INT iTime)
//DEBUG_MESSAGE("TRI_FadeOut_Safe")
IF IS_SCREEN_FADED_IN()
DO_SCREEN_FADE_OUT(iTime)
ELIF IS_SCREEN_FADED_OUT()
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
// -----------------------------------
// MARKER PROCS/FUNCTIONS
// -----------------------------------
PROC TRI_Blip_Destroy(BLIP_INDEX& Blip)
//DEBUG_MESSAGE("TRI_Blip_Destroy")
IF DOES_BLIP_EXIST(Blip)
REMOVE_BLIP(Blip)
ENDIF
ENDPROC
FUNC BOOL TRI_Blip_Coord_Create(BLIP_INDEX& Blip, VECTOR vPos, BLIP_SPRITE eBlipSprite = RADAR_TRACE_INVALID, FLOAT fScale = 1.0, INT iCurGate = -1, INT iNumGates = -1)
//DEBUG_MESSAGE("TRI_Blip_Coord_Create")
TRI_Blip_Destroy(Blip)
Blip = ADD_BLIP_FOR_COORD(vPos)
IF NOT DOES_BLIP_EXIST(Blip)
DEBUG_MESSAGE("TRI_Blip_Coord_Create: Failed to create blip!")
RETURN FALSE
ENDIF
//Set last blip to checkered flag
IF (iCurGate = (iNumGates - 1))
SET_BLIP_SPRITE(Blip, RADAR_TRACE_RACEFLAG)
ENDIF
UNUSED_PARAMETER(eBlipSprite)
SET_BLIP_SCALE(Blip, fScale)
SET_BLIP_DISPLAY(Blip, DISPLAY_BOTH)
IF iCurGate != -1
AND iNumGates != -1
BEGIN_TEXT_COMMAND_SET_BLIP_NAME("GATEBLIP")
ADD_TEXT_COMPONENT_INTEGER(iCurGate)
ADD_TEXT_COMPONENT_INTEGER(iNumGates)
END_TEXT_COMMAND_SET_BLIP_NAME(Blip)
ELSE
SET_BLIP_NAME_FROM_TEXT_FILE(Blip, "GATEBLIPDEF")
ENDIF
RETURN TRUE
ENDFUNC
FUNC BOOL TRI_Blip_Entity_Create(BLIP_INDEX& Blip, ENTITY_INDEX Entity, FLOAT fScale = 1.0)
//DEBUG_MESSAGE("TRI_Blip_Entity_Create")
TRI_Blip_Destroy(Blip)
IF IS_ENTITY_DEAD(Entity)
DEBUG_MESSAGE("TRI_Blip_Entity_Create: Entity is not alive!")
RETURN FALSE
ENDIF
Blip = ADD_BLIP_FOR_ENTITY(Entity)
IF NOT DOES_BLIP_EXIST(Blip)
DEBUG_MESSAGE("TRI_Blip_Entity_Create: Failed to create blip!")
RETURN FALSE
ENDIF
SET_BLIP_COLOUR(blip, BLIP_COLOUR_BLUE)
BEGIN_TEXT_COMMAND_SET_BLIP_NAME("OFF_OPP")
END_TEXT_COMMAND_SET_BLIP_NAME(Blip)
SET_BLIP_SCALE(Blip, fScale)
CPRINTLN(DEBUG_TRIATHLON, "TRI_Blip_Entity_Create: blip created! fScale: ", fScale)
RETURN TRUE
ENDFUNC
PROC TRI_Chkpnt_Destroy(CHECKPOINT_INDEX& Chkpnt)
//DEBUG_MESSAGE("TRI_Chkpnt_Destroy")
IF (Chkpnt <> NULL)
DELETE_CHECKPOINT(Chkpnt)
SET_TRI_CONTROL_FLAG(TCF_UNPATCH_CORONA)
Chkpnt = NULL
ENDIF
ENDPROC
FUNC CHECKPOINT_TYPE TRI_Get_ChnkPnt_Type_From_TRI_Type(TRI_RACE_CHECKPOINT_TYPE eChkpntType)
SWITCH eChkpntType
CASE TRI_CHKPT_TRI_SWIM
RETURN CHECKPOINT_RACE_TRI_SWIM_CHEVRON_1
BREAK
CASE TRI_CHKPT_TRI_BIKE
RETURN CHECKPOINT_RACE_TRI_CYCLE_CHEVRON_1
BREAK
CASE TRI_CHKPT_TRI_RUN
RETURN CHECKPOINT_RACE_TRI_RUN_CHEVRON_1
BREAK
CASE TRI_CHKPT_TRI_FINISH
RETURN CHECKPOINT_RACE_TRI_RUN_FLAG
//RETURN CHECKPOINT_RACE_AIR_FLAG // Ideally, the top half of this checkpoint visually works as a finish line.
BREAK
CASE TRI_CHKPT_TRI_FIRST_TRANS
// RETURN CHECKPOINT_RACE_TRI_SWIM_LAP
RETURN CHECKPOINT_RACE_TRI_SWIM_FLAG
BREAK
CASE TRI_CHKPT_TRI_SECOND_TRANS
// RETURN CHECKPOINT_RACE_TRI_CYCLE_LAP
// Prop_MK_Tri_Run
RETURN CHECKPOINT_RACE_TRI_CYCLE_FLAG
BREAK
ENDSWITCH
RETURN CHECKPOINT_RACE_GROUND_CHEVRON_1
ENDFUNC
// Copied from TRI_Gate.sch
FUNC BOOL TRI_Helpers_Check_Condition_Flag(TRI_GATE_STRUCT& sGate, ENUM_TO_INT iFlag)
RETURN IS_BITMASK_AS_ENUM_SET(sGate.iGateFlags, iFlag)
ENDFUNC
//******************************************************************************
//******************************************************************************
// Hint Cam Stuff
//******************************************************************************
//******************************************************************************
PROC TRI_INIT_HINT_CAM()
TRI_HINT_CAM.bActive = FALSE
// TRI_HINT_CAM.Entity = NULL
TRI_HINT_CAM.Coord = <<0,0,0>>
// TRI_HINT_CAM.HintType =
TRI_HINT_CAM.CustomCam = NULL
ENDPROC
PROC TRI_SET_HINT_CAM_ACTIVE(BOOL bActive)
TRI_HINT_CAM.bActive = bActive
SET_CINEMATIC_BUTTON_ACTIVE(!bActive)
ENDPROC
PROC TRI_SET_HINT_CAM_COORD(VECTOR vThisEntity)
KILL_RACE_HINT_CAM(localChaseHintCamStruct)
TRI_HINT_CAM.Coord = vThisEntity
ENDPROC
PROC TRI_CLEAR_HINT_CAM_TARGET()
TRI_HINT_CAM.Coord = <<0,0,0>>
ENDPROC
PROC TRI_KILL_HINT_CAM()
TRI_INIT_HINT_CAM()
SET_CINEMATIC_BUTTON_ACTIVE(TRUE)
ENDPROC
FUNC BOOL TRI_IS_HINT_CAM_BUTTON_PRESSED()
RETURN IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_VEH_CIN_CAM)// OR IS_CONTROL_PRESSED(FRONTEND_CONTROL, INPUT_FRONTEND_CANCEL)//IS_BUTTON_PRESSED(PAD1, CIRCLE)
ENDFUNC
PROC TRI_UPDATE_HINT_CAM()
IF NOT TRI_HINT_CAM.bActive
EXIT
ENDIF
// VECTOR vCheckpointToTest = TRI_GET_CURRENT_CHECKPOINT()
// IF NOT ARE_VECTORS_EQUAL(TRI_HINT_CAM.Coord, vCheckpointToTest)
// TRI_SET_HINT_CAM_COORD(vCheckpointToTest)
// IF DOES_CAM_EXIST(TRI_HINT_CAM.CustomCam)
// SWITCH TRI_HINT_CAM.HintType
// CASE TRI_HINT_FROM_CARGOPLANE
// RENDER_SCRIPT_CAMS(FALSE, FALSE)
// BREAK
// DEFAULT
// BREAK
// ENDSWITCH
// DESTROY_CAM(TRI_HINT_CAM.CustomCam)
// ELSE
// KILL_RACE_HINT_CAM(localChaseHintCamStruct)
// ENDIF
// ENDIF
IF TRI_IS_HINT_CAM_BUTTON_PRESSED()
IF NOT IS_VECTOR_ZERO(TRI_HINT_CAM.Coord)
CONTROL_RACE_HINT_CAM(localChaseHintCamStruct, TRI_HINT_CAM.Coord)
ELSE
DEBUG_MESSAGE("no coord to point at")
ENDIF
ELSE
IF DOES_CAM_EXIST(TRI_HINT_CAM.CustomCam)
DESTROY_CAM(TRI_HINT_CAM.CustomCam)
ELSE
KILL_RACE_HINT_CAM(localChaseHintCamStruct)
ENDIF
ENDIF
ENDPROC
/// PURPOSE: Works out which checkpoint type is needed based upon angle between checkpoints
FUNC CHECKPOINT_TYPE GET_CHEVRON_CHECKPOINT_TYPE(TRI_RACE_CHECKPOINT_TYPE sprType, VECTOR pos3, VECTOR pos, VECTOR pos2)
VECTOR vec1, vec2
FLOAT fReturnAngle
FLOAT fChevron1 = 180.0
FLOAT fChevron2 = 140.0
FLOAT fChevron3 = 80.0
CHECKPOINT_TYPE Chevron1, Chevron2, Chevron3
IF sprType = TRI_CHKPT_OFFROAD_DEFAULT
Chevron1 = CHECKPOINT_RACE_GROUND_CHEVRON_1
Chevron2 = CHECKPOINT_RACE_GROUND_CHEVRON_2
Chevron3 = CHECKPOINT_RACE_GROUND_CHEVRON_3
ELIF sprType = TRI_CHKPT_STUNT_DEFAULT
Chevron1 = CHECKPOINT_RACE_AIR_CHEVRON_1
Chevron2 = CHECKPOINT_RACE_AIR_CHEVRON_2
Chevron3 = CHECKPOINT_RACE_AIR_CHEVRON_3
ELIF sprType = TRI_CHKPT_TRI_SWIM
Chevron1 = CHECKPOINT_RACE_TRI_SWIM_CHEVRON_1
Chevron2 = CHECKPOINT_RACE_TRI_SWIM_CHEVRON_2
Chevron3 = CHECKPOINT_RACE_TRI_SWIM_CHEVRON_3
ELIF sprType = TRI_CHKPT_TRI_BIKE
Chevron1 = CHECKPOINT_RACE_TRI_CYCLE_CHEVRON_1
Chevron2 = CHECKPOINT_RACE_TRI_CYCLE_CHEVRON_2
Chevron3 = CHECKPOINT_RACE_TRI_CYCLE_CHEVRON_3
ELIF sprType = TRI_CHKPT_TRI_RUN
Chevron1 = CHECKPOINT_RACE_TRI_RUN_CHEVRON_1
Chevron2 = CHECKPOINT_RACE_TRI_RUN_CHEVRON_2
Chevron3 = CHECKPOINT_RACE_TRI_RUN_CHEVRON_3
ENDIF
IF NOT ARE_VECTORS_EQUAL(pos3, <<0,0,0>>)//if not first checkpoint
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 Chevron3
ELIF fReturnAngle < fChevron2
RETURN Chevron2
ELIF fReturnAngle < fChevron1
RETURN Chevron1
ENDIF
ENDIF
RETURN Chevron1
ENDFUNC
//FUNC BOOL TRI_Chkpnt_Create(CHECKPOINT_INDEX& Chkpnt, TRI_RACE_CHECKPOINT_TYPE ChkpntType, VECTOR vPos, VECTOR vPointAt, FLOAT fScale = TRI_GATE_CHKPNT_SCL)
FUNC BOOL TRI_Chkpnt_Create(VECTOR vPrevGate, TRI_GATE_STRUCT& sGate, VECTOR vPointAt, FLOAT fScale = TRI_GATE_CHKPNT_SCL)
CDEBUG1LN(DEBUG_TRIATHLON, "[TRI_Chkpnt_Create] Function called.")
vPrevGate = vPrevGate
CHECKPOINT_TYPE curCheckpointType
TRI_Chkpnt_Destroy(sGate.Chkpnt)
sGate.vHeading = vPointAt
INT iRed, iGreen, iBlue, iUnusedAlpha
IF sGate.eChkpntType != TRI_CHKPT_STUNT_DEFAULT
AND sGate.eChkpntType != TRI_CHKPT_STUNT_STUNT
AND sGate.eChkpntType != TRI_CHKPT_STUNT_FINISH
AND sGate.eChkpntType != TRI_CHKPT_TRI_SWIM
AND sGate.eChkpntType != TRI_CHKPT_OFFROAD_DEFAULT
AND NOT TRI_Helpers_Check_Condition_Flag(sGate, TRI_RACE_GATE_FLAG_DO_NOT_SNAP_TO_GROUND)
FLOAT fGroundZ
IF NOT GET_GROUND_Z_FOR_3D_COORD(sGate.vPos, fGroundZ)
DEBUG_MESSAGE("TRI_Chkpnt_Create: using default position, probe failed")
ELSE
FLOAT fHeightMod = 0.5
sGate.vPos.z = fGroundZ + (fHeightMod*fScale) //2.6m is arbitrary...using it from my tunings in drag races - SM
ENDIF
ENDIF
IF sGate.eChkpntType = TRI_CHKPT_TRI_SWIM OR sGate.eChkpntType = TRI_CHKPT_TRI_BIKE OR sGate.eChkpntType = TRI_CHKPT_TRI_RUN
curCheckpointType = GET_CHEVRON_CHECKPOINT_TYPE(sGate.eChkpntType, vPrevGate, sGate.vPos, vPointAt)
GET_RGB_FROM_INT(GET_INT_FROM_HUD_COLOUR(MG_GET_RACE_CHECKPOINT_DEFAULT_COLOUR()), iRed, iGreen, iBlue, sGate.iHUDAlphaAfterPass)
sGate.Chkpnt = CREATE_CHECKPOINT(curCheckpointType, sGate.vPos, vPointAt, fScale, iRed, iGreen, iBlue, MG_GET_CHECKPOINT_ALPHA(sGate.vPos))
GET_HUD_COLOUR(HUD_COLOUR_NORTH_BLUE, iRed, iGreen, iBlue, iUnusedAlpha)
SET_CHECKPOINT_RGBA2(sGate.Chkpnt, iRed, iGreen, iBlue, MG_GET_CHECKPOINT_ALPHA(sGate.vPos))
//CDEBUG1LN(DEBUG_TRIATHLON, "[TRI_Chkpnt_Create] Default chk arrow colors are RED: ", iRed, ", GREEN: ", iGreen, ", BLUE: ", iBlue, ", ALPHA: ", MG_GET_CHECKPOINT_ALPHA(sGate.vPos))
ELSE
sGate.Chkpnt = CREATE_CHECKPOINT(TRI_Get_ChnkPnt_Type_From_TRI_Type(sGate.eChkpntType), sGate.vPos, vPointAt, fScale, 254, 207, 12, MG_GET_CHECKPOINT_ALPHA(sGate.vPos))
GET_HUD_COLOUR(HUD_COLOUR_NORTH_BLUE, iRed, iGreen, iBlue, sGate.iHUDAlphaAfterPass)
SET_CHECKPOINT_RGBA2(sGate.Chkpnt, iRed, iGreen, iBlue, MG_GET_CHECKPOINT_ALPHA(sGate.vPos))
//CDEBUG1LN(DEBUG_TRIATHLON, "[TRI_Chkpnt_Create] Special chk arrow colors are RED: ", iRed, ", GREEN: ", iGreen, ", BLUE: ", iBlue, ", ALPHA: ", MG_GET_CHECKPOINT_ALPHA(sGate.vPos))
ENDIF
SET_CHECKPOINT_CYLINDER_HEIGHT(sGate.Chkpnt, 1.6, 1.6, 100)
DECAL_RENDERSETTING_ID driDecal
SWITCH TRI_Get_ChnkPnt_Type_From_TRI_Type(sGate.eChkpntType)
CASE CHECKPOINT_RACE_TRI_SWIM_CHEVRON_1 driDecal = DECAL_RSID_TRIATHLON_SWIMMING BREAK
CASE CHECKPOINT_RACE_TRI_CYCLE_CHEVRON_1 driDecal = DECAL_RSID_TRIATHLON_CYCLING BREAK
CASE CHECKPOINT_RACE_TRI_RUN_CHEVRON_1 driDecal = DECAL_RSID_TRIATHLON_RUNNING BREAK
CASE CHECKPOINT_RACE_TRI_RUN_FLAG driDecal = DECAL_RSID_TRIATHLON_RUNNING BREAK
CASE CHECKPOINT_RACE_TRI_SWIM_FLAG driDecal = DECAL_RSID_TRIATHLON_SWIMMING BREAK
CASE CHECKPOINT_RACE_TRI_CYCLE_FLAG driDecal = DECAL_RSID_TRIATHLON_CYCLING BREAK
ENDSWITCH
STRING sDecal
SWITCH TRI_Get_ChnkPnt_Type_From_TRI_Type(sGate.eChkpntType)
CASE CHECKPOINT_RACE_TRI_SWIM_CHEVRON_1 sDecal = "Corona_Marker" BREAK
CASE CHECKPOINT_RACE_TRI_CYCLE_CHEVRON_1 sDecal = "Corona_Marker" BREAK
CASE CHECKPOINT_RACE_TRI_RUN_CHEVRON_1 sDecal = "Corona_Marker" BREAK
CASE CHECKPOINT_RACE_TRI_RUN_FLAG sDecal = "Corona_Marker" BREAK
CASE CHECKPOINT_RACE_TRI_SWIM_FLAG sDecal = "Corona_Marker" BREAK
CASE CHECKPOINT_RACE_TRI_CYCLE_FLAG sDecal = "Corona_Marker" BREAK
ENDSWITCH
PATCH_DECAL_DIFFUSE_MAP(driDecal, texCheckPatch, sDecal)
IF (sGate.Chkpnt = NULL)
CDEBUG1LN(DEBUG_TRIATHLON, "[TRI_Chkpnt_Create] ERROR: FAILED to created checkpoint!")
RETURN FALSE
ENDIF
RETURN TRUE
ENDFUNC
PROC Remove_Reset_UI()
// REMOVE_MINIGAME_INSTRUCTION(TRI_Master.uiInput, ICON_UP)
ENDPROC
PROC Display_Reset_UI(TRI_RACE_STRUCT& Race, TRI_RACER_STRUCT& Racer, BOOL bRacerIsPlayer)
// Setup Scaleform UI for reset/restart.
// SHOULDN'T BE DOING THIS. YOU'RE SETTING UP AND UPDATING EVERY FRAME.
// SETUP ONCE, UPDATE EVERY FRAME.
CDEBUG2LN(DEBUG_TRIATHLON, "Display_Reset_UI :: SPR_UI_RESET")
INIT_SIMPLE_USE_CONTEXT(TRI_Master.uiInput, FALSE, FALSE, TRUE, TRUE)
ADD_SIMPLE_USE_CONTEXT_INPUT(TRI_Master.uiInput, "SPR_UI_RESET", FRONTEND_CONTROL, INPUT_FRONTEND_ACCEPT)
ADD_SIMPLE_USE_CONTEXT_INPUT(TRI_Master.uiInput, "SPR_UI_QUIT", FRONTEND_CONTROL, INPUT_FRONTEND_Y)
ADD_SIMPLE_USE_CONTEXT_INPUT(TRI_Master.uiInput, "SPR_UI_RESTART", FRONTEND_CONTROL, INPUT_FRONTEND_X)
SET_SIMPLE_USE_CONTEXT_FULLSCREEN(TRI_Master.uiInput, TRUE)
// If racer is player, display reset/restart options.
IF bRacerIsPlayer
UPDATE_SIMPLE_USE_CONTEXT(TRI_Master.uiInput)
IF IS_CONTROL_JUST_PRESSED( FRONTEND_CONTROL, INPUT_FRONTEND_ACCEPT)
// Reset vehicle.
Remove_Reset_UI(Race)
Racer.eReset = TRI_RACER_RESET_FADE_OUT
ELIF IS_CONTROL_JUST_PRESSED( FRONTEND_CONTROL, INPUT_FRONTEND_RLEFT)
// Restart race.
SET_TRI_CONTROL_FLAG(TCF_RACE_RESTARTING)
Remove_Reset_UI(Race)
Racer.eReset = TRI_RACER_RESET_FADE_OUT
ELIF IS_CONTROL_JUST_PRESSED( FRONTEND_CONTROL, INPUT_FRONTEND_RUP)
CLEAR_TRI_CONTROL_FLAG(TCF_RACE_RESTARTING)
Remove_Reset_UI(Race)
IF (TRI_Master.eRaceType = TRI_RACE_TYPE_OFFROAD)
TRI_Master.iRaceCur = -1 //forcing a quit here as there is no menu for offroad races
Racer.eReset = TRI_RACER_QUIT_FADE_IN
ELSE
DEBUG_MESSAGE("Quitting from rest UI, going to RACER_QUIT_FADE_OUT")
Racer.eReset = TRI_RACER_QUIT_FADE_OUT
ENDIF
ENDIF
ENDIF
ENDPROC
PROC TRI_RESET_DO_VEHICLE_CHECKS(TRI_RACE_STRUCT& Race)
INT iVehHealth, iEngHealth
iVehHealth = GET_ENTITY_HEALTH(Race.Racer[0].Vehicle)
IF NOT IS_ENTITY_DEAD(Race.Racer[0].Vehicle)
iEngHealth = ROUND(GET_VEHICLE_ENGINE_HEALTH(Race.Racer[0].Vehicle))
ENDIF
// health check
IF iVehHealth < 500.0
IF (TRI_Master.eRaceType = TRI_RACE_TYPE_TRIATHLON)
IF NOT IS_ENTITY_DEAD(Race.Racer[0].Vehicle)
AND NOT IS_ENTITY_DEAD(PLAYER_PED_ID())
IF IS_PED_IN_VEHICLE(PLAYER_PED_ID(), Race.Racer[0].Vehicle)
SET_TRI_CONTROL_FLAG(TCF_TRI_MOUNTED)
ENDIF
ENDIF
IF IS_TRI_CONTROL_FLAG_SET(TCF_TRI_MOUNTED)
IF (Race.sGate[Race.Racer[0].iGateCur].eChkpntType = TRI_CHKPT_TRI_BIKE) OR (Race.sGate[Race.Racer[0].iGateCur].eChkpntType = TRI_CHKPT_TRI_SECOND_TRANS)
IF NOT IS_MESSAGE_BEING_DISPLAYED()
PRINT_NOW_ONCE("SPR_HELP_DAMG", 5000, 0, TRI_HELP_BIT, TRI_DAMG_HELP)
ENDIF
ENDIF
ENDIF
ELSE
// nuke all existing messages and conversations before displaying vehicle health prompt
IF IS_MESSAGE_BEING_DISPLAYED()
CLEAR_PRINTS()
ENDIF
PRINT_NOW_ONCE("SPR_HELP_DAMG", 5000, 0, TRI_HELP_BIT, TRI_DAMG_HELP)
ENDIF
ENDIF
IF (TRI_Master.eRaceType = TRI_RACE_TYPE_OFFROAD)
IF iEngHealth < 200.0
DEBUG_MESSAGE("Player Vehicle Engine health is too low, prompt to reset")
// nuke all existing messages and conversations before displaying vehicle health prompt
IF IS_MESSAGE_BEING_DISPLAYED()
CLEAR_PRINTS()
ENDIF
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
KILL_ANY_CONVERSATION()
ENDIF
PRINT_NOW_ONCE("SPR_HELP_DAMG", 5000, 0, TRI_HELP_BIT, TRI_DAMG_HELP)
ENDIF
ENDIF
ENDPROC
PROC TRI_RESET_DO_DISTANCE_TO_RACE_LINE_CHECKS(TRI_RACE_STRUCT& Race)
VECTOR vCurGatePos, vPrevGatePos
vCurGatePos = Race.sGate[Race.Racer[0].iGateCur].vPos
IF (Race.Racer[0].iGateCur > 0)
vPrevGatePos = Race.sGate[Race.Racer[0].iGateCur-1].vPos
ELSE
vPrevGatePos = TRI_Master.vDefRcrPos
ENDIF
// Check distance between race start and first gate
FLOAT fWarnDist = GET_DISTANCE_BETWEEN_COORDS(vCurGatePos, vPrevGatePos)
FLOAT fFailDist = fWarnDist
SWITCH TRI_Master.eRaceType
CASE TRI_RACE_TYPE_OFFROAD
IF (Race.Racer[0].iGateCur = 0) //first gate
fWarnDist += 10.0
fFailDist += 100.0
ELSE
fWarnDist += 50.0
fFailDist += 300.0
ENDIF
BREAK
CASE TRI_RACE_TYPE_PLANE
IF (Race.Racer[0].iGateCur = 0) // at start of race
fWarnDist += 200.0
fFailDist += 750.0
ELSE
fWarnDist += 200.0
fFailDist += 9000
ENDIF
BREAK
CASE TRI_RACE_TYPE_TRIATHLON
IF (Race.Racer[0].iGateCur = 0) // at start of race
fWarnDist += 10.0
fFailDist += 60.0
ELSE
IF NOT IS_ENTITY_DEAD(Race.Racer[0].Driver)
IF IS_PED_IN_ANY_VEHICLE(Race.Racer[0].Driver)
fWarnDist += 20.0
fFailDist += 170.0
ELSE
fWarnDist += 20.0
fFailDist += 70.0
ENDIF
ENDIF
ENDIF
BREAK
ENDSWITCH
VECTOR vPlayerPosition = GET_ENTITY_COORDS(Race.Racer[0].Driver)
VECTOR vNearestPos = GET_CLOSEST_POINT_ON_LINE(vPlayerPosition, vPrevGatePos, vCurGatePos)
FLOAT fPlayerDistance = GET_DISTANCE_BETWEEN_COORDS(vNearestPos, vPlayerPosition)
BOOL bWarningDist = (fPlayerDistance >= fWarnDist)
BOOL bFailureDist = (fPlayerDistance >= fFailDist)
IF (TRI_Master.eRaceType = TRI_RACE_TYPE_OFFROAD)
IF ABSF(vNearestPos.z-vPlayerPosition.z) > 15.0 //291946 - Canyon Cliff race Not informed on how to reposition on falling off cliff
bWarningDist = TRUE
ENDIF
ENDIF
// Act on failure distance
IF bFailureDist
CPRINTLN(DEBUG_TRIATHLON, "Player has gone too far from race, going to FAIL OVER")
IF (TRI_Master.eRaceType = TRI_RACE_TYPE_TRIATHLON) AND IS_THIS_PRINT_BEING_DISPLAYED("TRI_LEAVE_VEH")
CLEAR_THIS_PRINT("TRI_LEAVE_VEH")
CPRINTLN(DEBUG_TRIATHLON, "Clearing TRI_LEAVE_VEH message")
ENDIF
RESTART_TIMER_NOW(exitTimer)
CLEAR_TRI_CONTROL_FLAG(TCF_FAIL_CHECKING)
CPRINTLN(DEBUG_TRIATHLON, "RESET_TUTORIAL: TCF_FAIL_CHECKING cleared")
Race.Racer[0].eReset = TRI_RACER_RESET_FAIL_OVER
Race.FailString = "SPR_HELP_FAIL"
//IF fPlayerDistance <= (fFailDist - 15) //make sure we're a good distance away so we dont stack msgs
// PRINT_NOW("SPR_HELP_FAIL", 5000, 0)
//ENDIF
ELSE
// Act on warning distance
IF bWarningDist
IF (TRI_Master.eRaceType = TRI_RACE_TYPE_TRIATHLON)
IF NOT IS_THIS_HELP_MESSAGE_BEING_DISPLAYED("SPR_HELP_DIST_2")
CLEAR_HELP()
PRINT_HELP_FOREVER("SPR_HELP_DIST_2")
ADD_TRI_NEWS_EVENT(TRNE_PLAYER_MISSED_CHECKPT)
CPRINTLN( DEBUG_TRIATHLON, "Adding missed checkpoint event." )
ENDIF
ELSE
IF fPlayerDistance <= (fFailDist - 15) //make sure we're a good distance away so we dont stack msgs
IF NOT IS_HELP_MESSAGE_BEING_DISPLAYED()
PRINT_HELP("SPR_HELP_DIST")
ENDIF
ENDIF
ENDIF
IF fPlayerDistance <= (fFailDist - 15) //make sure we're a good distance away so we dont stack msgs
PRINT_NOW_ONCE("SPR_HELP_WARN", 5000, 0, TRI_HELP_BIT, TRI_WARN_HELP)
ENDIF
ELSE
CLEAR_THIS_PRINT("SPR_HELP_WARN")
IF IS_THIS_HELP_MESSAGE_BEING_DISPLAYED("SPR_HELP_DIST_2")
CLEAR_HELP()
ENDIF
IF IS_BITMASK_AS_ENUM_SET(TRI_HELP_BIT, TRI_WARN_HELP)
CLEAR_BITMASK_AS_ENUM(TRI_HELP_BIT, TRI_WARN_HELP)
DEBUG_MESSAGE("RESET TUTORIAL: Clearing global WARN DIST BIT")
ENDIF
ENDIF
ENDIF
//if we want to see where the intersection is in the world
// #IF IS_DEBUG_BUILD
// SET_DEBUG_LINES_AND_SPHERES_DRAWING_ACTIVE(TRUE)
// DRAW_DEBUG_SPHERE(vNearestPos, 1.0)
// #ENDIF
ENDPROC
// ----------------------------------
// RESET TUTORIAL // FAIL CASE
// ----------------------------------
PROC RESET_TUTORIAL(TRI_RACE_STRUCT& Race)
IF IS_TRI_CONTROL_FLAG_SET(TCF_FAIL_CHECKING)
TRI_RESET_DO_DISTANCE_TO_RACE_LINE_CHECKS(Race)
TRI_RESET_DO_VEHICLE_CHECKS(Race)
ENDIF
ENDPROC
// EXIT VEHICLE FAILURE
PROC EXIT_VEHICLE_FAILURE(TRI_RACE_STRUCT& Race, BLIP_INDEX& blipVeh)
// TRIATHLON
IF (TRI_Master.eRaceType = TRI_RACE_TYPE_TRIATHLON)
// check if the player has gotten on the bike before failchecking it
IF NOT IS_ENTITY_DEAD(Race.Racer[0].Vehicle)
IF IS_PED_IN_VEHICLE(PLAYER_PED_ID(), Race.Racer[0].Vehicle)
SET_TRI_CONTROL_FLAG(TCF_TRI_MOUNTED)
ENDIF
ENDIF
IF IS_TRI_CONTROL_FLAG_SET(TCF_TRI_MOUNTED)
IF (Race.sGate[Race.Racer[0].iGateCur].eChkpntType = TRI_CHKPT_TRI_BIKE) OR (Race.sGate[Race.Racer[0].iGateCur].eChkpntType = TRI_CHKPT_TRI_SECOND_TRANS)
//DEBUG_MESSAGE("Inside Vehicle check for tri")
IF NOT IS_PED_IN_VEHICLE(PLAYER_PED_ID(), Race.Racer[0].Vehicle)
FLOAT fDist = VDIST2(GET_ENTITY_COORDS(PLAYER_PED_ID()), GET_ENTITY_COORDS(Race.Racer[0].Vehicle))
IF fDist > MAX_DISTANCE_FROM_BIKE * MAX_DISTANCE_FROM_BIKE
IF NOT DOES_BLIP_EXIST(blipVeh)
blipVeh = ADD_BLIP_FOR_ENTITY(Race.Racer[0].Vehicle)
SET_BLIP_COLOUR(blipVeh, BLIP_COLOUR_BLUE)
CPRINTLN(DEBUG_TRIATHLON, "ADD_BLIP_FOR_ENTITY(Race.Racer[0].Vehicle)")
ENDIF
IF NOT IS_TIMER_STARTED(ExitVehicleTimer)
START_TIMER_NOW_SAFE(ExitVehicleTimer)
ELSE
IF (GET_TIMER_IN_SECONDS(ExitVehicleTimer) >= 10.0)
PRINT_NOW_ONCE("SPR_TXIT_WARN", 15000, 0, TRI_HELP_BIT, TRI_TXIT_WARN)
ENDIF
IF (GET_TIMER_IN_SECONDS(ExitVehicleTimer) >= 35.0)
// PRINT_NOW_ONCE("SPR_TXIT_FAIL", 15000, 0, TRI_HELP_BIT, TRI_TXIT_FAIL)
DEBUG_MESSAGE("Failed to get back into vehicle")
RESTART_TIMER_NOW(exitTimer)
CANCEL_TIMER(ExitVehicleTimer)
// RESTART_TIMER_NOW(ExitVehicleTimer)
IF DOES_BLIP_EXIST(blipVeh)
REMOVE_BLIP(blipVeh)
IF (Race.Racer[0].iGateCur <= Race.iGateCnt-1)
IF DOES_BLIP_EXIST(Race.sGate[Race.Racer[0].iGateCur].blip)
SET_BLIP_DISPLAY(Race.sGate[Race.Racer[0].iGateCur].blip, DISPLAY_NOTHING)
ENDIF
ENDIF
IF ((Race.Racer[0].iGateCur+1) <= (Race.iGateCnt-2))
IF DOES_BLIP_EXIST(Race.sGate[Race.Racer[0].iGateCur+1].blip)
SET_BLIP_DISPLAY(Race.sGate[Race.Racer[0].iGateCur+1].blip, DISPLAY_NOTHING)
ENDIF
ENDIF
ENDIF
CLEAR_TRI_CONTROL_FLAG(TCF_FAIL_CHECKING)
Race.FailString = "SPR_TXIT_FAIL"
DEBUG_MESSAGE("EXIT_VEHICLE_FAILURE.4: TCF_FAIL_CHECKING cleared")
Race.Racer[0].eReset = TRI_RACER_RESET_FAIL_OVER
ENDIF
ENDIF
ENDIF
ELSE
IF DOES_BLIP_EXIST(blipVeh)
REMOVE_BLIP(blipVeh)
ENDIF
CANCEL_TIMER(ExitVehicleTimer)
IF IS_BITMASK_AS_ENUM_SET(TRI_HELP_BIT, TRI_TXIT_WARN)
CLEAR_BITMASK_AS_ENUM(TRI_HELP_BIT, TRI_TXIT_WARN)
ENDIF
IF IS_BITMASK_AS_ENUM_SET(TRI_HELP_BIT, TRI_TXIT_FAIL)
CLEAR_BITMASK_AS_ENUM(TRI_HELP_BIT, TRI_TXIT_FAIL)
ENDIF
ENDIF
ELSE
IF DOES_BLIP_EXIST(blipVeh)
REMOVE_BLIP(blipVeh)
CPRINTLN(DEBUG_TRIATHLON, "REMOVE_BLIP(blipVeh)")
ENDIF
CLEAR_TRI_CONTROL_FLAG(TCF_TRI_MOUNTED)
ENDIF
ENDIF
ENDIF
ENDPROC
// DEAD VEHICLE FAILURE
PROC Dead_Race_Vehicle(TRI_RACE_STRUCT& Race, BLIP_INDEX& blipVeh)
IF IS_TRI_CONTROL_FLAG_SET(TCF_FAIL_CHECKING)
IF (TRI_Master.eRaceType = TRI_RACE_TYPE_TRIATHLON)
AND (Race.sGate[Race.Racer[0].iGateCur].eChkpntType != TRI_CHKPT_TRI_BIKE) AND (Race.sGate[Race.Racer[0].iGateCur].eChkpntType != TRI_CHKPT_TRI_SECOND_TRANS)
EXIT
ENDIF
IF (GET_ENTITY_HEALTH(Race.Racer[0].Vehicle) < 5)
// Set failcase to false
// PRINT_NOW_ONCE("SPR_RETR_DES", 10000, 0, TRI_HELP_BIT, TRI_RETURN_FAIL)
RESTART_TIMER_NOW(exitTimer)
IF DOES_BLIP_EXIST(blipVeh)
REMOVE_BLIP(blipVeh)
ENDIF
IF (Race.Racer[0].iGateCur <= Race.iGateCnt-1)
IF DOES_BLIP_EXIST(Race.sGate[Race.Racer[0].iGateCur].blip)
SET_BLIP_DISPLAY(Race.sGate[Race.Racer[0].iGateCur].blip, DISPLAY_NOTHING)
ENDIF
ENDIF
IF ((Race.Racer[0].iGateCur+1) <= (Race.iGateCnt-2))
IF DOES_BLIP_EXIST(Race.sGate[Race.Racer[0].iGateCur+1].blip)
SET_BLIP_DISPLAY(Race.sGate[Race.Racer[0].iGateCur+1].blip, DISPLAY_NOTHING)
ENDIF
ENDIF
DEBUG_MESSAGE("Dead_Race_Vehicle: TCF_FAIL_CHECKING cleared")
CLEAR_TRI_CONTROL_FLAG(TCF_FAIL_CHECKING)
Race.FailString = "SPR_RETR_DES"
Race.Racer[0].eReset = TRI_RACER_RESET_FAIL_OVER
ENDIF
ENDIF
ENDPROC
FUNC BOOL IS_PLAYER_ON_TRI_BIKE()
IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
VEHICLE_INDEX vehRacerIsOn = GET_VEHICLE_PED_IS_USING(PLAYER_PED_ID())
IF IS_VEHICLE_MODEL(vehRacerIsOn, TRIBIKE) OR IS_VEHICLE_MODEL(vehRacerIsOn, TRIBIKE2) OR IS_VEHICLE_MODEL(vehRacerIsOn, TRIBIKE3)
RETURN TRUE
ELSE
RETURN FALSE
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
//TODO
//Ideally tri would have some sort of main fail function liek UPDATE_FAIL_CONDITIONS bur for now following the conventions in this script
PROC vehicleFailure(TRI_RACE_STRUCT& Race)
IF NOT IS_ENTITY_DEAD(PLAYER_PED_ID())
IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
IF NOT IS_PLAYER_ON_TRI_BIKE()
DEBUG_MESSAGE("vehicleFailure = RI_RACER_RESET_FAIL_OVER")
Race.FailString = "SPR_EXIT_FAIL2"
Race.Racer[0].eReset = TRI_RACER_RESET_FAIL_OVER
ENDIF
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Check if player vehicle has entered water, and reset player accordingly.
PROC waterFailure(TRI_RACE_STRUCT& Race)
IF (TRI_Master.eRaceType = TRI_RACE_TYPE_OFFROAD)
IF NOT IS_ENTITY_DEAD(Race.Racer[0].Vehicle)
IF IS_ENTITY_IN_WATER(Race.Racer[0].Vehicle)
IF NOT IS_TIMER_STARTED(waterTimer)
START_TIMER_NOW_SAFE(waterTimer)
DEBUG_MESSAGE("Started water Timer")
ELSE
IF IS_PED_IN_VEHICLE(Race.Racer[0].Driver, Race.Racer[0].Vehicle)
IF (IS_VEHICLE_MODEL(Race.Racer[0].Vehicle, SANCHEZ))
IF IS_VEHICLE_ON_ALL_WHEELS(Race.Racer[0].Vehicle)
RESTART_TIMER_NOW(waterTimer)
ELIF (GET_TIMER_IN_SECONDS(waterTimer) >= 2.75)
RESTART_TIMER_NOW(waterTimer)
RESTART_TIMER_NOW(exitTimer)
DEBUG_MESSAGE("waterFailure: TCF_FAIL_CHECKING cleared")
CLEAR_TRI_CONTROL_FLAG(TCF_FAIL_CHECKING)
Race.Racer[0].eReset = TRI_RACER_RESET_FADE_OUT
DEBUG_MESSAGE("Moving to TRI_RACER_RESET_FADE_OUT")
ENDIF
ELSE
IF IS_VEHICLE_ON_ALL_WHEELS(Race.Racer[0].Vehicle)
RESTART_TIMER_NOW(waterTimer)
ELIF (GET_TIMER_IN_SECONDS(waterTimer) >= 1.5)
RESTART_TIMER_NOW(waterTimer)
RESTART_TIMER_NOW(exitTimer)
CLEAR_TRI_CONTROL_FLAG(TCF_FAIL_CHECKING)
DEBUG_MESSAGE("WaterFailure.2: TCF_FAIL_CHECKING cleared")
Race.Racer[0].eReset = TRI_RACER_RESET_FADE_OUT
DEBUG_MESSAGE("Moving to TRI_RACER_RESET_FADE_OUT")
ENDIF
ENDIF
ELSE
IF (GET_TIMER_IN_SECONDS(waterTimer) >= 1.5)
RESTART_TIMER_NOW(waterTimer)
RESTART_TIMER_NOW(exitTimer)
CLEAR_TRI_CONTROL_FLAG(TCF_FAIL_CHECKING)
DEBUG_MESSAGE("waterFailure.3: TCF_FAIL_CHECKING cleared")
Race.Racer[0].eReset = TRI_RACER_RESET_FADE_OUT
DEBUG_MESSAGE("Moving to TRI_RACER_RESET_FADE_OUT")
ENDIF
ENDIF
ENDIF
ELIF IS_TIMER_STARTED(waterTimer)
RESTART_TIMER_NOW(waterTimer)
ENDIF
ENDIF
ENDIF
IF (TRI_Master.eRaceType = TRI_RACE_TYPE_TRIATHLON)
IF (Race.sGate[Race.Racer[0].iGateCur].eChkpntType = TRI_CHKPT_TRI_BIKE) OR (Race.sGate[Race.Racer[0].iGateCur].eChkpntType = TRI_CHKPT_TRI_SECOND_TRANS)
IF DOES_ENTITY_EXIST(Race.Racer[0].Vehicle)
//CPRINTLN(DEBUG_TRIATHLON, "[TRI_Helpers.sch->waterFailure] Player's bike EXISTS.")
IF IS_ENTITY_IN_WATER(Race.Racer[0].Vehicle)
//CPRINTLN(DEBUG_TRIATHLON, "[TRI_Helpers.sch->waterFailure] Player's bike is IN WATER.")
IF NOT IS_TIMER_STARTED(waterTimer)
//CPRINTLN(DEBUG_TRIATHLON, "[TRI_Helpers.sch->waterFailure] Water time has NOT been started. Starting water timer.")
START_TIMER_NOW_SAFE(waterTimer)
ENDIF
//CPRINTLN(DEBUG_TRIATHLON, "[TRI_Helpers.sch->waterFailure] Player's bike is in WATER. Check if player is on bike.")
IF IS_PED_IN_VEHICLE(PLAYER_PED_ID(), Race.Racer[0].Vehicle)
//CPRINTLN(DEBUG_TRIATHLON, "[TRI_Helpers.sch->waterFailure] Player is ON THE BIKE. Restarting water timer.")
RESTART_TIMER_NOW(waterTimer)
ELIF (GET_TIMER_IN_SECONDS(waterTimer) >= 1.5)
//CPRINTLN(DEBUG_TRIATHLON, "[TRI_Helpers.sch->waterFailure] Player is NOT ON THE BIKE. Not fail-checking anymore.")
CPRINTLN(DEBUG_TRIATHLON, "waterFailure.4: TCF_FAIL_CHECKING cleared")
CLEAR_TRI_CONTROL_FLAG(TCF_FAIL_CHECKING)
Race.Racer[0].eReset = TRI_RACER_RESET_FADE_OUT
ENDIF
ELIF IS_TIMER_STARTED(waterTimer)
//CPRINTLN(DEBUG_TRIATHLON, "[TRI_Helpers.sch->waterFailure] Player's bike is NOT IN WATER. Restarting water timer.")
RESTART_TIMER_NOW(waterTimer)
ENDIF
ELSE
CPRINTLN(DEBUG_TRIATHLON, "[TRI_Helpers.sch->waterFailure] Player's bike does NOT EXIST.")
ENDIF
ENDIF
ENDIF
ENDPROC
// WANTED FAILURE
PROC wantedFailure(TRI_RACE_STRUCT& Race)
// Failcheck for illegal stuffs
IF TRI_Master.eRaceType <> TRI_RACE_TYPE_PLANE
IF (GET_PLAYER_WANTED_LEVEL(PLAYER_ID()) > 0)
CPRINTLN(DEBUG_TRIATHLON, "Wanted Failure: Player is wanted.")
CPRINTLN(DEBUG_TRIATHLON, "Player's wanted level is: ", GET_PLAYER_WANTED_LEVEL(PLAYER_ID()))
// PRINT_NOW("SPR_HELP_WANT", 5000, 0)
IF (Race.Racer[0].iGateCur <= Race.iGateCnt-1)
IF DOES_BLIP_EXIST(Race.sGate[Race.Racer[0].iGateCur].blip)
SET_BLIP_DISPLAY(Race.sGate[Race.Racer[0].iGateCur].blip, DISPLAY_NOTHING)
ENDIF
ENDIF
IF ((Race.Racer[0].iGateCur+1) <= (Race.iGateCnt-2))
IF DOES_BLIP_EXIST(Race.sGate[Race.Racer[0].iGateCur+1].blip)
SET_BLIP_DISPLAY(Race.sGate[Race.Racer[0].iGateCur+1].blip, DISPLAY_NOTHING)
ENDIF
ENDIF
RESTART_TIMER_NOW(exitTimer)
Race.FailString = "SPR_HELP_WANT"
CLEAR_TRI_CONTROL_FLAG(TCF_FAIL_CHECKING)
CPRINTLN(DEBUG_TRIATHLON, "wantedFailure: TCF_FAIL_CHECKING cleared")
Race.Racer[0].eReset = TRI_RACER_RESET_FAIL_OVER
ELIF GET_MAX_WANTED_LEVEL() = 0
SET_MAX_WANTED_LEVEL(6) //setting this in case its been set too low.
ENDIF
IF IS_PED_SHOOTING(PLAYER_PED_ID())
SET_PLAYER_WANTED_LEVEL(PLAYER_ID(), 1)
SET_PLAYER_WANTED_LEVEL_NOW(PLAYER_ID())
CPRINTLN(DEBUG_TRIATHLON, "Wanted Failcase: Player has fired weapon, set wanted 1")
ENDIF
IF TRI_Master.eRaceType = TRI_RACE_TYPE_OFFROAD
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
IF HAS_PLAYER_DAMAGED_AT_LEAST_ONE_PED(PLAYER_ID())
INT i
PED_INDEX injuredPed
//check for killed peds who arent mission entities
IF Has_Ped_Been_Killed()
REPEAT Get_Number_Of_Ped_Killed_Events() i
IF DOES_ENTITY_EXIST(Get_Index_Of_Killed_Ped(i))
injuredPed = GET_PED_INDEX_FROM_ENTITY_INDEX(Get_Index_Of_Killed_Ped(i))
IF injuredPed <> PLAYER_PED_ID() AND HAS_ENTITY_BEEN_DAMAGED_BY_ENTITY(injuredPed, PLAYER_PED_ID())
SET_PLAYER_WANTED_LEVEL(PLAYER_ID(), 1)
SET_PLAYER_WANTED_LEVEL_NOW(PLAYER_ID())
CPRINTLN(DEBUG_TRIATHLON, "Wanted Failcase: Player has killed a ped with a car, set wanted 1")
CLEAR_PLAYER_HAS_DAMAGED_AT_LEAST_ONE_PED(PLAYER_ID())
EXIT
ENDIF
ENDIF
ENDREPEAT
ENDIF
//check for injured peds who arent mission entities
IF Has_Ped_Been_Injured()
REPEAT Get_Number_Of_Ped_Injured_Events() i
IF DOES_ENTITY_EXIST(Get_Index_Of_Injured_Ped(i))
injuredPed = GET_PED_INDEX_FROM_ENTITY_INDEX(Get_Index_Of_Injured_Ped(i))
IF injuredPed <> PLAYER_PED_ID() AND HAS_ENTITY_BEEN_DAMAGED_BY_ENTITY(injuredPed, PLAYER_PED_ID())
IF NOT IS_ENTITY_A_MISSION_ENTITY(injuredPed)
SET_PLAYER_WANTED_LEVEL(PLAYER_ID(), 1)
SET_PLAYER_WANTED_LEVEL_NOW(PLAYER_ID())
CPRINTLN(DEBUG_TRIATHLON, "Wanted Failcase: Player has injured a ped with a car, set wanted 1")
CLEAR_PLAYER_HAS_DAMAGED_AT_LEAST_ONE_PED(PLAYER_ID())
ENDIF
ENDIF
ENDIF
ENDREPEAT
ENDIF
ENDIF
ENDIF
ENDIF
ELSE
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
IF HAS_PLAYER_DAMAGED_AT_LEAST_ONE_PED(PLAYER_ID())
IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
VEHICLE_INDEX vehRacerIsOn = GET_VEHICLE_PED_IS_USING(Race.Racer[0].Driver)
IF NOT (IS_VEHICLE_MODEL( vehRacerIsOn, TRIBIKE)
OR IS_VEHICLE_MODEL( vehRacerIsOn, TRIBIKE2)
OR IS_VEHICLE_MODEL( vehRacerIsOn, TRIBIKE3))
SET_PLAYER_WANTED_LEVEL(PLAYER_ID(), 1)
SET_PLAYER_WANTED_LEVEL_NOW(PLAYER_ID())
CPRINTLN(DEBUG_TRIATHLON, "Wanted Failcase: Player has hit a ped with a car, set wanted 1")
ENDIF
ENDIF
CLEAR_PLAYER_HAS_DAMAGED_AT_LEAST_ONE_PED(PLAYER_ID())
ENDIF
ENDIF
ENDIF
ELSE
IF (GET_PLAYER_WANTED_LEVEL(PLAYER_ID()) > 0)
CLEAR_PLAYER_WANTED_LEVEL(PLAYER_ID())
ENDIF
ENDIF
ENDPROC
// -----------------------------------
// PLACEMENT PROCS/FUNCTIONS
// -----------------------------------
PROC TRI_GetRelPos_Ground_Side(VECTOR& vRelPos, FLOAT fDist)
//DEBUG_MESSAGE("TRI_GetRelPos_Ground_Side")
VECTOR vSide = <<1.0, 0.0, 0.0>>
vSide = vSide * fDist
vRelPos = vRelPos + vSide
ENDPROC
PROC TRI_GetRelPos_Ground_Fwd(VECTOR& vRelPos, FLOAT fDist)
//DEBUG_MESSAGE("TRI_GetRelPos_Ground_Fwd")
VECTOR vFwd = <<0.0, 1.0, 0.0>>
vFwd = vFwd * fDist
vRelPos = vRelPos + vFwd
ENDPROC
PROC TRI_GetRelPos_Ground_Up(VECTOR& vRelPos, FLOAT fDist)
//DEBUG_MESSAGE("TRI_GetRelPos_Ground_Up")
FLOAT fHeight = 0.0
IF NOT GET_GROUND_Z_FOR_3D_COORD(vRelPos, fHeight)
GET_WATER_HEIGHT_NO_WAVES(vRelPos, fHeight)
ENDIF
vRelPos.z -= fHeight
vRelPos.z += fDist
ENDPROC
PROC TRI_GetRelPos_Entity_Side(ENTITY_INDEX Entity, VECTOR& vRelPos, FLOAT fDist, BOOL bAbsolute)
//DEBUG_MESSAGE("TRI_GetRelPos_Entity_Side")
IF NOT IS_ENTITY_DEAD(Entity)
VECTOR vSide, vTmp1, vTmp2, vTmp3
GET_ENTITY_MATRIX(Entity, vTmp1, vSide, vTmp2, vTmp3)
IF bAbsolute
vRelPos.x = vTmp3.x
ENDIF
vSide = vSide * fDist
vRelPos = vRelPos + vSide
ENDIF
ENDPROC
PROC TRI_GetRelPos_Entity_Fwd(ENTITY_INDEX Entity, VECTOR& vRelPos, FLOAT fDist, BOOL bAbsolute)
//DEBUG_MESSAGE("TRI_GetRelPos_Entity_Fwd")
IF NOT IS_ENTITY_DEAD(Entity)
VECTOR vFwd, vTmp1, vTmp2, vTmp3
GET_ENTITY_MATRIX(Entity, vFwd, vTmp1, vTmp2, vTmp3)
IF bAbsolute
vRelPos.y = vTmp3.y
ENDIF
vFwd = vFwd * fDist
vRelPos = vRelPos + vFwd
ENDIF
ENDPROC
PROC TRI_GetRelPos_Entity_Up(ENTITY_INDEX Entity, VECTOR& vRelPos, FLOAT fDist, BOOL bAbsolute)
//DEBUG_MESSAGE("TRI_GetRelPos_Entity_Up")
IF NOT IS_ENTITY_DEAD(Entity)
VECTOR vUp, vTmp1, vTmp2, vTmp3
GET_ENTITY_MATRIX(Entity, vTmp1, vTmp2, vUp, vTmp3)
IF bAbsolute
vRelPos.z = vTmp3.z
ENDIF
vUp = vUp * fDist
vRelPos = vRelPos + vUp
ENDIF
ENDPROC
PROC TRI_GetRelPos_Coord_Side(VECTOR vCoord1, VECTOR vCoord2, VECTOR& vRelPos, FLOAT fDist, BOOL bAbsolute)
//DEBUG_MESSAGE("TRI_GetRelPos_Coord_Side")
IF bAbsolute
vRelPos.x = vCoord1.x
ENDIF
VECTOR vFwd = vCoord2 - vCoord1
VECTOR vUp = <<0.0, 0.0, 1.0>>
VECTOR vSide = CROSS_PRODUCT(vFwd, vUp)
vSide = NORMALISE_VECTOR(vSide)
vSide = vSide * fDist
vRelPos = vRelPos + vSide
ENDPROC
PROC TRI_GetRelPos_Coord_Fwd(VECTOR vCoord1, VECTOR vCoord2, VECTOR& vRelPos, FLOAT fDist, BOOL bAbsolute)
//DEBUG_MESSAGE("TRI_GetRelPos_Coord_Fwd")
IF bAbsolute
vRelPos.y = vCoord1.y
ENDIF
VECTOR vFwd = vCoord2 - vCoord1
vFwd = NORMALISE_VECTOR(vFwd)
vFwd = vFwd * fDist
vRelPos = vRelPos + vFwd
ENDPROC
PROC TRI_GetRelPos_Coord_Up(VECTOR vCoord1, VECTOR& vRelPos, FLOAT fDist, BOOL bAbsolute)
//DEBUG_MESSAGE("TRI_GetRelPos_Coord_Up")
IF bAbsolute
vRelPos.z = vCoord1.z
ENDIF
vRelPos.z += fDist
ENDPROC
// -----------------------------------
// HUD/UI PROCS/FUNCTIONS
// -----------------------------------
/// PURPOSE:
/// Displays the countdown at the start of the race.
///
/// PARAMS:
/// Display - Struct with a timer, and int and float counters.
///
/// RETURNS:
/// BOOL - Countdown still displaying.
FUNC BOOL TRI_Countdown_Display(TRI_DISPLAY_STRUCT& Display)
SWITCH(eCountdownStage)
CASE TRI_COUNTDOWN_STAGE_INIT
START_TIMER_NOW_SAFE(Display.tCnt)
SET_MINIGAME_COUNTDOWN_UI_NUMBER(TRI_CountDownUI, 3)
eCountdownStage = TRI_COUNTDOWN_RUN
BREAK
CASE TRI_COUNTDOWN_RUN
IF TIMER_DO_WHEN_READY(Display.tCnt, 1)
UPDATE_MINIGAME_COUNTDOWN_UI(TRI_CountDownUI)
eCountdownStage = TRI_COUNTDOWN_STAGE_WAIT
ENDIF
BREAK
CASE TRI_COUNTDOWN_STAGE_WAIT
IF UPDATE_MINIGAME_COUNTDOWN_UI(TRI_CountDownUI, FALSE)
RETURN FALSE
ENDIF
BREAK
RETURN TRUE
ENDSWITCH
// Countdown still displaying.
RETURN TRUE
ENDFUNC
/*
FUNC BOOL DEPRECATED_TRI_Countdown_Display(TRI_DISPLAY_STRUCT& Display)
//DEBUG_MESSAGE("TRI_Countdown_Display")
// If timer isn't started, play a sound and start it.
IF NOT IS_TIMER_STARTED(Display.tCnt)
PLAY_SOUND_FRONTEND(-1, "PHONE_GENERIC_KEY_01", "HUD_MINIGAME_SOUNDSET")
RESTART_TIMER_NOW(Display.tCnt)
// Otherwise, if ocunter > zero, display countdown (num) for proper amount of time.
ELIF (Display.iCnt > 0)
SET_TEXT_SCALE(TRI_UI_CD_NUM_SCALE, TRI_UI_CD_NUM_SCALE)
DISPLAY_TEXT_WITH_NUMBER(TRI_UI_CD_NUM_POS_X, TRI_UI_CD_NUM_POS_Y, "TRI_COUNT_NUM", Display.iCnt)
IF TIMER_DO_WHEN_READY(Display.tCnt, TRI_UI_CD_NUM_TIME)
CANCEL_TIMER(Display.tCnt)
--Display.iCnt
ENDIF
// Otherwise, ocunter is zero, display countdown (go) for proper amount of time.
ELSE
//SET_TEXT_SCALE(TRI_UI_CD_GO_SCALE, TRI_UI_CD_GO_SCALE)
//DISPLAY_TEXT(TRI_UI_CD_GO_POS_X, TRI_UI_CD_GO_POS_Y, "TRI_COUNT_GO")
//IF TIMER_DO_WHEN_READY(Display.tCnt, TRI_UI_CD_GO_TIME)
// CANCEL_TIMER(Display.tCnt)
RETURN FALSE
//ENDIF
ENDIF
// Countdown still displaying.
RETURN TRUE
ENDFUNC
*/
FUNC BOOL TRI_Finish_Display(TRI_DISPLAY_STRUCT& Display)
//DEBUG_MESSAGE("TRI_Finish_Display")
IF NOT IS_TIMER_STARTED(Display.tCnt)
RESTART_TIMER_NOW(Display.tCnt) //not sure if timer is used elsewhereso keeping it here, prob safe to remove tho- SiM - 10/31/2011
ENDIF
MISSION_FLOW_PLAY_END_OF_MISSION_MUSIC(TRUE)
RETURN TRUE
ENDFUNC
PROC TRI_Rank_Display(INT iRank, FLOAT fPosX, FLOAT fPosY, FLOAT fScale)
//DEBUG_MESSAGE("TRI_Rank_Display")
TEXT_LABEL_15 szRank
SWITCH iRank
CASE 1
szRank = "SPR_PLACE_ST"
BREAK
CASE 2
szRank = "SPR_PLACE_ND"
BREAK
CASE 3
szRank = "SPR_PLACE_RD"
BREAK
DEFAULT
szRank = "SPR_PLACE_TH"
BREAK
ENDSWITCH
SET_TEXT_SCALE(fScale, fScale)
DISPLAY_TEXT_WITH_NUMBER(fPosX, fPosY, szRank, iRank)
ENDPROC
PROC TRI_Clock_GetComponents(FLOAT fClock, INT& iMinutes, INT& iSeconds, INT& iMilliSecs)
//DEBUG_MESSAGE("TRI_Clock_GetComponents")
// Get total milliseconds on clock.
INT iTotal = ROUND(fClock * 1000.0)
// Use millisecond total to get clock components (m/s/ms).
iMinutes = (iTotal / 1000) / 60
iSeconds = (iTotal - (iMinutes * 60 * 1000)) / 1000
iMilliSecs = (iTotal - ((iSeconds + (iMinutes * 60)) * 1000))
ENDPROC
FUNC TEXT_LABEL_15 TRI_Clock_MakeString(FLOAT fClock, FLOAT& fPosX, FLOAT fScale, BOOL bDynamic)
//DEBUG_MESSAGE("TRI_Clock_MakeString")
// Local variables.
TEXT_LABEL_15 szClock
INT iMinutes, iSeconds, iMilliSecs
FLOAT fNumWidth = TRI_HUD_NUM_WIDTH * fScale
FLOAT fClnWidth = TRI_HUD_CLN_WIDTH * fScale
// Get clock components (m/s/ms).
TRI_Clock_GetComponents(fClock, iMinutes, iSeconds, iMilliSecs)
// Truncate milliseconds (dynamic - tenths, static - hundreths).
IF bDynamic
iMilliSecs /= 100
ELSE
iMilliSecs /= 10
ENDIF
// Assemble string from clock components (dynamic - #:##.#, static - ##:##.##).
IF (iMinutes < 10)
IF bDynamic
IF (iMinutes >= 1)
fPosX += fNumWidth
ENDIF
ELSE
szClock += "0"
ENDIF
ENDIF
IF (iMinutes < 1)
IF bDynamic
fPosX += fNumWidth
fPosX += fClnWidth
ELSE
szClock += "0:"
ENDIF
ELSE
szClock += iMinutes
szClock += ":"
ENDIF
IF (iSeconds < 10)
IF bDynamic
AND (iMinutes < 1)
fPosX += fNumWidth
ELSE
szClock += "0"
ENDIF
ENDIF
IF (iSeconds < 1)
IF bDynamic
AND (iMinutes < 1)
fPosX += fNumWidth
ELSE
szClock += "0"
ENDIF
ELSE
szClock += iSeconds
ENDIF
szClock += "."
szClock += iMilliSecs
IF NOT bDynamic
AND (iMilliSecs < 10)
szClock += "0"
ENDIF
// Return clock string.
RETURN szClock
ENDFUNC
PROC TRI_Clock_Display(FLOAT fClock, FLOAT fPosX, FLOAT fPosY, FLOAT fScale, BOOL bDynamic)
//DEBUG_MESSAGE("TRI_Clock_Display")
// Make clock string and offset position to accommodate format (dynamic/static).
TRI_Clock_MakeString(fClock, fPosX, fScale, bDynamic) //still using for scale
// Display clock string at desired position/scale.
SET_TEXT_SCALE(fScale, fScale)
BEGIN_TEXT_COMMAND_DISPLAY_TEXT("STRING")
ADD_TEXT_COMPONENT_SUBSTRING_TIME(FLOOR(fClock*1000), TIME_FORMAT_MINUTES|TIME_FORMAT_SECONDS|TIME_FORMAT_MILLISECONDS)
END_TEXT_COMMAND_DISPLAY_TEXT(fPosX, fPosY)
ENDPROC
FUNC TEXT_LABEL_15 TRI_PlusMinus_MakeString(FLOAT fPlusMinus, FLOAT& fPosX, FLOAT fScale, BOOL bPlusMinus)
//DEBUG_MESSAGE("TRI_PlusMinus_MakeString")
// Local variables.
TEXT_LABEL_15 szPlusMinus
INT iMinutes, iSeconds, iMilliSecs
FLOAT fNumWidth = TRI_HUD_NUM_WIDTH * fScale
FLOAT fClnWidth = TRI_HUD_CLN_WIDTH * fScale
// Get clock components (m/s/ms).
TRI_Clock_GetComponents(fPlusMinus, iMinutes, iSeconds, iMilliSecs)
// Truncate milliseconds (hundreths).
iMilliSecs /= 10
// Start string with a plus/minus accordingly.
IF bPlusMinus
szPlusMinus = "+"
fPosX -= (TRI_HUD_PLS_WIDTH * fScale)
ELSE
szPlusMinus = "-"
fPosX -= (TRI_HUD_MNS_WIDTH * fScale)
ENDIF
// Assemble string from clock components (plus - +##:##.##, minus - -##:##.##).
IF (iMinutes < 10)
IF (iMinutes >= 1)
fPosX += fNumWidth
ENDIF
ENDIF
IF (iMinutes < 1)
fPosX += fNumWidth
fPosX += fClnWidth
ELSE
szPlusMinus += iMinutes
szPlusMinus += ":"
ENDIF
IF (iSeconds < 10)
IF (iMinutes < 1)
fPosX += fNumWidth
ELSE
szPlusMinus += "0"
ENDIF
ENDIF
IF (iSeconds < 1)
IF (iMinutes < 1)
fPosX += fNumWidth
ELSE
szPlusMinus += "0"
ENDIF
ELSE
szPlusMinus += iSeconds
ENDIF
szPlusMinus += "."
szPlusMinus += iMilliSecs
IF (iMilliSecs < 10)
szPlusMinus += "0"
ENDIF
// Return plus/minus string.
RETURN szPlusMinus
ENDFUNC
PROC TRI_RadarOverlay_Display(FLOAT fRacerRoll)
//DEBUG_MESSAGE("TRI_RadarOverlay_Display")
// TODO: Ask Alwyn why this isn't drawing over HUD.
// Calculate radar overlay rotation using racer roll.
FLOAT fOverlayRot = fRacerRoll * TRI_HUD_RADAR_ROT_SCL
// Display radar overlay (sprite).
DRAW_SPRITE("PilotSchool", "PlaneRadarOver",
TRI_HUD_RADAR_POS_X, TRI_HUD_RADAR_POS_Y,
TRI_HUD_RADAR_WIDTH, TRI_HUD_RADAR_HEIGHT,
fOverlayRot, 128, 255, 128, 128)
ENDPROC
// -----------------------------------
// FILE I/O PROCS/FUNCTIONS
// -----------------------------------
#IF IS_DEBUG_BUILD
FUNC TEXT_LABEL_31 TRI_FileName_MakeString(STRING sFileName)
//DEBUG_MESSAGE("TRI_FileName_MakeString")
STRING sValid = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789"
INT i, j
BOOL bStrValid = FALSE
BOOL bChrValid = FALSE
TEXT_LABEL_31 szFileName
TEXT_LABEL_3 szBuf1, szBuf2
REPEAT GET_LENGTH_OF_LITERAL_STRING(sFileName) i
bChrValid = FALSE
szBuf1 = GET_STRING_FROM_STRING(sFileName, i, i + 1)
REPEAT GET_LENGTH_OF_LITERAL_STRING(sValid) j
szBuf2 = GET_STRING_FROM_STRING(sValid, j, j + 1)
IF ARE_STRINGS_EQUAL(szBuf1, szBuf2)
j = GET_LENGTH_OF_LITERAL_STRING(sValid)
bChrValid = TRUE
ENDIF
ENDREPEAT
IF bChrValid
bStrValid = TRUE
szFileName += szBuf1
ELIF bStrValid
szBuf1 = "_"
szFileName += szBuf1
ENDIF
IF (GET_LENGTH_OF_LITERAL_STRING(szFileName) >= 30)
i = GET_LENGTH_OF_LITERAL_STRING(sFileName)
ENDIF
ENDREPEAT
IF NOT bStrValid
szFileName = ""
ENDIF
RETURN szFileName
ENDFUNC
FUNC BOOL TRI_XML_Load(STRING sFileName)
//DEBUG_MESSAGE("SPR_XML_Load")
IF NOT LOAD_XML_FILE(sFileName)
DEBUG_MESSAGE("SPR_XML_Load: Can't open XML file!")
RETURN FALSE
ENDIF
IF (GET_NUMBER_OF_XML_NODES() = 0)
DEBUG_MESSAGE("SPR_XML_Load: XML file has zero nodes!")
RETURN FALSE
ENDIF
RETURN TRUE
ENDFUNC
PROC TRI_XML_GetRootNode(INT& iXMLNodeCnt, INT& iXMLNodeName)
//DEBUG_MESSAGE("SPR_XML_GetRootNode")
iXMLNodeCnt = 0
iXMLNodeName = GET_HASH_KEY(GET_XML_NODE_NAME())
ENDPROC
PROC TRI_XML_GetNextNode(INT& iXMLNodeCnt, INT& iXMLNodeName)
//DEBUG_MESSAGE("SPR_XML_GetNextNode")
GET_NEXT_XML_NODE()
++iXMLNodeCnt
iXMLNodeName = GET_HASH_KEY(GET_XML_NODE_NAME())
ENDPROC
PROC TRI_HashKey_PrintString(STRING sString)
//DEBUG_MESSAGE("SPR_HashKey_PrintString")
PRINTSTRING("STRING - HASHKEY : ")
PRINTSTRING(sString)
PRINTSTRING(" - ")
PRINTINT(GET_HASH_KEY(sString))
PRINTNL()
ENDPROC
#ENDIF // IS_DEBUG_BUILD
// -----------------------------------
// WIDGET PROCS/FUNCTIONS
// -----------------------------------
PROC TRI_ChkpntType_Populate(TEXT_LABEL_31& szChkpntType[])
//DEBUG_MESSAGE("TRI_ChkpntType_Populate")
szChkpntType[0] = "Offroad Default"
szChkpntType[1] = "Offroad Finish"
szChkpntType[2] = "Stunt Plane Default"
szChkpntType[3] = "Stunt Plane Finish"
szChkpntType[4] = "Triathlon Swim"
szChkpntType[5] = "Triathlon Bike"
szChkpntType[6] = "Triathlon Run"
szChkpntType[7] = "Triathlon Finish"
szChkpntType[8] = "Triathlon Swim>Bike"
szChkpntType[9] = "Triathlon Bike>Run"
ENDPROC
FUNC TRI_RACE_CHECKPOINT_TYPE TRI_ChkpntType_GetEnum(INT iChkpntType)
//DEBUG_MESSAGE("TRI_ChkpntType_GetEnum")
TRI_RACE_CHECKPOINT_TYPE eChkpntType
SWITCH iChkpntType
// Ground Arrow.
CASE 0
eChkpntType = TRI_CHKPT_OFFROAD_DEFAULT
BREAK
// Ground Flag.
CASE 1
eChkpntType = TRI_CHKPT_OFFROAD_FINISH
BREAK
// Air Arrow.
CASE 2
eChkpntType = TRI_CHKPT_STUNT_DEFAULT
BREAK
// Air Flag.
CASE 3
eChkpntType = TRI_CHKPT_STUNT_FINISH
BREAK
// Water Arrow.
CASE 4
eChkpntType = TRI_CHKPT_TRI_SWIM
BREAK
// Water Arrow.
CASE 5
eChkpntType = TRI_CHKPT_TRI_BIKE
BREAK
// Water Arrow.
CASE 6
eChkpntType = TRI_CHKPT_TRI_RUN
BREAK
// Water Flag.
CASE 7
eChkpntType = TRI_CHKPT_TRI_FINISH
BREAK
CASE 8
eChkpntType = TRI_CHKPT_TRI_FIRST_TRANS
BREAK
CASE 9
eChkpntType = TRI_CHKPT_TRI_SECOND_TRANS
BREAK
ENDSWITCH
RETURN eChkpntType
ENDFUNC
FUNC INT TRI_ChkpntType_GetIndex(TRI_RACE_CHECKPOINT_TYPE eChkpntType)
//DEBUG_MESSAGE("TRI_ChkpntType_GetIndex")
INT iChkpntType
SWITCH eChkpntType
// Ground Arrow.
CASE TRI_CHKPT_OFFROAD_DEFAULT
iChkpntType = 0
BREAK
// Ground Flag.
CASE TRI_CHKPT_OFFROAD_FINISH
iChkpntType = 1
BREAK
// Air Arrow.
CASE TRI_CHKPT_STUNT_DEFAULT
iChkpntType = 2
BREAK
// Air Flag.
CASE TRI_CHKPT_STUNT_FINISH
iChkpntType = 3
BREAK
// Water Arrow.
CASE TRI_CHKPT_TRI_SWIM
iChkpntType = 4
BREAK
// Water Arrow.
CASE TRI_CHKPT_TRI_BIKE
iChkpntType = 5
BREAK
// Water Arrow.
CASE TRI_CHKPT_TRI_RUN
iChkpntType = 6
BREAK
// Water Flag.
CASE TRI_CHKPT_TRI_FINISH
iChkpntType = 7
BREAK
// Water Flag.
CASE TRI_CHKPT_TRI_FIRST_TRANS
iChkpntType = 8
BREAK
// Water Flag.
CASE TRI_CHKPT_TRI_SECOND_TRANS
iChkpntType = 9
BREAK
ENDSWITCH
RETURN iChkpntType
ENDFUNC
FUNC TEXT_LABEL_31 TRI_ChkpntType_GetString(TRI_RACE_CHECKPOINT_TYPE eChkpntType)
//DEBUG_MESSAGE("TRI_ChkpntType_GetString")
TEXT_LABEL_31 szChkpntType
SWITCH eChkpntType
// Ground Arrow.
CASE TRI_CHKPT_OFFROAD_DEFAULT
szChkpntType = "TRI_CHKPT_OFFROAD_DEFAULT"
BREAK
// Ground Flag.
CASE TRI_CHKPT_OFFROAD_FINISH
szChkpntType = "TRI_CHKPT_OFFROAD_FINISH"
BREAK
// Air Arrow.
CASE TRI_CHKPT_STUNT_DEFAULT
szChkpntType = "TRI_CHKPT_STUNT_DEFAULT"
BREAK
// Air Flag.
CASE TRI_CHKPT_STUNT_FINISH
szChkpntType = "TRI_CHKPT_STUNT_FINISH"
BREAK
// Water Arrow.
CASE TRI_CHKPT_TRI_SWIM
szChkpntType = "TRI_CHKPT_TRI_SWIM"
BREAK
// Water Flag.
CASE TRI_CHKPT_TRI_BIKE
szChkpntType = "TRI_CHKPT_TRI_BIKE"
BREAK
// Water Arrow.
CASE TRI_CHKPT_TRI_RUN
szChkpntType = "TRI_CHKPT_TRI_RUN"
BREAK
// Water Flag.
CASE TRI_CHKPT_TRI_FINISH
szChkpntType = "TRI_CHKPT_TRI_FINISH"
BREAK
// Water Flag.
CASE TRI_CHKPT_TRI_FIRST_TRANS
szChkpntType = "TRI_CHKPT_TRI_FIRST_TRANS"
BREAK
// Water Flag.
CASE TRI_CHKPT_TRI_SECOND_TRANS
szChkpntType = "TRI_CHKPT_TRI_SECOND_TRANS"
BREAK
ENDSWITCH
RETURN szChkpntType
ENDFUNC
PROC TRI_DriverType_Populate(TEXT_LABEL_31& szDriverType[])
//DEBUG_MESSAGE("TRI_DriverType_Populate")
szDriverType[0] = "Player"
szDriverType[1] = "AI Male"
szDriverType[2] = "AI Female"
szDriverType[3] = "Triathlon Male"
ENDPROC
FUNC PED_TYPE TRI_DriverType_GetEnum(INT iDriverType)
//DEBUG_MESSAGE("TRI_DriverType_GetEnum")
PED_TYPE eDriverType
SWITCH iDriverType
// Player.
CASE 0
eDriverType = PEDTYPE_PLAYER1
BREAK
// AI Male.
CASE 1
eDriverType = PEDTYPE_CIVMALE
BREAK
// AI Female.
CASE 2
eDriverType = PEDTYPE_CIVFEMALE
BREAK
ENDSWITCH
RETURN eDriverType
ENDFUNC
FUNC INT TRI_DriverType_GetIndex(PED_TYPE eDriverType)
//DEBUG_MESSAGE("TRI_DriverType_GetIndex")
INT iDriverType
SWITCH eDriverType
// Player.
CASE PEDTYPE_PLAYER1
iDriverType = 0
BREAK
// AI Male.
CASE PEDTYPE_CIVMALE
iDriverType = 1
BREAK
// AI Female.
CASE PEDTYPE_CIVFEMALE
iDriverType = 2
BREAK
ENDSWITCH
RETURN iDriverType
ENDFUNC
FUNC TEXT_LABEL_31 TRI_DriverType_GetString(PED_TYPE eDriverType)
//DEBUG_MESSAGE("TRI_DriverType_GetString")
TEXT_LABEL_31 szDriverType
SWITCH eDriverType
// Player.
CASE PEDTYPE_PLAYER1
szDriverType = "PEDTYPE_PLAYER1"
BREAK
// AI Male.
CASE PEDTYPE_CIVMALE
szDriverType = "PEDTYPE_CIVMALE"
BREAK
// AI Female.
CASE PEDTYPE_CIVFEMALE
szDriverType = "PEDTYPE_CIVFEMALE"
BREAK
ENDSWITCH
RETURN szDriverType
ENDFUNC
PROC TRI_DriverModel_Populate(TEXT_LABEL_31& szDriverModel[])
//DEBUG_MESSAGE("TRI_DriverModel_Populate")
szDriverModel[0] = "Player"
szDriverModel[1] = "AI Male"
szDriverModel[2] = "AI Female"
szDriverModel[3] = "Triathlon Male"
ENDPROC
FUNC MODEL_NAMES TRI_DriverModel_GetEnum(INT iDriverModel)
//DEBUG_MESSAGE("TRI_DriverModel_GetEnum")
MODEL_NAMES eDriverModel
SWITCH iDriverModel
// Player.
CASE 0
eDriverModel = PLAYER_ONE
BREAK
// AI Male.
CASE 1
eDriverModel = A_M_Y_GENSTREET_01
BREAK
// AI Female.
CASE 2
eDriverModel = A_F_Y_TOURIST_01
BREAK
// AI Female.
CASE 3
eDriverModel = A_M_Y_RoadCyc_01
BREAK
ENDSWITCH
RETURN eDriverModel
ENDFUNC
FUNC INT TRI_DriverModel_GetIndex(MODEL_NAMES eDriverModel)
//DEBUG_MESSAGE("TRI_DriverModel_GetIndex")
INT iDriverModel
SWITCH eDriverModel
// Player.
CASE PLAYER_ONE
iDriverModel = 0
BREAK
// AI Male.
CASE A_M_Y_GENSTREET_01
iDriverModel = 1
BREAK
// AI Female.
CASE A_F_Y_TOURIST_01
iDriverModel = 2
BREAK
// AI Female.
CASE A_M_Y_RoadCyc_01
iDriverModel = 3
BREAK
ENDSWITCH
RETURN iDriverModel
ENDFUNC
FUNC TEXT_LABEL_31 TRI_DriverModel_GetString(MODEL_NAMES eDriverModel)
//DEBUG_MESSAGE("TRI_DriverModel_GetString")
TEXT_LABEL_31 szDriverModel
SWITCH eDriverModel
// Player.
CASE PLAYER_ONE
szDriverModel = "PLAYER_ONE"
BREAK
// AI Male.
CASE A_M_Y_GENSTREET_01
szDriverModel = "A_M_Y_GENSTREET_01"
BREAK
// AI Female.
CASE A_F_Y_TOURIST_01
szDriverModel = "A_F_Y_TOURIST_01"
BREAK
// AI Female.
CASE A_M_Y_RoadCyc_01
szDriverModel = "A_M_Y_RoadCyc_01"
BREAK
ENDSWITCH
RETURN szDriverModel
ENDFUNC
PROC TRI_VehicleModel_Populate(TEXT_LABEL_31& szVehicleModel[])
//DEBUG_MESSAGE("TRI_VehicleModel_Populate")
szVehicleModel[0] = "Cheetah (Sport)"
szVehicleModel[1] = "Infernus (Sport)"
szVehicleModel[2] = "JB700 (Sport)"
szVehicleModel[3] = "Monroe (Sport)"
szVehicleModel[4] = "Ninef 1 (Sport)"
szVehicleModel[5] = "Ninef 2 (Sport)"
szVehicleModel[6] = "Rapid GT 1 (Sport)"
szVehicleModel[7] = "Rapid GT 2 (Sport)"
szVehicleModel[8] = "Z Type (Sport)"
szVehicleModel[9] = "Entity XF (Sport)"
szVehicleModel[10] = "BF Injection 1 (2-Door)"
szVehicleModel[11] = "Bison (2-Door)"
szVehicleModel[12] = "Dominator (2-Door)"
szVehicleModel[13] = "Feltzer 2010 (2-Door)"
szVehicleModel[14] = "Penumbra (2-Door)"
szVehicleModel[15] = "Phoenix (2-Door)"
szVehicleModel[16] = "Stinger (2-Door)"
szVehicleModel[17] = "Cargobob (Helicopter)"
szVehicleModel[18] = "Maverick (Helicopter)"
szVehicleModel[19] = "Picador (2-Door)"
szVehicleModel[20] = "Tornado (2-Door)"
szVehicleModel[21] = "Baller (4-Door)"
szVehicleModel[22] = "Dubsta 1 (4-Door)"
szVehicleModel[23] = "Dubsta 2 (4-Door)"
szVehicleModel[24] = "FQ2 (4-Door)"
szVehicleModel[25] = "Granger (4-Door)"
szVehicleModel[26] = "Mesa (4-Door)"
szVehicleModel[27] = "Radius (4-Door)"
szVehicleModel[28] = "Sadler (4-Door)"
szVehicleModel[29] = "Surfer 1 (4-Door)"
szVehicleModel[30] = "Surfer 2 (4-Door)"
szVehicleModel[31] = "BJXL (4-Door)"
szVehicleModel[32] = "Jackal (4-Door)"
szVehicleModel[33] = "Blazer (4-Wheeler)"
szVehicleModel[34] = "Hexer (Motorcycle)"
szVehicleModel[35] = "Vader 1 (Motorcycle)"
szVehicleModel[36] = "Vader 2 (Motorcycle)"
szVehicleModel[37] = "Sanchez (Dirtbike)"
szVehicleModel[38] = "Faggio (Moped)"
szVehicleModel[39] = "BMX (Bicycle)"
szVehicleModel[40] = "Scorcher (Bicycle)"
szVehicleModel[41] = "Skivvy 1 (Boat)" //deprecated!!!
szVehicleModel[42] = "Skivvy 2 (Boat)" //deprecated!!!
szVehicleModel[43] = "Seashark (Jetski)"
szVehicleModel[44] = "Cuban 800 (Plane)"
szVehicleModel[45] = "Stunt (Plane)"
szVehicleModel[47] = "On Foot (No Vehicle)"
ENDPROC
FUNC MODEL_NAMES TRI_VehicleModel_GetEnum(INT iVehicleModel)
//DEBUG_MESSAGE("TRI_VehicleModel_GetEnum")
MODEL_NAMES eVehicleModel
SWITCH iVehicleModel
// Cheetah (Sport).
CASE 0
eVehicleModel = CHEETAH
BREAK
// Infernus (Sport).
CASE 1
eVehicleModel = INFERNUS
BREAK
// JB700 (Sport).
CASE 2
eVehicleModel = JB700
BREAK
// Monroe (Sport).
CASE 3
eVehicleModel = MONROE
BREAK
// Ninef 1 (Sport).
CASE 4
eVehicleModel = NINEF
BREAK
// Ninef 2 (Sport).
CASE 5
eVehicleModel = NINEF2
BREAK
// Rapid GT 1 (Sport).
CASE 6
eVehicleModel = RAPIDGT
BREAK
// Rapid GT 2 (Sport).
CASE 7
eVehicleModel = RAPIDGT2
BREAK
// Z Type (Sport).
CASE 8
eVehicleModel = ZTYPE
BREAK
// Entity XF (Sport).
CASE 9
eVehicleModel = ENTITYXF
BREAK
// BF Injection 1 (2-Door).
CASE 10
eVehicleModel = BFINJECTION
BREAK
// Bison (2-Door).
CASE 11
eVehicleModel = BISON
BREAK
// Dominator (2-Door).
CASE 12
eVehicleModel = DOMINATOR
BREAK
// Feltzer 2010 (2-Door).
CASE 13
eVehicleModel = FELTZER2
BREAK
// Penumbra (2-Door).
CASE 14
eVehicleModel = PENUMBRA
BREAK
// Phoenix (2-Door).
CASE 15
eVehicleModel = PHOENIX
BREAK
// Stinger (2-Door).
CASE 16
eVehicleModel = STINGER
BREAK
// Maverick (Helicopter).
CASE 17
eVehicleModel = CARGOBOB
BREAK
// Cargobob (Helicopter).
CASE 18
eVehicleModel = MAVERICK
BREAK
// Picador (2-Door).
CASE 19
eVehicleModel = PICADOR
BREAK
// Tornado (2-Door).
CASE 20
eVehicleModel = TORNADO
BREAK
// Baller (4-Door).
CASE 21
eVehicleModel = BALLER
BREAK
// Dubsta 1 (4-Door).
CASE 22
eVehicleModel = DUBSTA
BREAK
// Dubsta 2 (4-Door).
CASE 23
eVehicleModel = DUBSTA2
BREAK
// FQ2 (4-Door).
CASE 24
eVehicleModel = FQ2
BREAK
// Granger (4-Door).
CASE 25
eVehicleModel = GRANGER
BREAK
// Mesa (4-Door).
CASE 26
eVehicleModel = MESA
BREAK
// Radius (4-Door).
CASE 27
eVehicleModel = RADI
BREAK
// Sadler (4-Door).
CASE 28
eVehicleModel = SADLER
BREAK
// Surfer 1 (4-Door).
CASE 29
eVehicleModel = SURFER
BREAK
// Surfer 2 (4-Door).
CASE 30
eVehicleModel = SURFER2
BREAK
// BJXL (4-Door).
CASE 31
eVehicleModel = BJXL
BREAK
// Jackal (4-Door).
CASE 32
eVehicleModel = JACKAL
BREAK
// Blazer (4-Wheeler).
CASE 33
eVehicleModel = BLAZER
BREAK
// Hexer (Motorcycle).
CASE 34
eVehicleModel = HEXER
BREAK
// Vader 1 (Motorcycle).
CASE 35
eVehicleModel = VADER
BREAK
// Vader 2 (Motorcycle).
CASE 36
eVehicleModel = VADER
BREAK
// Sanchez (Dirtbike).
CASE 37
eVehicleModel = SANCHEZ
BREAK
// Faggio (Moped).
CASE 38
eVehicleModel = FAGGIO2
BREAK
// BMX (Bicycle).
CASE 39
eVehicleModel = BMX
BREAK
// Scorcher (Bicycle).
CASE 40
eVehicleModel = SCORCHER
BREAK
// Seashark (Jetski).
CASE 43
eVehicleModel = SEASHARK
BREAK
// Cuban 800 (Plane).
CASE 44
eVehicleModel = CUBAN800
BREAK
// Stunt (Plane).
CASE 45
eVehicleModel = STUNT
BREAK
// On Foot (No Vehicle).
CASE 47
eVehicleModel = DUMMY_MODEL_FOR_SCRIPT
BREAK
ENDSWITCH
RETURN eVehicleModel
ENDFUNC
FUNC INT TRI_VehicleModel_GetIndex(MODEL_NAMES eVehicleModel)
//DEBUG_MESSAGE("TRI_VehicleModel_GetIndex")
INT iVehicleModel
SWITCH eVehicleModel
// Cheetah (Sport).
CASE CHEETAH
iVehicleModel = 0
BREAK
// Infernus (Sport).
CASE INFERNUS
iVehicleModel = 1
BREAK
// JB700 (Sport).
CASE JB700
iVehicleModel = 2
BREAK
// Monroe (Sport).
CASE MONROE
iVehicleModel = 3
BREAK
// Ninef 1 (Sport).
CASE NINEF
iVehicleModel = 4
BREAK
// Ninef 2 (Sport).
CASE NINEF2
iVehicleModel = 5
BREAK
// Rapid GT 1 (Sport).
CASE RAPIDGT
iVehicleModel = 6
BREAK
// Rapid GT 2 (Sport).
CASE RAPIDGT2
iVehicleModel = 7
BREAK
// Z Type (Sport).
CASE ZTYPE
iVehicleModel = 8
BREAK
// Entity XF (Sport).
CASE ENTITYXF
iVehicleModel = 9
BREAK
// BF Injection 1 (2-Door).
CASE BFINJECTION
iVehicleModel = 10
BREAK
// Bison (2-Door).
CASE BISON
iVehicleModel = 11
BREAK
// Dominator (2-Door).
CASE DOMINATOR
iVehicleModel = 12
BREAK
// Feltzer 2010 (2-Door).
CASE FELTZER2
iVehicleModel = 13
BREAK
// Penumbra (2-Door).
CASE PENUMBRA
iVehicleModel = 14
BREAK
// Phoenix (2-Door).
CASE PHOENIX
iVehicleModel = 15
BREAK
// Stinger (2-Door).
CASE STINGER
iVehicleModel = 16
BREAK
// Cargobob (Helicopter).
CASE CARGOBOB
iVehicleModel = 17
BREAK
// Maverick (Helicopter).
CASE MAVERICK
iVehicleModel = 18
BREAK
// Picador (2-Door).
CASE PICADOR
iVehicleModel = 19
BREAK
// Tornado (2-Door).
CASE TORNADO
iVehicleModel = 20
BREAK
// Baller (4-Door).
CASE BALLER
iVehicleModel = 21
BREAK
// Dubsta 1 (4-Door).
CASE DUBSTA
iVehicleModel = 22
BREAK
// Dubsta 2 (4-Door).
CASE DUBSTA2
iVehicleModel = 23
BREAK
// FQ2 (4-Door).
CASE FQ2
iVehicleModel = 24
BREAK
// Granger (4-Door).
CASE GRANGER
iVehicleModel = 25
BREAK
// Mesa (4-Door).
CASE MESA
iVehicleModel = 26
BREAK
// Radius (4-Door).
CASE RADI
iVehicleModel = 27
BREAK
// Sadler (4-Door).
CASE SADLER
iVehicleModel = 28
BREAK
// Surfer 1 (4-Door).
CASE SURFER
iVehicleModel = 29
BREAK
// Surfer 2 (4-Door).
CASE SURFER2
iVehicleModel = 30
BREAK
// BJXL (4-Door).
CASE BJXL
iVehicleModel = 31
BREAK
// Jackal (4-Door).
CASE JACKAL
iVehicleModel = 32
BREAK
// Blazer (4-Wheeler).
CASE BLAZER
iVehicleModel = 33
BREAK
// Hexer (Motorcycle).
CASE HEXER
iVehicleModel = 34
BREAK
// Vader 1 (Motorcycle).
CASE VADER
iVehicleModel = 35
BREAK
// Vader 2 (Motorcycle).
// CASE VADER2
// iVehicleModel = 36
// BREAK
// Sanchez (Dirtbike).
CASE SANCHEZ
iVehicleModel = 37
BREAK
// Faggio (Moped).
CASE FAGGIO2
iVehicleModel = 38
BREAK
// BMX (Bicycle).
CASE BMX
iVehicleModel = 39
BREAK
// Scorcher (Bicycle).
CASE SCORCHER
iVehicleModel = 40
BREAK
// Seashark (Jetski).
CASE SEASHARK
iVehicleModel = 43
BREAK
// Cuban 800 (Plane).
CASE CUBAN800
iVehicleModel = 44
BREAK
// Stunt (Plane).
CASE STUNT
iVehicleModel = 45
BREAK
// On Foot (No Vehicle).
CASE DUMMY_MODEL_FOR_SCRIPT
iVehicleModel = 47
BREAK
ENDSWITCH
RETURN iVehicleModel
ENDFUNC
FUNC TEXT_LABEL_31 TRI_VehicleModel_GetString(MODEL_NAMES eVehicleModel)
//DEBUG_MESSAGE("TRI_VehicleModel_GetString")
TEXT_LABEL_31 szVehicleModel
SWITCH eVehicleModel
// Cheetah (Sport).
CASE CHEETAH
szVehicleModel = "CHEETAH"
BREAK
// Infernus (Sport).
CASE INFERNUS
szVehicleModel = "INFERNUS"
BREAK
// JB700 (Sport).
CASE JB700
szVehicleModel = "JB700"
BREAK
// Monroe (Sport).
CASE MONROE
szVehicleModel = "MONROE"
BREAK
// Ninef 1 (Sport).
CASE NINEF
szVehicleModel = "NINEF"
BREAK
// Ninef 2 (Sport).
CASE NINEF2
szVehicleModel = "NINEF2"
BREAK
// Rapid GT 1 (Sport).
CASE RAPIDGT
szVehicleModel = "RAPIDGT"
BREAK
// Rapid GT 2 (Sport).
CASE RAPIDGT2
szVehicleModel = "RAPIDGT"//1624012
BREAK
// Z Type (Sport).
CASE ZTYPE
szVehicleModel = "ZTYPE"
BREAK
// Entity XF (Sport).
CASE ENTITYXF
szVehicleModel = "ENTITYXF"
BREAK
// BF Injection 1 (2-Door).
CASE BFINJECTION
szVehicleModel = "BFINJECTION"
BREAK
// Bison (2-Door).
CASE BISON
szVehicleModel = "BISON"
BREAK
// Dominator (2-Door).
CASE DOMINATOR
szVehicleModel = "DOMINATOR"
BREAK
// Penumbra (2-Door).
CASE PENUMBRA
szVehicleModel = "PENUMBRA"
BREAK
// Phoenix (2-Door).
CASE PHOENIX
szVehicleModel = "PHOENIX"
BREAK
// Stinger (2-Door).
CASE STINGER
szVehicleModel = "STINGER"
BREAK
// Cargobob (Helicopter).
CASE CARGOBOB
szVehicleModel = "CARGOBOB"
BREAK
// Maverick (Helicopter).
CASE MAVERICK
szVehicleModel = "MAVERICK"
BREAK
// Picador (2-Door).
CASE PICADOR
szVehicleModel = "PICADOR"
BREAK
// Tornado (2-Door).
CASE TORNADO
szVehicleModel = "TORNADO"
BREAK
// Baller (4-Door).
CASE BALLER
szVehicleModel = "BALLER"
BREAK
// Dubsta 1 (4-Door).
CASE DUBSTA
szVehicleModel = "DUBSTA"
BREAK
// Dubsta 2 (4-Door).
CASE DUBSTA2
szVehicleModel = "DUBSTA2"
BREAK
// FQ2 (4-Door).
CASE FQ2
szVehicleModel = "FQ2"
BREAK
// Granger (4-Door).
CASE GRANGER
szVehicleModel = "GRANGER"
BREAK
// Mesa (4-Door).
CASE MESA
szVehicleModel = "MESA"
BREAK
// Radius (4-Door).
CASE RADI
szVehicleModel = "RADI"
BREAK
// Sadler (4-Door).
CASE SADLER
szVehicleModel = "SADLER"
BREAK
// Surfer 1 (4-Door).
CASE SURFER
szVehicleModel = "SURFER"
BREAK
// Surfer 2 (4-Door).
CASE SURFER2
szVehicleModel = "SURFER2"
BREAK
// BJXL (4-Door).
CASE BJXL
szVehicleModel = "BJXL"
BREAK
// Jackal (4-Door).
CASE JACKAL
szVehicleModel = "JACKAL"
BREAK
// Blazer (4-Wheeler).
CASE BLAZER
szVehicleModel = "BLAZER"
BREAK
// Hexer (Motorcycle).
CASE HEXER
szVehicleModel = "HEXER"
BREAK
// Vader 1 (Motorcycle).
CASE VADER
szVehicleModel = "VADER"
BREAK
// Vader 2 (Motorcycle).
// CASE VADER2
// szVehicleModel = "VADER2"
// BREAK
// Sanchez (Dirtbike).
CASE SANCHEZ
szVehicleModel = "SANCHEZ"
BREAK
// Faggio (Moped).
CASE FAGGIO2
szVehicleModel = "FAGGIO2"
BREAK
// BMX (Bicycle).
CASE BMX
szVehicleModel = "BMX"
BREAK
// Scorcher (Bicycle).
CASE SCORCHER
szVehicleModel = "SCORCHER"
BREAK
// Seashark (Jetski).
CASE SEASHARK
szVehicleModel = "SEASHARK"
BREAK
// Cuban 800 (Plane).
CASE CUBAN800
szVehicleModel = "CUBAN800"
BREAK
// Stunt (Plane).
CASE STUNT
szVehicleModel = "STUNT"
BREAK
// On Foot (No Vehicle).
CASE DUMMY_MODEL_FOR_SCRIPT
szVehicleModel = "DUMMY_MODEL_FOR_SCRIPT"
BREAK
ENDSWITCH
RETURN szVehicleModel
ENDFUNC
// -----------------------------------
// MISC PROCS/FUNCTION
// -----------------------------------
// TODO: Organize these into proper categories.
FUNC TEXT_LABEL_31 TRI_RacerName_GetString(INT nLookUp)
TEXT_LABEL_31 szRacerName
SWITCH (nLookUp)
CASE 0
szRacerName = "Michael Bagley"
BREAK
CASE 1
szRacerName = "Alan Blaine"
BREAK
CASE 2
szRacerName = "Chris Bourassa"
BREAK
CASE 3
szRacerName = "Jason Umbriet"
BREAK
CASE 4
szRacerName = "John Diaz"
BREAK
CASE 5
szRacerName = "Goeffry Show"
BREAK
CASE 6
szRacerName = "DJ Jones"
BREAK
CASE 7
szRacerName = "Ghyan Koehne"
BREAK
CASE 8
szRacerName = "Stevie Messinger"
BREAK
CASE 9
szRacerName = "Silas Morse"
BREAK
CASE 10
szRacerName = "Ryan Paradis"
BREAK
CASE 11
szRacerName = "Yomal Perera"
BREAK
CASE 12
szRacerName = "Troy Schram"
BREAK
CASE 13
szRacerName = "John Sripan"
BREAK
CASE 14
szRacerName = "David Stinchcomb"
BREAK
CASE 15
szRacerName = "Stephen Russo"
BREAK
CASE 16
szRacerName = "Adrian Castaneda"
BREAK
CASE 17
szRacerName = "David Kunkler"
BREAK
CASE 18
szRacerName = "Steve Martin"
BREAK
CASE 19
szRacerName = "John Ricchio"
BREAK
CASE 20
szRacerName = "Eric Smith"
BREAK
CASE 21
szRacerName = "Ted Carson"
BREAK
CASE 22
szRacerName = "Michael Currington"
BREAK
CASE 23
szRacerName = "Fredrik Farnstrom"
BREAK
CASE 24
szRacerName = "Andrew Gardner"
BREAK
CASE 25
szRacerName = "Alan Goykhman"
BREAK
CASE 26
szRacerName = "Jason Jurecka"
BREAK
CASE 27
szRacerName = "Jonathan Martin"
BREAK
CASE 28
szRacerName = "Bryan Musson"
BREAK
CASE 29
szRacerName = "Robert Percival"
BREAK
CASE 30
szRacerName = "C. Rakowsky"
BREAK
CASE 31
szRacerName = "Ryan Satrappe"
BREAK
CASE 32
szRacerName = "Tom Shepherd"
BREAK
CASE 33
szRacerName = "Aaron Robuck"
BREAK
DEFAULT
szRacerName = "Racer"
BREAK
ENDSWITCH
RETURN szRacerName
ENDFUNC
PROC TRI_RacerName_Populate(TEXT_LABEL_31& szRacerName[])
INT i, j, iLimit
INT tempNumbers[10]
REPEAT COUNT_OF(szRacerName) i
//szRacerName[i] = TRI_RacerName_GetString()
tempNumbers[i]=GET_RANDOM_INT_IN_RANGE(0, 34)
/*PRINTSTRING("Picking a random number for slot ")
PRINTINT(i)
PRINTNL()*/
IF (i > 0)
j = i - 1
iLimit = 0
WHILE (j >= 0)
/*PRINTINT(i)
PRINTSTRING(" value of ")
PRINTINT(tempNumbers[i])
PRINTSTRING(" vs. ")
PRINTINT(j)
PRINTSTRING(" value of ")
PRINTINT(tempNumbers[j])
PRINTNL()*/
IF tempNumbers[i] = tempNumbers[j] //ARE_STRINGS_EQUAL(szRacerName[i], szRacerName[j])
IF (iLimit < 100)
//szRacerName[i] = TRI_RacerName_GetString()
tempNumbers[i]=GET_RANDOM_INT_IN_RANGE(0, 34)
++iLimit
ELSE
--j
ENDIF
ELSE
iLimit = 0
--j
ENDIF
ENDWHILE
ENDIF
ENDREPEAT
i=0
REPEAT COUNT_OF(szRacerName) i
szRacerName[i]=TRI_RacerName_GetString(tempNumbers[i])
ENDREPEAT
ENDPROC
FUNC TEXT_LABEL TRI_Race_Racer_Format_Time(FLOAT fUnformattedTime)
TEXT_LABEL sFormattedTime = "0:00\:000"
INT iNumMinutes = 0
INT iNumSeconds = 0
INT iNumMilliSeconds = 0
FLOAT fMilliseconds = 0
WHILE fUnformattedTime >= 60.0
iNumMinutes++
fUnformattedTime -= 60.0
ENDWHILE
iNumSeconds = FLOOR(fUnformattedTime)
fMilliseconds = (fUnformattedTime - iNumSeconds)*1000
iNumMilliSeconds = FLOOR(fMilliseconds)
sFormattedTime = iNumMinutes
sFormattedTime += "'"
IF iNumSeconds < 10
sFormattedTime += "0"
ENDIF
sFormattedTime += iNumSeconds
sFormattedTime += "\""
sFormattedTime += iNumMilliSeconds
RETURN sFormattedTime
ENDFUNC
/// PURPOSE:
/// Task ai to go to next gate position.
/// PARAMS:
/// Race -
/// iDriver -
/// iVehicle -
/// vGateGoto -
/// eChkpntType -
/// iRacerIndex -
PROC TRI_Race_Racer_Task_Go_To_Next_Gate(TRI_RACE_STRUCT& Race, PED_INDEX iDriver, VEHICLE_INDEX iVehicle, VECTOR vGateGoto, TRI_RACE_CHECKPOINT_TYPE eChkpntType, INT iRacerIndex)
CPRINTLN(DEBUG_TRIATHLON, "[tri_helpers.sch::TRI_Race_Racer_Task_Go_To_Next_Gate] ", iRacerIndex)
IF NOT IS_ENTITY_DEAD(iDriver)
iVehicle = iVehicle
eChkpntType = eChkpntType //may need for later
TASK_TRI_RACER_TO_FOLLOW_RACE_COURSE(Race, vGateGoto, iRacerIndex)
ELSE
CPRINTLN(DEBUG_TRIATHLON, "[tri_helpers.sch::TRI_Race_Racer_Task_Go_To_Next_Gate] entity is dead for iRacerIndex ", iRacerIndex)
ENDIF
ENDPROC
PROC TRI_SAFELY_SET_SCENARIO_GROUP_ENABLED(STRING sThisGroupName, BOOL bSetActive)
IF NOT IS_STRING_NULL_OR_EMPTY(sThisGroupName)
IF DOES_SCENARIO_GROUP_EXIST(sThisGroupName)
IF NOT IS_SCENARIO_GROUP_ENABLED(sThisGroupName)
SET_SCENARIO_GROUP_ENABLED(sThisGroupName, bSetActive)
ENDIF
ELSE
IF TRI_Master.eRaceType = TRI_RACE_TYPE_OFFROAD
CDEBUG1LN(DEBUG_SP_RACES, "Scenario group ", sThisGroupName, " does not exist")
ELIF TRI_Master.eRaceType = TRI_RACE_TYPE_PLANE
CDEBUG1LN(DEBUG_OR_RACES, "Scenario group ", sThisGroupName, " does not exist")
ELIF TRI_Master.eRaceType = TRI_RACE_TYPE_TRIATHLON
CPRINTLN(DEBUG_TRIATHLON, "Scenario group ", sThisGroupName, " does not exist")
ENDIF
ENDIF
ELSE
IF TRI_Master.eRaceType = TRI_RACE_TYPE_OFFROAD
CDEBUG1LN(DEBUG_SP_RACES, "String is null or empty!")
ELIF TRI_Master.eRaceType = TRI_RACE_TYPE_PLANE
CDEBUG1LN(DEBUG_OR_RACES, "String is null or empty!")
ELIF TRI_Master.eRaceType = TRI_RACE_TYPE_TRIATHLON
CPRINTLN(DEBUG_TRIATHLON, "String is null or empty!")
ENDIF
ENDIF
ENDPROC
FUNC BOOL TRI_Master_Choose_Tri_Race()
//DEBUG_MESSAGE("TRI_Master_Choose_Race")
// Update Choose Race controls.
// D-Pad Down - Increment current race.
IF IS_CONTROL_JUST_PRESSED(FRONTEND_CONTROL, INPUT_FRONTEND_DOWN)
IF (TRI_Master.iRaceCur < (TRI_Master.iRaceCnt - 1))
++TRI_Master.iRaceCur
ENDIF
// D-Pad Up - Decrement current race.
ELIF IS_CONTROL_JUST_PRESSED(FRONTEND_CONTROL, INPUT_FRONTEND_UP)
IF (TRI_Master.iRaceCur > 0)
--TRI_Master.iRaceCur
ENDIF
// A/X Button - Choose current race.
ELIF IS_CONTROL_JUST_PRESSED(FRONTEND_CONTROL, INPUT_FRONTEND_ACCEPT)
RETURN FALSE
// B/O Button - Exit race script.
ELIF IS_CONTROL_JUST_PRESSED(FRONTEND_CONTROL, INPUT_FRONTEND_CANCEL)
TRI_Master.iRaceCur = -1
RETURN FALSE
ENDIF
// Display Choose Race heading.
SET_TEXT_SCALE(TRI_UI_CR_HEAD_SCALE, TRI_UI_CR_HEAD_SCALE)
DISPLAY_TEXT(TRI_UI_CR_HEAD_POS_X, TRI_UI_CR_HEAD_POS_Y, "SPR_CHOOSERACE")
// Display Choose Race info (name/rank/time).
// TODO: Need some sort of display line limit and scrolling.
INT i
INT iBestRank
FLOAT fBestClockTime
REPEAT TRI_Master.iRaceCnt i
// Cache Best Rank and Clock Time.
iBestRank = TRI_Global_BestRank_Get(i)
fBestClockTime = TRI_Global_BestTime_Get(i)
// Cache Choose Race info position-y.
FLOAT fInfoPosY = TRI_UI_CR_INFO_POS_Y + (i * TRI_UI_CR_INFO_SPC_Y)
// Display Choose Race name.
IF (i = TRI_Master.iRaceCur)
SET_TEXT_COLOUR(255, 255, 0, 255)
ENDIF
SET_TEXT_SCALE(TRI_UI_CR_INFO_SCALE, TRI_UI_CR_INFO_SCALE)
BEGIN_TEXT_COMMAND_DISPLAY_TEXT(TRI_Master.szRaceName[i])
END_TEXT_COMMAND_DISPLAY_TEXT(TRI_UI_CR_INFO_POS_X, fInfoPosY)
// Display Choose Race best rank.
IF (i = TRI_Master.iRaceCur)
SET_TEXT_COLOUR(255, 255, 0, 255)
ENDIF
IF (iBestRank <= 0)
SET_TEXT_SCALE(TRI_UI_CR_INFO_SCALE, TRI_UI_CR_INFO_SCALE)
DISPLAY_TEXT(TRI_UI_CR_INFO_POS_X + TRI_UI_CR_INFO_SPC_X1, fInfoPosY, "SPR_PLACE_NA")
ELSE
TRI_Rank_Display(iBestRank, TRI_UI_CR_INFO_POS_X + TRI_UI_CR_INFO_SPC_X1, fInfoPosY, TRI_UI_CR_INFO_SCALE)
ENDIF
// Display Choose Race best time.
IF (i = TRI_Master.iRaceCur)
SET_TEXT_COLOUR(255, 255, 0, 255)
ENDIF
IF (fBestClockTime <= 0.0)
SET_TEXT_SCALE(TRI_UI_CR_INFO_SCALE, TRI_UI_CR_INFO_SCALE)
DISPLAY_TEXT(TRI_UI_CR_INFO_POS_X + TRI_UI_CR_INFO_SPC_X2, fInfoPosY, "SPR_CLOCK_NA")
ELSE
TRI_Clock_Display(fBestClockTime, TRI_UI_CR_INFO_POS_X + TRI_UI_CR_INFO_SPC_X2, fInfoPosY, TRI_UI_LB_INFO_SCALE, FALSE)
ENDIF
ENDREPEAT
// Display Choose Race controls (select/enter/exit).
SET_TEXT_SCALE(TRI_UI_CR_SEL_SCALE, TRI_UI_CR_SEL_SCALE)
DISPLAY_TEXT(TRI_UI_CR_SEL_POS_X, TRI_UI_CR_SEL_POS_Y, "SPR_UI_SELECT")
SET_TEXT_SCALE(TRI_UI_CR_ENT_SCALE, TRI_UI_CR_ENT_SCALE)
DISPLAY_TEXT(TRI_UI_CR_ENT_POS_X, TRI_UI_CR_ENT_POS_Y, "SPR_UI_ENTER")
SET_TEXT_SCALE(TRI_UI_CR_EXIT_SCALE, TRI_UI_CR_EXIT_SCALE)
DISPLAY_TEXT(TRI_UI_CR_EXIT_POS_X, TRI_UI_CR_EXIT_POS_Y, "SPR_UI_EXIT")
// Display Choose Race rectangle.
DRAW_RECT(TRI_UI_CR_RECT_POS_X, TRI_UI_CR_RECT_POS_Y, TRI_UI_CR_RECT_WIDTH, TRI_UI_CR_RECT_HEIGHT, 0, 0, 0, TRI_UI_CR_RECT_ALPHA)
// Choose SPR Race still running.
RETURN TRUE
ENDFUNC
/// PURPOSE:
/// Does the waiting around while the player animates during the countdown.
/// PARAMS:
/// Race -
PROC HANDLE_TRI_COUNTDOWN_ANIMS(TRI_RACE_STRUCT &Race)
INT p
REPEAT Race.iRacerCnt p
Race.Racer[p].fAnimWait += GET_FRAME_TIME()
IF Race.Racer[p].fAnimWait > ANIM_WAIT_THRESHOLD AND Race.Racer[p].fAnimWait < ANIM_WAIT_THRESHOLD * 3
IF NOT IS_ENTITY_DEAD(Race.Racer[p].Driver)
INT iAnim = GET_RANDOM_INT_IN_RANGE(1, 14)
STRING sAnim
sAnim = PICK_STRING(iAnim = 1, "ig_2_gen_warmup_01",
PICK_STRING(iAnim = 2, "ig_2_gen_warmup_02",
PICK_STRING(iAnim = 3, "ig_2_gen_warmup_03",
PICK_STRING(iAnim = 4, "ig_2_gen_warmup_04",
PICK_STRING(iAnim = 5, "ig_2_gen_warmup_05",
PICK_STRING(iAnim = 6, "ig_2_gen_warmup_06",
PICK_STRING(iAnim = 7, "ig_2_gen_warmup_07",
PICK_STRING(iAnim = 8, "ig_2_gen_warmup_08",
PICK_STRING(iAnim = 9, "ig_2_gen_warmup_09",
PICK_STRING(iAnim = 10, "ig_2_gen_warmup_10",
PICK_STRING(iAnim = 11, "ig_2_gen_warmup_11",
PICK_STRING(iAnim = 12, "ig_2_gen_warmup_12", "ig_2_gen_warmup_13"))))))))))))
TASK_PLAY_ANIM(Race.Racer[p].Driver, "mini@triathlon", sAnim, default, default, default, AF_ABORT_ON_PED_MOVEMENT | AF_EXIT_AFTER_INTERRUPTED)
Race.Racer[p].fAnimWait = ANIM_WAIT_THRESHOLD * 5 // make the timer huge so we only do this once.
CPRINTLN(DEBUG_TRIATHLON, "[tri_helpers.sch::HANDLE_TRI_COUNTDOWN_ANIMS] Setting iRacer[", p, "] with ", sAnim)
ENDIF
ENDIF
ENDREPEAT
ENDPROC
FUNC INT TRI_GET_NUM_RACERS_FINISHED( TRI_RACE_STRUCT& race )
INT iIndex
INT iRetVal = 0
REPEAT race.iRacerCnt iIndex
IF race.Racer[iIndex].Driver <> PLAYER_PED_ID()
IF HAS_TRI_RACER_FINISHED_RACE(race, race.Racer[iIndex])
++iRetVal
ENDIF
ENDIF
ENDREPEAT
RETURN iRetVal
ENDFUNC
PROC TRI_RACE_MANAGE_CHECKPOINT_ALPHAS(TRI_GATE_STRUCT& GateCur, TRI_GATE_STRUCT& GateNxt)
INT iRed, iGreen, iBlue, iAlpha
IF GateCur.Chkpnt != NULL
AND NOT GateCur.bIsFading
HUD_COLOURS eColor = MG_GET_RACE_CHECKPOINT_DEFAULT_COLOUR()
//HUD_COLOURS eColor = HUD_COLOUR_BLUE
GET_RGB_FROM_INT(GET_INT_FROM_HUD_COLOUR(eColor), iRed, iGreen, iBlue, iAlpha)
SET_CHECKPOINT_RGBA(GateCur.Chkpnt, iRed, iGreen, iBlue, MG_GET_CHECKPOINT_ALPHA(GateCur.vPos))
GET_HUD_COLOUR(HUD_COLOUR_NORTH_BLUE, iRed, iGreen, iBlue, iAlpha)
SET_CHECKPOINT_RGBA2(GateCur.Chkpnt, iRed, iGreen, iBlue, MG_GET_CHECKPOINT_ALPHA(GateCur.vPos))
//CDEBUG1LN(DEBUG_TRIATHLON, "[TRI_RACE_MANAGE_CHECKPOINT_ALPHAS] Current arrow colors are RED: ", iRed, ", GREEN: ", iGreen, ", BLUE: ", iBlue, ", ALPHA: ", MG_GET_CHECKPOINT_ALPHA(GateCur.vPos))
ENDIF
//EXIT
IF GateNxt.Chkpnt != NULL
AND NOT GateNxt.bIsFading
HUD_COLOURS eColor = MG_GET_RACE_CHECKPOINT_DEFAULT_COLOUR()
//HUD_COLOURS eColor = HUD_COLOUR_BLUE
GET_RGB_FROM_INT(GET_INT_FROM_HUD_COLOUR(eColor), iRed, iGreen, iBlue, iAlpha)
SET_CHECKPOINT_RGBA(GateNxt.Chkpnt, iRed, iGreen, iBlue, MG_GET_CHECKPOINT_ALPHA(GateNxt.vPos))
GET_HUD_COLOUR(HUD_COLOUR_NORTH_BLUE, iRed, iGreen, iBlue, iAlpha)
SET_CHECKPOINT_RGBA2(GateNxt.Chkpnt, iRed, iGreen, iBlue, MG_GET_CHECKPOINT_ALPHA(GateNxt.vPos))
//CDEBUG1LN(DEBUG_TRIATHLON, "[TRI_RACE_MANAGE_CHECKPOINT_ALPHAS] Next arrow colors are RED: ", iRed, ", GREEN: ", iGreen, ", BLUE: ", iBlue, ", ALPHA: ", MG_GET_CHECKPOINT_ALPHA(GateNxt.vPos))
ENDIF
ENDPROC
/// PURPOSE:
/// Once the player passes a gate, change its color and fade it out.
/// PARAMS:
/// Race - Contains all race data.
PROC TRI_RACE_MANAGE_GATE_FADE_ON_PASS(TRI_RACE_STRUCT& Race, INT iGateIdx)
Race.sGate[iGateIdx].iHUDAlphaAfterPass -= 25
CDEBUG1LN(DEBUG_TRIATHLON, "[TRI_RACE_MANAGE_GATE_FADE_ON_PASS] For gate ", iGateIdx, ", iHUDAlphaAfterPass decremented to ", Race.sGate[iGateIdx].iHUDAlphaAfterPass)
IF Race.sGate[iGateIdx].iHUDAlphaAfterPass > 0
CDEBUG1LN(DEBUG_TRIATHLON, "[TRI_RACE_MANAGE_GATE_FADE_ON_PASS] Alpha of gate ", iGateIdx, " has NOT reached 0. Updating alpha value on checkpoint and arrow.")
SET_CHECKPOINT_RGBA(Race.sGate[iGateIdx].Chkpnt, 255, 255, 255, Race.sGate[iGateIdx].iHUDAlphaAfterPass)
SET_CHECKPOINT_RGBA2(Race.sGate[iGateIdx].Chkpnt, 255, 255, 255, Race.sGate[iGateIdx].iHUDAlphaAfterPass)
ELSE
CDEBUG1LN(DEBUG_TRIATHLON, "[TRI_RACE_MANAGE_GATE_FADE_ON_PASS] Alpha reached 0 with Race.sGate[", iGateIdx, "].iHUDAlphaAfterPass at ", Race.sGate[iGateIdx].iHUDAlphaAfterPass,". Deleting checkpoint.")
TRI_Chkpnt_Destroy(Race.sGate[iGateIdx].Chkpnt)
Race.sGate[iGateIdx].bIsFading = FALSE
ENDIF
ENDPROC
/// PURPOSE:
/// Manage the gates fading once the player passes them.
/// PARAMS:
/// Race - Contains all race data.
PROC TRI_RACE_MANAGE_ALL_GATES_FADE_ON_PASS(TRI_RACE_STRUCT& Race)
INT iGateIdx
REPEAT Race.iGateCnt iGateIdx
IF Race.sGate[iGateIdx].bIsFading
CDEBUG1LN(DEBUG_TRIATHLON, "[TRI_RACE_MANAGE_ALL_GATES_FADE_ON_PASS] Gate ", iGateIdx, " is fading.")
TRI_RACE_MANAGE_GATE_FADE_ON_PASS(Race, iGateIdx)
ENDIF
ENDREPEAT
ENDPROC
// END OF FILE! DO NOT ADD ANYTHING BELOW THIS LINE!