//- commands headers -// USING "commands_replay.sch" //- script headers -// //- public headers -// //- private headers -// USING "friendActivity_dialogue_private.sch" #IF IS_DEBUG_BUILD //- debug headers -// #ENDIF //--------------------------------------------------------------------------------------------------- //-- Sort friends //--------------------------------------------------------------------------------------------------- FUNC BOOL Private_SortMembers(BOOL bSortFriendMembers) enumCharacterList currentPlayerChar = GET_CURRENT_PLAYER_PED_ENUM() BOOL bResortedMembers = FALSE // If player has swapped with friend A IF gActivity.mFriendA.eState <> FRIEND_NULL AND gActivity.mFriendA.eChar = currentPlayerChar structFriend tempMember = gActivity.mPlayer // Swap player and friend members gActivity.mPlayer = gActivity.mFriendA gActivity.mFriendA = tempMember bResortedMembers = TRUE ENDIF // If player has swapped with friend B IF gActivity.mFriendB.eState <> FRIEND_NULL AND gActivity.mFriendB.eChar = currentPlayerChar structFriend tempMember = gActivity.mPlayer // Swap player and friend members gActivity.mPlayer = gActivity.mFriendB gActivity.mFriendB = tempMember bResortedMembers = TRUE ENDIF // If friend A has cancelled, but friend B still exists IF bSortFriendMembers IF gActivity.mFriendA.eState = FRIEND_NULL AND gActivity.mFriendB.eState <> FRIEND_NULL structFriend tempMember = gActivity.mFriendA // Swap player and friend members gActivity.mFriendA = gActivity.mFriendB gActivity.mFriendB = tempMember bResortedMembers = TRUE ENDIF ENDIF // PRIVATE_SET_FRIEND_A_PED_ID(gActivity.mFriendA.hPed) // PRIVATE_SET_FRIEND_B_PED_ID(gActivity.mFriendB.hPed) Private_SetFriendsForcedSeats() IF bResortedMembers #IF IS_DEBUG_BUILD TEXT_LABEL tPlayer = GetLabel_enumCharacterList(gActivity.mPlayer.eChar) TEXT_LABEL tFriendA = GetLabel_enumCharacterList(gActivity.mFriendA.eChar) TEXT_LABEL tFriendB = GetLabel_enumCharacterList(gActivity.mFriendB.eChar) CPRINTLN(DEBUG_FRIENDS, "Pickup_SortFriends():- ", tPlayer, " / ", tFriendA, " / ", tFriendB) #ENDIF RETURN TRUE ENDIF RETURN FALSE ENDFUNC //--------------------------------------------------------------------------------------------------- //-- Rejection //--------------------------------------------------------------------------------------------------- PROC Private_DeleteMembersForGriefing() Private_CleanupFriend(gActivity.mPlayer, MC_Delete) Private_CleanupFriend(gActivity.mFriendA, MC_Delete) Private_CleanupFriend(gActivity.mFriendB, MC_Delete) ENDPROC FUNC BOOL Private_CanRejectCharForMission(enumCharacterList eChar, INT iAllowedChars) RETURN NOT IS_BIT_SET(iAllowedChars, ENUM_TO_INT(GET_FRIEND_FROM_CHAR(eChar))) ENDFUNC FUNC BOOL Private_CanZoneRejectAnyConversableMembers() // Is player in a rejection zone for a mission he can trigger? IF (g_eFriendMissionZoneState = FRIEND_MISSION_ZONE_REJECT AND IS_BITMASK_SET(g_sMissionStaticData[g_eFriendMissionZoneID].triggerCharBitset, GET_PLAYER_PED_BIT(GET_CURRENT_PLAYER_PED_ENUM()))) // Can any friends in group be rejected for this mission? IF (Private_CanFriendConverse(gActivity.mFriendA) AND Private_CanRejectCharForMission(gActivity.mFriendA.eChar, g_iFriendMissionZoneAcceptBitset)) OR (Private_CanFriendConverse(gActivity.mFriendB) AND Private_CanRejectCharForMission(gActivity.mFriendB.eChar, g_iFriendMissionZoneAcceptBitset)) RETURN TRUE ENDIF // Can any soldiers in group be rejected for this mission? enumCharacterList ePlayerChar = GET_CURRENT_PLAYER_PED_ENUM() enumCharacterList eChar REPEAT MAX_BATTLE_BUDDIES eChar IF eChar <> ePlayerChar IF (Private_CanSoldierConverse(gActivity.mSoldiers[eChar]) AND Private_CanRejectCharForMission(eChar, g_iFriendMissionZoneAcceptBitset)) RETURN TRUE ENDIF ENDIF ENDREPEAT ENDIF RETURN FALSE ENDFUNC FUNC BOOL Private_CanTimeRejectAnyConversableMembers() IF g_eFriendMissionZoneState = FRIEND_MISSION_ZONE_OFF IF GET_PLAYER_WANTED_LEVEL(PLAYER_ID()) = 0 enumCharacterList ePlayerChar = GET_CURRENT_PLAYER_PED_ENUM() enumCharacterList eChar REPEAT MAX_BATTLE_BUDDIES eChar IF eChar <> ePlayerChar IF Private_CanSoldierConverse(gActivity.mSoldiers[eChar]) AND Private_CanRejectSoldierForTime(gActivity.mSoldiers[eChar]) RETURN TRUE ENDIF ENDIF ENDREPEAT ENDIF ENDIF RETURN FALSE ENDFUNC PROC Private_RejectMembersForMission(BOOL bAllowSubtitles, enumFriendActivityPhrase ePhrase = FAP_REJECTION_OK, BOOL bIsPrep = FALSE) IF bAllowSubtitles CPRINTLN(DEBUG_FRIENDS, "Private_RejectMembersForMission(bAllowSubtitles = TRUE)") ELSE CPRINTLN(DEBUG_FRIENDS, "Private_RejectMembersForMission(bAllowSubtitles = FALSE)") ENDIF CPRINTLN(DEBUG_FRIENDS, "Current mission = ", GetLabel_SP_MISSIONS(g_eFriendMissionZoneID)) // Reject friends if they cannot join current mission, or if they are not in group IF bIsPrep IF Private_IsFriendValid(gActivity.mFriendA) AND NOT Private_CanFriendLeave(gActivity.mFriendA) Private_SetFriendTrapped(gActivity.mFriendA) ELSE Private_SetFriendRejected(gActivity.mFriendA, bAllowSubtitles, ePhrase) ENDIF ELSE IF Private_CanRejectCharForMission(gActivity.mFriendA.eChar, g_iFriendMissionZoneAcceptBitset) OR NOT Private_CanFriendConverse(gActivity.mFriendA) Private_SetFriendRejected(gActivity.mFriendA, bAllowSubtitles, ePhrase) ENDIF ENDIF IF bIsPrep IF Private_IsFriendValid(gActivity.mFriendB) AND NOT Private_CanFriendLeave(gActivity.mFriendB) Private_SetFriendTrapped(gActivity.mFriendB) ELSE Private_SetFriendRejected(gActivity.mFriendB, bAllowSubtitles, ePhrase) ENDIF ELSE IF Private_CanRejectCharForMission(gActivity.mFriendB.eChar, g_iFriendMissionZoneAcceptBitset) OR NOT Private_CanFriendConverse(gActivity.mFriendB) Private_SetFriendRejected(gActivity.mFriendB, bAllowSubtitles, ePhrase) ENDIF ENDIF // Same for soldiers, except if they are on the way to a prep mission, don't reject them for not being in the group yet // enumCharacterList ePlayerChar = GET_CURRENT_PLAYER_PED_ENUM() // BBUDDIES REMOVED // enumCharacterList eChar // REPEAT MAX_BATTLE_BUDDIES eChar // IF eChar <> ePlayerChar // IF Private_CanRejectCharForMission(eChar, g_iFriendMissionZoneAcceptBitset) // Private_SetSoldierRejected(gActivity.mSoldiers[eChar], g_eFriendMissionZoneID, bAllowSubtitles, ePhrase) // // ELIF NOT Private_CanSoldierConverse(gActivity.mSoldiers[eChar]) AND NOT IS_BIT_SET(g_sMissionStaticData[g_eFriendMissionZoneID].settingsBitset, MF_INDEX_IS_PREP) // Private_SetSoldierRejected(gActivity.mSoldiers[eChar], g_eFriendMissionZoneID, bAllowSubtitles, ePhrase) // ENDIF // ENDIF // ENDREPEAT ENDPROC PROC Private_RejectAllSoldiers(BOOL bAllowSubtitles, enumFriendActivityPhrase ePhrase) #IF IS_DEBUG_BUILD TEXT_LABEL_63 tPhrase = GetLabel_enumFriendActivityPhrase(ePhrase) CPRINTLN(DEBUG_FRIENDS, "Private_RejectAllSoldiers(", tPhrase, ")") #ENDIF enumCharacterList ePlayerChar = GET_CURRENT_PLAYER_PED_ENUM() enumCharacterList eChar REPEAT MAX_BATTLE_BUDDIES eChar IF eChar <> ePlayerChar Private_SetSoldierRejected(gActivity.mSoldiers[eChar], g_BattleBuddyMission, bAllowSubtitles, ePhrase) ENDIF ENDREPEAT ENDPROC PROC Private_SetZoneRejection(BOOL bEnable) IF gActivity.bIsZoneRejectionEnabled <> bEnable // Enable/disable zone rejection gActivity.bIsZoneRejectionEnabled = bEnable // If disabling, stop current dialogue if running IF bEnable = TRUE CPRINTLN(DEBUG_FRIENDS, "Private_EnableZoneRejection(TRUE)") ELSE CPRINTLN(DEBUG_FRIENDS, "Private_EnableZoneRejection(FALSE)") IF gActivity.mDialogue.eState = FDIALOGUE_REJECTZONE OR gActivity.mDialogue.eState = FDIALOGUE_REJECTWAIT CPRINTLN(DEBUG_FRIENDS, "Private_EnableZoneRejection(FALSE) - Ending rejection zone dialogue") Private_EndDialogueState(gActivity.mDialogue) ELSE CPRINTLN(DEBUG_FRIENDS, "Private_EnableZoneRejection(FALSE) - No rejection zone dialogue playing") ENDIF gActivity.eRecentRejectionZone = SP_MISSION_NONE ENDIF ENDIF ENDPROC PROC Private_UpdateRejection() // Reject for zone IF gActivity.bIsZoneRejectionEnabled AND g_eFriendMissionZoneState <> FRIEND_MISSION_ZONE_LAUNCHING AND g_eFriendMissionZoneState <> FRIEND_MISSION_ZONE_LAUNCHED IF Private_CanZoneRejectAnyConversableMembers() // Start dialogue IF gActivity.mDialogue.eState <> FDIALOGUE_REJECTZONE AND gActivity.mDialogue.eState <> FDIALOGUE_REJECTWAIT AND gActivity.eRecentRejectionZone <> g_eFriendMissionZoneID Private_SetDialogueState(gActivity.mDialogue, FDIALOGUE_REJECTZONE) gActivity.eRecentRejectionZone = g_eFriendMissionZoneID ENDIF // Reject members if possible IF NOT IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID()) IF NOT IS_MESSAGE_BEING_DISPLAYED() IF gActivity.mDialogue.eState <> FDIALOGUE_REJECTZONE Private_RejectMembersForMission(TRUE) ENDIF ENDIF ENDIF ELSE // Abort dialogue IF gActivity.mDialogue.eState = FDIALOGUE_REJECTWAIT IF g_eFriendMissionZoneState <> FRIEND_MISSION_ZONE_REJECT Private_SetDialogueState(gActivity.mDialogue, FDIALOGUE_REJECTCANCEL) ENDIF ENDIF ENDIF ENDIF // Reject trapped friends IF gActivity.mFriendA.eState = FRIEND_TRAPPED IF Private_CanFriendLeave(gActivity.mFriendA) AND NOT IS_MESSAGE_BEING_DISPLAYED() IF IS_PLAYER_PED_PLAYABLE(gActivity.mFriendA.eChar) Private_SetFriendRejected(gActivity.mFriendA, /*g_BattleBuddyMission*/ TRUE, FAP_REJECTION_OK) ELSE Private_SetFriendRejected(gActivity.mFriendA, /*g_BattleBuddyMission*/ TRUE, FAP_REJECTION_CRAZY) ENDIF ENDIF ENDIF IF gActivity.mFriendB.eState = FRIEND_TRAPPED IF Private_CanFriendLeave(gActivity.mFriendB) AND NOT IS_MESSAGE_BEING_DISPLAYED() IF IS_PLAYER_PED_PLAYABLE(gActivity.mFriendB.eChar) Private_SetFriendRejected(gActivity.mFriendB, /*g_BattleBuddyMission*/ TRUE, FAP_REJECTION_OK) ELSE Private_SetFriendRejected(gActivity.mFriendB, /*g_BattleBuddyMission*/ TRUE, FAP_REJECTION_CRAZY) ENDIF ENDIF ENDIF // Reject for squad timeout IF Private_CanTimeRejectAnyConversableMembers() IF Private_CanPlayAudio(gActivity.mAudio) AND (NOT IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID()) OR ABSF(GET_ENTITY_SPEED(PLAYER_PED_ID())) < 0.5) Private_RejectAllSoldiers(TRUE, FAP_REJECTION_TIMEOUT) ENDIF ENDIF // Reject for BB flag IF Private_CheckBehaviourFlag(BBF_RejectAllBattleBuddies) Private_RejectAllSoldiers(TRUE, NO_FRIEND_ACTIVITY_PHRASE) ENDIF ENDPROC //--------------------------------------------------------------------------------------------------- //-- Add requests //--------------------------------------------------------------------------------------------------- FUNC BOOL Private_ProcessAddFriends(BOOL bOnlyAllowIfMetAmbiently = FALSE) IF NOT Private_IsPlayerSwitching() // Get pending connection enumFriendConnection ePendingConnection IF GET_PENDING_CONNECTIONS(ePendingConnection) > 0 // Get friend char from pending connection enumCharacterList eFriendChar IF GET_PENDING_CONNECTION_CHAR(ePendingConnection, eFriendChar) //-- If met friend ambiently, remove any friends waiting to be picked up -- BOOL bMetAmbiently = FALSE IF GET_CONNECTION_MODE(ePendingConnection) = FC_MODE_Ambient bMetAmbiently = TRUE ENDIF IF bMetAmbiently BOOL bWereMembersRemoved = FALSE IF gActivity.mFriendA.eState = FRIEND_PICKUP CPRINTLN(DEBUG_FRIENDS, "Private_HandleAddFriendRequests() - Met friend - Removing pickup ", GetLabel_enumCharacterList(gActivity.mFriendA.eChar)) Private_CleanupFriend(gActivity.mFriendA, MC_Release) bWereMembersRemoved = TRUE ENDIF IF gActivity.mFriendB.eState = FRIEND_PICKUP CPRINTLN(DEBUG_FRIENDS, "Private_HandleAddFriendRequests() - Met friend - Removing pickup ", GetLabel_enumCharacterList(gActivity.mFriendB.eChar)) Private_CleanupFriend(gActivity.mFriendB, MC_Release) bWereMembersRemoved = TRUE ENDIF IF bWereMembersRemoved Private_SortMembers(TRUE) // TODO: Help message ENDIF ELIF bOnlyAllowIfMetAmbiently // Can only meet ambiently at this stage -> so abort and reset connection SET_CONNECTION_STATE(ePendingConnection, FC_STATE_ContactWait) RETURN FALSE ENDIF //-- Add friend -- IF gActivity.mFriendA.eState = FRIEND_NULL enumFriendLocation ePickupLocation = FriendLoc_GetBestPickupLoc(gActivity.mPlayer.eChar, eFriendChar, TRUE, gActivity.mFriendB.ePickup) IF ACTIVATE_CONNECTION(ePendingConnection, FC_MODE_Friend) IF Private_AddFriend(gActivity.mFriendA, eFriendChar, ePickupLocation, 0, bMetAmbiently) // Cancel old queued text messages Private_CancelCommsBetweenFriends(gActivity.mFriendA.eChar, gActivity.mPlayer.eChar) Private_CancelCommsBetweenFriends(gActivity.mFriendA.eChar, gActivity.mFriendB.eChar) RETURN TRUE ENDIF ENDIF ELIF gActivity.mFriendB.eState = FRIEND_NULL enumFriendLocation ePickupLocation = FriendLoc_GetBestPickupLoc(gActivity.mPlayer.eChar, eFriendChar, TRUE, gActivity.mFriendA.ePickup) IF ACTIVATE_CONNECTION(ePendingConnection, FC_MODE_Friend) IF Private_AddFriend(gActivity.mFriendB, eFriendChar, ePickupLocation, 1, bMetAmbiently) // Cancel old queued text messages Private_CancelCommsBetweenFriends(gActivity.mFriendB.eChar, gActivity.mPlayer.eChar) Private_CancelCommsBetweenFriends(gActivity.mFriendB.eChar, gActivity.mFriendA.eChar) RETURN TRUE ENDIF ENDIF ENDIF ELSE SCRIPT_ASSERT("Private_HandleAddFriendRequests() - Cannot get valid character for friend to be added - perhaps current player is not properly involved in the pending connection") ENDIF // Failed to create pending connection, reset it SET_CONNECTION_STATE(ePendingConnection, FC_STATE_ContactWait) RETURN FALSE ENDIF ENDIF RETURN FALSE ENDFUNC FUNC BOOL Private_ProcessAddSoldiers() IF NOT Private_IsPlayerSwitching() // Get pending connection enumFriendConnection ePendingConnection IF GET_PENDING_CONNECTIONS(ePendingConnection) > 0 // Get friend char from pending connection enumCharacterList eFriendChar = NO_CHARACTER IF GET_PENDING_CONNECTION_CHAR(ePendingConnection, eFriendChar) AND IS_PLAYER_PED_PLAYABLE(eFriendChar) //-- Add squad member -- IF gActivity.mSoldiers[eFriendChar].eState = SOLDIER_NULL enumFriendConnectionMode eInitMode = GET_CONNECTION_MODE(ePendingConnection) IF ACTIVATE_CONNECTION(ePendingConnection, FC_MODE_Squad) IF Private_AddSoldier(gActivity.mSoldiers[eFriendChar], eInitMode) RETURN TRUE ENDIF ENDIF ENDIF ELSE SCRIPT_ASSERT("Private_HandleSquadAddRequests() - Cannot get valid character for squad member to be added - perhaps current player is not properly involved in the pending connection") ENDIF // Failed to create pending connection, reset it SET_CONNECTION_STATE(ePendingConnection, FC_STATE_ContactWait) RETURN FALSE ENDIF ENDIF RETURN FALSE ENDFUNC //--------------------------------------------------------------------------------------------------- //-- Process members //--------------------------------------------------------------------------------------------------- PROC Private_ProcessMembers() // Process soldiers INT iSlot REPEAT MAX_BATTLE_BUDDIES iSlot Private_UpdateSoldier(gActivity.mSoldiers[iSlot]) ENDREPEAT // Process friends Private_UpdateFriend(gActivity.mPlayer) Private_UpdateFriend(gActivity.mFriendA) Private_UpdateFriend(gActivity.mFriendB) HANDLE_BUDDY_HEAD_TRACK_WHILE_ENTERING_VEHICLE() // Clear damage IF NOT IS_PED_INJURED(PLAYER_PED_ID()) CLEAR_ENTITY_LAST_DAMAGE_ENTITY(PLAYER_PED_ID()) CLEAR_ENTITY_LAST_WEAPON_DAMAGE(PLAYER_PED_ID()) ENDIF IF NOT IS_PED_INJURED(gActivity.mFriendA.hPed) CLEAR_ENTITY_LAST_DAMAGE_ENTITY(gActivity.mFriendA.hPed) CLEAR_ENTITY_LAST_WEAPON_DAMAGE(gActivity.mFriendA.hPed) ENDIF IF NOT IS_PED_INJURED(gActivity.mFriendB.hPed) CLEAR_ENTITY_LAST_DAMAGE_ENTITY(gActivity.mFriendB.hPed) CLEAR_ENTITY_LAST_WEAPON_DAMAGE(gActivity.mFriendB.hPed) ENDIF ENDPROC //--------------------------------------------------------------------------------------------------- //-- Remove requests //--------------------------------------------------------------------------------------------------- PROC Private_LogFriendFail(structFriend& friend, enumCharacterList& eFailChar) IF friend.eState <> FRIEND_CANCEL eFailChar = friend.eChar ENDIF ENDPROC PROC Private_ProcessRemoveMembers() // Process rejection for zones and time Private_UpdateRejection() BOOL bWereMembersRemoved = FALSE // Remove friends IF NOT Private_IsPlayerSwitching() // Remove friend A if requested IF gActivity.mFriendA.eState >= FRIEND_CANCEL CPRINTLN(DEBUG_FRIENDS, "Private_ProcessRemoveMembers() - Removing friend A: ", GetLabel_enumCharacterList(gActivity.mFriendA.eChar)) Private_LogFriendFail(gActivity.mFriendA, gActivity.eLogFailCharA) Private_RemoveFailedFriend(gActivity.mFriendA) bWereMembersRemoved = TRUE ENDIF // Remove friend B if requested IF gActivity.mFriendB.eState >= FRIEND_CANCEL CPRINTLN(DEBUG_FRIENDS, "Private_ProcessRemoveMembers() - Removing friend B: ", GetLabel_enumCharacterList(gActivity.mFriendB.eChar)) Private_LogFriendFail(gActivity.mFriendB, gActivity.eLogFailCharB) Private_RemoveFailedFriend(gActivity.mFriendB) bWereMembersRemoved = TRUE ENDIF // Ensure friend A is never blank IF bWereMembersRemoved Private_SortMembers(TRUE) ENDIF ENDIF // Remove soldiers // enumCharacterList eChar // REPEAT MAX_BATTLE_BUDDIES eChar // // IF gActivity.mSoldiers[eChar].eState >= SOLDIER_FAIL_INJURED // CPRINTLN(DEBUG_FRIENDS, "Private_ProcessRemoveMembers() - Removing soldier: ", GetLabel_enumCharacterList(eChar)) // // Private_HandleSoldierFail(gActivity.mSoldiers[eChar], eCleanupStyle) // Private_CleanupSoldier(gActivity.mSoldiers[eChar], eCleanupStyle) // ENDIF // // ENDREPEAT ENDPROC //--------------------------------------------------------------------------------------------------- //-- Help //--------------------------------------------------------------------------------------------------- FUNC BOOL Private_DisplayQueuedHelp(STRING sLabel) // IF NOT IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_STORY_PREP) // AND NOT IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_FRIEND_SQUAD) // // SWITCH GET_FLOW_HELP_MESSAGE_STATUS(sLabel) // CASE FHS_EXPIRED // CPRINTLN(DEBUG_FRIENDS, "Private_DisplayQueuedHelp() - \"", sLabel, "\" trying to queue") // ADD_HELP_TO_FLOW_QUEUE(sLabel, FHP_HIGH, 0, DEFAULT_HELP_TEXT_TIME) // BREAK // //// CASE FHS_QUEUED //// CPRINTLN(DEBUG_FRIENDS, "Private_DisplayQueuedHelp() - \"", sLabel, "\" is queued") //// BREAK // // CASE FHS_DISPLAYED // CPRINTLN(DEBUG_FRIENDS, "Private_DisplayQueuedHelp() - \"", sLabel, "\" was displayed by queue") // RETURN TRUE // BREAK // ENDSWITCH // // ELSE IF NOT IS_HELP_MESSAGE_ON_SCREEN() CPRINTLN(DEBUG_FRIENDS, "Private_DisplayQueuedHelp() - \"", sLabel, "\" was displayed without queueing (as on mission)") PRINT_HELP(sLabel) RETURN TRUE ENDIF // ENDIF RETURN FALSE ENDFUNC PROC Private_ProcessHelp() // Help text: battle buddy arriving IF g_savedGlobals.sFriendsData.g_bHelpDoneBBuddyArrival = FALSE IF gActivity.mSoldiers[CHAR_MICHAEL].eState = SOLDIER_ARRIVE_IN_CAR OR gActivity.mSoldiers[CHAR_MICHAEL].eState = SOLDIER_FOLLOW IF Private_DisplayQueuedHelp("FR_H_BUDM_A") g_savedGlobals.sFriendsData.g_bHelpDoneBBuddyArrival = TRUE EXIT ENDIF ELIF gActivity.mSoldiers[CHAR_FRANKLIN].eState = SOLDIER_ARRIVE_IN_CAR OR gActivity.mSoldiers[CHAR_FRANKLIN].eState = SOLDIER_FOLLOW IF Private_DisplayQueuedHelp("FR_H_BUDF_A") g_savedGlobals.sFriendsData.g_bHelpDoneBBuddyArrival = TRUE EXIT ENDIF ELIF gActivity.mSoldiers[CHAR_TREVOR].eState = SOLDIER_ARRIVE_IN_CAR OR gActivity.mSoldiers[CHAR_TREVOR].eState = SOLDIER_FOLLOW IF Private_DisplayQueuedHelp("FR_H_BUDT_A") g_savedGlobals.sFriendsData.g_bHelpDoneBBuddyArrival = TRUE EXIT ENDIF ENDIF ENDIF // Help text: player can switch to battle buddy IF g_savedGlobals.sFriendsData.g_bHelpDoneBBuddySwitch = FALSE IF gActivity.bIsAnySwitchAvailable IF Private_DisplayQueuedHelp("FR_H_BUD_SW") g_savedGlobals.sFriendsData.g_bHelpDoneBBuddySwitch = TRUE EXIT ENDIF ENDIF ELIF IS_HELP_MESSAGE_BEING_DISPLAYED() IF IS_PLAYER_SWITCH_IN_PROGRESS() IF IS_THIS_HELP_MESSAGE_BEING_DISPLAYED("FR_H_BUD_SW") CLEAR_HELP() ENDIF ENDIF ENDIF ENDPROC //--------------------------------------------------------------------------------------------------- //-- Global handles //--------------------------------------------------------------------------------------------------- PROC Private_UpdateGlobalFriendHandles() // Keep global ped IDs in sync IF FRIEND_A_PED_ID() <> gActivity.mFriendA.hPed CPRINTLN(DEBUG_FRIENDS, "Update FRIEND_A_PED_ID to ", GetLabel_enumCharacterList(gActivity.mFriendA.eChar), ", hPed = ", NATIVE_TO_INT(gActivity.mFriendA.hPed)) PRIVATE_SET_FRIEND_A_PED_ID(gActivity.mFriendA.hPed) ENDIF IF FRIEND_B_PED_ID() <> gActivity.mFriendB.hPed CPRINTLN(DEBUG_FRIENDS, "Update FRIEND_B_PED_ID to ", GetLabel_enumCharacterList(gActivity.mFriendB.eChar), ", hPed = ", NATIVE_TO_INT(gActivity.mFriendB.hPed)) PRIVATE_SET_FRIEND_B_PED_ID(gActivity.mFriendB.hPed) ENDIF ENDPROC //--------------------------------------------------------------------------------------------------- //-- Transfer //--------------------------------------------------------------------------------------------------- /// This is called when player has friends and either (a) squad mission starts, or (b) player calls squad buddy PROC Private_TransferMembersToSquad() // CPRINTLN(DEBUG_FRIENDS, "\n") // CPRINTLN(DEBUG_FRIENDS, "Private_TransferMembersToSquad() - ** TRANSFER STARTED **") // // enumFriendConnection eConnection // enumCharacterList ePlayerChar = gActivity.mPlayer.eChar // enumCharacterList eFriendAChar = gActivity.mFriendA.eChar // enumCharacterList eFriendBChar = gActivity.mFriendB.eChar // // gActivity.eLogFailCharA = NO_CHARACTER // gActivity.eLogFailCharB = NO_CHARACTER // // // //-- Squad mission must be set to transfer members // IF g_BattleBuddyMission = SP_MISSION_NONE // SCRIPT_ASSERT("Private_TransferMembersToSquad() - Squad mission is not set") // ENDIF // // // //-- Setup dialogue states for squad mode // Private_SetDialogueState(gActivity.mDialogue, FDIALOGUE_SQUAD) // Private_SetDialogueIdleState(gActivity.mDialogue, FDIALOGUE_SQUAD_IDLE) // // // //-- Transfer connections // // // Backup connections, as Init ones will get cleared by cleanups // enumFriendConnectionState backupStates[MAX_FRIEND_CONNECTIONS] // enumFriendConnectionMode backupModes[MAX_FRIEND_CONNECTIONS] // REPEAT MAX_FRIEND_CONNECTIONS eConnection // backupStates[eConnection] = GET_CONNECTION_STATE(eConnection) // backupModes[eConnection] = GET_CONNECTION_MODE(eConnection) // ENDREPEAT // // // Transfer player // Private_CleanupFriend(gActivity.mPlayer, MC_LeavePedIntact) // Private_AddSoldier(gActivity.mSoldiers[ePlayerChar]) // Private_SetSoldierGlobalFlag(gActivity.mSoldiers[ePlayerChar], g_bitfieldBattleBuddyAvailable) // // // Transfer friend A // IF NOT Private_IsFriendValid(gActivity.mFriendA) // OR NOT Private_CanFriendConverse(gActivity.mFriendA) // // Private_SetFriendRejected(gActivity.mFriendA, g_BattleBuddyMission, FALSE, NO_FRIEND_ACTIVITY_PHRASE) // Private_CleanupFriend(gActivity.mFriendA, MC_Release) // // ELIF NOT IS_BIT_SET(g_BattleBuddyAllowedChars, ENUM_TO_INT(GET_FRIEND_FROM_CHAR(gActivity.mFriendA.eChar))) // // IF NOT Private_CanFriendLeave(gActivity.mFriendA) // Private_SetFriendTrapped(gActivity.mFriendA) // ELSE // Private_SetFriendRejected(gActivity.mFriendA, g_BattleBuddyMission, FALSE, FAP_REJECTION_OK) // Private_CleanupFriend(gActivity.mFriendA, MC_Release) // ENDIF // // ELSE // // Convert to soldier // Private_CleanupFriend(gActivity.mFriendA, MC_LeavePedIntact) // // IF GET_CONNECTION(ePlayerChar, eFriendAChar, eConnection) // IF ACTIVATE_CONNECTION(eConnection, FC_MODE_Squad) // Private_AddSoldier(gActivity.mSoldiers[eFriendAChar]) // Private_SetSoldierGlobalFlag(gActivity.mSoldiers[eFriendAChar], g_bitfieldBattleBuddyAvailable) // ENDIF // ENDIF // ENDIF // // // Transfer friend B // IF NOT Private_IsFriendValid(gActivity.mFriendB) // OR NOT Private_CanFriendConverse(gActivity.mFriendB) // // Private_SetFriendRejected(gActivity.mFriendB, g_BattleBuddyMission, FALSE, NO_FRIEND_ACTIVITY_PHRASE) // Private_CleanupFriend(gActivity.mFriendB, MC_Release) // // ELIF NOT IS_BIT_SET(g_BattleBuddyAllowedChars, ENUM_TO_INT(GET_FRIEND_FROM_CHAR(gActivity.mFriendB.eChar))) // // IF NOT Private_CanFriendLeave(gActivity.mFriendB) // Private_SetFriendTrapped(gActivity.mFriendB) // ELSE // Private_SetFriendRejected(gActivity.mFriendB, g_BattleBuddyMission, FALSE, FAP_REJECTION_OK) // Private_CleanupFriend(gActivity.mFriendB, MC_Release) // ENDIF // // ELSE // // Convert to soldier // Private_CleanupFriend(gActivity.mFriendB, MC_LeavePedIntact) // // IF GET_CONNECTION(ePlayerChar, eFriendBChar, eConnection) // IF ACTIVATE_CONNECTION(eConnection, FC_MODE_Squad) // Private_AddSoldier(gActivity.mSoldiers[eFriendBChar]) // Private_SetSoldierGlobalFlag(gActivity.mSoldiers[eFriendBChar], g_bitfieldBattleBuddyAvailable) // ENDIF // ENDIF // ENDIF // // // Restore any init connections // REPEAT MAX_FRIEND_CONNECTIONS eConnection // IF backupStates[eConnection] = FC_STATE_Init // SET_CONNECTION_STATE(eConnection, backupStates[eConnection]) // SET_CONNECTION_MODE(eConnection, backupModes[eConnection]) // ENDIF // ENDREPEAT // // OVERWRITE_BATTLEBUDDY_SNAPSHOT() // CPRINTLN(DEBUG_FRIENDS, "Snapshot: g_bitfieldBattleBuddyAvailable = ", g_bitfieldBattleBuddyAvailable) // // IF g_eFriendMissionZoneState <> FRIEND_MISSION_ZONE_OFF // IF g_eFriendMissionZoneID = SP_MISSION_FBI_4_PREP_4 // OR g_eFriendMissionZoneID = SP_MISSION_FBI_4_PREP_5 // CPRINTLN(DEBUG_FRIENDS, "Friend activity will resume when player passes squad mission...") // gActivity.bResumeFriendsAfterSquad = TRUE // ENDIF // ENDIF // // CPRINTLN(DEBUG_FRIENDS, "Private_TransferMembersToSquad() - ** TRANSFER DONE **\n") ENDPROC FUNC BOOL Private_TransferMembersToFriends() // CPRINTLN(DEBUG_FRIENDS, "\n") // CPRINTLN(DEBUG_FRIENDS, "Private_TransferMembersToFriends() - ** TRANSFER STARTED **") // // // Clear any friends that are remaining from before the squad mode // IF Private_IsFriendValid(gActivity.mFriendA) // Private_SetFriendRejected(gActivity.mFriendA, g_BattleBuddyMission, FALSE, NO_FRIEND_ACTIVITY_PHRASE) // ENDIF // IF Private_IsFriendValid(gActivity.mFriendB) // Private_SetFriendRejected(gActivity.mFriendB, g_BattleBuddyMission, FALSE, NO_FRIEND_ACTIVITY_PHRASE) // ENDIF // // Private_CleanupFriend(gActivity.mPlayer) // Private_CleanupFriend(gActivity.mFriendA) // Private_CleanupFriend(gActivity.mFriendB) // // //g_bitfieldBattleBuddyAvailable = 0 // Does this need doing? // // DEACTIVATE_ALL_CONNECTIONS() // // enumFriendConnection eConnection // enumCharacterList ePlayerChar = GET_CURRENT_PLAYER_PED_ENUM() // // // Transfer soldiers to friends // BOOL bAddedFriendA = FALSE // // IF NOT IS_PED_INJURED(gActivity.mSoldiers[ePlayerChar].hPed) // // // Transfer player // Private_CleanupSoldier(gActivity.mSoldiers[ePlayerChar], MC_LeavePedIntact) // Private_AddFriend(gActivity.mPlayer, ePlayerChar, NO_FRIEND_LOCATION, 0, FALSE) // // // Transfer other buddies // enumCharacterList eChar // REPEAT MAX_BATTLE_BUDDIES eChar // IF eChar <> ePlayerChar // IF NOT IS_PED_INJURED(gActivity.mSoldiers[eChar].hPed) // IF (gActivity.mSoldiers[eChar].eState = SOLDIER_GROUP // OR gActivity.mSoldiers[eChar].eState = SOLDIER_APPROACH // OR gActivity.mSoldiers[eChar].eState = SOLDIER_OVERRIDDEN) // AND Private_IsSoldierGlobalFlagSet(gActivity.mSoldiers[eChar], g_bitfieldBattleBuddyAvailable) // // Private_CleanupSoldier(gActivity.mSoldiers[eChar], MC_LeavePedIntact) // // IF GET_CONNECTION(ePlayerChar, eChar, eConnection) // IF ACTIVATE_CONNECTION(eConnection, FC_MODE_Friend) // IF bAddedFriendA = FALSE // Private_AddFriend(gActivity.mFriendA, eChar, NO_FRIEND_LOCATION, 0, TRUE) // bAddedFriendA = TRUE // ELSE // Private_AddFriend(gActivity.mFriendB, eChar, NO_FRIEND_LOCATION, 0, TRUE) // ENDIF // ENDIF // ENDIF // // ELSE // Private_CleanupSoldier(gActivity.mSoldiers[eChar], MC_Release) // ENDIF // ENDIF // ENDIF // ENDREPEAT // // ENDIF // // CPRINTLN(DEBUG_FRIENDS, "Private_TransferMembersToFriends() - ** TRANSFER DONE **\n") // RETURN ARE_ANY_FRIEND_CONNECTIONS_PENDING_OR_ACTIVE() ENDFUNC //--------------------------------------------------------------------------------------------------- //-- Friend fails //--------------------------------------------------------------------------------------------------- FUNC BOOL Private_AreFriendsFailed() // If all members have failed, fail mission IF gActivity.mFriendA.eState = FRIEND_NULL AND gActivity.mFriendB.eState = FRIEND_NULL IF Private_GetDialogueState(gActivity.mDialogue) <> FDIALOGUE_REJECTED IF gActivity.iFailQueueCount = 0 RETURN TRUE ENDIF ENDIF ENDIF RETURN FALSE ENDFUNC FUNC BOOL Private_AreAnyMembersValid() // Are any friends are valid... IF (gActivity.mFriendA.eState <> FRIEND_NULL AND gActivity.mFriendA.eState < FRIEND_CANCEL) OR (gActivity.mFriendB.eState <> FRIEND_NULL AND gActivity.mFriendB.eState < FRIEND_CANCEL) RETURN TRUE ENDIF // Are any soldiers valid... enumCharacterList eLoopChar REPEAT MAX_BATTLE_BUDDIES eLoopChar IF gActivity.mSoldiers[eLoopChar].eState <> SOLDIER_NULL AND gActivity.mSoldiers[eLoopChar].eState <> SOLDIER_PLAYER AND gActivity.mSoldiers[eLoopChar].eState < SOLDIER_FAIL_INJURED RETURN TRUE ENDIF ENDREPEAT RETURN FALSE ENDFUNC FUNC BOOL Private_AreAllMembersRemoved() // If any friends are valid, don't fail IF gActivity.mFriendA.eState <> FRIEND_NULL OR gActivity.mFriendB.eState <> FRIEND_NULL RETURN FALSE ENDIF // If any soldiers are valid don't fail enumCharacterList eLoopChar REPEAT MAX_BATTLE_BUDDIES eLoopChar IF gActivity.mSoldiers[eLoopChar].eState <> SOLDIER_NULL AND gActivity.mSoldiers[eLoopChar].eState <> SOLDIER_PLAYER RETURN FALSE ENDIF ENDREPEAT // If doing rejection dialogue, or need to print fail reason don't fail IF Private_GetDialogueState(gActivity.mDialogue) = FDIALOGUE_REJECTED OR gActivity.iFailQueueCount > 0 RETURN FALSE ENDIF RETURN TRUE ENDFUNC PROC Private_ProcessSystem(BOOL bProcessHelp = FALSE) Private_ProcessDialogue(gActivity.mDialogue, gActivity.mAudio) Private_UpdateGlobalFriendHandles() Private_ProcessFailReasonQueue() Private_ProcessTextMessageQueue() IF bProcessHelp Private_ProcessHelp() ENDIF ENDPROC