//╒═════════════════════════════════════════════════════════════════════════════╕ //│ Author: Adam Westwood Date: 12/07/14 │ //╞═════════════════════════════════════════════════════════════════════════════╡ //│ │ //│ Drill Minigame │ //│ │ //│ Controls the drill minigame │ //| │ //│ │ //╘═════════════════════════════════════════════════════════════════════════════╛ USING "timer_public.sch" USING "rage_builtins.sch" USING "globals.sch" USING "commands_audio.sch" USING "commands_camera.sch" USING "commands_clock.sch" USING "commands_debug.sch" USING "commands_fire.sch" USING "commands_graphics.sch" USING "commands_hud.sch" USING "commands_misc.sch" USING "commands_object.sch" USING "commands_pad.sch" USING "commands_ped.sch" USING "commands_player.sch" USING "commands_script.sch" USING "commands_streaming.sch" USING "commands_task.sch" USING "commands_vehicle.sch" USING "commands_interiors.sch" USING "net_include.sch" USING "model_enums.sch" USING "script_player.sch" USING "script_misc.sch" USING "selector_public.sch" USING "timer_public.sch" USING "LineActivation.sch" #IF IS_DEBUG_BUILD USING "shared_debug.sch" USING "script_debug.sch" #ENDIF CONST_INT DRILL_MINIGAME_STATE_INITIALISE 0 CONST_INT DRILL_MINIGAME_STATE_DRILLING 1 CONST_INT DRILL_MINIGAME_STATE_CLEANUP 2 CONST_INT DRILL_BITSET_IS_IN_SWEET_SPOT 0 CONST_INT DRILL_BITSET_IS_MINIGAME_COMPLETE 1 CONST_INT DRILL_BITSET_DID_PLAYER_MESS_UP 2 CONST_INT DRILL_BITSET_DID_PLAYER_MESS_UP_ON_LEFT_SIDE 4 CONST_INT DRILL_BITSET_DID_PLAYER_BACK_OUT 5 CONST_INT DRILL_BITSET_SKIP_WALK_TO_POSITION 6 CONST_INT DRILL_BITSET_HAS_BROADCAST_ASSET_REQUEST 7 CONST_FLOAT DRILL_MAX_SWEET_SPOT_SIZE 0.25 //0.2 - Rob - 2167673 - make drilling game twice as long (compensate a little for decreased speed) CONST_FLOAT DRILL_MIN_SWEET_SPOT_SIZE 0.15 CONST_FLOAT DRILL_MAX_PROGRESS_SPEED 0.025 //0.07 - Rob - 2167673 - make drilling game twice as long CONST_FLOAT DRILL_MIN_PROGRESS_SPEED 0.0 CONST_FLOAT DRILL_COOLDOWN_SPEED 0.08 CONST_FLOAT DRILL_OVERHEAT_SPEED 0.35 //0.4 - Rob - 2167673 - make drilling game twice as long (compensate a little for decreased speed) CONST_FLOAT DRILL_LEAN_INTERP_SPEED 0.2 CONST_FLOAT DRILL_POS_SCALE_MODIFIER 0.82 CONST_FLOAT DRILL_PASS_POINT 0.775 CONST_FLOAT DRILL_START_POINT 0.08 CONST_FLOAT DRILL_PIN_BREAK_POWER_MODIFER_MAX 0.5 CONST_FLOAT DRILL_PIN_BREAK_POWER_MODIFIER_DECEL 0.4 STRUCT S_DRILL_DATA INT iBitset INT iHUDFlashTimer INT iCurrentState INT iDrillSoundID = -1 INT iSyncScene INT iPassTimer INT iAudioEvent //INT iMoveNetworkSignalState FLOAT fCurrentDrillPosY FLOAT fCurrentDrillBasePosX FLOAT fCurrentDrillPower FLOAT fPinBreakPowerModifier FLOAT fCurrentProgress FLOAT fCurrentSweetSpotHeight FLOAT fCurrentSweetSpotMin FLOAT fCurrentSweetSpotMax FLOAT fCurrentHeatLevel FLOAT fCurrentProgressIncreaseSpeed FLOAT fCurrentLeanPos FLOAT fCurrentForwardLeanPos FLOAT fForwardLeanExtraAmountForPins FLOAT fCurrentDrillAnimPower FLOAT fCurrentDrillBitPos FLOAT fDrillBitShakeOffset FLOAT fDesiredDrillBitShakeOffset FLOAT fCurrentCamShake FLOAT fCamRotOffset FLOAT fDesiredCamRotOffset FLOAT fCamHeightOffset FLOAT fDesiredCamHeightOffset FLOAT fDrillBitAnimSpeed FLOAT fHudPosX = 0.82 FLOAT fHudPosY = 0.83 CAMERA_INDEX cam SCALEFORM_INDEX sfDrillHud VECTOR vCamPointPos VECTOR vCamStartPos #IF IS_DEBUG_BUILD BOOL bDisplayDebug INT iDebugNumPrintsThisFrame #ENDIF ENDSTRUCT // PC CONTROL FOR DRILLING MINIGAME BOOL bPCCOntrolsSetup = FALSE PROC SETUP_PC_DRILLING_CONTROLS() IF IS_PC_VERSION() IF bPCCOntrolsSetup = FALSE CDEBUG1LN(DEBUG_MISSION, "[RUN_DRILL_MINIGAME]- Setup PC controls" ) INIT_PC_SCRIPTED_CONTROLS("MP DRILL MINIGAME") bPCCOntrolsSetup = TRUE ENDIF ENDIF ENDPROC PROC CLEANUP_PC_DRILLING_CONTROLS() IF IS_PC_VERSION() IF bPCCOntrolsSetup = TRUE CDEBUG1LN(DEBUG_MISSION, "[RUN_DRILL_MINIGAME]- Cleanup PC controls" ) SHUTDOWN_PC_SCRIPTED_CONTROLS() bPCCOntrolsSetup = FALSE ENDIF ENDIF ENDPROC /// REQUEST_DRILL_MINIGAME_ASSETS() /// NOTES: /// PURPOSE: /// checking assets are loaded /// PARAMS: /// RETURNS: PROC REQUEST_DRILL_MINIGAME_ASSETS(S_DRILL_DATA &sDrillData) REQUEST_ANIM_DICT("anim@heists@fleeca_bank@drilling") REQUEST_MODEL(HEI_PROP_HEIST_DEPOSIT_BOX) REQUEST_MODEL(hei_prop_heist_drill) REQUEST_MODEL(HEI_P_M_BAG_VAR22_ARM_S) REQUEST_MODEL(HEI_PROP_HEI_DRILL_HOLE) REQUEST_SCRIPT_AUDIO_BANK("DLC_MPHEIST\\HEIST_FLEECA_DRILL") REQUEST_SCRIPT_AUDIO_BANK("DLC_MPHEIST\\HEIST_FLEECA_DRILL_2") REQUEST_NAMED_PTFX_ASSET("fm_mission_controler") IF sDrillData.sfDrillHud = NULL sDrillData.sfDrillHud = REQUEST_SCALEFORM_MOVIE("DRILLING") ENDIF ENDPROC /// HAVE_DRILL_ASSETS_LOADED() /// NOTES: /// PURPOSE: /// checking assets are loaded /// PARAMS: /// RETURNS: FUNC BOOL HAVE_DRILL_ASSETS_LOADED(S_DRILL_DATA &sDrillData) REQUEST_ANIM_DICT("anim@heists@fleeca_bank@drilling") REQUEST_MODEL(HEI_PROP_HEIST_DEPOSIT_BOX) REQUEST_MODEL(hei_prop_heist_drill) REQUEST_MODEL(HEI_P_M_BAG_VAR22_ARM_S) IF HAS_ANIM_DICT_LOADED("anim@heists@fleeca_bank@drilling") AND HAS_MODEL_LOADED(HEI_PROP_HEIST_DEPOSIT_BOX) AND HAS_MODEL_LOADED(hei_prop_heist_drill) AND HAS_MODEL_LOADED(HEI_P_M_BAG_VAR22_ARM_S) AND HAS_MODEL_LOADED(HEI_PROP_HEI_DRILL_HOLE) AND HAS_NAMED_PTFX_ASSET_LOADED("fm_mission_controler") AND HAS_SCALEFORM_MOVIE_LOADED(sDrillData.sfDrillHud) AND REQUEST_SCRIPT_AUDIO_BANK("DLC_MPHEIST\\HEIST_FLEECA_DRILL") AND REQUEST_SCRIPT_AUDIO_BANK("DLC_MPHEIST\\HEIST_FLEECA_DRILL_2") RETURN TRUE ENDIF RETURN FALSE ENDFUNC PROC RESET_DRILL_MINIGAME_DATA(S_DRILL_DATA &sDrillData) sDrillData.iBitset = 0 sDrillData.iHUDFlashTimer = 0 sDrillData.iCurrentState = 0 sDrillData.iAudioEvent = 0 sDrillData.fCurrentDrillPosY = 0.0 sDrillData.fCurrentDrillBitPos = 0.0 sDrillData.fDrillBitShakeOffset = 0.0 sDrillData.fCurrentDrillBasePosX = 0.0 sDrillData.fCurrentDrillPower = 0.0 sDrillData.fCurrentProgress = 0.0 sDrillData.fCurrentSweetSpotHeight = DRILL_MAX_SWEET_SPOT_SIZE sDrillData.fCurrentSweetSpotMin = 0.0 sDrillData.fCurrentSweetSpotMax = 0.0 sDrillData.fCurrentHeatLevel = 0.0 sDrillData.fCurrentProgressIncreaseSpeed = 0.0 sDrillData.fForwardLeanExtraAmountForPins = 0.0 sDrillData.fPinBreakPowerModifier = 0.0 ENDPROC /// PURPOSE: /// Checks if it's okay to run the drilling minigame. FUNC BOOL IS_SAFE_TO_PLAY_DRILL_MINIGAME() //Currently just one check: may be expanded in the future. IF NOT IS_CUTSCENE_PLAYING() RETURN TRUE ENDIF RETURN FALSE ENDFUNC FUNC BOOL MANAGE_DRILL_TIMER(INT &iStartTime, INT iTimeToWait) RETURN (GET_GAME_TIMER() - iStartTime > iTimeToWait) ENDFUNC PROC FORCE_QUIT_FAIL_DRILL_MINIGAME_KEEP_DATA(S_DRILL_DATA &drill_data, BOOL bResetData = TRUE) IF IS_MINIGAME_IN_PROGRESS() SET_MINIGAME_IN_PROGRESS(FALSE) ENDIF CLEAR_HELP() NET_SET_PLAYER_CONTROL(PLAYER_ID(), TRUE) DISABLE_CELLPHONE(FALSE) DISABLE_SCRIPT_HUD_THIS_FRAME_RESET() IF bResetData RESET_DRILL_MINIGAME_DATA(drill_data) ENDIF ENDPROC PROC FORCE_QUIT_PASS_DRILL_MINIGAME_KEEP_DATA(S_DRILL_DATA &drill_data, BOOL bResetData = TRUE, BOOL bClearTasks = TRUE, BOOL bRestoreControl = TRUE) IF IS_MINIGAME_IN_PROGRESS() SET_MINIGAME_IN_PROGRESS(FALSE) ENDIF IF bClearTasks CLEAR_PED_TASKS(PLAYER_PED_ID()) ENDIF CLEAR_HELP() IF bRestoreControl NET_SET_PLAYER_CONTROL(PLAYER_ID(), TRUE) ENDIF DISABLE_CELLPHONE(FALSE) DISABLE_SCRIPT_HUD_THIS_FRAME_RESET() CLEANUP_PC_DRILLING_CONTROLS() IF bResetData RESET_DRILL_MINIGAME_DATA(drill_data) ENDIF ENDPROC FUNC BOOL HAS_PLAYER_BEAT_DRILL_MINIGAME(S_DRILL_DATA &sDrillData, BOOL bForceQuit = FALSE) IF IS_BIT_SET(sDrillData.iBitset, DRILL_BITSET_IS_MINIGAME_COMPLETE) IF bForceQuit FORCE_QUIT_PASS_DRILL_MINIGAME_KEEP_DATA(sDrillData) ENDIF RETURN TRUE ENDIF RETURN FALSE ENDFUNC PROC INITIALISE_MINIGAME_VALUES(S_DRILL_DATA &sDrillData) IF NOT IS_BIT_SET(sDrillData.iBitset, DRILL_BITSET_DID_PLAYER_MESS_UP) IF NOT IS_BIT_SET(sDrillData.iBitset, DRILL_BITSET_DID_PLAYER_BACK_OUT) sDrillData.fCurrentProgress = DRILL_START_POINT sDrillData.iAudioEvent = 0 ENDIF sDrillData.fCurrentHeatLevel = 0.0 ENDIF sDrillData.iHUDFlashTimer = 0 sDrillData.iCurrentState = 0 sDrillData.fCurrentDrillPosY = 0.0 sDrillData.fCurrentDrillBitPos = 0.0 sDrillData.fDrillBitShakeOffset = 0.0 sDrillData.fCurrentDrillBasePosX = 0.0 sDrillData.fCurrentDrillPower = 0.0 sDrillData.fCurrentProgressIncreaseSpeed = 0.0 sDrillData.fCurrentForwardLeanPos = 0.0 sDrillData.fForwardLeanExtraAmountForPins = 0.0 sDrillData.fPinBreakPowerModifier = 0.0 sDrillData.fCurrentSweetSpotHeight = DRILL_MAX_SWEET_SPOT_SIZE sDrillData.fCurrentSweetSpotMax = sDrillData.fCurrentProgress sDrillData.fCurrentSweetSpotMin = sDrillData.fCurrentSweetSpotMax - DRILL_MAX_SWEET_SPOT_SIZE IF sDrillData.fCurrentSweetSpotMin < 0.0 sDrillData.fCurrentSweetSpotMin = 0.0 ENDIF CLEAR_BIT(sDrillData.iBitset, DRILL_BITSET_IS_MINIGAME_COMPLETE) CLEAR_BIT(sDrillData.iBitset, DRILL_BITSET_DID_PLAYER_MESS_UP) ENDPROC /*FUNC BOOL IS_DRILL_IN_SWEET_SPOT(S_DRILL_DATA &sDrillData) IF sDrillData.fCurrentDrillPosY >= sDrillData.fCurrentSweetSpotMin AND sDrillData.fCurrentDrillPosY <= sDrillData.fCurrentSweetSpotMax RETURN TRUE ENDIF RETURN FALSE ENDFUNC*/ PROC SET_PLAYER_BACKED_OUT_OF_DRILLING(S_DRILL_DATA &sDrillData) SET_BIT(sDrillData.iBitset, DRILL_BITSET_DID_PLAYER_BACK_OUT) ENDPROC FUNC BOOL HAS_PLAYER_BACKED_OUT_OF_DRILLING(S_DRILL_DATA &sDrillData) RETURN IS_BIT_SET(sDrillData.iBitset, DRILL_BITSET_DID_PLAYER_BACK_OUT) ENDFUNC PROC PLAYER_MESSED_UP_DRILLING(S_DRILL_DATA &sDrillData) SET_CONTROL_SHAKE(PLAYER_CONTROL, 2000, 220) SET_BIT(sDrillData.iBitset, DRILL_BITSET_DID_PLAYER_MESS_UP) IF sDrillData.fCurrentDrillBasePosX <= 0.0 SET_BIT(sDrillData.iBitset, DRILL_BITSET_DID_PLAYER_MESS_UP_ON_LEFT_SIDE) ELSE CLEAR_BIT(sDrillData.iBitset, DRILL_BITSET_DID_PLAYER_MESS_UP_ON_LEFT_SIDE) ENDIF ENDPROC FUNC BOOL HAS_PLAYER_MESSED_UP_DRILLING(S_DRILL_DATA &sDrillData) RETURN IS_BIT_SET(sDrillData.iBitset, DRILL_BITSET_DID_PLAYER_MESS_UP) ENDFUNC /// PURPOSE: /// Returns whether the player was leaning on the left side when they messed up the drilling minigame. Useful for /// working out which transition anim to play. FUNC BOOL DID_PLAYER_MESS_UP_DRILLING_ON_LEFT_SIDE(S_DRILL_DATA &sDrillData) RETURN IS_BIT_SET(sDrillData.iBitset, DRILL_BITSET_DID_PLAYER_MESS_UP_ON_LEFT_SIDE) ENDFUNC /// PURPOSE: /// Calculates a skew value for the drill's sideways movement: the skew forces the player to compensate their own movement to avoid hitting the edges. /// The skew changes with the current progress of the drill. /*FUNC FLOAT GET_CURRENT_DRILL_POSITION_SKEW(S_DRILL_DATA &sDrillData) FLOAT fSkew = 0.0 IF sDrillData.fCurrentProgress > 0.3 fSkew = 1.15 * SIN(600.0 * (sDrillData.fCurrentProgress - 0.3)) ENDIF RETURN fSkew ENDFUNC*/ PROC SHAKE_DRILL_BIT(S_DRILL_DATA &sDrillData) IF sDrillData.fCurrentDrillPosY > sDrillData.fCurrentSweetSpotMax IF ABSF(sDrillData.fDesiredDrillBitShakeOffset - sDrillData.fDrillBitShakeOffset) < 0.002 sDrillData.fDesiredDrillBitShakeOffset = GET_RANDOM_FLOAT_IN_RANGE(-0.04, 0.0) ENDIF ELSE sDrillData.fDesiredDrillBitShakeOffset = 0.0 ENDIF sDrillData.fDrillBitShakeOffset = LERP_FLOAT(sDrillData.fDrillBitShakeOffset, sDrillData.fDesiredDrillBitShakeOffset, 1.0) ENDPROC //Old HUD, due to be replaced by Scaleform. /*PROC DRAW_DRILL_MINIGAME_HUD(S_DRILL_DATA &sDrillData) IF CAN_INGAME_HUD_ELEMENTS_DISPLAY() CONST_FLOAT DRILL_HUD_CENTRE_X 0.85 CONST_FLOAT DRILL_HUD_CENTRE_Y 0.8 CONST_FLOAT DRILL_HUD_HEIGHT 0.2 CONST_FLOAT DRILL_HUD_WIDTH 0.03 CONST_FLOAT DRILL_HUD_PROGRESS_HEIGHT 0.18 CONST_FLOAT DRILL_HUD_PROGRESS_WIDTH 0.025 CONST_FLOAT DRILL_HUD_INDICATOR_SIZE 0.003 BOOL bFlashHUD = FALSE INT iR, iG, iB INT iScreenSizeX INT iScreenSizeY GET_SCREEN_RESOLUTION(iScreenSizeX, iScreenSizeY) FLOAT fAspectRatio = TO_FLOAT(iScreenSizeX) / TO_FLOAT(iScreenSizeY) //Work out the colour for the progress bar: colour is based on heat level. Try to get the colour to gradually turn from green to red. //Roughly the colours should be: // heat = 0.0 colour = green // heat - 0.25 colour = yellow // heat = 0.5 colour = orange // heat = 0.75 colour = red // heat = 1.0 colour = dark red IF sDrillData.fCurrentHeatLevel >= 0.75 //Increase red value where heat 1.0 = 128 and heat 0.75 = 255 iR = 128 + ROUND(((0.25 - (sDrillData.fCurrentHeatLevel - 0.75)) / 0.25) * 127.0) ELIF sDrillData.fCurrentHeatLevel < 0.25 iR = ROUND((sDrillData.fCurrentHeatLevel / 0.25) * 255.0) ELSE iR = 255 ENDIF IF sDrillData.fCurrentHeatLevel >= 0.75 iG = 0 ELIF sDrillData.fCurrentHeatLevel >= 0.25 //Increase green value where heat 0.75 = 0 and heat 0.25 = 255 iG = ROUND(((0.5 - (sDrillData.fCurrentHeatLevel - 0.25)) / 0.5) * 255.0) ELSE iG = 255 ENDIF iB = 0 //If the player is outside the sweet spot then flash the whole bar. IF NOT IS_BIT_SET(sDrillData.iBitset, DRILL_BITSET_IS_IN_SWEET_SPOT) AND sDrillData.fCurrentDrillPower > 0.0 IF sDrillData.iHUDFlashTimer = 0 OR GET_GAME_TIMER() - sDrillData.iHUDFlashTimer > 300 sDrillData.iHUDFlashTimer = GET_GAME_TIMER() ELSE IF GET_GAME_TIMER() - sDrillData.iHUDFlashTimer < 100 bFlashHUD = TRUE ENDIF ENDIF ENDIF //Draw the background (black background plus a progress background). DRAW_RECT(DRILL_HUD_CENTRE_X, DRILL_HUD_CENTRE_Y, DRILL_HUD_WIDTH, DRILL_HUD_HEIGHT, 0, 0, 0, 128) IF bFlashHUD DRAW_RECT(DRILL_HUD_CENTRE_X, DRILL_HUD_CENTRE_Y, DRILL_HUD_PROGRESS_WIDTH, DRILL_HUD_PROGRESS_HEIGHT, 255, 255, 255, 255) ELSE DRAW_RECT(DRILL_HUD_CENTRE_X, DRILL_HUD_CENTRE_Y, DRILL_HUD_PROGRESS_WIDTH, DRILL_HUD_PROGRESS_HEIGHT, ROUND(TO_FLOAT(iR) * 0.25), ROUND(TO_FLOAT(iG) * 0.25), ROUND(TO_FLOAT(iB) * 0.25), 255) ENDIF //Draw the progress bar. FLOAT fProgressBarHeight = sDrillData.fCurrentProgress * DRILL_HUD_PROGRESS_HEIGHT FLOAT fProgressBarCentreY = DRILL_HUD_CENTRE_Y + (DRILL_HUD_PROGRESS_HEIGHT * 0.5) - (fProgressBarHeight * 0.5) IF bFlashHUD DRAW_RECT(DRILL_HUD_CENTRE_X, fProgressBarCentreY, DRILL_HUD_PROGRESS_WIDTH, fProgressBarHeight, 255, 255, 255, 255) ELSE DRAW_RECT(DRILL_HUD_CENTRE_X, fProgressBarCentreY, DRILL_HUD_PROGRESS_WIDTH, fProgressBarHeight, iR, iG, iB, 255) ENDIF //Draw the sweet spot. FLOAT fSweetSpotHeight = (sDrillData.fCurrentSweetSpotMax - sDrillData.fCurrentSweetSpotMin) * DRILL_HUD_PROGRESS_HEIGHT FLOAT fSweetSpotCentreY = DRILL_HUD_CENTRE_Y + (DRILL_HUD_PROGRESS_HEIGHT * 0.5) - fProgressBarHeight + (fSweetSpotHeight * 0.5) IF bFlashHUD DRAW_RECT(DRILL_HUD_CENTRE_X, fSweetSpotCentreY, DRILL_HUD_PROGRESS_WIDTH, fSweetSpotHeight, 255, 255, 255, 255) ELSE DRAW_RECT(DRILL_HUD_CENTRE_X, fSweetSpotCentreY, DRILL_HUD_PROGRESS_WIDTH, fSweetSpotHeight, 0, 96, 255, 255) ENDIF //Draw the drill indicator. FLOAT fIndicatorPosX = DRILL_HUD_CENTRE_X + (sDrillData.fCurrentDrillSkewedPosX * DRILL_HUD_PROGRESS_WIDTH * 0.5) FLOAT fIndicatorPosY = DRILL_HUD_CENTRE_Y + (DRILL_HUD_PROGRESS_HEIGHT * 0.5) - (sDrillData.fCurrentDrillPosY * DRILL_HUD_PROGRESS_HEIGHT) DRAW_RECT(fIndicatorPosX, fIndicatorPosY, DRILL_HUD_INDICATOR_SIZE, DRILL_HUD_INDICATOR_SIZE * fAspectRatio, 255, 255, 255, 255) ENDIF ENDPROC*/ //New version of HUD using scaleform movie. PROC DRAW_DRILL_MINIGAME_SCALEFORM_HUD(S_DRILL_DATA &sDrillData) IF CAN_INGAME_HUD_ELEMENTS_DISPLAY() AND IS_SAFE_TO_PLAY_DRILL_MINIGAME() HIDE_HUD_AND_RADAR_THIS_FRAME() THEFEED_HIDE_THIS_FRAME() //NOTE: with the current UI the drill starts to strobe at max power, so adjust the input value slightly. This also lets us boost the speed when we hit a pin (2207563) CALL_SCALEFORM_MOVIE_METHOD_WITH_NUMBER(sDrillData.sfDrillHud, "SET_SPEED", (sDrillData.fCurrentDrillPower * 0.79) + (sDrillData.fPinBreakPowerModifier * 0.08)) CALL_SCALEFORM_MOVIE_METHOD_WITH_NUMBER(sDrillData.sfDrillHud, "SET_HOLE_DEPTH", sDrillData.fCurrentProgress) CALL_SCALEFORM_MOVIE_METHOD_WITH_NUMBER(sDrillData.sfDrillHud, "SET_DRILL_POSITION", sDrillData.fCurrentDrillBitPos + sDrillData.fDrillBitShakeOffset) CALL_SCALEFORM_MOVIE_METHOD_WITH_NUMBER(sDrillData.sfDrillHud, "SET_TEMPERATURE", sDrillData.fCurrentHeatLevel) DRAW_SCALEFORM_MOVIE_FULLSCREEN(sDrillData.sfDrillHUD, 255, 255, 255, 255) //DRAW_SCALEFORM_MOVIE(sDrillData.sfDrillHUD, sDrillData.fHudPosX, sDrillData.fHudPosY, 0.6, 0.8, 255, 255, 255, 255) ENDIF ENDPROC #IF IS_DEBUG_BUILD PROC DRAW_STRING_TO_DRILL_DEBUG(S_DRILL_DATA &sDrillData, STRING strDebug) SET_DEBUG_LINES_AND_SPHERES_DRAWING_ACTIVE(TRUE) DRAW_DEBUG_TEXT_2D(strDebug, <<0.05, 0.04 + (0.04 * sDrillData.iDebugNumPrintsThisFrame), 0.0>>, 0, 0, 255, 255) sDrillData.iDebugNumPrintsThisFrame++ ENDPROC PROC DRAW_INT_TO_DRILL_DEBUG(S_DRILL_DATA &sDrillData, INT iDebug, STRING strLabel) TEXT_LABEL_63 strConcat = strLabel strConcat += iDebug DRAW_STRING_TO_DRILL_DEBUG(sDrillData, strConcat) ENDPROC PROC DRAW_FLOAT_TO_DRILL_DEBUG(S_DRILL_DATA &sDrillData, FLOAT fDebug, STRING strLabel) TEXT_LABEL_63 strConcat = strLabel strConcat += " " strConcat += GET_STRING_FROM_FLOAT(fDebug) DRAW_STRING_TO_DRILL_DEBUG(sDrillData, strConcat) ENDPROC PROC DUMP_DRILL_MINIGAME_STATE_TO_CONSOLE(S_DRILL_DATA &sDrillData) INT iCurrentTime = GET_GAME_TIMER() CDEBUG1LN(DEBUG_MISSION, "[RUN_DRILL_MINIGAME] Dumping script state, current game time = ", iCurrentTime) CDEBUG1LN(DEBUG_MISSION, "[RUN_DRILL_MINIGAME] iCurrentState = ", sDrillData.iCurrentState) CDEBUG1LN(DEBUG_MISSION, "[RUN_DRILL_MINIGAME] iBitset = ", sDrillData.iBitSet) CDEBUG1LN(DEBUG_MISSION, "[RUN_DRILL_MINIGAME] iHUDFlashTimer = ", sDrillData.iHUDFlashTimer) CDEBUG1LN(DEBUG_MISSION, "[RUN_DRILL_MINIGAME] fCurrentDrillPosY = ", sDrillData.fCurrentDrillPosY) CDEBUG1LN(DEBUG_MISSION, "[RUN_DRILL_MINIGAME] fCurrentDrillBasePosX = ", sDrillData.fCurrentDrillBasePosX) CDEBUG1LN(DEBUG_MISSION, "[RUN_DRILL_MINIGAME] fCurrentDrillBitPos = ", sDrillData.fCurrentDrillBitPos) CDEBUG1LN(DEBUG_MISSION, "[RUN_DRILL_MINIGAME] fDrillBitShakeOffset = ", sDrillData.fDrillBitShakeOffset) CDEBUG1LN(DEBUG_MISSION, "[RUN_DRILL_MINIGAME] fCurrentLeanPos = ", sDrillData.fCurrentLeanPos) CDEBUG1LN(DEBUG_MISSION, "[RUN_DRILL_MINIGAME] fCurrentForwardLeanPos = ", sDrillData.fCurrentForwardLeanPos) CDEBUG1LN(DEBUG_MISSION, "[RUN_DRILL_MINIGAME] fCurrentDrillPower = ", sDrillData.fCurrentDrillPower) CDEBUG1LN(DEBUG_MISSION, "[RUN_DRILL_MINIGAME] fCurrentProgress = ", sDrillData.fCurrentProgress) CDEBUG1LN(DEBUG_MISSION, "[RUN_DRILL_MINIGAME] fCurrentSweetSpotHeight = ", sDrillData.fCurrentSweetSpotHeight) CDEBUG1LN(DEBUG_MISSION, "[RUN_DRILL_MINIGAME] fCurrentSweetSpotMin = ", sDrillData.fCurrentSweetSpotMin) CDEBUG1LN(DEBUG_MISSION, "[RUN_DRILL_MINIGAME] fCurrentSweetSpotMax = ", sDrillData.fCurrentSweetSpotMax) CDEBUG1LN(DEBUG_MISSION, "[RUN_DRILL_MINIGAME] fCurrentHeatLevel = ", sDrillData.fCurrentHeatLevel) CDEBUG1LN(DEBUG_MISSION, "[RUN_DRILL_MINIGAME] fCurrentProgressIncreaseSpeed = ", sDrillData.fCurrentProgressIncreaseSpeed) CDEBUG1LN(DEBUG_MISSION, "[RUN_DRILL_MINIGAME] fHudPosX = ", sDrillData.fHudPosX) CDEBUG1LN(DEBUG_MISSION, "[RUN_DRILL_MINIGAME] fHudPosY = ", sDrillData.fHudPosY) ENDPROC PROC UPDATE_DRILL_MINIGAME_DEBUG(S_DRILL_DATA &sDrillData) //Dump the state of all variables if someone enters a bug. IF IS_KEYBOARD_KEY_PRESSED(KEY_SPACE) OR IS_KEYBOARD_KEY_PRESSED(KEY_RBRACKET) DUMP_DRILL_MINIGAME_STATE_TO_CONSOLE(sDrillData) ENDIF //Instant pass. IF IS_KEYBOARD_KEY_JUST_PRESSED(KEY_NUMPAD1) sDrillData.fCurrentProgress = 1.0 ENDIF //Incremental increase IF IS_KEYBOARD_KEY_JUST_PRESSED(KEY_NUMPAD9) sDrillData.fCurrentProgress += 0.005 ENDIF //Incremental decrease IF IS_KEYBOARD_KEY_JUST_PRESSED(KEY_NUMPAD3) sDrillData.fCurrentProgress -= 0.005 ENDIF //Display some debug IF IS_KEYBOARD_KEY_JUST_PRESSED(KEY_NUMPAD5) sDrillData.bDisplayDebug = NOT sDrillData.bDisplayDebug ENDIF //Move the HUD around IF IS_KEYBOARD_KEY_JUST_PRESSED(KEY_NUMPAD4) sDrillData.fHudPosX -= 0.01 ENDIF IF IS_KEYBOARD_KEY_JUST_PRESSED(KEY_NUMPAD6) sDrillData.fHudPosX += 0.01 ENDIF IF IS_KEYBOARD_KEY_JUST_PRESSED(KEY_NUMPAD8) sDrillData.fHudPosY -= 0.01 ENDIF IF IS_KEYBOARD_KEY_JUST_PRESSED(KEY_NUMPAD2) sDrillData.fHudPosY += 0.01 ENDIF IF sDrillData.bDisplayDebug sDrillData.iDebugNumPrintsThisFrame = 0 DRAW_INT_TO_DRILL_DEBUG(sDrillData, sDrillData.iCurrentState, "iCurrentState") DRAW_FLOAT_TO_DRILL_DEBUG(sDrillData, sDrillData.fCurrentDrillBasePosX, "fCurrentDrillBasePosX") DRAW_FLOAT_TO_DRILL_DEBUG(sDrillData, sDrillData.fCurrentLeanPos, "fCurrentLeanPos") DRAW_FLOAT_TO_DRILL_DEBUG(sDrillData, sDrillData.fCurrentForwardLeanPos, "fCurrentForwardLeanPos") DRAW_FLOAT_TO_DRILL_DEBUG(sDrillData, sDrillData.fCurrentDrillPosY, "fCurrentDrillPosY") DRAW_FLOAT_TO_DRILL_DEBUG(sDrillData, sDrillData.fCurrentDrillBitPos, "fCurrentDrillBitPos") DRAW_FLOAT_TO_DRILL_DEBUG(sDrillData, sDrillData.fDrillBitShakeOffset, "fDrillBitShakeOffset") DRAW_FLOAT_TO_DRILL_DEBUG(sDrillData, sDrillData.fCurrentDrillPower, "fCurrentDrillPower") DRAW_FLOAT_TO_DRILL_DEBUG(sDrillData, sDrillData.fPinBreakPowerModifier, "fPinBreakPowerModifier") DRAW_FLOAT_TO_DRILL_DEBUG(sDrillData, sDrillData.fCurrentDrillAnimPower, "fCurrentDrillAnimPower") DRAW_FLOAT_TO_DRILL_DEBUG(sDrillData, sDrillData.fCurrentProgress, "fCurrentProgress") DRAW_FLOAT_TO_DRILL_DEBUG(sDrillData, sDrillData.fCurrentSweetSpotHeight, "fCurrentSweetSpotHeight") DRAW_FLOAT_TO_DRILL_DEBUG(sDrillData, sDrillData.fCurrentSweetSpotMin, "fCurrentSweetSpotMin") DRAW_FLOAT_TO_DRILL_DEBUG(sDrillData, sDrillData.fCurrentSweetSpotMax, "fCurrentSweetSpotMax") DRAW_FLOAT_TO_DRILL_DEBUG(sDrillData, sDrillData.fCurrentHeatLevel, "fCurrentHeatLevel") DRAW_FLOAT_TO_DRILL_DEBUG(sDrillData, sDrillData.fCurrentProgressIncreaseSpeed, "fCurrentProgressIncreaseSpeed") DRAW_RECT(0.8, 0.5, 0.05, sDrillData.fCurrentSweetSpotHeight * 0.5, 255, 0, 0, 255) ENDIF ENDPROC #ENDIF PROC RUN_DRILL_MINIGAME(S_DRILL_DATA &sDrillData) #IF IS_DEBUG_BUILD UPDATE_DRILL_MINIGAME_DEBUG(sDrillData) #ENDIF SWITCH sDrillData.iCurrentState CASE DRILL_MINIGAME_STATE_INITIALISE INITIALISE_MINIGAME_VALUES(sDrillData) //If this is a second attempt at the game then reset the backing out flag. CLEAR_BIT(sDrillData.iBitset, DRILL_BITSET_DID_PLAYER_BACK_OUT) sDrillData.iCurrentState = DRILL_MINIGAME_STATE_DRILLING SETUP_PC_DRILLING_CONTROLS() BREAK CASE DRILL_MINIGAME_STATE_DRILLING CLEAR_BIT(sDrillData.iBitset, DRILL_BITSET_IS_IN_SWEET_SPOT) //Grab the inputs IF HAS_PLAYER_MESSED_UP_DRILLING(sDrillData) OR NOT IS_SAFE_TO_PLAY_DRILL_MINIGAME() sDrillData.fCurrentDrillBasePosX = 0.0 sDrillData.fCurrentDrillPosY = 0.0 sDrillData.fCurrentDrillPower = 0.0 ELSE sDrillData.fCurrentDrillBasePosX = GET_CONTROL_NORMAL(FRONTEND_CONTROL, INPUT_SCRIPT_LEFT_AXIS_X) IF IS_USING_KEYBOARD_AND_MOUSE(FRONTEND_CONTROL) IF IS_MOUSE_LOOK_INVERTED() sDrillData.fCurrentDrillPosY += ( GET_CONTROL_NORMAL(FRONTEND_CONTROL, INPUT_SCRIPT_LEFT_AXIS_Y) * 0.25 ) ELSE sDrillData.fCurrentDrillPosY -= ( GET_CONTROL_NORMAL(FRONTEND_CONTROL, INPUT_SCRIPT_LEFT_AXIS_Y) * 0.25 ) ENDIF ELSE sDrillData.fCurrentDrillPosY = -GET_CONTROL_NORMAL(FRONTEND_CONTROL, INPUT_FRONTEND_AXIS_Y) ENDIF sDrillData.fCurrentDrillPower = GET_CONTROL_NORMAL(FRONTEND_CONTROL, INPUT_SCRIPT_RT) ENDIF //Floor negative values of the Y position as they're not relevant. IF sDrillData.fCurrentDrillPosY < 0.0 sDrillData.fCurrentDrillPosY = 0.0 ENDIF //2081557 - Allow some room in the Y-position so the game doesn't get stuck due to a dodgy analog stick. IF NOT IS_USING_KEYBOARD_AND_MOUSE(FRONTEND_CONTROL) sDrillData.fCurrentDrillPosY = sDrillData.fCurrentDrillPosY / DRILL_POS_SCALE_MODIFIER ENDIF IF sDrillData.fCurrentDrillPosY > 1.0 sDrillData.fCurrentDrillPosY = 1.0 ENDIF // No need to dead-zone on mouse IF NOT IS_USING_KEYBOARD_AND_MOUSE(FRONTEND_CONTROL) //If the power is a really small value then floor it (to protect against dodgy pad triggers). IF sDrillData.fCurrentDrillPower < 0.03 sDrillData.fCurrentDrillPower = 0.0 ENDIF ENDIF //2207563 - Have a power modifier value that kicks in when a pin breaks and gradually dies down. If the player stops drilling it dies down more quickly. sDrillData.fPinBreakPowerModifier = sDrillData.fPinBreakPowerModifier -@ (DRILL_PIN_BREAK_POWER_MODIFIER_DECEL + (0.2 * (1.0 - sDrillData.fCurrentDrillPower))) IF sDrillData.fPinBreakPowerModifier < 0.0 sDrillData.fPinBreakPowerModifier = 0.0 ENDIF sDrillData.fCurrentDrillPower *= (1.0 + (sDrillData.fPinBreakPowerModifier * DRILL_PIN_BREAK_POWER_MODIFER_MAX)) IF sDrillData.fCurrentDrillPower > 1.0 sDrillData.fCurrentDrillPower = 1.0 ENDIF //Determine the current sweet spot height and progress speed we should progress (both are based on drill power). //Extra request: Make the sweet spot bigger at the start to make it easier. FLOAT fSweetSpotExtraHeight sDrillData.fCurrentSweetSpotHeight = DRILL_MAX_SWEET_SPOT_SIZE - ((DRILL_MAX_SWEET_SPOT_SIZE - DRILL_MIN_SWEET_SPOT_SIZE) * sDrillData.fCurrentDrillPower) fSweetSpotExtraHeight = (1.0 - sDrillData.fCurrentProgress) * DRILL_MAX_SWEET_SPOT_SIZE sDrillData.fCurrentSweetSpotHeight += fSweetSpotExtraHeight sDrillData.fCurrentProgressIncreaseSpeed = DRILL_MIN_PROGRESS_SPEED + ((DRILL_MAX_PROGRESS_SPEED - DRILL_MIN_PROGRESS_SPEED) * sDrillData.fCurrentDrillPower) //2207563 - Make the sweet spot smaller if we just broke a pin. sDrillData.fCurrentSweetSpotHeight /= (1.0 + (sDrillData.fPinBreakPowerModifier * 6.0)) //Determine the current sweet spot: the sweet spot goes from the top of the progress bar down to a position depending on the current height. sDrillData.fCurrentSweetSpotMin = sDrillData.fCurrentProgress sDrillData.fCurrentSweetSpotMax = sDrillData.fCurrentSweetSpotMin + sDrillData.fCurrentSweetSpotHeight IF sDrillData.fCurrentSweetSpotMin < 0.0 sDrillData.fCurrentSweetSpotMin = 0.0 ENDIF IF sDrillData.fCurrentSweetSpotMax > 1.0 sDrillData.fCurrentSweetSpotMax = 1.0 ENDIF //Handle progress and overheat updates (don't update if the player currently messed up and is still recovering). IF NOT HAS_PLAYER_MESSED_UP_DRILLING(sDrillData) IF sDrillData.fCurrentDrillPower > 0.0 IF sDrillData.fCurrentDrillPosY < sDrillData.fCurrentSweetSpotMin //Drill is too far back: nothing happens. SET_CONTROL_SHAKE(FRONTEND_CONTROL, 200, 15 + ROUND(sDrillData.fCurrentDrillPower * 45.0) + ROUND(sDrillData.fPinBreakPowerModifier * 45.0)) ELIF sDrillData.fCurrentDrillPosY > sDrillData.fCurrentSweetSpotMax //Drill is too far forward: overheat it. Increase the rate of overheating based on drill power. sDrillData.fCurrentHeatLevel = sDrillData.fCurrentHeatLevel +@ (DRILL_OVERHEAT_SPEED + (sDrillData.fCurrentDrillPower * 0.2)) SET_CONTROL_SHAKE(FRONTEND_CONTROL, 200, 200) ELSE //Drill is in the sweet spot. sDrillData.fCurrentProgress = sDrillData.fCurrentProgress +@ sDrillData.fCurrentProgressIncreaseSpeed IF sDrillData.fCurrentProgress >= 1.0 sDrillData.fCurrentProgress = 1.0 ENDIF SET_BIT(sDrillData.iBitset, DRILL_BITSET_IS_IN_SWEET_SPOT) SET_CONTROL_SHAKE(FRONTEND_CONTROL, 200, 30 + ROUND(sDrillData.fCurrentDrillPower * 60.0) + ROUND(sDrillData.fPinBreakPowerModifier * 60.0)) ENDIF ELSE //Shake slightly if the player is pushing the drill too hard. IF sDrillData.fCurrentDrillPosY > sDrillData.fCurrentSweetSpotMax SET_CONTROL_SHAKE(FRONTEND_CONTROL, 200, 30) ENDIF ENDIF ELSE sDrillData.fCurrentForwardLeanPos = 0.0 ENDIF //Decrease the overheat meter over time, if the player has let go of the power then cool down quicker (or if they overheated completely). IF HAS_PLAYER_MESSED_UP_DRILLING(sDrillData) sDrillData.fCurrentHeatLevel = sDrillData.fCurrentHeatLevel -@ (DRILL_COOLDOWN_SPEED * 2.0) ELIF sDrillData.fCurrentDrillPower > 0.0 sDrillData.fCurrentHeatLevel = sDrillData.fCurrentHeatLevel -@ DRILL_COOLDOWN_SPEED ELSE sDrillData.fCurrentHeatLevel = sDrillData.fCurrentHeatLevel -@ (DRILL_COOLDOWN_SPEED * 1.25) ENDIF //Cap the heat value. IF sDrillData.fCurrentHeatLevel > 1.0 sDrillData.fCurrentHeatLevel = 1.0 ELIF sDrillData.fCurrentHeatLevel < 0.0 sDrillData.fCurrentHeatLevel = 0.0 ENDIF //Set the visible drill bit position: the drill can't go further than the current progress. If the player is trying to do this then shake the drill bit. sDrillData.fCurrentDrillBitPos = sDrillData.fCurrentDrillBitPos + ((sDrillData.fCurrentDrillPosY - sDrillData.fCurrentDrillBitPos) * 0.5) IF sDrillData.fCurrentDrillBitPos > sDrillData.fCurrentProgress sDrillData.fCurrentDrillBitPos = sDrillData.fCurrentProgress ENDIF SHAKE_DRILL_BIT(sDrillData) //Work out the anim values: these are just interpolations of the progress and sideways movement values, and are used for smoothing out the anims. sDrillData.fCurrentLeanPos = COSINE_INTERP_FLOAT(sDrillData.fCurrentLeanPos, sDrillData.fCurrentDrillBasePosX, DRILL_LEAN_INTERP_SPEED) sDrillData.fCurrentForwardLeanPos = COSINE_INTERP_FLOAT(sDrillData.fCurrentForwardLeanPos, sDrillData.fCurrentDrillBitPos, DRILL_LEAN_INTERP_SPEED * 0.5) sDrillData.fCurrentDrillAnimPower = COSINE_INTERP_FLOAT(sDrillData.fCurrentDrillAnimPower, sDrillData.fCurrentDrillPower, 0.4) //If the progress reaches max then go to the next stage. //NOTE: the new drill scaleform cracks before progress reaches 1.0. //2136848 - Have some delay so it doesn't cut to the cutscene too quickly after passing. IF sDrillData.fCurrentProgress >= DRILL_PASS_POINT AND IS_SAFE_TO_PLAY_DRILL_MINIGAME() //Guarantee that we;ve gone past the point where the drill HUD cracks. IF DRILL_PASS_POINT < 0.99 AND sDrillData.fCurrentProgress - DRILL_PASS_POINT < 0.01 sDrillData.fCurrentProgress = DRILL_PASS_POINT + 0.01 ENDIF IF GET_GAME_TIMER() - sDrillData.iPassTimer > 500 CDEBUG1LN(DEBUG_MISSION, "[RUN_DRILL_MINIGAME] Progress complete, passing minigame.") sDrillData.iCurrentState = DRILL_MINIGAME_STATE_CLEANUP ENDIF ELSE sDrillData.iPassTimer = GET_GAME_TIMER() ENDIF //If the heat level reaches max then put us in the overheat state. IF sDrillData.fCurrentHeatLevel >= 1.0 AND sDrillData.iCurrentState != DRILL_MINIGAME_STATE_CLEANUP CDEBUG1LN(DEBUG_MISSION, "[RUN_DRILL_MINIGAME] Player messed up.") PLAYER_MESSED_UP_DRILLING(sDrillData) ENDIF //Handle audio for pins breaking, also make sure the progress is forced to a value that guarantees the sound and UI sync up. IF sDrillData.iAudioEvent = 0 IF sDrillData.fCurrentProgress > 0.325 CDEBUG1LN(DEBUG_MISSION, "[RUN_DRILL_MINIGAME] Playing drill pin break sound ", sDrillData.iAudioEvent) PLAY_SOUND_FRONTEND( -1, "Drill_Pin_Break", "DLC_HEIST_FLEECA_SOUNDSET") IF sDrillData.fCurrentProgress < 0.33 sDrillData.fCurrentProgress = 0.33 ENDIF sDrillData.fCurrentProgress += 0.01 //2207563 - This gives the effect of the drill lurching forward after breaking a pin. sDrillData.fPinBreakPowerModifier = 1.0 sDrillData.iAudioEvent++ ENDIF ELIF sDrillData.iAudioEvent = 1 //2207563 - This will be added to the lean animation phase, giving the effect of the player lurching forward after each pin breaking. sDrillData.fForwardLeanExtraAmountForPins += (0.06 - sDrillData.fForwardLeanExtraAmountForPins) * 0.5 IF sDrillData.fCurrentProgress > 0.475 CDEBUG1LN(DEBUG_MISSION, "[RUN_DRILL_MINIGAME] Playing drill pin break sound ", sDrillData.iAudioEvent) PLAY_SOUND_FRONTEND( -1, "Drill_Pin_Break", "DLC_HEIST_FLEECA_SOUNDSET") IF sDrillData.fCurrentProgress < 0.48 sDrillData.fCurrentProgress = 0.48 ENDIF sDrillData.fCurrentProgress += 0.01 sDrillData.fPinBreakPowerModifier = 1.0 sDrillData.iAudioEvent++ ENDIF ELIF sDrillData.iAudioEvent = 2 sDrillData.fForwardLeanExtraAmountForPins += (0.12 - sDrillData.fForwardLeanExtraAmountForPins) * 0.5 IF sDrillData.fCurrentProgress > 0.625 CDEBUG1LN(DEBUG_MISSION, "[RUN_DRILL_MINIGAME] Playing drill pin break sound ", sDrillData.iAudioEvent) PLAY_SOUND_FRONTEND( -1, "Drill_Pin_Break", "DLC_HEIST_FLEECA_SOUNDSET") IF sDrillData.fCurrentProgress < 0.63 sDrillData.fCurrentProgress = 0.63 ENDIF sDrillData.fCurrentProgress += 0.01 sDrillData.fPinBreakPowerModifier = 1.0 sDrillData.iAudioEvent++ ENDIF ELIF sDrillData.iAudioEvent = 3 sDrillData.fForwardLeanExtraAmountForPins += (0.18 - sDrillData.fForwardLeanExtraAmountForPins) * 0.5 IF sDrillData.fCurrentProgress >= DRILL_PASS_POINT CDEBUG1LN(DEBUG_MISSION, "[RUN_DRILL_MINIGAME] Playing drill pin break sound ", sDrillData.iAudioEvent) PLAY_SOUND_FRONTEND( -1, "Drill_Pin_Break", "DLC_HEIST_FLEECA_SOUNDSET") sDrillData.fCurrentProgress += 0.01 sDrillData.fPinBreakPowerModifier = 1.0 sDrillData.iAudioEvent++ ENDIF ENDIF BREAK CASE DRILL_MINIGAME_STATE_CLEANUP SET_BIT(sDrillData.iBitset, DRILL_BITSET_IS_MINIGAME_COMPLETE) sDrillData.iCurrentState++ CLEANUP_PC_DRILLING_CONTROLS() BREAK ENDSWITCH //Update HUD //DRAW_DRILL_MINIGAME_HUD(sDrillData) DRAW_DRILL_MINIGAME_SCALEFORM_HUD(sDrillData) ENDPROC