////////////////////////////////////////////////////////////////////////////////////////// // // // SCRIPT NAME : Range_Modern.sc // // AUTHOR : Ryan Paradis // // DESCRIPTION : Our shooting range! The modern range involves more // // game like shooting // // // ////////////////////////////////////////////////////////////////////////////////////////// //Compile out Title Update changes to header functions. //Must be before includes. //CONST_INT USE_TU_CHANGES 0 // Removed by Kenneth R. #IF IS_DEBUG_BUILD CONST_INT COMPILE_WIDGET_OUTPUT 0 BOOL PRINT_RANGE_MEDAL_VALUES = FALSE #ENDIF USING "socialclub_leaderboard.sch" USING "Range_Public.sch" USING "selector_public.sch" USING "script_oddjob_funcs.sch" USING "minigame_UIInputs.sch" USING "cellphone_public.sch" USING "shop_public.sch" USING "savegame_public.sch" USING "mission_titles_private.sch" USING "cheat_controller_public.sch" // My four globals: PED_INDEX rangePlayerPed enumCharacterList ePlayerChar VECTOR EARMUFFS_OFFSET = <<0.111, 0, 0>> VECTOR EARMUFFS_ROT = <<0, 90, 0>> USING "range_header.sch" USING "Range_Core_lib.sch" USING "Range_UI.sch" USING "Range_Tutorial_lib.sch" USING "Range_Round_lib.sch" USING "Range_Menu_lib.sch" USING "range_round_library.sch" #IF IS_DEBUG_BUILD USING "range_debug.sch" USING "Range_Widget_Support_lib.sch" #ENDIF PROC Initialize(Range_RangeData & sRangeData, Range_RoundInfo & sRndInfo, Range_WeaponRounds & sWeapRnds[], Range_SPTData & sSPTInfo, SHOOTING_RANGE_LAUNCH_DATA & launchData, Range_TutorialData & sTutorialInfo) // No player control for now IF IS_PLAYER_PLAYING(PLAYER_ID()) SET_PLAYER_CONTROL(PLAYER_ID(), FALSE) ENDIF DISABLE_CELLPHONE(TRUE) DISPLAY_RADAR(FALSE) SET_PLAYER_NOISE_MULTIPLIER(PLAYER_ID(), 0.0) // Initialize all of our weapons INIT_WEAPON_ROUNDS(sWeapRnds) // Check our unlocks INIT_ROUND_UNLOCKS(sWeapRnds) // Create our HUD items SETUP_SPT_QUEUE(sSPTInfo.sSPTQueue) // Store where we are. sRangeData.eLocation = launchData.eLocation // Allow me to draw debug info // SET_DEBUG_LINES_AND_SPHERES_DRAWING_ACTIVE(TRUE) // Range Corners -- 0: Back Left, 1: Back Right, 2: Front Right, 3: Front Left IF (sRangeData.eLocation = RANGELOC_PILLBOX_HILL) sRangeData.vDoorPos = <<6.8179, -1098.2095, 29.9469>> sRangeData.vRangeCorners[RANGE_FRONT_LEFT] = << 12.617, -1092.350, 31.580 >> sRangeData.vRangeCorners[RANGE_BACK_LEFT] = << 16.475, -1081.5134, 31.580 >> sRangeData.vRangeCorners[RANGE_BACK_RIGHT] = << 20.1332, -1081.7876, 31.580 >> sRangeData.vRangeCorners[RANGE_FRONT_RIGHT] = << 17.325, -1094.090, 31.580 >> // Here are the far coords sRangeData.vRangeCorners[RANGE_FRONT_LEFT_FAR] = << 16.995, -1080.040, 31.580 >> sRangeData.vRangeCorners[RANGE_BACK_LEFT_FAR] = << 19.475, -1073.203, 31.580 >> sRangeData.vRangeCorners[RANGE_FRONT_RIGHT_FAR] = << 21.945, -1081.930, 31.580 >> sRangeData.vPlayerRootPos = <<13.4784, -1097.4746, 28.8347>> sRangeData.fPlayerRootHead = 345.1710 // 339.6250 sRangeData.vAngledAreaChk1 = <<11.1371, -1097.8242, 23.8347>> sRangeData.vAngledAreaChk2 = <<14.8423, -1099.4520, 33.8348>> sRangeData.vRedressPos = <<7.6658, -1097.2264, 28.7970>> sRangeData.fRedressHead = 166.8465 sRangeData.vRedressGoto = <<7.4450, -1100.0970, 28.7970>> sRangeData.vRedressCamStart = <<8.7466, -1103.6846, 30.1295>> sRangeData.vRedressCamStartOrient = <<-0.8304, -0.0000, 19.3158>> sRangeData.vRedressCamInterp = <<8.6633, -1103.4474, 30.1259>> sRangeData.vRedressCamInterpOrient = <<-0.8304, -0.0000, 19.3158>> sRangeData.vRedressCamEnd = <<6.4526, -1098.5763, 30.4486>> sRangeData.vRedressCamEndOrient = <<-7.9441, -0.0000, -150.3985>> sRangeData.vQuitCamPos = <<14.6062, -1096.6014, 30.3995>> sRangeData.vQuitCamOrient = <<-6.4007, 0.0000, 128.1684>> sRangeData.vRemoveGlassesFacing = <<12.65248, -1100.08313, 29.74706>> sRangeData.vRedressLeaveRangeGoto = <<7.7033, -1097.8596, 28.7970>> sTutorialInfo.vSceneRootPos = << 6.818, -1098.210, 29.946 >> sTutorialInfo.vSceneRootOrient = << 0.000, 0.000, 160.000 >> sTutorialInfo.vScoreTargetPos = <<14.4990, -1093.4354, 31.32>> sTutorialInfo.vNonTutorialCamPos = <<13.9958, -1097.8820, 30.3701>> sTutorialInfo.vNonTutorialCamOrient = <<-6.0067, -0.0000, -19.5923>> sTutorialInfo.vNonTutorialCamEndPos = <<13.4248, -1099.6191, 30.4893>> sTutorialInfo.vNonTutorialCamEndOrient = <<-6.1681, -0.0000, -12.1775>> sRangeData.fTargetEndZRot = 160.0 ELSE sRangeData.vDoorPos = <<827.5342, -2160.4927, 29.7688>> sRangeData.vRangeCorners[RANGE_FRONT_LEFT] = <<824.1354, -2167.8152, 31.4334>> sRangeData.vRangeCorners[RANGE_BACK_LEFT] = <<824.0692, -2179.0039, 31.3222>> sRangeData.vRangeCorners[RANGE_BACK_RIGHT] = <<820.6007, -2180.3564, 31.3625>> sRangeData.vRangeCorners[RANGE_FRONT_RIGHT] = <<819.0558, -2167.5212, 31.4334>> // Here are the far coords sRangeData.vRangeCorners[RANGE_FRONT_LEFT_FAR] = <<823.9216, -2180.9316, 31.2504>> sRangeData.vRangeCorners[RANGE_BACK_LEFT_FAR] = <<823.9360, -2188.2485, 31.1813>> sRangeData.vRangeCorners[RANGE_FRONT_RIGHT_FAR] = <<818.8218, -2180.8616, 31.3736>> sRangeData.vPlayerRootPos = <<821.5508, -2163.7073, 28.6567>> sRangeData.fPlayerRootHead = 184.3922 sRangeData.vAngledAreaChk1 = <<823.5616, -2162.2393, 24.4409>> sRangeData.vAngledAreaChk2 = <<819.3583, -2163.4966, 34.5824>> sRangeData.vRedressPos = <<826.8076, -2162.1846, 28.6190>> sRangeData.fRedressHead = 346.2118 sRangeData.vRedressGoto = <<824.8320, -2158.3601, 28.6190>> sRangeData.vRedressCamStart = <<823.9988, -2156.3330, 29.8591>> sRangeData.vRedressCamStartOrient = <<-1.9082, 0.0000, -142.3420>> sRangeData.vRedressCamInterp = <<824.2747, -2156.6902, 29.8441>> sRangeData.vRedressCamInterpOrient = <<-1.9082, 0.0000, -142.3420>> sRangeData.vRedressCamEnd = <<827.7817, -2160.1260, 30.2877>> sRangeData.vRedressCamEndOrient = <<-8.0026, 0.0000, 55.1241>> sRangeData.vQuitCamPos = <<820.7900, -2164.8320, 30.1899>> sRangeData.vQuitCamOrient = <<-2.2613, -0.0000, -30.6783>> sRangeData.vRemoveGlassesFacing = <<821.5570, -2160.8552, 30.3338>> sRangeData.vRedressLeaveRangeGoto = <<826.6258, -2161.7048, 28.6190>>//<<822.3644, -2163.3521, 30.9273>> sTutorialInfo.vSceneRootPos = <<827.5342, -2160.4927, 29.7688>> sTutorialInfo.vSceneRootOrient = << 0,0,0 >> sTutorialInfo.vScoreTargetPos = <<821.9563, -2167.0859, 31.0>> sTutorialInfo.vNonTutorialCamPos = <<820.9255, -2163.0254, 30.1917>> sTutorialInfo.vNonTutorialCamOrient = <<-4.2298, 0.0000, -179.5710>> sTutorialInfo.vNonTutorialCamEndPos = <<820.8491, -2161.1663, 30.3292>> sTutorialInfo.vNonTutorialCamEndOrient = <<-4.2298, -0.0000, -173.1768>> sRangeData.fTargetEndZRot = 359.0 ENDIF // Int our range INIT_RANGE_GRID(sRangeData, sRndInfo) // Just temp spot for these now sRndInfo.iMaxActions = 0 sRndInfo.fCurrentRoundLength = 45.0 sTutorialInfo.eSceneState = eRangeSyncScene_Init // Now law ENABLE_DISPATCH_SERVICE(DT_POLICE_AUTOMOBILE,FALSE) ENABLE_DISPATCH_SERVICE(DT_POLICE_HELICOPTER,FALSE) SET_WANTED_LEVEL_MULTIPLIER(0.0) SET_MAX_WANTED_LEVEL(0) SET_EVERYONE_IGNORE_PLAYER(GET_PLAYER_INDEX(), TRUE) CLEAR_RANK_REDICTION_DETAILS() RANGE_SP_CLEANUP_SOCIAL_CLUB_LEADERBOARD() ENDPROC // Cleanup the script on termination – must not include any WAITs PROC Script_Cleanup(Range_RangeData & sRangeInfo, Range_Targets & sTargData, Range_CoreData & sCoreInfo, Range_MenuData & sMenuInfo, VEHICLE_SAVE_ARGS &vehPlayerCar, BOOL bForceCleanup=FALSE) CDEBUG2LN(DEBUG_SHOOTRANGE, "Shooting Range: Script_Cleanup()") SET_STATE_OF_CLOSEST_DOOR_OF_TYPE(V_ILEV_GC_DOOR01, sRangeInfo.vDoorPos, FALSE, 0.0) //unlock the door now that we've ended. // We may need to make an emergency write. IF sCoreInfo.ProcessPrediction AND NOT scLB_rank_predict.bFinishedWrite WRITE_TO_RANGE_SP_HIGH_SCORE_LEADERBOARD(sCoreInfo.lbdWrite) ENDIF CLEAR_RANK_REDICTION_DETAILS() RANGE_SP_CLEANUP_SOCIAL_CLUB_LEADERBOARD() MISSION_FLOW_CLEAR_DISPLAY_MISSION_TITLE() DISABLE_COMPOSITE_SHOTGUN_DECALS(FALSE) ODDJOB_RESTORE_SAVED_VEHICLE(vehPlayerCar) IF IS_SHOOTING_RANGE_UNSAVED_BITFLAG_SET(SRB_RangeInSession) CLEAR_SHOOTING_RANGE_UNSAVED_BITFLAG(SRB_RangeInSession) ENDIF // Resetting last known info to be consistent with missions, B*909265 ResetLastKnownPedInfo(g_savedGlobals.sPlayerData.sInfo, SP_MISSION_NONE) IF g_bResultScreenDisplaying SET_RESULT_SCREEN_DISPLAYING_STATE(FALSE) ENDIF ENABLE_SELECTOR() SET_PLAYER_NOISE_MULTIPLIER(PLAYER_ID(), 1.0) SET_GAME_PAUSED(FALSE) // Destroy all targets INT iTer REPEAT iMAX_ENTITIES iTer DESTROY_TARGET(sTargData.sTargetEntities[iTer].target) ENDREPEAT IF NOT sCoreInfo.bRestoredWeapons RANGE_RESTORE_PLAYER_WEAPONS(sCoreInfo.sWeapons) ENDIF IF DOES_ENTITY_EXIST(sCoreInfo.oEarMuffs) SET_OBJECT_AS_NO_LONGER_NEEDED(sCoreInfo.oEarMuffs) ENDIF REMOVE_ANIM_DICT("mini@ears_defenders") IF NOT IS_TRANSITION_ACTIVE() AND GET_CAM_VIEW_MODE_FOR_CONTEXT(CAM_VIEW_MODE_CONTEXT_ON_FOOT) <> CAM_VIEW_MODE_FIRST_PERSON AND NOT RANGE_GET_HAS_PLAYER_KICKED_OFF_IN_RANGE( sCoreInfo ) CDEBUG2LN(DEBUG_SHOOTRANGE, "STOP_RENDERING_SCRIPT_CAMS_USING_CATCH_UP(FALSE)") STOP_RENDERING_SCRIPT_CAMS_USING_CATCH_UP(FALSE) ENDIF // Player can switch weapons again SET_PED_CAN_SWITCH_WEAPON(rangePlayerPed, TRUE) // Turn off our Radar DISPLAY_RADAR(TRUE) // Give control back SET_PLAYER_CONTROL(PLAYER_ID(), TRUE) // don't need to keep the interior loaded. IF (sCoreInfo.RangeInterior <> NULL) UNPIN_INTERIOR(sCoreInfo.RangeInterior) sCoreInfo.RangeInterior = NULL ENDIF // Clear floaty help. CLEAR_FLOATING_HELP(FLOATING_HELP_TEXT_ID_2) CLEAR_ALL_FLOATING_HELP() // Turn law in this shop back on SET_PLAYER_IS_ALLOWED_TO_SHOOT_IN_SHOP(GUN_SHOP_01_DT, FALSE) ENABLE_DISPATCH_SERVICE(DT_POLICE_AUTOMOBILE, TRUE) ENABLE_DISPATCH_SERVICE(DT_POLICE_HELICOPTER, TRUE) SET_WANTED_LEVEL_MULTIPLIER(1.0) SET_MAX_WANTED_LEVEL(6) SET_EVERYONE_IGNORE_PLAYER(GET_PLAYER_INDEX(), FALSE) RELEASE_SCRIPT_AUDIO_BANK() CLEAR_ADDITIONAL_TEXT(MINIGAME_TEXT_SLOT, FALSE) DISABLE_CELLPHONE(FALSE) //B* 2138704: Remove railgun if before Exile1 IF DOES_PLAYER_HAVE_WEAPON(WEAPONTYPE_DLC_RAILGUN) IF NOT GET_MISSION_COMPLETE_STATE(SP_MISSION_EXILE_1) OR NOT IS_PLAYER_PED_WEAPON_PURCHASED(GET_PLAYER_PED_ENUM(PLAYER_PED_ID()),WEAPONTYPE_DLC_RAILGUN) CPRINTLN(DEBUG_SHOOTRANGE,"Player has the Railgun before completing Exile1 or without purchasing it, removing from inventory") REMOVE_WEAPON_FROM_PED(PLAYER_PED_ID(), WEAPONTYPE_DLC_RAILGUN) ENDIF ENDIF CLEANUP_SIMPLE_USE_CONTEXT(sMenuInfo.menuContext) RANGE_CLEAN_UI(sMenuInfo) RELEASE_MINIGAME_COUNTDOWN_UI(sMenuInfo.uiCountdown) #IF IS_DEBUG_BUILD CLEANUP_RANGE_WIDGETS() #ENDIF IF sCoreInfo.bDelayShutdown CDEBUG2LN(DEBUG_SHOOTRANGE, "Range Core has been ordered to delay shutdown. Delaying 10 seconds...") WAIT(10000) ENDIF IF IS_SCREEN_FADED_OUT() DO_SCREEN_FADE_IN(500) ENDIF SET_AUTOSAVE_IGNORES_ON_MISSION_FLAG(FALSE) // ENABLE CHEATS! DISABLE_CHEAT(CHEAT_TYPE_ALL, FALSE) DISABLE_CHEAT(CHEAT_TYPE_GIVE_WEAPONS, FALSE) IF bForceCleanup IF DOES_ENTITY_EXIST(sCoreInfo.oEarMuffs) DELETE_OBJECT(sCoreInfo.oEarMuffs) ENDIF CLEAR_PED_PROP(rangePlayerPed, ANCHOR_HEAD) CLEAR_PED_PROP(rangePlayerPed, ANCHOR_EYES) ENDIF SET_SHOP_IGNORES_KICKING_OFF_CHECKS(GUN_SHOP_01_DT, FALSE) SET_SHOP_IGNORES_KICKING_OFF_CHECKS(GUN_SHOP_11_ID1, FALSE) CPRINTLN(DEBUG_SHOOTRANGE, "Michael's Discounts") CPRINTLN(DEBUG_SHOOTRANGE, "Gold Discount: ", PICK_STRING( IS_BITMASK_AS_ENUM_SET(g_savedGlobals.sRangeData[0].iBools, SRB_ShownFloatingHelp_ShopDiscountGold), "unlocked", "locked" ) ) CPRINTLN(DEBUG_SHOOTRANGE, "Silver Discount: ", PICK_STRING( IS_BITMASK_AS_ENUM_SET(g_savedGlobals.sRangeData[0].iBools, SRB_ShownFloatingHelp_ShopDiscountSilver), "unlocked", "locked" ) ) CPRINTLN(DEBUG_SHOOTRANGE, "Bronze Discount: ", PICK_STRING( IS_BITMASK_AS_ENUM_SET(g_savedGlobals.sRangeData[0].iBools, SRB_ShownFloatingHelp_ShopDiscountBronze), "unlocked", "locked" ) ) CPRINTLN(DEBUG_SHOOTRANGE, "Franklin's Discounts") CPRINTLN(DEBUG_SHOOTRANGE, "Gold Discount: ", PICK_STRING( IS_BITMASK_AS_ENUM_SET(g_savedGlobals.sRangeData[1].iBools, SRB_ShownFloatingHelp_ShopDiscountGold), "unlocked", "locked" ) ) CPRINTLN(DEBUG_SHOOTRANGE, "Silver Discount: ", PICK_STRING( IS_BITMASK_AS_ENUM_SET(g_savedGlobals.sRangeData[1].iBools, SRB_ShownFloatingHelp_ShopDiscountSilver), "unlocked", "locked" ) ) CPRINTLN(DEBUG_SHOOTRANGE, "Bronze Discount: ", PICK_STRING( IS_BITMASK_AS_ENUM_SET(g_savedGlobals.sRangeData[1].iBools, SRB_ShownFloatingHelp_ShopDiscountBronze), "unlocked", "locked" ) ) CPRINTLN(DEBUG_SHOOTRANGE, "Trevor's Discounts") CPRINTLN(DEBUG_SHOOTRANGE, "Gold Discount: ", PICK_STRING( IS_BITMASK_AS_ENUM_SET(g_savedGlobals.sRangeData[2].iBools, SRB_ShownFloatingHelp_ShopDiscountGold), "unlocked", "locked" ) ) CPRINTLN(DEBUG_SHOOTRANGE, "Silver Discount: ", PICK_STRING( IS_BITMASK_AS_ENUM_SET(g_savedGlobals.sRangeData[2].iBools, SRB_ShownFloatingHelp_ShopDiscountSilver), "unlocked", "locked" ) ) CPRINTLN(DEBUG_SHOOTRANGE, "Bronze Discount: ", PICK_STRING( IS_BITMASK_AS_ENUM_SET(g_savedGlobals.sRangeData[2].iBools, SRB_ShownFloatingHelp_ShopDiscountBronze), "unlocked", "locked" ) ) CDEBUG2LN(DEBUG_SHOOTRANGE, "******************* TERMINATING THE SHOOTING RANGE *******************") TERMINATE_THIS_THREAD() ENDPROC /// PURPOSE: /// Removes the player's glasses and ear defenders with or without animations involved. /// PARAMS: /// sCoreInfo - /// sTutorialInfo - /// sRangeInfo - /// RETURNS: /// TRUE when finished removing stuff. FALSE otherwise. FUNC BOOL RANGE_REMOVE_CRANIAL_ACCESSORIES(Range_CoreData & sCoreInfo, Range_TutorialData & sTutorialInfo, Range_RangeData & sRangeInfo) IF GET_CAM_VIEW_MODE_FOR_CONTEXT(CAM_VIEW_MODE_CONTEXT_ON_FOOT) = CAM_VIEW_MODE_FIRST_PERSON CDEBUG2LN(DEBUG_SHOOTRANGE, "Deleting glasses, in first person") CLEAR_PED_PROP(rangePlayerPed, ANCHOR_EYES) IF DOES_ENTITY_EXIST(sCoreInfo.oEarmuffs) CDEBUG2LN(DEBUG_SHOOTRANGE, "Deleting ear muffs, in first person") DELETE_OBJECT(sCoreInfo.oEarmuffs) ENDIF CLEAR_PED_PROP(rangePlayerPed, ANCHOR_HEAD) RETURN TRUE ENDIF IF (GET_SCRIPT_TASK_STATUS(rangePlayerPed, SCRIPT_TASK_PERFORM_SEQUENCE) != PERFORMING_TASK) // This handles all cases of quitting. // If we've been tasked to sequentially play an anim, once it's started, the sequence is done. // Alternatively, if we walk out or something, we never started the sequence. IF (sCoreInfo.iEarsRemoveStart = 0) IF NOT sCoreInfo.bFailed IF NOT DOES_CAM_EXIST(sTutorialInfo.sceneCamera) sTutorialInfo.sceneCamera = CREATE_CAM("DEFAULT_SCRIPTED_CAMERA") ENDIF SET_CAM_COORD(sTutorialInfo.sceneCamera, sRangeInfo.vQuitCamPos) SET_CAM_ROT(sTutorialInfo.sceneCamera, sRangeInfo.vQuitCamOrient) SET_CAM_FOV(sTutorialInfo.sceneCamera, 50.0) SET_CAM_ACTIVE(sTutorialInfo.sceneCamera, TRUE) RENDER_SCRIPT_CAMS(TRUE, FALSE) SET_GAMEPLAY_CAM_RELATIVE_PITCH(0.0) SET_GAMEPLAY_CAM_RELATIVE_HEADING(0.0) ENDIF sCoreInfo.iAnimStartTime = GET_GAME_TIMER() sCoreInfo.iEarsRemoveStart = 315 + GET_GAME_TIMER() sCoreInfo.iEarsRemoveEnd = 920 + GET_GAME_TIMER() ENDIF ENDIF IF (sCoreInfo.iEarsRemoveStart != 0) // Remove glasses. IF GET_GAME_TIMER() >= sCoreInfo.iEarsRemoveStart CDEBUG2LN(DEBUG_SHOOTRANGE, "Deleting glasses") CLEAR_PED_PROP(rangePlayerPed, ANCHOR_EYES) IF DOES_ENTITY_EXIST(sCoreInfo.oEarmuffs) IF NOT IS_ENTITY_VISIBLE(sCoreInfo.oEarmuffs) CDEBUG2LN(DEBUG_SHOOTRANGE, "showing object earmuffs") SET_ENTITY_VISIBLE(sCoreInfo.oEarmuffs, TRUE) ENDIF ENDIF IF NOT IS_PED_INJURED(PLAYER_PED_ID()) CDEBUG2LN(DEBUG_SHOOTRANGE, "clearing head ped prop") CLEAR_PED_PROP(PLAYER_PED_ID(), ANCHOR_HEAD) ENDIF ENDIF IF GET_GAME_TIMER() >= sCoreInfo.iEarsRemoveStart AND GET_GAME_TIMER() < sCoreInfo.iEarsRemoveEnd // time to attach earmuffs to the ped's hand CDEBUG2LN(DEBUG_SHOOTRANGE, "Attaching earmuffs to hand") ATTACH_ENTITY_TO_ENTITY(sCoreInfo.oEarmuffs, PLAYER_PED_ID(), GET_PED_BONE_INDEX(PLAYER_PED_ID(), BONETAG_PH_L_HAND), (<<0,0,0>>), (<<0,0,0>>), TRUE, TRUE, TRUE) ELIF GET_GAME_TIMER() >= sCoreInfo.iEarsRemoveEnd CDEBUG2LN(DEBUG_SHOOTRANGE, "Detaching earmuffs from hand") DETACH_ENTITY(sCoreInfo.oEarmuffs) RETURN TRUE ENDIF ENDIF RETURN FALSE ENDFUNC /// PURPOSE: /// PRocesses the player's final state, where he'll remove glasses, etc. PROC RANGE_MONITOR_END_CUTSCENE(Range_CoreData & sCoreInfo, Range_RoundInfo & sRndInfo, Range_TutorialData & sTutorialInfo, Range_Targets & sTargInfo, Range_MenuData & sMenuInfo, VEHICLE_SAVE_ARGS &vehPlayerCar, Range_RangeData & sRangeInfo) IF NOT sCoreInfo.bTriggeredOutro IF IS_ROUND_FLAG_SET(sRndInfo, ROUND_FAIL_TARGET_CLEANUP) BOOL bAnimFinished = RANGE_REMOVE_CRANIAL_ACCESSORIES(sCoreInfo, sTutorialInfo, sRangeInfo) IF NOT ARE_ANY_TARGET_ENTITIES_MOVING(sRndInfo, sTargInfo.sTargetEntities) AND bAnimFinished CLEAR_ROUND_FLAG(sRndInfo, ROUND_FAIL_TARGET_CLEANUP) // If the palyer had something on his head, we need to have an exit cut to show him taking it off.. IF (sCoreInfo.iStartHeadPropIdx != -1 OR sCoreInfo.iStartFacePropIdx != -1) AND NOT sCoreInfo.bFailed SETTIMERA(0) TASK_FOLLOW_NAV_MESH_TO_COORD(rangePlayerPed, sRangeInfo.vRedressLeaveRangeGoto, PEDMOVEBLENDRATIO_WALK) sCoreInfo.eRangeState = SRM_TRIGGER_EXIT_REDRESS sCoreInfo.bTriggeredOutro = TRUE ELSE Script_Cleanup(sRangeInfo, sTargInfo, sCoreInfo, sMenuInfo, vehPlayerCar) ENDIF ENDIF ELIF CHECK_RANGE_PLAYER_FAIL_CONDITIONS(sCoreInfo, sRangeInfo) sCoreInfo.bFailed = TRUE EXIT_ALL_TARGETS(sTargInfo.sTargetEntities) SET_ROUND_FLAG(sRndInfo, ROUND_FAIL_TARGET_CLEANUP) sCoreInfo.bRestoredWeapons = TRUE RANGE_RESTORE_PLAYER_WEAPONS(sCoreInfo.sWeapons) IF GET_CAM_VIEW_MODE_FOR_CONTEXT(CAM_VIEW_MODE_CONTEXT_ON_FOOT) = CAM_VIEW_MODE_FIRST_PERSON EXIT ENDIF WAIT(1000) ANIM_DATA none ANIM_DATA animDataBlend INT iAnimFlags = 0 animDataBlend.type = APT_SINGLE_ANIM animDataBlend.anim0 = "takeoff_earsdefenders_idle" animDataBlend.dictionary0 = "mini@ears_defenders" animDataBlend.phase0 = 0.0 animDataBlend.rate0 = 1.0 animDataBlend.filter = GET_HASH_KEY("BONEMASK_HEAD_NECK_AND_L_ARM") iAnimFlags += ENUM_TO_INT(AF_SECONDARY) iAnimFlags += ENUM_TO_INT(AF_EXIT_AFTER_INTERRUPTED) animDataBlend.flags = INT_TO_ENUM(ANIMATION_FLAGS, iAnimFlags) TASK_SCRIPTED_ANIMATION(rangePlayerPed, animDataBlend, none, none, SLOW_BLEND_DURATION, SLOW_BLEND_DURATION) CPRINTLN(DEBUG_SHOOTRANGE, "TASKING TO PLAY REMOVAL ANIM!!!!") ENDIF ENDIF ENDPROC /// PURPOSE: /// Sets the player's initial state in the range, clears the area, pins interior. PROC RANGE_SET_INITAL_STATE(Range_CoreData & sCoreInfo, Range_RangeData & sRangeInfo) SET_ROOM_FOR_GAME_VIEWPORT_BY_NAME("V_7_ShootRm") // Clear the area of vehicles and projectiles CLEAR_AREA_OF_VEHICLES(sRangeInfo.vPlayerRootPos, 20) RANGE_STORE_PLAYER_WEAPONS(sCoreInfo.sWeapons) SET_PED_STEALTH_MOVEMENT(rangePlayerPed, FALSE) // We need to stream that interior. IF (sCoreInfo.RangeInterior = NULL) sCoreInfo.RangeInterior = GET_INTERIOR_AT_COORDS(sRangeInfo.vPlayerRootPos) PIN_INTERIOR_IN_MEMORY(sCoreInfo.RangeInterior) ENDIF ENDPROC /// PURPOSE: /// The main update loop for the shooting range PROC UPDATE_MAIN(Range_CoreData & sCoreInfo, Range_RoundInfo & sRndInfo, Range_TutorialData & sTutorialInfo, Range_Targets & sTargInfo, Range_WeaponRounds & sWeaponRndInfo[], Range_RangeData & sRangeInfo, Range_SPTData & sSPTInfo, Range_MenuData & sMenuInfo, VEHICLE_SAVE_ARGS &vehPlayerCar, SHOOTING_RANGE_LAUNCH_DATA & launchData) IF NOT IS_CELLPHONE_DISABLED() DISABLE_CELLPHONE(TRUE) ENDIF INT iTer // This handles player leaving states. RANGE_MONITOR_END_CUTSCENE(sCoreInfo, sRndInfo, sTutorialInfo, sTargInfo, sMenuInfo, vehPlayerCar, sRangeInfo) // Don't allow the player to aim at anyone. SET_PLAYER_LOCKON_RANGE_OVERRIDE(PLAYER_ID(), 0.05) // Block crimes. SUPPRESS_CRIME_THIS_FRAME(PLAYER_ID(), CRIME_DISTURBANCE) SUPPRESS_CRIME_THIS_FRAME(PLAYER_ID(), CRIME_DAMAGE_TO_PROPERTY) SUPPRESS_CRIME_THIS_FRAME(PLAYER_ID(), CRIME_FIREARM_DISCHARGE) SET_SHOP_IGNORES_KICKING_OFF_CHECKS(GUN_SHOP_01_DT, TRUE) SET_SHOP_IGNORES_KICKING_OFF_CHECKS(GUN_SHOP_11_ID1, TRUE) #IF IS_DEBUG_BUILD DRAW_DEBUG_TEXT_2D( GET_STRING_FROM_RANGE_STATE(sCoreInfo.eRangeState), (<< 0.9, 0.2, 0.0 >>) ) #ENDIF SWITCH (sCoreInfo.eRangeState) CASE SRM_INIT CDEBUG2LN(DEBUG_SHOOTRANGE, "SRM_INIT") // Our string table REQUEST_ADDITIONAL_TEXT("S_RANGE", MINIGAME_TEXT_SLOT) // Initialize everything Initialize(sRangeInfo, sRndInfo, sWeaponRndInfo, sSPTInfo, launchData, sTutorialInfo) enumCharacterList eChar eChar = GET_CURRENT_PLAYER_PED_ENUM() IF (eChar = CHAR_MICHAEL) DO_BANK_ACCOUNT_ACTION(BANK_ACCOUNT_MICHAEL, BAA_DEBIT, BAAC_SHOOTING_RANGE, PRICE_OF_RANGE, TRUE) ELIF (eChar = CHAR_TREVOR) DO_BANK_ACCOUNT_ACTION(BANK_ACCOUNT_TREVOR, BAA_DEBIT, BAAC_SHOOTING_RANGE, PRICE_OF_RANGE, TRUE) ELIF (eChar = CHAR_FRANKLIN) DO_BANK_ACCOUNT_ACTION(BANK_ACCOUNT_FRANKLIN, BAA_DEBIT, BAAC_SHOOTING_RANGE, PRICE_OF_RANGE, TRUE) ENDIF CDEBUG2LN(DEBUG_SHOOTRANGE, "SRM_INIT -> SRM_LOAD_AREA_INTRO") sCoreInfo.eRangeState = SRM_LOAD_AREA_INTRO BREAK // Do our Intro cutscene CASE SRM_LOAD_AREA_INTRO SET_PLAYER_CONTROL(PLAYER_ID(), FALSE) // Instead of loading, just set the assets. RANGE_REQUEST_FIRST_STAGE_ASSETS() IF RANGE_HAVE_FIRST_STAGE_ASSETS_LOADED() RANGE_SET_INITAL_STATE(sCoreInfo, sRangeInfo) // Wait for the streaming RESTART_TIMER_AT(sRndInfo.sGenTimer, 0.0) // Okay, first stage done loading, request all. RANGE_STREAM_ALL_ASSETS(sCoreInfo.iAudioStreamTimeout, sMenuInfo) DEBUG_MESSAGE("UpdateMain -- SRM_INIT_DONE (after intro scene)") sCoreInfo.eRangeState = SRM_INIT_DONE ENDIF BREAK // Wait till everything is loaded CASE SRM_INIT_DONE SET_ROOM_FOR_GAME_VIEWPORT_BY_NAME("V_7_ShootRm") IF GET_TIMER_IN_SECONDS(sRndInfo.sGenTimer) > 1.0 IF IS_SCREEN_FADED_OUT() DO_SCREEN_FADE_IN(250) ENDIF FREEZE_ENTITY_POSITION(rangePlayerPed, FALSE) // If the tutorial peds don't exist, don't run the tutorial... BOOL bCanTutorialRun bCanTutorialRun = TRUE IF NOT DOES_ENTITY_EXIST(sTutorialInfo.pedGuy1) OR NOT DOES_ENTITY_EXIST(sTutorialInfo.pedGuy2) OR NOT DOES_ENTITY_EXIST(sTutorialInfo.pedGuy3) bCanTutorialRun = FALSE ENDIF // Do we do our tutorial first? IF NOT g_savedGlobals.sRangeData[0].m_bSeenTutorial AND bCanTutorialRun sTutorialInfo.iTutorialState = 0 SETUP_PLAYER_WEAPONS(WEAPONTYPE_PISTOL, sRndInfo) TASK_SWAP_WEAPON(rangePlayerPed, TRUE) RESTART_TIMER_AT(sRndInfo.sGenTimer, 0.0) g_savedGlobals.sRangeData[0].m_bSeenTutorial = TRUE DEBUG_MESSAGE("UpdateMain -- SRM_TUTORIAL") sCoreInfo.eRangeState = SRM_TUTORIAL ELSE sTutorialInfo.iTutorialState = 0 DEBUG_MESSAGE("UpdateMain -- SRM_NON_TUTORIAL_INTRO") sCoreInfo.eRangeState = SRM_NON_TUTORIAL_INTRO ENDIF ENDIF BREAK CASE SRM_NON_TUTORIAL_INTRO IF RANGE_RUN_NON_TUTORIAL_INTRO(sTutorialInfo, sRndInfo, sCoreInfo, sRangeInfo) AND RANGE_HAVE_ALL_ASSETS_STREAMED(sCoreInfo.iAudioStreamTimeout, sMenuInfo) DEBUG_MESSAGE("UpdateMain -- SRM_PICK_WEAPON") SET_MISSION_FLOW_FLAG_STATE(FLOWFLAG_GUNRANGE_TUTORIAL_COMPLETED, TRUE) CANCEL_COMMUNICATION(TEXT_SRANGE_UNLOCK) SET_STATE_OF_CLOSEST_DOOR_OF_TYPE(V_ILEV_GC_DOOR01, sRangeInfo.vDoorPos, TRUE, 0.0) // lock the door now that we've started sCoreInfo.eRangeState = SRM_PICK_WEAPON ENDIF BREAK // Weapon pick menu CASE SRM_PICK_WEAPON IF IS_PC_VERSION() DISABLE_CONTROL_ACTION(FRONTEND_CONTROL, INPUT_FRONTEND_PAUSE) ENDIF DISABLE_CONTROL_ACTION(FRONTEND_CONTROL, INPUT_FRONTEND_PAUSE_ALTERNATE) // B*2239651 - Disabling pause_alternate during end screens (to avoid clash when exiting leaderboards) // Make sure the transition is active. RANGE_UI_TRIGGER_TRANSITION(sMenuInfo, TRUE) IF NOT IS_TIMER_STARTED(sMenuInfo.tQuitDelay) RESTART_TIMER_NOW(sMenuInfo.tQuitDelay) EXIT ELIF GET_TIMER_IN_SECONDS(sMenuInfo.tQuitDelay) < 0.5 EXIT ENDIF // Check if they want to unlock all rounds #IF IS_DEBUG_BUILD IF IS_DEBUG_KEY_JUST_PRESSED(KEY_W, KEYBOARD_MODIFIER_NONE, "Unlock all rounds.") IF NOT CHEAT_ARE_ALL_ROUNDS_UNLOCKED(sCoreInfo) CHEAT_UNLOCK_ALL_WEAPONS(sCoreInfo) DEBUG_MESSAGE("ReadWepMenuInput -- Cheat entered, all rounds unlocked.") // Mess with our menu selections. sMenuInfo.curMenu = RANGE_MENU_WEAPCAT sMenuInfo.catMenu.iCurElement = 0 sMenuInfo.weapMenu.iCurElement = -1 sMenuInfo.chalMenu.iCurElement = -1 sMenuInfo.weapMenu.iNumElements = 0 SETUP_RANGE_MENU_CONTROLS(sMenuInfo.menuContext, TRUE, DEFAULT, TRUE) // Go through all rounds and set them to active. INT index FOR index = 0 TO (ENUM_TO_INT(NUM_WEAPON_CATS) - 1) sMenuInfo.catMenu.menuElement[index].bActive = TRUE ENDFOR FOR index = 0 TO MAX_WEAPONS_PER_CAT - 1 sMenuInfo.weapMenu.menuElement[index].bActive = TRUE ENDFOR FOR index = 0 TO (ENUM_TO_INT(NUM_WEAPON_CHALLS) - 1) sMenuInfo.chalMenu.menuElement[index].bActive = TRUE ENDFOR ENDIF ENDIF #ENDIF //Put categories and guns that qualify for round 4 here. IF INT_TO_ENUM(RANGE_WEAPON_CATEGORY, sMenuInfo.catMenu.iCurElement) = WEAPCAT_RAILGUN AND sCoreInfo.bCGtoNG sMenuInfo.chalMenu.menuElement[WEAPCHAL_4].bActive = IS_ROUND_CHALLENGE_REQ_MET(sWeaponRndInfo[INT_TO_ENUM(RANGE_WEAPON_CATEGORY, sMenuInfo.catMenu.iCurElement)].sChallenges[WEAPCHAL_4].eUnlockReq) OR CHEAT_ARE_ALL_ROUNDS_UNLOCKED(sCoreInfo) sMenuInfo.chalMenu.iNumElements = 4 ELSE sMenuInfo.chalMenu.menuElement[WEAPCHAL_4].bActive = FALSE sMenuInfo.chalMenu.iNumElements = 3 ENDIF // Having an issue keeping the room streamed in. SET_ROOM_FOR_GAME_VIEWPORT_BY_NAME("V_7_ShootRm") IF NOT (sMenuInfo.bInitMenu) sMenuInfo.bInitMenu = TRUE INIT_MAIN_MENU(sCoreInfo, sMenuInfo, sWeaponRndInfo) ENDIF // Update our menus. They are compartmentalized. THREE_STATE_RETVAL tempRet tempRet = UPDATE_MAIN_MENU(sCoreInfo, sRndInfo, sWeaponRndInfo, sMenuInfo) IF (tempRet = RETVAL_TRUE) // We've just been given a complete round description in rndStarting. Set this up as our current playing. RANGE_SetupRound(sCoreInfo, sRndInfo, sTargInfo, sRangeInfo) IF (sCoreInfo.eRangeLoc = RANGELOC_PILLBOX_HILL) SET_STATIC_EMITTER_ENABLED("LOS_SANTOS_AMMUNATION_GUN_RANGE", FALSE) ELSE SET_STATIC_EMITTER_ENABLED("SE_AMMUNATION_CYPRESS_FLATS_GUN_RANGE", FALSE) ENDIF CANCEL_TIMER(sMenuInfo.tQuitDelay) // Turn off transition effect. RANGE_UI_TRIGGER_TRANSITION(sMenuInfo, FALSE) // Set our next state (to begin countdown) sCoreInfo.eRangeState = SRM_COUNT_DWN_INIT ELIF (tempRet = RETVAL_FALSE) // We've backed out of the first menu. Need to display Are you sure you want to quit screen? INIT_SIMPLE_USE_CONTEXT(sMenuInfo.menuContext, FALSE, FALSE, TRUE, TRUE) ADD_SIMPLE_USE_CONTEXT_INPUT(sMenuInfo.menuContext, "FE_HLP29", FRONTEND_CONTROL, INPUT_FRONTEND_ACCEPT) ADD_SIMPLE_USE_CONTEXT_INPUT(sMenuInfo.menuContext, "FE_HLP31", FRONTEND_CONTROL, INPUT_FRONTEND_CANCEL) SET_SIMPLE_USE_CONTEXT_FULLSCREEN(sMenuInfo.menuContext, TRUE) CANCEL_TIMER(sMenuInfo.tQuitDelay) sCoreInfo.eRangeState = SRM_EXIT_CONF ENDIF BREAK CASE SRM_EXIT_CONF UPDATE_UI_EXIT(TRUE) IF IS_CONTROL_JUST_RELEASED(FRONTEND_CONTROL, INPUT_FRONTEND_ACCEPT) // GET_CONTROL_INSTRUCTIONAL_BUTTONS_STRING(FRONTEND_CONTROL, INPUT_FRONTEND_ACCEPT) // Turn off transition effect. RANGE_UI_TRIGGER_TRANSITION(sMenuInfo, FALSE) sCoreInfo.eRangeState = SRM_START_EXIT_CUTSCENE ENDIF IF IS_CONTROL_JUST_RELEASED(FRONTEND_CONTROL, INPUT_FRONTEND_CANCEL) //GET_CONTROL_INSTRUCTIONAL_BUTTONS_STRING(FRONTEND_CONTROL, INPUT_FRONTEND_CANCEL) // Set us to have a previous button depending on our destination... IF (sMenuInfo.curMenu != RANGE_MENU_WEAPCAT) SETUP_RANGE_MENU_CONTROLS(sMenuInfo.menuContext, FALSE, DEFAULT, TRUE) sCoreInfo.eRangeState = SRM_PICK_WEAPON ELSE SETUP_RANGE_MENU_CONTROLS(sMenuInfo.menuContext, TRUE, sMenuInfo.catMenu.menuElement[sMenuInfo.catMenu.iCurElement].bActive, TRUE) sCoreInfo.eRangeState = SRM_PICK_WEAPON ENDIF SET_SIMPLE_USE_CONTEXT_MINIGAME_ATTACHED(sMenuInfo.menuContext) ENDIF BREAK CASE SRM_START_EXIT_CUTSCENE CDEBUG2LN(DEBUG_SHOOTRANGE, "SRM_START_EXIT_CUTSCENE started, script exiting") IF NOT IS_ROUND_FLAG_SET(sRndInfo, ROUND_FAIL_TARGET_CLEANUP) SET_ROUND_FLAG(sRndInfo, ROUND_FAIL_TARGET_CLEANUP) // Turn off transition effect. RANGE_UI_TRIGGER_TRANSITION(sMenuInfo, FALSE) IF GET_CAM_VIEW_MODE_FOR_CONTEXT(CAM_VIEW_MODE_CONTEXT_ON_FOOT) <> CAM_VIEW_MODE_FIRST_PERSON SEQUENCE_INDEX leaveSeq OPEN_SEQUENCE_TASK(leaveSeq) TASK_TURN_PED_TO_FACE_COORD(NULL, sRangeInfo.vRemoveGlassesFacing) ANIM_DATA none ANIM_DATA animDataBlend INT iAnimFlags iAnimFlags = 0 animDataBlend.type = APT_SINGLE_ANIM animDataBlend.anim0 = "takeoff_earsdefenders_idle" animDataBlend.dictionary0 = "mini@ears_defenders" animDataBlend.phase0 = 0.0 animDataBlend.rate0 = 1.0 animDataBlend.filter = GET_HASH_KEY("BONEMASK_HEAD_NECK_AND_L_ARM") iAnimFlags += ENUM_TO_INT(AF_SECONDARY) iAnimFlags += ENUM_TO_INT(AF_EXIT_AFTER_INTERRUPTED) animDataBlend.flags = INT_TO_ENUM(ANIMATION_FLAGS, iAnimFlags) TASK_SCRIPTED_ANIMATION(NULL, animDataBlend, none, none, SLOW_BLEND_DURATION, SLOW_BLEND_DURATION) CLOSE_SEQUENCE_TASK(leaveSeq) TASK_PERFORM_SEQUENCE(rangePlayerPed, leaveSeq) CLEAR_SEQUENCE_TASK(leaveSeq) ENDIF ENDIF BREAK // Tutorial if we have too CASE SRM_TUTORIAL IF UPDATE_TUTORIAL(sTutorialInfo, sCoreInfo, sTargInfo.sTargetEntities, sRndInfo, sRangeInfo.sRangeGrid, sSPTInfo, sRangeInfo) AND RANGE_HAVE_ALL_ASSETS_STREAMED(sCoreInfo.iAudioStreamTimeout, sMenuInfo) ROUND_CLEANUP(sRangeInfo.sRangeGrid, sRndInfo, sTargInfo, sSPTInfo.sSptQueue, sWeaponRndInfo, sMenuInfo, TRUE) SET_WIDESCREEN_BORDERS(FALSE, 0) // Clear floaty help. CLEAR_FLOATING_HELP(FLOATING_HELP_TEXT_ID_2) SET_MISSION_FLOW_FLAG_STATE(FLOWFLAG_GUNRANGE_TUTORIAL_COMPLETED, TRUE) CANCEL_COMMUNICATION(TEXT_SRANGE_UNLOCK) SET_STATE_OF_CLOSEST_DOOR_OF_TYPE(V_ILEV_GC_DOOR01, sRangeInfo.vDoorPos, TRUE, 0.0) // lock the door now that we've started // Return to the menu DEBUG_MESSAGE("UpdateMain -- SRM_PICK_WEAPON") sCoreInfo.eRangeState = SRM_PICK_WEAPON EXIT ENDIF BREAK // Countdown. CASE SRM_COUNT_DWN_INIT // Set the player looking toward the range, do it only once. IF NOT IS_BITMASK_AS_ENUM_SET(sRndInfo.iRoundFlags, ROUND_WIPE_CAM) SET_BITMASK_AS_ENUM(sRndInfo.iRoundFlags, ROUND_WIPE_CAM) IF NOT IS_POINT_IN_ANGLED_AREA(GET_ENTITY_COORDS(PLAYER_PED_ID()), sRangeInfo.vAngledAreaChk1, sRangeInfo.vAngledAreaChk2, 4) SET_ENTITY_COORDS(PLAYER_PED_ID(), sRangeInfo.vPlayerRootPos) SET_ENTITY_HEADING(PLAYER_PED_ID(), sRangeInfo.fPlayerRootHead) CDEBUG2LN(DEBUG_SHOOTRANGE, "SRM_COUNT_DWN_INIT Setting coords and heading because we're at a crap view") ENDIF RANGE_SET_PLAYER_CAM_DOWNRANGE(sRangeInfo) ENDIF // Short wait here... IF GET_TIMER_IN_SECONDS(sRndInfo.sGenTimer) >= 0.35 // Give player control back SET_PLAYER_CONTROL(PLAYER_ID(), TRUE) CLEAR_ROUND_FLAG(sRndInfo, ROUND_CAN_DISPLAY_TARGET_HELP) CLEAR_PRINTS() RESTART_TIMER_AT(sRndInfo.sGenTimer, 0.0) IF NOT IS_PLAYER_DEAD(PLAYER_ID()) SET_PED_USING_ACTION_MODE(PLAYER_PED_ID(), TRUE) CDEBUG2LN(DEBUG_SHOOTRANGE, "Setting ped into action mode for shooting range") ENDIF CLEAR_RANK_REDICTION_DETAILS() RANGE_SP_CLEANUP_SOCIAL_CLUB_LEADERBOARD() sCoreInfo.ePredictedRnd = RT_INVALID //Print Multiplier help IF sRndInfo.eWeaponCat = WEAPCAT_PISTOL PRINT_HELP("SH_MULT_HG") ELIF sRndInfo.eWeaponCat = WEAPCAT_SMG OR sRndInfo.eWeaponCat = WEAPCAT_AR OR sRndInfo.eWeaponCat = WEAPCAT_LIGHT_MG PRINT_HELP("SH_MULT_AUTO") ELIF sRndInfo.eWeaponCat = WEAPCAT_MINIGUN PRINT_HELP("SH_MULT_HEAVY") ENDIF CLEAR_AREA(GET_ENTITY_COORDS(PLAYER_PED_ID()), 100, TRUE) sCoreInfo.eRangeState = SRM_COUNT_DWN ENDIF BREAK CASE SRM_COUNT_DWN IF GET_TIMER_IN_SECONDS(sRndInfo.sGenTimer) > 2.25 SET_PLAYER_CONTROL(PLAYER_ID(), TRUE) RENDER_SCRIPT_CAMS(FALSE, TRUE) ENDIF HIDE_HUD_COMPONENT_THIS_FRAME(NEW_HUD_RETICLE) RANGE_DISABLE_SHOOTING() DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_NEXT_CAMERA) // When the cd ui is done, move us on! IF UPDATE_MINIGAME_COUNTDOWN_UI(sMenuInfo.uiCountdown, TRUE, FALSE, TRUE, 3, FALSE, TRUE) RESET_MULTIPLIER(sRndInfo.sMPData) CLEAR_ROUND_FLAG(sRndInfo, ROUND_TARGET_HIT) // 2144283 - clear target hit CLEAR_ROUND_FLAG(sRndInfo, ROUND_SHOT_FIRED) // 2144283 - clear shot fired sRndInfo.iTargetsHitThisExplosion = 0 // 2144283 - clear hits this explosion sCoreInfo.eRangeState = SRM_SHOOT ENDIF BREAK //// MAIN STATE RIGHT HERE CASE SRM_SHOOT // Draw our hud DRAW_RANGE_HUD(sRndInfo, sWeaponRndInfo, sSPTInfo) IF IS_BITMASK_AS_ENUM_SET(sRndInfo.iRoundFlags, ROUND_WIPE_CAM) CLEAR_BITMASK_AS_ENUM(sRndInfo.iRoundFlags, ROUND_WIPE_CAM) ENDIF // Always draw the movie. DRAW_SCALEFORM_MOVIE(sMenuInfo.uiCountdown.uiCountdown, 0.5, 0.5, 1.0, 1.0, 255, 255, 255, 100) // If we're more than 1 second into the round, we're now able to display floating help. IF IS_TIMER_STARTED(sRndInfo.sTimeLeft) IF GET_TIMER_IN_SECONDS(sRndInfo.sTimeLeft) > 1.0 SET_ROUND_FLAG(sRndInfo, ROUND_CAN_DISPLAY_TARGET_HELP) // Also, draw the reticle here. SHOW_HUD_COMPONENT_THIS_FRAME(NEW_HUD_RETICLE) ENDIF ENDIF // Check if times up. IF IS_ROUND_OVER(sRndInfo, sTargInfo.sTargetEntities) // Going to force a reload here, just for good looks. CLEAR_HELP() STOP_FIRE_IN_RANGE(GET_ENTITY_COORDS(PLAYER_PED_ID()), 100) // Target slide sounds may persist to here. Shut them down. STOP_TARGET_SOUNDS(sTargInfo.sTargetEntities, sRndInfo.iMaxTargets) sCoreInfo.bSkipPressed = TRUE RESTART_TIMER_AT(sRndInfo.sGenTimer, 0.0) // Calculate our time bonus, if any. ROUND_CALCULATE_TIME_BONUS(sRndInfo) // What's our reason for the round ending? // And did we pass the minimum score? INT iScore, iScoreReq BOOL bPassed iScore = sRndInfo.sScoreData.iP1Score iScoreReq = GET_MEDAL_SCORE_REQUIREMENT(sWeaponRndInfo[sRndInfo.eWeaponCat].sChallenges[sRndInfo.eChallengeType], RRM_BRONZE) IF NOT IS_ROUND_FLAG_SET(sRndInfo, ROUND_NO_TIME_BONUS) iScore += sRndInfo.sScoreData.iTimeBonus ENDIF CDEBUG2LN(DEBUG_SHOOTRANGE, "IF IS_ROUND_OVER checking scores for messaging, iScore=", iScore, ", iScoreReq=", iScoreReq) bPassed = iScore >= iScoreReq SET_ROUND_OVER_MESSAGE(sRndInfo, sMenuInfo, bPassed) IF NOT IS_PLAYER_DEAD(PLAYER_ID()) SET_PED_USING_ACTION_MODE(PLAYER_PED_ID(), FALSE) IF IS_PED_IN_COVER(PLAYER_PED_ID()) CLEAR_PED_TASKS(PLAYER_PED_ID()) ENDIF ENDIF SET_PLAYER_CONTROL(PLAYER_ID(), FALSE) IF NOT bPassed PLAY_SOUND_FRONTEND(-1, "LOSER", "HUD_AWARDS") ELSE PLAY_SOUND_FRONTEND(-1, "SHOOTING_RANGE_ROUND_OVER", "HUD_AWARDS") ENDIF DEBUG_MESSAGE("UpdateMain -- SRM_COMPLETE_MSG") sCoreInfo.eRangeState = SRM_COMPLETE_MSG EXIT ENDIF // We can hit the back button to leave if we're not cleaning up. Update us pressing back IF NOT IS_ROUND_FLAG_SET(sRndInfo, ROUND_FAIL_TARGET_CLEANUP) // Don't display help if we're drawing another important help. IF NOT IS_THIS_HELP_MESSAGE_BEING_DISPLAYED("SHR_EXIT_HELP") AND NOT IS_THIS_HELP_MESSAGE_BEING_DISPLAYED("SHR_DEST_LOWHIT") AND NOT IS_THIS_HELP_MESSAGE_BEING_DISPLAYED("SH_MULT_HG") AND NOT IS_THIS_HELP_MESSAGE_BEING_DISPLAYED("SH_MULT_AUTO") AND NOT IS_THIS_HELP_MESSAGE_BEING_DISPLAYED("SH_MULT_HEAVY") AND NOT IS_THIS_HELP_MESSAGE_BEING_DISPLAYED("SHR_H_LEAVE") PRINT_HELP_FOREVER("SHR_EXIT_HELP") ENDIF IF IS_CONTROL_JUST_PRESSED(FRONTEND_CONTROL, INPUT_CONTEXT) OR IS_DISABLED_CONTROL_JUST_PRESSED(FRONTEND_CONTROL, INPUT_CONTEXT) PLAY_RANGE_SOUND("QUIT", TRUE) sCoreInfo.ePrevState = SRM_SHOOT PAUSE_RANGE_ROUND(sCoreInfo, sRndInfo, sMenuInfo) ENDIF ENDIF // Update Time Remaining UPDATE_ROUND_TIME_LEFT(sRndInfo) // Check what targets need to be created PROCESS_TARGET_CREATION(sRndInfo, sTargInfo.sTargetEntities, sRangeInfo) // Check what needs to be done this frame! PROCESS_TARGET_ACTIONS(sRndInfo, sTargInfo, sRangeInfo) // Process general round needs PROCESS_ROUND_GENERAL(sRndInfo) IF sRndInfo.eWeaponCat <> WEAPCAT_RAILGUN // Go through all of our targets INT iTargetsHitThisIter iTargetsHitThisIter = sRndInfo.iTargetHitsCached // Set equal to the cached hits BOOL bCheckShotgunHits bCheckShotgunHits = FALSE // We're not checking shotgun hits unless the buffer has expired INT iGameTimer iGameTimer = GET_GAME_TIMER() // Check that the buffer has expired IF iGameTimer > sRndInfo.iTargetHitsBuffer sRndInfo.iTargetHitsCached = 0 bCheckShotgunHits = TRUE ENDIF REPEAT sRndInfo.iMaxTargets iTer // Only update this target if it is occupied IF CHECK_TARGET_STATUS(sTargInfo.sTargetEntities[iTer], TS_CREATED) AND NOT CHECK_TARGET_STATUS(sTargInfo.sTargetEntities[iTer], TS_DESTROYED) IF UPDATE_TARGET_ENTITY(sTargInfo.sTargetEntities[iTer], sRangeInfo.sRangeGrid, sRndInfo, sSPTInfo, sRangeInfo) iTargetsHitThisIter += 1 sRndInfo.iTargetHitsBuffer = iGameTimer + k_RANGE_TARGET_HIT_BUFFER bCheckShotgunHits = FALSE CDEBUG2LN(DEBUG_SHOOTRANGE, "SRM_SHOOT We hit another target, increased iTargetsHitThisIter to ", iTargetsHitThisIter) CDEBUG2LN(DEBUG_SHOOTRANGE, "sRndInfo.iTargetHitsCached = ", sRndInfo.iTargetHitsCached) CDEBUG2LN(DEBUG_SHOOTRANGE, "bCheckShotgunHits = ", bCheckShotgunHits) CDEBUG2LN(DEBUG_SHOOTRANGE, "iGameTimer = ", iGameTimer) CDEBUG2LN(DEBUG_SHOOTRANGE, "sRndInfo.iTargetHitsBuffer = ", sRndInfo.iTargetHitsBuffer) ENDIF ENDIF ENDREPEAT IF NOT bCheckShotgunHits // We're not submitting results for points, cache off the new number of targets hit. sRndInfo.iTargetHitsCached = iTargetsHitThisIter ENDIF CLEAR_PED_LAST_WEAPON_DAMAGE(rangePlayerPed) // If we're in the shotgun challenge, and we've destroyed targets this loop, count all and SPT draw. IF (sRndInfo.sScoreData.eScoreStyle = ROUNDSCORE_DESTRUCTION) IF (iTargetsHitThisIter <> 0) ADD_SCORE_TO_SPT(iTargetsHitThisIter, HUD_COLOUR_GREEN, sSPTInfo) ENDIF ELIF (sRndInfo.sScoreData.eScoreStyle = ROUNDSCORE_DESTRUCTION_W_BONUS) // If we're minigun 3, and we've hit some back rows, go ahead and add to SPT. INT iMult BOOL bIsMinigunChallenge bIsMinigunChallenge = (sRndInfo.eRoundType = RT_MINIGUN_CHAL_1 OR sRndInfo.eRoundType = RT_MINIGUN_CHAL_2 OR sRndInfo.eRoundType = RT_MINIGUN_CHAL_3) IF NOT bIsMinigunChallenge AND NOT bCheckShotgunHits EXIT ENDIF IF bIsMinigunChallenge iMult = 100 ELSE iMult = 1 ENDIF // Handles hitting up to 6 simultaneous targets... impossible? to get more than that. IF (iTargetsHitThisIter = 1) ADD_SCORE_TO_SPT(1 * iMult, HUD_COLOUR_GREY, sSPTInfo) sRndInfo.sScoreData.iP1Score += 1 * iMult RANGE_INCREMENT_ZONE_HITS(sRndInfo, 4) ELIF (iTargetsHitThisIter = 2) ADD_SCORE_TO_SPT(CONST_SHOTTY_2TARGS * iMult, HUD_COLOUR_GREEN, sSPTInfo) sRndInfo.sScoreData.iP1Score += CONST_SHOTTY_2TARGS * iMult RANGE_INCREMENT_ZONE_HITS(sRndInfo, 3) ELIF (iTargetsHitThisIter = 3) ADD_SCORE_TO_SPT(CONST_SHOTTY_3TARGS * iMult, HUD_COLOUR_BLUE, sSPTInfo) sRndInfo.sScoreData.iP1Score += CONST_SHOTTY_3TARGS * iMult RANGE_INCREMENT_ZONE_HITS(sRndInfo, 2) ELIF (iTargetsHitThisIter = 4) ADD_SCORE_TO_SPT(CONST_SHOTTY_4TARGS * iMult, HUD_COLOUR_RED, sSPTInfo) sRndInfo.sScoreData.iP1Score += CONST_SHOTTY_4TARGS * iMult RANGE_INCREMENT_ZONE_HITS(sRndInfo, 1) ELIF (iTargetsHitThisIter = 5) ADD_SCORE_TO_SPT(CONST_SHOTTY_5TARGS * iMult, HUD_COLOUR_YELLOW, sSPTInfo) sRndInfo.sScoreData.iP1Score += CONST_SHOTTY_5TARGS * iMult RANGE_INCREMENT_ZONE_HITS(sRndInfo, 1) ELIF (iTargetsHitThisIter = 6) ADD_SCORE_TO_SPT(CONST_SHOTTY_6TARGS * iMult, HUD_COLOUR_WHITE, sSPTInfo) sRndInfo.sScoreData.iP1Score += CONST_SHOTTY_6TARGS * iMult RANGE_INCREMENT_ZONE_HITS(sRndInfo, 1) ENDIF // ENDIF ELIF (sRndInfo.sScoreData.eScoreStyle = ROUNDSCORE_MINIGUN) // If we are to increment the multiplier IF sRndInfo.sMPData.bIncrementMP // Set the timer back to MAX_MINIGUN_COMBO_FRAMES RESET_RANGE_MINIGUN_COMBO_TIMER(sRndInfo.sMPData) IF GET_RANGE_MINIGUN_BLOCK_TIMER(sRndInfo.sMPData) > 0 sRndInfo.sMPData.bIncrementMP = FALSE sRndInfo.iTotalShots++ ENDIF ENDIF UPDATE_RANGE_MINIGUN_COMBO_TIMERS(sRndInfo.sMPData) ENDIF // We can check for another hit now. CLEAR_ROUND_FLAG(sRndInfo, ROUND_TARGET_HIT) // Shotguns don't get multipliers. IF (sRndInfo.eWeaponCat = WEAPCAT_SHOTGUN) sRndInfo.sMPData.bIncrementMP = FALSE ENDIF // After checking all the entities, do we need to increase our mp? IF (sRndInfo.sMPData.bIncrementMP) // Increment our multiplier INCREMENT_MULTIPLIER(sRndInfo.sMPData) sRndInfo.sMPData.bIncrementMP = FALSE RESET_RANGE_MINIGUN_BLOCK_TIMER(sRndInfo.sMPData) CDEBUG2LN(DEBUG_SHOOTRANGE, "Incrementing iTotalShots because (sRndInfo.sMPData.bIncrementMP) :: ", sRndInfo.iTotalShots) ELIF IS_ROUND_FLAG_SET(sRndInfo, ROUND_SHOT_FIRED) AND sRndInfo.sScoreData.eScoreStyle <> ROUNDSCORE_MINIGUN // Reset the multiplier, unless we're an auto weapon and haven't consumed the grace period. IF NEED_RESET_MULTIPLIER(sRndInfo) RESET_MULTIPLIER(sRndInfo.sMPData) ENDIF CDEBUG2LN(DEBUG_SHOOTRANGE, "Incrementing iTotalShots because IS_ROUND_FLAG_SET(sRndInfo, ROUND_SHOT_FIRED) :: ", sRndInfo.iTotalShots) ELIF GET_RANGE_MINIGUN_COMBO_TIMER(sRndInfo.sMPData) <= 0 AND sRndInfo.sScoreData.eScoreStyle = ROUNDSCORE_MINIGUN RESET_MULTIPLIER(sRndInfo.sMPData) ENDIF IF IS_ROUND_FLAG_SET(sRndInfo, ROUND_SHOT_FIRED) sRndInfo.iTotalShots++ ENDIF // Gotta clamp accuracy for shotguns... RANGE_ACCURACY_CLAMP(sRndInfo) CLEAR_ROUND_FLAG(sRndInfo, ROUND_SHOT_FIRED) ELSE REPEAT sRndInfo.iMaxTargets iTer // Only update this target if it is occupied IF CHECK_TARGET_STATUS(sTargInfo.sTargetEntities[iTer], TS_CREATED) AND NOT CHECK_TARGET_STATUS(sTargInfo.sTargetEntities[iTer], TS_DESTROYED) IF UPDATE_TARGET_ENTITY(sTargInfo.sTargetEntities[iTer], sRangeInfo.sRangeGrid, sRndInfo, sSPTInfo, sRangeInfo) sRndInfo.iTargetsHitThisExplosion += 1 ENDIF ENDIF ENDREPEAT CLEAR_PED_LAST_WEAPON_DAMAGE(rangePlayerPed) // We can check for another hit now. CLEAR_ROUND_FLAG(sRndInfo, ROUND_TARGET_HIT) IF IS_EXPLOSION_IN_SPHERE(EXP_TAG_DONTCARE, GET_ENTITY_COORDS(PLAYER_PED_ID()), 50) AND NOT IS_ROUND_FLAG_SET(sRndInfo, ROUND_SHOT_FIRED) sRndInfo.iTotalShots++ SET_ROUND_FLAG(sRndInfo, ROUND_SHOT_FIRED) ELSE IF NOT IS_EXPLOSION_IN_SPHERE(EXP_TAG_DONTCARE, GET_ENTITY_COORDS(PLAYER_PED_ID()), 50) AND IS_ROUND_FLAG_SET(sRndInfo, ROUND_SHOT_FIRED) IF (sRndInfo.iTargetsHitThisExplosion = 1) ADD_SCORE_TO_SPT(1, HUD_COLOUR_GREY, sSPTInfo) sRndInfo.sScoreData.iP1Score += 1 RANGE_INCREMENT_ZONE_HITS(sRndInfo, 4) ELIF (sRndInfo.iTargetsHitThisExplosion = 2) ADD_SCORE_TO_SPT(CONST_SHOTTY_2TARGS, HUD_COLOUR_GREEN, sSPTInfo) sRndInfo.sScoreData.iP1Score += CONST_SHOTTY_2TARGS RANGE_INCREMENT_ZONE_HITS(sRndInfo, 3) ELIF (sRndInfo.iTargetsHitThisExplosion = 3) ADD_SCORE_TO_SPT(CONST_SHOTTY_3TARGS, HUD_COLOUR_BLUE, sSPTInfo) sRndInfo.sScoreData.iP1Score += CONST_SHOTTY_3TARGS RANGE_INCREMENT_ZONE_HITS(sRndInfo, 2) ELIF (sRndInfo.iTargetsHitThisExplosion = 4) ADD_SCORE_TO_SPT(CONST_SHOTTY_4TARGS, HUD_COLOUR_RED, sSPTInfo) sRndInfo.sScoreData.iP1Score += CONST_SHOTTY_4TARGS RANGE_INCREMENT_ZONE_HITS(sRndInfo, 1) ELIF (sRndInfo.iTargetsHitThisExplosion = 5) ADD_SCORE_TO_SPT(CONST_SHOTTY_5TARGS, HUD_COLOUR_YELLOW, sSPTInfo) sRndInfo.sScoreData.iP1Score += CONST_SHOTTY_5TARGS RANGE_INCREMENT_ZONE_HITS(sRndInfo, 1) ELIF (sRndInfo.iTargetsHitThisExplosion = 6) ADD_SCORE_TO_SPT(CONST_SHOTTY_6TARGS, HUD_COLOUR_WHITE, sSPTInfo) sRndInfo.sScoreData.iP1Score += CONST_SHOTTY_6TARGS RANGE_INCREMENT_ZONE_HITS(sRndInfo, 1) ENDIF CLEAR_ROUND_FLAG(sRndInfo, ROUND_SHOT_FIRED) sRndInfo.iTargetsHitThisExplosion = 0 ENDIF ENDIF RANGE_ACCURACY_CLAMP(sRndInfo) ENDIF BREAK CASE SRM_COMPLETE_MSG STOP_FIRE_IN_RANGE(GET_ENTITY_COORDS(PLAYER_PED_ID()), 100) CLEAR_AREA(GET_ENTITY_COORDS(PLAYER_PED_ID()), 100, TRUE) // Draw the hud for a bit longer. DRAW_RANGE_HUD(sRndInfo, sWeaponRndInfo, sSPTInfo, TRUE) // Remove the weapon from the player IF NOT IS_PED_INJURED(rangePlayerPed) SET_CURRENT_PED_WEAPON(rangePlayerPed, WEAPONTYPE_UNARMED) ENDIF // Okay, need to add the medal feed a little after the message comes up. IF IS_TIMER_STARTED(sMenuInfo.uiSplashText.movieTimer) IF GET_TIMER_IN_SECONDS(sMenuInfo.uiSplashText.movieTimer) > 1.0 IF NOT IS_RANGE_MENU_FLAG_SET(sMenuInfo, RMF_SHOWED_MEDAL_SPLASH) RANGE_ROUND_MEDAL eMedalToGive eMedalToGive = GET_MEDAL_AWARD(sRndInfo.sScoreData.iP1Score + sRndInfo.sScoreData.iTimeBonus, sWeaponRndInfo[sRndInfo.eWeaponCat].sChallenges[sRndInfo.eChallengeType]) sMenuInfo.iMedalFeed = UPDATE_RANGE_MEDAL_TOAST(eMedalToGive, sRndInfo) SET_RANGE_MENU_FLAG(sMenuInfo, RMF_SHOWED_MEDAL_SPLASH) ENDIF ENDIF ENDIF IF UPDATE_RANGE_SPLASH(sMenuInfo) // Turn on the radio! IF (sCoreInfo.eRangeLoc = RANGELOC_PILLBOX_HILL) SET_STATIC_EMITTER_ENABLED("LOS_SANTOS_AMMUNATION_GUN_RANGE", TRUE) ELSE SET_STATIC_EMITTER_ENABLED("SE_AMMUNATION_CYPRESS_FLATS_GUN_RANGE", TRUE) ENDIF IF (sRndInfo.sScoreData.eScoreStyle = ROUNDSCORE_BULLSEYE) CDEBUG2LN(DEBUG_SHOOTRANGE, "UpdateMain -- Applying time bonus...") // Actually add the bonus. ROUND_GIVE_TIME_BONUS(sRndInfo) ENDIF // If we cleared the round, with a better score than our last, // as Michael or Trevor, add some special ability power. -- #411002 enumCharacterList tempChar tempChar = GET_CURRENT_PLAYER_PED_ENUM() IF (tempChar = CHAR_TREVOR) OR (tempChar = CHAR_MICHAEL) IF IS_ROUND_CLEARED(sRndInfo, sWeaponRndInfo[sRndInfo.eWeaponCat].sChallenges[sRndInfo.eChallengeType]) IF (sRndInfo.sScoreData.iP1Score > GET_RANGE_SP_HIGH_SCORE(ePlayerChar, sRndInfo.eRoundType)) SPECIAL_ABILITY_CHARGE_NORMALIZED(GET_PLAYER_INDEX(), 0.1, TRUE) ELSE SPECIAL_ABILITY_CHARGE_NORMALIZED(GET_PLAYER_INDEX(), 0.05, TRUE) ENDIF ENDIF ENDIF // Do something with numbers! SET_ROUND_ZONE_HITS(sRndInfo.eRoundType, sRndInfo.sScoreData.iP1Score, sRndInfo.iZ1Hits, sRndInfo.iZ2Hits, sRndInfo.iZ3Hits, sRndInfo.iZ4Hits) // Check if we beat the high schore IF SAVE_PLAYER_MEDAL(sWeaponRndInfo[sRndInfo.eWeaponCat].sChallenges[sRndInfo.eChallengeType], sRndInfo) // Move on. CDEBUG2LN(DEBUG_SHOOTRANGE, "UpdateMain -- SRM_MEDAL_TOAST") sCoreInfo.eRangeState = SRM_MEDAL_TOAST //SRM_PICK_WEAPON ELSE // Move on. CDEBUG2LN(DEBUG_SHOOTRANGE, "UpdateMain -- SRM_PICK_WEAPON") sCoreInfo.eRangeState = SRM_PICK_WEAPON ENDIF CHECK_OUR_SCORE_AGAINST_HIGH_SCORE(sRndInfo.sScoreData, sRndInfo) // Are we setting the next round to unlocked? CHECK_UNLOCK_NEXT_ROUND(sRndInfo, sWeaponRndInfo[sRndInfo.eWeaponCat].sChallenges[sRndInfo.eChallengeType]) // Start our predictions... IF IS_PLAYER_ONLINE() RANGE_SP_PRE_READ_LBD(sCoreInfo.lbdWrite, sRndInfo, sWeaponRndInfo[sRndInfo.eWeaponCat].sChallenges[sRndInfo.eChallengeType]) sCoreInfo.ProcessPrediction = TRUE sCoreInfo.bOnlineForPrediction = TRUE sCoreInfo.ePredictedRnd = sRndInfo.eRoundType ELSE // Track this, we may need to make an emergency predition... sCoreInfo.bOnlineForPrediction = FALSE sCoreInfo.ProcessPrediction = FALSE sCoreInfo.ePredictedRnd = sRndInfo.eRoundType ENDIF // Return to the menu CLEAR_RANGE_MENU_FLAG(sMenuInfo, RMF_SHOWED_MEDAL_SPLASH) IF (sMenuInfo.iMedalFeed != -1) THEFEED_REMOVE_ITEM(sMenuInfo.iMedalFeed) sMenuInfo.iMedalFeed = -1 ENDIF ROUND_CLEANUP(sRangeInfo.sRangeGrid, sRndInfo, sTargInfo, sSPTInfo.sSptQueue, sWeaponRndInfo, sMenuInfo) INIT_CATEGORY_MENU(sCoreInfo, sMenuInfo) INIT_WEAPONS_MENU(sCoreInfo, sRndInfo.eWeaponCat, sMenuInfo) INIT_CHALLENGES_MENU(sWeaponRndInfo, sCoreInfo, sRndInfo.eWeaponCat, sMenuInfo) INIT_RANGE_MENU(sMenuInfo.uiPlacement) sCoreInfo.bSkipPressed = TRUE SET_PLAYER_CONTROL(PLAYER_ID(), FALSE) RESTART_TIMER_AT(sRndInfo.sGenTimer, 0.0) // Trigger a save, need to restore weapons first... RANGE_RESTORE_PLAYER_WEAPONS(sCoreInfo.sWeapons) SET_AUTOSAVE_IGNORES_ON_MISSION_FLAG(TRUE) MAKE_AUTOSAVE_REQUEST() HANDLE_RANGE_SCORE_AWARDS() ENDIF BREAK CASE SRM_MEDAL_TOAST // Can use this as an update state if need be. CDEBUG2LN(DEBUG_SHOOTRANGE, "UpdateMain -- SRM_PICK_WEAPON") sCoreInfo.eRangeState = SRM_PICK_WEAPON //SRM_PICK_WEAPON BREAK CASE SRM_EXIT UPDATE_UI_EXIT() IF IS_CONTROL_JUST_RELEASED(FRONTEND_CONTROL, INPUT_FRONTEND_ACCEPT) //CASE GET_CONTROL_INSTRUCTIONAL_BUTTONS_STRING(FRONTEND_CONTROL, INPUT_FRONTEND_ACCEPT) // Make sure he's at the range. This is so cutscenes line up. SET_ENTITY_COORDS(PLAYER_PED_ID(), sRangeInfo.vPlayerRootPos) SET_ENTITY_HEADING(PLAYER_PED_ID(), sRangeInfo.fPlayerRootHead) SET_GAME_PAUSED(FALSE) IF NOT IS_PLAYER_DEAD(PLAYER_ID()) SET_PED_USING_ACTION_MODE(PLAYER_PED_ID(), FALSE) ENDIF // Remove the weapon from the player IF NOT IS_PED_INJURED(rangePlayerPed) SET_CURRENT_PED_WEAPON(rangePlayerPed, WEAPONTYPE_UNARMED) ENDIF // Trigger a save, need to restore weapons first... RANGE_RESTORE_PLAYER_WEAPONS(sCoreInfo.sWeapons) // Return to the menu STOP_TARGET_SOUNDS(sTargInfo.sTargetEntities, sRndInfo.iMaxTargets) ROUND_CLEANUP(sRangeInfo.sRangeGrid, sRndInfo, sTargInfo, sSPTInfo.sSptQueue, sWeaponRndInfo, sMenuInfo, DEFAULT, TRUE) INIT_CATEGORY_MENU(sCoreInfo, sMenuInfo) INIT_WEAPONS_MENU(sCoreInfo, sRndInfo.eWeaponCat, sMenuInfo) INIT_CHALLENGES_MENU(sWeaponRndInfo, sCoreInfo, sRndInfo.eWeaponCat, sMenuInfo) INIT_RANGE_MENU(sMenuInfo.uiPlacement) sCoreInfo.bSkipPressed = TRUE IF (sRndInfo.iSFX_Warning != -1) STOP_SOUND(sRndInfo.iSFX_Warning) RELEASE_SOUND_ID(sRndInfo.iSFX_Warning) sRndInfo.iSFX_Warning = -1 ENDIF // Need to tell the leaderboard system not to write anything here, because we quit mid round. // We do this by faking being online... sCoreInfo.bOnlineForPrediction = TRUE sCoreInfo.ProcessPrediction = FALSE sCoreInfo.ePredictedRnd = RT_INVALID sCoreInfo.lbdWrite.eRoundType = RT_INVALID // Re-add radio. IF (sCoreInfo.eRangeLoc = RANGELOC_PILLBOX_HILL) SET_STATIC_EMITTER_ENABLED("LOS_SANTOS_AMMUNATION_GUN_RANGE", TRUE) ELSE SET_STATIC_EMITTER_ENABLED("SE_AMMUNATION_CYPRESS_FLATS_GUN_RANGE", TRUE) ENDIF CDEBUG2LN(DEBUG_SHOOTRANGE, "UpdateMain -- SRM_PICK_WEAPON") sCoreInfo.eRangeState = SRM_PICK_WEAPON EXIT ENDIF IF IS_CONTROL_JUST_RELEASED(FRONTEND_CONTROL, INPUT_FRONTEND_CANCEL) //CASE GET_CONTROL_INSTRUCTIONAL_BUTTONS_STRING(FRONTEND_CONTROL, INPUT_FRONTEND_CANCEL) PAUSE_RANGE_ROUND(sCoreInfo, sRndInfo, sMenuInfo, FALSE) ENDIF BREAK CASE SRM_TRIGGER_EXIT_REDRESS // Okay, we need to have the player exit the range. IF (TIMERA() > 1000) // Warp the player. SET_ENTITY_COORDS(rangePlayerPed, sRangeInfo.vRedressPos, FALSE) SET_ENTITY_HEADING(rangePlayerPed, sRangeInfo.fRedressHead) SET_STATE_OF_CLOSEST_DOOR_OF_TYPE(V_ILEV_GC_DOOR01, sRangeInfo.vDoorPos, FALSE, 0.0) // Set the camera. IF NOT DOES_CAM_EXIST(sTutorialInfo.sceneCamera) sTutorialInfo.sceneCamera = CREATE_CAM("DEFAULT_SCRIPTED_CAMERA") ENDIF SET_CAM_COORD(sTutorialInfo.sceneCamera, sRangeInfo.vRedressCamStart) SET_CAM_ROT(sTutorialInfo.sceneCamera, sRangeInfo.vRedressCamStartOrient) SET_CAM_FOV(sTutorialInfo.sceneCamera, 42.3427) SET_CAM_ACTIVE(sTutorialInfo.sceneCamera, TRUE) RENDER_SCRIPT_CAMS(TRUE, FALSE) SET_CAM_PARAMS(sTutorialInfo.sceneCamera, sRangeInfo.vRedressCamInterp, sRangeInfo.vRedressCamInterpOrient, 42.3427, 2500) CLEAR_PED_PROP(rangePlayerPed, ANCHOR_HEAD) CLEAR_PED_PROP(rangePlayerPed, ANCHOR_EYES) // Restore the player's props. RESTORE_PLAYER_PED_VARIATIONS(rangePlayerPed) // Now set the player to walk out. IF (sCoreInfo.eRangeLoc = RANGELOC_CYPRESS_FLATS) SEQUENCE_INDEX siExit OPEN_SEQUENCE_TASK(siExit) TASK_GO_STRAIGHT_TO_COORD(NULL, <<826.8521, -2160.5791, 28.6190>>, PEDMOVEBLENDRATIO_WALK) TASK_GO_STRAIGHT_TO_COORD(NULL, <<826.0770, -2158.7080, 28.6190>>, PEDMOVEBLENDRATIO_WALK) CLOSE_SEQUENCE_TASK(siExit) TASK_PERFORM_SEQUENCE(rangePlayerPed, siExit) CLEAR_SEQUENCE_TASK(siExit) ELSE TASK_FOLLOW_NAV_MESH_TO_COORD(rangePlayerPed, sRangeInfo.vRedressGoto, PEDMOVEBLENDRATIO_WALK) ENDIF SET_PED_CONFIG_FLAG(rangePlayerPed, PCF_OpenDoorArmIK, TRUE) SET_PED_RESET_FLAG(rangePlayerPed, PRF_SearchForClosestDoor, TRUE) SETTIMERA(0) sCoreInfo.eRangeState = SRM_REDRESS_STAGE_2 ENDIF BREAK CASE SRM_REDRESS_STAGE_2 SET_PED_RESET_FLAG(rangePlayerPed, PRF_SearchForClosestDoor, TRUE) IF TIMERA() > 2500 // Shut the door in the corner SET_STATE_OF_CLOSEST_DOOR_OF_TYPE(V_ILEV_GC_DOOR01, sRangeInfo.vDoorPos, TRUE, 0.0) SET_CAM_COORD(sTutorialInfo.sceneCamera, sRangeInfo.vRedressCamEnd) SET_CAM_ROT(sTutorialInfo.sceneCamera, sRangeInfo.vRedressCamEndOrient) SET_CAM_ACTIVE(sTutorialInfo.sceneCamera, TRUE) RENDER_SCRIPT_CAMS(TRUE, FALSE) sCoreInfo.eRangeState = SRM_REDRESS_EXIT ENDIF BREAK CASE SRM_REDRESS_EXIT SET_STATE_OF_CLOSEST_DOOR_OF_TYPE(V_ILEV_GC_DOOR01, sRangeInfo.vDoorPos, FALSE, 0.0) IF NOT IS_TRANSITION_ACTIVE() CDEBUG2LN(DEBUG_SHOOTRANGE, "STOP_RENDERING_SCRIPT_CAMS_USING_CATCH_UP(FALSE, 20.0)") STOP_RENDERING_SCRIPT_CAMS_USING_CATCH_UP(FALSE, 20.0) ENDIF Script_Cleanup(sRangeInfo, sTargInfo, sCoreInfo, sMenuInfo, vehPlayerCar) BREAK ENDSWITCH ENDPROC /// PURPOSE: /// Saves the player vehicle to a position based on the range location we started near. /// PARAMS: /// sCoreRangeInfo - /// vehPlayerCar - PROC RANGE_SAVE_VEHICLE( Range_CoreData & sCoreRangeInfo, VEHICLE_SAVE_ARGS & vehPlayerCar ) VECTOR vSavePosition FLOAT fSaveHeading BOOL bNeedLargeSpace IF DOES_ENTITY_EXIST( vehPlayerCar.playerVehicle ) bNeedLargeSpace = MINIGAME_DOES_VEHICLE_NEED_LARGE_RESPAWN_SPACE( vehPlayerCar.playerVehicle ) ENDIF IF sCoreRangeInfo.eRangeLoc = RANGELOC_PILLBOX_HILL vSavePosition = (<< 15.4041, -1125.9149, 27.7096 >>) fSaveHeading = 90.5811 ELIF sCoreRangeInfo.eRangeLoc = RANGELOC_CYPRESS_FLATS vSavePosition = PICK_VECTOR(bNeedLargeSpace, (<< 810.0622, -2137.9922, 28.2980 >>), (<< 782.8192, -2120.5012, 28.3352 >>) ) fSaveHeading = PICK_FLOAT(bNeedLargeSpace, 0.0589, 355.0583) ELSE CERRORLN( DEBUG_SHOOTRANGE, "RANGE_SAVE_VEHICLE :: RangeLocation is wrong, sCoreRangeInfo.eRangeLoc=", sCoreRangeInfo.eRangeLoc ) ENDIF IF ODDJOB_SAVE_VEHICLE_AND_WARP( vehPlayerCar, vSavePosition, TRUE, fSaveHeading ) CDEBUG2LN(DEBUG_SHOOTRANGE, "RANGE_SAVE_VEHICLE :: vehPlayerCar Saved :)") ELSE CDEBUG2LN(DEBUG_SHOOTRANGE, "RANGE_SAVE_VEHICLE :: vehPlayerCar Not Saved :(") ENDIF ENDPROC // Initialisation and the script loop SCRIPT (SHOOTING_RANGE_LAUNCH_DATA launchData) CDEBUG2LN(DEBUG_SHOOTRANGE, "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Range SP First Post %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") // Variables we'll need: Range_CoreData sCoreRangeInfo // The info about the shooting range as a whole Range_RoundInfo sRoundInfo // Info per round Range_SPTData sSPTData // Our SPT scroll, probably going to flash. Range_RangeData sRangeData // The range is constant, this should become constant one day. Range_Targets sTargets // Target information. Range_WeaponRounds sRoundUnlocks[NUM_WEAPON_CATS] // Our unlock info for weapons and challenges Range_TutorialData sTutorialInfo // Information about the tutorial. Range_MenuData sMenuInfo VEHICLE_SAVE_ARGS vehPlayerCar sCoreRangeInfo.eRangeLoc = launchData.eLocation ePlayerChar = GET_CURRENT_PLAYER_PED_ENUM() RANGE_CHECK_DLC(sCoreRangeInfo) SET_SHOOTING_RANGE_UNSAVED_BITFLAG(SRB_RangeInSession) STORE_PLAYER_PED_VARIATIONS(PLAYER_PED_ID(), TRUE) // DISABLE CHEATS! DISABLE_CHEAT(CHEAT_TYPE_ALL, TRUE) DISABLE_CHEAT(CHEAT_TYPE_GIVE_WEAPONS, TRUE) DISABLE_COMPOSITE_SHOTGUN_DECALS(TRUE) // TRACE_NATIVE_COMMAND("SET_EXCLUSIVE_INPUT") TEXT_LABEL_23 mMocapName = "NONE" MINIGAME_DISPLAY_MISSION_TITLE(ENUM_TO_INT(MINIGAME_SHOOTING_RANGE)) RANGE_SAVE_VEHICLE( sCoreRangeInfo, vehPlayerCar ) // Handles the player being busted or arrested, or if the player // jumps into Multiplayer from Singleplayer – ensures the script // gets cleaned up properly under the correct circumstances IF (HAS_FORCE_CLEANUP_OCCURRED(DEFAULT_FORCE_CLEANUP_FLAGS | FORCE_CLEANUP_FLAG_SP_TO_MP | FORCE_CLEANUP_FLAG_REPEAT_PLAY)) Script_Cleanup(sRangeData, sTargets, sCoreRangeInfo, sMenuInfo, vehPlayerCar, TRUE) ENDIF IF NOT IS_PED_INJURED(PLAYER_PED_ID()) SET_PLAYER_WANTED_LEVEL(PLAYER_ID(), 0) SET_PLAYER_WANTED_LEVEL_NOW(PLAYER_ID()) ENDIF // Store some tutorial data. RANGE_STORE_TUTORIAL_INFO(launchData, sTutorialInfo) // Any initialisation (generally, only mission scripts should set // the mission flag to TRUE) SET_MISSION_FLAG(TRUE) // Disable the character selector DISABLE_SELECTOR() CLEAR_HELP() CLEAR_PRINTS() #IF IS_DEBUG_BUILD enumCharacterList ePlayer = GET_CURRENT_PLAYER_PED_ENUM() CDEBUG2LN(DEBUG_SHOOTRANGE, "Player Character is ", PICK_STRING(ePlayer = CHAR_MICHAEL, "CHAR_MICHAEL", PICK_STRING(ePlayer = CHAR_FRANKLIN, "CHAR_FRANKLIN", PICK_STRING(ePlayer = CHAR_TREVOR, "CHAR_TREVOR", "Unknown playabled ped")))) #ENDIF // The script loop WHILE (TRUE) rangePlayerPed = PLAYER_PED_ID() HIDE_UI_DURING_RANGE(sCoreRangeInfo.eRangeState) // Don't this if we're on or past the menu. IF (sCoreRangeInfo.eRangeState < SRM_PICK_WEAPON) UPDATE_MISSION_NAME_DISPLAYING(mMocapName, default, default, default, TRUE) ELSE g_eMissionTitleState = MTS_DONE ENDIF IF NOT IS_SELECTOR_DISABLED() DISABLE_SELECTOR() ENDIF #IF IS_DEBUG_BUILD // Explanation: If UPDATE_RANGE_WIDGETS returns true, that means we're debugging a target or something. // Anything going on in the general shooting range will just get in the way. IF NOT UPDATE_RANGE_WIDGETS(sMenuInfo, sCoreRangeInfo.eRangeState) #ENDIF // Make sure Law is not going to hurt us SET_PLAYER_IS_ALLOWED_TO_SHOOT_IN_SHOP(GUN_SHOP_01_DT, TRUE) // Handle ped flags and whatnot on the player. Every frame. RANGE_UPDATE_PED_ABILITIES() // Maintain the script – perform per-frame functionality UPDATE_MAIN(sCoreRangeInfo, sRoundInfo, sTutorialInfo, sTargets, sRoundUnlocks, sRangeData, sSPTData, sMenuInfo, vehPlayerCar, launchData) #IF IS_DEBUG_BUILD // Debug Key: Check for Pass (not for Minigmes) IF (IS_KEYBOARD_KEY_JUST_PRESSED(KEY_S)) RANGE_UI_TRIGGER_TRANSITION(sMenuInfo, FALSE) DELETE_OBJECT(sCoreRangeInfo.oEarmuffs) CLEAR_PED_PROP(rangePlayerPed, ANCHOR_HEAD) CLEAR_PED_PROP(rangePlayerPed, ANCHOR_EYES) Script_Cleanup(sRangeData, sTargets, sCoreRangeInfo, sMenuInfo, vehPlayerCar) ENDIF // Debug Key: Check for Fail (not for Minigames) IF (IS_KEYBOARD_KEY_JUST_PRESSED(KEY_F)) RANGE_UI_TRIGGER_TRANSITION(sMenuInfo, FALSE) DELETE_OBJECT(sCoreRangeInfo.oEarmuffs) CLEAR_PED_PROP(rangePlayerPed, ANCHOR_HEAD) CLEAR_PED_PROP(rangePlayerPed, ANCHOR_EYES) g_savedGlobals.sRangeData[0].m_bSeenTutorial = FALSE Script_Cleanup(sRangeData, sTargets, sCoreRangeInfo, sMenuInfo, vehPlayerCar) ENDIF //Debug Key: Toggle CGtoNG IF (IS_KEYBOARD_KEY_JUST_PRESSED(KEY_NUMPAD1)) IF sCoreRangeInfo.bCGtoNG = TRUE sCoreRangeInfo.bCGtoNG = FALSE sMenuInfo.catMenu.iNumElements -= 1 sMenuInfo.curMenu = RANGE_MENU_WEAPCAT sMenuInfo.catMenu.iCurElement = 0 sMenuInfo.weapMenu.iNumElements = 0 ELSE sCoreRangeInfo.bCGtoNG = TRUE sMenuInfo.catMenu.iNumElements += 1 ENDIF sRoundInfo.eWeaponCat = INT_TO_ENUM(RANGE_WEAPON_CATEGORY, sMenuInfo.catMenu.iCurElement) INIT_CHALLENGES_MENU(sRoundUnlocks, sCoreRangeInfo, sRoundInfo.eWeaponCat, sMenuInfo) ENDIF #ENDIF #IF IS_DEBUG_BUILD ENDIF #ENDIF WAIT(0) ENDWHILE ENDSCRIPT