Files
gtav-src/script/dev_ng/singleplayer/include/public/mission_repeat_public.sch
T
2025-09-29 00:52:08 +02:00

997 lines
35 KiB
XML
Executable File

//╒═════════════════════════════════════════════════════════════════════════════╕
//│ Author: Ben Rollinson Date: 14/09/11 │
//╞═════════════════════════════════════════════════════════════════════════════╡
//│ │
//│ Mission Repeat System - Public Script Interface │
//│ │
//│ This header contains all public script commands used by │
//│ the mission repeat system. This system allows replaying of │
//│ missions that have already been completed by the player. │
//│ │
//╘═════════════════════════════════════════════════════════════════════════════╛
USING "rage_builtins.sch"
USING "globals.sch"
USING "commands_entity.sch"
USING "commands_stats.sch"
USING "commands_dlc.sch"
USING "commands_decorator.sch"
USING "dlc_mission_stat_private.sch"
#IF USE_CLF_DLC
USING "mission_stat_generated_private_CLF.sch"
#ENDIF
#IF NOT USE_CLF_DLC
USING "mission_stat_generated_private.sch"
#ENDIF
#IF NOT USE_SP_DLC
USING "randomchar_private_gta5.sch"
#ENDIF
/// PURPOSE:
/// this has to live here to fix cyclic header
/// PARAMS:
/// paramMission -
/// RETURNS:
///
FUNC TEXT_LABEL_7 GET_SP_MISSION_NAME_LABEL(SP_MISSIONS paramMission)
TEXT_LABEL_7 txtMissionName = "M_"
txtMissionName += g_sMissionStaticData[paramMission].statID
#IF NOT USE_SP_DLC
//Special case for the Jewelry Heist. Work out if we should use the A or B choice label.
IF paramMission = SP_HEIST_JEWELRY_2
SWITCH g_savedGlobals.sFlow.controls.intIDs[FLOWINT_HEIST_CHOICE_JEWEL]
CASE HEIST_CHOICE_JEWEL_STEALTH
txtMissionName += "A"
BREAK
CASE HEIST_CHOICE_JEWEL_HIGH_IMPACT
txtMissionName += "B"
BREAK
DEFAULT
txtMissionName += "A"
BREAK
ENDSWITCH
ENDIF
#ENDIF
RETURN txtMissionName
ENDFUNC
/// PURPOSE:
/// update's the eyefind news story state enum
/// PARAMS:
/// iMissionindex - mission
/// bIsRCMission - if this is an RC mission else SP
#IF USE_CLF_DLC
PROC UPDATE_EYEFIND_CURRENT_NEWS_STORY_STATECLF(INT iMissionindex, BOOL bIsRCMission)
EYEFIND_NEWS_STORY_STATE_ENUM eNewStoryState = EYEFIND_NEWS_STORY_STATE_INVALID
SP_MISSIONS eSPMission = INT_TO_ENUM(SP_MISSIONS, iMissionindex)
//Story Mission
IF eSPMission = SP_MISSION_CLF_TRAIN
ENDIF
eNewStoryState = eNewStoryState
bIsRCMission = bIsRCMission
ENDPROC
#ENDIF
#IF USE_NRM_DLC
PROC UPDATE_EYEFIND_CURRENT_NEWS_STORY_STATENRM(INT iMissionindex, BOOL bIsRCMission)
EYEFIND_NEWS_STORY_STATE_ENUM eNewStoryState = EYEFIND_NEWS_STORY_STATE_INVALID
SP_MISSIONS eSPMission = INT_TO_ENUM(SP_MISSIONS, iMissionindex)
//Story Mission
IF eSPMission = SP_MISSION_NRM_SUR_START
ELIF eSPMission = SP_MISSION_NRM_SUR_AMANDA
ELIF eSPMission = SP_MISSION_NRM_SUR_TRACEY
ELIF eSPMission = SP_MISSION_NRM_SUR_MICHAEL
ELIF eSPMission = SP_MISSION_NRM_SUR_HOME
ELIF eSPMission = SP_MISSION_NRM_SUR_JIMMY
ELIF eSPMission = SP_MISSION_NRM_SUR_PARTY
ELIF eSPMission = SP_MISSION_NRM_SUR_CURE
ELIF eSPMission = SP_MISSION_NRM_RESCUE_ENG
ELIF eSPMission = SP_MISSION_NRM_RESCUE_MED
ELIF eSPMission = SP_MISSION_NRM_RESCUE_GUN
ELIF eSPMission = SP_MISSION_NRM_SUP_FUEL
ELIF eSPMission = SP_MISSION_NRM_SUP_AMMO
ELIF eSPMission = SP_MISSION_NRM_SUP_MEDS
ELIF eSPMission = SP_MISSION_NRM_SUP_FOOD
ELIF eSPMission = SP_MISSION_NRM_RADIO_A
ELIF eSPMission = SP_MISSION_NRM_RADIO_B
ELIF eSPMission = SP_MISSION_NRM_RADIO_C
ENDIF
eNewStoryState = eNewStoryState
bIsRCMission = bIsRCMission
ENDPROC
#ENDIF
PROC UPDATE_EYEFIND_CURRENT_NEWS_STORY_STATE(INT iMissionindex, BOOL bIsRCMission)
#IF USE_CLF_DLC
UPDATE_EYEFIND_CURRENT_NEWS_STORY_STATECLF(iMissionindex,bIsRCMission)
#ENDIF
#IF USE_NRM_DLC
UPDATE_EYEFIND_CURRENT_NEWS_STORY_STATENRM(iMissionindex,bIsRCMission)
#ENDIF
#IF NOT USE_SP_DLC
EYEFIND_NEWS_STORY_STATE_ENUM eNewStoryState = EYEFIND_NEWS_STORY_STATE_INVALID
// RC mission
IF bIsRCMission
g_eRC_MissionIDs eRcMission = INT_TO_ENUM(g_eRC_MissionIDs, iMissionindex)
IF eRcMission = RC_PAPARAZZO_1
eNewStoryState = EYEFIND_NEWS_STORY_STATE_RC_PAP1
ELIF eRcMission = RC_PAPARAZZO_3A
eNewStoryState = EYEFIND_NEWS_STORY_STATE_RC_PAP3A
ELIF eRcMission = RC_PAPARAZZO_3B
eNewStoryState = EYEFIND_NEWS_STORY_STATE_RC_PAP3B
ELIF eRcMission = RC_DREYFUSS_1
eNewStoryState = EYEFIND_NEWS_STORY_STATE_RC_DRF1
ELIF eRcMission = RC_EPSILON_8
eNewStoryState = EYEFIND_NEWS_STORY_STATE_RC_EPN8
ELIF eRcMission = RC_NIGEL_1A
eNewStoryState = EYEFIND_NEWS_STORY_STATE_RC_NIG1A
ELIF eRcMission = RC_NIGEL_1B
eNewStoryState = EYEFIND_NEWS_STORY_STATE_RC_NIG1B
ELIF eRcMission = RC_NIGEL_1C
eNewStoryState = EYEFIND_NEWS_STORY_STATE_RC_NIG1C
ELIF eRcMission = RC_NIGEL_1D
eNewStoryState = EYEFIND_NEWS_STORY_STATE_RC_NIG1D
ELIF eRcMission = RC_NIGEL_2
eNewStoryState = EYEFIND_NEWS_STORY_STATE_RC_NIG2
ELIF eRcMission = RC_NIGEL_3
eNewStoryState = EYEFIND_NEWS_STORY_STATE_RC_NIG3
ELIF eRcMission = RC_EXTREME_4
eNewStoryState = EYEFIND_NEWS_STORY_STATE_RC_EXT4
ENDIF
// Story Mission
ELSE
SP_MISSIONS eSPMission = INT_TO_ENUM(SP_MISSIONS, iMissionindex)
//Story Mission
IF eSPMission = SP_MISSION_PROLOGUE
eNewStoryState = EYEFIND_NEWS_STORY_STATE_SP_PRO
ELIF eSPMission = SP_MISSION_ARMENIAN_2
eNewStoryState = EYEFIND_NEWS_STORY_STATE_SP_ARM2
ELIF eSPMission = SP_MISSION_ARMENIAN_3
eNewStoryState = EYEFIND_NEWS_STORY_STATE_SP_ARM3
ELIF eSPMission = SP_MISSION_FAMILY_1
eNewStoryState = EYEFIND_NEWS_STORY_STATE_SP_FAM1
ELIF eSPMission = SP_MISSION_FAMILY_3
eNewStoryState = EYEFIND_NEWS_STORY_STATE_SP_FAM3
ELIF eSPMission = SP_MISSION_LAMAR
eNewStoryState = EYEFIND_NEWS_STORY_STATE_SP_LAM1
ELIF eSPMission = SP_MISSION_LESTER_1
eNewStoryState = EYEFIND_NEWS_STORY_STATE_SP_LST1
ELIF eSPMission = SP_MISSION_TREVOR_2
eNewStoryState = EYEFIND_NEWS_STORY_STATE_SP_TRE2
ELIF eSPMission = SP_MISSION_CHINESE_1
eNewStoryState = EYEFIND_NEWS_STORY_STATE_SP_CHI1
ELIF eSPMission = SP_MISSION_CHINESE_2
eNewStoryState = EYEFIND_NEWS_STORY_STATE_SP_CHI2
ELIF eSPMission = SP_MISSION_TREVOR_3
eNewStoryState = EYEFIND_NEWS_STORY_STATE_SP_TRE3
ELIF eSPMission = SP_MISSION_FAMILY_4
eNewStoryState = EYEFIND_NEWS_STORY_STATE_SP_FAM4
ELIF eSPMission = SP_MISSION_FBI_2
eNewStoryState = EYEFIND_NEWS_STORY_STATE_SP_FIB2
ELIF eSPMission = SP_MISSION_FBI_3
eNewStoryState = EYEFIND_NEWS_STORY_STATE_SP_FIB3
ELIF eSPMission = SP_MISSION_FRANKLIN_1
eNewStoryState = EYEFIND_NEWS_STORY_STATE_SP_FRA1
ELIF eSPMission = SP_MISSION_FBI_4
eNewStoryState = EYEFIND_NEWS_STORY_STATE_SP_FIB4
ELIF eSPMission = SP_MISSION_CARSTEAL_2
eNewStoryState = EYEFIND_NEWS_STORY_STATE_SP_CARS2
ELIF eSPMission = SP_MISSION_SOLOMON_1
eNewStoryState = EYEFIND_NEWS_STORY_STATE_SP_SOL1
ELIF eSPMission = SP_MISSION_MARTIN_1
eNewStoryState = EYEFIND_NEWS_STORY_STATE_SP_MTN1
ELIF eSPMission = SP_MISSION_CARSTEAL_3
eNewStoryState = EYEFIND_NEWS_STORY_STATE_SP_CARS3
ELIF eSPMission = SP_MISSION_EXILE_1
eNewStoryState = EYEFIND_NEWS_STORY_STATE_SP_EXL1
ELIF eSPMission = SP_MISSION_EXILE_3
eNewStoryState = EYEFIND_NEWS_STORY_STATE_SP_EXL3
ELIF eSPMission = SP_MISSION_FBI_5
eNewStoryState = EYEFIND_NEWS_STORY_STATE_SP_FIB5
ELIF eSPMission = SP_MISSION_MICHAEL_1
eNewStoryState = EYEFIND_NEWS_STORY_STATE_SP_MIC1
ELIF eSPMission = SP_MISSION_SOLOMON_2
eNewStoryState = EYEFIND_NEWS_STORY_STATE_SP_SOL2
ELIF eSPMission = SP_MISSION_FAMILY_6
eNewStoryState = EYEFIND_NEWS_STORY_STATE_SP_FAM6
ELIF eSPMission = SP_MISSION_MICHAEL_3
eNewStoryState = EYEFIND_NEWS_STORY_STATE_SP_MIC3
ELIF eSPMission = SP_MISSION_SOLOMON_3
eNewStoryState = EYEFIND_NEWS_STORY_STATE_SP_SOL3
ELIF eSPMission = SP_MISSION_MICHAEL_4
eNewStoryState = EYEFIND_NEWS_STORY_STATE_SP_MIC4
ELIF eSPMission = SP_MISSION_FINALE_C2 // story only makes sense if player takes C2 (save Mike and Trev)
eNewStoryState = EYEFIND_NEWS_STORY_STATE_SP_FINALE
//Assasinations
ELIF eSPMission = SP_MISSION_ASSASSIN_1
eNewStoryState = EYEFIND_NEWS_STORY_STATE_SP_ASS1
ELIF eSPMission = SP_MISSION_ASSASSIN_2
eNewStoryState = EYEFIND_NEWS_STORY_STATE_SP_ASS2
ELIF eSPMission = SP_MISSION_ASSASSIN_3
eNewStoryState = EYEFIND_NEWS_STORY_STATE_SP_ASS3
ELIF eSPMission = SP_MISSION_ASSASSIN_4
eNewStoryState = EYEFIND_NEWS_STORY_STATE_SP_ASS4
ELIF eSPMission = SP_MISSION_ASSASSIN_5
eNewStoryState = EYEFIND_NEWS_STORY_STATE_SP_ASS5
//Shrink
ELIF eSPMission = SP_MISSION_SHRINK_5
eNewStoryState = EYEFIND_NEWS_STORY_STATE_SP_SHK5
// Heist
ELIF eSPMission = SP_HEIST_JEWELRY_2
eNewStoryState = EYEFIND_NEWS_STORY_STATE_SP_H_JWL
ELIF eSPMission = SP_HEIST_DOCKS_2A
OR eSPMission = SP_HEIST_DOCKS_2B
eNewStoryState = EYEFIND_NEWS_STORY_STATE_SP_H_DOCK
ELIF eSPMission = SP_HEIST_RURAL_2
eNewStoryState = EYEFIND_NEWS_STORY_STATE_SP_H_RB2A
ELIF eSPMission = SP_HEIST_AGENCY_3A
OR eSPMission = SP_HEIST_AGENCY_3B
eNewStoryState = EYEFIND_NEWS_STORY_STATE_SP_H_AG3A
ELIF eSPMission = SP_HEIST_FINALE_2A
or eSPMission = SP_HEIST_FINALE_2B
eNewStoryState = EYEFIND_NEWS_STORY_STATE_SP_H_BS2A
ENDIF
ENDIF
IF eNewStoryState != EYEFIND_NEWS_STORY_STATE_INVALID
g_savedGlobals.sFinanceData.eCurrentEyeFindNewsStoryState = eNewStoryState
CPRINTLN(DEBUG_INTERNET, GET_THIS_SCRIPT_NAME(), " UPDATE_EYEFIND_CURRENT_NEWS_STORY_STATE() : updated eCurrentEyeFindNewsStoryState = ", eNewStoryState)
ENDIF
#ENDIF
ENDPROC
/// PURPOSE:
/// Checks if a the player is playing barber chair anims or doing barber intro
/// RETURNS:
/// TRUE if player playing haircut anims. FALSE otherwise
FUNC BOOL IS_PLAYER_IN_BARBER_CHAIR_OR_DOING_BARBER_INTRO()
IF NOT IS_ENTITY_DEAD(PLAYER_PED_ID())
AND NOT IS_PED_INJURED(PLAYER_PED_ID())
IF IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(),"misshair_shop@barbers","player_intro")
OR IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(),"misshair_shop@barbers","player_base")
OR IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(),"misshair_shop@barbers","player_enterchair")
OR IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(),"misshair_shop@barbers","player_exitchair")
OR IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(),"misshair_shop@barbers","player_idle_a")
OR IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(),"misshair_shop@barbers","player_idle_b")
OR IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(),"misshair_shop@barbers","player_idle_c")
OR IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(),"misshair_shop@barbers","player_idle_d")
OR IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(),"misshair_shop@hair_dressers","player_intro")
OR IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(),"misshair_shop@hair_dressers","player_base")
OR IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(),"misshair_shop@hair_dressers","player_enterchair")
OR IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(),"misshair_shop@hair_dressers","player_exitchair")
OR IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(),"misshair_shop@hair_dressers","player_idle_a")
OR IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(),"misshair_shop@hair_dressers","player_idle_b")
OR IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(),"misshair_shop@hair_dressers","player_idle_c")
OR IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(),"misshair_shop@hair_dressers","player_idle_d")
RETURN TRUE
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// Checks if a player is in the mod shop
/// RETURNS:
/// TRUE if in shop. FALSE otherwise
FUNC BOOL IS_PLAYER_BROWSING_MOD_SHOP()
RETURN IS_BIT_SET(g_iRepeatPlayBits, ENUM_TO_INT(RPB_PLAYER_BROWSING_MOD_SHOP))
ENDFUNC
/// PURPOSE:
/// Checks if a player is browsing tattoos in a tattoo shop
/// RETURNS:
/// TRUE if in shop. FALSE otherwise
FUNC BOOL IS_PLAYER_BROWSING_TATTOO_SHOP()
RETURN IS_BIT_SET(g_iRepeatPlayBits, ENUM_TO_INT(RPB_PLAYER_BROWSING_TATTOO_SHOP))
ENDFUNC
/// PURPOSE:
/// Checks if a mission is being replayed via the "Replay Mission" pause menu
/// RETURNS:
/// TRUE if repeat play is active. FALSE otherwise
FUNC BOOL IS_REPEAT_PLAY_ACTIVE(BOOL bIgnoreBenchmark = FALSE)
//Also return true if running the benchmark script - considered a replay
IF (NOT bIgnoreBenchmark) AND GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(HASH("benchmark"))>0
RETURN TRUE
ENDIF
RETURN IS_BIT_SET(g_iRepeatPlayBits, ENUM_TO_INT(RPB_ACTIVE))
ENDFUNC
/// PURPOSE:
/// Tells the repeat play controller to launch repeat play of mission specified
/// PARAMS:
/// iMissionIndex - index of appropriate array
/// eMissionType - CP_GROUP_MISSIONS / CP_GROUP_MISSIONS
PROC LaunchRepeatPlay(INT iMissionIndex, enumGrouping eMissionType)
g_RepeatPlayData.iMissionIndex = iMissionIndex
g_RepeatPlayData.eMissionType = eMissionType
//Ensure RC mission leave area flags are activated as soon as we start setting up a repeat play.
IF eMissionType = CP_GROUP_RANDOMCHARS
IF iMissionIndex >= 0 AND iMissionIndex < ENUM_TO_INT(MAX_RC_MISSIONS)
g_RandomChars[iMissionIndex].rcLeaveAreaCheck = TRUE
ENDIF
ENDIF
SET_BIT(g_iRepeatPlayBits, ENUM_TO_INT(RPB_ACTIVE))
ENDPROC
/// PURPOSE:
/// Checks if repeat play is active and if it is this RC that is being repeat played
/// PARAMS:
/// iMissionIndex - index of RC in RC array
/// RETURNS:
/// TRUE if this RC mission is being repeat played, FALSE otherwise
FUNC BOOL IsThisRCBeingRepeatPlayed(INT iMissionIndex)
IF IS_REPEAT_PLAY_ACTIVE()
IF g_RepeatPlayData.eMissionType = CP_GROUP_RANDOMCHARS
IF g_RepeatPlayData.iMissionIndex = iMissionIndex
// This RC is being repeat played
RETURN TRUE
ENDIF
ENDIF
ENDIF
// This RC is not being repeat played
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// Returns the text label of the mission name for selected mission
/// PARAMS:
/// iMissionIndex - index of appropriate array
/// eMissionType - CP_GROUP_MISSIONS / CP_GROUP_MISSIONS
/// RETURNS:
/// the text label of the mission name
#IF USE_CLF_DLC
FUNC TEXT_LABEL_7 GetRepeatPlayMissionNameCLF(INT iMissionIndex, enumGrouping eMissionType)
TEXT_LABEL_7 tMissionNameLabel = ""
SWITCH eMissionType
CASE CP_GROUP_MISSIONS
// other missions
tMissionNameLabel = "M_"
tMissionNameLabel += g_sMissionStaticData[iMissionIndex].statID
BREAK
DEFAULT
CPRINTLN(DEBUG_REPEAT,"GetRepeatPlayMissionName passed a mission type that isn't repeat playable: ", eMissionType)
BREAK
ENDSWITCH
RETURN tMissionNameLabel
ENDFUNC
#ENDIF
#IF USE_NRM_DLC
FUNC TEXT_LABEL_7 GetRepeatPlayMissionNameNRM(INT iMissionIndex, enumGrouping eMissionType)
TEXT_LABEL_7 tMissionNameLabel = ""
SWITCH eMissionType
CASE CP_GROUP_MISSIONS
// other missions
tMissionNameLabel = "M_"
tMissionNameLabel += g_sMissionStaticData[iMissionIndex].statID
BREAK
DEFAULT
CPRINTLN(DEBUG_REPEAT,"GetRepeatPlayMissionName passed a mission type that isn't repeat playable: ", eMissionType)
BREAK
ENDSWITCH
RETURN tMissionNameLabel
ENDFUNC
#ENDIF
FUNC TEXT_LABEL_7 GetRepeatPlayMissionName(INT iMissionIndex, enumGrouping eMissionType)
#IF USE_CLF_DLC
RETURN GetRepeatPlayMissionNameCLF(iMissionIndex,eMissionType)
#ENDIF
#IF USE_NRM_DLC
RETURN GetRepeatPlayMissionNameNRM(iMissionIndex,eMissionType)
#ENDIF
#IF NOT USE_SP_DLC
TEXT_LABEL_7 tMissionNameLabel = ""
SWITCH eMissionType
CASE CP_GROUP_MISSIONS
// Special case to overwrite the Gauntlet mission names
IF (INT_TO_ENUM(SP_MISSIONS, iMissionIndex) = SP_HEIST_FINALE_PREP_C1
OR INT_TO_ENUM(SP_MISSIONS, iMissionIndex) = SP_HEIST_FINALE_PREP_C2
OR INT_TO_ENUM(SP_MISSIONS, iMissionIndex) = SP_HEIST_FINALE_PREP_C3)
tMissionNameLabel += g_sMissionStaticData[iMissionIndex].statID
tMissionNameLabel += "A"
ELSE
// other missions
tMissionNameLabel = "M_"
tMissionNameLabel += g_sMissionStaticData[iMissionIndex].statID
//Special case for the Jewelry Heist.
IF INT_TO_ENUM(SP_MISSIONS, iMissionIndex) = SP_HEIST_JEWELRY_2
tMissionNameLabel += "A"
ENDIF
ENDIF
BREAK
CASE CP_GROUP_RANDOMCHARS
tMissionNameLabel = GET_RC_MISSION_NAME_LABEL(INT_TO_ENUM(g_eRC_MissionIDs, iMissionIndex))
BREAK
DEFAULT
CPRINTLN(DEBUG_REPEAT,"GetRepeatPlayMissionName passed a mission type that isn't repeat playable: ", eMissionType)
BREAK
ENDSWITCH
RETURN tMissionNameLabel
#ENDIF
ENDFUNC
/// PURPOSE:
/// Returns the number of stats this mission has associated with it
/// PARAMS:
/// iMissionIndex - index of appropriate array
/// eMissionType - CP_GROUP_MISSIONS / CP_GROUP_MISSIONS
/// RETURNS:
/// int = number of stats this mission has
FUNC INT GetRepeatPlayMissionStatCount(INT iMissionIndex, enumGrouping eMissionType)
SWITCH eMissionType
CASE CP_GROUP_MISSIONS
RETURN g_sMissionStaticData[iMissionIndex].statCount
BREAK
#IF NOT USE_SP_DLC
CASE CP_GROUP_RANDOMCHARS
RETURN GET_NUMBER_OF_STATS_FOR_RC_MISSION(INT_TO_ENUM(g_eRC_MissionIDs, iMissionIndex))
BREAK
#ENDIF
DEFAULT
CPRINTLN(DEBUG_REPEAT,"GetRepeatPlayMissionStatCount passed a mission type that isn't repeat playable: ", eMissionType)
BREAK
ENDSWITCH
RETURN 0 // not repeatable mission
ENDFUNC
/// PURPOSE:
/// Returns the specified stat associated with this mission
/// PARAMS:
/// iMissionIndex - index of appropriate array
/// eMissionType - CP_GROUP_MISSIONS / CP_GROUP_MISSIONS
/// iStatIndex - the stat we want
/// RETURNS:
/// ENUM_MISSION_STATS the specified stat
FUNC ENUM_MISSION_STATS GetRepeatPlayMissionStat(INT iMissionIndex, enumGrouping eMissionType, INT iStatIndex)
SWITCH eMissionType
CASE CP_GROUP_MISSIONS
RETURN g_sMissionStaticData[iMissionIndex].stats[iStatIndex]
BREAK
#IF NOT USE_SP_DLC
CASE CP_GROUP_RANDOMCHARS
RETURN GET_NTH_STAT_FOR_RC_MISSION(INT_TO_ENUM(g_eRC_MissionIDs, iMissionIndex), iStatIndex)
BREAK
#ENDIF
DEFAULT
CPRINTLN(DEBUG_REPEAT,"GetRepeatPlayMissionStatIndex passed a mission type that isn't repeat playable: ", eMissionType)
BREAK
ENDSWITCH
RETURN EMPTY_MISSION_STAT // not repeatable mission
ENDFUNC
/// PURPOSE:
/// Gets the total number of missions used in repeat play unlocking that have been completed
/// If anything else gets added to repeat play unlocking, it needs adding here
/// RETURNS:
/// INT missions completed + RCs completed
FUNC INT GetTotalCompletionOrder()
#IF USE_CLF_DLC
RETURN g_savedGlobalsClifford.sFlowCustom.iMissionsCompleted
#ENDIF
#IF USE_NRM_DLC
RETURN g_savedGlobalsnorman.sFlowCustom.iMissionsCompleted
#ENDIF
#IF NOT USE_SP_DLC
RETURN g_savedGlobals.sFlowCustom.iMissionsCompleted + g_savedGlobals.sRandomChars.iRCMissionsCompleted
#ENDIF
ENDFUNC
/// PURPOSE:
/// Sets the repeat play completion order for this RC mission
/// PARAMS:
/// iMissionID - the RC mission that has been completed
PROC UpdateRCMissionRepeatCompletionOrder(INT iMissionID)
UPDATE_EYEFIND_CURRENT_NEWS_STORY_STATE(iMissionID, TRUE)
// Update repeat play variables, so we know the playthrough order the player has used
g_savedGlobals.sRandomChars.savedRC[iMissionID].iCompletionOrder = GetTotalCompletionOrder()
CPRINTLN(DEBUG_REPEAT,"URCMCO iMissionID ", iMissionID," iCompletionOrder = ", g_savedGlobals.sRandomChars.savedRC[iMissionID].iCompletionOrder)
g_savedGlobals.sRandomChars.iRCMissionsCompleted++
ENDPROC
/// PURPOSE:
/// Sets the repeat play completion order for this story mission
/// PARAMS:
/// iMissionID - the stroy mission that has been completed
/// eMissionCompletionOrderStat - stat enum for social club
/// bOtherFinales - set this to TRUE for the other finales.
/// when the player passes one of the 3 finales, the other 2 will get force added to the completion list
/// so we don't need all of the functionality in here, as the player hasn't really passed them
PROC UpdateStoryMissionCompletionOrder_CLF(INT iMissionID, STATSENUM eMissionCompletionOrderStat, BOOL bOtherFinales = FALSE)
IF bOtherFinales = FALSE
//disabled for agent T currently
// UPDATE_EYEFIND_CURRENT_NEWS_STORY_STATE(iMissionID, FALSE)
ENDIF
// Update repeat play variables, so we know the playthrough order the player has used
g_savedGlobalsClifford.sFlow.missionSavedData[iMissionID].iCompletionOrder = GetTotalCompletionOrder()
g_savedGlobalsClifford.sFlowCustom.iMissionsCompleted++
IF bOtherFinales = FALSE
// only update the stat is this mission isnt flagged with MF_INDEX_NO_COMP_ORDER
IF NOT IS_BIT_SET(g_sMissionStaticData[iMissionID].settingsBitset, MF_INDEX_NO_COMP_ORDER)
// Update the missions completion order stat
IF eMissionCompletionOrderStat != CITIES_PASSED //CITIES_PASSED used as a default/null value as no enum exists for this purpose.
STAT_SET_INT(eMissionCompletionOrderStat, g_savedGlobalsClifford.sFlowCustom.iMissionsCompleted)
//Send a presence event to notify friends we have passed this mission (and pass our score).
IF NOT g_flowUnsaved.bUpdatingGameflow
PRESENCE_EVENT_UPDATESTAT_INT(eMissionCompletionOrderStat, g_savedGlobalsClifford.sFlow.missionSavedData[iMissionID].iScore)
ENDIF
ENDIF
ENDIF
ENDIF
CPRINTLN(DEBUG_REPEAT,"USMCO CLF iMissionID ", iMissionID, " iCompletionOrder = ", g_savedGlobalsClifford.sFlow.missionSavedData[iMissionID].iCompletionOrder)
ENDPROC
/// PURPOSE:
/// Sets the repeat play completion order for this story mission
/// PARAMS:
/// iMissionID - the stroy mission that has been completed
/// eMissionCompletionOrderStat - stat enum for social club
/// bOtherFinales - set this to TRUE for the other finales.
/// when the player passes one of the 3 finales, the other 2 will get force added to the completion list
/// so we don't need all of the functionality in here, as the player hasn't really passed them
PROC UpdateStoryMissionCompletionOrder_NRM(INT iMissionID, STATSENUM eMissionCompletionOrderStat, BOOL bOtherFinales = FALSE)
IF bOtherFinales = FALSE
//disabled for agent T currently
// UPDATE_EYEFIND_CURRENT_NEWS_STORY_STATE(iMissionID, FALSE)
ENDIF
// Update repeat play variables, so we know the playthrough order the player has used
g_savedGlobalsnorman.sFlow.missionSavedData[iMissionID].iCompletionOrder = GetTotalCompletionOrder()
g_savedGlobalsnorman.sFlowCustom.iMissionsCompleted++
IF bOtherFinales = FALSE
// only update the stat is this mission isnt flagged with MF_INDEX_NO_COMP_ORDER
IF NOT IS_BIT_SET(g_sMissionStaticData[iMissionID].settingsBitset, MF_INDEX_NO_COMP_ORDER)
// Update the missions completion order stat
IF eMissionCompletionOrderStat != CITIES_PASSED //CITIES_PASSED used as a default/null value as no enum exists for this purpose.
STAT_SET_INT(eMissionCompletionOrderStat, g_savedGlobalsnorman.sFlowCustom.iMissionsCompleted)
//Send a presence event to notify friends we have passed this mission (and pass our score).
IF NOT g_flowUnsaved.bUpdatingGameflow
PRESENCE_EVENT_UPDATESTAT_INT(eMissionCompletionOrderStat, g_savedGlobalsnorman.sFlow.missionSavedData[iMissionID].iScore)
ENDIF
ENDIF
ENDIF
ENDIF
CPRINTLN(DEBUG_REPEAT,"USMCO CLF iMissionID ", iMissionID, " iCompletionOrder = ", g_savedGlobalsnorman.sFlow.missionSavedData[iMissionID].iCompletionOrder)
ENDPROC
/// PURPOSE:
/// Sets the repeat play completion order for this story mission
/// PARAMS:
/// iMissionID - the stroy mission that has been completed
/// eMissionCompletionOrderStat - stat enum for social club
/// bOtherFinales - set this to TRUE for the other finales.
/// when the player passes one of the 3 finales, the other 2 will get force added to the completion list
/// so we don't need all of the functionality in here, as the player hasn't really passed them
PROC UpdateStoryMissionCompletionOrder(INT iMissionID, STATSENUM eMissionCompletionOrderStat, BOOL bOtherFinales = FALSE)
#IF USE_CLF_DLC
UpdateStoryMissionCompletionOrder_CLF(iMissionID,eMissionCompletionOrderStat,bOtherFinales)
EXIT
#ENDIF
#IF USE_NRM_DLC
UpdateStoryMissionCompletionOrder_NRM(iMissionID,eMissionCompletionOrderStat,bOtherFinales)
EXIT
#ENDIF
IF bOtherFinales = FALSE
UPDATE_EYEFIND_CURRENT_NEWS_STORY_STATE(iMissionID, FALSE)
ENDIF
// Update repeat play variables, so we know the playthrough order the player has used
g_savedGlobals.sFlow.missionSavedData[iMissionID].iCompletionOrder = GetTotalCompletionOrder()
g_savedGlobals.sFlowCustom.iMissionsCompleted++
IF bOtherFinales = FALSE
// only update the stat is this mission isnt flagged with MF_INDEX_NO_COMP_ORDER
IF NOT IS_BIT_SET(g_sMissionStaticData[iMissionID].settingsBitset, MF_INDEX_NO_COMP_ORDER)
// Update the missions completion order stat
IF eMissionCompletionOrderStat != CITIES_PASSED //CITIES_PASSED used as a default/null value as no enum exists for this purpose.
STAT_SET_INT(eMissionCompletionOrderStat, g_savedGlobals.sFlowCustom.iMissionsCompleted)
//Send a presence event to notify friends we have passed this mission (and pass our score).
IF NOT g_flowUnsaved.bUpdatingGameflow
PRESENCE_EVENT_UPDATESTAT_INT(eMissionCompletionOrderStat, g_savedGlobals.sFlow.missionSavedData[iMissionID].iScore)
ENDIF
ENDIF
ENDIF
ENDIF
CPRINTLN(DEBUG_REPEAT,"USMCO iMissionID ", iMissionID, " iCompletionOrder = ", g_savedGlobals.sFlow.missionSavedData[iMissionID].iCompletionOrder)
ENDPROC
/// PURPOSE:
/// Checks if this story / RC mission is repeatable
/// PARAMS:
/// iMissionID - mission we are checking
/// eMissionType - the mission type
/// RETURNS:
/// TRUE if mission is repeatable, FALSE otherwise
FUNC BOOL IsMissionRepeatable(INT iMissionID, enumGrouping eMissionType)
SWITCH eMissionType
CASE CP_GROUP_MISSIONS
RETURN NOT IS_BIT_SET(g_sMissionStaticData[iMissionID].settingsBitset, MF_INDEX_NO_REPEAT)
BREAK
#IF NOT USE_SP_DLC
CASE CP_GROUP_RANDOMCHARS
RETURN IS_RC_REPEATABLE(INT_TO_ENUM(g_eRC_MissionIDs, iMissionID))
BREAK
#ENDIF
DEFAULT
CPRINTLN(DEBUG_REPEAT,"HasMissionBeenCompleted passed a mission type that isn't repeat playable: ", eMissionType)
BREAK
ENDSWITCH
RETURN FALSE // invalid
ENDFUNC
/// PURPOSE:
/// Checks if this mission is one of the 3 finales
/// PARAMS:
/// iMissionID - mission ID of story mission (must be checked 1st)
/// RETURNS:
/// TRUE if finale mission. FALSE otherwise
#IF USE_CLF_DLC
FUNC BOOL IS_FINALE_MISSIONCLF(INT iMissionID)
SP_MISSIONS eMission = INT_TO_ENUM(SP_MISSIONS, iMissionID)
IF eMission = SP_MISSION_CLF_FIN
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
#ENDIF
#IF USE_NRM_DLC
FUNC BOOL IS_FINALE_MISSIONNRM(INT iMissionID)
SP_MISSIONS eMission = INT_TO_ENUM(SP_MISSIONS, iMissionID)
IF eMission = SP_MISSION_NRM_SUR_CURE
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
#ENDIF
FUNC BOOL IS_FINALE_MISSION(INT iMissionID)
#IF USE_CLF_DLC
return IS_FINALE_MISSIONCLF(iMissionID)
#ENDIF
#IF USE_NRM_DLC
return IS_FINALE_MISSIONNRM(iMissionID)
#ENDIF
#IF NOT USE_SP_DLC
SP_MISSIONS eMission = INT_TO_ENUM(SP_MISSIONS, iMissionID)
IF eMission = SP_MISSION_FINALE_A
OR eMission = SP_MISSION_FINALE_B
OR eMission = SP_MISSION_FINALE_C1
OR eMission = SP_MISSION_FINALE_C2
RETURN TRUE
ENDIF
RETURN FALSE
#ENDIF
ENDFUNC
/// PURPOSE:
/// Returns whether or not the player has completed one of the 3 finales
/// RETURNS:
/// TRUE if a finale has been completed. FALSE otherwise
FUNC BOOL HAVE_ANY_FINALES_BEEN_COMPLETED()
#IF USE_CLF_DLC
IF g_savedGlobalsClifford.sFlow.missionSavedData[SP_MISSION_CLF_FIN].completed = TRUE
RETURN TRUE
ENDIF
#ENDIF
#IF USE_NRM_DLC
IF g_savedGlobalsnorman.sFlow.missionSavedData[SP_MISSION_NRM_SUR_CURE].completed = TRUE
RETURN TRUE
ENDIF
#ENDIF
#IF NOT USE_SP_DLC
IF g_savedGlobals.sFlow.missionSavedData[SP_MISSION_FINALE_A].completed = TRUE
OR g_savedGlobals.sFlow.missionSavedData[SP_MISSION_FINALE_B].completed = TRUE
OR g_savedGlobals.sFlow.missionSavedData[SP_MISSION_FINALE_C1].completed = TRUE
OR g_savedGlobals.sFlow.missionSavedData[SP_MISSION_FINALE_C2].completed = TRUE
RETURN TRUE
ENDIF
#ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// Checks if this story / RC mission has been completed
/// PARAMS:
/// iMissionID - mission we are checking
/// eMissionType - the mission type
/// RETURNS:
/// TRUE if mission complete, FALSE otherwise
FUNC BOOL HasMissionBeenCompleted(INT iMissionID, enumGrouping eMissionType)
SWITCH eMissionType
CASE CP_GROUP_MISSIONS
IF IS_FINALE_MISSION(iMissionID)
// If 1 finale complete, they're all complete
RETURN HAVE_ANY_FINALES_BEEN_COMPLETED()
ELSE
// normal mission, do normal check
#IF USE_CLF_DLC
RETURN g_savedGlobalsClifford.sFlow.missionSavedData[iMissionID].completed
#ENDIF
#IF USE_NRM_DLC
RETURN g_savedGlobalsnorman.sFlow.missionSavedData[iMissionID].completed
#ENDIF
#IF NOT USE_SP_DLC
RETURN g_savedGlobals.sFlow.missionSavedData[iMissionID].completed
#ENDIF
ENDIF
BREAK
#IF NOT USE_SP_DLC
CASE CP_GROUP_RANDOMCHARS
RETURN IS_BIT_SET(g_savedGlobals.sRandomChars.savedRC[iMissionID].rcFlags, ENUM_TO_INT(RC_FLAG_COMPLETED))
BREAK
#ENDIF
DEFAULT
CPRINTLN(DEBUG_REPEAT,"HasMissionBeenCompleted passed a mission type that isn't repeat playable: ", eMissionType)
BREAK
ENDSWITCH
RETURN FALSE // invalid
ENDFUNC
/// PURPOSE:
/// Checks if the mission hasn't already been completed and adds to repeat play list.
/// THIS IS ONLY TO BE CALLED BY ADD_ALL_FINALES_TO_REPEAT_PLAY!!!!!
PROC ADD_MISSION_TO_REPEAT_PLAY(SP_MISSIONS eMission)
INT iMissionID = ENUM_TO_INT(eMission)
IF g_savedGlobals.sFlow.missionSavedData[iMissionID].completed = FALSE
CPRINTLN(DEBUG_REPEAT, "Adding finale to list: ", eMission)
UpdateStoryMissionCompletionOrder(iMissionID, CITIES_PASSED, TRUE) // CITIES_PASSED is null / default value and isnt used
ELSE
// mission already completed
CPRINTLN(DEBUG_REPEAT, "Finale already completed: ", eMission)
ENDIF
ENDPROC
/// PURPOSE:
/// Called once one of the finale missions has been completed.
/// Adds all of the finales to the repeat play list
PROC ADD_ALL_FINALES_TO_REPEAT_PLAY()
#IF NOT USE_SP_DLC
ADD_MISSION_TO_REPEAT_PLAY(SP_MISSION_FINALE_A)
ADD_MISSION_TO_REPEAT_PLAY(SP_MISSION_FINALE_B)
ADD_MISSION_TO_REPEAT_PLAY(SP_MISSION_FINALE_C1)
ADD_MISSION_TO_REPEAT_PLAY(SP_MISSION_FINALE_C2)
#ENDIF
ENDPROC
/// PURPOSE:
/// Gets the completion order for this story / RC mission
/// PARAMS:
/// iMissionID - mission we are checking
/// eMissionType - the mission type
/// RETURNS:
/// the completion order of this mission. (The point in the playthrough that mission was completed)
FUNC INT GetMissionCompletionOrder(INT iMissionID, enumGrouping eMissionType)
SWITCH eMissionType
CASE CP_GROUP_MISSIONS
#IF USE_CLF_DLC
RETURN g_savedGlobalsClifford.sFlow.missionSavedData[iMissionID].iCompletionOrder
#ENDIF
#IF USE_NRM_DLC
RETURN g_savedGlobalsnorman.sFlow.missionSavedData[iMissionID].iCompletionOrder
#ENDIF
#IF NOT USE_SP_DLC
RETURN g_savedGlobals.sFlow.missionSavedData[iMissionID].iCompletionOrder
#ENDIF
BREAK
#IF NOT USE_SP_DLC
CASE CP_GROUP_RANDOMCHARS
RETURN g_savedGlobals.sRandomChars.savedRC[iMissionID].iCompletionOrder
BREAK
#ENDIF
DEFAULT
CPRINTLN(DEBUG_REPEAT,"HasMissionBeenCompleted passed a mission type that isn't repeat playable: ", eMissionType)
BREAK
ENDSWITCH
RETURN -1 // invalid
ENDFUNC
/// PURPOSE:
/// Gets the number of missions of this type
/// PARAMS:
/// eMissionType - the mission type
/// RETURNS:
/// Number of missions of this type (SP_MISSION_MAX or MAX_RC_MISSIONS)
FUNC INT GetMaxMissionsOfType(enumGrouping eMissionType)
SWITCH eMissionType
CASE CP_GROUP_MISSIONS
RETURN ENUM_TO_INT(SP_MISSION_MAX)
BREAK
#IF NOT USE_SP_DLC
CASE CP_GROUP_RANDOMCHARS
RETURN ENUM_TO_INT(MAX_RC_MISSIONS)
BREAK
#ENDIF
DEFAULT
CPRINTLN(DEBUG_REPEAT,"HasMissionBeenCompleted passed a mission type that isn't repeat playable: ", eMissionType)
BREAK
ENDSWITCH
RETURN -1 // invalid
ENDFUNC
// --------------------------HEIST FUNCTIONS ------------------------------------------------------------
/// PURPOSE:
/// Returns which heist this mission is a part of
/// PARAMS:
/// eMission - the mission we are checking
/// RETURNS:
/// the index of the heist this mission is part of or index of "NO_HEISTS"
#IF NOT USE_SP_DLC
FUNC INT GET_HEIST_FROM_MISSION_ID(SP_MISSIONS eMission)
SWITCH eMission
// ------AGENCY------
CASE SP_HEIST_AGENCY_1
CASE SP_HEIST_AGENCY_2
CASE SP_HEIST_AGENCY_PREP_1
CASE SP_HEIST_AGENCY_3A
CASE SP_HEIST_AGENCY_3B
RETURN HEIST_AGENCY
BREAK
// ------DOCKS / PORT OF LS------
CASE SP_HEIST_DOCKS_1
CASE SP_HEIST_DOCKS_2A
CASE SP_HEIST_DOCKS_2B
RETURN HEIST_DOCKS
BREAK
// ------FINALE / BIG SCORE------
CASE SP_HEIST_FINALE_1
CASE SP_HEIST_FINALE_2_INTRO
CASE SP_HEIST_FINALE_PREP_A
CASE SP_HEIST_FINALE_PREP_B
CASE SP_HEIST_FINALE_PREP_C1
CASE SP_HEIST_FINALE_PREP_C2
CASE SP_HEIST_FINALE_PREP_C3
CASE SP_HEIST_FINALE_PREP_D
CASE SP_HEIST_FINALE_2A
CASE SP_HEIST_FINALE_2B
RETURN HEIST_FINALE
BREAK
// ------JEWELLRY / JEWEL STORE------
CASE SP_HEIST_JEWELRY_1
CASE SP_HEIST_JEWELRY_PREP_1A
CASE SP_HEIST_JEWELRY_PREP_2A
CASE SP_HEIST_JEWELRY_PREP_1B
CASE SP_HEIST_JEWELRY_2
RETURN HEIST_JEWEL
BREAK
// ------RURAL / PALETO------
CASE SP_HEIST_RURAL_1
CASE SP_HEIST_RURAL_2
RETURN HEIST_RURAL_BANK
BREAK
DEFAULT
RETURN NO_HEISTS // other missions do not have an associated heist
BREAK
ENDSWITCH
RETURN NO_HEISTS
ENDFUNC
#ENDIF
/// PURPOSE:
/// Adds a decor to a vehicle
/// PARAMS:
/// veh -
/// RETURNS:
///
FUNC BOOL SET_VEHICLE_IGNORED_BY_QUICK_SAVE(VEHICLE_INDEX veh)
IF NOT DECOR_EXIST_ON(veh, "IgnoredByQuickSave")
IF DECOR_SET_BOOL(veh, "IgnoredByQuickSave", TRUE)
RETURN TRUE
ENDIF
ELSE
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC