USING "rage_builtins.sch" USING "globals.sch" USING "commands_camera.sch" USING "commands_hud.sch" USING "commands_misc.sch" USING "commands_pad.sch" USING "commands_script.sch" USING "commands_replay.sch" USING "flow_help_messages.sch" USING "cutscene_control.sch" USING "cutscene_private.sch" USING "finance_control_public.sch" USING "trains_control_public.sch" USING "script_launch_control.sch" USING "socialclub_leaderboard.sch" USING "Minigame_private.sch" USING "family_controller.sch" USING "slow_zone_private.sch" USING "comms_control_private.sch" USING "selector_public.sch" USING "flow_reset_game.sch" USING "achievement_public.sch" USING "player_ped_public.sch" USING "noirEffects.sch" USING "socialclub_leaderboard.sch" // Keith 15/7/13: Joblist maintenance for cross-session invites to join MP to players in SP allowing them to accept on the phone USING "net_mission_joblist.sch" // Kenneth 30/08/13: Moving property system from the building_controller to main in order to reduce script store in GTA Online USING "properties_private.sch" USING "ply_to_ply_calls.sch" // ***************************************************************************************** // ***************************************************************************************** // ***************************************************************************************** // // MISSION NAME : main.sc // AUTHOR : Keith // DESCRIPTION : Initial setup for the game. // Launches 'Initial'. // Launches 'Debug'. // Endlessly performs the scripting main loop. // // ***************************************************************************************** // ***************************************************************************************** // ***************************************************************************************** BOOL bGauntletSuppressed = FALSE BOOL bJimmySUVSuppressed = FALSE BOOL bDoProfileSettingCheckForLastGen = FALSE BOOL bProfileSettingCheckForLastGenDone = FALSE INT iGameTime INT iOneSecondTimer = 0 INT iFiveSecondTimer = 0 //DirectorTravelLocation eDirectorLocation = INT_TO_ENUM(DirectorTravelLocation, 0) //Cover help state. BOOL bDisplayingCoverHelpLastFrame = FALSE INT iFramesCoverHelpCheckPassed = 0 //Vehicle duck help state. BOOL bDisplayingVehDuckHelpLastFrame = FALSE INT iFramesVehDuckHelpCheckPassed = 0 INT iVehIdDuckHelpCurrent INT iVehIdDuckHelpLast INT iTimeVehDuckHelpLastDisplayed = 0 ScriptLaunchVars sScriptLaunchVars FlowHelpMessageVars sFlowHelpMessageVars FriendControllerVars sFriendControllerVars SlowZoneLocalVars sSlowZoneVars ActivityFeedLocalVars sActivityFeedVars DLC_WEAPON_UNLOCK_VARS sDLCWeaponVars NOIR_DATA noirData #IF IS_DEBUG_BUILD WIDGET_GROUP_ID main_widget #ENDIF // =========================================================================================================== // Cleanup // =========================================================================================================== // PURPOSE: Ensures that the script gets a chance to cleanup under specific circumstances (ie: moving from SP to MP) // PROC SCRIPT_CLEANUP() CPRINTLN(DEBUG_INIT_SP, "Main thread cleaning up.") SET_GAME_BOOTED_TO_SP(FALSE) NOIR_FORCE_OFF(noirData) CLEANUP_CUTSCENE_CONTROL() RESET_PLATFORM_UPGRADE_LB_CHECK_STRUCT(platformUpgradeLBCheckSP) TERMINATE_THIS_THREAD() ENDPROC // ----------------------------------------------------------------------------------------------------------- /// PURPOSE: Outputs the #defines for this script image configuration to the log files DEBUGONLY PROC OUTPUT_SCRIPT_IMAGE_CONFIGURATION_TO_CONSOLE_LOG() CPRINTLN(DEBUG_INIT, "-----------------------------------") CPRINTLN(DEBUG_INIT, "SCRIPT IMAGE CONFIGURATION DETAILS:") IF IS_XBOX360_VERSION() CPRINTLN(DEBUG_INIT, " XBOX 360") ENDIF IF IS_SCARLETT_VERSION() CPRINTLN(DEBUG_INIT, " XBOX Series S/X") ELIF IS_DURANGO_VERSION() CPRINTLN(DEBUG_INIT, " XBOX ONE") ENDIF IF IS_PS3_VERSION() CPRINTLN(DEBUG_INIT, " PS3") ENDIF IF IS_PROSPERO_VERSION() CPRINTLN(DEBUG_INIT, " PS5") ELIF IS_ORBIS_VERSION() CPRINTLN(DEBUG_INIT, " PS4") ENDIF #IF IS_DEBUG_BUILD CPRINTLN(DEBUG_INIT, " DEBUG") #ENDIF #IF IS_FINAL_BUILD CPRINTLN(DEBUG_INIT, " FINAL") #ENDIF #IF IS_JAPANESE_BUILD CPRINTLN(DEBUG_INIT, " JAPANESE") #ENDIF IF NOT IS_XBOX360_VERSION() CPRINTLN(DEBUG_INIT, " ......not xbox 360") ENDIF IF NOT IS_XBOX_PLATFORM() CPRINTLN(DEBUG_INIT, " ......not xbox one or XBSX") ENDIF IF NOT IS_PS3_VERSION() CPRINTLN(DEBUG_INIT, " ......not ps3") ENDIF IF NOT IS_PLAYSTATION_PLATFORM() CPRINTLN(DEBUG_INIT, " ......not ps4 or PS5") ENDIF #IF NOT IS_JAPANESE_BUILD CPRINTLN(DEBUG_INIT, " ......not japanese") #ENDIF CPRINTLN(DEBUG_INIT, "-----------------------------------") ENDPROC /// PURPOSE: Monitor unexpected termination of core script threads. DEBUGONLY PROC RUN_CORE_SP_THREAD_CHECKS() IF NOT g_bMagDemoActive AND NOT g_bInMultiplayer AND GET_INDEX_OF_CURRENT_LEVEL() = LEVEL_GTA5 IF GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(HASH("flow_controller")) < 1 SCRIPT_ASSERT("Core SP script thread \"flow_controller\" has terminated unexpectedly. Bug BenR.") ENDIF IF GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(HASH("blip_controller")) < 1 SCRIPT_ASSERT("Core SP script thread \"blip_controller\" has terminated unexpectedly. Bug *Default Levels*") ENDIF ENDIF ENDPROC /// PURPOSE: Requests the 'Initial' script, waits for it to stream in, then launches it PROC REQUEST_AND_LAUNCH_INITIAL_SCRIPT_WITH_WAIT() STRING initialScriptName = "initial" REQUEST_SCRIPT(initialScriptName) WHILE NOT (HAS_SCRIPT_LOADED(initialScriptName)) REQUEST_SCRIPT(initialScriptName) WAIT(0) ENDWHILE START_NEW_SCRIPT(initialScriptName, FRIEND_STACK_SIZE) SET_SCRIPT_AS_NO_LONGER_NEEDED(initialScriptName) ENDPROC PROC MAINTAIN_GAUNTLET_SUPPRESSION() IF NOT bGauntletSuppressed IF GET_MISSION_COMPLETE_STATE(SP_HEIST_FINALE_2_INTRO) IF GET_MISSION_FLOW_INT_VALUE(FLOWINT_HEIST_CHOICE_FINALE) = HEIST_CHOICE_FINALE_TRAFFCONT AND NOT GET_MISSION_COMPLETE_STATE(SP_HEIST_FINALE_2A) IF (NOT IS_MISSION_AVAILABLE(SP_HEIST_FINALE_PREP_C1) AND NOT GET_MISSION_COMPLETE_STATE(SP_HEIST_FINALE_PREP_C1)) AND (NOT IS_MISSION_AVAILABLE(SP_HEIST_FINALE_PREP_C2) AND NOT GET_MISSION_COMPLETE_STATE(SP_HEIST_FINALE_PREP_C2)) AND (NOT IS_MISSION_AVAILABLE(SP_HEIST_FINALE_PREP_C3) AND NOT GET_MISSION_COMPLETE_STATE(SP_HEIST_FINALE_PREP_C3)) CPRINTLN(DEBUG_MISSION, "Suppressing Gauntlet model for Big score prep C missions. From ", GET_THIS_SCRIPT_NAME()) bGauntletSuppressed = TRUE SET_VEHICLE_MODEL_IS_SUPPRESSED(GAUNTLET, TRUE) ENDIF ENDIF ENDIF ELSE IF IS_MISSION_AVAILABLE(SP_HEIST_FINALE_PREP_C1) AND IS_MISSION_AVAILABLE(SP_HEIST_FINALE_PREP_C2) AND IS_MISSION_AVAILABLE(SP_HEIST_FINALE_PREP_C3) bGauntletSuppressed = FALSE CPRINTLN(DEBUG_MISSION, "Unsuppressed Gauntlet model. From ", GET_THIS_SCRIPT_NAME()) SET_VEHICLE_MODEL_IS_SUPPRESSED(GAUNTLET, FALSE) ENDIF ENDIF ENDPROC PROC MAINTAIN_JIMMY_VEHICLE_SUPPRESSED_CHECKS() IF NOT bJimmySUVSuppressed IF g_savedGlobals.sFlow.isGameflowActive IF NOT GET_MISSION_COMPLETE_STATE(SP_MISSION_TREVOR_1) CPRINTLN(DEBUG_FLOW, "Main thread suppressed Jimmy's SUV model until Trevor1 is completed or gameflow is inactive.") SET_VEHICLE_MODEL_IS_SUPPRESSED(BJXL, TRUE) bJimmySUVSuppressed = TRUE ENDIF ENDIF ELSE IF GET_MISSION_COMPLETE_STATE(SP_MISSION_TREVOR_1) OR NOT g_savedGlobals.sFlow.isGameflowActive CPRINTLN(DEBUG_FLOW, "Main thread unsuppressed Jimmy's SUV model as Trevor1 is completed or gameflow is inactive.") SET_VEHICLE_MODEL_IS_SUPPRESSED(BJXL, FALSE) bJimmySUVSuppressed = FALSE ENDIF ENDIF ENDPROC PROC MANAGE_SUB_CRUSH_DEPTH() //Fix for B* 1772703: Player can exit sub below -200 m and gets teleported to the surface VEHICLE_INDEX viTemp = GET_VEHICLE_PED_IS_USING(PLAYER_PED_ID()) IF DOES_ENTITY_EXIST(viTemp) IF IS_VEHICLE_MODEL(viTemp,SUBMERSIBLE) OR IS_VEHICLE_MODEL(viTemp,CHERNOBOG) Vector pos = GET_ENTITY_COORDS(PLAYER_PED_ID()) IF IS_VEHICLE_FUCKED(viTemp) OR (pos.z <-190 AND IS_ENTITY_IN_WATER(PLAYER_PED_ID())) EXPLODE_PED_HEAD(PLAYER_PED_ID()) ENDIF ENDIF ENDIF ENDPROC PROC MAINTAIN_MISSION_RECORDING_CLEANUP_CHECKS() IF REPLAY_SYSTEM_HAS_REQUESTED_A_SCRIPT_CLEANUP() // #IF IS_DEBUG_BUILD // OR IS_DEBUG_KEY_PRESSED(KEY_END, KEYBOARD_MODIFIER_SHIFT, "Do recoring system script cleanup test.") // #ENDIF CPRINTLN(DEBUG_CLEANUP_SP, "The mission recording system has requested scripts clean up.") g_bForceCleaupVehgenForRecordingPlayback = TRUE g_bForceCleaupShopsForRecordingPlayback = TRUE RUN_GENERAL_SCRIPT_CLEANUP(TRUE) RESET_GAMEFLOW() //Disabling trains for bug:2341432 SET_RANDOM_TRAINS(false) DELETE_ALL_TRAINS() // #2173929 Informing code to block invites while in the R*Editor. Allows net code to display // a message to explain why accepting the invite isn't transitioning. Block must be cleaned // up on SP starting back up. NETWORK_BLOCK_INVITES(TRUE) CPRINTLN(DEBUG_CLEANUP_SP, "Flagging that the recording system is now active.") g_bRockstarEditorActive = TRUE SET_SCRIPTS_HAVE_CLEANED_UP_FOR_REPLAY_SYSTEM() CPRINTLN(DEBUG_CLEANUP_SP, "Scripts have cleaned up for recording system.") ENDIF ENDPROC PROC MAINTAIN_FIRST_PERSON_COVER_HELP() BOOL bBaseCheckPassed = FALSE BOOL bSafeToDisplay = FALSE BOOL bDisplayingCoverHelpThisFrame = FALSE // Mission or flow specific checks. IF IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_STORY) IF MISSION_FLOW_GET_RUNNING_MISSION() != SP_MISSION_PROLOGUE IF g_savedGlobals.sFlowCustom.iFirstPersonCoverHelpCountMission < 3 bBaseCheckPassed = TRUE ENDIF ENDIF ELIF g_savedGlobals.sFlowCustom.iFirstPersonCoverHelpCountFlow < 3 IF IS_FLOW_HELP_QUEUE_EMPTY() bBaseCheckPassed = TRUE ENDIF ENDIF // Checks to run against flow and mission help. IF bBaseCheckPassed IF NOT IS_PED_INJURED(PLAYER_PED_ID()) IF GET_FOLLOW_PED_CAM_VIEW_MODE() = CAM_VIEW_MODE_FIRST_PERSON IF IS_PED_IN_COVER(PLAYER_PED_ID()) IF IS_PLAYER_CONTROL_ON(PLAYER_ID()) IF NOT IS_CUTSCENE_PLAYING() IF IS_SCREEN_FADED_IN() IF NOT IS_WARNING_MESSAGE_ACTIVE() IF (NOT IS_HELP_MESSAGE_BEING_DISPLAYED()) OR IS_THIS_HELP_MESSAGE_BEING_DISPLAYED("FP_COVER_HLP") bSafeToDisplay = TRUE ENDIF ENDIF ENDIF ENDIF ENDIF ENDIF ENDIF ENDIF ENDIF // Wait for 10 consecutive safe frames before allowing the help to display. // This will give scripts a chance to queue up back to back help messages // without this help interrupting. IF bSafeToDisplay iFramesCoverHelpCheckPassed++ IF iFramesCoverHelpCheckPassed > 10 DISPLAY_HELP_TEXT_THIS_FRAME("FP_COVER_HLP", FALSE) bDisplayingCoverHelpThisFrame = TRUE ENDIF ELIF iFramesCoverHelpCheckPassed > 0 CDEBUG2LN(DEBUG_FLOW_HELP, " No longer safe to display. Resetting safe frame count.") iFramesCoverHelpCheckPassed = 0 ENDIF // Check if we've just finished displaying help. IF bDisplayingCoverHelpLastFrame AND NOT bDisplayingCoverHelpThisFrame IF IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_STORY) g_savedGlobals.sFlowCustom.iFirstPersonCoverHelpCountMission++ CPRINTLN(DEBUG_FLOW_HELP, " Finished displaying first person cover help while on mission. New count is ", g_savedGlobals.sFlowCustom.iFirstPersonCoverHelpCountMission, ".") ELSE g_savedGlobals.sFlowCustom.iFirstPersonCoverHelpCountFlow++ CPRINTLN(DEBUG_FLOW_HELP, " Finished displaying first person cover help while off mission. New count is ", g_savedGlobals.sFlowCustom.iFirstPersonCoverHelpCountFlow, ".") ENDIF ENDIF // Update last frame variable. bDisplayingCoverHelpLastFrame = bDisplayingCoverHelpThisFrame ENDPROC // TODO 1925330 PROC MAINTAIN_VEHICLE_DUCK_HELP() BOOL bSafeToDisplay = FALSE BOOL bDisplayingVehDuckHelpThisFrame = FALSE VEHICLE_INDEX vehCurrent // Display condition checks. IF g_savedGlobals.sFlowCustom.iVehDuckHelpCount < 4 IF NOT IS_CURRENTLY_ON_MISSION_TO_TYPE() IF NOT IS_PED_INJURED(PLAYER_PED_ID()) IF IS_PLAYER_CONTROL_ON(PLAYER_ID()) IF NOT IS_CUTSCENE_PLAYING() AND NOT IS_PLAYER_IN_PROPERTY(PLAYER_ID(), TRUE, TRUE) AND NOT IS_PLAYER_BROWSING_ITEMS_IN_ANY_SHOP() IF IS_SCREEN_FADED_IN() IF NOT IS_WARNING_MESSAGE_ACTIVE() IF IS_PED_SITTING_IN_ANY_VEHICLE(PLAYER_PED_ID()) vehCurrent = GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()) IF IS_VEHICLE_DRIVEABLE(vehCurrent) IF NOT IS_VEHICLE_A_SUPERMOD_MODEL(GET_ENTITY_MODEL(vehCurrent), SUPERMOD_FLAG_HAS_HYDRAULICS) iVehIdDuckHelpCurrent = NATIVE_TO_INT(vehCurrent) IF GET_GAME_TIMER() > iTimeVehDuckHelpLastDisplayed + 120000 //Don't display more often than once every 2 mins. IF iVehIdDuckHelpLast != iVehIdDuckHelpCurrent IF IS_THIS_MODEL_A_CAR(GET_ENTITY_MODEL(vehCurrent)) IF IS_CONTROL_ENABLED(PLAYER_CONTROL, INPUT_VEH_DUCK) IF (NOT IS_HELP_MESSAGE_BEING_DISPLAYED()) OR IS_THIS_HELP_MESSAGE_BEING_DISPLAYED("HELP_DCK") bSafeToDisplay = TRUE ENDIF ENDIF ENDIF ENDIF ELSE //If we get into a vehicle with a timer blocking, don't allow the help //to pop up while still in that vehicle. It will seem like it came up //at an arbitrary moment. Better to try and display it just after the //player enters a fresh vehicle. iVehIdDuckHelpLast = iVehIdDuckHelpCurrent ENDIF ENDIF ENDIF ENDIF ENDIF ENDIF ENDIF ENDIF ENDIF ENDIF ENDIF // Wait for 10 consecutive safe frames before allowing the help to display. // This will give scripts a chance to queue up back to back help messages // without this help interrupting. IF bSafeToDisplay iFramesVehDuckHelpCheckPassed++ IF iFramesVehDuckHelpCheckPassed > 10 IF GET_FLOW_HELP_MESSAGE_STATUS("HELP_DCK") = FHS_EXPIRED ADD_HELP_TO_FLOW_QUEUE("HELP_DCK", FHP_LOW, 0, 1000) ENDIF ENDIF ELIF iFramesVehDuckHelpCheckPassed > 0 CDEBUG2LN(DEBUG_FLOW_HELP, " No longer safe to display. Resetting safe frame count.") iFramesVehDuckHelpCheckPassed = 0 IF GET_FLOW_HELP_MESSAGE_STATUS("HELP_DCK") = FHS_QUEUED REMOVE_HELP_FROM_FLOW_QUEUE("HELP_DCK") ENDIF IF IS_THIS_HELP_MESSAGE_BEING_DISPLAYED("HELP_DCK") CLEAR_HELP() ENDIF ENDIF IF IS_THIS_HELP_MESSAGE_BEING_DISPLAYED("HELP_DCK") bDisplayingVehDuckHelpThisFrame = TRUE ENDIF // Check if we've just finished displaying help. IF bDisplayingVehDuckHelpLastFrame AND NOT bDisplayingVehDuckHelpThisFrame g_savedGlobals.sFlowCustom.iVehDuckHelpCount++ iTimeVehDuckHelpLastDisplayed = GET_GAME_TIMER() iVehIdDuckHelpLast = iVehIdDuckHelpCurrent g_txtFlowHelpLastDisplayed = "" //Clear last displayed message. CPRINTLN(DEBUG_FLOW_HELP, " Finished displaying vehicle duck help. New count is ", g_savedGlobals.sFlowCustom.iVehDuckHelpCount, ".") ENDIF // Update last frame variable. bDisplayingVehDuckHelpLastFrame = bDisplayingVehDuckHelpThisFrame ENDPROC ENUM MAGIC_MOMENT_TYPE MAGICMOMENT_TYPE_5_STAR_CRIMINAL, //1. 5 Star Criminal – Records video of a player ticking over to 5 starts during a wanted rating spree MAGICMOMENT_TYPE_CHAIN_REACTION, //2. Chain Reaction – Records a video if the player blow up X cars within X seconds MAGICMOMENT_TYPE_BIRD_DOWN, //3. Bird Down – Records when the player kills the pilot to make a helicopter crash to make it spiral and crash MAGICMOMENT_TYPE_SCOPED, //4. Scoped – Records the player performing a headshot rom a large distance using a sniper rifle MAGICMOMENT_TYPE_TOP_GUN, //5. Top Gun – Records a video when the player destroys something using an aircraft MAGICMOMENT_TYPE_AIRTIME, //6. Airtime – Records any massive jump over a certain distance / height MAGICMOMENT_TYPE_UNTOUCHABLE, //7. Untouchable – Records when the player drives at speed into oncoming traffic without hitting anything for X time MAGICMOMENT_TYPE_WHEELIE_RIDER, //8. Wheelie Rider – Records when the player has performed a wheelie for X distance (500m?). MAGICMOMENT_TYPE_BUCKLE_UP, //9. Buckle Up! – Records when the player crashes and flies through the windscreen of their car MAGICMOMENT_TYPE_ROLLED_OVER, //10. Rolled Over – Records when the player crashes and flips / rolls X times in a vehicle (Like achievement in IV) MAGICMOMENT_TYPE_DIZZYING_LOWS, //11. Dizzying Lows – Records when the player flies upside down and low to the ground for x time MAGICMOMENT_TYPE_YANK_THE_CORD, //12. Yank the Cord! Records when the player free falls X distance and opens their chute at the last second MAGICMOMENT_TYPE_ANIMAUL, //13. Animaul – Records when the player is killed by any animals (Mountain Lions, Sharks and Dogs etc.) MAGICMOMENT_TYPE_FULLY_MODDED, //14. Fully Modded – Records when a player’s fully mods their vehicle and exits LS Custom MAGICMOMENT_TYPE_GLORY_HOLE, //15. Glory Hole – Records when the player gets a Hole in 1 during Golf MAGICMOMENT_TYPE_ARRAY_SIZE ENDENUM //FIVE_START_CRIMINAL = 0, //CHAIN_REACTION, //BIRD_DOWN, //SCOPED, //TOP_GUN, //AIRTIME, //UNTOUCHABLE, //WHEELIE_RIDER, //BUCKLE_UP, //ROLLED_OVER, //DIZZYING_LAWS, //YANK_THE_CORD, //ANIMAUL, //FULLY_MODDED, //GLORY_HOLE ENUM MAGIC_MOMENT_TYPE_VARIABLE_STATE //Labels our previous and current array values MM_PREVIOUS, MM_CURRENT ENDENUM MAGIC_MOMENT_TYPE eCurrentlyProcessedMagicMomentType = MAGICMOMENT_TYPE_5_STAR_CRIMINAL MAGIC_MOMENT_TYPE eCurrentlyProcessedMagicMomentTypeMinigame = MAGICMOMENT_TYPE_GLORY_HOLE MAGIC_MOMENT_TYPE eCurrentlyProcessedMagicMomentTypeOnFoot = MAGICMOMENT_TYPE_SCOPED MAGIC_MOMENT_TYPE eCurrentlyProcessedMagicMomentTypeInPlane = MAGICMOMENT_TYPE_DIZZYING_LOWS MAGIC_MOMENT_TYPE eCurrentlyProcessedMagicMomentTypeInVehicle = MAGICMOMENT_TYPE_AIRTIME //Actually make native stat procedure useful FUNC INT STAT_RETURN_INT(STATSENUM seThisStat) INT iTempStat STAT_GET_INT(seThisStat, iTempStat) RETURN iTempStat ENDFUNC //Actually make native stat procedure useful FUNC FLOAT STAT_RETURN_FLOAT(STATSENUM seThisStat) FLOAT fTempStat STAT_GET_FLOAT(seThisStat, fTempStat) RETURN fTempStat ENDFUNC FLOAT iMMStats[MAGICMOMENT_TYPE_ARRAY_SIZE][2] INT iChainReactionTimer = -1 INT iUntouchableTimer = -1 INT iMagicMomentsTimer INT iAirstrikeWindowTime FLOAT fChainReactionInProgressCount = 0 BOOL bForceResetTopgunStats BOOL bCheckedLastDestroyedHeli BOOL bLastDestroyedHeliInAir BOOL bInitialisedMagicMoments BOOL bDontSpamMagicMoments BOOL bHitAnimal PROC SET_MAGIC_MOMENT_CURRENT_VALUE(MAGIC_MOMENT_TYPE thisMoment, BOOL bAlsoSetPreviousValue = FALSE) SWITCH thisMoment CASE MAGICMOMENT_TYPE_5_STAR_CRIMINAL iMMStats[thisMoment][MM_CURRENT] = 0 BREAK CASE MAGICMOMENT_TYPE_CHAIN_REACTION iMMStats[thisMoment][MM_CURRENT] = TO_FLOAT(STAT_RETURN_INT(SP0_CARS_EXPLODED)+STAT_RETURN_INT(SP1_CARS_EXPLODED)+STAT_RETURN_INT(SP2_CARS_EXPLODED)) BREAK CASE MAGICMOMENT_TYPE_BIRD_DOWN iMMStats[thisMoment][MM_CURRENT] = TO_FLOAT(STAT_RETURN_INT(SP0_HELIS_EXPLODED) + STAT_RETURN_INT(SP1_HELIS_EXPLODED) + STAT_RETURN_INT(SP2_HELIS_EXPLODED)) BREAK CASE MAGICMOMENT_TYPE_YANK_THE_CORD iMMStats[thisMoment][MM_CURRENT] = g_savedGlobals.sBasejumpData.fLongestSkydive//STAT_RETURN_FLOAT(SP0_LONGEST_SKYDIVE) + STAT_RETURN_FLOAT(SP1_LONGEST_SKYDIVE) + STAT_RETURN_FLOAT(SP2_LONGEST_SKYDIVE) BREAK CASE MAGICMOMENT_TYPE_BUCKLE_UP iMMStats[thisMoment][MM_CURRENT] = TO_FLOAT(STAT_RETURN_INT(SP0_THROWNTHROUGH_WINDSCREEN) + STAT_RETURN_INT(SP1_THROWNTHROUGH_WINDSCREEN) + STAT_RETURN_INT(SP2_THROWNTHROUGH_WINDSCREEN)) BREAK CASE MAGICMOMENT_TYPE_GLORY_HOLE iMMStats[thisMoment][MM_CURRENT] = 0 BREAK CASE MAGICMOMENT_TYPE_SCOPED iMMStats[thisMoment][MM_CURRENT] = TO_FLOAT(STAT_RETURN_INT(SP0_HEADSHOTS) + STAT_RETURN_INT(SP1_HEADSHOTS) + STAT_RETURN_INT(SP2_HEADSHOTS)) BREAK CASE MAGICMOMENT_TYPE_ANIMAUL iMMStats[thisMoment][MM_CURRENT] = -60000 BREAK CASE MAGICMOMENT_TYPE_DIZZYING_LOWS iMMStats[thisMoment][MM_CURRENT] = 0 BREAK CASE MAGICMOMENT_TYPE_TOP_GUN iMMStats[thisMoment][MM_CURRENT] = TO_FLOAT(STAT_RETURN_INT(SP0_KILLS) + STAT_RETURN_INT(SP1_KILLS) + STAT_RETURN_INT(SP2_KILLS)) BREAK CASE MAGICMOMENT_TYPE_AIRTIME iMMStats[thisMoment][MM_CURRENT] = TO_FLOAT(STAT_RETURN_INT(SP0_AIR_LAUNCHES_OVER_5S) + STAT_RETURN_INT(SP1_AIR_LAUNCHES_OVER_5S) + STAT_RETURN_INT(SP2_AIR_LAUNCHES_OVER_5S)) BREAK CASE MAGICMOMENT_TYPE_WHEELIE_RIDER iMMStats[thisMoment][MM_CURRENT] = TO_FLOAT(STAT_RETURN_INT(SP0_LONGEST_WHEELIE_TIME) + STAT_RETURN_INT(SP1_LONGEST_WHEELIE_TIME) + STAT_RETURN_INT(SP2_LONGEST_WHEELIE_TIME)) BREAK CASE MAGICMOMENT_TYPE_ROLLED_OVER iMMStats[thisMoment][MM_CURRENT] = TO_FLOAT(STAT_RETURN_INT(SP0_MOST_FLIPS_IN_ONE_JUMP) + STAT_RETURN_INT(SP1_MOST_FLIPS_IN_ONE_JUMP) + STAT_RETURN_INT(SP2_MOST_FLIPS_IN_ONE_JUMP)) BREAK CASE MAGICMOMENT_TYPE_UNTOUCHABLE iMMStats[thisMoment][MM_CURRENT] = TO_FLOAT(STAT_RETURN_INT(SP0_NUMBER_NEAR_MISS) + STAT_RETURN_INT(SP1_NUMBER_NEAR_MISS) + STAT_RETURN_INT(SP2_NUMBER_NEAR_MISS)) //STAT_RETURN_FLOAT(SP0_LONGEST_DRIVE_NOCRASH) + STAT_RETURN_FLOAT(SP1_LONGEST_DRIVE_NOCRASH) + STAT_RETURN_FLOAT(SP2_LONGEST_DRIVE_NOCRASH) BREAK ENDSWITCH IF bAlsoSetPreviousValue iMMStats[thisMoment][MM_PREVIOUS] = iMMStats[thisMoment][MM_CURRENT] ENDIF ENDPROC BOOL bResetGroundVehicleStatsFlag BOOL bResetAirVehicleStatsFlag PROC MANAGE_MAGIC_MOMENTS() IF NOT bInitialisedMagicMoments // initialise values on load to what is currently stored in stats IF IS_PLAYER_PLAYING(PLAYER_ID()) INT i REPEAT MAGICMOMENT_TYPE_ARRAY_SIZE i SET_MAGIC_MOMENT_CURRENT_VALUE(INT_TO_ENUM(MAGIC_MOMENT_TYPE, i), TRUE) ENDREPEAT iMagicMomentsTimer = -30000 bInitialisedMagicMoments = TRUE ENDIF ELSE // process after initialisation // 2048106 - ensure destroyed heli is in air INT iCount STRUCT_ENTITY_ID sei EVENT_NAMES eventType // rob - 2079393 - ensure last destroyed heli is checked for in air/has pilot before processed from the stat increment // rob - 2099008 - don't count birds for air strike REPEAT GET_NUMBER_OF_EVENTS(SCRIPT_EVENT_QUEUE_AI) iCount eventType = GET_EVENT_AT_INDEX(SCRIPT_EVENT_QUEUE_AI, iCount) IF eventType = EVENT_ENTITY_DESTROYED GET_EVENT_DATA(SCRIPT_EVENT_QUEUE_AI,iCount, sei,SIZE_OF(STRUCT_ENTITY_ID)) IF DOES_ENTITY_EXIST(sei.EntityId) IF IS_THIS_MODEL_A_HELI(GET_ENTITY_MODEL(sei.EntityId)) IF NOT bCheckedLastDestroyedHeli bLastDestroyedHeliInAir = FALSE bCheckedLastDestroyedHeli = TRUE IF IS_ENTITY_DEAD(sei.EntityId) OR NOT IS_ENTITY_DEAD(sei.EntityId) IF IS_ENTITY_IN_AIR(sei.EntityId) OR DOES_ENTITY_EXIST(GET_PED_IN_VEHICLE_SEAT(GET_VEHICLE_INDEX_FROM_ENTITY_INDEX(sei.EntityId))) // rob - 2079393 - some helis shot down by kiing the pilot weren't triggering this bLastDestroyedHeliInAir = TRUE ENDIF ENDIF ENDIF ELIF IS_ENTITY_A_PED(sei.EntityId) iAirstrikeWindowTime = GET_GAME_TIMER() + 1000 IF NOT IS_PED_HUMAN(GET_PED_INDEX_FROM_ENTITY_INDEX(sei.EntityId)) bHitAnimal = TRUE ELSE bHitAnimal = FALSE ENDIF ENDIF ENDIF ENDIF ENDREPEAT BOOL bWasInAircraft = FALSE //Magic moments that can happen at any time. SWITCH eCurrentlyProcessedMagicMomentType CASE MAGICMOMENT_TYPE_5_STAR_CRIMINAL IF iMMStats[MAGICMOMENT_TYPE_5_STAR_CRIMINAL][MM_PREVIOUS] < 5 IF GET_PLAYER_WANTED_LEVEL(PLAYER_ID()) = 5 AND GET_GAME_TIMER() - iMagicMomentsTimer > 30000 AND NOT IS_CURRENTLY_ON_MISSION_OF_ANY_TYPE() iMagicMomentsTimer = GET_GAME_TIMER() RECORD_GREATEST_MOMENT(FIVE_START_CRIMINAL, -5000, 8000) printstring("Record Greatest Moment - Five star criminal") printnl() ENDIF ENDIF iMMStats[MAGICMOMENT_TYPE_5_STAR_CRIMINAL][MM_PREVIOUS] = TO_FLOAT(GET_PLAYER_WANTED_LEVEL(PLAYER_ID())) eCurrentlyProcessedMagicMomentType = MAGICMOMENT_TYPE_CHAIN_REACTION BREAK CASE MAGICMOMENT_TYPE_CHAIN_REACTION SET_MAGIC_MOMENT_CURRENT_VALUE(MAGICMOMENT_TYPE_CHAIN_REACTION) IF iMMStats[MAGICMOMENT_TYPE_CHAIN_REACTION][MM_CURRENT] - iMMStats[MAGICMOMENT_TYPE_CHAIN_REACTION][MM_PREVIOUS] > 1.0 IF iChainReactionTimer = -1 //Start Timer! fChainReactionInProgressCount = iMMStats[MAGICMOMENT_TYPE_CHAIN_REACTION][MM_CURRENT] iChainReactionTimer = GET_GAME_TIMER() ENDIF IF iMMStats[MAGICMOMENT_TYPE_CHAIN_REACTION][MM_CURRENT] - iMMStats[MAGICMOMENT_TYPE_CHAIN_REACTION][MM_PREVIOUS] >= 4.0 IF GET_GAME_TIMER() - iMagicMomentsTimer > 30000 iMagicMomentsTimer = GET_GAME_TIMER() RECORD_GREATEST_MOMENT(CHAIN_REACTION, -6000, 12000) printstring("Record Greatest Moment - Chain reaction") printnl() ENDIF iChainReactionTimer = -1 iMMStats[MAGICMOMENT_TYPE_CHAIN_REACTION][MM_PREVIOUS] = iMMStats[MAGICMOMENT_TYPE_CHAIN_REACTION][MM_CURRENT] ENDIF IF iChainReactionTimer >= 0 // rob - 2079393 - add to the timer while the chain reaction's still ongoing IF iMMStats[MAGICMOMENT_TYPE_CHAIN_REACTION][MM_CURRENT] > fChainReactionInProgressCount fChainReactionInProgressCount = iMMStats[MAGICMOMENT_TYPE_CHAIN_REACTION][MM_CURRENT] IF GET_GAME_TIMER() - iChainReactionTimer > 2000 iChainReactionTimer = GET_GAME_TIMER() - 2000 ENDIF ENDIF IF GET_GAME_TIMER() - iChainReactionTimer > 4000 iChainReactionTimer = -1 iMMStats[MAGICMOMENT_TYPE_CHAIN_REACTION][MM_PREVIOUS] = iMMStats[MAGICMOMENT_TYPE_CHAIN_REACTION][MM_CURRENT] ENDIF ENDIF ENDIF eCurrentlyProcessedMagicMomentType = MAGICMOMENT_TYPE_BIRD_DOWN BREAK CASE MAGICMOMENT_TYPE_BIRD_DOWN //Number of helis exploded SET_MAGIC_MOMENT_CURRENT_VALUE(MAGICMOMENT_TYPE_BIRD_DOWN) IF iMMStats[MAGICMOMENT_TYPE_BIRD_DOWN][MM_CURRENT] - iMMStats[MAGICMOMENT_TYPE_BIRD_DOWN][MM_PREVIOUS] > 0.0 IF bCheckedLastDestroyedHeli IF bLastDestroyedHeliInAir IF GET_GAME_TIMER() - iMagicMomentsTimer > 30000 iMagicMomentsTimer = GET_GAME_TIMER() RECORD_GREATEST_MOMENT(BIRD_DOWN, -8000, 12000) printstring("Record Greatest Moment - Bird down") printnl() ENDIF ENDIF bLastDestroyedHeliInAir = FALSE bCheckedLastDestroyedHeli = FALSE // don't let them buffer up iMMStats[MAGICMOMENT_TYPE_BIRD_DOWN][MM_PREVIOUS] = iMMStats[MAGICMOMENT_TYPE_BIRD_DOWN][MM_CURRENT] ENDIF ENDIF eCurrentlyProcessedMagicMomentType = MAGICMOMENT_TYPE_YANK_THE_CORD BREAK CASE MAGICMOMENT_TYPE_YANK_THE_CORD //Implementation incomplete. Awaiting proper stat from Miguel. IF GET_PED_PARACHUTE_STATE(PLAYER_PED_ID()) = PPS_SKYDIVING //Init IF iMMStats[MAGICMOMENT_TYPE_YANK_THE_CORD][MM_PREVIOUS] = 0.0 iMMStats[MAGICMOMENT_TYPE_YANK_THE_CORD][MM_CURRENT] = 100.0 iMMStats[MAGICMOMENT_TYPE_YANK_THE_CORD][MM_PREVIOUS] = 100.0 ENDIF ELIF GET_PED_PARACHUTE_STATE(PLAYER_PED_ID()) = PPS_DEPLOYING SET_MAGIC_MOMENT_CURRENT_VALUE(MAGICMOMENT_TYPE_YANK_THE_CORD) PRINTLN("deployed data:", GET_ENTITY_HEIGHT_ABOVE_GROUND(PLAYER_PED_ID()), " < ", iMMStats[MAGICMOMENT_TYPE_YANK_THE_CORD][MM_PREVIOUS]) IF GET_ENTITY_HEIGHT_ABOVE_GROUND(PLAYER_PED_ID()) < iMMStats[MAGICMOMENT_TYPE_YANK_THE_CORD][MM_PREVIOUS] iMMStats[MAGICMOMENT_TYPE_YANK_THE_CORD][MM_PREVIOUS] = GET_ENTITY_HEIGHT_ABOVE_GROUND(PLAYER_PED_ID()) iMagicMomentsTimer = GET_GAME_TIMER() bDontSpamMagicMoments = FALSE ENDIF ELIF GET_PED_PARACHUTE_STATE(PLAYER_PED_ID()) = PPS_LANDING //Now check if they land safely... IF NOT IS_PED_INJURED(PLAYER_PED_ID()) IF NOT IS_ENTITY_IN_AIR(PLAYER_PED_ID()) IF GET_GAME_TIMER() - iMagicMomentsTimer < 10000 IF bDontSpamMagicMoments = FALSE g_savedGlobals.sBasejumpData.fLongestSkydive = iMMStats[MAGICMOMENT_TYPE_YANK_THE_CORD][MM_PREVIOUS] RECORD_GREATEST_MOMENT(YANK_THE_CORD, -7000, 10000) printstring("Record Greatest Moment - Yank the cord") printnl() bDontSpamMagicMoments = TRUE ENDIF ELSE PRINTLN("GET_GAME_TIMER() - iMagicMomentsTimer:, ", (GET_GAME_TIMER() - iMagicMomentsTimer)) iMMStats[MAGICMOMENT_TYPE_YANK_THE_CORD][MM_PREVIOUS] = g_savedGlobals.sBasejumpData.fLongestSkydive //SCRIPT_ASSERT("timer expired") ENDIF ENDIF ELSE iMMStats[MAGICMOMENT_TYPE_YANK_THE_CORD][MM_PREVIOUS] = g_savedGlobals.sBasejumpData.fLongestSkydive //SCRIPT_ASSERT("reseting value") ENDIF ENDIF eCurrentlyProcessedMagicMomentType = MAGICMOMENT_TYPE_BUCKLE_UP BREAK CASE MAGICMOMENT_TYPE_BUCKLE_UP SET_MAGIC_MOMENT_CURRENT_VALUE(MAGICMOMENT_TYPE_BUCKLE_UP) IF iMMStats[MAGICMOMENT_TYPE_BUCKLE_UP][MM_CURRENT] - iMMStats[MAGICMOMENT_TYPE_BUCKLE_UP][MM_PREVIOUS] > 0.0 IF GET_GAME_TIMER() - iMagicMomentsTimer > 30000 iMagicMomentsTimer = GET_GAME_TIMER() RECORD_GREATEST_MOMENT(BUCKLE_UP, -3000, 8000) printstring("Record Greatest Moment - Buckle up") printnl() ENDIF iMMStats[MAGICMOMENT_TYPE_BUCKLE_UP][MM_PREVIOUS] = iMMStats[MAGICMOMENT_TYPE_BUCKLE_UP][MM_CURRENT] ENDIF eCurrentlyProcessedMagicMomentType = MAGICMOMENT_TYPE_5_STAR_CRIMINAL BREAK ENDSWITCH //Magic moments that can only happen during minigames //IF IS_MINIGAME_ACTIVE(MINIGAME_GOLF) // rob - 2079393 - change is golf running check IF GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(HASH("golf")) > 0 SWITCH eCurrentlyProcessedMagicMomentTypeMinigame CASE MAGICMOMENT_TYPE_GLORY_HOLE IF IS_GLOBAL_GOLF_CONTROL_FLAG_SET(GGCF_PLAYER_HOLE_IN_ONE) IF iMMStats[MAGICMOMENT_TYPE_GLORY_HOLE][MM_CURRENT] = 0 RECORD_GREATEST_MOMENT(GLORY_HOLE, -15000, 18000) printstring("Record Greatest Moment - Glory") printnl() iMagicMomentsTimer = GET_GAME_TIMER() iMMStats[MAGICMOMENT_TYPE_GLORY_HOLE][MM_CURRENT] = 1 ENDIF ELSE iMMStats[MAGICMOMENT_TYPE_GLORY_HOLE][MM_CURRENT] = 0 ENDIF BREAK ENDSWITCH //Magic moments that can only happen on foot ELIF IS_PED_ON_FOOT(PLAYER_PED_ID()) //If a player pulls off a "magic moment" bug exits the vehicle before it finishes processing //we need to reset. IF bResetGroundVehicleStatsFlag = FALSE SET_MAGIC_MOMENT_CURRENT_VALUE(MAGICMOMENT_TYPE_AIRTIME, TRUE) SET_MAGIC_MOMENT_CURRENT_VALUE(MAGICMOMENT_TYPE_WHEELIE_RIDER, TRUE) SET_MAGIC_MOMENT_CURRENT_VALUE(MAGICMOMENT_TYPE_ROLLED_OVER, TRUE) SET_MAGIC_MOMENT_CURRENT_VALUE(MAGICMOMENT_TYPE_UNTOUCHABLE, TRUE) bResetGroundVehicleStatsFlag = TRUE ENDIF //If a player pulls off a "magic moment" bug exits the aircraft before it finishes processing //we need to reset. IF bResetAirVehicleStatsFlag = FALSE SET_MAGIC_MOMENT_CURRENT_VALUE(MAGICMOMENT_TYPE_TOP_GUN, TRUE) SET_MAGIC_MOMENT_CURRENT_VALUE(MAGICMOMENT_TYPE_DIZZYING_LOWS, TRUE) bResetAirVehicleStatsFlag = TRUE ENDIF ENTITY_INDEX eiPlayerKiller PED_INDEX piPlayerKillerPedIndex WEAPON_TYPE MMReturnWeaponType SWITCH eCurrentlyProcessedMagicMomentTypeOnFoot CASE MAGICMOMENT_TYPE_SCOPED SET_MAGIC_MOMENT_CURRENT_VALUE(MAGICMOMENT_TYPE_SCOPED) IF iMMStats[MAGICMOMENT_TYPE_SCOPED][MM_CURRENT] - iMMStats[MAGICMOMENT_TYPE_SCOPED][MM_PREVIOUS] > 0.0 IF GET_GAME_TIMER() - iMagicMomentsTimer > 30000 IF GET_CURRENT_PED_WEAPON(PLAYER_PED_ID(),MMReturnWeaponType, FALSE) // rob - 2090369 - limit "scoped" to using a sniper rifle IF MMReturnWeaponType = WEAPONTYPE_SNIPERRIFLE OR MMReturnWeaponType = WEAPONTYPE_HEAVYSNIPER OR MMReturnWeaponType = WEAPONTYPE_DLC_MARKSMANRIFLE RECORD_GREATEST_MOMENT(SCOPED, -4000, 8000) printstring("Record Greatest Moment - Scoped") printnl() iMagicMomentsTimer = GET_GAME_TIMER() ENDIF ENDIF ENDIF ENDIF iMMStats[MAGICMOMENT_TYPE_SCOPED][MM_PREVIOUS] = iMMStats[MAGICMOMENT_TYPE_SCOPED][MM_CURRENT] eCurrentlyProcessedMagicMomentTypeOnFoot = MAGICMOMENT_TYPE_ANIMAUL BREAK CASE MAGICMOMENT_TYPE_ANIMAUL IF IS_PED_INJURED(PLAYER_PED_ID()) eiPlayerKiller = GET_PED_SOURCE_OF_DEATH(PLAYER_PED_ID()) IF IS_ENTITY_A_PED(eiPlayerKiller) piPlayerKillerPedIndex = GET_PED_INDEX_FROM_ENTITY_INDEX(eiPlayerKiller) IF NOT IS_ENTITY_DEAD(piPlayerKillerPedIndex) IF GET_PED_TYPE(piPlayerKillerPedIndex) = PEDTYPE_ANIMAL AND GET_GAME_TIMER() - iMMStats[MAGICMOMENT_TYPE_ANIMAUL][MM_CURRENT] > 60000.0 AND GET_GAME_TIMER() - iMagicMomentsTimer > 30000 RECORD_GREATEST_MOMENT(ANIMAUL, -8000, 12000) printstring("Record Greatest Moment - Animaul") printnl() iMagicMomentsTimer = GET_GAME_TIMER() iMMStats[MAGICMOMENT_TYPE_ANIMAUL][MM_CURRENT] = TO_FLOAT(GET_GAME_TIMER()) ENDIF ENDIF ENDIF ENDIF eCurrentlyProcessedMagicMomentTypeOnFoot = MAGICMOMENT_TYPE_SCOPED BREAK ENDSWITCH //Magic moments that can only happen in vehicles ELIF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID()) //Magic moments that can only happen in planes IF IS_PED_IN_ANY_PLANE(PLAYER_PED_ID()) OR IS_PED_IN_ANY_HELI(PLAYER_PED_ID()) bWasInAircraft = TRUE //If a player pulls off a "magic moment" bug exits the vehicle before it finishes processing //we need to reset. IF bResetGroundVehicleStatsFlag = FALSE SET_MAGIC_MOMENT_CURRENT_VALUE(MAGICMOMENT_TYPE_AIRTIME, TRUE) SET_MAGIC_MOMENT_CURRENT_VALUE(MAGICMOMENT_TYPE_WHEELIE_RIDER, TRUE) SET_MAGIC_MOMENT_CURRENT_VALUE(MAGICMOMENT_TYPE_ROLLED_OVER, TRUE) SET_MAGIC_MOMENT_CURRENT_VALUE(MAGICMOMENT_TYPE_UNTOUCHABLE, TRUE) bResetGroundVehicleStatsFlag = TRUE ENDIF bResetAirVehicleStatsFlag = FALSE SWITCH eCurrentlyProcessedMagicMomentTypeInPlane CASE MAGICMOMENT_TYPE_DIZZYING_LOWS // url:bugstar:2102428 IF NOT IS_ENTITY_DEAD(PLAYER_PED_ID()) AND NOT IS_ENTITY_DEAD(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID())) IF IS_ENTITY_UPSIDEDOWN(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID())) IF GET_ENTITY_HEIGHT_ABOVE_GROUND(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID())) < 30.0 IF iMMStats[MAGICMOMENT_TYPE_DIZZYING_LOWS][MM_CURRENT] = 0.0 //Use current here to store time and previous to store record time iMMStats[MAGICMOMENT_TYPE_DIZZYING_LOWS][MM_CURRENT] = TO_FLOAT(GET_GAME_TIMER() ) iMMStats[MAGICMOMENT_TYPE_DIZZYING_LOWS][MM_PREVIOUS] = 3000.0 ENDIF IF GET_GAME_TIMER() - iMMStats[MAGICMOMENT_TYPE_DIZZYING_LOWS][MM_CURRENT] > iMMStats[MAGICMOMENT_TYPE_DIZZYING_LOWS][MM_PREVIOUS] AND GET_GAME_TIMER() - iMagicMomentsTimer > 30000 iMMStats[MAGICMOMENT_TYPE_DIZZYING_LOWS][MM_PREVIOUS] = TO_FLOAT(GET_GAME_TIMER()) - iMMStats[MAGICMOMENT_TYPE_DIZZYING_LOWS][MM_CURRENT] RECORD_GREATEST_MOMENT(DIZZYING_LAWS, -5000, 8000) printstring("Record Greatest Moment - Dizzying lows") printnl() iMMStats[MAGICMOMENT_TYPE_DIZZYING_LOWS][MM_CURRENT] = 0.0 iMagicMomentsTimer = GET_GAME_TIMER() ENDIF ELSE iMMStats[MAGICMOMENT_TYPE_DIZZYING_LOWS][MM_CURRENT] = 0.0 ENDIF ELSE iMMStats[MAGICMOMENT_TYPE_DIZZYING_LOWS][MM_CURRENT] = 0.0 ENDIF ENDIF eCurrentlyProcessedMagicMomentTypeInPlane = MAGICMOMENT_TYPE_TOP_GUN BREAK CASE MAGICMOMENT_TYPE_TOP_GUN SET_MAGIC_MOMENT_CURRENT_VALUE(MAGICMOMENT_TYPE_TOP_GUN) // force reset when only just entered vehicle, to avoid situations where you can get a kill on foot then it records soon as you get in a plane IF bForceResetTopgunStats iMMStats[MAGICMOMENT_TYPE_TOP_GUN][MM_PREVIOUS] = iMMStats[MAGICMOMENT_TYPE_TOP_GUN][MM_CURRENT] ENDIF IF iMMStats[MAGICMOMENT_TYPE_TOP_GUN][MM_CURRENT] - iMMStats[MAGICMOMENT_TYPE_TOP_GUN][MM_PREVIOUS] > 0.0 AND GET_GAME_TIMER() < iAirstrikeWindowTime VEHICLE_INDEX airVehicle airVehicle = GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()) IF GET_GAME_TIMER() - iMagicMomentsTimer > 30000 AND IS_VEHICLE_DRIVEABLE(airVehicle) // check the plane you are in is OK - 2049101 AND NOT bHitAnimal // not a bird - 2099008 RECORD_GREATEST_MOMENT(TOP_GUN, -3000, 8000) printstring("Record Greatest Moment - Top") printnl() iMagicMomentsTimer = GET_GAME_TIMER() ENDIF //Dont let them buffer up iMMStats[MAGICMOMENT_TYPE_TOP_GUN][MM_PREVIOUS] = iMMStats[MAGICMOMENT_TYPE_TOP_GUN][MM_CURRENT] ENDIF eCurrentlyProcessedMagicMomentTypeInPlane = MAGICMOMENT_TYPE_DIZZYING_LOWS bForceResetTopgunStats = FALSE BREAK ENDSWITCH ELSE //If a player pulls off a "magic moment" bug exits the aircraft before it finishes processing //we need to reset. IF bResetAirVehicleStatsFlag = FALSE SET_MAGIC_MOMENT_CURRENT_VALUE(MAGICMOMENT_TYPE_TOP_GUN, TRUE) SET_MAGIC_MOMENT_CURRENT_VALUE(MAGICMOMENT_TYPE_DIZZYING_LOWS, TRUE) bResetAirVehicleStatsFlag = TRUE ENDIF bResetGroundVehicleStatsFlag = FALSE SWITCH eCurrentlyProcessedMagicMomentTypeInVehicle CASE MAGICMOMENT_TYPE_AIRTIME SET_MAGIC_MOMENT_CURRENT_VALUE(MAGICMOMENT_TYPE_AIRTIME) // IF iMMStats[MAGICMOMENT_TYPE_AIRTIME][MM_CURRENT] < 1.0 // iMMStats[MAGICMOMENT_TYPE_AIRTIME][MM_CURRENT] = 1.0 // iMMStats[MAGICMOMENT_TYPE_AIRTIME][MM_PREVIOUS] = 1.0 // ENDIF PRINTLN("Values: ", iMMStats[MAGICMOMENT_TYPE_AIRTIME][MM_CURRENT], ", ", iMMStats[MAGICMOMENT_TYPE_AIRTIME][MM_PREVIOUS]) IF iMMStats[MAGICMOMENT_TYPE_AIRTIME][MM_PREVIOUS] - iMMStats[MAGICMOMENT_TYPE_AIRTIME][MM_CURRENT] <> 0 AND GET_GAME_TIMER() - iMagicMomentsTimer > 30000 RECORD_GREATEST_MOMENT(AIRTIME, -9000, 12000) printstring("Record Greatest Moment - Airtime") printnl() PRINTLN("Values: ", iMMStats[MAGICMOMENT_TYPE_AIRTIME][MM_CURRENT], ", ", iMMStats[MAGICMOMENT_TYPE_AIRTIME][MM_PREVIOUS]) iMagicMomentsTimer = GET_GAME_TIMER() ENDIF iMMStats[MAGICMOMENT_TYPE_AIRTIME][MM_PREVIOUS] = iMMStats[MAGICMOMENT_TYPE_AIRTIME][MM_CURRENT] eCurrentlyProcessedMagicMomentTypeInVehicle = MAGICMOMENT_TYPE_WHEELIE_RIDER BREAK CASE MAGICMOMENT_TYPE_WHEELIE_RIDER SET_MAGIC_MOMENT_CURRENT_VALUE(MAGICMOMENT_TYPE_WHEELIE_RIDER) // IF iMMStats[MAGICMOMENT_TYPE_WHEELIE_RIDER][MM_CURRENT] < 1.0 // iMMStats[MAGICMOMENT_TYPE_WHEELIE_RIDER][MM_CURRENT] = 1.0 // iMMStats[MAGICMOMENT_TYPE_WHEELIE_RIDER][MM_PREVIOUS] = 1.0 // ENDIF IF iMMStats[MAGICMOMENT_TYPE_WHEELIE_RIDER][MM_PREVIOUS] - iMMStats[MAGICMOMENT_TYPE_WHEELIE_RIDER][MM_CURRENT] <> 0 AND GET_GAME_TIMER() - iMagicMomentsTimer > 30000 RECORD_GREATEST_MOMENT(WHEELIE_RIDER, -6000, 8000) printstring("Record Greatest Moment - Wheelie") printnl() PRINTLN("Values: ", iMMStats[MAGICMOMENT_TYPE_WHEELIE_RIDER][MM_CURRENT], ", ", iMMStats[MAGICMOMENT_TYPE_WHEELIE_RIDER][MM_PREVIOUS]) iMagicMomentsTimer = GET_GAME_TIMER() ENDIF iMMStats[MAGICMOMENT_TYPE_WHEELIE_RIDER][MM_PREVIOUS] = iMMStats[MAGICMOMENT_TYPE_WHEELIE_RIDER][MM_CURRENT] eCurrentlyProcessedMagicMomentTypeInVehicle = MAGICMOMENT_TYPE_ROLLED_OVER BREAK CASE MAGICMOMENT_TYPE_ROLLED_OVER SET_MAGIC_MOMENT_CURRENT_VALUE(MAGICMOMENT_TYPE_ROLLED_OVER) IF iMMStats[MAGICMOMENT_TYPE_ROLLED_OVER][MM_CURRENT] - iMMStats[MAGICMOMENT_TYPE_ROLLED_OVER][MM_PREVIOUS] > 0.0 AND GET_GAME_TIMER() - iMagicMomentsTimer > 30000 iMagicMomentsTimer = GET_GAME_TIMER() RECORD_GREATEST_MOMENT(ROLLED_OVER, -5000, 8000) printstring("Record Greatest Moment - Rolled over") printnl() PRINTLN("Values: ", iMMStats[MAGICMOMENT_TYPE_ROLLED_OVER][MM_CURRENT], ", ", iMMStats[MAGICMOMENT_TYPE_ROLLED_OVER][MM_PREVIOUS]) ENDIF iMMStats[MAGICMOMENT_TYPE_ROLLED_OVER][MM_PREVIOUS] = iMMStats[MAGICMOMENT_TYPE_ROLLED_OVER][MM_CURRENT] eCurrentlyProcessedMagicMomentTypeInVehicle = MAGICMOMENT_TYPE_UNTOUCHABLE BREAK CASE MAGICMOMENT_TYPE_UNTOUCHABLE //Longest drive without crashing SET_MAGIC_MOMENT_CURRENT_VALUE(MAGICMOMENT_TYPE_UNTOUCHABLE) //PRINTLN("Values: ", iMMStats[MAGICMOMENT_TYPE_UNTOUCHABLE][MM_CURRENT], ", ", iMMStats[MAGICMOMENT_TYPE_UNTOUCHABLE][MM_PREVIOUS], " Speed: ", GET_ENTITY_SPEED(PLAYER_PED_ID())) IF iMMStats[MAGICMOMENT_TYPE_UNTOUCHABLE][MM_CURRENT] - iMMStats[MAGICMOMENT_TYPE_UNTOUCHABLE][MM_PREVIOUS] > 1.0 IF iUntouchableTimer = -1 //Start Timer! //SCRIPT_ASSERT("timer started!") iUntouchableTimer = GET_GAME_TIMER() ENDIF IF iMMStats[MAGICMOMENT_TYPE_UNTOUCHABLE][MM_CURRENT] - iMMStats[MAGICMOMENT_TYPE_UNTOUCHABLE][MM_PREVIOUS] >= 8.0 IF GET_GAME_TIMER() - iMagicMomentsTimer > 30000 AND GET_ENTITY_SPEED(PLAYER_PED_ID()) > 22.8 iMagicMomentsTimer = GET_GAME_TIMER() RECORD_GREATEST_MOMENT(UNTOUCHABLE, -4000, 8000) printstring("Record Greatest Moment - Untouchable") printnl() ENDIF //SCRIPT_ASSERT("reset!") iUntouchableTimer = -1 iMMStats[MAGICMOMENT_TYPE_UNTOUCHABLE][MM_PREVIOUS] = iMMStats[MAGICMOMENT_TYPE_UNTOUCHABLE][MM_CURRENT] ENDIF IF iUntouchableTimer >= 0 IF GET_GAME_TIMER() - iUntouchableTimer > 6000 //SCRIPT_ASSERT("timer up!") iUntouchableTimer = -1 iMMStats[MAGICMOMENT_TYPE_UNTOUCHABLE][MM_PREVIOUS] = iMMStats[MAGICMOMENT_TYPE_UNTOUCHABLE][MM_CURRENT] ENDIF ENDIF ENDIF eCurrentlyProcessedMagicMomentTypeInVehicle = MAGICMOMENT_TYPE_AIRTIME BREAK //Taken care of in Mod Shop script // CASE MAGICMOMENT_TYPE_FULLY_MODDED ENDSWITCH ENDIF ENDIF IF NOT bWasInAircraft bForceResetTopgunStats = TRUE ENDIF ENDIF ENDPROC PROC PRINT_AVAILABLE_SAVE_DATA_STRUCT(STRUCT_AVAILABLE_SAVE_DATA &sData, STRING strDebugName) CDEBUG1LN(DEBUG_INIT_SP, "--- ", strDebugName, " ---") CDEBUG1LN(DEBUG_INIT_SP, "m_totalProgressMadeInSp = ", sData.m_totalProgressMadeInSp) CDEBUG1LN(DEBUG_INIT_SP, "m_numberOfChars = ", sData.m_numberOfChars) CDEBUG1LN(DEBUG_INIT_SP, "m_lastchar = ", sData.m_lastchar) CDEBUG1LN(DEBUG_INIT_SP, "m_gamerName = ", sData.m_gamerName) CDEBUG1LN(DEBUG_INIT_SP, "m_gamerHandle = ", sData.m_gamerHandle) CDEBUG1LN(DEBUG_INIT_SP, "m_pvc = ", sData.m_pvc) CDEBUG1LN(DEBUG_INIT_SP, "m_evc = ", sData.m_evc) CDEBUG1LN(DEBUG_INIT_SP, "m_bank = ", sData.m_bank) INT i REPEAT 5 i CDEBUG1LN(DEBUG_INIT_SP, "m_wallet[", i, "] = ", sData.m_wallet[i]) ENDREPEAT REPEAT 5 i CDEBUG1LN(DEBUG_INIT_SP, "m_xp[", i, "] = ", sData.m_xp[i]) ENDREPEAT REPEAT 5 i CDEBUG1LN(DEBUG_INIT_SP, "m_isactive[", i, "] = ", sData.m_isactive[i]) ENDREPEAT CDEBUG1LN(DEBUG_INIT_SP, "-----------------------") ENDPROC // Work out if this player had the Collector's or Special edition versions of the game // in last gen. Do this by querying the social club commerce leaderboard, or if we're online // check cached player settings. PROC MAINTAIN_LAST_GEN_PLAYER_SE_AND_CE_CHECKS_IN_SP() // Are we online? IF NETWORK_HAS_SOCIAL_CLUB_ACCOUNT() AND NETWORK_IS_SIGNED_ONLINE() AND ARE_PROFILE_SETTINGS_VALID() // Has the leaderboard check already run? IF NOT platformUpgradeLBCheckSP.bComplete CDEBUG1LN(DEBUG_LASTGEN, " Player is online with a Social Club account. Running server checks.") #IF USE_FINAL_PRINTS PRINTLN_FINAL("[LASTGEN][SE-CE] Player is online with a Social Club account. Running server checks.") #ENDIF // If the profile setting test has run this session clear it now we are // running online tests. This will let it run again if we switch offline. IF bProfileSettingCheckForLastGenDone CDEBUG1LN(DEBUG_LASTGEN, " Clearing profile setting test flag so it can run again.") #IF USE_FINAL_PRINTS PRINTLN_FINAL("[LASTGEN][SE-CE] Clearing profile setting test flag so it can run again.") #ENDIF bProfileSettingCheckForLastGenDone = FALSE ENDIF // First of all check this player is a last gen player. IF GET_PLAYER_LAST_GEN_CHECK() = LAST_GEN_STATUS_NONE CDEBUG3LN(DEBUG_LASTGEN, " Waiting for server query...") #IF USE_FINAL_PRINTS PRINTLN_FINAL("[LASTGEN][SE-CE] Waiting for server query...") #ENDIF ELIF GET_PLAYER_LAST_GEN_CHECK() = LAST_GEN_STATUS_FAILED CPRINTLN(DEBUG_LASTGEN, " The last gen check failed this session.") CPRINTLN(DEBUG_LASTGEN, " Giving up online test but checking profile settings.") #IF USE_FINAL_PRINTS PRINTLN_FINAL("[LASTGEN][SE-CE] The last gen check failed this session.") PRINTLN_FINAL("[LASTGEN][SE-CE] Giving up online test but checking profile settings.") #ENDIF platformUpgradeLBCheckSP.bComplete = TRUE bDoProfileSettingCheckForLastGen = TRUE ELIF GET_PLAYER_LAST_GEN_CHECK() = LAST_GEN_STATUS_IS_NOT_LAST_GEN CPRINTLN(DEBUG_LASTGEN, " The player wasn't a last gen player. Nothing to do.") #IF USE_FINAL_PRINTS PRINTLN_FINAL("[LASTGEN][SE-CE] The player wasn't a last gen player. Nothing to do.") #ENDIF platformUpgradeLBCheckSP.bComplete = TRUE // Player has a last gen account. ELSE CDEBUG1LN(DEBUG_LASTGEN, " The player is a last gen player. Checking if we have the required data to run leaderboard checks...") #IF USE_FINAL_PRINTS PRINTLN_FINAL("[LASTGEN][SE-CE] The player is a last gen player. Checking if we have the required data to run leaderboard checks...") #ENDIF // Do we have the information we need to query leaderboards? IF (g_struct_Save_transfer_data_PS3.m_totalProgressMadeInSp <= 0 OR IS_STRING_NULL_OR_EMPTY(g_struct_Save_transfer_data_PS3.m_gamerHandle)) AND (g_struct_Save_transfer_data_XBOX360.m_totalProgressMadeInSp <= 0 OR IS_STRING_NULL_OR_EMPTY(g_struct_Save_transfer_data_XBOX360.m_gamerHandle)) CDEBUG1LN(DEBUG_LASTGEN, " Data not present. Doing nothing this pass.") #IF USE_FINAL_PRINTS PRINTLN_FINAL("[LASTGEN][SE-CE] Data not present. Doing nothing this pass.") #ENDIF ELSE CDEBUG1LN(DEBUG_LASTGEN, " Data is present. Running leaderboard check.") #IF USE_FINAL_PRINTS PRINTLN_FINAL("[LASTGEN][SE-CE] Data is present. Running leaderboard check.") #ENDIF // We have the information we need. Let's query the leaderboard. // This will update g_iPlayerHasLastGenSpecialContentBitset for us. IF RUN_PLATFORM_UPGRADE_LB_CHECKS(platformUpgradeLBCheckSP, TRUE) CPRINTLN(DEBUG_LASTGEN, " Lastgen special content query complete.") CPRINTLN(DEBUG_LASTGEN, " -----------------------------------------------") CPRINTLN(DEBUG_LASTGEN, " Lastgen PS3 Collectors Edition: ", PICK_STRING(IS_BIT_SET(g_iPlayerHasLastGenSpecialContentBitset, BIT_LAST_GEN_SPECIAL_CONTENT_PS3_COLLECTORS), "TRUE", "FALSE")) CPRINTLN(DEBUG_LASTGEN, " Lastgen PS3 Special Edition: ", PICK_STRING(IS_BIT_SET(g_iPlayerHasLastGenSpecialContentBitset, BIT_LAST_GEN_SPECIAL_CONTENT_PS3_SPECIAL), "TRUE", "FALSE")) CPRINTLN(DEBUG_LASTGEN, " Lastgen 360 Collectors Edition: ", PICK_STRING(IS_BIT_SET(g_iPlayerHasLastGenSpecialContentBitset, BIT_LAST_GEN_SPECIAL_CONTENT_360_COLLECTORS), "TRUE", "FALSE")) CPRINTLN(DEBUG_LASTGEN, " Lastgen 360 Special Edition: ", PICK_STRING(IS_BIT_SET(g_iPlayerHasLastGenSpecialContentBitset, BIT_LAST_GEN_SPECIAL_CONTENT_360_SPECIAL), "TRUE", "FALSE")) CPRINTLN(DEBUG_LASTGEN, " -----------------------------------------------") #IF USE_FINAL_PRINTS PRINTLN_FINAL("[LASTGEN][SE-CE] Lastgen special content query complete.") PRINTLN_FINAL("[LASTGEN][SE-CE] -----------------------------------------------") PRINTLN_FINAL("[LASTGEN][SE-CE] Lastgen PS3 Collectors Edition: ", PICK_STRING(IS_BIT_SET(g_iPlayerHasLastGenSpecialContentBitset, BIT_LAST_GEN_SPECIAL_CONTENT_PS3_COLLECTORS), "TRUE", "FALSE")) PRINTLN_FINAL("[LASTGEN][SE-CE] Lastgen PS3 Special Edition: ", PICK_STRING(IS_BIT_SET(g_iPlayerHasLastGenSpecialContentBitset, BIT_LAST_GEN_SPECIAL_CONTENT_PS3_SPECIAL), "TRUE", "FALSE")) PRINTLN_FINAL("[LASTGEN][SE-CE] Lastgen 360 Collectors Edition: ", PICK_STRING(IS_BIT_SET(g_iPlayerHasLastGenSpecialContentBitset, BIT_LAST_GEN_SPECIAL_CONTENT_360_COLLECTORS), "TRUE", "FALSE")) PRINTLN_FINAL("[LASTGEN][SE-CE] Lastgen 360 Special Edition: ", PICK_STRING(IS_BIT_SET(g_iPlayerHasLastGenSpecialContentBitset, BIT_LAST_GEN_SPECIAL_CONTENT_360_SPECIAL), "TRUE", "FALSE")) PRINTLN_FINAL("[LASTGEN][SE-CE] -----------------------------------------------") #ENDIF platformUpgradeLBCheckSP.bComplete = TRUE //Flag not to run leaderboard check again. bProfileSettingCheckForLastGenDone = TRUE //Flag not to run profile setting check again. ENDIF ENDIF ENDIF ENDIF // We're offline. We can't run the leaderboard check. ELSE // If the online leaderboard check has run this session clean it up now we are // offline. This will let it run again if we go online again. IF platformUpgradeLBCheckSP.bComplete OR platformUpgradeLBCheckSP.bSuccessful OR platformUpgradeLBCheckSP.iTotalStage != 0 OR platformUpgradeLBCheckSP.iReadStage != 0 CPRINTLN(DEBUG_LASTGEN, " Player is offline resetting the state of the online test so it runs again.") #IF USE_FINAL_PRINTS PRINTLN_FINAL("[LASTGEN][SE-CE] Player is offline resetting the state of the online test so it runs again.") #ENDIF RESET_PLATFORM_UPGRADE_LB_CHECK_STRUCT(platformUpgradeLBCheckSP) ENDIF // Do we have access to this user's profile settings? IF NETWORK_IS_SIGNED_IN() AND ARE_PROFILE_SETTINGS_VALID() // We can query cached profile settings. IF NOT bProfileSettingCheckForLastGenDone CDEBUG1LN(DEBUG_LASTGEN, " Player is offline but has valid profile. Running profile setting test.") #IF USE_FINAL_PRINTS PRINTLN_FINAL("[LASTGEN][SE-CE] Player is offline but has valid profile. Running profile setting test.") #ENDIF bDoProfileSettingCheckForLastGen = TRUE ENDIF // We're offline with no valid profile settings. There is nothing we can query. Remove access to the content. ELSE // If the profile setting test has run this session clear it now we are // signed out. This will let it run again if we sign back in. IF bProfileSettingCheckForLastGenDone CDEBUG1LN(DEBUG_LASTGEN, " Clearing profile setting test flag so it can run again.") #IF USE_FINAL_PRINTS PRINTLN_FINAL("[LASTGEN][SE-CE] Clearing profile setting test flag so it can run again.") #ENDIF bProfileSettingCheckForLastGenDone = FALSE ENDIF //Remove access to content. g_iPlayerHasLastGenSpecialContentBitset = 0 ENDIF ENDIF // Handle requests to query the profile settings. IF bDoProfileSettingCheckForLastGen AND NOT bProfileSettingCheckForLastGenDone CDEBUG1LN(DEBUG_LASTGEN, " Profile setting test requested.") #IF USE_FINAL_PRINTS PRINTLN_FINAL("[LASTGEN][SE-CE] Profile setting test requested.") #ENDIF IF NETWORK_IS_SIGNED_IN() AND ARE_PROFILE_SETTINGS_VALID() CDEBUG1LN(DEBUG_LASTGEN, " Updating lastget SE/CE unlock to cached profile setting.") #IF USE_FINAL_PRINTS PRINTLN_FINAL("[LASTGEN][SE-CE] Updating lastget SE/CE unlock to cached profile setting.") #ENDIF g_iPlayerHasLastGenSpecialContentBitset = GET_PROFILE_SETTING(GAMER_HAS_SPECIALEDITION_CONTENT) ENDIF bDoProfileSettingCheckForLastGen = FALSE bProfileSettingCheckForLastGenDone = TRUE ENDIF ENDPROC #IF IS_NEXTGEN_BUILD // Last gen gives you the weapons automatically from startup.sc - they are not unlocked in the flow like NG so no email need to be sent. PROC MAINTAIN_DLC_WEAPON_EMAILS() IF IS_MP_CHRISTMAS2_PACK_PRESENT() //Proximity mine email. IF NOT GET_MISSION_FLOW_FLAG_STATE(FLOWFLAG_SENT_PROXIMITY_MINE_EMAIL) IF GET_MISSION_COMPLETE_STATE(SP_MISSION_TREVOR_3) IF REGISTER_EMAIL_FROM_CHARACTER_TO_PLAYER(EMAIL_WEAPON_STOCK_10, CT_AMBIENT, BIT_MICHAEL|BIT_FRANKLIN|BIT_TREVOR, CHAR_AMMUNATION, 20000, 10000) SET_MISSION_FLOW_FLAG_STATE(FLOWFLAG_SENT_PROXIMITY_MINE_EMAIL, TRUE) ENDIF ENDIF ENDIF //Homing missile email. IF NOT GET_MISSION_FLOW_FLAG_STATE(FLOWFLAG_SENT_HOMING_MISSILE_EMAIL) IF GET_MISSION_COMPLETE_STATE(SP_MISSION_EXILE_1) IF REGISTER_EMAIL_FROM_CHARACTER_TO_PLAYER(EMAIL_WEAPON_STOCK_11, CT_AMBIENT, BIT_MICHAEL|BIT_FRANKLIN|BIT_TREVOR, CHAR_AMMUNATION, 20000, 10000) SET_MISSION_FLOW_FLAG_STATE(FLOWFLAG_SENT_HOMING_MISSILE_EMAIL, TRUE) ENDIF ENDIF ENDIF ENDIF IF IS_MP_LUXE_PACK_PRESENT() //Knuckle duster email. IF NOT GET_MISSION_FLOW_FLAG_STATE(FLOWFLAG_SENT_KNUCKLE_DUSTER_EMAIL) IF GET_MISSION_COMPLETE_STATE(SP_MISSION_ARMENIAN_3) IF REGISTER_EMAIL_FROM_CHARACTER_TO_PLAYER(EMAIL_WEAPON_STOCK_12, CT_AMBIENT, BIT_MICHAEL|BIT_FRANKLIN|BIT_TREVOR, CHAR_AMMUNATION, 20000, 10000) SET_MISSION_FLOW_FLAG_STATE(FLOWFLAG_SENT_KNUCKLE_DUSTER_EMAIL, TRUE) ENDIF ENDIF ENDIF //Combat PDW email. IF NOT GET_MISSION_FLOW_FLAG_STATE(FLOWFLAG_SENT_COMBAT_PDW_EMAIL) IF GET_MISSION_COMPLETE_STATE(SP_HEIST_RURAL_PREP_1) IF REGISTER_EMAIL_FROM_CHARACTER_TO_PLAYER(EMAIL_WEAPON_STOCK_13, CT_AMBIENT, BIT_MICHAEL|BIT_FRANKLIN|BIT_TREVOR, CHAR_AMMUNATION, 20000, 10000) SET_MISSION_FLOW_FLAG_STATE(FLOWFLAG_SENT_COMBAT_PDW_EMAIL, TRUE) ENDIF ENDIF ENDIF //Marksman pistol email. IF NOT GET_MISSION_FLOW_FLAG_STATE(FLOWFLAG_SENT_MARKSMAN_PISTOL_EMAIL) IF GET_MISSION_COMPLETE_STATE(SP_MISSION_SOLOMON_1) IF REGISTER_EMAIL_FROM_CHARACTER_TO_PLAYER(EMAIL_WEAPON_STOCK_14, CT_AMBIENT, BIT_MICHAEL|BIT_FRANKLIN|BIT_TREVOR, CHAR_AMMUNATION, 20000, 10000) SET_MISSION_FLOW_FLAG_STATE(FLOWFLAG_SENT_MARKSMAN_PISTOL_EMAIL, TRUE) ENDIF ENDIF ENDIF ENDIF IF IS_MP_LOWRIDER_PACK_PRESENT() //Machete email. IF NOT GET_MISSION_FLOW_FLAG_STATE(FLOWFLAG_SENT_MACHETE_EMAIL) IF GET_MISSION_COMPLETE_STATE(SP_MISSION_TREVOR_2) IF REGISTER_EMAIL_FROM_CHARACTER_TO_PLAYER(EMAIL_WEAPON_STOCK_15, CT_AMBIENT, BIT_MICHAEL|BIT_FRANKLIN|BIT_TREVOR, CHAR_AMMUNATION, 20000, 10000) SET_MISSION_FLOW_FLAG_STATE(FLOWFLAG_SENT_MACHETE_EMAIL, TRUE) ENDIF ENDIF ENDIF //Machine Pistol email. IF NOT GET_MISSION_FLOW_FLAG_STATE(FLOWFLAG_SENT_MACHINE_PISTOL_EMAIL) IF GET_MISSION_COMPLETE_STATE(SP_MISSION_FRANKLIN_1) IF REGISTER_EMAIL_FROM_CHARACTER_TO_PLAYER(EMAIL_WEAPON_STOCK_16, CT_AMBIENT, BIT_MICHAEL|BIT_FRANKLIN|BIT_TREVOR, CHAR_AMMUNATION, 20000, 10000) SET_MISSION_FLOW_FLAG_STATE(FLOWFLAG_SENT_MACHINE_PISTOL_EMAIL, TRUE) ENDIF ENDIF ENDIF ENDIF ENDPROC #ENDIF PROC MAINTAIN_FEED_HIDE_WHILE_TRANSITIONING() IF IS_PLAYER_SWITCH_IN_PROGRESS() IF GET_FRAME_COUNT() % 30 = 0 CDEBUG1LN(DEBUG_INIT_SP, "Player switch in progress, hiding the feed.") ENDIF THEFEED_HIDE_THIS_FRAME() ENDIF ENDPROC PROC INIT_DLC_WEAPON_VARS(DLC_WEAPON_UNLOCK_VARS &sWeaponVars) sWeaponVars.iDLCWeaponCount = GET_NUM_DLC_WEAPONS() sWeaponVars.iFirstDLCWeaponIndex = 45 #IF IS_DEBUG_BUILD IF ENUM_TO_INT(WEAPON_DLC_BOTTLE_BIT_FIELD) != sWeaponVars.iFirstDLCWeaponIndex ASSERTLN(" THE WEAPONTYPE BITSET ORDERING HAS CHANGED - The SC unlocks will be unordered - Change sWeaponVars.IFirstDLCWeaponIndex to the correct index - Speak to Rowan Jones! - main - INIT_DLC_WEAPON_VARS") ENDIF PRINT_WEAPON_NAMES_AND_HASHES() #ENDIF ENDPROC PROC MAINTAIN_DLC_WEAPON_UNLOCKS( DLC_WEAPON_UNLOCK_VARS &sWeaponVars ) INT iWeaponID = GET_FRAME_COUNT() % sWeaponVars.iDLCWeaponCount IF GET_DLC_WEAPON_DATA(iWeaponID, sWeaponVars.weaponData) INT iWeaponUnlocked = IS_WEAPON_UNLOCKED_IN_FLOW( INT_TO_ENUM(WEAPON_TYPE, sWeaponVars.weaponData.m_nameHash) ) IF iWeaponUnlocked = 1 SET_DLC_WEAPON_SC_UNLOCKED_BIT( sWeaponVars ) ELIF iWeaponUnlocked = 0 CLEAR_DLC_WEAPON_SC_UNLOCKED_BIT( sWeaponVars ) ENDIF ENDIF ENDPROC //=========================================================================================================== SCRIPT CPRINTLN(DEBUG_INIT_SP, "Main.sc started.") IF (HAS_FORCE_CLEANUP_OCCURRED(FORCE_CLEANUP_FLAG_SP_TO_MP)) Script_Cleanup() ENDIF #IF IS_DEBUG_BUILD IF GET_COMMANDLINE_PARAM_EXISTS("sc_ForceCriminalEnterprisePremiumPackOn") g_bForce_PREMIUM_true = TRUE g_bForce_PREMIUM_false = FALSE ENDIF IF GET_COMMANDLINE_PARAM_EXISTS("sc_ForceCriminalEnterprisePremiumPackOff") g_bForce_PREMIUM_false = TRUE g_bForce_PREMIUM_true = FALSE ENDIF IF GET_COMMANDLINE_PARAM_EXISTS("sc_ForceCriminalEnterpriseStarterPackOn") g_bForce_STARTER_true = TRUE g_bForce_STARTER_false = FALSE ENDIF IF GET_COMMANDLINE_PARAM_EXISTS("sc_ForceCriminalEnterpriseStarterPackOff") g_bForce_STARTER_false = TRUE g_bForce_STARTER_true = FALSE ENDIF IF GET_COMMANDLINE_PARAM_EXISTS("sc_ForceHackerTruckOn") g_bForce_HACKER_TRUCK_true = TRUE g_bForce_HACKER_TRUCK_false = FALSE ENDIF IF GET_COMMANDLINE_PARAM_EXISTS("sc_ForceHackerTruckOff") g_bForce_HACKER_TRUCK_false = TRUE g_bForce_HACKER_TRUCK_true = FALSE ENDIF #ENDIF // Immediately set this FALSE now we know SP is running and we need to verify the character // model the player is loading. MAINTAIN_CHARACTER_MODEL_CHECK() will set this TRUE again. CPRINTLN(DEBUG_INIT_SP, "Main flagged to run a character mode validation check.") #IF USE_FINAL_PRINTS PRINTLN_FINAL("<2140379> Main flagged to run a character mode validation check.") #ENDIF SET_CHARACTER_MODEL_CHECK_DONE(FALSE) CLEAR_ALL_PRIORITY_HUD_ELEMENTS() CPRINTLN(DEBUG_INIT_SP, "Main.sc started waiting for Initial.sc") REQUEST_AND_LAUNCH_INITIAL_SCRIPT_WITH_WAIT() WHILE (GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(HASH("initial")) > 0) WAIT(0) ENDWHILE CPRINTLN(DEBUG_INIT, "Main.sc finished waiting for Initial.sc") #IF IS_DEBUG_BUILD //Validate enums. Code request TODO #252153. VALIDATE_ENUM_VALUES() OUTPUT_SCRIPT_IMAGE_CONFIGURATION_TO_CONSOLE_LOG() main_widget = START_WIDGET_GROUP("main.sc") STOP_WIDGET_GROUP() #ENDIF INITIALISE_SCRIPT_LAUNCH_CHECKS( #IF IS_DEBUG_BUILD main_widget #ENDIF ) BANK_INITIALISE_STARTING_BALANCES() SETUP_SLOW_ZONE_DATA(sSlowZoneVars) INIT_DLC_WEAPON_VARS( sDLCWeaponVars ) // Keith 15/7/13: To clear out any cross-session and joblist data when SP starts Initialise_SP_Joblist() // Calculate the initial target values for the PS4 activity feed. IF IS_PLAYSTATION_PLATFORM() ACTIVITY_FEED_INITIALISE_TARGET_VALUES(sActivityFeedVars) ENDIF // Unlock Director Mode characters for the current save progress. // Required when loading an old save after just patching in Director Mode. #IF FEATURE_SP_DLC_DIRECTOR_MODE CPRINTLN(DEBUG_DIRECTOR, "Unlocking Director Mode features as SP starts.") UNLOCK_ALL_DIRECTOR_PROGRESS_FOR_CURRENT_PLAYTHROUGH() #ENDIF DO_MISSION_STAT_INITIAL_CONFIGURATION() CHECK_REPLAY_MISSION_STAT_STATE() SET_CASINO_ROOFTOP_STATIC_EMITTERS(FALSE) // Check strip club is unlocked. IF g_savedGlobals.sFlow.missionSavedData[SP_MISSION_ARMENIAN_1].completed AND NOT (GET_MISSION_FLOW_BITSET_BIT_STATE(FLOWBITSET_MINIGAME_ACTIVE, ENUM_TO_INT(MINIGAME_STRIPCLUB))) CPRINTLN(DEBUG_INIT_SP, "Strip club locked when it shouldn't be on startup! Unlocking now.") SET_MISSION_FLOW_BITSET_BIT_STATE(FLOWBITSET_MINIGAME_ACTIVE, ENUM_TO_INT(MINIGAME_STRIPCLUB), TRUE) SET_STATIC_BLIP_ACTIVE_STATE(STATIC_BLIP_MINIGAME_STRIPCLUB, TRUE) ENDIF // enable prospero activity processing #IF FEATURE_GEN9_STANDALONE SET_ACTIVITY_SCRIPT_ROUTING_ENABLED(TRUE) #ENDIF //************************** // MAIN LOOP //************************** // This should be the last thing done before the main loop launches g_isSPMainInitialised = TRUE CPRINTLN(DEBUG_INIT_SP, "GTA5 starting main loop.") WHILE (TRUE) iGameTime = GET_GAME_TIMER() #IF IS_DEBUG_BUILD IF g_flowUnsaved.bUpdatingGameflow //Prevents a debug menu issue with blip flashing g_bBlipDebugPreventFlash = TRUE ENDIF #ENDIF #IF IS_DEBUG_BUILD RUN_CORE_SP_THREAD_CHECKS()// #ENDIF PROCESS_SP_HELP_MESSAGES(sFlowHelpMessageVars) //Help text displaying. UPDATE_CUTSCENE_CONTROL() //Off mission cutscene loading handshake system. DO_SCRIPT_LAUNCH_CHECKS(sScriptLaunchVars) //Script thread relaunch checks. MAINTAIN_CACHE_CLEARING() //added for maintenance of leaderboard cache Let me know if there are any issues. Conor McGuire MAINTAIN_FREE_PLAYER_PARACHUTE() MAINTAIN_FAMILY_CONTROLLER(sFriendControllerVars #IF IS_DEBUG_BUILD , main_widget #ENDIF ) PRIVATE_Safe_For_Cutscene_Update() PRIVATE_Cutscene_Failsafe_Update() UPDATE_SLOW_ZONES(sSlowZoneVars) //Forces the player to walk in specific areas of the map. MAINTAIN_MINIGAME_BLIP_STATES() MAINTAIN_GAUNTLET_SUPPRESSION() MAINTAIN_FIRST_PERSON_COVER_HELP() MAINTAIN_VEHICLE_DUCK_HELP() MAINTAIN_LAST_GEN_PLAYER_SE_AND_CE_CHECKS_IN_SP() //Make sure we detect if a player had SE/CE editions in last gen. MAINTAIN_DLC_WEAPON_UNLOCKS( sDLCWeaponVars ) IF IS_PLAYSTATION_PLATFORM() MAINTAIN_ACTIVITY_FEED_CHECKS(sActivityFeedVars) //The PS4 "What's New" Feed. ENDIF UPDATE_PROPERTIES_SYSTEM() //SP only for now. IF IS_XBOX_PLATFORM() MANAGE_MAGIC_MOMENTS() //SP only for now ENDIF // Keith 15/7/13: Every frame maintenance of cross-session invites being listed and accepted on the joblist (minimal processing if no invites) Maintain_SP_Joblist() MAINTAIN_MISSION_RECORDING_CLEANUP_CHECKS() // Run updates in here on a 1 second tick. IF iGameTime > iOneSecondTimer BANK_CHECK_FOR_CODE_DEPOSITS() //Keep singleplayer bank balances PRIVATE_Maintain_Phone_Sleep_Mode_Flag() MANAGE_SUB_CRUSH_DEPTH() //Kills player if in sub and it has crushed. MAINTAIN_JIMMY_VEHICLE_SUPPRESSED_CHECKS() //Validate our SP character model in case it has been hacked. #1945436 MAINTAIN_SP_CHARACTER_MODEL_CHECK() iOneSecondTimer = iGameTime + 1000 ENDIF // Run updates in here on a 5 second tick. IF iGameTime > iFiveSecondTimer MAINTAIN_FACEBOOK_ACCOUNT_LINKED_FEED() MAINTAIN_FACEBOOK_ALL_VEHICLES_DRIVEN_CHECKS() MAINTAIN_FACEBOOK_MAP_REVEALED_CHECKS() #IF IS_NEXTGEN_BUILD MAINTAIN_DLC_WEAPON_EMAILS() // MAINTAIN_CHRISTMAS2_DLC_WEAPON_EMAILS() #ENDIF iFiveSecondTimer = iGameTime + 5000 ENDIF MAINTAIN_INCOMING_PLAYER_CALLS() //MAINTAIN_DIRECTOR_LOCATION_REVEALED_CHECKS(eDirectorLocation) // Removed for B* 2412706 NOIR_UPDATE_EFFECTS(noirData) // updates film noir effects for murder mystery MAINTAIN_FEED_HIDE_WHILE_TRANSITIONING() WAIT(0) ENDWHILE ENDSCRIPT