USING "rage_builtins.sch" USING "globals.sch" USING "code_control_public.sch" USING "commands_brains.sch" USING "flow_public_core_override.sch" USING "mission_control_public.sch" USING "randomChar_private.sch" USING "replay_public.sch" USING "savegame_public.sch" USING "director_mode_public.sch" // ***************************************************************************************** // ***************************************************************************************** // ***************************************************************************************** // // MISSION NAME : randomChar_Public.sch // CREATED : Keith // MAINTAINED : Andrew Minghella // DESCRIPTION : Contains all Random Character public functions. // // ***************************************************************************************** // ***************************************************************************************** // ***************************************************************************************** /// PURPOSE: /// Return the state of the 'Completed' flag for this mission ID /// PARAMS: /// paramID - RC mission ID /// RETURNS: /// TRUE if this RC mission is already completed. FALSE otherwise FUNC BOOL IS_THIS_RANDOM_CHARACTER_MISSION_COMPLETED(g_eRC_MissionIDs paramID) IF ((paramID = MAX_RC_MISSIONS) OR (paramID = NO_RC_MISSION)) SCRIPT_ASSERT("ERROR: Is_This_Random_Character_Mission_Completed has been passed an illegal Random Character mission ID") RETURN FALSE ENDIF // Return the Completed state of this RC mission RETURN IS_BIT_SET(g_savedGlobals.sRandomChars.savedRC[paramID].rcFlags, ENUM_TO_INT(RC_FLAG_COMPLETED)) ENDFUNC /// PURPOSE: /// Is current RC blocked due to an active story mission? FUNC BOOL Random_Character_Blocked_Due_To_Mission(g_eRC_MissionIDs eRCMission) IF eRCMission = RC_TONYA_1 OR eRCMission = RC_TONYA_2 OR eRCMission = RC_TONYA_5 IF IS_MISSION_AVAILABLE(SP_MISSION_FRANKLIN_0) OR IS_MISSION_AVAILABLE(SP_MISSION_FRANKLIN_1) OR IS_MISSION_AVAILABLE(SP_MISSION_LAMAR) OR IS_MISSION_AVAILABLE(SP_MISSION_MICHAEL_2) RETURN TRUE ENDIF ENDIF //B*-2167022 IF eRCMission = RC_HAO_1 IF IS_MISSION_AVAILABLE(SP_MISSION_FRANKLIN_1) RETURN TRUE ENDIF ENDIF RETURN FALSE ENDFUNC /// PURPOSE: /// Returns whether or not this RC mission is allowed to launch if the player has a wanted level. /// PARAMS: /// eRCMission - RC mission we are checking /// RETURNS: /// TRUE if this RC is allowed to launch with the player wanted. FALSE otherwise FUNC BOOL Random_Character_Allows_Wanted_Level(g_eRC_MissionIDs eRCMission) // Missions which can be launched with a wanted level IF eRCMission = RC_BARRY_3A OR eRCMission = RC_BARRY_3C OR eRCMission = RC_NIGEL_1D OR eRCMission = RC_TONYA_3 OR eRCMission = RC_TONYA_4 RETURN TRUE ENDIF // Wanted level not allowed RETURN FALSE ENDFUNC /// PURPOSE: /// Is current RC blocked due to player being wanted? FUNC BOOL Random_Character_Blocked_Due_To_Wanted_Level(g_eRC_MissionIDs eRCMission) IF Random_Character_Allows_Wanted_Level(eRCMission) RETURN FALSE ELSE IF NOT IS_PED_INJURED(PLAYER_PED_ID()) IF (GET_PLAYER_WANTED_LEVEL(PLAYER_ID()) != 0) RETURN TRUE ENDIF ENDIF ENDIF RETURN FALSE ENDFUNC /// PURPOSE: /// Can the RC mission activate with the current player character? FUNC BOOL Random_Character_Blocked_Due_To_Character(g_eRC_MissionIDs eRCMission = NO_RC_MISSION) g_structRCMissionsStatic sRCMissionDetails Retrieve_Random_Character_Static_Mission_Details(eRCMission, sRCMissionDetails) // Check for valid SP character enumCharacterList eCurrChar = GET_CURRENT_PLAYER_PED_ENUM() IF eCurrChar = NO_CHARACTER CPRINTLN(DEBUG_RANDOM_CHAR, "Random_Character_Blocked_Due_To_Character: eCurrChar = NO CHARACTER : ", sRCMissionDetails.rcScriptName) RETURN TRUE ELIF eCurrChar <> CHAR_FRANKLIN AND eCurrChar <> CHAR_MICHAEL AND eCurrChar <> CHAR_TREVOR CPRINTLN(DEBUG_RANDOM_CHAR, "Random_Character_Blocked_Due_To_Character: eCurrChar = NOT PLAYABLE CHAR :", sRCMissionDetails.rcScriptName) RETURN TRUE ENDIF // Ensure the player is the correct character for this RCM IF NOT IS_BIT_SET(sRCMissionDetails.rcPlayableChars,ENUM_TO_INT(eCurrChar)) CPRINTLN(DEBUG_RANDOM_CHAR, "Random_Character_Blocked_Due_To_Character: eCurrChar = NOT CORRECT CHAR :", sRCMissionDetails.rcScriptName) RETURN TRUE ENDIF RETURN FALSE ENDFUNC /// PURPOSE: /// Checks if this specific mission is currently allowed to launch. /// If not allowed, the script should terminate. /// PARAMS: /// eRCMission - The Rc mission we are checking /// (Leave the eRCMission param to NO_RC_MISSION to auto detect mission ID.) /// RETURNS: /// TRUE if the misison is allowed to launch, false otherwsie. FUNC BOOL Random_Character_Is_Allowed_To_Launch(g_eRC_MissionIDs eRCMission = NO_RC_MISSION) g_structRCMissionsStatic sRCMissionDetails Retrieve_Random_Character_Static_Mission_Details(eRCMission, sRCMissionDetails) // Don't allow the mission to launch if another mission or activity is currently running // Will not cancel on switch scenes... IF NOT CAN_MISSION_TYPE_START_AGAINST_CURRENT_TYPE(MISSION_TYPE_RANDOM_CHAR) IF IS_THIS_RC_MISSION_BEING_PROCESSED_FOR_REPLAY(eRCMission) // only allow to run if a replay is being setup for this mission CPRINTLN(DEBUG_REPLAY, "Allowing RC to launch- it is being processed for a replay.", sRCMissionDetails.rcScriptName) ELSE CPRINTLN(DEBUG_RANDOM_CHAR, "Random_Character_Is_Allowed_To_Launch: Failed, player already on mission - terminate ", sRCMissionDetails.rcScriptName) RETURN FALSE ENDIF ENDIF IF IS_MISSION_LEADIN_WITH_HIGH_MEMORY_ACTIVE() AND NOT IS_HIGH_MEMORY_PC() CPRINTLN(DEBUG_RANDOM_CHAR, "Random_Character_Is_Allowed_To_Launch: Failed, mission with high memory active. Terminate.", sRCMissionDetails.rcScriptName) RETURN FALSE ENDIF IF Random_Character_Blocked_Due_To_Wanted_Level(eRCMission) CPRINTLN(DEBUG_RANDOM_CHAR, "Random_Character_Is_Allowed_To_Launch: Failed, player is wanted. Terminate.", sRCMissionDetails.rcScriptName) RETURN FALSE ENDIF // Retrieve the Random Character array index for this script IF eRCMission = NO_RC_MISSION eRCMission = Get_RC_MissionID_For_This_Script() ENDIF IF (eRCMission = NO_RC_MISSION) CPRINTLN(DEBUG_RANDOM_CHAR, "Random_Character_Is_Allowed_To_Launch: Failed. invalid RC mission. Terminate.", sRCMissionDetails.rcScriptName) RETURN FALSE ENDIF IF NOT IsThisRCBeingRepeatPlayed(ENUM_TO_INT(eRCMission)) // don't need these checks in rpeeat play // Ensure this Random Character mission is Activated IF NOT (Is_This_Random_Character_Mission_Active(eRCMission)) CPRINTLN(DEBUG_RANDOM_CHAR, "Random_Character_Is_Allowed_To_Launch: Failed. Not activated. Terminate ", sRCMissionDetails.rcScriptName) RETURN FALSE ENDIF // Ensure this Random Character mission is Ready To Play IF NOT (Is_This_Random_Character_Mission_Ready_To_Play(eRCMission)) CPRINTLN(DEBUG_RANDOM_CHAR, "Random_Character_Is_Allowed_To_Launch: Failed. Not ready to play ", sRCMissionDetails.rcScriptName) RETURN FALSE ENDIF // Ensure this Random Character mission is not Completed IF (Is_This_Random_Character_Mission_Completed(eRCMission)) CPRINTLN(DEBUG_RANDOM_CHAR, "Random_Character_Is_Allowed_To_Launch: Failed. Already completed ", sRCMissionDetails.rcScriptName) RETURN FALSE ENDIF ENDIF // Allow Tonya 1 to activate when in Franklin's safehouse in the event of reloading from an autosave (B*1324029) IF eRCMission = RC_TONYA_1 #if not USE_CLF_DLC #if not USE_NRM_DLC IF IS_PLAYER_IN_SAVEHOUSE(SAVEHOUSE_FRANKLIN_SC) CPRINTLN(DEBUG_RANDOM_CHAR, "Random_Character_Is_Allowed_To_Launch: Player is in safehouse, bypassing leave area check ", sRCMissionDetails.rcScriptName) g_RandomChars[eRCMission].rcLeaveAreaCheck = FALSE ENDIF #endif #endif ENDIF // Ensure this RC mission is not waiting for the player to leave the area IF g_RandomChars[eRCMission].rcLeaveAreaCheck = TRUE CPRINTLN(DEBUG_RANDOM_CHAR, "Random_Character_Is_Allowed_To_Launch: Waiting for player to leave area ", sRCMissionDetails.rcScriptName) RETURN FALSE ENDIF // Allowed to Launch CPRINTLN(DEBUG_RANDOM_CHAR, sRCMissionDetails.rcScriptName, " RC mission allowed to launch") RETURN TRUE ENDFUNC /// PURPOSE: /// Sets the RC as running, not passed and not failed. Called when it has permission to run /// PARAMS: /// eRCMission - ID of the RC mission we are setting as running PROC SET_RC_AS_RUNNING(g_eRC_MissionIDs eRCMission) CPRINTLN(DEBUG_RANDOM_CHAR, "SET_RC_AS_RUNNING()") g_RandomChars[eRCMission].rcIsRunning = TRUE g_RandomChars[eRCMission].rcPassed = FALSE g_RandomChars[eRCMission].rcFailed = FALSE g_RandomChars[eRCMission].rcTerminateLauncher = FALSE // The RC mission will set this to TRUE when up and running ENDPROC /// PURPOSE: /// Uses candidate ID system to try to get permission for specified RC mission to run. /// PARAMS: /// eRCMission - RC mission that wants to run /// ( Leave the eRCMission param to NO_RC_MISSION to auto detect mission ID.) /// RETURNS: /// TRUE if the RC mission has permission to run. FALSE otherwise. FUNC BOOL RC_REQUEST_PERMISSION_TO_RUN(g_eRC_MissionIDs eRCMission = NO_RC_MISSION) IF eRCMission = NO_RC_MISSION eRCMission = Get_RC_MissionID_For_This_Script() ENDIF IF (eRCMission = NO_RC_MISSION) SCRIPT_ASSERT("ERROR: RC_REQUEST_PERMISSION_TO_RUN has been passed an illegal Random Character mission ID") RETURN FALSE ENDIF m_enumMissionCandidateReturnValue allowLaunch = Request_Mission_Launch(g_RandomChars[eRCMission].rcMissionCandidateID, MCTID_MEET_CHARACTER, MISSION_TYPE_RANDOM_CHAR) #IF IS_DEBUG_BUILD g_structRCMissionsStatic sRCMissionDetails Retrieve_Random_Character_Static_Mission_Details(eRCMission, sRCMissionDetails) CPRINTLN(DEBUG_RANDOM_CHAR, "RC Controller - RC_REQUEST_PERMISSION_TO_RUN: ", sRCMissionDetails.rcScriptName) IF (allowLaunch = MCRET_DENIED) CPRINTLN(DEBUG_RANDOM_CHAR,"DENIED - so another mission must have launched so this Random Character should terminate") ENDIF IF (allowLaunch = MCRET_PROCESSING) CPRINTLN(DEBUG_RANDOM_CHAR,"PROCESSING - so this Random Character should keep trying") ENDIF IF (allowLaunch = MCRET_ACCEPTED) CPRINTLN(DEBUG_RANDOM_CHAR,"ACCEPTED - Random Character must run because it now has control of the IS_CURRENTLY_ON_MISSION_TO_TYPE() flag") ENDIF #ENDIF IF NOT (allowLaunch = MCRET_ACCEPTED) // DENIED or still PROCESSING. RETURN FALSE ENDIF // This mission has permission to launch SET_RC_AS_RUNNING(eRCMission) RETURN TRUE ENDFUNC /// PURPOSE: /// Checks if this RC launcher now needs to terminate. /// (If player has gone on another mission, got wanted level, is wrong character etc) /// PARAMS: /// eRCMission - the RC mission we are checking /// RETURNS: /// TRUE if the RC mission should now terminate. FALSE otherwise FUNC BOOL SHOULD_RC_TERMINATE(g_eRC_MissionIDs eRCMission = NO_RC_MISSION) IF eRCMission = NO_RC_MISSION eRCMission = Get_RC_MissionID_For_This_Script() ENDIF IF (eRCMission = NO_RC_MISSION) SCRIPT_ASSERT("ERROR: SHOULD_RC_TERMINATE has been passed an illegal Random Character mission ID") // Needs to terminate RETURN TRUE ENDIF // If this RC is being repeat played, we should never terminate here IF IsThisRCBeingRepeatPlayed(ENUM_TO_INT(eRCMission)) CPRINTLN(DEBUG_RANDOM_CHAR, GET_RC_MISSION_DISPLAY_STRING_FROM_ID(eRCMission), " is being repeat played. SHOULD_RC_TERMINATE = FALSE") RETURN FALSE ENDIF // Don't allow the mission to launch if another mission or activity is currently running // Will not cancel on switch scenes... IF NOT CAN_MISSION_TYPE_START_AGAINST_CURRENT_TYPE(MISSION_TYPE_RANDOM_CHAR) IF IS_THIS_RC_MISSION_BEING_PROCESSED_FOR_REPLAY(eRCMission) // Only allow to run if a replay is being setup for this mission CPRINTLN(DEBUG_REPLAY, "Allowing RC to launch- it is being processed for a replay.") ELSE CPRINTLN(DEBUG_RANDOM_CHAR,"SHOULD_RC_TERMINATE. Player is on another mission. Terminate.", GET_THIS_SCRIPT_NAME()) RETURN TRUE ENDIF ENDIF IF IS_MISSION_LEADIN_WITH_HIGH_MEMORY_ACTIVE() AND NOT IS_HIGH_MEMORY_PC() CPRINTLN(DEBUG_RANDOM_CHAR, "Random_Character_Is_Allowed_To_Launch: Failed, mission with high memory lead-in has activated. Terminate.") RETURN TRUE ENDIF // Don't allow the mission to launch if the player has a wanted level IF NOT Random_Character_Allows_Wanted_Level(eRCMission) IF NOT IS_PED_INJURED(PLAYER_PED_ID()) IF (GET_PLAYER_WANTED_LEVEL(PLAYER_ID()) != 0) CPRINTLN(DEBUG_RANDOM_CHAR,"SHOULD_RC_TERMINATE. Player has wanted level. Terminate.", GET_THIS_SCRIPT_NAME()) RETURN TRUE ENDIF ENDIF ENDIF // Don't allow the mission to launch if the 'Ready to play' flag has been cleared IF NOT (IS_BIT_SET(g_savedGlobals.sRandomChars.savedRC[ENUM_TO_INT(eRCMission)].rcFlags, ENUM_TO_INT(RC_FLAG_READY_TO_PLAY))) CPRINTLN(DEBUG_RANDOM_CHAR,"SHOULD_RC_TERMINATE. Ready to play flag has been cleared. Terminate.", GET_THIS_SCRIPT_NAME()) RETURN TRUE ENDIF // Doesn't need to terminate RETURN FALSE ENDFUNC /// PURPOSE: /// Checks if this RC launcher now needs to terminate when it is active as an invalid character FUNC BOOL SHOULD_RC_TERMINATE_WHEN_INCORRECT_CHAR(g_eRC_MissionIDs eRCMission) IF NOT IS_WORLD_POINT_WITHIN_BRAIN_ACTIVATION_RANGE() CPRINTLN(DEBUG_RANDOM_CHAR,"SHOULD_RC_TERMINATE_WHEN_INCORRECT_CHAR: NOT IS_WORLD_POINT_WITHIN_BRAIN_ACTIVATION_RANGE()") RETURN TRUE ENDIF IF IS_PLAYER_SWITCH_IN_PROGRESS() CPRINTLN(DEBUG_RANDOM_CHAR,"SHOULD_RC_TERMINATE_WHEN_INCORRECT_CHAR: IS_PLAYER_SWITCH_IN_PROGRESS()") RETURN TRUE ENDIF IF SHOULD_RC_TERMINATE(eRCMission) CPRINTLN(DEBUG_RANDOM_CHAR,"SHOULD_RC_TERMINATE_WHEN_INCORRECT_CHAR: SHOULD_RC_TERMINATE()") RETURN TRUE ENDIF RETURN FALSE ENDFUNC /// PURPOSE: /// Updates playstats, launches ambient scripts, executes code IDs, activates next RC mission /// Updates repeat play completion order. Sets completed bit PROC Set_Random_Character_Mission_Complete(g_eRC_MissionIDs eRCMission,bool bdebugJump = false) // Before we set the complete flag, check to see if we need to perform any more actions g_structRCMissionsStatic sRCMissionDetails Retrieve_Random_Character_Static_Mission_Details(eRCMission, sRCMissionDetails) // Launch ambient script? IF NOT ARE_STRINGS_EQUAL(sRCMissionDetails.rcAmbientPassScript, "") // Attempt to launch... WHILE NOT Random_Character_Launch_Ambient_Script(sRCMissionDetails.rcAmbientPassScript) WAIT(0) ENDWHILE ENDIF // Execute code ID? IF sRCMissionDetails.rcPassCodeID != CID_BLANK Execute_Code_ID(sRCMissionDetails.rcPassCodeID) ENDIF // Make Director Mode characters linked to this RC mission available to the player. #IF FEATURE_SP_DLC_DIRECTOR_MODE UNLOCK_DIRECTOR_STORY_CHAR_FOR_RC_MISSION(eRCMission, g_flowUnsaved.bUpdatingGameflow) #ENDIF if not bdebugJump // Unlock news story for RCM if it exists... INT iNewsStoryUnlock = GET_RCM_NEWS_STORY_UNLOCK(eRCMission) IF iNewsStoryUnlock != ENUM_TO_INT(NEWS_BLANK) CPRINTLN(DEBUG_FLOW, "Unlocked news story for ", GET_RC_MISSION_DISPLAY_STRING_FROM_ID(eRCMission)) if not IS_MISSION_NEWS_STORY_UNLOCKED(iNewsStoryUnlock) CPRINTLN(debug_flow,"Unlocking news story #",iNewsStoryUnlock) UNLOCK_MISSION_NEWS_STORY(iNewsStoryUnlock) endif ENDIF endif // Activate next RC mission? IF sRCMissionDetails.rcNextMission <> NO_RC_MISSION BOOL bActivateMission = TRUE // If this mission is part of a group, make sure all other missions in this group have // been marked as 'Completed' before we activate the next RC mission. IF sRCMissionDetails.rcMissionGroup <> NO_RC_MISSION_GROUP INT iMission g_structRCMissionsStatic sRCTempMissionDetails g_eRC_MissionIDs eRCTempMission REPEAT MAX_RC_MISSIONS iMission eRCTempMission = INT_TO_ENUM(g_eRC_MissionIDs, iMission) IF (eRCTempMission <> eRCMission) // Ignore this mission Retrieve_Random_Character_Static_Mission_Details(eRCTempMission, sRCTempMissionDetails) // In the same group? IF (sRCTempMissionDetails.rcMissionGroup = sRCMissionDetails.rcMissionGroup) IF NOT IS_BIT_SET(g_savedGlobals.sRandomChars.savedRC[eRCTempMission].rcFlags, ENUM_TO_INT(RC_FLAG_COMPLETED)) bActivateMission = FALSE ENDIF // Ensure that this mission has been Activated. IF NOT IS_BIT_SET(g_savedGlobals.sRandomChars.savedRC[eRCTempMission].rcFlags, ENUM_TO_INT(RC_FLAG_ACTIVATED)) // do we need to check RC_FLAG_ACTIVATED_IN_FLOW ? Random_Character_Activate_Mission(eRCTempMission) ENDIF ENDIF ENDIF ENDREPEAT ENDIF // Safe to activate next RC mission? IF bActivateMission Random_Character_Activate_Mission(sRCMissionDetails.rcNextMission) ENDIF // Activate next group of RC missions? ELIF sRCMissionDetails.rcNextMissionGroup <> NO_RC_MISSION_GROUP // Activate all missions that are part of this group. INT iMission g_structRCMissionsStatic sRCTempMissionDetails g_eRC_MissionIDs eRCTempMission // Grab all the individual missions that are part of the next group and activate. REPEAT MAX_RC_MISSIONS iMission eRCTempMission = INT_TO_ENUM(g_eRC_MissionIDs, iMission) IF (eRCTempMission <> eRCMission) // Ignore this mission Retrieve_Random_Character_Static_Mission_Details(eRCTempMission, sRCTempMissionDetails) // In the same group? IF (sRCTempMissionDetails.rcMissionGroup = sRCMissionDetails.rcNextMissionGroup) Random_Character_Activate_Mission(eRCTempMission) ENDIF ENDIF ENDREPEAT ENDIF // Pass procedure complete so set the Completed flag (only if not already flagged- used in debug skipping) IF NOT IS_BIT_SET(g_savedGlobals.sRandomChars.savedRC[ENUM_TO_INT(eRCMission)].rcFlags, ENUM_TO_INT(RC_FLAG_COMPLETED)) CPRINTLN(DEBUG_FLOW, "Flagging RC mission as completed + passed:", sRCMissionDetails.rcScriptName, " Variation:", sRCMissionDetails.rcStatVariation) SET_BIT(g_savedGlobals.sRandomChars.savedRC[ENUM_TO_INT(eRCMission)].rcFlags, ENUM_TO_INT(RC_FLAG_COMPLETED)) g_RandomChars[ENUM_TO_INT(eRCMission)].rcPassed = TRUE // Update repeat play completion order UpdateRCMissionRepeatCompletionOrder(ENUM_TO_INT(eRCMission)) // Set 100% completion stuff enumCompletionPercentageEntries eMissionCompletion = GET_RC_MISSION_COMPLETION_ID(eRCMission) IF eMissionCompletion != UNUSED_DEFAULT REGISTER_SCRIPT_IN_COMPLETION_PERCENTAGE_TOTAL(eMissionCompletion) CPRINTLN(DEBUG_FLOW, "Adding RC to 100% completion: ", GET_RC_MISSION_DISPLAY_STRING_FROM_ID(eRCMission)) ELSE CPRINTLN(DEBUG_FLOW, "Not adding RC to 100% completion as it has no completion percentage: ", GET_RC_MISSION_DISPLAY_STRING_FROM_ID(eRCMission)) ENDIF ENDIF ENDPROC /// PURPOSE: /// Sets flags needed to activate RC mission /// PARAMS: /// eRCTempMission - the RC mission we want to activate /// bCompleteMission - if True the mission is be set as completed. PROC Activate_RC_Mission(g_eRC_MissionIDs eRCTempMission, BOOL bCompleteMission) SET_BIT(g_savedGlobals.sRandomChars.savedRC[eRCTempMission].rcFlags, ENUM_TO_INT(RC_FLAG_ACTIVATED)) SET_BIT(g_savedGlobals.sRandomChars.savedRC[eRCTempMission].rcFlags, ENUM_TO_INT(RC_FLAG_ACTIVATED_IN_FLOW)) SET_BIT(g_savedGlobals.sRandomChars.savedRC[eRCTempMission].rcFlags, ENUM_TO_INT(RC_FLAG_READY_TO_PLAY)) IF bCompleteMission = TRUE Set_Random_Character_Mission_Complete(eRCTempMission,true) ENDIF ENDPROC /// PURPOSE: /// Sets flags needed to deactivate RC mission PROC Deactivate_RC_Mission(g_eRC_MissionIDs eRCTempMission) CLEAR_BIT(g_savedGlobals.sRandomChars.savedRC[eRCTempMission].rcFlags, ENUM_TO_INT(RC_FLAG_ACTIVATED)) CLEAR_BIT(g_savedGlobals.sRandomChars.savedRC[eRCTempMission].rcFlags, ENUM_TO_INT(RC_FLAG_ACTIVATED_IN_FLOW)) CLEAR_BIT(g_savedGlobals.sRandomChars.savedRC[eRCTempMission].rcFlags, ENUM_TO_INT(RC_FLAG_READY_TO_PLAY)) ENDPROC /// PURPOSE: /// Record that the Random Character mission passed, and perform any pass-specific functionality. /// PARAMS: /// bClearWantedLevel - Clears the wanted level PROC Random_Character_Passed(enumCompletionPercentageEntries eCompletionPercentage=UNUSED_DEFAULT, BOOL bClearWantedLevel=TRUE) // Retrieve the Random Character array index for this script g_eRC_MissionIDs eRCMission = Get_RC_MissionID_For_This_Script() IF (eRCMission = NO_RC_MISSION) SCRIPT_ASSERT("ERROR: Random_Character_Passed has been passed an illegal Random Character mission ID") EXIT ENDIF // Make sure that the Random Character was running IF NOT (g_RandomChars[eRCMission].rcIsRunning) CPRINTLN(DEBUG_RANDOM_CHAR, "ERROR: Random_Character_Passed But script wasn't running: ", GET_THIS_SCRIPT_NAME()) SCRIPT_ASSERT("RC Controller - Random_Character_Passed: Random Character Mission wasn't running") EXIT ENDIF // Make sure it hasn't already passed IF (g_RandomChars[eRCMission].rcPassed) CPRINTLN(DEBUG_RANDOM_CHAR, "ERROR: Random_Character_Passed But script has already passed: ", GET_THIS_SCRIPT_NAME()) SCRIPT_ASSERT("RC Controller - Random_Character_Passed: Random Character Mission has already passed") EXIT ENDIF // Make sure it hasn't already been classed as failed IF (g_RandomChars[eRCMission].rcFailed) CPRINTLN(DEBUG_RANDOM_CHAR, "ERROR: Random_Character_Passed But script already failed: ", GET_THIS_SCRIPT_NAME()) SCRIPT_ASSERT("RC Controller - Random_Character_Passed: Random Character Mission has already been classed as failed") EXIT ENDIF CPRINTLN(DEBUG_RANDOM_CHAR, "Random_Character_Passed: ", GET_THIS_SCRIPT_NAME()) // Do all of the RC complete stuff Set_Random_Character_Mission_Complete(eRCMission) SET_BIT(g_iRepeatPlayBits, ENUM_TO_INT(RPB_PASSED)) // Mark the mission as over // Ensure the mission candidate ID is valid IF (g_RandomChars[eRCMission].rcMissionCandidateID = NO_CANDIDATE_ID) CPRINTLN(DEBUG_RANDOM_CHAR, "Random_Character_Passed: invalid Mission Candidate System ID: ", GET_THIS_SCRIPT_NAME()) SCRIPT_ASSERT("RC Controller - Random_Character_Passed: Random Character Mission has an invalid Mission Candidate System ID") ELSE // ...the ID is valid, so inform Mission Candidate System that the mission is over CPRINTLN(DEBUG_REPLAY, "RC mission passed and calling mission over") Mission_Over(g_RandomChars[eRCMission].rcMissionCandidateID) ENDIF #IF IS_DEBUG_BUILD g_txtFlowAutoplayRunningMission = "NO MISSION" g_bFlowAutoplayJustPassed = TRUE #ENDIF // Clear the player's wanted level (on by default) IF bClearWantedLevel IF IS_PLAYER_PLAYING( PLAYER_ID() ) CPRINTLN(DEBUG_RANDOM_CHAR, "Random_Character_Passed: : Clearing wanted level and starting firing amnesty now") SET_PLAYER_WANTED_LEVEL(PLAYER_ID(), 0) SET_PLAYER_WANTED_LEVEL_NOW(PLAYER_ID()) START_FIRING_AMNESTY() ENDIF ENDIF // Call the common RC Mission Over procedure. RC_MISSION_OVER(eRCMission, TRUE, FALSE, FALSE) // Play mission passed audio and show passed screen. TRIGGER_MISSION_STATS_UI() // Set the last completed mission so that it appears on the savegame. TEXT_LABEL_15 tlRCMissionName = GET_RC_MISSION_NAME_LABEL(eRCMission) SET_LAST_COMPLETED_MISSION_STAT(tlRCMissionName, GET_CURRENT_PLAYER_PED_BIT()) // Remove headsets from player characters REMOVE_ALL_HEADSETS() //Restore phone's sleep mode if it was set before the mission. IF IS_BIT_SET(g_savedGlobals.sFlowCustom.spInitBitset, SP_INIT_RESTORE_SLEEP_MODE) SET_CELLPHONE_PROFILE_TO_SLEEP() ENDIF // Reset replay variables, so the game knows we are no longer on a replay Reset_All_Replay_Variables() // Tonya 3 and 4 registration IF eCompletionPercentage = CP_OJ_TOW3 OR eCompletionPercentage = CP_OJ_TOW4 REGISTER_SCRIPT_IN_COMPLETION_PERCENTAGE_TOTAL(eCompletionPercentage, 406.38, -1635.86) // Mrs Philips 2 ELIF eCompletionPercentage = CP_RAND_C_MRS2 REGISTER_SCRIPT_IN_COMPLETION_PERCENTAGE_TOTAL(eCompletionPercentage, 1973.84, 3814.89) // Register completion percentage ELIF eCompletionPercentage <> UNUSED_DEFAULT REGISTER_SCRIPT_IN_COMPLETION_PERCENTAGE_TOTAL(eCompletionPercentage) ENDIF // Save the game MAKE_AUTOSAVE_REQUEST() ENDPROC /// PURPOSE: /// Record that the Random Character mission failed and perform any fail-specific functionality. /// PARAMS: /// bSetupReplay - can this mission be replayed? PROC Random_Character_Failed(BOOL bSetupReplay = TRUE) // Set whether player gets warped when rejecting replay + update fail reason if killed / arrested // always need to check this, to handle player being killed during fail screen SET_FORCE_CLEANUP_FAIL_REASON() // this check is needed as it is possible to fail a mission and then get killed // during the fade (after mission already marked as failed, and replay is being processed) IF NOT IS_REPLAY_BEING_PROCESSED() // Retrieve the Random Character array index for this script g_eRC_MissionIDs eRCMission = Get_RC_MissionID_For_This_Script() IF (eRCMission = NO_RC_MISSION) SCRIPT_ASSERT("ERROR: Random_Character_Failed has been passed an illegal Random Character mission ID") EXIT ENDIF // Make sure that the Random Character was running IF NOT (g_RandomChars[eRCMission].rcIsRunning) CPRINTLN(DEBUG_RANDOM_CHAR, "Random_Character_Failed: Script wasn't running: ", GET_THIS_SCRIPT_NAME()) SCRIPT_ASSERT("RC Controller - Random_Character_Failed: Random Character Mission wasn't running") EXIT ENDIF // Make sure it hasn't already passed IF (g_RandomChars[eRCMission].rcPassed) CPRINTLN(DEBUG_RANDOM_CHAR, "Random_Character_Failed: RC has already been classed as passed: ", GET_THIS_SCRIPT_NAME()) SCRIPT_ASSERT("RC Controller - Random_Character_Failed: Random Character Mission has already been classed as passed") EXIT ENDIF // Make sure it hasn't already been classed as failed IF (g_RandomChars[eRCMission].rcFailed) CPRINTLN(DEBUG_RANDOM_CHAR, "Random_Character_Failed: RC has already been classed as failed: ", GET_THIS_SCRIPT_NAME()) SCRIPT_ASSERT("RC Controller - Random_Character_Failed: Random Character Mission has already failed") EXIT ENDIF CPRINTLN(DEBUG_RANDOM_CHAR, "Random_Character_Failed: ", GET_THIS_SCRIPT_NAME()) #IF IS_DEBUG_BUILD g_txtFlowAutoplayRunningMission = "NO MISSION" g_bFlowAutoplayJustPassed = FALSE #ENDIF //Increment the shitskip counter but only if the retry value is the same as last time IF g_iLastObservedRetryStatusOnFail = g_replayMissionStage g_savedGlobals.sRandomChars.savedRC[eRCMission].iFailsNoProgress++ CPRINTLN(DEBUG_REPLAY, "Mission fail without progress counter increased to ",g_savedGlobals.sRandomChars.savedRC[eRCMission].iFailsNoProgress) ENDIF // update the checkpoint we reached g_iLastObservedRetryStatusOnFail = g_replayMissionStage IF bSetupReplay // Tell the playstats system that we've failed an RC mission. SET_RC_MISSION_OVER_PLAYSTATS(eRCMission, TRUE, FALSE) // set up the replay Setup_RC_Replay(GET_THIS_SCRIPT_NAME(), ENUM_TO_INT(eRCMission)) ELSE // Mark the mission as over IF (g_RandomChars[eRCMission].rcMissionCandidateID = NO_CANDIDATE_ID) // Ensure the mission candidate ID is valid CPRINTLN(DEBUG_RANDOM_CHAR, "Random_Character_Failed: RC has an invalid Mission Candidate System ID: ", GET_THIS_SCRIPT_NAME()) SCRIPT_ASSERT("Random_Character_Failed: Random Character Mission has an invalid Mission Candidate System ID") ELSE // ...the ID is valid, so inform Mission Candidate System that the mission is over Mission_Over(g_RandomChars[eRCMission].rcMissionCandidateID) ENDIF // Call the common RC Mission Over procedure // (also called if player passes mission, or rejects replay) RC_MISSION_OVER(eRCMission, TRUE, TRUE, FALSE) ENDIF g_RandomChars[eRCMission].rcFailed = TRUE ENDIF ENDPROC /// PURPOSE: /// Record that the Random Character mission failed, and set the fail message that will appear. /// PARAMS: /// paramFailReason - fail reason for the mission failed screen /// paramSetupReplay - is this RC replayable? /// bDelayFade - should the replay controller delay the fade out for this fail reason PROC Random_Character_Failed_With_Reason(STRING paramFailReason, BOOL paramSetupReplay = TRUE) MISSION_FLOW_SET_FAIL_REASON(paramFailReason) Random_Character_Failed(paramSetupReplay) ENDPROC /// PURPOSE: /// Cleanup if the random character was running. /// RETURNS: /// TRUE if this random character mission had been triggered, FALSE if not triggered FUNC BOOL Random_Character_Cleanup_If_Triggered() // Retrieve the Random Character array index for this script g_eRC_MissionIDs eRCMission = Get_RC_MissionID_For_This_Script() IF (eRCMission = NO_RC_MISSION) SCRIPT_ASSERT("ERROR: Random_Character_Cleanup_If_Triggered has been passed an illegal Random Character mission ID") RETURN FALSE ENDIF IF NOT g_RandomChars[eRCMission].rcIsRunning CPRINTLN(DEBUG_RANDOM_CHAR, "Random_Character_Cleanup_If_Triggered: mission wasn't triggered. Basic cleanup.", GET_THIS_SCRIPT_NAME()) RETURN FALSE ENDIF // The mission had been triggered g_RandomChars[eRCMission].rcIsRunning = FALSE // Ensure mission brief is cleared CLEAR_ADDITIONAL_TEXT(MISSION_TEXT_SLOT, TRUE) CLEAR_ADDITIONAL_TEXT(MINIGAME_TEXT_SLOT, TRUE) // Used on Tonya RCM CLEAR_ADDITIONAL_TEXT(ODDJOB_TEXT_SLOT, TRUE) IF NOT IS_REPEAT_PLAY_ACTIVE() // These error checks are not needed in repeat play, as it uses it own passed / failed flag // Ensure it hasn't been classed as both passed and failed IF (g_RandomChars[eRCMission].rcPassed) AND (g_RandomChars[eRCMission].rcFailed) CPRINTLN(DEBUG_RANDOM_CHAR, "Random_Character_Cleanup_If_Triggered: is classed as having both passed and failed - TEMP TREATING AS PASSED.", GET_THIS_SCRIPT_NAME()) SCRIPT_ASSERT("Random_Character_Cleanup_If_Triggered: Random Character Mission is classed as having both passed and failed - TEMP TREATING AS PASSED") g_RandomChars[eRCMission].rcFailed = FALSE // Although an assert, allow it to continue to cleanup properly ENDIF // Ensure it has been classed as either passed or failed IF NOT (g_RandomChars[eRCMission].rcFailed) AND NOT (g_RandomChars[eRCMission].rcPassed) CPRINTLN(DEBUG_RANDOM_CHAR, "Random_Character_Cleanup_If_Triggered: is not classed as having passed or failed - TEMP TREATING AS FAILED.", GET_THIS_SCRIPT_NAME()) SCRIPT_ASSERT("Random_Character_Cleanup_If_Triggered: Random Character Mission is not classed as having passed or failed - TEMP TREATING AS FAILED") g_RandomChars[eRCMission].rcFailed = TRUE // Although an assert, allow it to continue to cleanup properly ENDIF ENDIF // Any other cleanup here to allow the random character mission to continue // Mission was running so probably needs additional cleanup CPRINTLN(DEBUG_RANDOM_CHAR, "Random_Character_Cleanup_If_Triggered: full clean up - mission was triggered - returning TRUE.", GET_THIS_SCRIPT_NAME()) RETURN TRUE ENDFUNC /// PURPOSE: /// Sets a flag telling the RC launcher that it needs to terminate PROC RC_CLEANUP_LAUNCHER() // Retrieve the Random Character array index for this script g_eRC_MissionIDs eRCMission = Get_RC_MissionID_For_This_Script() IF (eRCMission = NO_RC_MISSION) SCRIPT_ASSERT("ERROR: RC_CLEANUP_LAUNCHER has been passed an illegal Random Character mission ID") EXIT ENDIF CPRINTLN(DEBUG_RANDOM_CHAR, "RC_CLEANUP_LAUNCHER()") g_RandomChars[eRCMission].rcTerminateLauncher = TRUE ENDPROC /// PURPOSE: /// Sets a flag so the random character controller what state the mission is in. /// PARAMS: /// eRCMission - the RC misison we are using /// (Leave the eRCMission param to NO_RC_MISSION to auto detect mission ID) PROC SET_RC_AWAITING_TRIGGER(g_eRC_MissionIDs eRCMission = NO_RC_MISSION) // Retrieve the Random Character array index for this script IF eRCMission = NO_RC_MISSION eRCMission = Get_RC_MissionID_For_This_Script() ENDIF IF (eRCMission = NO_RC_MISSION) SCRIPT_ASSERT("ERROR: SET_RC_AWAITING_TRIGGER has been passed an illegal Random Character mission ID") EXIT ENDIF g_RandomChars[eRCMission].rcIsAwaitingTrigger = TRUE ENDPROC /// PURPOSE: /// Gets the mission ID of a RC mission which is valid, active and ready to play /// NOTES: /// This function is duplicated in comms_control_private.sch due to cyclic header error /// on compilation - please update both functions when making edits /// RETURNS: /// The mission ID of the nearest RC valid mission (NO_RC_MISSION is returned if nothing is found or the player isn't playing) FUNC g_eRC_MissionIDs GET_NEAREST_VALID_RC_MISSION(FLOAT fDistanceToCheck=RC_BRAIN_ACTIVATION_RANGE_EXTRA, BOOL bCheckPlayerChar=TRUE) // Mission and player info g_structRCMissionsStatic sRCMissionDetails g_eRC_MissionIDs eRCMission g_eRC_MissionIDs eNearestRCM = NO_RC_MISSION FLOAT fRCMDistance = fDistanceToCheck FLOAT fCurrentDist // Valid player check IF IS_PLAYER_PLAYING(PLAYER_ID()) #IF USE_TU_CHANGES IF IS_PLAYER_PED_PLAYABLE(GET_CURRENT_PLAYER_PED_ENUM()) #ENDIF INT iPlayerChar = GET_CURRENT_PLAYER_PED_BIT() // Iterate through all RCM's INT iMission = 0 REPEAT MAX_RC_MISSIONS iMission eRCMission = INT_TO_ENUM(g_eRC_MissionIDs, iMission) // RC mission is ready to play IF IS_BIT_SET(g_savedGlobals.sRandomChars.savedRC[ENUM_TO_INT(eRCMission)].rcFlags, ENUM_TO_INT(RC_FLAG_READY_TO_PLAY)) AND NOT IS_BIT_SET(g_savedGlobals.sRandomChars.savedRC[ENUM_TO_INT(eRCMission)].rcFlags, ENUM_TO_INT(RC_FLAG_COMPLETED)) // Get the RCM information (only really need the trigger coords) Retrieve_Random_Character_Static_Mission_Details(eRCMission, sRCMissionDetails) // Is this RCM within specified distance and nearer to the player than any previously stored RCM? fCurrentDist = GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID(), FALSE),sRCMissionDetails.rcCoords) IF (fCurrentDist < fRCMDistance) BOOL bValidMission = TRUE // Is the player currently the correct character for this RCM? IF bCheckPlayerChar IF iPlayerChar <> sRCMissionDetails.rcPlayableChars bValidMission = FALSE ENDIF ENDIF // Store this as the nearest RCM IF bValidMission eNearestRCM = eRCMission fRCMDistance = fCurrentDist ENDIF ENDIF ENDIF ENDREPEAT #IF USE_TU_CHANGES ENDIF #ENDIF ENDIF // Return nearest valid RCM (NO_RC_MISSION if nothing is found...) RETURN eNearestRCM ENDFUNC /// PURPOSE: /// Check to see if a random char mission is available /// PARAMS: /// paramRCMission - Mission id /// RETURNS: /// True if it is, false if it isn't FUNC BOOL IS_RC_MISSION_AVAILABLE(g_eRC_MissionIDs paramRCMission) RETURN g_RandomChars[paramRCMission].rcIsAwaitingTrigger ENDFUNC /// PURPOSE: /// Checks if a post RC script should terminate due to character switch /// Or a mission trigger scene being active etc /// PARAMS: /// eChar - the character the play was in this mission /// RETURNS: /// TRUE if script should terminate, FALSE otherwise FUNC BOOL SHOULD_POST_RC_SCRIPT_TERMINATE(enumCharacterList eChar) IF NOT (GET_CURRENT_PLAYER_PED_ENUM() = eChar) OR IS_CURRENTLY_ON_MISSION_OF_ANY_TYPE() OR IS_MISSION_LEADIN_ACTIVE() OR g_iOffMissionCutsceneRequestActive <> NULL_OFFMISSION_CUTSCENE_REQUEST IF NOT (GET_CURRENT_PLAYER_PED_ENUM() = CHAR_FRANKLIN) CPRINTLN(DEBUG_RANDOM_CHAR, "POSTRC Script termination! - swapped character. ", GET_THIS_SCRIPT_NAME()) ENDIF IF IS_CURRENTLY_ON_MISSION_OF_ANY_TYPE() CPRINTLN(DEBUG_RANDOM_CHAR, "POSTRC Script termination! - gone on mission. ", GET_THIS_SCRIPT_NAME()) ENDIF IF IS_MISSION_LEADIN_ACTIVE() CPRINTLN(DEBUG_RANDOM_CHAR, "POSTRC Script termination! - lead in active. ", GET_THIS_SCRIPT_NAME()) ENDIF IF g_iOffMissionCutsceneRequestActive <> NULL_OFFMISSION_CUTSCENE_REQUEST CPRINTLN(DEBUG_RANDOM_CHAR, "POSTRC Script termination! -cut-scene requested. ", GET_THIS_SCRIPT_NAME()) ENDIF ENDIF RETURN FALSE ENDFUNC FUNC BOOL IS_RC_LEADIN_ACTIVE() RETURN g_iNoRCLeadinsActive > 0 ENDFUNC