// ***************************************************************************************** // ***************************************************************************************** // ***************************************************************************************** // // SCRIPT NAME : SPTT_Race.sch // AUTHOR : Nicholas Zippmann // DESCRIPTION : Single Player Races - Race procs/functions file // // ***************************************************************************************** // ***************************************************************************************** // ***************************************************************************************** USING "globals.sch" USING "SPTT_Head.sch" USING "SPTT_Helpers.sch" USING "SPTT_Gate.sch" USING "chase_hint_cam.sch" // CHASE_HINT_CAM_STRUCT localChaseHintCamStruct USING "SPTT_Racer.sch" USING "minigame_stats_tracker_helpers.sch" USING "CompletionPercentage_public.sch" USING "SPTT_SC_Leaderboard_lib.sch" //structTimer taxiTime structTimer resetTimer structTimer manualResetTimer //structTimer tShutdownTimer BOOL bDebugFailure = FALSE BOOL bTriggerFirstMusicEvent = FALSE BOOL bEndTracking = TRUE BOOL bEndShake = TRUE BLIP_INDEX returnToVehBlip //only used in off-road but may need for bike in Tris BOOL SPTT_USE_WAYPOINT_RECORDING = TRUE INT iButtonSounds //#IF IS_DEBUG_BUILD // VECTOR vAIGoto[20] //#ENDIF #IF NOT DEFINED(GET_HUD_STUNT_STRING) FUNC STRING GET_HUD_STUNT_STRING() RETURN NULL_STRING() ENDFUNC #ENDIF #IF NOT DEFINED(iSPRStuntFinishCam) CAMERA_INDEX iSPRStuntFinishCam #ENDIF #IF NOT DEFINED(GET_HUD_STUNT_FLOAT) FUNC FLOAT GET_HUD_STUNT_FLOAT() RETURN -1.0 ENDFUNC #ENDIF #IF NOT DEFINED(GET_HUD_STUNT_INT) FUNC INT GET_HUD_STUNT_INT() RETURN ENUM_TO_INT(HUD_COLOUR_WHITE) ENDFUNC #ENDIF #IF NOT DEFINED(RUN_OFFROAD_AUDIO) PROC RUN_OFFROAD_AUDIO(SPTT_RACE_STRUCT& Race) IF (Race.iRacerCnt = -1) PRINTINT(Race.iRacerCnt) PRINTNL() ENDIF ENDPROC #ENDIF #IF NOT DEFINED(stop_vehicle_recordings) PROC stop_vehicle_recordings(SPTT_RACE_STRUCT& Race) Race.iGateCnt = Race.iGateCnt ENDPROC #ENDIF #IF NOT DEFINED(Disable_Airport_Icons) PROC Disable_Airport_Icons() /* IF SPTT_Master.eRaceType = SPTT_RACE_TYPE_PLANE DEBUG_MESSAGE("Inside dummy Disable_Airport_Icons proc") ENDIF */ ENDPROC #ENDIF #IF NOT DEFINED(SPTT_Gate_Reward) PROC SPTT_Gate_Reward(SPTT_RACER_STRUCT& Racer, SPTT_RACE_GATE_STATUS status) Racer.fPlsMnsTot = Racer.fPlsMnsTot status = status ENDPROC #ENDIF #IF NOT DEFINED(SPTT_Racer_ClockTime_Penalty) PROC SPTT_Racer_ClockTime_Penalty(SPTT_RACER_STRUCT& Racer, FLOAT fPenalty) Racer.fPlsMnsTot = Racer.fPlsMnsTot fPenalty = fPenalty ENDPROC #ENDIF #IF NOT DEFINED(runGateTimers) PROC runGateTimers(SPTT_RACER_STRUCT& Racer, BOOL bRacerIsPlayer, INT iGateCheck) Racer.fPlsMnsTot = Racer.fPlsMnsTot bRacerIsPlayer = bRacerIsPlayer iGateCheck = iGateCheck ENDPROC #ENDIF #IF NOT DEFINED(rewardPlayer) PROC rewardPlayer() ENDPROC #ENDIF #IF NOT DEFINED(SPTT_Race_Racer_AutoPilot) PROC SPTT_Race_Racer_AutoPilot(SPTT_RACE_STRUCT& Race) Race.fBestClockTime = Race.fBestClockTime ENDPROC #ENDIF #IF NOT DEFINED(SPTT_Race_Racer_AutoCircle) PROC SPTT_Race_Racer_AutoCircle(SPTT_RACE_STRUCT& Race) Race.fBestClockTime = Race.fBestClockTime ENDPROC #ENDIF #IF NOT DEFINED(SPTT_Racer_AutoPilot) PROC SPTT_Racer_AutoPilot(SPTT_RACER_STRUCT& Racer, FLOAT fSpeed, BOOL bRotInterp) Racer.fStartHead = Racer.fStartHead fSpeed = fSpeed bRotInterp = bRotInterp ENDPROC #ENDIF #IF NOT DEFINED(SPTT_Racer_AutoCircle) PROC SPTT_Racer_AutoCircle(SPTT_RACER_STRUCT& Racer, FLOAT fSpeed, BOOL bRotInterp) Racer.fStartHead = Racer.fStartHead fSpeed = fSpeed bRotInterp= bRotInterp ENDPROC #ENDIF #IF NOT DEFINED(Tri_Showing_Player_Finished_Race) FUNC BOOL Tri_Showing_Player_Finished_Race() RETURN FALSE ENDFUNC #ENDIF #IF NOT DEFINED(SET_TRI_RACERS_ONCE_RACE_ENDS) PROC SET_TRI_RACERS_ONCE_RACE_ENDS(SPTT_RACE_STRUCT& Race) Race.iGateCnt = Race.iGateCnt ENDPROC #ENDIF #IF NOT DEFINED(SET_CUTSCENE_CAMERA_AT_END_OF_RACE) PROC SET_CUTSCENE_CAMERA_AT_END_OF_RACE(BOOL bActivateCam) bActivateCam = bActivateCam ENDPROC #ENDIF #IF NOT DEFINED(SPTT_Init_Scorecard) PROC SPTT_Init_Scorecard(SPTT_RACE_STRUCT &Race) Race.iGateCheck = Race.iGateCheck ENDPROC #ENDIF #IF NOT DEFINED(SPTT_Draw_Scorecard) PROC SPTT_Draw_Scorecard(SPTT_RACE_STRUCT &Race, INT &iPlayerIndex) Race.iGateCheck = Race.iGateCheck iPlayerIndex = iPlayerIndex ENDPROC #ENDIF #IF NOT DEFINED(SPTT_Setup_Leaderboard) PROC SPTT_Setup_Leaderboard(SPTT_RACE_STRUCT &Race) UNUSED_PARAMETER(Race) ENDPROC #ENDIF #IF NOT DEFINED(Cleanup_Finish_Camera) PROC Cleanup_Finish_Camera() ENDPROC #ENDIF #IF NOT DEFINED(SPTT_Race_Stunt_Manage_Finish_Camera) PROC SPTT_Race_Stunt_Manage_Finish_Camera(VEHICLE_INDEX& iPlayersPlane) iPlayersPlane = iPlayersPlane ENDPROC #ENDIF #IF NOT DEFINED(SPTT_UPDATING_END_SCREEN) PROC SPTT_UPDATING_END_SCREEN() //nothing ENDPROC #ENDIF #IF NOT DEFINED(SPTT_Race_Manage_Race_Beats) PROC SPTT_Race_Manage_Race_Beats(INT iGateCur, BOOL bFailChecking) iGateCur = iGateCur bFailChecking = bFailChecking ENDPROC #ENDIF #IF NOT DEFINED(SPTT_Race_Cleanup_Stunt_Beats) PROC SPTT_Race_Cleanup_Stunt_Beats() ENDPROC #ENDIF #IF NOT DEFINED(FINISH_AI_RACERS) PROC FINISH_AI_RACERS(SPTT_RACER_STRUCT& Racer) PRINTFLOAT(Racer.fStartHead) PRINTNL() ENDPROC #ENDIF #IF NOT DEFINED(RELEASE_AI_RACERS) PROC RELEASE_AI_RACERS(SPTT_RACE_STRUCT& Race) PRINTINT(Race.iRacerCnt) PRINTNL() ENDPROC #ENDIF // ----------------------------------- // HELPER PROCS/FUNCTIONS // ----------------------------------- PROC SPTT_Race_FakeRacer_Populate(SPTT_RACE_STRUCT& Race) //DEBUG_MESSAGE("SPTT_Race_FakeRacer_Populate") TEXT_LABEL_31 szRacerName[SPTT_UI_LB_RACER_LIMIT - 1] SPTT_RacerName_Populate(szRacerName) FLOAT fBestClockTime = Race.fBestClockTime IF (fBestClockTime > Race.Racer[0].fClockTime) fBestClockTime = Race.Racer[0].fClockTime ENDIF WHILE (Race.iRacerCnt < SPTT_UI_LB_RACER_LIMIT) Race.Racer[Race.iRacerCnt].szName = szRacerName[Race.iRacerCnt - 1] Race.Racer[Race.iRacerCnt].fClockTime = GET_RANDOM_FLOAT_IN_RANGE(fBestClockTime, fBestClockTime * 1.25) ++Race.iRacerCnt ENDWHILE ENDPROC PROC SPTT_Race_ClockTime_SimAI(SPTT_RACE_STRUCT& Race) //DEBUG_MESSAGE("SPTT_Race_ClockTime_SimAI") INT i REPEAT Race.iRacerCnt i IF (Race.Racer[i].iGateCur <> Race.iGateCnt) Race.Racer[i].fClockTime = Race.Racer[0].fClockTime + ((Race.iGateCnt - Race.Racer[i].iGateCur) * GET_RANDOM_FLOAT_IN_RANGE(0.5, 2.5)) ENDIF ENDREPEAT ENDPROC PROC SPTT_Race_Rank_CalcFinal(SPTT_RACE_STRUCT& Race) //DEBUG_MESSAGE("SPTT_Race_Rank_CalcFinal") INT i, j, iRank REPEAT Race.iRacerCnt i iRank = 1 REPEAT Race.iRacerCnt j IF (i <> j) IF (Race.Racer[i].fClockTime > Race.Racer[j].fClockTime) ++iRank // TODO: Should be doing something to offset tied ranks for leaderboard. // TODO: Also make sure if 2 guys share a rank, the next rank is 1 higher. //ELIF (Race.Racer[i].iGateCur = Race.Racer[j].iGateCur) // ++iRank ENDIF ENDIF ENDREPEAT Race.Racer[i].iRank = iRank ENDREPEAT ENDPROC // TODO: My method of finding player racer here is different from above. // May want to come up with a safe way we know which racer is player. PROC SPTT_Race_RankClock_FindPlayerBest(SPTT_RACE_STRUCT& Race) //DEBUG_MESSAGE("SPTT_Race_FindPlayerBest") INT i REPEAT Race.iRacerCnt i IF NOT IS_ENTITY_DEAD(Race.Racer[i].Driver) IF (Race.Racer[i].Driver = PLAYER_PED_ID()) INT iBestRank = SPTT_Global_BestRank_Get(SPTT_Master.iRaceCur) IF (iBestRank <= 0) OR (iBestRank > Race.Racer[i].iRank) SPTT_Global_BestRank_Set(SPTT_Master.iRaceCur, Race.Racer[i].iRank) ENDIF FLOAT fBestTime = SPTT_Global_BestTime_Get(SPTT_Master.iRaceCur) SPTT_LastTime_Set(SPTT_Master.iRaceCur, TO_FLOAT(CEIL(Race.Racer[0].fClockTime))) IF (fBestTime = 0.0) OR (fBestTime > Race.Racer[0].fClockTime) SPTT_Global_BestTime_Set(SPTT_Master.iRaceCur, TO_FLOAT(CEIL(Race.Racer[0].fClockTime))) ENDIF EXIT ENDIF ENDIF ENDREPEAT ENDPROC PROC SPTT_Race_Leaderboard_Init_Scorecard(SPTT_RACE_STRUCT& Race) SPTT_Init_Scorecard(Race) SETTIMERA(0) SET_AUTOSAVE_IGNORES_ON_MISSION_FLAG(TRUE) MAKE_AUTOSAVE_REQUEST() ENDPROC FUNC BOOL SPTT_Race_Draw_Scorecard(SPTT_RACE_STRUCT& Race) //delay scorecard IF TIMERA() < 2000 RETURN FALSE ENDIF Race.Racer[0].Driver = Race.Racer[0].Driver // INT iPlayerIndex = 0 // INT i // REPEAT Race.iRacerCnt i // IF NOT IS_ENTITY_DEAD(Race.Racer[i].Driver) // IF (Race.Racer[i].Driver = PLAYER_PED_ID()) // iPlayerIndex = i // ENDIF // ENDIF // ENDREPEAT //show medal toast. IF NOT IS_RADAR_HIDDEN() DISPLAY_RADAR(FALSE) ENDIF IF TIMERA() > 5000 RETURN TRUE ENDIF RETURN FALSE ENDFUNC // ----------------------------------- // GATE PROCS/FUNCTIONS // ----------------------------------- FUNC BOOL SPTT_Race_Gate_Activate(SPTT_RACE_STRUCT& Race, INT iGate, BOOL bGateCur) VECTOR vNextGate //DEBUG_MESSAGE("SPTT_Race_Gate_Activate") IF (iGate < 0) OR (iGate > (SPTT_GATE_MAX - 1)) DEBUG_MESSAGE("SPTT_Race_Gate_Activate: Gate index out of range!") RETURN FALSE ENDIF BLIP_SPRITE eBlipSprite = RADAR_TRACE_INVALID IF (iGate = (Race.iGateCnt - 1)) eBlipSprite = RADAR_TRACE_RACEFLAG ENDIF FLOAT fBlipScale = SPTT_GATE_BLIPCUR_SCL IF NOT bGateCur fBlipScale = SPTT_GATE_BLIPNXT_SCL ENDIF IF NOT SPTT_Gate_Blip_Create(Race.sGate[iGate], eBlipSprite, fBlipScale, iGate, Race.iGateCnt) DEBUG_MESSAGE("SPTT_Race_Gate_Activate: Failed to create gate blip!") RETURN FALSE ENDIF IF bGateCur VECTOR vNextGatePos = Race.sGate[iGate].vPos VECTOR vPrevGatePos = <<0,0,0>> IF (iGate < (Race.iGateCnt - 1)) IF NOT ARE_VECTORS_ALMOST_EQUAL(Race.sGate[iGate].vPos, Race.sGate[iGate + 1].vPos) vNextGatePos = Race.sGate[iGate + 1].vPos ENDIF ENDIF IF SPTT_Master.eRaceType = SPTT_RACE_TYPE_OFFROAD IF (SPTT_Master.iRaceCur = 1) // 1 for Ridgerun) IF IS_BITMASK_AS_ENUM_SET(Race.sGate[8].iGateFlags, SPTT_RACE_GATE_FLAG_DO_NOT_SNAP_TO_GROUND) CLEAR_BITMASK_AS_ENUM(Race.sGate[8].iGateFlags, SPTT_RACE_GATE_FLAG_DO_NOT_SNAP_TO_GROUND) PRINTLN("SPTT_Race_Gate_Activate: Cleared Bitmask as Enum for sGate[8]") PRINTNL() ENDIF ENDIF ENDIF IF (iGate > 0) vPrevGatePos = Race.sGate[iGate-1].vPos ENDIF IF NOT SPTT_Gate_Chkpnt_Create(vPrevGatePos, Race.sGate[iGate], vNextGatePos, SPTT_GATE_CHKPNT_SCL) DEBUG_MESSAGE("SPTT_Race_Gate_Activate: Failed to create gate checkpoint!") RETURN FALSE ENDIF //turn on the next checkpoint and make it tiny IF iGate+1 < Race.iGateCnt IF (iGate+2 >= SPTT_GATE_MAX) vNextGate = Race.sGate[0].vPos ELSE vNextGate = Race.sGate[iGate+2].vPos ENDIF //just set the nextgatepos to the origin because we can't even see the arrow anyways IF NOT SPTT_Gate_Chkpnt_Create(Race.sGate[iGate].vPos, Race.sGate[iGate+1], vNextGate, SPTT_GATE_CHKPNT_SCL)//SPTT_GATE_CHKPNTNXT_SCL) DEBUG_MESSAGE("SPTT_Race_Gate_Activate: Failed to create gate checkpoint!") RETURN FALSE ENDIF ENDIF ENDIF RETURN TRUE ENDFUNC FUNC BOOL SPTT_Race_Gate_Activate_All(SPTT_RACE_STRUCT& Race, BOOL bGateCur) //DEBUG_MESSAGE("SPTT_Race_Gate_Activate_All") INT i BOOL bAllDone = TRUE REPEAT Race.iGateCnt i IF NOT SPTT_Race_Gate_Activate(Race, i, bGateCur) bAllDone = FALSE ENDIF ENDREPEAT RETURN bAllDone ENDFUNC PROC SPTT_Race_Gate_Deactivate(SPTT_RACE_STRUCT& Race, INT iGate) //DEBUG_MESSAGE("SPTT_Race_Gate_Deactivate") IF (iGate < 0) OR (iGate > (SPTT_GATE_MAX - 1)) DEBUG_MESSAGE("SPTT_Race_Gate_Deactivate: Gate index out of range!") EXIT ENDIF SPTT_Gate_Blip_Destroy(Race.sGate[iGate]) SPTT_Chkpnt_BeginFade(Race.sGate[iGate].Chkpnt, Race.fadeCheckpoint, Race.iFadeAlpha, (Race.sGate[iGate].eChkpntType = SPTT_CHKPT_STUNT_FINISH)) // SPTT_Gate_Chkpnt_Destroy(Race.sGate[iGate]) //turn off our extra checkpoint IF iGate+1 < Race.iGateCnt SPTT_Gate_Blip_Destroy(Race.sGate[iGate+1]) SPTT_Gate_Chkpnt_Destroy(Race.sGate[iGate+1]) ENDIF ENDPROC PROC SPTT_Race_Gate_Deactivate_All(SPTT_RACE_STRUCT& Race) //DEBUG_MESSAGE("SPTT_Race_Gate_Deactivate_All") INT i REPEAT Race.iGateCnt i SPTT_Race_Gate_Deactivate(Race, i) ENDREPEAT ENDPROC PROC SPTT_Race_Gate_Init(SPTT_RACE_STRUCT& Race, INT iGate) //DEBUG_MESSAGE("SPTT_Race_Gate_Init") IF (iGate < 0) OR (iGate > (SPTT_GATE_MAX - 1)) DEBUG_MESSAGE("SPTT_Race_Gate_Init: Gate index out of range!") EXIT ENDIF SPTT_Gate_Blip_Destroy(Race.sGate[iGate]) SPTT_Gate_Chkpnt_Destroy(Race.sGate[iGate]) SPTT_Gate_Init(Race.sGate[iGate]) ENDPROC PROC SPTT_Race_Gate_Init_All(SPTT_RACE_STRUCT& Race) //DEBUG_MESSAGE("SPTT_Race_Gate_Init_All") INT i REPEAT Race.iGateCnt i SPTT_Race_Gate_Init(Race, i) ENDREPEAT ENDPROC // ----------------------------------- // RACER DRIVER PROCS/FUNCTIONS // ----------------------------------- PROC SPTT_Race_Racer_Driver_Request(SPTT_RACE_STRUCT& Race, INT iRacer) //DEBUG_MESSAGE("SPTT_Race_Racer_Driver_Request") IF (iRacer < 0) OR (iRacer > (SPTT_RACER_MAX - 1)) DEBUG_MESSAGE("SPTT_Race_Racer_Driver_Request: Racer index out of range!") EXIT ENDIF SPTT_Racer_Driver_Request(Race.Racer[iRacer]) ENDPROC PROC SPTT_Race_Racer_Driver_Request_All(SPTT_RACE_STRUCT& Race) //DEBUG_MESSAGE("SPTT_Race_Racer_Driver_Request_All") INT i REPEAT Race.iRacerCnt i SPTT_Race_Racer_Driver_Request(Race, i) ENDREPEAT ENDPROC FUNC BOOL SPTT_Race_Racer_Driver_Stream(SPTT_RACE_STRUCT& Race, INT iRacer) //DEBUG_MESSAGE("SPTT_Race_Racer_Driver_Stream") IF (iRacer < 0) OR (iRacer > (SPTT_RACER_MAX - 1)) DEBUG_MESSAGE("SPTT_Race_Racer_Driver_Stream: Racer index out of range!") RETURN FALSE ENDIF RETURN SPTT_Racer_Driver_Stream(Race.Racer[iRacer]) ENDFUNC FUNC BOOL SPTT_Race_Racer_Driver_Stream_All(SPTT_RACE_STRUCT& Race) //DEBUG_MESSAGE("SPTT_Race_Racer_Driver_Stream_All") INT i BOOL bStreamDone = TRUE REPEAT Race.iRacerCnt i IF NOT SPTT_Racer_Driver_Stream(Race, i) bStreamDone = FALSE ENDIF ENDREPEAT RETURN bStreamDone ENDFUNC PROC SPTT_Race_Racer_Driver_Evict(SPTT_RACE_STRUCT& Race, INT iRacer) //DEBUG_MESSAGE("SPTT_Race_Racer_Driver_Evict") IF (iRacer < 0) OR (iRacer > (SPTT_RACER_MAX - 1)) DEBUG_MESSAGE("SPTT_Race_Racer_Driver_Evict: Racer index out of range!") EXIT ENDIF SPTT_Racer_Driver_Evict(Race.Racer[iRacer]) ENDPROC PROC SPTT_Race_Racer_Driver_Evict_All(SPTT_RACE_STRUCT& Race) //DEBUG_MESSAGE("SPTT_Race_Racer_Driver_Evict_All") INT i REPEAT Race.iRacerCnt i SPTT_Race_Racer_Driver_Evict(Race, i) ENDREPEAT ENDPROC FUNC BOOL SPTT_Race_Racer_Driver_Create(SPTT_RACE_STRUCT& Race, INT iRacer) //DEBUG_MESSAGE("SPTT_Race_Racer_Driver_Create") IF (iRacer < 0) OR (iRacer > (SPTT_RACER_MAX - 1)) DEBUG_MESSAGE("SPTT_Race_Racer_Driver_Create: Racer index out of range!") RETURN FALSE ENDIF RETURN SPTT_Racer_Driver_Create(Race.Racer[iRacer]) ENDFUNC FUNC BOOL SPTT_Race_Racer_Driver_Create_All(SPTT_RACE_STRUCT& Race) //DEBUG_MESSAGE("SPTT_Race_Racer_Driver_Create_All") INT i BOOL bCreateDone = TRUE REPEAT Race.iRacerCnt i IF NOT SPTT_Race_Racer_Driver_Create(Race, i) bCreateDone = FALSE ENDIF ENDREPEAT RETURN bCreateDone ENDFUNC PROC SPTT_Race_Racer_Driver_Freeze(SPTT_RACE_STRUCT& Race, INT iRacer) //DEBUG_MESSAGE("SPTT_Race_Racer_Driver_Freeze") IF (iRacer < 0) OR (iRacer > (SPTT_RACER_MAX - 1)) DEBUG_MESSAGE("SPTT_Race_Racer_Driver_Freeze: Racer index out of range!") EXIT ENDIF SPTT_Racer_Driver_Freeze(Race.Racer[iRacer]) ENDPROC PROC SPTT_Race_Racer_Driver_Freeze_All(SPTT_RACE_STRUCT& Race) //DEBUG_MESSAGE("SPTT_Race_Racer_Driver_Freeze_All") INT i REPEAT Race.iRacerCnt i SPTT_Race_Racer_Driver_Freeze(Race, i) ENDREPEAT ENDPROC PROC SPTT_Race_Racer_Driver_UnFreeze(SPTT_RACE_STRUCT& Race, INT iRacer) //DEBUG_MESSAGE("SPTT_Race_Racer_Driver_UnFreeze") IF (iRacer < 0) OR (iRacer > (SPTT_RACER_MAX - 1)) DEBUG_MESSAGE("SPTT_Race_Racer_Driver_UnFreeze: Racer index out of range!") EXIT ENDIF SPTT_Racer_Driver_UnFreeze(Race.Racer[iRacer]) ENDPROC PROC SPTT_Race_Racer_Driver_UnFreeze_All(SPTT_RACE_STRUCT& Race) //DEBUG_MESSAGE("SPTT_Race_Racer_Driver_UnFreeze_All") INT i REPEAT Race.iRacerCnt i SPTT_Race_Racer_Driver_UnFreeze(Race, i) ENDREPEAT ENDPROC PROC SPTT_Race_Racer_Driver_Release(SPTT_RACE_STRUCT& Race, INT iRacer) //DEBUG_MESSAGE("SPTT_Race_Racer_Driver_Release") IF (iRacer < 0) OR (iRacer > (SPTT_RACER_MAX - 1)) DEBUG_MESSAGE("SPTT_Race_Racer_Driver_Release: Racer index out of range!") EXIT ENDIF SPTT_Racer_Driver_Release(Race.Racer[iRacer]) ENDPROC PROC SPTT_Race_Racer_Driver_Release_All(SPTT_RACE_STRUCT& Race) //DEBUG_MESSAGE("SPTT_Race_Racer_Driver_Release_All") INT i REPEAT Race.iRacerCnt i SPTT_Race_Racer_Driver_Release(Race, i) ENDREPEAT ENDPROC PROC SPTT_Race_Racer_Driver_Destroy(SPTT_RACE_STRUCT& Race, INT iRacer) //DEBUG_MESSAGE("SPTT_Race_Racer_Driver_Destroy") IF (iRacer < 0) OR (iRacer > (SPTT_RACER_MAX - 1)) DEBUG_MESSAGE("SPTT_Race_Racer_Driver_Destroy: Racer index out of range!") EXIT ENDIF SPTT_Racer_Driver_Destroy(Race.Racer[iRacer]) ENDPROC PROC SPTT_Race_Racer_Driver_Destroy_All(SPTT_RACE_STRUCT& Race) //DEBUG_MESSAGE("SPTT_Race_Racer_Driver_Destroy_All") INT i REPEAT Race.iRacerCnt i SPTT_Race_Racer_Driver_Destroy(Race, i) ENDREPEAT ENDPROC // ----------------------------------- // RACER VEHICLE PROCS/FUNCTIONS // ----------------------------------- PROC SPTT_Race_Racer_Vehicle_Request(SPTT_RACE_STRUCT& Race, INT iRacer) //DEBUG_MESSAGE("SPTT_Race_Racer_Vehicle_Request") IF (iRacer < 0) OR (iRacer > (SPTT_RACER_MAX - 1)) DEBUG_MESSAGE("SPTT_Race_Racer_Vehicle_Request: Racer index out of range!") EXIT ENDIF SPTT_Racer_Vehicle_Request(Race.Racer[iRacer]) ENDPROC PROC SPTT_Race_Racer_Vehicle_Request_All(SPTT_RACE_STRUCT& Race) //DEBUG_MESSAGE("SPTT_Race_Racer_Vehicle_Request_All") INT i REPEAT Race.iRacerCnt i SPTT_Race_Racer_Vehicle_Request(Race, i) ENDREPEAT ENDPROC FUNC BOOL SPTT_Race_Racer_Vehicle_Stream(SPTT_RACE_STRUCT& Race, INT iRacer) //DEBUG_MESSAGE("SPTT_Race_Racer_Vehicle_Stream") IF (iRacer < 0) OR (iRacer > (SPTT_RACER_MAX - 1)) DEBUG_MESSAGE("SPTT_Race_Racer_Vehicle_Stream: Racer index out of range!") RETURN FALSE ENDIF RETURN SPTT_Racer_Vehicle_Stream(Race.Racer[iRacer]) ENDFUNC FUNC BOOL SPTT_Race_Racer_Vehicle_Stream_All(SPTT_RACE_STRUCT& Race) //DEBUG_MESSAGE("SPTT_Race_Racer_Vehicle_Stream_All") INT i BOOL bStreamDone = TRUE REPEAT Race.iRacerCnt i IF NOT SPTT_Racer_Vehicle_Stream(Race, i) bStreamDone = FALSE ENDIF ENDREPEAT RETURN bStreamDone ENDFUNC PROC SPTT_Race_Racer_Vehicle_Evict(SPTT_RACE_STRUCT& Race, INT iRacer) //DEBUG_MESSAGE("SPTT_Race_Racer_Vehicle_Evict") IF (iRacer < 0) OR (iRacer > (SPTT_RACER_MAX - 1)) DEBUG_MESSAGE("SPTT_Race_Racer_Vehicle_Evict: Racer index out of range!") EXIT ENDIF SPTT_Racer_Vehicle_Evict(Race.Racer[iRacer]) ENDPROC PROC SPTT_Race_Racer_Vehicle_Evict_All(SPTT_RACE_STRUCT& Race) //DEBUG_MESSAGE("SPTT_Race_Racer_Vehicle_Evict_All") INT i REPEAT Race.iRacerCnt i SPTT_Race_Racer_Vehicle_Evict(Race, i) ENDREPEAT ENDPROC FUNC BOOL SPTT_Race_Racer_Vehicle_Create(SPTT_RACE_STRUCT& Race, INT iRacer) //DEBUG_MESSAGE("SPTT_Race_Racer_Vehicle_Create") IF (iRacer < 0) OR (iRacer > (SPTT_RACER_MAX - 1)) DEBUG_MESSAGE("SPTT_Race_Racer_Vehicle_Create: Racer index out of range!") RETURN FALSE ENDIF RETURN SPTT_Racer_Vehicle_Create(Race.Racer[iRacer]) ENDFUNC FUNC BOOL SPTT_Race_Racer_Vehicle_Create_All(SPTT_RACE_STRUCT& Race) //DEBUG_MESSAGE("SPTT_Race_Racer_Vehicle_Create_All") INT i BOOL bCreateDone = TRUE REPEAT Race.iRacerCnt i IF NOT SPTT_Race_Racer_Vehicle_Create(Race, i) bCreateDone = FALSE ENDIF ENDREPEAT RETURN bCreateDone ENDFUNC PROC SPTT_Race_Racer_Vehicle_Freeze(SPTT_RACE_STRUCT& Race, INT iRacer) //DEBUG_MESSAGE("SPTT_Race_Racer_Vehicle_Freeze") IF (iRacer < 0) OR (iRacer > (SPTT_RACER_MAX - 1)) DEBUG_MESSAGE("SPTT_Race_Racer_Vehicle_Freeze: Racer index out of range!") EXIT ENDIF SPTT_Racer_Vehicle_Freeze(Race.Racer[iRacer]) ENDPROC PROC SPTT_Race_Racer_Vehicle_Freeze_All(SPTT_RACE_STRUCT& Race) //DEBUG_MESSAGE("SPTT_Race_Racer_Vehicle_Freeze_All") INT i REPEAT Race.iRacerCnt i SPTT_Race_Racer_Vehicle_Freeze(Race, i) ENDREPEAT ENDPROC PROC SPTT_Race_Racer_Vehicle_UnFreeze(SPTT_RACE_STRUCT& Race, INT iRacer) //DEBUG_MESSAGE("SPTT_Race_Racer_Vehicle_UnFreeze") IF (iRacer < 0) OR (iRacer > (SPTT_RACER_MAX - 1)) DEBUG_MESSAGE("SPTT_Race_Racer_Vehicle_UnFreeze: Racer index out of range!") EXIT ENDIF SPTT_Racer_Vehicle_UnFreeze(Race.Racer[iRacer]) ENDPROC PROC SPTT_Race_Racer_Vehicle_UnFreeze_All(SPTT_RACE_STRUCT& Race) //DEBUG_MESSAGE("SPTT_Race_Racer_Vehicle_UnFreeze_All") INT i REPEAT Race.iRacerCnt i SPTT_Race_Racer_Vehicle_UnFreeze(Race, i) ENDREPEAT ENDPROC PROC SPTT_Race_Racer_Vehicle_Release(SPTT_RACE_STRUCT& Race, INT iRacer) //DEBUG_MESSAGE("SPTT_Race_Racer_Vehicle_Release") IF (iRacer < 0) OR (iRacer > (SPTT_RACER_MAX - 1)) DEBUG_MESSAGE("SPTT_Race_Racer_Vehicle_Release: Racer index out of range!") EXIT ENDIF SPTT_Racer_Vehicle_Release(Race.Racer[iRacer]) ENDPROC PROC SPTT_Race_Racer_Vehicle_Release_All(SPTT_RACE_STRUCT& Race) //DEBUG_MESSAGE("SPTT_Race_Racer_Vehicle_Release_All") INT i REPEAT Race.iRacerCnt i SPTT_Race_Racer_Vehicle_Release(Race, i) ENDREPEAT ENDPROC PROC SPTT_Race_Racer_Vehicle_Destroy(SPTT_RACE_STRUCT& Race, INT iRacer) //DEBUG_MESSAGE("SPTT_Race_Racer_Vehicle_Destroy") IF (iRacer < 0) OR (iRacer > (SPTT_RACER_MAX - 1)) DEBUG_MESSAGE("SPTT_Race_Racer_Vehicle_Destroy: Racer index out of range!") EXIT ENDIF SPTT_Racer_Vehicle_Destroy(Race.Racer[iRacer]) ENDPROC PROC SPTT_Race_Racer_Vehicle_Destroy_All(SPTT_RACE_STRUCT& Race) //DEBUG_MESSAGE("SPTT_Race_Racer_Vehicle_Destroy_All") INT i REPEAT Race.iRacerCnt i SPTT_Race_Racer_Vehicle_Destroy(Race, i) ENDREPEAT ENDPROC // ----------------------------------- // RACER MAIN PROCS/FUNCTIONS // ----------------------------------- PROC SPTT_Race_Racer_Request(SPTT_RACE_STRUCT& Race, INT iRacer) //DEBUG_MESSAGE("SPTT_Race_Racer_Request") IF (iRacer < 0) OR (iRacer > (SPTT_RACER_MAX - 1)) DEBUG_MESSAGE("SPTT_Race_Racer_Request: Racer index out of range!") EXIT ENDIF SPTT_Racer_Request(Race.Racer[iRacer]) ENDPROC PROC SPTT_Race_Racer_Request_All(SPTT_RACE_STRUCT& Race) //DEBUG_MESSAGE("SPTT_Race_Racer_Request_All") INT i REPEAT Race.iRacerCnt i SPTT_Race_Racer_Request(Race, i) ENDREPEAT ENDPROC FUNC BOOL SPTT_Race_Racer_Stream(SPTT_RACE_STRUCT& Race, INT iRacer) //DEBUG_MESSAGE("SPTT_Race_Racer_Stream") IF (iRacer < 0) OR (iRacer > (SPTT_RACER_MAX - 1)) DEBUG_MESSAGE("SPTT_Race_Racer_Stream: Racer index out of range!") RETURN FALSE ENDIF RETURN SPTT_Racer_Stream(Race.Racer[iRacer]) ENDFUNC FUNC BOOL SPTT_Race_Racer_Stream_All(SPTT_RACE_STRUCT& Race) //DEBUG_MESSAGE("SPTT_Race_Racer_Stream_All") INT i BOOL bStreamDone = TRUE REPEAT Race.iRacerCnt i IF NOT SPTT_Race_Racer_Stream(Race, i) bStreamDone = FALSE ENDIF ENDREPEAT RETURN bStreamDone ENDFUNC PROC SPTT_Race_Racer_Evict(SPTT_RACE_STRUCT& Race, INT iRacer) //DEBUG_MESSAGE("SPTT_Race_Racer_Evict") IF (iRacer < 0) OR (iRacer > (SPTT_RACER_MAX - 1)) DEBUG_MESSAGE("SPTT_Race_Racer_Evict: Racer index out of range!") EXIT ENDIF SPTT_Racer_Evict(Race.Racer[iRacer]) ENDPROC PROC SPTT_Race_Racer_Evict_All(SPTT_RACE_STRUCT& Race) //DEBUG_MESSAGE("SPTT_Race_Racer_Evict_All") INT i REPEAT Race.iRacerCnt i SPTT_Race_Racer_Evict(Race, i) ENDREPEAT ENDPROC FUNC BOOL SPTT_Race_Racer_Blip_Create(SPTT_RACE_STRUCT& Race, INT iRacer) //DEBUG_MESSAGE("SPTT_Race_Racer_Blip_Create") IF (iRacer < 0) OR (iRacer > (SPTT_RACER_MAX - 1)) DEBUG_MESSAGE("SPTT_Race_Racer_Blip_Create: Racer index out of range!") RETURN FALSE ENDIF RETURN SPTT_Racer_Blip_Create(Race.Racer[iRacer]) ENDFUNC FUNC BOOL SPTT_Race_Racer_Blip_Create_All(SPTT_RACE_STRUCT& Race) //DEBUG_MESSAGE("SPTT_Race_Racer_Blip_Create_All") INT i BOOL bCreateDone = TRUE REPEAT Race.iRacerCnt i IF NOT SPTT_Race_Racer_Blip_Create(Race, i) bCreateDone = FALSE ENDIF ENDREPEAT RETURN bCreateDone ENDFUNC PROC SPTT_Race_Racer_Blip_Destroy(SPTT_RACE_STRUCT& Race, INT iRacer) //DEBUG_MESSAGE("SPTT_Race_Racer_Blip_Destroy") IF (iRacer < 0) OR (iRacer > (SPTT_RACER_MAX - 1)) DEBUG_MESSAGE("SPTT_Race_Racer_Blip_Destroy: Racer index out of range!") EXIT ENDIF SPTT_Racer_Blip_Destroy(Race.Racer[iRacer]) ENDPROC PROC SPTT_Race_Racer_Blip_Destroy_All(SPTT_RACE_STRUCT& Race) //DEBUG_MESSAGE("SPTT_Race_Racer_Blip_Destroy_All") INT i REPEAT Race.iRacerCnt i SPTT_Race_Racer_Blip_Destroy(Race, i) ENDREPEAT ENDPROC FUNC BOOL SPTT_Race_Racer_Create(SPTT_RACE_STRUCT& Race, INT iRacer) //DEBUG_MESSAGE("SPTT_Race_Racer_Create") IF (iRacer < 0) OR (iRacer > (SPTT_RACER_MAX - 1)) DEBUG_MESSAGE("SPTT_Race_Racer_Create: Racer index out of range!") RETURN FALSE ENDIF IF (iRacer > 0) RETURN SPTT_Racer_Create(Race.Racer[iRacer], TRUE) ELSE RETURN SPTT_Racer_Create(Race.Racer[iRacer], FALSE) ENDIF ENDFUNC FUNC BOOL SPTT_Race_Racer_Create_All(SPTT_RACE_STRUCT& Race) //DEBUG_MESSAGE("SPTT_Race_Racer_Create_All") INT i BOOL bCreateDone = TRUE REPEAT Race.iRacerCnt i IF NOT SPTT_Race_Racer_Create(Race, i) bCreateDone = FALSE ENDIF ENDREPEAT RETURN bCreateDone ENDFUNC PROC SPTT_Race_Racer_Freeze(SPTT_RACE_STRUCT& Race, INT iRacer) //DEBUG_MESSAGE("SPTT_Race_Racer_Freeze") IF (iRacer < 0) OR (iRacer > (SPTT_RACER_MAX - 1)) DEBUG_MESSAGE("SPTT_Race_Racer_Freeze: Racer index out of range!") EXIT ENDIF SPTT_Racer_Freeze(Race.Racer[iRacer]) ENDPROC PROC SPTT_Race_Racer_Freeze_All(SPTT_RACE_STRUCT& Race) //DEBUG_MESSAGE("SPTT_Race_Racer_Freeze_All") INT i REPEAT Race.iRacerCnt i SPTT_Race_Racer_Freeze(Race, i) ENDREPEAT ENDPROC PROC SPTT_Race_Racer_UnFreeze(SPTT_RACE_STRUCT& Race, INT iRacer) //DEBUG_MESSAGE("SPTT_Race_Racer_UnFreeze") IF (iRacer < 0) OR (iRacer > (SPTT_RACER_MAX - 1)) DEBUG_MESSAGE("SPTT_Race_Racer_UnFreeze: Racer index out of range!") EXIT ENDIF SPTT_Racer_UnFreeze(Race.Racer[iRacer]) ENDPROC PROC SPTT_Race_Racer_UnFreeze_All(SPTT_RACE_STRUCT& Race) //DEBUG_MESSAGE("SPTT_Race_Racer_UnFreeze_All") INT i REPEAT Race.iRacerCnt i SPTT_Race_Racer_UnFreeze(Race, i) ENDREPEAT ENDPROC PROC SPTT_Race_Racer_Release(SPTT_RACE_STRUCT& Race, INT iRacer) //DEBUG_MESSAGE("SPTT_Race_Racer_Release") IF (iRacer < 0) OR (iRacer > (SPTT_RACER_MAX - 1)) DEBUG_MESSAGE("SPTT_Race_Racer_Release: Racer index out of range!") EXIT ENDIF SPTT_Racer_Release(Race.Racer[iRacer]) ENDPROC PROC SPTT_Race_Racer_Release_All(SPTT_RACE_STRUCT& Race) //DEBUG_MESSAGE("SPTT_Race_Racer_Release_All") INT i REPEAT Race.iRacerCnt i SPTT_Race_Racer_Release(Race, i) ENDREPEAT ENDPROC PROC SPTT_Race_Racer_Destroy(SPTT_RACE_STRUCT& Race, INT iRacer) //DEBUG_MESSAGE("SPTT_Race_Racer_Destroy") IF (iRacer < 0) OR (iRacer > (SPTT_RACER_MAX - 1)) DEBUG_MESSAGE("SPTT_Race_Racer_Destroy: Racer index out of range!") EXIT ENDIF SPTT_Racer_Destroy(Race.Racer[iRacer]) ENDPROC PROC SPTT_Race_Racer_Destroy_All(SPTT_RACE_STRUCT& Race) //DEBUG_MESSAGE("SPTT_Race_Racer_Destroy_All") INT i REPEAT Race.iRacerCnt i SPTT_Race_Racer_Destroy(Race, i) ENDREPEAT ENDPROC PROC SPTT_Race_Racer_Init(SPTT_RACE_STRUCT& Race, INT iRacer) //DEBUG_MESSAGE("SPTT_Race_Racer_Init") IF (iRacer < 0) OR (iRacer > (SPTT_RACER_MAX - 1)) DEBUG_MESSAGE("SPTT_Race_Racer_Init: Racer index out of range!") EXIT ENDIF SPTT_Racer_Destroy(Race.Racer[iRacer]) SPTT_Racer_Init(Race.Racer[iRacer]) ENDPROC PROC SPTT_Race_Racer_Init_All(SPTT_RACE_STRUCT& Race) //DEBUG_MESSAGE("SPTT_Race_Racer_Init_All") INT i REPEAT Race.iRacerCnt i SPTT_Race_Racer_Init(Race, i) ENDREPEAT ENDPROC PROC SPTT_RACE_TELL_AUDIENCE_TO_LOOK_AT_PLAYER() PED_INDEX pedArray[10] GET_PED_NEARBY_PEDS(PLAYER_PED_ID(), pedArray, PEDTYPE_INVALID | PEDTYPE_MISSION) INT i = 0 REPEAT COUNT_OF(pedArray) i IF DOES_ENTITY_EXIST(pedArray[i]) AND NOT IS_PED_INJURED(pedArray[i]) SET_ENTITY_AS_MISSION_ENTITY(pedArray[i]) TASK_TURN_PED_TO_FACE_ENTITY(pedArray[i], PLAYER_PED_ID(), -1) TASK_LOOK_AT_ENTITY(pedArray[i], PLAYER_PED_ID(), -1, SLF_USE_TORSO | SLF_EXTEND_YAW_LIMIT) ENDIF ENDREPEAT ENDPROC // ----------------------------------- // RACER HELPER PROCS/FUNCTIONS // ----------------------------------- // TODO: Make following Racer function follow above scheme... PROC SPTT_Race_Racer_Start(SPTT_RACE_STRUCT& Race) //DEBUG_MESSAGE("SPTT_Race_Racer_Start") TEXT_LABEL OffroadRecording = "Offroad_" OffroadRecording += (SPTT_Master.iRaceCur+1) // Start race clock. RESTART_TIMER_NOW(Race.tClock) Race.Racer[0].fPlsMnsTot = 0//no bonus time! iHUDDisplayBonusTracker = 0 // Give back player control. SET_PLAYER_CONTROL(PLAYER_ID(), TRUE) IF (SPTT_Master.eRaceType = SPTT_RACE_TYPE_PLANE) SET_PLAYER_INVINCIBLE(PLAYER_ID(), TRUE) ENDIF Race.bFailChecking = TRUE DEBUG_MESSAGE("SPTT_Race_Racer_Start: Race.bFailChecking set to TRUE") RESTART_TIMER_NOW(manualResetTimer) DEBUG_MESSAGE("RACE_RACER_START: FAILCHECKING: ON") // Loop through all racers and start them. INT i REPEAT Race.iRacerCnt i // Start racer. SPTT_Racer_Start(Race.Racer[i]) IF SPTT_Master.eRaceType <> SPTT_RACE_TYPE_OFFROAD // TODO: Put any player specific logic here... IF i != 0 //not the player!? SPTT_Race_Racer_Task_Go_To_Next_Gate(Race, Race.Racer[i].Driver, Race.Racer[i].Vehicle, Race.sGate[Race.Racer[i].iGateCur].vPos, Race.sGate[Race.Racer[i].iGateCur].eChkpntType, i) ENDIF ELSE IF SPTT_USE_WAYPOINT_RECORDING // Task AI to follow waypoint recording for offroad race // Pick random waypoint recording to start IF i > 0 IF NOT IS_ENTITY_DEAD(Race.Racer[i].Driver) AND NOT IS_ENTITY_DEAD(Race.Racer[i].Vehicle) IF i = 1 AND SPTT_Master.iRaceCur = 0 OffroadRecording += "a" ENDIF TASK_VEHICLE_FOLLOW_WAYPOINT_RECORDING(Race.Racer[i].Driver, Race.Racer[i].Vehicle, OffroadRecording, DRIVINGMODE_PLOUGHTHROUGH, 0, EWAYPOINT_START_FROM_CLOSEST_POINT, -1, GET_VEHICLE_ESTIMATED_MAX_SPEED(Race.Racer[i].Vehicle)) ENDIF ENDIF ELSE IF i != 0 //not the player!? SPTT_Race_Racer_Task_Go_To_Next_Gate(Race, Race.Racer[i].Driver, Race.Racer[i].Vehicle, Race.sGate[Race.Racer[i].iGateCur].vPos, Race.sGate[Race.Racer[i].iGateCur].eChkpntType, i) ENDIF ENDIF ENDIF ENDREPEAT IF IS_VEHICLE_DRIVEABLE(Race.Racer[0].Vehicle) SET_VEHICLE_RADIO_ENABLED(Race.Racer[0].Vehicle, TRUE) IF NOT IS_STRING_NULL_OR_EMPTY(sRadStation) SET_RADIO_TO_STATION_NAME(sRadStation) SET_VEH_RADIO_STATION(Race.Racer[0].Vehicle, sRadStation) DEBUG_MESSAGE("SPTT_Race_Racer_Start: SET_VEH_RADIO_STATION") ENDIF ENDIF ENDPROC PROC AI_End_Of_Race_Stop(SPTT_RACE_STRUCT& Race) INT i REPEAT Race.iRacerCnt i IF i > 0 IF NOT IS_ENTITY_DEAD(Race.Racer[i].Driver) AND NOT IS_ENTITY_DEAD(Race.Racer[i].Vehicle) IF SPTT_Master.eRaceType <> SPTT_RACE_TYPE_TRIATHLON TASK_VEHICLE_TEMP_ACTION(Race.Racer[i].Driver,Race.Racer[i].Vehicle, TEMPACT_HANDBRAKETURNRIGHT, 5000) ENDIF ENDIF ENDIF ENDREPEAT ENDPROC PROC SPTT_Race_Racer_Finish(SPTT_RACE_STRUCT& Race) //PRINTLN("[SPTT_Race.sch->SPTT_Race_Racer_Finish] Procedure started.") // Pause race clock, if needed. IF NOT IS_TIMER_PAUSED(Race.tClock) PAUSE_TIMER(Race.tClock) ENDIF SET_ENTITY_INVINCIBLE(Race.Racer[0].Vehicle, TRUE) DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_EXIT) SPTT_Race_ClockTime_SimAI(Race) // Calculate final race ranks. IF SPTT_Master.eRaceType = SPTT_RACE_TYPE_PLANE SPTT_Race_Rank_CalcFinal(Race) ENDIF // Find player best rank and clock time. SPTT_Race_RankClock_FindPlayerBest(Race) // Loop through all racers and finish them. INT iLoopCounter REPEAT Race.iRacerCnt iLoopCounter SPTT_Racer_Finish(Race.Racer[iLoopCounter]) IF iLoopCounter <> 0 FINISH_AI_RACERS(Race.Racer[iLoopCounter]) ENDIF ENDREPEAT ENDPROC PROC SPTT_Race_Racer_Gate_Jump(SPTT_RACE_STRUCT& Race, INT iRacer, INT iGate, BOOL bBlockLoad = FALSE) //DEBUG_MESSAGE("SPTT_Race_Racer_Gate_Jump") IF (iGate < 0) OR (iGate > (Race.iGateCnt - 1)) DEBUG_MESSAGE("SPTT_Race_Racer_Gate_Jump: Gate index out of range!") EXIT ENDIF IF (iRacer < 0) OR (iRacer > (Race.iRacerCnt - 1)) DEBUG_MESSAGE("SPTT_Race_Racer_Gate_Jump: Racer index out of range!") EXIT ENDIF // TODO: Decide if this is the right error checking needed... IF IS_ENTITY_DEAD(Race.Racer[iRacer].Driver) EXIT ENDIF IF (Race.Racer[iRacer].eVehicleModel <> DUMMY_MODEL_FOR_SCRIPT) IF IS_ENTITY_DEAD(Race.Racer[iRacer].Vehicle) EXIT ENDIF ENDIF VECTOR vFwd = Race.sGate[iGate + 1].vPos - Race.sGate[iGate].vPos FLOAT fHeading = GET_HEADING_FROM_VECTOR_2D(vFwd.x, vFwd.y) FLOAT fSpeed = 0.0 IF IS_THIS_MODEL_A_BIKE(Race.Racer[iRacer].eVehicleModel) fSpeed = 0.0 ELIF IS_THIS_MODEL_A_CAR(Race.Racer[iRacer].eVehicleModel) fSpeed = 25.0 ELIF IS_THIS_MODEL_A_PLANE(Race.Racer[iRacer].eVehicleModel) fSpeed = SPTT_PLANE_SPD_MAX ENDIF IF bBlockLoad PRINTLN("[SPTT_Race_Racer_Gate_Jump] Loading scene from gate jumping. This is NOT a new load scene.") //LOAD_SCENE(Race.sGate[iGate].vPos) ENDIF SPTT_Racer_Teleport(Race.Racer[iRacer], Race.sGate[iGate].vPos, fHeading, fSpeed) ENDPROC PROC SPTT_Race_Racer_Gate_Jump_Cur(SPTT_RACE_STRUCT& Race, INT iRacer, BOOL bBlockLoad = FALSE) //DEBUG_MESSAGE("SPTT_Race_Racer_Gate_Jump_Cur") SPTT_Race_Racer_Gate_Jump(Race, iRacer, Race.Racer[iRacer].iGateCur, bBlockLoad) ENDPROC PROC SPTT_Race_Racer_Gate_Jump_Nxt(SPTT_RACE_STRUCT& Race, INT iRacer, BOOL bBlockLoad = FALSE) //DEBUG_MESSAGE("SPTT_Race_Racer_Gate_Jump_Nxt") SPTT_Race_Racer_Gate_Jump(Race, iRacer, Race.Racer[iRacer].iGateCur - 1, bBlockLoad) ENDPROC PROC SPTT_Race_Racer_Gate_Jump_Last(SPTT_RACE_STRUCT& Race, INT iRacer, BOOL bBlockLoad = FALSE) //DEBUG_MESSAGE("SPTT_Race_Racer_Gate_Jump_Last") Race.Racer[iRacer].iGateCur = Race.iGateCnt-1 SPTT_Race_Racer_Gate_Jump(Race, iRacer, Race.iGateCnt-1, bBlockLoad) ENDPROC PROC SPTT_Race_Racer_Gate_Jump_Penultimate(SPTT_RACE_STRUCT& Race, INT iRacer, BOOL bBlockLoad = FALSE) //DEBUG_MESSAGE("SPTT_Race_Racer_Gate_Jump_Last") Race.Racer[iRacer].iGateCur = Race.iGateCnt-3 SPTT_Race_Racer_Gate_Jump(Race, iRacer, Race.iGateCnt-3, bBlockLoad) ENDPROC PROC SPTT_Race_Racer_Rank_Calc(SPTT_RACE_STRUCT& Race, INT iRacer) //DEBUG_MESSAGE("SPTT_Race_Racer_Rank_Calc") IF (iRacer < 0) OR (iRacer > (Race.iRacerCnt - 1)) DEBUG_MESSAGE("SPTT_Race_Racer_Rank_Calc: Racer index out of range!") EXIT ENDIF INT nRank = Race.iRacerCnt INT i SPTT_RACER_STRUCT tmpRacer = Race.Racer[iRacer] REPEAT Race.iRacerCnt i //skip ourselves IF tmpRacer.Driver <> Race.Racer[i].Driver IF NOT IS_ENTITY_DEAD(Race.Racer[i].Driver) AND NOT IS_ENTITY_DEAD(tmpRacer.Driver) IF tmpRacer.iGateCur > Race.Racer[i].iGateCur nRank-- ELIF tmpRacer.iGateCur = Race.Racer[i].iGateCur //same checkpoint lets get the distance to the next checkpoint FLOAT ourRacer, evilRacer ourRacer = GET_ENTITY_DISTANCE_FROM_LOCATION(tmpRacer.Driver, Race.sGate[tmpRacer.iGateCur].vPos) evilRacer = GET_ENTITY_DISTANCE_FROM_LOCATION(Race.Racer[i].Driver, Race.sGate[Race.Racer[i].iGateCur].vPos) IF ourRacer < evilRacer nRank-- ENDIF ENDIF ELSE nRank-- ENDIF ENDIF ENDREPEAT Race.Racer[iRacer].iRank=nRank ENDPROC PROC SPTT_Race_Racer_Fix_Up_Start(VECTOR vCurGatePos1, VEHICLE_INDEX iPlaneIndex, VECTOR vCurGatePos, BOOL bIsStart) PRINTLN("[SPTT_Race_Racer_Fix_Up_Start] Procedure called.") IF NOT IS_ENTITY_DEAD(iPlaneIndex) FLOAT fHeading FLOAT fPitch // FLOAT fPitchRad VECTOR vRotation VECTOR vPlayersPlaneCurrentPos VECTOR vGateDiff // Stuntplane minimum hard deck check FLOAT fHardDeckGround VECTOR vHardDeckProbe //1524715 //special case for bridge binge because it doesn't teleport player at beginning //...first gate in bad restart position IF bIsStart AND INT_TO_ENUM(SPTT_Races_ENUM, SPTT_Master.iRaceCur) = SPTT_BridgeBinge SET_ENTITY_COORDS(iPlaneIndex, <<1705.0386, 3251.1299, 40.0016>>) PRINTLN("Resetting at the beginning of bridge binge so using special coords") ENDIF vHardDeckProbe = GET_ENTITY_COORDS(iPlaneIndex) REQUEST_COLLISION_AT_COORD(vHardDeckProbe) GET_GROUND_Z_FOR_3D_COORD(vHardDeckProbe, fHardDeckGround) PRINTSTRING("Ground Height is: ") PRINTFLOAT(fHardDeckGround) PRINTNL() vPlayersPlaneCurrentPos = GET_ENTITY_COORDS(iPlaneIndex) // PRINTSTRING("vPlayersPlaneCurrentPos is: ") // PRINTVECTOR(vPlayersPlaneCurrentPos) // PRINTNL() IF bIsStart DEBUG_MESSAGE("iGateCur = 0 using vCurGatePos for vGateDiff") vGateDiff = vCurGatePos1 - vCurGatePos ELSE DEBUG_MESSAGE("iGateCur != 0 using regular diff") vGateDiff = vCurGatePos - vPlayersPlaneCurrentPos ENDIF fHeading = GET_HEADING_FROM_VECTOR_2D(vGateDiff.x, vGateDiff.y) // PRINTSTRING("fHeading is: ") // PRINTFLOAT(fHeading) // PRINTNL() fPitch = GET_HEADING_FROM_VECTOR_2D(vGateDiff.x, vGateDiff.z)-270 PRINTSTRING("fPitch is: ") PRINTFLOAT(fPitch) PRINTNL() WHILE fPitch > 180 fPitch -= 360 ENDWHILE WHILE fPitch < -180 fPitch += 360 ENDWHILE IF fPitch < -90 fPitch = -(180-ABSF(fPitch)) ENDIF IF fPitch > 90 fPitch = (180-ABSF(fPitch)) ENDIF PRINTSTRING("fPitch is: ") PRINTFLOAT(fPitch) PRINTNL() IF ( ABSF(vHardDeckProbe.z - fHardDeckGround) < 25.0 ) AND ( (fPitch > 15) OR (fPitch < -15) ) vHardDeckProbe.z = fHardDeckGround + 25.0 SET_ENTITY_COORDS(iPlaneIndex, vHardDeckProbe) PRINTSTRING("MOVING PLAYER'S PLANE 25 METERS ABOVE THE GROUND") PRINTNL() // ELSE // PRINTSTRING("Player is already this many meters above the ground: !") // PRINTFLOAT(ABSF(vHardDeckProbe.z - fHardDeckGround)) // PRINTNL() ENDIF FREEZE_ENTITY_POSITION(iPlaneIndex, TRUE) vRotation = GET_ENTITY_ROTATION(iPlaneIndex) vRotation.x = fPitch //we may not want to set this if the next gate is lower than the restart position and is close (hit the ground a lot)...that or set it to a portion of the pitch, using height delta and distance delta as the ratio vRotation.z = fHeading SET_ENTITY_ROTATION(iPlaneIndex, vRotation) FREEZE_ENTITY_POSITION(iPlaneIndex, FALSE) PRINTSTRING("GET_ENTITY_PITCH is: ") PRINTFLOAT(GET_ENTITY_PITCH(iPlaneIndex)) PRINTNL() NEW_LOAD_SCENE_START(vHardDeckProbe, GET_ENTITY_FORWARD_VECTOR(iPlaneIndex), 500.0) PRINTLN("[SPTT_Race_Racer_Fix_Up_Start] Starting new load scene at hard deck probe: ", vHardDeckProbe) ENDIF ENDPROC /// PURPOSE: /// Reset SPR Race Racer. /// RETURNS: /// TRUE if resetting SPR Race Racer. FUNC BOOL SPTT_Race_Racer_Reset(SPTT_RACE_STRUCT& Race, SPTT_RACER_STRUCT& Racer, BOOL bRacerIsPlayer) //PRINTLN("[SPTT_Race_Racer_Reset] Function started.") // Reset Racer State Machine. SWITCH (Racer.eReset) // Failcase PLAYER HAS FORFEITED RACE CASE SPTT_RACER_RESET_FAIL_OVER SPTT_Race_Gate_Deactivate_All(Race) SPTT_RACE_CLEANUP_FINISH_STREAMVOL() INIT_SIMPLE_USE_CONTEXT(SPTT_Master.uiInput, FALSE, FALSE, TRUE, TRUE) ADD_SIMPLE_USE_CONTEXT_INPUT(SPTT_Master.uiInput, "IB_RETRY", FRONTEND_CONTROL, INPUT_FRONTEND_ACCEPT) ADD_SIMPLE_USE_CONTEXT_INPUT(SPTT_Master.uiInput, "FE_HLP16", FRONTEND_CONTROL, INPUT_FRONTEND_CANCEL) SET_MINIGAME_SPLASH_SHOWING(TRUE) TRIGGER_MUSIC_EVENT("MGSP_FAIL") Racer.eReset = SPTT_RACER_RESET_FAIL_EFFECTS BREAK CASE SPTT_RACER_RESET_FAIL_EFFECTS IF MG_UPDATE_FAIL_FADE_EFFECT(SPTT_Master.failFadeEffect, SPTT_Master.failSplash, Race.bigMessageUI, spttFailString, spttFailStrapline, Race.bRestarting) bTriggerFirstMusicEvent = FALSE IF NOT IS_ENTITY_DEAD(Race.Racer[0].Vehicle) SET_VEHICLE_DOORS_LOCKED(Race.Racer[0].Vehicle, VEHICLELOCK_LOCKED_PLAYER_INSIDE) ENDIF IF IS_THIS_PRINT_BEING_DISPLAYED("SPR_HELP_DAMG") CLEAR_THIS_PRINT("SPR_HELP_DAMG") ENDIF PRINTLN("SPTT_RACER_RESET_FAIL_OVER Race.bFailChecking = FALSE ") Race.bFailChecking = FALSE MG_INIT_FAIL_FADE_EFFECT(SPTT_Master.failFadeEffect, TRUE) // Setup Scaleform UI for reset/restart. // SHOULDN'T BE CALLING SETUP AND UPDATE EVERY FRAME. SETUP ONCE, UPDATE EVERY FRAME. //SET_SCALEFORM_BIG_MESSAGE(Race.bigMessageUI, spttFailString, spttFailStrapline, -1, HUD_COLOUR_RED, DEFAULT, TRUE, 0.15) //Racer.eReset = SPTT_RACER_RESET_FAIL_SELECT_RETRY IF Race.bRestarting //cleanup fail effects MG_DO_FAIL_EFFECT(FALSE) MG_DO_FAIL_OUT_EFFECT(FALSE) MG_RESET_FAIL_EFFECT_VARS() //iButtonSounds = GET_SOUND_ID() //ODDJOB_PLAY_SOUND("Phone_Generic_Key_02", iButtonSounds, FALSE) //PLAY_SOUND_FRONTEND(iButtonSounds, "Phone_Generic_Key_02", "HUD_MINIGAME_SOUNDSET") //kill the chase came so if we were looking at //it when we reset the camera is still not looking at it. IF IS_THIS_PRINT_BEING_DISPLAYED("SPR_RETR_DES") CLEAR_THIS_PRINT("SPR_RETR_DES") ENDIF // This command also sets the cinematic cam back to true, so turning off for Tri. // KILL_CHASE_HINT_CAM(localChaseHintCamStruct) SET_MINIGAME_SPLASH_SHOWING(FALSE) Race.bRestarting = TRUE Racer.eReset = SPTT_RACER_RESET_FADE_OUT ELSE //cleanup fail effects MG_DO_FAIL_EFFECT(FALSE) MG_DO_FAIL_OUT_EFFECT(FALSE) MG_RESET_FAIL_EFFECT_VARS() //iButtonSounds = GET_SOUND_ID() //ODDJOB_PLAY_SOUND("Phone_Generic_Key_03", iButtonSounds, FALSE) //PLAY_SOUND_FRONTEND(iButtonSounds, "Phone_Generic_Key_03", "HUD_MINIGAME_SOUNDSET") // Kill the chase cam in case it's being used. // This command also sets the cinematic cam back to true, so turning off for Tri. // KILL_CHASE_HINT_CAM(localChaseHintCamStruct) DEBUG_MESSAGE("[SPTT_Race->SPTT_Race_Racer_Reset] CASE SPTT_RACER_RESET_FAIL_OVER: CASE GET_CONTROL_INSTRUCTIONAL_BUTTONS_STRING(FRONTEND_CONTROL, INPUT_FRONTEND_Y): eReset = SPTT_RACER_QUIT_FADE_OUT") ADJUST_TIMER(exitTimer, 10.0) SET_MINIGAME_SPLASH_SHOWING(FALSE) Race.bRestarting = FALSE Racer.eReset = SPTT_RACER_QUIT_FADE_OUT ENDIF ENDIF BREAK // DEPRECATED. New fail screen handles this in the SPTT_RACER_RESET_FAIL_EFFECTS, just above. CASE SPTT_RACER_RESET_FAIL_SELECT_RETRY PRINTLN("updating retry screen") /* SET_SCRIPT_GFX_DRAW_ORDER(GFX_ORDER_AFTER_FADE) UPDATE_SCALEFORM_BIG_MESSAGE(Race.bigMessageUI) DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_CIN_CAM) DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_EXIT) DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_SELECT_NEXT_WEAPON) DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_SELECT_PREV_WEAPON) HIDE_HUD_COMPONENT_THIS_FRAME(NEW_HUD_STREET_NAME) HIDE_HUD_COMPONENT_THIS_FRAME(NEW_HUD_AREA_NAME) */ UPDATE_SIMPLE_USE_CONTEXT(SPTT_Master.uiInput, DEFAULT, GFX_ORDER_AFTER_FADE, TRUE) IF IS_CONTROL_JUST_PRESSED(FRONTEND_CONTROL, INPUT_FRONTEND_ACCEPT) //cleanup fail effects MG_DO_FAIL_EFFECT(FALSE) MG_DO_FAIL_OUT_EFFECT(FALSE) MG_RESET_FAIL_EFFECT_VARS() iButtonSounds = GET_SOUND_ID() //ODDJOB_PLAY_SOUND("Phone_Generic_Key_02", iButtonSounds, FALSE) PLAY_SOUND_FRONTEND(iButtonSounds, "Phone_Generic_Key_02", "HUD_MINIGAME_SOUNDSET") //kill the chase came so if we were looking at //it when we reset the camera is still not looking at it. IF IS_THIS_PRINT_BEING_DISPLAYED("SPR_RETR_DES") CLEAR_THIS_PRINT("SPR_RETR_DES") ENDIF // This command also sets the cinematic cam back to true, so turning off for Tri. // KILL_CHASE_HINT_CAM(localChaseHintCamStruct) SET_MINIGAME_SPLASH_SHOWING(FALSE) Race.bRestarting = TRUE Racer.eReset = SPTT_RACER_RESET_FADE_OUT ELIF IS_CONTROL_JUST_PRESSED(FRONTEND_CONTROL, INPUT_FRONTEND_CANCEL) //cleanup fail effects MG_DO_FAIL_EFFECT(FALSE) MG_DO_FAIL_OUT_EFFECT(FALSE) MG_RESET_FAIL_EFFECT_VARS() iButtonSounds = GET_SOUND_ID() //ODDJOB_PLAY_SOUND("Phone_Generic_Key_03", iButtonSounds, FALSE) PLAY_SOUND_FRONTEND(iButtonSounds, "Phone_Generic_Key_03", "HUD_MINIGAME_SOUNDSET") // Kill the chase cam in case it's being used. // This command also sets the cinematic cam back to true, so turning off for Tri. // KILL_CHASE_HINT_CAM(localChaseHintCamStruct) DEBUG_MESSAGE("[SPTT_Race->SPTT_Race_Racer_Reset] CASE SPTT_RACER_RESET_FAIL_OVER: CASE GET_CONTROL_INSTRUCTIONAL_BUTTONS_STRING(FRONTEND_CONTROL, INPUT_FRONTEND_Y): eReset = SPTT_RACER_QUIT_FADE_OUT") ADJUST_TIMER(exitTimer, 10.0) SET_MINIGAME_SPLASH_SHOWING(FALSE) Race.bRestarting = FALSE Racer.eReset = SPTT_RACER_QUIT_FADE_OUT ENDIF BREAK // Reset racer (init). NOTE: Check if this ever used. CASE SPTT_RACER_RESET_INIT IF Race.bRestarting = TRUE Race.bFailChecking = FALSE DEBUG_MESSAGE("SPTT_RACER_RESET_INIT: Race.bFailChecking set to FALSE") ENDIF // Overwrite racer start pos with current gate pos. IF Racer.iGateCur > 0 Racer.vStartPos = Race.sGate[Racer.iGateCur].vPos ENDIF // Setup Scaleform UI for reset/restart. IF bRacerIsPlayer // Write something to put the player into the vehicle IF IS_VEHICLE_DRIVEABLE(Race.Racer[0].Vehicle) SET_PLAYER_INVINCIBLE(PLAYER_ID(), TRUE) SET_PLAYER_CONTROL(PLAYER_ID(), FALSE) INIT_SIMPLE_USE_CONTEXT(SPTT_Master.uiInput, FALSE, FALSE, TRUE, TRUE) ADD_SIMPLE_USE_CONTEXT_INPUT(SPTT_Master.uiInput, "SPR_UI_CONT", FRONTEND_CONTROL, INPUT_FRONTEND_ACCEPT) ADD_SIMPLE_USE_CONTEXT_INPUT(SPTT_Master.uiInput, "IB_NO", FRONTEND_CONTROL, INPUT_FRONTEND_CANCEL) ENDIF ENDIF // If racer is player, go to choose state. IF bRacerIsPlayer // Write something to put the player into the vehicle IF IS_VEHICLE_DRIVEABLE(Race.Racer[0].Vehicle)//NOT IS_ENTITY_DEAD(Race.Racer[0].Vehicle) //IF NOT IS_PED_IN_VEHICLE(Race.Racer[0].Driver, Race.Racer[0].Vehicle) // SET_PED_INTO_VEHICLE(Race.Racer[0].Driver, Race.Racer[0].Vehicle, VS_DRIVER) // SET_PLAYER_CONTROL(PLAYER_ID(), FALSE)//, SPC_ALLOW_PLAYER_DAMAGE) DEBUG_MESSAGE("Moving to SPTT_RACER_RESET_CHOOSE") Racer.eReset = SPTT_RACER_RESET_CHOOSE //ENDIF ENDIF ELSE // Otherwise, racer is ai, go to create state. DEBUG_MESSAGE("Moving to SPTT_RACER_RESET_CREATE") Racer.eReset = SPTT_RACER_RESET_CREATE ENDIF BREAK // Choose reset/restart. CASE SPTT_RACER_RESET_CHOOSE IF NOT IS_ENTITY_DEAD(Race.Racer[0].Vehicle) SET_VEHICLE_DOORS_LOCKED(Race.Racer[0].Vehicle, VEHICLELOCK_LOCKED_PLAYER_INSIDE) ENDIF Race.bFailChecking = FALSE // DEBUG_MESSAGE("SPTT_RACER_RESET_CHOOSE - Race.bFailChecking = FALSE") IF (GET_TIMER_IN_SECONDS(exitTimer) <= 10.0) // If racer is player, display reset/restart options. IF bRacerIsPlayer HIDE_HUD_COMPONENT_THIS_FRAME(NEW_HUD_STREET_NAME) HIDE_HUD_COMPONENT_THIS_FRAME(NEW_HUD_AREA_NAME) DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_SELECT_NEXT_WEAPON) DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_SELECT_PREV_WEAPON) UPDATE_SIMPLE_USE_CONTEXT(SPTT_Master.uiInput) IF IS_CONTROL_JUST_PRESSED( FRONTEND_CONTROL, INPUT_FRONTEND_ACCEPT) Race.bRestarting = TRUE DEBUG_MESSAGE("Moving to SPTT_RACER_RESET_FADE_OUT") iButtonSounds = GET_SOUND_ID() //ODDJOB_PLAY_SOUND("Phone_Generic_Key_02", iButtonSounds, FALSE) PLAY_SOUND_FRONTEND(iButtonSounds, "Phone_Generic_Key_02", "HUD_MINIGAME_SOUNDSET") Racer.eReset = SPTT_RACER_RESET_FADE_OUT //kill the chase came so if we were looking at //it when we reset the camera is still not looking at it. ELIF IS_CONTROL_JUST_PRESSED( FRONTEND_CONTROL, INPUT_FRONTEND_CANCEL) Race.bRestarting = FALSE //kill the chase came so if we were looking at //it when we reset the camera is still not looking at it. // KILL_CHASE_HINT_CAM(localChaseHintCamStruct) DEBUG_MESSAGE("Moving to SPTT_RACER_QUIT_FADE_OUT") ADJUST_TIMER(exitTimer, 10.0) iButtonSounds = GET_SOUND_ID() //ODDJOB_PLAY_SOUND("Phone_Generic_Key_03", iButtonSounds, FALSE) PLAY_SOUND_FRONTEND(iButtonSounds, "Phone_Generic_Key_03", "HUD_MINIGAME_SOUNDSET") Racer.eReset = SPTT_RACER_RESET_FADE_OUT ENDIF ENDIF ELSE CLEAR_PRINTS() //changing big message for b* 1366955 spttFailStrapline = "SPR_RETR_DES" MG_INIT_FAIL_FADE_EFFECT(SPTT_Master.failFadeEffect, TRUE) //SET_SCALEFORM_BIG_MESSAGE(Race.bigMessageUI, spttFailString, spttFailStrapline, -1, HUD_COLOUR_RED, DEFAULT, TRUE, 0.15) Racer.eReset = SPTT_RACER_QUIT_EXIT ENDIF BREAK // Fade out screen to black. CASE SPTT_RACER_RESET_FADE_OUT IF SPTT_FadeOut_Safe(SPTT_FADE_QUICK_TIME) CLEAR_PRINTS() CLEAR_HELP() PRINTLN("[SPTT_Race_Racer_Reset] SPTT_RACER_RESET_FADE_OUT: Screen done fading OUT. Racer.eReset = SPTT_RACER_RESET_CREATE.") Racer.eReset = SPTT_RACER_RESET_CREATE ELSE PRINTLN("[SPTT_Race_Racer_Reset] SPTT_RACER_RESET_FADE_OUT: Fading out screen...") ENDIF BREAK // Fade out from quitting race. CASE SPTT_RACER_QUIT_FADE_OUT IF IS_TIMER_STARTED(Race.tClock) PRINTLN("[SPTT_Race_Racer_Reset] SPTT_RACER_QUIT_FADE_OUT: Cancel the clock timer.") CANCEL_TIMER(Race.tClock) ENDIF IF MG_DO_FAIL_BLUR_EFFECT() IF IS_SCREEN_FADED_OUT() PRINTLN("[SPTT_Race_Racer_Reset] SPTT_RACER_QUIT_FADE_OUT: The screen has faded out. Disabling player control and deactivating all gates.") SPTT_Race_Gate_Deactivate_All(Race) SET_PLAYER_CONTROL(PLAYER_ID(), FALSE) IF DOES_ENTITY_EXIST(Race.Racer[0].Vehicle) PRINTLN("[SPTT_Race_Racer_Reset] SPTT_RACER_QUIT_FADE_OUT: Stop the plane and replenish its health.") SET_ENTITY_VELOCITY(Race.Racer[0].Vehicle, <<0, 0, 0>>) SET_ENTITY_HEALTH(Race.Racer[0].Vehicle, GET_ENTITY_MAX_HEALTH(Race.Racer[0].Vehicle)) ENDIF DEBUG_MESSAGE("[SPTT_Race_Racer_Reset] SPTT_RACER_QUIT_FADE_OUT: Racer.eReset = SPTT_RACER_QUIT_PLACE.") Racer.eReset = SPTT_RACER_QUIT_PLACE ENDIF ENDIF BREAK // Create the racer's driver and vehicle. CASE SPTT_RACER_RESET_CREATE IF SPTT_Racer_Create(Racer, TRUE) PRINTLN("[SPTT_Race_Racer_Reset] SPTT_RACER_RESET_CREATE: Racer created.") IF Race.bRestarting PRINTLN("[SPTT_Race_Racer_Reset] SPTT_RACER_RESET_CREATE: Trial is restarting. Race.eUpdate = SPTT_RACE_UPDATE_CLEANUP.") Race.eUpdate = SPTT_RACE_UPDATE_CLEANUP ELSE PRINTLN("[SPTT_Race_Racer_Reset] SPTT_RACER_RESET_CREATE: Trial is NOT restarting.") // ???: I wonder if we need to enable control this early since the screen is still faded out. And do we need to check bRacerIsPlayer? //give back the player control here so they don't drop out of the sky IF bRacerIsPlayer // Give back player control. SET_PLAYER_CONTROL(PLAYER_ID(), TRUE) IF (SPTT_Master.eRaceType = SPTT_RACE_TYPE_PLANE) SET_PLAYER_INVINCIBLE(PLAYER_ID(), TRUE) ENDIF ENDIF PRINTLN("[SPTT_Race_Racer_Reset] SPTT_RACER_RESET_CREATE: Racer.eReset = SPTT_RACER_RESET_PLACE.") Racer.eReset = SPTT_RACER_RESET_PLACE ENDIF ELSE PRINTLN("[SPTT_Race_Racer_Reset] SPTT_RACER_RESET_CREATE: Racer not yet created.") ENDIF BREAK // Place racer during fade out. CASE SPTT_RACER_RESET_PLACE PRINTLN("[SPTT_Race_Racer_Reset] SPTT_RACER_RESET_PLACE: Case entered.") // ???: Why are we doing this? INT i REPEAT Race.iRacerCnt i IF (Race.Racer[i].Driver = Racer.Driver) PRINTLN("[SPTT_Race_Racer_Reset] SPTT_RACER_RESET_PLACE: Teleport this racer to the next checkpoint... because YES?") SPTT_Race_Racer_Gate_Jump_Nxt(Race, i) ENDIF ENDREPEAT IF bRacerIsPlayer IF NOT IS_ENTITY_DEAD(Race.Racer[0].Vehicle) AND (Race.Racer[0].iGateCur != -1) SPTT_Race_Racer_Fix_Up_Start(Race.sGate[Race.Racer[0].iGateCur+1].vPos, Race.Racer[0].Vehicle, Race.sGate[Race.Racer[0].iGateCur].vPos, (Race.Racer[0].iGateCur = 0)) ENDIF SET_GAMEPLAY_CAM_RELATIVE_HEADING() PRINTLN("[SPTT_Race.sch->SPTT_Race_Racer_Reset] From SPTT_RACER_RESET_PLACE to SPTT_RACER_RESET_FADE_IN.") RESTART_TIMER_NOW(manualResetTimer) Racer.eReset = SPTT_RACER_RESET_FADE_IN ELSE // Otherwise, racer is ai, go to wait state. PRINTLN("[SPTT_Race.sch->SPTT_Race_Racer_Reset] From SPTT_RACER_RESET_PLACE to SPTT_RACER_RESET_WAIT.") Racer.eReset = SPTT_RACER_RESET_WAIT ENDIF BREAK // Return the player and vehicle to the main menu. CASE SPTT_RACER_QUIT_PLACE // Cleanup fail effects. MG_DO_FAIL_EFFECT(FALSE) MG_DO_FAIL_OUT_EFFECT(FALSE) // Reset vehicle here. SPTT_Racer_Vehicle_Create(Racer, TRUE) // Return the player to the hangar, where the main menu will be. SPTT_Racer_Teleport(Racer, SPTT_Master.vDefRcrPos, SPTT_Master.fDefRcrHead, 0.0) SETTIMERA(0) PRINTLN("[SPTT_Race_Racer_Reset] SPTT_RACER_QUIT_PLACE: Racer.eReset=SPTT_RACER_QUIT_FADE_IN") Racer.eReset=SPTT_RACER_QUIT_FADE_IN BREAK // Fade in. CASE SPTT_RACER_RESET_FADE_IN IF NOT IS_NEW_LOAD_SCENE_ACTIVE() OR IS_NEW_LOAD_SCENE_LOADED() PRINTLN("[SPTT_Race_Racer_Reset] SPTT_RACER_RESET_FADE_IN: NEW_LOAD_SCENE_START has loaded.") Race.bFailChecking = TRUE DEBUG_MESSAGE("SPTT_RACER_RESET_FADE_IN: Race.bFailChecking set to TRUE") RESTART_TIMER_NOW(manualResetTimer) SPTT_Racer_AutoPilot(Race.Racer[i], SPTT_PLANE_SPD_MAX, FALSE) IF SPTT_FadeIn_Safe(SPTT_FADE_QUICK_TIME) PRINTLN("[SPTT_Race_Racer_Reset] SPTT_RACER_RESET_FADE_IN: Faded in, so stop scene from loading.") NEW_LOAD_SCENE_STOP() DEBUG_MESSAGE("RACER_RESET_FADE_IN: FAILCHECKING: ON") IF NOT IS_ENTITY_DEAD(Race.Racer[0].Vehicle) SET_PED_INTO_VEHICLE(Race.Racer[0].Driver, Race.Racer[0].Vehicle, VS_DRIVER) ENDIF DEBUG_MESSAGE("Going to RESET_WAIT from QUIT_FADE_IN") IF bRacerIsPlayer AND SPTT_Master.eRaceType = SPTT_RACE_TYPE_PLANE SPTT_Racer_ClockTime_Penalty(Race.Racer[0], SPTT_GATE_MISS_PENALTY) ENDIF Racer.eReset = SPTT_RACER_RESET_WAIT ENDIF // Reset SPR Racer waiting. RETURN FALSE ELSE IF IS_NEW_LOAD_SCENE_ACTIVE() IF Race.Racer[0].iGateCur < Race.iGateCnt IF IS_TIMER_STARTED(manualResetTimer) IF GET_TIMER_IN_SECONDS_SAFE(manualResetTimer) >= 3.0 NEW_LOAD_SCENE_STOP() ENDIF ELSE START_TIMER_NOW_SAFE(manualResetTimer) ENDIF PRINTLN("GET_TIMER_IN_SECONDS_SAFE(manualResetTimer) is...", GET_TIMER_IN_SECONDS_SAFE(manualResetTimer)) ENDIF ENDIF PRINTLN("[SPTT_Race_Racer_Reset] SPTT_RACER_RESET_FADE_IN: New scene is active or new scene has not loaded. Waiting otherwise.") ENDIF BREAK CASE SPTT_RACER_QUIT_FADE_IN PRINTLN("[SPTT_Race_Racer_Reset] SPTT_RACER_QUIT_FADE_IN: Race.eUpdate = SPTT_RACE_UPDATE_CLEANUP. Returning FALSE.") Race.eUpdate = SPTT_RACE_UPDATE_CLEANUP RETURN FALSE BREAK // Reset racer (wait). CASE SPTT_RACER_RESET_WAIT // If racer crashed, go to init state. IF Racer.eVehicleModel <> DUMMY_MODEL_FOR_SCRIPT IF NOT IS_ENTITY_DEAD(Racer.Driver) IF SPTT_Racer_Stuck_Check(Racer) // OR ( NOT IS_PED_IN_VEHICLE(Racer.Driver, Racer.Vehicle) AND (SPTT_Master.eRaceType != SPTT_RACE_TYPE_OFFROAD) ) DEBUG_MESSAGE("Player isn't in the vehicle, moving to SPTT_RACER_RESET_INIT") RESTART_TIMER_NOW(exitTimer) spttFailStrapline = "SPR_RETR_STUK" Racer.eReset = SPTT_RACER_RESET_FAIL_OVER RETURN TRUE ENDIF ENDIF ENDIF // Reset SPR Racer waiting. RETURN FALSE CASE SPTT_RACER_QUIT_EXIT SPTT_Race_Gate_Deactivate_All(Race) CANCEL_TIMER(Race.tClock) Race.eUpdate = SPTT_RACE_UPDATE_CLEANUP BREAK ENDSWITCH // Reset SPR Racer running. RETURN TRUE ENDFUNC /// PURPOSE: /// Update SPR Race Racers. /// RETURNS: /// TRUE if still updating SPR Race Racers. FUNC BOOL SPTT_Race_Racer_Update(SPTT_RACE_STRUCT& Race, SPTT_RACE_TYPE_ENUM eRaceType) //DEBUG_MESSAGE("SPTT_Race_Racer_Update") // TODO: Break this into a function called for each racer, // then make this function call that in a loop...... // Local variables. FLOAT fClockTime INT i IF INT_TO_ENUM(SPTT_Races_ENUM, SPTT_Master.iRaceCur) = SPTT_BridgeBinge //if we're on bridge binge, dont update until after the first gate IF Race.Racer[0].iGateCur = 0 RESTART_TIMER_NOW(Race.tClock) IF IS_BITMASK_AS_ENUM_SET(SPTT_HELP_BIT, SPTT_RESET_INFO) RESET_VEHICLE_STUCK_TIMER(Race.Racer[0].Vehicle, VEH_STUCK_RESET_ALL) CLEAR_BITMASK_AS_ENUM(SPTT_HELP_BIT, SPTT_RESET_INFO) ENDIF ELIF Race.Racer[0].iGateCur = 1 AND NOT IS_BITMASK_AS_ENUM_SET(SPTT_HELP_BIT, SPTT_RESET_INFO) PRINT_HELP("SPR_INFO_BON", DEFAULT_HELP_TEXT_TIME) SET_BITMASK_AS_ENUM(SPTT_HELP_BIT, SPTT_RESET_INFO) IF IS_BITMASK_AS_ENUM_SET(SPTT_HELP_BIT, SPTT_TIME_INFO) CLEAR_BITMASK_AS_ENUM(SPTT_HELP_BIT, SPTT_TIME_INFO) ENDIF ELIF Race.Racer[0].iGateCur = 4 AND NOT IS_BITMASK_AS_ENUM_SET(SPTT_HELP_BIT, SPTT_TIME_INFO) PRINT_HELP("SPR_INFO_RESET", DEFAULT_HELP_TEXT_TIME) SET_BITMASK_AS_ENUM(SPTT_HELP_BIT, SPTT_TIME_INFO) ENDIF ENDIF // Cache current race clock time. IF IS_TIMER_STARTED(Race.tClock) fClockTime = GET_TIMER_IN_SECONDS(Race.tClock) ENDIF SPTT_Race_Manage_Race_Beats(Race.Racer[0].iGateCur, Race.bFailChecking) //IF Race.bFailChecking //CDEBUG3LN(DEBUG_MISSION, " - sptt_race - SPPT_Race_Racer_Update - SET_INPUT_EXCLUSIVE (PLAYER_CONTROL, INPUT_SCRIPT_RUP)") //SET_INPUT_EXCLUSIVE (PLAYER_CONTROL, INPUT_SCRIPT_RUP) // B*2259751 // INPUT_SCRIPT_RUP //ELSE //CDEBUG3LN(DEBUG_MISSION, " - sptt_race - SPPT_Race_Racer_Update - Race.bFailChecking = FALSE") //ENDIF DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_EXIT) // B* 2259751 & 2275136 // Loop through all racers and update them. REPEAT Race.iRacerCnt i // Don't update racers that already finished the race. (or racers that are dead) IF (Race.Racer[i].iGateCur < Race.iGateCnt) SPTT_GATE_STRUCT GateCur, GateNxt INT iGateCur // Check if racer is player and update Scaleform UI, if needed. BOOL bRacerIsPlayer = FALSE IF (Race.Racer[i].Driver = PLAYER_PED_ID()) bRacerIsPlayer = TRUE ENDIF // Cache current index and cur/next gates. iGateCur = Race.Racer[i].iGateCur IF (Race.Racer[i].iGateCur >= Race.iGateCnt) GateCur = Race.sGate[Race.iGateCnt-1] ELSE GateCur = Race.sGate[iGateCur] ENDIF IF (iGateCur < (Race.iGateCnt-1)) GateNxt = Race.sGate[iGateCur + 1] ELSE GateNxt = GateCur ENDIF // Udpate racer clock time (account for plus/minus) (clamp negatives). IF iGateCur <> Race.iGateCnt Race.Racer[i].fClockTime = fClockTime - Race.Racer[i].fPlsMnsTot IF (Race.Racer[i].fClockTime < 0.0) Race.Racer[i].fClockTime = 0.0 ENDIF ENDIF // Make sure racer isn't resetting before continuing. IF NOT SPTT_Race_Racer_Reset(Race, Race.Racer[i], bRacerIsPlayer) // Moved this RESET stuff here so it's only checked when we're not already resetting // Vehicle water check IF bRacerIsPlayer AND Race.bFailChecking AND (INT_TO_ENUM(SPTT_Races_ENUM, SPTT_Master.iRaceCur) != SPTT_BridgeBinge OR Race.Racer[0].iGateCur > 0) /// RACE RESET CHECK IF NOT IS_TIMER_STARTED(resetTimer) START_TIMER_NOW(resetTimer) DEBUG_MESSAGE("Started reset Timer") ENDIF // Manual Reset IF (GET_TIMER_IN_SECONDS(manualResetTimer) >= 6.5) IF NOT IS_CONTROL_PRESSED(FRONTEND_CONTROL, INPUT_SCRIPT_RUP) RESTART_TIMER_NOW(resetTimer) ELIF (GET_TIMER_IN_SECONDS(resetTimer) >= 1.5) Race.bFailChecking = FALSE DEBUG_MESSAGE("Player pressed down, resetting...") CLEAR_BITMASK_AS_ENUM(SPTT_HELP_BIT, SPTT_RESET_HELP) Race.Racer[0].eReset = SPTT_RACER_RESET_FADE_OUT ENDIF ELSE // Player has restarted recently, tell them why they cant restart IF IS_CONTROL_PRESSED(FRONTEND_CONTROL, INPUT_SCRIPT_RUP) DEBUG_MESSAGE("Race clock is currently: ") PRINTFLOAT(GET_TIMER_IN_SECONDS(Race.tClock)) PRINTNL() IF (GET_TIMER_IN_SECONDS(Race.tClock) < 6.5) // do race start message PRINT_HELP_ONCE("SPR_HELP_RST1", SPTT_HELP_BIT, SPTT_RESET_HELP1) DEBUG_MESSAGE("You have restarted recently and must wait to restart: ") PRINTFLOAT(GET_TIMER_IN_SECONDS(manualResetTimer)) PRINTNL() ELSE // Do normal message PRINT_HELP_ONCE("SPR_HELP_RST", SPTT_HELP_BIT, SPTT_RESET_HELP) DEBUG_MESSAGE("You have restarted recently and must wait to restart: ") PRINTFLOAT(GET_TIMER_IN_SECONDS(manualResetTimer)) PRINTNL() ENDIF ENDIF ENDIF ENDIF IF NOT IS_PED_INJURED(Race.Racer[i].Driver) // Calculate racer rank. SPTT_Race_Racer_Rank_Calc(Race, i) ///if we're doing a vehicle fail, that means the race is ending and we should stop updating gates IF SPTT_Master.eRaceType = SPTT_RACE_TYPE_PLANE AND IS_TIMER_STARTED(ExitVehicleTimer) RETURN TRUE ENDIF // Check if racer is player. IF bRacerIsPlayer // If it's time to display plus/minus, start timer. IF (Race.Racer[i].fPlsMnsLst <> 0.0) START_TIMER_NOW(Race.Display.tCnt) ENDIF IF IS_BITMASK_AS_ENUM_SET(iSPRGeneralBits, SPTT_FORCE_GATE_ACTIVATION) SPTT_Race_Gate_Activate(Race, iGateCur, TRUE) IF (iGateCur < (Race.iGateCnt - 1)) SPTT_Race_Gate_Activate(Race, iGateCur + 1, FALSE) ENDIF CLEAR_BITMASK_AS_ENUM(iSPRGeneralBits, SPTT_FORCE_GATE_ACTIVATION) ENDIF ENDIF // Check if racer has passed/missed their current gate. //SPTT_RACE_GATE_STATUS IF Race.bFailChecking Race.iGateCheck = ENUM_TO_INT(SPTT_Racer_Gate_Check(Race, GateCur, GateNxt, Race.Racer[i].Driver)) SPTT_RACE_MANAGE_CHECKPOINT_ALPHAS(GateCur, GateNxt) ENDIF IF (Race.iGateCheck <> ENUM_TO_INT(SPTT_RACE_GATE_STATUS_INVALID)) // Run Stunt Timers here IF (eRaceType = SPTT_RACE_TYPE_PLANE) runGateTimers(Race.Racer[i], bRacerIsPlayer, Race.iGateCheck) ENDIF bMissedStuntGate = SPTT_Stunt_Gate_Missed(INT_TO_ENUM(SPTT_RACE_GATE_STATUS , Race.iGateCheck)) // Increment racer current gate and re-cache it. ++Race.Racer[i].iGateCur iGateCur = Race.Racer[i].iGateCur IF (iGateCur >= Race.iGateCnt-1) GateCur = Race.sGate[Race.iGateCnt-1] ELSE GateCur = Race.sGate[iGateCur] ENDIF // Check if racer is player. IF bRacerIsPlayer // If we're at the last gate, end the race. SPTT_Race_Gate_Deactivate(Race, iGateCur - 1) IF (iGateCur = Race.iGateCnt) INT iRank = 0 IF IS_TIMER_STARTED(Race.tClock) IF NOT IS_TIMER_PAUSED(Race.tClock) PAUSE_TIMER(Race.tClock) ENDIF IF Race.Racer[0].fClockTime > 0 PRINTLN("Race.Racer[0].fClockTime is ", Race.Racer[0].fClockTime, " and SPTT_Master.fTimeGold[SPTT_Master.iRaceCur] is ", SPTT_Master.fTimeGold[SPTT_Master.iRaceCur]) IF Race.Racer[0].fClockTime <= SPTT_Master.fTimeGold[SPTT_Master.iRaceCur] PRINTLN("gold because Race.Racer[0].fClockTime is ", Race.Racer[0].fClockTime, " and SPTT_Master.fTimeGold[SPTT_Master.iRaceCur] is ", SPTT_Master.fTimeGold[SPTT_Master.iRaceCur]) iRank = 1 ELIF Race.Racer[0].fClockTime <= ((SPTT_Master.fTimeBronze[SPTT_Master.iRaceCur]-SPTT_Master.fTimeGold[SPTT_Master.iRaceCur])/2)+SPTT_Master.fTimeGold[SPTT_Master.iRaceCur] PRINTLN("silver because Race.Racer[0].fClockTime is ", Race.Racer[0].fClockTime, " and SPTT_Master.fTimeGold[SPTT_Master.iRaceCur] is ", SPTT_Master.fTimeGold[SPTT_Master.iRaceCur]) iRank = 2 ELIF Race.Racer[0].fClockTime <= SPTT_Master.fTimeBronze[SPTT_Master.iRaceCur] PRINTLN("bronze because Race.Racer[0].fClockTime is ", Race.Racer[0].fClockTime, " and SPTT_Master.fTimeGold[SPTT_Master.iRaceCur] is ", SPTT_Master.fTimeGold[SPTT_Master.iRaceCur]) iRank = 3 ENDIF ENDIF ENDIF IF iRank = 0 CDEBUG1LN( DEBUG_OR_RACES, "rank is 0! Failing!") ENDIF IF iRank > 0 RETURN FALSE ELSE Race.bFailChecking = FALSE Race.Racer[i].iGateCur-- DEBUG_MESSAGE("Idle Failure Race.bFailChecking set to FALSE") CLEAR_PRINTS() spttFailStrapline = "SPR_TIME_FAIL" Race.Racer[0].eReset = SPTT_RACER_RESET_FAIL_OVER ENDIF // Otherwise, activate new current/next gates. ELSE SPTT_Race_Gate_Activate(Race, iGateCur, TRUE) IF (iGateCur < (Race.iGateCnt - 1)) SPTT_Race_Gate_Activate(Race, iGateCur + 1, FALSE) ENDIF ENDIF // If split is still displaying since last gate, cancel it. IF (Race.Racer[i].fPlsMnsLst = 0.0) IF IS_TIMER_STARTED(Race.Display.tCnt) CANCEL_TIMER(Race.Display.tCnt) ENDIF ENDIF // If it's time to display split, calculate it and restart timer. IF Race.iGateCnt > 0 IF (Race.fBestSplitTime > 0.0) IF (iGateCur = ROUND(Race.iGateCnt / 2.0)) Race.Racer[i].fPlsMnsLst = 0.0 RESTART_TIMER_NOW(Race.Display.tCnt) ENDIF ENDIF ENDIF // Otherwise, racer is ai controlled. ELSE IF (Race.Racer[i].iGateCur >= Race.iGateCnt) IF SPTT_Master.eRaceType <> SPTT_RACE_TYPE_TRIATHLON IF NOT IS_ENTITY_DEAD(Race.Racer[i].Driver) FINISH_AI_RACERS(Race.Racer[i]) ENDIF ENDIF ELSE IF SPTT_Master.eRaceType <> SPTT_RACE_TYPE_OFFROAD // TODO: Put any player specific logic here... IF i != 0 //not the player!? SPTT_Race_Racer_Task_Go_To_Next_Gate(Race, Race.Racer[i].Driver, Race.Racer[i].Vehicle, Race.sGate[Race.Racer[i].iGateCur].vPos, Race.sGate[Race.Racer[i].iGateCur].eChkpntType, i) ENDIF ELSE TEXT_LABEL OffroadRecording = "Offroad_" OffroadRecording += (SPTT_Master.iRaceCur+1) IF i = 1 OffroadRecording += "a" ENDIF // Task AI to follow waypoint recording for offroad race // Pick random waypoint recording to start IF i > 0 IF SPTT_USE_WAYPOINT_RECORDING IF NOT IS_ENTITY_DEAD(Race.Racer[i].Driver) AND NOT IS_ENTITY_DEAD(Race.Racer[i].Vehicle) IF (GET_SCRIPT_TASK_STATUS(Race.Racer[i].Driver, SCRIPT_TASK_VEHICLE_FOLLOW_WAYPOINT_RECORDING) = PERFORMING_TASK) DEBUG_MESSAGE("AI on waypoint recording") ELSE TASK_VEHICLE_FOLLOW_WAYPOINT_RECORDING(Race.Racer[i].Driver, Race.Racer[i].Vehicle, OffroadRecording, DRIVINGMODE_PLOUGHTHROUGH, 0, EWAYPOINT_START_FROM_CLOSEST_POINT, -1, GET_VEHICLE_ESTIMATED_MAX_SPEED(Race.Racer[i].Vehicle)) ENDIF ENDIF ELSE IF i != 0 //not the player!? SPTT_Race_Racer_Task_Go_To_Next_Gate(Race, Race.Racer[i].Driver, Race.Racer[i].Vehicle, Race.sGate[Race.Racer[i].iGateCur].vPos, Race.sGate[Race.Racer[i].iGateCur].eChkpntType, i) ENDIF ENDIF ENDIF ENDIF // Triathlon has its own rubber-banding system, so avoid updating this in Tri. IF SPTT_Master.eRaceType <> SPTT_RACE_TYPE_TRIATHLON SPTT_Race_Racer_Update_Rubberband_Speed(Race, i) ENDIF ENDIF ENDIF ENDIF // Run rewards here IF (eRaceType = SPTT_RACE_TYPE_PLANE) IF bRacerIsPlayer rewardPlayer() ENDIF ENDIF ENDIF ENDIF ENDIF ENDREPEAT IF Race.bFailChecking = TRUE // PRINTLN("ACTIVELY CHECKING FAIL CASES") RESET_TUTORIAL(Race) EXIT_VEHICLE_FAILURE(Race, returnToVehBlip) Dead_Race_Vehicle(Race, returnToVehBlip) wantedFailure() //waterFailure(Race) idleFailure(Race) Disable_Airport_Icons() RUN_OFFROAD_AUDIO(Race) IF Race.Racer[0].eReset != SPTT_RACER_RESET_FAIL_OVER //make sure we dont draw on the same frame we fail. IF INT_TO_ENUM(SPTT_Races_ENUM, SPTT_Master.iRaceCur) = SPTT_BridgeBinge //if we're on bridge binge, done draw until after ze first gate IF Race.Racer[0].iGateCur > 0 SPTT_Race_Draw_HUD(Race) ENDIF ELSE SPTT_Race_Draw_HUD(Race) ENDIF ENDIF ELSE // PRINTLN("NOT ACTIVELY CHECKING FAIL CASES ------") ENDIF // Update SPR Race Racers still running. RETURN TRUE ENDFUNC // ----------------------------------- // FILE I/O PROCS/FUNCTIONS // ----------------------------------- /// PURPOSE: /// Init SPR Race. PROC SPTT_Race_Init(SPTT_RACE_STRUCT& Race) //DEBUG_MESSAGE("SPTT_Race_Init") CANCEL_TIMER(Race.tClock) // TEMP: Pulling in best clock/split times from master. // TODO: Might want to put this into it's own function. IF (SPTT_Master.iRaceCur <> -1) FLOAT fBestClockTime = SPTT_Global_BestTime_Get(SPTT_Master.iRaceCur) IF (fBestClockTime <= 0.0) OR (fBestClockTime > SPTT_Master.fRaceTime[SPTT_Master.iRaceCur]) fBestClockTime = SPTT_Master.fRaceTime[SPTT_Master.iRaceCur] ENDIF Race.fBestClockTime = fBestClockTime Race.fBestSplitTime = Race.fBestClockTime / 2.0 ENDIF SPTT_Race_Gate_Init_All(Race) Race.iGateCnt = 0 SPTT_Race_Racer_Init_All(Race) Race.iRacerCnt = 0 // TODO: Should I be resetting state machine data here? ENDPROC #IF IS_DEBUG_BUILD /// PURPOSE: /// Load SPR Race. /// RETURNS: /// TRUE if SPR Race was successfully loaded. FUNC BOOL SPTT_Race_Load(SPTT_RACE_STRUCT& Race, STRING sRaceFileName) DEBUG_MESSAGE("SPTT_Race_Load") sRaceFileName = sRaceFileName UNUSED_PARAMETER(Race) RETURN TRUE ENDFUNC /// PURPOSE: /// Save SPR Race. /// RETURNS: /// TRUE if SPR Race was successfully saved. FUNC BOOL SPTT_Race_Save(SPTT_RACE_STRUCT& Race, STRING sRaceFileName) DEBUG_MESSAGE("SPTT_Race_Save") UNUSED_PARAMETER(Race) sRaceFileName = sRaceFileName RETURN TRUE ENDFUNC /// PURPOSE: /// Export SPR Race. /// RETURNS: /// TRUE if SPR Race was successfully exported. FUNC BOOL SPTT_Race_Export(SPTT_RACE_STRUCT& Race, STRING sRaceFileName) DEBUG_MESSAGE("SPTT_Race_Export") UNUSED_PARAMETER(Race) sRaceFileName = sRaceFileName // Race successfully exported. RETURN TRUE ENDFUNC /// PURPOSE: /// Create SPR Race. /// RETURNS: /// TRUE if SPR Race was successfully created. FUNC BOOL SPTT_Race_Create(SPTT_RACE_STRUCT& Race, STRING sRaceFileName) //DEBUG_MESSAGE("SPTT_Race_Create") SPTT_Race_Init(Race) IF SPTT_Race_Save(Race, sRaceFileName) RETURN SPTT_Race_Export(Race, sRaceFileName) ENDIF RETURN FALSE ENDFUNC #ENDIF // ----------------------------------- // MAIN PROCS/FUNCTIONS // ----------------------------------- /// PURPOSE: /// Setup SPR Race. /// RETURNS: /// TRUE if still setting up SPR Race. FUNC BOOL SPTT_Race_Setup(SPTT_RACE_STRUCT& Race) //DEBUG_MESSAGE("SPTT_Race_Setup") // Setup SPR Race State Machine. SWITCH (Race.eSetup) // Setup (init). CASE SPTT_RACE_SETUP_INIT DEBUG_MESSAGE("SPTT_RACE_SETUP - INIT") // Disable cellphone. DISABLE_CELLPHONE(TRUE) REQUEST_STREAMED_TEXTURE_DICT("MPHUD") SPTT_Master.uiLeaderboard = REQUEST_SC_LEADERBOARD_UI() // Request the appropriate race textures. SWITCH (SPTT_Master.eRaceType) CASE SPTT_RACE_TYPE_PLANE REQUEST_STREAMED_TEXTURE_DICT("SPRRaces") REQUEST_STREAMED_TEXTURE_DICT("MPMedals_FEED") BREAK CASE SPTT_RACE_TYPE_OFFROAD REQUEST_STREAMED_TEXTURE_DICT("SPROffroad") BREAK CASE SPTT_RACE_TYPE_TRIATHLON REQUEST_STREAMED_TEXTURE_DICT("Triathlon") REQUEST_STREAMED_TEXTURE_DICT("MPMedals_FEED") BREAK ENDSWITCH DEBUG_MESSAGE("SPTT_RACE_SETUP - LOAD_INIT") Race.eSetup = SPTT_RACE_SETUP_LOAD_INIT BREAK // Setup Load (init). CASE SPTT_RACE_SETUP_LOAD_INIT SPTT_Race_Racer_Request_All(Race) // Request Countdown UI scaleform movie. // SPTT_COUNTDOWN_UI = REQUEST_SCALEFORM_MOVIE("COUNTDOWN") DEBUG_MESSAGE("SPTT_RACE_SETUP - LOAD_WAIT") Race.eSetup = SPTT_RACE_SETUP_LOAD_WAIT BREAK // Setup Load (wait). CASE SPTT_RACE_SETUP_LOAD_WAIT IF SPTT_Race_Racer_Stream_All(Race) IF HAS_STREAMED_TEXTURE_DICT_LOADED("MPHUD") IF HAS_SCALEFORM_MOVIE_LOADED(SPTT_Master.uiLeaderboard) // IF HAS_MINIGAME_COUNTDOWN_UI_LOADED(SPTT_CountDownUI) // Check the appropriate race textures have loaded. SWITCH (SPTT_Master.eRaceType) CASE SPTT_RACE_TYPE_PLANE IF HAS_STREAMED_TEXTURE_DICT_LOADED("SPRRaces") AND HAS_STREAMED_TEXTURE_DICT_LOADED("MPMedals_FEED") DEBUG_MESSAGE("SPTT_RACE_SETUP - CREATE_INIT") Race.eSetup = SPTT_RACE_SETUP_CREATE_INIT ENDIF BREAK CASE SPTT_RACE_TYPE_OFFROAD IF HAS_STREAMED_TEXTURE_DICT_LOADED("SPROffroad") DEBUG_MESSAGE("SPTT_RACE_SETUP - CREATE_INIT") Race.eSetup = SPTT_RACE_SETUP_CREATE_INIT ENDIF BREAK CASE SPTT_RACE_TYPE_TRIATHLON IF HAS_STREAMED_TEXTURE_DICT_LOADED("Triathlon") AND HAS_STREAMED_TEXTURE_DICT_LOADED("MPMedals_FEED") DEBUG_MESSAGE("SPTT_RACE_SETUP - CREATE_INIT") Race.eSetup = SPTT_RACE_SETUP_CREATE_INIT ENDIF BREAK ENDSWITCH // ENDIF ENDIF ENDIF ENDIF BREAK // Setup Create (init). CASE SPTT_RACE_SETUP_CREATE_INIT //clear this so we dont set off fail checks immediately CLEAR_PLAYER_HAS_DAMAGED_AT_LEAST_ONE_PED(PLAYER_ID()) IF INT_TO_ENUM(SPTT_Races_ENUM, SPTT_Master.iRaceCur) = SPTT_BridgeBinge AND NOT Race.bDidWeRestart //do nothing ELSE SPTT_Race_Racer_Create_All(Race) ENDIF DEBUG_MESSAGE("SPTT_RACE_SETUP - CREATE_WAIT") Race.eSetup = SPTT_RACE_SETUP_CREATE_WAIT BREAK // Setup Create (wait). CASE SPTT_RACE_SETUP_CREATE_WAIT //if we're on the first race and we're not restarting //set plane to taxi //otherwise autopilot IF INT_TO_ENUM(SPTT_Races_ENUM, SPTT_Master.iRaceCur) = SPTT_BridgeBinge// AND NOT Race.bDidWeRestart RETURN FALSE ELSE // Auto-pilot race racers. IF DOES_ENTITY_EXIST(Race.Racer[0].Vehicle) FREEZE_ENTITY_POSITION(Race.Racer[0].Vehicle, TRUE) ENDIF IF NOT IS_NEW_LOAD_SCENE_ACTIVE() REQUEST_COLLISION_AT_COORD(Race.Racer[0].vStartPos) // Load the scene at the player's race start position. NEW_LOAD_SCENE_START(Race.Racer[0].vStartPos, GET_ENTITY_FORWARD_VECTOR(Race.Racer[0].Vehicle), 5000.0) PRINTLN("[SPTT_Race_Setup] SPTT_RACE_SETUP_CREATE_WAIT: New load scene started at player's position.") #IF IS_DEBUG_BUILD PRINTLN(GET_THIS_SCRIPT_NAME(), ": Calling NEW_LOAD_SCENE_START().") #ENDIF ENDIF IF IS_NEW_LOAD_SCENE_LOADED() #IF IS_DEBUG_BUILD PRINTLN(GET_THIS_SCRIPT_NAME(), ": Calling NEW_LOAD_SCENE_STOP() due to IS_NEW_LOAD_SCENE_LOADED() returning TRUE.") #ENDIF NEW_LOAD_SCENE_STOP() IF DOES_ENTITY_EXIST(Race.Racer[0].Vehicle) FREEZE_ENTITY_POSITION(Race.Racer[0].Vehicle, FALSE) ENDIF SPTT_Race_Racer_AutoPilot(Race) RETURN FALSE ENDIF ENDIF BREAK // Setup (wait). CASE SPTT_RACE_SETUP_WAIT RETURN FALSE BREAK // Setup (cleanup). CASE SPTT_RACE_SETUP_CLEANUP RETURN FALSE BREAK ENDSWITCH // Setup SPR Race still running. RETURN TRUE ENDFUNC FUNC BOOL UPDATE_TAXI_INTRO(SPTT_RACE_STRUCT& Race) SPTT_RACE_GATE_STATUS thisGateStatus thisGateStatus = SPTT_Racer_Gate_Check(Race, Race.sGate[0], Race.sGate[1], Race.Racer[0].Driver) IF thisGateStatus = SPTT_RACE_GATE_STATUS_INVALID OR thisGateStatus = SPTT_RACE_GATE_STATUS_INCOMPLETE RETURN FALSE ENDIF RETURN TRUE ENDFUNC /// PURPOSE: /// Update SPR Race. /// RETURNS: /// TRUE if still updating SPR Race. FUNC BOOL SPTT_Race_Update(SPTT_RACE_STRUCT& Race) //DEBUG_MESSAGE("SPTT_Race_Update") //VECTOR vCurCamRotation // Update SPR Race State Machine. #IF IS_DEBUG_BUILD IF IS_DEBUG_KEY_JUST_PRESSED(KEY_1, KEYBOARD_MODIFIER_NONE, "") SPTT_Race_Racer_Gate_Jump_Penultimate(Race, 0, TRUE) ELIF IS_DEBUG_KEY_JUST_PRESSED(KEY_E, KEYBOARD_MODIFIER_SHIFT, "") bEndTracking = !bEndTracking ELIF IS_DEBUG_KEY_JUST_PRESSED(KEY_E, KEYBOARD_MODIFIER_CTRL, "") bEndShake = !bEndShake ENDIF #ENDIF SWITCH (Race.eUpdate) // Update (init). CASE SPTT_RACE_UPDATE_INIT DEBUG_MESSAGE("SPTT_RACE_UPDATE - INIT") CLEAR_BITMASK_AS_ENUM(iSPRGeneralBits, SPTT_PLAYED_STINGER) HIDE_HUD_COMPONENT_THIS_FRAME(NEW_HUD_WEAPON_ICON) stop_vehicle_recordings(Race) Race.bigMessageUI.siMovie = REQUEST_MG_BIG_MESSAGE() // Auto-pilot race racers. IF INT_TO_ENUM(SPTT_Races_ENUM, SPTT_Master.iRaceCur) = SPTT_BridgeBinge// AND NOT Race.bDidWeRestart IF NOT IS_BITMASK_AS_ENUM_SET(iSPRGeneralBits, SPTT_FIRST_GATE_ACTIVATION) // Activate first/second race gates. SPTT_Race_Gate_Activate(Race, 0, TRUE) SPTT_Race_Gate_Activate(Race, 1, FALSE) SET_BITMASK_AS_ENUM(iSPRGeneralBits, SPTT_FIRST_GATE_ACTIVATION) ENDIF ELSE SPTT_Race_Racer_AutoPilot(Race) IF NOT IS_BITMASK_AS_ENUM_SET(iSPRGeneralBits, SPTT_FIRST_GATE_ACTIVATION) // Activate first/second race gates. SPTT_Race_Gate_Activate(Race, 0, TRUE) SPTT_Race_Gate_Activate(Race, 1, FALSE) SET_BITMASK_AS_ENUM(iSPRGeneralBits, SPTT_FIRST_GATE_ACTIVATION) ENDIF ENDIF // Setup countdown display. CANCEL_TIMER(Race.Display.tCnt) eCountdownStage = SPTT_COUNTDOWN_STAGE_INIT DEBUG_MESSAGE("SPTT_RACE_UPDATE - COUNTDOWN") SET_PLAYER_CONTROL(PLAYER_ID(), FALSE) PRINTLN("setting player control false") Race.eUpdate = SPTT_RACE_UPDATE_COUNTDOWN BREAK // Update Countdown. CASE SPTT_RACE_UPDATE_COUNTDOWN HIDE_HUD_COMPONENT_THIS_FRAME(NEW_HUD_WEAPON_ICON) // Auto-pilot race racers. IF INT_TO_ENUM(SPTT_Races_ENUM, SPTT_Master.iRaceCur) = SPTT_BridgeBinge// AND NOT Race.bDidWeRestart // clear one shot first checkpoints drawn bits PRINTLN("SPTT_RACE_UPDATE_COUNTDOWN - skipping countdown since we're taxi-ing out.") IF IS_BITMASK_AS_ENUM_SET(iSPRGeneralBits, SPTT_FIRST_GATE_ACTIVATION) CLEAR_BITMASK_AS_ENUM(iSPRGeneralBits, SPTT_FIRST_GATE_ACTIVATION) ENDIF SPTT_Race_Racer_Start(Race) DEBUG_MESSAGE("SPTT_RACE_UPDATE - WAIT") Race.eUpdate = SPTT_RACE_UPDATE_WAIT ELSE SPTT_Race_Racer_AutoPilot(Race) // Display countdown until done, then start race. IF NOT SPTT_Countdown_Display(Race.Display) // failsafe backup to switch to cutscene cam IF NOT IS_INTERPOLATING_FROM_SCRIPT_CAMS() RENDER_SCRIPT_CAMS(FALSE, TRUE) ENDIF // clear one shot first checkpoints drawn bits IF IS_BITMASK_AS_ENUM_SET(iSPRGeneralBits, SPTT_FIRST_GATE_ACTIVATION) CLEAR_BITMASK_AS_ENUM(iSPRGeneralBits, SPTT_FIRST_GATE_ACTIVATION) ENDIF // Start race racers. DISPLAY_HUD(TRUE) SPTT_Race_Racer_Start(Race) IF SPTT_Master.iRaceCur = ENUM_TO_INT(SPTT_BridgeBinge) AND ((g_savedGlobals.sSPTTData.fBestTime[SPTT_BridgeBinge] > SPTT_Master.fTimeBronze[SPTT_BridgeBinge]) OR (g_savedGlobals.sSPTTData.fBestTime[SPTT_BridgeBinge] = 0)) PRINT_HELP("SPR_HELP_GATE", 10000) ENDIF DEBUG_MESSAGE("SPTT_RACE_UPDATE - WAIT") Race.eUpdate = SPTT_RACE_UPDATE_WAIT ENDIF ENDIF BREAK // Update Finish. CASE SPTT_RACE_UPDATE_FINISH // In the case of Triathlon, immediately show the celebrating/tired triatheles. // show player controls after 1 second IF NOT IS_BITMASK_AS_ENUM_SET(iSPRGeneralBits, SPTT_SCORECARD_INIT) SETTIMERA(0) SPTT_Race_Leaderboard_Init_Scorecard(Race) INIT_SIMPLE_USE_CONTEXT(SPTT_Master.uiInput, FALSE, FALSE, TRUE, TRUE) ADD_SIMPLE_USE_CONTEXT_INPUT(SPTT_Master.uiInput, "SPR_CONT2", FRONTEND_CONTROL, INPUT_FRONTEND_ACCEPT) SET_SIMPLE_USE_CONTEXT_MINIGAME_ATTACHED(SPTT_Master.uiInput) SET_BITMASK_AS_ENUM(iSPRGeneralBits, SPTT_SCORECARD_INIT) ENDIF // manage pre-results camera pan IF IS_HELP_MESSAGE_BEING_DISPLAYED() CLEAR_HELP(TRUE) ENDIF IF IS_THIS_PRINT_BEING_DISPLAYED("SPR_RETR_FAIL") CLEAR_PRINTS() ENDIF IF IS_HELP_MESSAGE_BEING_DISPLAYED() CLEAR_HELP(TRUE) ENDIF IF IS_THIS_PRINT_BEING_DISPLAYED("SPR_RETR_FAIL") CLEAR_PRINTS() ENDIF DEBUG_MESSAGE("SPTT_RACE_UPDATE - LEADERBOARD") SETTIMERA(0) SPTT_KILL_HINT_CAM() SPTT_SET_HINT_CAM_ACTIVE(FALSE) SPECIAL_ABILITY_DEACTIVATE(PLAYER_ID()) ENABLE_SPECIAL_ABILITY(PLAYER_ID(), FALSE) DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_EXIT) SET_MINIGAME_SPLASH_SHOWING(TRUE) Race.eUpdate = SPTT_RACE_UPDATE_LEADERBOARD BREAK // Update Leaderboard. CASE SPTT_RACE_UPDATE_LEADERBOARD DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_EXIT) // Auto-circle race racers. REPLAY_PREVENT_RECORDING_AND_UI_THIS_FRAME() // freeze plane location, and transition camera off plane while scorecard is up IF NOT IS_ENTITY_DEAD(Race.Racer[0].Vehicle) IF NOT IS_ENTITY_ON_SCREEN(Race.Racer[0].Vehicle) AND DOES_CAM_EXIST(iSPRStuntFinishCam1) GET_CAM_ROT(iSPRStuntFinishCam1) //SET_ENTITY_COORDS(Race.Racer[0].Vehicle, GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(GET_CAM_COORD(iSPRStuntFinishCam1), vCurCamRotation.z, <<-10, 0, 10>>)) SET_ENTITY_VISIBLE(Race.Racer[0].Vehicle, FALSE) FREEZE_ENTITY_POSITION(Race.Racer[0].Vehicle, TRUE) SPTT_RACE_CLEANUP_FINISH_STREAMVOL() ENDIF ENDIF #IF COMPILE_WIDGET_OUTPUT EXPORT_SCREEN_MEGA_PLACEMENT(Race.uiScorecard) #ENDIF // Wait for player to exit leaderboard. IF NOT SPTT_UPDATING_END_SCREEN(Race, bEndTracking, bEndShake) SPTT_RACE_CLEANUP_FINISH_STREAMVOL() // SET_MINIGAME_SPLASH_SHOWING(FALSE) SET_RESULT_SCREEN_DISPLAYING_STATE(FALSE) CLEAR_HELP() IF IS_BITMASK_AS_ENUM_SET(iSPRGeneralBits, SPTT_SCORECARD_INIT) CLEAR_BITMASK_AS_ENUM(iSPRGeneralBits, SPTT_SCORECARD_INIT) ENDIF DEBUG_MESSAGE("SPTT_RACE_UPDATE - CLEANUP") SET_AUTOSAVE_IGNORES_ON_MISSION_FLAG(FALSE) IF NOT IS_PED_INJURED(PLAYER_PED_ID()) CLEAR_PED_TASKS(PLAYER_PED_ID()) ENDIF SET_GAMEPLAY_CAM_RELATIVE_PITCH() SET_GAMEPLAY_CAM_RELATIVE_HEADING() STOP_SCRIPTED_CONVERSATION(FALSE) iButtonSounds = GET_SOUND_ID() //ODDJOB_PLAY_SOUND("Phone_Generic_Key_02", iButtonSounds, FALSE) PLAY_SOUND_FRONTEND(iButtonSounds, "Phone_Generic_Key_02", "HUD_MINIGAME_SOUNDSET") CANCEL_TIMER(exitTimer) Race.eUpdate = SPTT_RACE_UPDATE_FADE_OUT_BEFORE_FINISH //ELSE // DEBUG_MESSAGE("Waiting for tracker thread to die") ENDIF BREAK // Fade out right before cleaning and killing the script. CASE SPTT_RACE_UPDATE_FADE_OUT_BEFORE_FINISH IF NOT IS_ENTITY_DEAD(Race.Racer[0].Vehicle) // AsD TODO: SET_ENTITY_COORDS(Race.Racer[0].Vehicle, SPTT_MENU_PLAYER_COORDS) SET_ENTITY_ROTATION(Race.Racer[0].Vehicle, SPTT_MENU_PLAYER_ROTATION) SET_ENTITY_VISIBLE(Race.Racer[0].Vehicle, TRUE) DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_EXIT) SET_VEHICLE_ON_GROUND_PROPERLY(Race.Racer[0].Vehicle) SET_ENTITY_INVINCIBLE(Race.Racer[0].Vehicle, FALSE) ENDIF // AsD TODO: //LOAD_SCENE(SPTT_MENU_PLAYER_COORDS) bTriggerFirstMusicEvent = FALSE Race.eUpdate = SPTT_RACE_UPDATE_FADE_IN_BEFORE_FINISH Race.Racer[0].eReset = SPTT_RACER_QUIT_FADE_OUT BREAK // Fade in after cleaning and killing the script. Currently only used in Tri. CASE SPTT_RACE_UPDATE_FADE_IN_BEFORE_FINISH Race.eUpdate = SPTT_RACE_UPDATE_CLEANUP BREAK // Update (wait). CASE SPTT_RACE_UPDATE_WAIT // need to draw it for a bit longer after the GO! first appears // think about adding a proper timer so we don't call this every frame afterwards DRAW_SCALEFORM_MOVIE(SPTT_CountDownUI.uiCountdown, 0.5, 0.5, 1.0, 1.0, 255, 255, 255, 100) IF NOT IS_BITMASK_AS_ENUM_SET(iSPRGeneralBits, SPTT_FIRST_GATE_ACTIVATION) // Activate first/second race gates. SPTT_Race_Gate_Activate(Race, 0, TRUE) SPTT_Race_Gate_Activate(Race, 1, FALSE) SET_BITMASK_AS_ENUM(iSPRGeneralBits, SPTT_FIRST_GATE_ACTIVATION) SPTT_SET_HINT_CAM_ACTIVE(TRUE) SPTT_SET_HINT_CAM_COORD(Race.sGate[Race.Racer[0].iGateCur].vPos) ENDIF IF Race.bFailChecking //if we're checking it means we havent failed yet SPTT_UPDATE_HINT_CAM(Race) SPTT_RACE_CREATE_FINISH_STREAMVOL(Race) ELSE KILL_RACE_HINT_CAM(localChaseHintCamStruct) SPTT_RACE_CLEANUP_FINISH_STREAMVOL() SET_CINEMATIC_BUTTON_ACTIVE(FALSE) ENDIF // Update race racers and auto-restart race. IF NOT SPTT_Race_Racer_Update(Race, SPTT_Master.eRaceType) TRIGGER_MUSIC_EVENT("MGSP_END") PRINTLN("TRIGGERING MUSIC EVENT - MGSP_END") // Finish race racers. SPTT_Race_Racer_Finish(Race) // Setup finish display. CANCEL_TIMER(Race.Display.tCnt) DEBUG_MESSAGE("SPTT_RACE_UPDATE - FINISH") Race.eUpdate = SPTT_RACE_UPDATE_FINISH CANCEL_TIMER(Race.tUpdate) ENDIF BREAK // Update (cleanup). CASE SPTT_RACE_UPDATE_CLEANUP DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_VEH_EXIT) CLEANUP_MG_BIG_MESSAGE(Race.bigMessageUI) SPTT_RACE_CLEANUP_FINISH_STREAMVOL() PRINTLN("SPTT_RACE_UPDATE_CLEANUP") SPTT_Race_Cleanup_Stunt_Beats() // SET_PLAYER_INVINCIBLE(PLAYER_ID(), FALSE) RETURN FALSE BREAK ENDSWITCH // Update SPR Race still running. RETURN TRUE ENDFUNC /// PURPOSE: /// Cleanup SPR Race. PROC SPTT_Race_Cleanup(SPTT_RACE_STRUCT& Race, BOOL bDefault) //DEBUG_MESSAGE("SPTT_Race_Cleanup") IF bDefault DEBUG_MESSAGE("SPTT_RACE_CLEANUP: Default bool hit, doing race init") // Init race data. SPTT_Race_Init(Race) ELSE DEBUG_MESSAGE("SPTT_RACE_CLEANUP: False bool hit, releasing offroad AI") // Release AI RELEASE_AI_RACERS(Race) ENDIF // Enable cellphone. DISABLE_CELLPHONE(FALSE) CLEANUP_MG_BIG_MESSAGE(Race.bigMessageUI) CLEAR_HELP() CLEAR_PRINTS() IF bDebugFailure DEBUG_MESSAGE("SPTT_Main_Debug: Debug Fail: before message") PRINT_NOW("SPR_MOVE_FAIL", 5000, 0) DEBUG_MESSAGE("SPTT_Main_Debug: Debug Fail: after message") bDebugFailure = FALSE ENDIF // Cleanup countdown scaleform UI. //SET_SCALEFORM_MOVIE_AS_NO_LONGER_NEEDED(SPTT_COUNTDOWN_UI) //SET_STREAMED_TEXTURE_DICT_AS_NO_LONGER_NEEDED("MPHUD") //SET_STREAMED_TEXTURE_DICT_AS_NO_LONGER_NEEDED("SRange") //SET_STREAMED_TEXTURE_DICT_AS_NO_LONGER_NEEDED("SPROffroad") //SET_STREAMED_TEXTURE_DICT_AS_NO_LONGER_NEEDED("SPRRaces") // TODO: Probably need more stuff in here... ENDPROC // END OF FILE! DO NOT ADD ANYTHING BELOW THIS LINE!