4689 lines
161 KiB
Scheme
Executable File
4689 lines
161 KiB
Scheme
Executable File
//- commands headers -//
|
|
USING "rage_builtins.sch"
|
|
USING "globals.sch"
|
|
USING "commands_script.sch"
|
|
USING "commands_replay.sch"
|
|
|
|
//- script headers -//
|
|
USING "rc_helper_functions.sch"
|
|
USING "rgeneral_include.sch"
|
|
|
|
//- public headers -//
|
|
USING "player_ped_public.sch"
|
|
USING "timer_public.sch"
|
|
USING "dialogue_public.sch"
|
|
USING "blip_control_public.sch"
|
|
USING "flow_public_core_override.sch"
|
|
|
|
USING "organiser_public.sch"
|
|
USING "selector_public.sch"
|
|
USING "context_control_public.sch"
|
|
|
|
USING "chase_hint_cam.sch"
|
|
USING "friends_public.sch"
|
|
USING "friendActivity_public.sch"
|
|
|
|
USING "rc_threat_public.sch"
|
|
|
|
//- private headers -//
|
|
USING "friendUtil_private.sch"
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
//- debug headers -//
|
|
USING "script_debug.sch"
|
|
USING "shared_debug.sch"
|
|
#ENDIF
|
|
|
|
///private header for friend controller scripts
|
|
/// sam.hackett@rockstarnorth.com
|
|
///
|
|
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
PROC DEBUG_PrintFriendCallInfo(STRING sDescription, TEXT_LABEL tGreetingA, TEXT_LABEL tGreetingB, TEXT_LABEL tAnswerA, TEXT_LABEL tAnswerB)
|
|
|
|
TEXT_LABEL_63 tGreeting = ""
|
|
tGreeting += tGreetingA
|
|
tGreeting += ", "
|
|
tGreeting += tGreetingB
|
|
tGreeting += ", "
|
|
|
|
TEXT_LABEL_63 tAnswer = ""
|
|
tAnswer += tAnswerA
|
|
tAnswer += ", "
|
|
tAnswer += tAnswerB
|
|
|
|
CPRINTLN(DEBUG_FRIENDS, "DEBUG_PrintFriendCallInfo(", sDescription, ": ", tGreeting, tAnswer, ")")
|
|
|
|
ENDPROC
|
|
#ENDIF
|
|
|
|
// *******************************************************************************************
|
|
// Checks for if friend call will be successful
|
|
// *******************************************************************************************
|
|
|
|
FUNC BOOL PRIVATE_Get_Sleep_Times_from_enumFriend(enumFriend friendID, INT &iAwakeHour, INT &iSleepHour)
|
|
SWITCH friendID
|
|
CASE FR_MICHAEL iAwakeHour = 0 iSleepHour = 0 RETURN TRUE BREAK
|
|
CASE FR_FRANKLIN iAwakeHour = 0 iSleepHour = 0 RETURN TRUE BREAK
|
|
CASE FR_TREVOR iAwakeHour = 0 iSleepHour = 0 RETURN TRUE BREAK
|
|
CASE FR_LAMAR iAwakeHour = 0 iSleepHour = 0 RETURN TRUE BREAK
|
|
CASE FR_JIMMY iAwakeHour = 14 iSleepHour = 5 RETURN TRUE BREAK
|
|
CASE FR_AMANDA iAwakeHour = 9 iSleepHour = 0 RETURN TRUE BREAK
|
|
ENDSWITCH
|
|
|
|
SCRIPT_ASSERT("invalid friendID in PRIVATE_Get_Sleep_Times_from_enumFriend()")
|
|
iAwakeHour = -1
|
|
iSleepHour = 24
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
FUNC BOOL PRIVATE_FriendAcceptsPlayer_exists(enumFriend eFriend)
|
|
|
|
enumCharacterList eFriendChar = GET_CHAR_FROM_FRIEND(eFriend)
|
|
|
|
IF NOT IS_PED_THE_CURRENT_PLAYER_PED(eFriendChar)
|
|
// Playable char
|
|
IF IS_PLAYER_PED_PLAYABLE(eFriendChar)
|
|
|
|
SELECTOR_SLOTS_ENUM eSelectorSlot = GET_SELECTOR_SLOT_FROM_PLAYER_PED_ENUM(eFriendChar)
|
|
IF eSelectorSlot < SELECTOR_PED_MULTIPLAYER
|
|
PED_INDEX playerLastKnownPedID = g_sPlayerPedRequest.sSelectorPeds.pedID[eSelectorSlot]
|
|
IF DOES_ENTITY_EXIST(playerLastKnownPedID)
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// NPC char
|
|
ELSE
|
|
INT iIndex = ENUM_TO_INT(eFriend) - NUM_OF_PLAYABLE_PEDS
|
|
|
|
IF iIndex < NUM_OF_NPC_FRIENDS
|
|
IF DOES_ENTITY_EXIST(g_pGlobalFriends[iIndex])
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
FUNC BOOL PRIVATE_FriendAcceptsPlayer_fail(enumFriend eFriendID) // BBUDDIES REMOVED
|
|
|
|
IF HAS_FRIEND_FAILED(eFriendID)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
FUNC BOOL PRIVATE_FriendAcceptsPlayer_hiatusBlock(enumFriend playerID, enumFriend friendID)
|
|
|
|
RETURN NOT IS_FRIEND_BLOCK_FLAG_SET(GET_CHAR_FROM_FRIEND(playerID), GET_CHAR_FROM_FRIEND(friendID), FRIEND_BLOCK_FLAG_HIATUS)
|
|
|
|
ENDFUNC
|
|
|
|
FUNC BOOL PRIVATE_FriendAcceptsPlayer_clashBlock(enumFriend playerID, enumFriend friendID)
|
|
|
|
RETURN NOT IS_FRIEND_BLOCK_FLAG_SET(GET_CHAR_FROM_FRIEND(playerID), GET_CHAR_FROM_FRIEND(friendID), FRIEND_BLOCK_FLAG_CLASH)
|
|
|
|
ENDFUNC
|
|
|
|
FUNC BOOL PRIVATE_FriendAcceptsPlayer_missionBlock(enumFriend playerID, enumFriend friendID)
|
|
|
|
RETURN NOT IS_FRIEND_BLOCK_FLAG_SET(GET_CHAR_FROM_FRIEND(playerID), GET_CHAR_FROM_FRIEND(friendID), FRIEND_BLOCK_FLAG_MISSION)
|
|
|
|
ENDFUNC
|
|
|
|
FUNC BOOL PRIVATE_FriendAcceptsPlayer_missionBlock_AnswerPhone(enumFriend playerID, enumFriend friendID)
|
|
#if USE_CLF_DLC
|
|
playerID = playerID
|
|
friendID = friendID
|
|
#ENDIF
|
|
#if USE_NRM_DLC
|
|
playerID = playerID
|
|
friendID = friendID
|
|
#ENDIF
|
|
#if not USE_CLF_DLC
|
|
#if not USE_NRM_DLC
|
|
IF (playerID = FR_MICHAEL AND friendID = FR_TREVOR)
|
|
OR (friendID = FR_MICHAEL AND playerID = FR_TREVOR)
|
|
IF IS_FRIEND_BLOCK_FLAG_SET(GET_CHAR_FROM_FRIEND(playerID), GET_CHAR_FROM_FRIEND(friendID), FRIEND_BLOCK_FLAG_MISSION)
|
|
IF g_SavedGlobals.sFriendsData.g_FriendConnectData[FC_TREVOR_MICHAEL].blockMissionID = SP_MISSION_MICHAEL_1
|
|
CPRINTLN(DEBUG_FRIENDS, "PRIVATE_FriendAcceptsPlayer_missionBlock_AnswerPhone: SP_MISSION_MICHAEL_1")
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
#ENDIF
|
|
#ENDIF
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
FUNC BOOL PRIVATE_FriendAcceptsPlayer_wanted(enumFriend playerID, enumFriend friendID)
|
|
|
|
enumFriendConnection eConnID = GET_CONNECTION_FROM_FRIENDS(playerID, friendID)
|
|
enumFriend wantedFriend = g_SavedGlobals.sFriendsData.g_FriendConnectData[eConnID].wanted
|
|
|
|
IF playerID = wantedFriend
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
FUNC BOOL PRIVATE_FriendAcceptsPlayer_group(enumFriend ePlayerID, enumFriend eFriendID)
|
|
|
|
enumCharacterList ePlayerChar = GET_CHAR_FROM_FRIEND(ePlayerID)
|
|
enumCharacterList eFriendChar = GET_CHAR_FROM_FRIEND(eFriendID)
|
|
|
|
enumFriendConnection eDesiredConnection
|
|
enumFriendConnection eActiveConnection
|
|
enumFriendConnection eCommonConnection
|
|
|
|
INT iActiveOrPendingFriends = GET_PENDING_OR_ACTIVE_CONNECTIONS(eActiveConnection)
|
|
|
|
// Make sure the requested connection is ready
|
|
IF GET_CONNECTION(ePlayerChar, eFriendChar, eDesiredConnection)
|
|
AND GET_CONNECTION_STATE(eDesiredConnection) = FC_STATE_ContactWait
|
|
|
|
// If no connections running...
|
|
IF iActiveOrPendingFriends = 0
|
|
RETURN TRUE
|
|
|
|
// If one connection are already running...
|
|
ELIF iActiveOrPendingFriends = 1
|
|
|
|
// Make sure there's a common connection, and it's ready
|
|
IF GET_COMMON_CONNECTION(eActiveConnection, eDesiredConnection, eCommonConnection)
|
|
AND GET_CONNECTION_STATE(eCommonConnection) = FC_STATE_ContactWait
|
|
|
|
// Don't allow multiple hangouts involving Jimmmy
|
|
IF DOES_CONNECTION_INVOLVE_CHAR(eDesiredConnection, CHAR_JIMMY)
|
|
OR DOES_CONNECTION_INVOLVE_CHAR(eActiveConnection, CHAR_JIMMY)
|
|
RETURN FALSE
|
|
ELSE
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
|
|
ENDFUNC
|
|
|
|
FUNC BOOL PRIVATE_FriendAcceptsPlayer_common(enumFriend ePlayerID, enumFriend eFriendID)
|
|
|
|
enumCharacterList ePlayerChar = GET_CHAR_FROM_FRIEND(ePlayerID)
|
|
enumCharacterList eFriendChar = GET_CHAR_FROM_FRIEND(eFriendID)
|
|
|
|
enumFriendConnection eDesiredConnection
|
|
enumFriendConnection eActiveConnection
|
|
enumFriendConnection eCommonConnection
|
|
|
|
INT iActiveOrPendingFriends = GET_PENDING_OR_ACTIVE_CONNECTIONS(eActiveConnection)
|
|
|
|
// Make sure the requested connection is ready
|
|
IF GET_CONNECTION(ePlayerChar, eFriendChar, eDesiredConnection)
|
|
|
|
// If no connections running...
|
|
IF iActiveOrPendingFriends = 0
|
|
RETURN TRUE
|
|
|
|
// If one connection are already running...
|
|
ELIF iActiveOrPendingFriends = 1
|
|
|
|
// Make sure there's a common connection, and it's not blocked
|
|
IF GET_COMMON_CONNECTION(eActiveConnection, eDesiredConnection, eCommonConnection)
|
|
|
|
IF g_SavedGlobals.sFriendsData.g_FriendConnectData[eCommonConnection].blockBits = 0
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
|
|
ENDFUNC
|
|
|
|
FUNC BOOL PRIVATE_FriendAcceptsPlayer_time(enumFriend playerID, enumFriend friendID, FLOAT &fLastContactTime, enumFriendContactType &eLastContactType)
|
|
enumCharacterList playerCharID = GET_CHAR_FROM_FRIEND(playerID)
|
|
enumCharacterList friendCharID = GET_CHAR_FROM_FRIEND(friendID)
|
|
|
|
fLastContactTime = Private_GET_FRIEND_LAST_CONTACT_TIME(playerCharID, friendCharID)
|
|
eLastContactType = Private_GET_FRIEND_LAST_CONTACT_TYPE(playerCharID, friendCharID)
|
|
|
|
CONST_FLOAT CONST_fPlayerRealtimeMinuteWait 5.0
|
|
|
|
IF fLastContactTime <= (CONST_fPlayerRealtimeMinuteWait*60.0)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
FUNC BOOL PRIVATE_FriendAcceptsPlayer_awake(enumFriend friendID, INT &iAwakeHour, INT &iSleepHour, INT &iCurrentHour)
|
|
|
|
PRIVATE_Get_Sleep_Times_from_enumFriend(friendID, iAwakeHour, iSleepHour)
|
|
iCurrentHour = GET_CLOCK_HOURS()
|
|
|
|
IF iAwakeHour < iSleepHour
|
|
IF iCurrentHour < iAwakeHour
|
|
OR iCurrentHour >= iSleepHour
|
|
RETURN FALSE
|
|
ELSE
|
|
RETURN TRUE
|
|
ENDIF
|
|
ELSE
|
|
IF iCurrentHour < iAwakeHour
|
|
AND iCurrentHour >= iSleepHour
|
|
RETURN FALSE
|
|
ELSE
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ENDFUNC
|
|
|
|
FUNC BOOL PRIVATE_FriendAcceptsPlayer_laylow(enumFriend friendID)
|
|
|
|
// After the finale, if Michael/Trevor killed, Lamar lays low and will only go out at night
|
|
IF friendID = FR_LAMAR
|
|
#if not USE_CLF_DLC
|
|
#if not USE_NRM_DLC
|
|
IF (GET_MISSION_FLOW_FLAG_STATE(FLOWFLAG_MICHAEL_KILLED)
|
|
OR GET_MISSION_FLOW_FLAG_STATE(FLOWFLAG_TREVOR_KILLED))
|
|
INT iCurrentHour = GET_CLOCK_HOURS()
|
|
|
|
IF iCurrentHour < 21
|
|
AND iCurrentHour >= 5
|
|
RETURN FALSE
|
|
ELSE
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
#endif
|
|
#endif
|
|
ENDIF
|
|
|
|
RETURN TRUE
|
|
|
|
ENDFUNC
|
|
|
|
FUNC BOOL PRIVATE_FriendAcceptsPlayer(enumFriend playerID, enumFriend friendID)
|
|
|
|
// Can't accept call if laying low
|
|
IF NOT PRIVATE_FriendAcceptsPlayer_laylow(friendID)
|
|
CPRINTLN(DEBUG_FRIENDS, "friend ", GetLabel_enumFriend(friendID), "can't accept call: laying low")
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
// Can't accept as blocked by mission
|
|
IF NOT PRIVATE_FriendAcceptsPlayer_missionBlock(playerID, friendID)
|
|
#IF IS_DEBUG_BUILD
|
|
enumFriendConnection eConn = GET_CONNECTION_FROM_FRIENDS(playerID, friendID)
|
|
TEXT_LABEL tFriend = GetLabel_enumFriend(friendID)
|
|
TEXT_LABEL tMission = GET_SP_MISSION_DISPLAY_STRING_FROM_ID(g_SavedGlobals.sFriendsData.g_FriendConnectData[eConn].blockMissionID)
|
|
CPRINTLN(DEBUG_FRIENDS, "friend ", tFriend, " can't accept hangout: will be appearing with player in mission '", tMission, "'")
|
|
#ENDIF
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
// Can't accept as blocked by clash
|
|
IF NOT PRIVATE_FriendAcceptsPlayer_clashBlock(playerID, friendID)
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_FRIENDS, "friend ", GetLabel_enumFriend(friendID), " can't accept call: blocked (clash type)")
|
|
#ENDIF
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
// Can't accept as called recently (and isn't specifically wanted)
|
|
enumFriendContactType eLastContactType
|
|
FLOAT fLastContactTime
|
|
|
|
IF NOT PRIVATE_FriendAcceptsPlayer_wanted(playerID, friendID)
|
|
IF NOT PRIVATE_FriendAcceptsPlayer_time(playerID, friendID, fLastContactTime, eLastContactType)
|
|
|
|
CPRINTLN(DEBUG_FRIENDS, "friend ", GetLabel_enumFriend(friendID), "can't accept hangout: contacted too recently: ", GET_STRING_FROM_MILISECONDS(ROUND((fLastContactTime) * 1000.0)),
|
|
" <= (five minutes) //FCR_time_", ENUM_TO_INT(eLastContactType))
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// Can't accept as other activities are running, and the common connection is blocked
|
|
IF NOT PRIVATE_FriendAcceptsPlayer_common(playerID, friendID)
|
|
CPRINTLN(DEBUG_FRIENDS, "friend ", GetLabel_enumFriend(friendID), " can't accept multiple hangout: common connection blocked")
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
FUNC BOOL PRIVATE_FriendAcceptsCall(enumFriend playerID, enumFriend friendID)
|
|
|
|
INT iAwakeHour, iSleepHour, iCurrentHour
|
|
|
|
// Can't accept call if friend ped exists
|
|
IF NOT PRIVATE_FriendAcceptsPlayer_exists(friendID)
|
|
CPRINTLN(DEBUG_FRIENDS, "friend ", GetLabel_enumFriend(friendID), " can't accept call: Friend ped exists")
|
|
RETURN FALSE
|
|
|
|
// Can't accept call if friend failed recently
|
|
ELIF NOT PRIVATE_FriendAcceptsPlayer_fail(friendID)
|
|
CPRINTLN(DEBUG_FRIENDS, "friend ", GetLabel_enumFriend(friendID), "can't accept call: char failed recently")
|
|
RETURN FALSE
|
|
|
|
// Can't accept call if friend is blocked by mission where player character doesn't know about friend's participation in advance
|
|
ELIF NOT PRIVATE_FriendAcceptsPlayer_missionBlock_AnswerPhone(playerID, friendID)
|
|
CPRINTLN(DEBUG_FRIENDS, "friend ", GetLabel_enumFriend(friendID), " can't accept call: blocked (mission - divert to answerphone)")
|
|
RETURN FALSE
|
|
|
|
// Can't accept call if friend is blocked by hiatus
|
|
ELIF NOT PRIVATE_FriendAcceptsPlayer_hiatusBlock(playerID, friendID)
|
|
CPRINTLN(DEBUG_FRIENDS, "friend ", GetLabel_enumFriend(friendID), " can't accept call: blocked (hiatus type)")
|
|
RETURN FALSE
|
|
|
|
// Can't accept multiple activity call if group not allowed
|
|
ELIF NOT PRIVATE_FriendAcceptsPlayer_group(playerID, friendID)
|
|
CPRINTLN(DEBUG_FRIENDS, "friend ", GetLabel_enumFriend(friendID), "can't accept call: group not allowed")
|
|
RETURN FALSE
|
|
|
|
// Can't accept call if not awake
|
|
ELIF NOT PRIVATE_FriendAcceptsPlayer_awake(friendID, iAwakeHour, iSleepHour, iCurrentHour)
|
|
CPRINTLN(DEBUG_FRIENDS, "friend ", GetLabel_enumFriend(friendID), "can't accept call: asleep: ", iAwakeHour, " < ", iCurrentHour, " < ", iSleepHour)
|
|
RETURN FALSE
|
|
|
|
// If we know friend wants to play, but conditions mean he must decline - just go to answer phone so he doesn't have to give an excuse.
|
|
ELIF PRIVATE_FriendAcceptsPlayer_wanted(playerID, friendID)
|
|
|
|
IF NOT PRIVATE_FriendAcceptsPlayer(playerID, friendID)
|
|
CPRINTLN(DEBUG_FRIENDS, "friend ", GetLabel_enumFriend(friendID), "can't accept call: Can't accept player, but is known to want to see them")
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
ENDIF
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
|
|
// *******************************************************************************************
|
|
// Checks for if squad call will be successful
|
|
// *******************************************************************************************
|
|
|
|
//FUNC BOOL PRIVATE_SquadAcceptsPlayer_fail(enumFriend eFriendID) // BBUDDIES REMOVED
|
|
//
|
|
// IF HAS_SOLDIER_FAILED(GET_CHAR_FROM_FRIEND(eFriendID))
|
|
// RETURN FALSE
|
|
// ENDIF
|
|
//
|
|
// RETURN TRUE
|
|
//ENDFUNC
|
|
//
|
|
//FUNC BOOL PRIVATE_SquadAcceptsPlayer_group(enumFriend ePlayerID, enumFriend eFriendID)
|
|
//
|
|
// enumCharacterList ePlayerChar = GET_CHAR_FROM_FRIEND(ePlayerID)
|
|
// enumCharacterList eFriendChar = GET_CHAR_FROM_FRIEND(eFriendID)
|
|
//
|
|
// enumFriendConnection eDesiredConnection
|
|
// enumFriendConnection eActiveConnection
|
|
// enumFriendConnection eCommonConnection
|
|
//
|
|
// // Make sure the requested connection is ready
|
|
// IF GET_CONNECTION(ePlayerChar, eFriendChar, eDesiredConnection)
|
|
// AND GET_CONNECTION_STATE(eDesiredConnection) = FC_STATE_ContactWait
|
|
//
|
|
// INT iActiveOrPendingSoldiers = GET_PENDING_OR_ACTIVE_CONNECTIONS(eActiveConnection)
|
|
//
|
|
// // If no connections running...
|
|
// IF iActiveOrPendingSoldiers = 0
|
|
// RETURN TRUE
|
|
//
|
|
// // If one connection are already running...
|
|
// ELIF iActiveOrPendingSoldiers = 1
|
|
//
|
|
// // Make sure there's a common connection, and it's ready
|
|
// IF GET_COMMON_CONNECTION(eActiveConnection, eDesiredConnection, eCommonConnection)
|
|
// AND GET_CONNECTION_STATE(eCommonConnection) = FC_STATE_ContactWait
|
|
//
|
|
// RETURN TRUE
|
|
//
|
|
// ENDIF
|
|
// ENDIF
|
|
// ENDIF
|
|
//
|
|
// RETURN FALSE
|
|
//
|
|
//ENDFUNC
|
|
//
|
|
//FUNC BOOL PRIVATE_SquadAcceptsPlayer_count()
|
|
//
|
|
// // One buddy limit applies on big score prep B
|
|
// IF g_BattleBuddyMission = SP_HEIST_FINALE_PREP_B
|
|
// OR g_BattleBuddyMission = SP_MISSION_FBI_4_PREP_2
|
|
// IF ARE_ANY_SQUAD_CONNECTIONS_PENDING_OR_ACTIVE()
|
|
// RETURN FALSE
|
|
// ENDIF
|
|
// ENDIF
|
|
//
|
|
// RETURN TRUE
|
|
//
|
|
//ENDFUNC
|
|
//
|
|
//FUNC BOOL PRIVATE_SquadAcceptsCall(enumFriend playerID, enumFriend friendID)
|
|
//
|
|
// // Can't accept call if battle buddy exists
|
|
// IF NOT PRIVATE_FriendAcceptsPlayer_exists(friendID)
|
|
// CPRINTLN(DEBUG_FRIENDS, "buddy ", GetLabel_enumFriend(friendID), " can't accept call: Battle buddy exists")
|
|
// RETURN FALSE
|
|
//
|
|
// // Can't accept call if battle buddy came already and failed
|
|
// ELIF NOT PRIVATE_SquadAcceptsPlayer_fail(friendID)
|
|
// CPRINTLN(DEBUG_FRIENDS, "buddy ", GetLabel_enumFriend(friendID), " can't accept call: Battle buddy failed recently")
|
|
// RETURN FALSE
|
|
//
|
|
// // Can't accept call if friend is blocked by hiatus
|
|
//// ELIF NOT PRIVATE_FriendAcceptsPlayer_hiatusBlock(playerID, friendID)
|
|
//// CPRINTLN(DEBUG_FRIENDS, "friend ", GetLabel_enumFriend(friendID), " can't accept call: blocked (hiatus type)")
|
|
//// RETURN FALSE
|
|
//
|
|
// // Can't accept multiple activity call if group not allowed
|
|
// ELIF NOT PRIVATE_SquadAcceptsPlayer_group(playerID, friendID)
|
|
// CPRINTLN(DEBUG_FRIENDS, "buddy ", GetLabel_enumFriend(friendID), "can't accept call: group not allowed")
|
|
// RETURN FALSE
|
|
//
|
|
// // Can't accept call if only one battle buddy is allowed and has already been called
|
|
// ELIF NOT PRIVATE_SquadAcceptsPlayer_count()
|
|
// CPRINTLN(DEBUG_FRIENDS, "buddy ", GetLabel_enumFriend(friendID), " can't accept call: Only one battle buddy allowed")
|
|
// RETURN FALSE
|
|
// ENDIF
|
|
//
|
|
// RETURN TRUE
|
|
//ENDFUNC
|
|
|
|
// *******************************************************************************************
|
|
// GET RELEVANT CONVERSATION
|
|
// *******************************************************************************************
|
|
|
|
FUNC BOOL TIMER_DO_WHEN_VERYIRATE(structTimer &t)
|
|
CONST_FLOAT fCONST_MINUTES_IN_HOUR 60.0
|
|
|
|
CONST_FLOAT fCONST_VERY_IRATE_minToWait 300.0
|
|
// CONST_FLOAT fCONST_IRATE_minToWait 60.0
|
|
|
|
IF TIMER_DO_WHEN_READY(t, fCONST_VERY_IRATE_minToWait*fCONST_MINUTES_IN_HOUR)
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
FUNC BOOL TIMER_DO_WHEN_IRATE(structTimer &t)
|
|
CONST_FLOAT fCONST_MINUTES_IN_HOUR 60.0
|
|
|
|
// CONST_FLOAT fCONST_VERY_IRATE_minToWait 300.0
|
|
CONST_FLOAT fCONST_IRATE_minToWait 60.0
|
|
|
|
IF TIMER_DO_WHEN_READY(t, fCONST_IRATE_minToWait*fCONST_MINUTES_IN_HOUR)
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
FUNC BOOL PRIVATE_Friend_GetPhoneConv_Greet(enumFriend ePlayer, enumFriendPhonePhrase &greetConv_a, enumFriendPhonePhrase &greetConv_b)
|
|
|
|
enumFriend eAlreadyMeetingFriend = NO_FRIEND
|
|
|
|
// If a connection is active (and current player is one of the friends in the connection), must be travelling to meet the other friend in the connection
|
|
enumFriendConnection eActiveConnection
|
|
IF GET_PENDING_OR_ACTIVE_CONNECTIONS(eActiveConnection) > 0
|
|
|
|
enumFriend eActiveFriendA = g_SavedGlobals.sFriendsData.g_FriendConnectData[eActiveConnection].friendA
|
|
enumFriend eActiveFriendB = g_SavedGlobals.sFriendsData.g_FriendConnectData[eActiveConnection].friendB
|
|
|
|
// Friend will be the one who isn't current player
|
|
IF eActiveFriendA = ePlayer
|
|
eAlreadyMeetingFriend = eActiveFriendB
|
|
ENDIF
|
|
IF eActiveFriendB = ePlayer
|
|
eAlreadyMeetingFriend = eActiveFriendA
|
|
ENDIF
|
|
|
|
ENDIF
|
|
|
|
// Setup proper greeting pair
|
|
SWITCH (eAlreadyMeetingFriend)
|
|
CASE FR_MICHAEL
|
|
greetConv_a = FPP_OUTGOING_GREET1
|
|
greetConv_b = FPP_OUTGOING_GREET2_MEETINGMICHAEL
|
|
BREAK
|
|
CASE FR_FRANKLIN
|
|
greetConv_a = FPP_OUTGOING_GREET1
|
|
greetConv_b = FPP_OUTGOING_GREET2_MEETINGFRANKLIN
|
|
BREAK
|
|
CASE FR_TREVOR
|
|
greetConv_a = FPP_OUTGOING_GREET1
|
|
greetConv_b = FPP_OUTGOING_GREET2_MEETINGTREVOR
|
|
BREAK
|
|
CASE FR_LAMAR
|
|
greetConv_a = FPP_OUTGOING_GREET1
|
|
greetConv_b = FPP_OUTGOING_GREET2_MEETINGLAMAR
|
|
BREAK
|
|
DEFAULT
|
|
greetConv_a = FPP_OUTGOING_GREET1
|
|
greetConv_b = FPP_OUTGOING_GREET2
|
|
BREAK
|
|
ENDSWITCH
|
|
|
|
RETURN TRUE
|
|
|
|
ENDFUNC
|
|
|
|
FUNC BOOL PRIVATE_Friend_GetPhoneConv_Accept(enumFriend ePlayer, enumFriend eBuddy, enumFriendPhonePhrase &yesConv_a, enumFriendPhonePhrase &yesConv_b, BOOL bAttemptAdhoc=FALSE)
|
|
|
|
enumFriendConnection eConn = GET_CONNECTION_FROM_FRIENDS(ePlayer, eBuddy)
|
|
|
|
CONST_INT iCONST_LOW_LIKES 30
|
|
|
|
// select YES-ACCEPTED response
|
|
IF NOT g_SavedGlobals.sFriendsData.g_bHelpDoneCanCancel
|
|
yesConv_a = FPP_OUTGOING_YES1_FIRSTTIME
|
|
yesConv_b = FPP_OUTGOING_YES2_OK
|
|
RETURN TRUE
|
|
ELSE
|
|
|
|
// enumFriend eAlreadyMeetingFriend = NO_FRIEND
|
|
//
|
|
// // If a connection is active (and phone call being made to one of the friends in the connection), must be travelling to meet the other friend in the connection
|
|
// enumFriendConnection eActiveConnection
|
|
// IF GET_ONLY_ACTIVE_CONNECTION(eActiveConnection)
|
|
//
|
|
// enumFriend eActiveFriendA = g_SavedGlobals.sFriendsData.g_FriendConnectData[eActiveConnection].friendA
|
|
// enumFriend eActiveFriendB = g_SavedGlobals.sFriendsData.g_FriendConnectData[eActiveConnection].friendB
|
|
//
|
|
// // Friend will be the one who isn't current player
|
|
// IF eActiveFriendA = eBuddy
|
|
// eAlreadyMeetingFriend = eActiveFriendB
|
|
// ENDIF
|
|
// IF eActiveFriendB = eBuddy
|
|
// eAlreadyMeetingFriend = eActiveFriendA
|
|
// ENDIF
|
|
//
|
|
// ENDIF
|
|
//
|
|
// IF eAlreadyMeetingFriend <> NO_FRIEND
|
|
// SWITCH (eAlreadyMeetingFriend)
|
|
// CASE FR_MICHAEL
|
|
// yesConv_a = FPP_OUTGOING_YES1_MEETINGMICHAEL
|
|
// yesConv_b = FPP_OUTGOING_YES2_OK
|
|
// RETURN TRUE
|
|
// BREAK
|
|
// CASE FR_FRANKLIN
|
|
// yesConv_a = FPP_OUTGOING_YES1_MEETINGFRANKLIN
|
|
// yesConv_b = FPP_OUTGOING_YES2_OK
|
|
// RETURN TRUE
|
|
// BREAK
|
|
// CASE FR_TREVOR
|
|
// yesConv_a = FPP_OUTGOING_YES1_MEETINGTREVOR
|
|
// yesConv_b = FPP_OUTGOING_YES2_OK
|
|
// RETURN TRUE
|
|
// BREAK
|
|
// CASE FR_LAMAR
|
|
// yesConv_a = FPP_OUTGOING_YES1_MEETINGLAMAR
|
|
// yesConv_b = FPP_OUTGOING_YES2_OK
|
|
// RETURN TRUE
|
|
// BREAK
|
|
// ENDSWITCH
|
|
|
|
// IF ARE_ANY_EVENTS_PENDING_IN_ORGANISER() // TODO: Surely this needs to know which organiser the event is in?
|
|
// yesConv_a = FPP_OUTGOING_YES1_BUSY
|
|
// yesConv_b = FPP_OUTGOING_YES2_OK
|
|
// RETURN TRUE
|
|
// ELSE
|
|
IF (g_SavedGlobals.sFriendsData.g_FriendConnectData[eConn].likes < iCONST_LOW_LIKES)
|
|
yesConv_a = FPP_OUTGOING_YES1_LIKELOW
|
|
yesConv_b = FPP_OUTGOING_YES2_OK
|
|
RETURN TRUE
|
|
ELIF TIMER_DO_WHEN_VERYIRATE(g_SavedGlobals.sFriendsData.g_FriendConnectData[eConn].lastContactTimer)
|
|
yesConv_a = FPP_OUTGOING_YES1_VERYIRATE
|
|
yesConv_b = FPP_OUTGOING_YES2_OK
|
|
RETURN TRUE
|
|
ELIF TIMER_DO_WHEN_IRATE(g_SavedGlobals.sFriendsData.g_FriendConnectData[eConn].lastContactTimer)
|
|
yesConv_a = FPP_OUTGOING_YES1_IRATE
|
|
yesConv_b = FPP_OUTGOING_YES2_OK
|
|
RETURN TRUE
|
|
ELIF bAttemptAdhoc
|
|
AND GET_RANDOM_INT_IN_RANGE(0, 100) < CONST_iFriendAdhocChance
|
|
AND NOT (ePlayer = FR_TREVOR AND eBuddy = FR_MICHAEL)
|
|
AND NOT (ePlayer = FR_MICHAEL AND eBuddy = FR_AMANDA)
|
|
AND NOT IS_PED_INJURED(PLAYER_PED_ID())
|
|
AND Private_GetAvailableAdhocFriendLoc(GET_ENTITY_COORDS(PLAYER_PED_ID()))
|
|
yesConv_a = FPP_OUTGOING_YES1_COMETOYOU
|
|
yesConv_b = FPP_OUTGOING_YES2_COMETOYOU
|
|
RETURN TRUE
|
|
ELSE
|
|
yesConv_a = FPP_OUTGOING_YES1_OK
|
|
yesConv_b = FPP_OUTGOING_YES2_OK
|
|
RETURN TRUE
|
|
ENDIF
|
|
// ENDIF
|
|
ENDIF
|
|
|
|
SCRIPT_ASSERT("missing PRIVATE_Friend_GetPhoneConv_Accept()")
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
FUNC BOOL PRIVATE_Friend_GetPhoneConv_Reject(enumFriend ePlayer, enumFriend eBuddy, enumFriendPhonePhrase &noConv_a, enumFriendPhonePhrase &noConv_b)
|
|
|
|
enumFriendContactType eLastContactType
|
|
FLOAT fLastContactTime
|
|
|
|
// select NO-REJECT response
|
|
|
|
IF NOT PRIVATE_FriendAcceptsPlayer_time(ePlayer, eBuddy, fLastContactTime, eLastContactType)
|
|
|
|
IF eLastContactType = FRIEND_CONTACT_FACE OR eLastContactType = FRIEND_CONTACT_DISMISSED
|
|
noConv_a = FPP_OUTGOING_NO1_RECENTFACE
|
|
noConv_b = FPP_OUTGOING_NO2
|
|
RETURN TRUE
|
|
ELSE
|
|
noConv_a = FPP_OUTGOING_NO1_RECENTPHONE
|
|
noConv_b = FPP_OUTGOING_NO2
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
ELIF NOT PRIVATE_FriendAcceptsPlayer_missionBlock(ePlayer, eBuddy)
|
|
noConv_a = FPP_OUTGOING_NO1_BLOCKED
|
|
noConv_b = FPP_OUTGOING_NO2
|
|
RETURN TRUE
|
|
|
|
// ELIF NOT PRIVATE_FriendAcceptsPlayer_clashBlock(ePlayer, eBuddy)
|
|
// noConv_a = FPP_OUTGOING_NO1_OK
|
|
// noConv_b = FPP_OUTGOING_NO2
|
|
// RETURN TRUE
|
|
|
|
ELSE
|
|
noConv_a = FPP_OUTGOING_NO1_OK
|
|
noConv_b = FPP_OUTGOING_NO2
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
SCRIPT_ASSERT("missing PRIVATE_Friend_GetPhoneConv_Reject()")
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
FUNC BOOL PRIVATE_Friend_GetPhoneConv(enumFriend ePlayer, enumFriend eBuddy,
|
|
enumFriendPhonePhrase &greetConv_a, enumFriendPhonePhrase &greetConv_b,
|
|
enumFriendPhonePhrase &yesConv_a, enumFriendPhonePhrase &yesConv_b,
|
|
enumFriendPhonePhrase &noConv_a, enumFriendPhonePhrase &noConv_b)
|
|
|
|
// select GREET-HANGOUT response
|
|
PRIVATE_Friend_GetPhoneConv_Greet(ePlayer, greetConv_a, greetConv_b)
|
|
|
|
// select YES-ACCEPTED response
|
|
PRIVATE_Friend_GetPhoneConv_Accept(ePlayer, eBuddy, yesConv_a, yesConv_b)
|
|
|
|
// select NO-REJECT response
|
|
PRIVATE_Friend_GetPhoneConv_Reject(ePlayer, eBuddy, noConv_a, noConv_b)
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
//FUNC BOOL PRIVATE_Friend_GetPhoneConv_Backup(enumFriendPhonePhrase &ePhrase) // BBUDDIES REMOVED
|
|
//
|
|
// // If on/near prep mission use mission-specific dialogue, otherwise use default
|
|
// IF g_eFriendMissionZoneID <> SP_MISSION_NONE
|
|
//
|
|
// SWITCH g_eFriendMissionZoneID
|
|
// CASE SP_HEIST_DOCKS_PREP_2B
|
|
// ePhrase = FPP_BACKUP_DOCKS_2
|
|
// BREAK
|
|
//
|
|
// CASE SP_HEIST_RURAL_PREP_1
|
|
// ePhrase = FPP_BACKUP_RURAL
|
|
// BREAK
|
|
//
|
|
// CASE SP_HEIST_AGENCY_PREP_1
|
|
// ePhrase = FPP_BACKUP_AGENCY
|
|
// BREAK
|
|
//
|
|
// CASE SP_HEIST_FINALE_PREP_A
|
|
// ePhrase = FPP_BACKUP_FINALE_A
|
|
// BREAK
|
|
//
|
|
// CASE SP_HEIST_FINALE_PREP_B
|
|
// ePhrase = FPP_BACKUP_FINALE_B
|
|
// BREAK
|
|
//
|
|
// CASE SP_MISSION_FBI_4_PREP_1
|
|
// ePhrase = FPP_BACKUP_FBI_1
|
|
// BREAK
|
|
//
|
|
// CASE SP_MISSION_FBI_4_PREP_2
|
|
// ePhrase = FPP_BACKUP_FBI_2
|
|
// BREAK
|
|
//
|
|
// CASE SP_MISSION_FBI_4_PREP_4
|
|
// ePhrase = FPP_BACKUP_FBI_4
|
|
// BREAK
|
|
//
|
|
// CASE SP_MISSION_FBI_4_PREP_5
|
|
// ePhrase = FPP_BACKUP_FBI_5
|
|
// BREAK
|
|
//
|
|
// DEFAULT
|
|
// ePhrase = FPP_BACKUP
|
|
// BREAK
|
|
// ENDSWITCH
|
|
//
|
|
// RETURN TRUE
|
|
//
|
|
// ENDIF
|
|
//
|
|
// SCRIPT_ASSERT("missing PRIVATE_Friend_GetPhoneConv_Backup()")
|
|
// ePhrase = FPP_BACKUP
|
|
// RETURN FALSE
|
|
//
|
|
//ENDFUNC
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// *******************************************************************************************
|
|
// APPROACH MONITOR
|
|
// *******************************************************************************************
|
|
|
|
ENUM enumAmbFriendState
|
|
AMBFRIEND_NULL = 0,
|
|
AMBFRIEND_PLAYER,
|
|
AMBFRIEND_IDLE,
|
|
AMBFRIEND_GREET,
|
|
AMBFRIEND_GREET_SAFEHOUSE,
|
|
AMBFRIEND_GREET_OUTSIDE,
|
|
AMBFRIEND_DISMISSED,
|
|
AMBFRIEND_OUTRO
|
|
ENDENUM
|
|
|
|
ENUM enumAmbConvState
|
|
AMBCONV_NULL = 0,
|
|
|
|
AMBCONV_SAFEHOUSE_TRAILER1,
|
|
AMBCONV_SAFEHOUSE_TRAILER2,
|
|
AMBCONV_SAFEHOUSE_TRAILER3,
|
|
|
|
AMBCONV_MFSHOWROOM_HELLO,
|
|
AMBCONV_MFSHOWROOM_CHAT,
|
|
|
|
AMBCONV_MTFALLOUT_HELLO,
|
|
AMBCONV_MTFALLOUT_CHAT,
|
|
|
|
AMBCONV_KILLEDT_HELLO,
|
|
AMBCONV_KILLEDT_CHAT,
|
|
|
|
AMBCONV_KILLEDM_HELLO,
|
|
AMBCONV_KILLEDM_CHAT,
|
|
|
|
AMBCONV_ANGRY_HELLO,
|
|
AMBCONV_ANGRY_GOODBYE,
|
|
|
|
AMBCONV_OFFER_HELLO_HOME,
|
|
AMBCONV_OFFER_HELLO,
|
|
AMBCONV_OFFER_ASK,
|
|
AMBCONV_OFFER_INPUT,
|
|
AMBCONV_OFFER_NO1,
|
|
AMBCONV_OFFER_NO2,
|
|
AMBCONV_OFFER_YES1,
|
|
AMBCONV_OFFER_YES2,
|
|
AMBCONV_OFFER_LAUNCH1,
|
|
AMBCONV_OFFER_LAUNCH2,
|
|
|
|
AMBCONV_MISBLOCK_HELLO_HOME,
|
|
AMBCONV_MISBLOCK_HELLO,
|
|
AMBCONV_MISBLOCK_BUSY,
|
|
AMBCONV_MISBLOCK_GOODBYE,
|
|
|
|
AMBCONV_DEFBLOCK_HELLO_HOME,
|
|
AMBCONV_DEFBLOCK_HELLO,
|
|
AMBCONV_DEFBLOCK_BUSY,
|
|
AMBCONV_DEFBLOCK_GOODBYE
|
|
ENDENUM
|
|
|
|
|
|
STRUCT structAmbFriend
|
|
enumAmbFriendState eState
|
|
enumCharacterList eChar
|
|
PED_INDEX hPed
|
|
VEHICLE_INDEX hVehicle
|
|
|
|
INT iProgress
|
|
PED_INDEX hTargetPed
|
|
REL_GROUP_HASH hOriginalGroup
|
|
REL_GROUP_HASH hOriginalDefaultGroup
|
|
BOOL bIsVulnerable
|
|
|
|
SHAPETEST_INDEX hLosTest
|
|
INT iLosTestTime
|
|
|
|
enumAmbGrabMode eGrabMode
|
|
enumAmbDismissMode eDismissMode
|
|
BOOL bDismissAudioRequest
|
|
BOOL bInitDismissMode
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
PED_INDEX hDebugGrabFail
|
|
#ENDIF
|
|
ENDSTRUCT
|
|
|
|
CONST_INT MAX_GRIEF_OUTRO_AREAS 3
|
|
|
|
STRUCT structAmbGroup
|
|
structAmbFriend mFriends[NUM_OF_PLAYABLE_PEDS]
|
|
INT iGreetCount
|
|
BOOL bHasSaidHello
|
|
BOOL bHasJoined
|
|
|
|
BOOL bIsSwitchActive
|
|
|
|
enumAmbConvState eConvState
|
|
enumCharacterList eConvChar
|
|
BOOL bInitConvState
|
|
INT hConvInput
|
|
structTimer mOfferTimer
|
|
|
|
REL_GROUP_HASH hEmptyGroup
|
|
BOOL bAttemptResumeFightAfterSwitch
|
|
BOOL bUpdateAfterSwitch
|
|
|
|
BOOL bOutroActive
|
|
SHAPETEST_INDEX hOutroTest[MAX_GRIEF_OUTRO_AREAS]
|
|
INT iOutroTestTime[MAX_GRIEF_OUTRO_AREAS]
|
|
VECTOR vOutroTestPos
|
|
FLOAT fOutroTestRot
|
|
INT iOutroSpeechVariation
|
|
|
|
enumCharacterList eOutroChar
|
|
INT hOutroCandidate
|
|
INT hOutroScene
|
|
CAMERA_INDEX hOutroCamera
|
|
SCENARIO_BLOCKING_INDEX hOutroScenarioBlock
|
|
VECTOR vOutroAnchor
|
|
|
|
ENDSTRUCT
|
|
|
|
//------------------------------------------------------------------------------------------------------------------------------
|
|
// Debug
|
|
//------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
FUNC STRING GetLabel_enumAmbFriendState(enumAmbFriendState eState)
|
|
SWITCH eState
|
|
CASE AMBFRIEND_NULL RETURN "AMBFRIEND_NULL" BREAK
|
|
CASE AMBFRIEND_PLAYER RETURN "AMBFRIEND_PLAYER" BREAK
|
|
CASE AMBFRIEND_IDLE RETURN "AMBFRIEND_IDLE" BREAK
|
|
CASE AMBFRIEND_GREET RETURN "AMBFRIEND_GREET" BREAK
|
|
CASE AMBFRIEND_GREET_SAFEHOUSE RETURN "AMBFRIEND_GREET_SAFEHOUSE" BREAK
|
|
CASE AMBFRIEND_GREET_OUTSIDE RETURN "AMBFRIEND_GREET_OUTSIDE" BREAK
|
|
CASE AMBFRIEND_DISMISSED RETURN "AMBFRIEND_DISMISSED" BREAK
|
|
CASE AMBFRIEND_OUTRO RETURN "AMBFRIEND_OUTRO" BREAK
|
|
ENDSWITCH
|
|
|
|
SCRIPT_ASSERT("GetLabel_enumAmbFriendState() - Unknown state")
|
|
RETURN "<unknown state>"
|
|
ENDFUNC
|
|
|
|
FUNC STRING GetLabel_enumAmbConvState(enumAmbConvState eState)
|
|
SWITCH eState
|
|
CASE AMBCONV_NULL RETURN "AMBCONV_NULL" BREAK
|
|
|
|
CASE AMBCONV_SAFEHOUSE_TRAILER1 RETURN "AMBCONV_SAFEHOUSE_TRAILER1" BREAK
|
|
CASE AMBCONV_SAFEHOUSE_TRAILER2 RETURN "AMBCONV_SAFEHOUSE_TRAILER2" BREAK
|
|
CASE AMBCONV_SAFEHOUSE_TRAILER3 RETURN "AMBCONV_SAFEHOUSE_TRAILER3" BREAK
|
|
|
|
CASE AMBCONV_MFSHOWROOM_HELLO RETURN "AMBCONV_MFSHOWROOM_HELLO" BREAK
|
|
CASE AMBCONV_MFSHOWROOM_CHAT RETURN "AMBCONV_MFSHOWROOM_CHAT" BREAK
|
|
|
|
CASE AMBCONV_MTFALLOUT_HELLO RETURN "AMBCONV_MTFALLOUT_HELLO" BREAK
|
|
CASE AMBCONV_MTFALLOUT_CHAT RETURN "AMBCONV_MTFALLOUT_CHAT" BREAK
|
|
|
|
CASE AMBCONV_KILLEDT_HELLO RETURN "AMBCONV_KILLEDT_HELLO" BREAK
|
|
CASE AMBCONV_KILLEDT_CHAT RETURN "AMBCONV_KILLEDT_CHAT" BREAK
|
|
|
|
CASE AMBCONV_KILLEDM_HELLO RETURN "AMBCONV_KILLEDM_HELLO" BREAK
|
|
CASE AMBCONV_KILLEDM_CHAT RETURN "AMBCONV_KILLEDM_CHAT" BREAK
|
|
|
|
CASE AMBCONV_ANGRY_HELLO RETURN "AMBCONV_ANGRY_HELLO" BREAK
|
|
CASE AMBCONV_ANGRY_GOODBYE RETURN "AMBCONV_ANGRY_GOODBYE" BREAK
|
|
|
|
CASE AMBCONV_OFFER_HELLO_HOME RETURN "AMBCONV_OFFER_HELLO_HOME" BREAK
|
|
CASE AMBCONV_OFFER_HELLO RETURN "AMBCONV_OFFER_HELLO" BREAK
|
|
CASE AMBCONV_OFFER_ASK RETURN "AMBCONV_OFFER_ASK" BREAK
|
|
CASE AMBCONV_OFFER_INPUT RETURN "AMBCONV_OFFER_INPUT" BREAK
|
|
CASE AMBCONV_OFFER_NO1 RETURN "AMBCONV_OFFER_NO1" BREAK
|
|
CASE AMBCONV_OFFER_NO2 RETURN "AMBCONV_OFFER_NO2" BREAK
|
|
CASE AMBCONV_OFFER_YES1 RETURN "AMBCONV_OFFER_YES1" BREAK
|
|
CASE AMBCONV_OFFER_YES2 RETURN "AMBCONV_OFFER_YES2" BREAK
|
|
CASE AMBCONV_OFFER_LAUNCH1 RETURN "AMBCONV_OFFER_LAUNCH1" BREAK
|
|
CASE AMBCONV_OFFER_LAUNCH2 RETURN "AMBCONV_OFFER_LAUNCH2" BREAK
|
|
|
|
CASE AMBCONV_MISBLOCK_HELLO_HOME RETURN "AMBCONV_MISBLOCK_HELLO_HOME" BREAK
|
|
CASE AMBCONV_MISBLOCK_HELLO RETURN "AMBCONV_MISBLOCK_HELLO" BREAK
|
|
CASE AMBCONV_MISBLOCK_BUSY RETURN "AMBCONV_MISBLOCK_BUSY" BREAK
|
|
CASE AMBCONV_MISBLOCK_GOODBYE RETURN "AMBCONV_MISBLOCK_GOODBYE" BREAK
|
|
|
|
CASE AMBCONV_DEFBLOCK_HELLO_HOME RETURN "AMBCONV_DEFBLOCK_HELLO_HOME" BREAK
|
|
CASE AMBCONV_DEFBLOCK_HELLO RETURN "AMBCONV_DEFBLOCK_HELLO" BREAK
|
|
CASE AMBCONV_DEFBLOCK_BUSY RETURN "AMBCONV_DEFBLOCK_BUSY" BREAK
|
|
CASE AMBCONV_DEFBLOCK_GOODBYE RETURN "AMBCONV_DEFBLOCK_GOODBYE" BREAK
|
|
ENDSWITCH
|
|
|
|
SCRIPT_ASSERT("GetLabel_enumAmbConvState() - Unknown state")
|
|
RETURN "<unknown state>"
|
|
ENDFUNC
|
|
|
|
FUNC STRING GetLabel_enumAmbDismissMode(enumAmbDismissMode eState)
|
|
SWITCH eState
|
|
CASE AMBMODE_WANDER RETURN "Wander" BREAK
|
|
CASE AMBMODE_FLEE RETURN "Flee" BREAK
|
|
CASE AMBMODE_REJECTED RETURN "Rejected" BREAK
|
|
CASE AMBMODE_JACKED RETURN "Jacked" BREAK
|
|
CASE AMBMODE_FIGHT RETURN "Fight" BREAK
|
|
ENDSWITCH
|
|
|
|
SCRIPT_ASSERT("GetLabel_enumAmbDismissMode() - Unknown state")
|
|
RETURN "<unknown state>"
|
|
ENDFUNC
|
|
|
|
PROC DEBUG_DisplayAmbFriendInfo(structAmbGroup& group, structAmbFriend& friend)
|
|
// Get line to print on
|
|
INT iRow = 4 + ENUM_TO_INT(friend.eChar)
|
|
|
|
// Build string
|
|
TEXT_LABEL_63 tName = GetLabel_enumFriend(GET_FRIEND_FROM_CHAR(friend.eChar))
|
|
IF friend.bIsVulnerable
|
|
tName+="-V"
|
|
ENDIF
|
|
tName += ": "
|
|
tName += GetLabel_enumAmbFriendState(friend.eState)
|
|
|
|
IF friend.eState = AMBFRIEND_DISMISSED
|
|
tName += " / "
|
|
tName += GetLabel_enumAmbDismissMode(friend.eDismissMode)
|
|
IF friend.bDismissAudioRequest
|
|
tName += "*"
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF group.eConvState <> AMBCONV_NULL
|
|
IF group.eConvChar = friend.eChar
|
|
tName += " [conv]"
|
|
ENDIF
|
|
ENDIF
|
|
|
|
DrawFriendLiteralString(tName, iRow, HUD_COLOUR_BLUELIGHT)
|
|
ENDPROC
|
|
|
|
PROC DEBUG_DisplayAmbGroupInfo(structAmbGroup& group)
|
|
IF g_flowUnsaved.bShowMissionFlowDebugScreen
|
|
IF (g_iDebugSelectedFriendConnDisplay > 0)
|
|
|
|
IF NOT IS_FRIEND_ACTIVITY_SCRIPT_RUNNING()
|
|
// Get line to print on
|
|
INT iRow = 4 + NUM_OF_PLAYABLE_PEDS + 1
|
|
|
|
TEXT_LABEL_63 tName = "Conversation: "
|
|
tName += GetLabel_enumAmbConvState(group.eConvState)
|
|
DrawFriendLiteralString(tName, iRow, HUD_COLOUR_BLUELIGHT)
|
|
iRow++
|
|
|
|
tName = ""
|
|
IF group.bHasSaidHello
|
|
tName+= "[HelloDone]"
|
|
ENDIF
|
|
IF group.bHasJoined
|
|
tName+= "[JoinDone]"
|
|
ENDIF
|
|
DrawFriendLiteralString(tName, iRow, HUD_COLOUR_BLUELIGHT)
|
|
|
|
// Print info for each ambfriend
|
|
enumCharacterList eChar
|
|
REPEAT NUM_OF_PLAYABLE_PEDS eChar
|
|
DEBUG_DisplayAmbFriendInfo(group, group.mFriends[eChar])
|
|
ENDREPEAT
|
|
ENDIF
|
|
|
|
ENDIF
|
|
ENDIF
|
|
ENDPROC
|
|
#ENDIF
|
|
|
|
|
|
//------------------------------------------------------------------------------------------------------------------------------
|
|
// AmbFriend - Idle state
|
|
//------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
PROC Private_UpdateAmbFriend_Idle(structAmbGroup& group, structAmbFriend& friend)
|
|
|
|
IF NOT IS_PED_IN_ANY_VEHICLE(friend.hPed)
|
|
|
|
IF friend.iProgress = 0
|
|
|
|
// Is ped on road...
|
|
CLEAR_PED_TASKS(friend.hPed)
|
|
|
|
VECTOR vFriendPos = GET_ENTITY_COORDS(friend.hPed)
|
|
IF IS_POINT_ON_ROAD(vFriendPos, NULL)
|
|
friend.iProgress++
|
|
ELSE
|
|
friend.iProgress = 60
|
|
ENDIF
|
|
|
|
ELIF friend.iProgress < 60
|
|
|
|
// On road -> Try to find pavement pos to walk to
|
|
CPRINTLN(DEBUG_FRIENDS, "Search for pavement vector... (", friend.iProgress, ")")
|
|
friend.iProgress++
|
|
|
|
VECTOR vFriendPos = GET_ENTITY_COORDS(friend.hPed)
|
|
VECTOR vPavementPos
|
|
INT iFlags = ENUM_TO_INT(GSC_FLAG_ONLY_PAVEMENT)|ENUM_TO_INT(GSC_FLAG_NOT_ISOLATED)|ENUM_TO_INT(GSC_FLAG_NOT_INTERIOR)|ENUM_TO_INT(GSC_FLAG_NOT_WATER)
|
|
|
|
IF GET_SAFE_COORD_FOR_PED(vFriendPos, TRUE, vPavementPos, INT_TO_ENUM(GET_SAFE_COORD_FLAGS, iFlags))
|
|
|
|
BOOL bCloseToOtherFriend = FALSE
|
|
enumCharacterList eCharLoop
|
|
REPEAT NUM_OF_PLAYABLE_PEDS eCharLoop
|
|
IF eCharLoop <> friend.eChar
|
|
IF group.mFriends[eCharLoop].eState != AMBFRIEND_NULL
|
|
IF NOT IS_PED_INJURED(group.mFriends[eCharLoop].hPed)
|
|
IF Util_IsPedInsideRange(group.mFriends[eCharLoop].hPed, vPavementPos, 3.0)
|
|
bCloseToOtherFriend = TRUE
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
IF bCloseToOtherFriend = FALSE
|
|
TASK_FOLLOW_NAV_MESH_TO_COORD(friend.hPed, vPavementPos, PEDMOVE_WALK, DEFAULT_TIME_NEVER_WARP)
|
|
CPRINTLN(DEBUG_FRIENDS, "Private_AmbFriendTasks_Idle() DEST = <<", vPavementPos.x, ", ", vPavementPos.y, ", ", vPavementPos.z, ">>")
|
|
friend.iProgress = 60
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ELIF friend.iProgress = 60
|
|
IF NOT IsPedPerformingTask(friend.hPed, SCRIPT_TASK_FOLLOW_NAV_MESH_TO_COORD)
|
|
friend.iProgress++
|
|
ENDIF
|
|
|
|
ELIF friend.iProgress = 61
|
|
IF NOT IS_PED_USING_ANY_SCENARIO(friend.hPed)
|
|
SET_PED_CAN_PLAY_AMBIENT_ANIMS(friend.hPed, TRUE)
|
|
SET_PED_CAN_PLAY_AMBIENT_BASE_ANIMS(friend.hPed, TRUE)
|
|
SET_PED_SHOULD_PLAY_IMMEDIATE_SCENARIO_EXIT(friend.hPed)
|
|
|
|
CLEAR_PED_TASKS(friend.hPed)
|
|
INT iRandom = GET_RANDOM_INT_IN_RANGE(0, 3)
|
|
IF iRandom = 0
|
|
TASK_START_SCENARIO_IN_PLACE(friend.hPed, "WORLD_HUMAN_SMOKING", 0, TRUE)
|
|
ELSE
|
|
TASK_START_SCENARIO_IN_PLACE(friend.hPed, "WORLD_HUMAN_STAND_MOBILE", 0, TRUE)
|
|
ENDIF
|
|
// ELIF iRandom = 2
|
|
// TASK_START_SCENARIO_IN_PLACE(friend.hPed, "WORLD_HUMAN_STAND_IMPATIENT", 0, TRUE)
|
|
// ELIF iRandom = 3
|
|
// TASK_START_SCENARIO_IN_PLACE(friend.hPed, "WORLD_HUMAN_GUARD_STAND", 0, TRUE)
|
|
// ENDIF
|
|
|
|
ELSE//IF NOT IS_PED_ACTIVE_IN_SCENARIO(friend.hPed)
|
|
TRIGGER_IDLE_ANIMATION_ON_PED(friend.hPed)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ELSE
|
|
|
|
friend.iProgress = 0
|
|
VEHICLE_INDEX hVehicle = GET_VEHICLE_PED_IS_IN(friend.hPed)
|
|
|
|
IF GET_PED_IN_VEHICLE_SEAT(hVehicle, VS_DRIVER) = friend.hPed
|
|
IF NOT IsPedPerformingTask(friend.hPed, SCRIPT_TASK_VEHICLE_MISSION)
|
|
CLEAR_PED_TASKS(friend.hPed)
|
|
TASK_VEHICLE_DRIVE_WANDER(friend.hPed, hVehicle, 7.5, DRIVINGMODE_STOPFORCARS)
|
|
ENDIF
|
|
ELSE
|
|
IF ABSF(GET_ENTITY_SPEED(hVehicle)) < 10.0
|
|
IF NOT IsPedPerformingTask(friend.hPed, SCRIPT_TASK_LEAVE_ANY_VEHICLE)
|
|
CLEAR_PED_TASKS(friend.hPed)
|
|
TASK_LEAVE_ANY_VEHICLE(friend.hPed)
|
|
ENDIF
|
|
ELSE
|
|
IF NOT IsPedPerformingTask(friend.hPed, SCRIPT_TASK_PAUSE)
|
|
CLEAR_PED_TASKS(friend.hPed)
|
|
TASK_PAUSE(friend.hPed, -1)
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
//------------------------------------------------------------------------------------------------------------------------------
|
|
// AmbFriend - Greet state
|
|
//------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
PROC Private_UpdateAmbFriend_Greet(structAmbFriend& friend, BOOL bAllowMovement = TRUE)
|
|
|
|
IF bAllowMovement
|
|
|
|
// If in vehicle, leave it
|
|
IF IS_PED_IN_ANY_VEHICLE(friend.hPed)
|
|
IF NOT IsPedPerformingTask(friend.hPed, SCRIPT_TASK_LEAVE_ANY_VEHICLE)
|
|
CLEAR_PED_TASKS(friend.hPed)
|
|
TASK_LEAVE_ANY_VEHICLE(friend.hPed, GET_RANDOM_INT_IN_RANGE(0, 1000), ECF_RESUME_IF_INTERRUPTED)
|
|
ENDIF
|
|
|
|
// If on foot, approach player (run)
|
|
ELIF NOT IS_ENTITY_AT_ENTITY(friend.hPed, PLAYER_PED_ID(), <<15.0, 15.0, 15.0>>)
|
|
IF NOT IsPedPerformingTask(friend.hPed, SCRIPT_TASK_GO_TO_ENTITY)
|
|
CLEAR_PED_TASKS(friend.hPed)
|
|
TASK_GO_TO_ENTITY(friend.hPed, PLAYER_PED_ID(), DEFAULT_TIME_NEVER_WARP, 6.0, PEDMOVE_RUN)
|
|
ENDIF
|
|
|
|
// If on foot, approach player (walk)
|
|
ELIF NOT IS_ENTITY_AT_ENTITY(friend.hPed, PLAYER_PED_ID(), <<7.5, 7.5, 7.5>>)
|
|
IF NOT IsPedPerformingTask(friend.hPed, SCRIPT_TASK_GO_TO_ENTITY)
|
|
CLEAR_PED_TASKS(friend.hPed)
|
|
TASK_GO_TO_ENTITY(friend.hPed, PLAYER_PED_ID(), DEFAULT_TIME_NEVER_WARP, 6.0, PEDMOVE_WALK)
|
|
ENDIF
|
|
|
|
// If on foot, turn to player
|
|
ELSE
|
|
IF NOT IsPedPerformingTask(friend.hPed, SCRIPT_TASK_TURN_PED_TO_FACE_ENTITY)
|
|
CLEAR_PED_TASKS(friend.hPed)
|
|
TASK_TURN_PED_TO_FACE_ENTITY(friend.hPed, PLAYER_PED_ID(), -1)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ENDIF
|
|
|
|
// Peds look at each other
|
|
IF NOT IsPedPerformingTask(friend.hPed, SCRIPT_TASK_LOOK_AT_ENTITY)
|
|
TASK_LOOK_AT_ENTITY(friend.hPed, PLAYER_PED_ID(), -1, SLF_WHILE_NOT_IN_FOV, SLF_LOOKAT_HIGH)
|
|
ENDIF
|
|
|
|
IF NOT IsPedPerformingTask(PLAYER_PED_ID(), SCRIPT_TASK_LOOK_AT_ENTITY)
|
|
TASK_LOOK_AT_ENTITY(PLAYER_PED_ID(), friend.hPed, -1, SLF_DEFAULT, SLF_LOOKAT_HIGH)
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
|
|
//------------------------------------------------------------------------------------------------------------------------------
|
|
// AmbFriend - Dismissed state
|
|
//------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
FUNC BOOL Private_CanAmbFriendConverse(structAmbGroup& group)
|
|
|
|
// Check technical reasons
|
|
IF group.eConvState <> AMBCONV_NULL
|
|
OR IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
|
|
OR IS_MESSAGE_BEING_DISPLAYED()
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
PROC Private_GetAmbFriendOutroAreas(enumCharacterList eChar, VECTOR& vBoxOffsetA, VECTOR& vBoxSizeA, VECTOR& vBoxOffsetB, VECTOR& vBoxSizeB, VECTOR& vBoxOffsetC, VECTOR& vBoxSizeC)
|
|
SWITCH eChar
|
|
CASE CHAR_MICHAEL
|
|
vBoxOffsetA = << 0.0, 0.5, 0.0 >>
|
|
vBoxSizeA = << 1.0, 1.5, 2.0 >>
|
|
|
|
vBoxOffsetB = << 0.0, 1.5, 0.25 >>
|
|
vBoxSizeB = << 1.0, 1.0, 1.5 >>
|
|
|
|
vBoxOffsetC = << 0.0, -1.5, 0.0 >>
|
|
vBoxSizeC = << 1.5, 2.5, 1.25 >>
|
|
BREAK
|
|
CASE CHAR_FRANKLIN
|
|
vBoxOffsetA = << 0.1, 0.5, 0.0 >>
|
|
vBoxSizeA = << 1.75, 1.5, 2.0 >>
|
|
|
|
vBoxOffsetB = << 0.0, 1.5, 0.1 >>
|
|
vBoxSizeB = << 1.0, 1.8, 1.6 >>
|
|
|
|
vBoxOffsetC = << 0.75, -1.75, 0.0 >>
|
|
vBoxSizeC = << 2.5, 3.0, 1.25 >>
|
|
BREAK
|
|
CASE CHAR_TREVOR FALLTHRU
|
|
DEFAULT
|
|
vBoxOffsetA = << -0.25, 0.75, 0.0 >>
|
|
vBoxSizeA = << 1.25, 1.5, 2.0 >>
|
|
|
|
vBoxOffsetB = << -0.25, 1.75, 0.1 >>
|
|
vBoxSizeB = << 1.0, 2.0, 1.6 >>
|
|
|
|
vBoxOffsetC = << -1.0, -1.5, 0.0 >>
|
|
vBoxSizeC = << 3.0, 3.0, 1.25 >>
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
FUNC BOOL Private_CheckAmbFriendOutroArea(structAmbGroup& group, structAmbFriend& friend)
|
|
|
|
// IF NOT IS_ENTITY_IN_AIR(PLAYER_PED_ID())
|
|
// AND NOT IS_PED_RAGDOLL(PLAYER_PED_ID())
|
|
// AND NOT IS_PED_RAGDOLL(friend.hPed)
|
|
|
|
// Calculate proposed scene position
|
|
VECTOR vPlayerPos = GET_ENTITY_COORDS(PLAYER_PED_ID())
|
|
VECTOR vPlayerToFriend = GET_ENTITY_COORDS(friend.hPed) - GET_ENTITY_COORDS(PLAYER_PED_ID())
|
|
FLOAT fSceneRot = GET_HEADING_FROM_VECTOR_2D(vPlayerToFriend.x, vPlayerToFriend.y)
|
|
|
|
VEHICLE_INDEX hPlayerCar = NULL
|
|
|
|
ENTITY_INDEX hHitEntity
|
|
VECTOR vHitPoint, vHitNormal
|
|
INT iHitCount
|
|
|
|
VECTOR vBoxOffset[MAX_GRIEF_OUTRO_AREAS]
|
|
VECTOR vBoxSize[MAX_GRIEF_OUTRO_AREAS]
|
|
|
|
Private_GetAmbFriendOutroAreas(friend.eChar, vBoxOffset[0], vBoxSize[0], vBoxOffset[1], vBoxSize[1], vBoxOffset[2], vBoxSize[2])
|
|
|
|
IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
|
|
hPlayerCar = GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID())
|
|
ENDIF
|
|
|
|
INT iAreaLoop
|
|
REPEAT MAX_GRIEF_OUTRO_AREAS iAreaLoop
|
|
IF (group.hOutroTest[iAreaLoop] = NULL)
|
|
IF vBoxSize[iAreaLoop].x != 0.0 AND vBoxSize[iAreaLoop].y != 0.0 AND vBoxSize[iAreaLoop].z != 0.0
|
|
|
|
VECTOR vCentre = GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(vPlayerPos, fSceneRot, vBoxOffset[iAreaLoop])
|
|
INT iFlags = /*SCRIPT_INCLUDE_MOVER|*/SCRIPT_INCLUDE_VEHICLE|SCRIPT_INCLUDE_OBJECT|SCRIPT_INCLUDE_GLASS|SCRIPT_INCLUDE_FOLIAGE
|
|
|
|
IF iAreaLoop = 0
|
|
vCentre += << 0.0, 0.0, 0.1 >>
|
|
ENDIF
|
|
|
|
group.hOutroTest[iAreaLoop] = START_SHAPE_TEST_BOX(vCentre, vBoxSize[iAreaLoop], <<0, 0, fSceneRot>>, EULER_YXZ, iFlags, hPlayerCar, SCRIPT_SHAPETEST_OPTION_DEFAULT)
|
|
|
|
ENDIF
|
|
ELSE
|
|
SHAPETEST_STATUS eStatus = GET_SHAPE_TEST_RESULT(group.hOutroTest[iAreaLoop], iHitCount, vHitPoint, vHitNormal, hHitEntity)
|
|
|
|
SWITCH (eStatus)
|
|
CASE SHAPETEST_STATUS_RESULTS_READY
|
|
IF iHitCount = 0
|
|
IF iAreaLoop = 0
|
|
group.vOutroTestPos = vPlayerPos
|
|
group.fOutroTestRot = fSceneRot
|
|
ENDIF
|
|
group.iOutroTestTime[iAreaLoop] = GET_GAME_TIMER()
|
|
// ELSE
|
|
// VECTOR vCentre
|
|
// vCentre = GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(vPlayerPos, fSceneRot, vBoxOffset[iAreaLoop])
|
|
// IF iAreaLoop = 0
|
|
// DRAW_DEBUG_BOX(vCentre - (vBoxSize[iAreaLoop]*0.5), vCentre + (vBoxSize[iAreaLoop]*0.5), 255, 0, 0, 64)
|
|
// ELIF iAreaLoop = 1
|
|
// DRAW_DEBUG_BOX(vCentre - (vBoxSize[iAreaLoop]*0.5), vCentre + (vBoxSize[iAreaLoop]*0.5), 0, 255, 0, 64)
|
|
// ELIF iAreaLoop = 2
|
|
// DRAW_DEBUG_BOX(vCentre - (vBoxSize[iAreaLoop]*0.5), vCentre + (vBoxSize[iAreaLoop]*0.5), 0, 0, 255, 64)
|
|
// ENDIF
|
|
ENDIF
|
|
|
|
group.hOutroTest[iAreaLoop] = NULL
|
|
BREAK
|
|
CASE SHAPETEST_STATUS_RESULTS_NOTREADY
|
|
BREAK
|
|
CASE SHAPETEST_STATUS_NONEXISTENT
|
|
group.hOutroTest[iAreaLoop] = NULL
|
|
BREAK
|
|
ENDSWITCH
|
|
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
IF GET_GAME_TIMER() < group.iOutroTestTime[0] + 500
|
|
AND GET_GAME_TIMER() < group.iOutroTestTime[1] + 500
|
|
AND GET_GAME_TIMER() < group.iOutroTestTime[2] + 500
|
|
// DRAW_DEBUG_BOX(group.vOutroTestPos + vBoxOffset[0] - (vBoxSize[0]*0.5), group.vOutroTestPos + vBoxOffset[0] + (vBoxSize[0]*0.5), 255, 255, 255, 64)
|
|
RETURN TRUE
|
|
ENDIF
|
|
// ENDIF
|
|
|
|
RETURN FALSE
|
|
|
|
ENDFUNC
|
|
|
|
FUNC BOOL Private_CanAmbFriendBlank(structAmbFriend& friend, BOOL bDoDialogue = FALSE)
|
|
#if USE_CLF_DLC
|
|
bDoDialogue = bDoDialogue
|
|
unused_parameter(friend)
|
|
#ENDIF
|
|
#if USE_NRM_DLC
|
|
bDoDialogue = bDoDialogue
|
|
unused_parameter(friend)
|
|
#ENDIF
|
|
#if not USE_CLF_DLC
|
|
#if not USE_NRM_DLC
|
|
IF (friend.eChar = CHAR_FRANKLIN AND g_eDefaultPlayerChar = CHAR_TREVOR)
|
|
OR (friend.eChar = CHAR_TREVOR AND g_eDefaultPlayerChar = CHAR_FRANKLIN)
|
|
IF NOT GET_MISSION_COMPLETE_STATE(SP_MISSION_FBI_2)
|
|
IF bDoDialogue
|
|
IF NOT IS_ANY_SPEECH_PLAYING(friend.hPed)
|
|
IF g_eDefaultPlayerChar = CHAR_TREVOR
|
|
PLAY_PED_AMBIENT_SPEECH(friend.hPed, "GENERIC_FUCK_YOU", SPEECH_PARAMS_FORCE) // Treat Trevor as a homeless person
|
|
ELSE
|
|
PLAY_PED_AMBIENT_SPEECH(friend.hPed, "GENERIC_FUCK_YOU", SPEECH_PARAMS_FORCE) // Call Franklin a cunt
|
|
ENDIF
|
|
ENDIF
|
|
IF IS_ANY_SPEECH_PLAYING(friend.hPed)
|
|
RETURN TRUE
|
|
ENDIF
|
|
ELSE
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
#ENDIF
|
|
#ENDIF
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
FUNC BOOL Private_HasPlayerAttackedAmbFriend(structAmbFriend& friend)
|
|
|
|
VEHICLE_INDEX hVehicle
|
|
IF IS_PED_IN_ANY_VEHICLE(friend.hPed)
|
|
hVehicle = GET_VEHICLE_PED_IS_IN(friend.hPed)
|
|
ENDIF
|
|
|
|
VECTOR vFriendPos = GET_ENTITY_COORDS(friend.hPed)
|
|
|
|
// Check if damage has occured
|
|
IF (NOT IS_PED_INJURED(PLAYER_PED_ID()) AND HAS_ENTITY_BEEN_DAMAGED_BY_ENTITY(friend.hPed, PLAYER_PED_ID()))
|
|
OR (NOT IS_PED_INJURED(PLAYER_PED_ID()) AND DOES_ENTITY_EXIST(hVehicle) AND HAS_ENTITY_BEEN_DAMAGED_BY_ENTITY(hVehicle, PLAYER_PED_ID()))
|
|
OR IS_PLAYER_SHOOTING_NEAR_PED(friend.hPed, FALSE, FALSE, FALSE)
|
|
// OR (GET_NUMBER_OF_FIRES_IN_RANGE(vFriendPos, 20.0) > 0)
|
|
OR IS_ENTITY_ON_FIRE(friend.hPed)
|
|
OR (IS_EXPLOSION_IN_SPHERE(EXP_TAG_DONTCARE, vFriendPos, 20.0) AND NOT ( IS_EXPLOSION_IN_SPHERE(EXP_TAG_DIR_STEAM, vFriendPos, 20.0)
|
|
OR IS_EXPLOSION_IN_SPHERE(EXP_TAG_DIR_WATER_HYDRANT, vFriendPos, 20.0)
|
|
OR IS_EXPLOSION_IN_SPHERE(EXP_TAG_DIR_GAS_CANISTER, vFriendPos, 20.0)))
|
|
|
|
// Clear damage
|
|
IF DOES_ENTITY_EXIST(hVehicle)
|
|
CLEAR_ENTITY_LAST_DAMAGE_ENTITY(hVehicle)
|
|
ENDIF
|
|
CLEAR_ENTITY_LAST_DAMAGE_ENTITY(friend.hPed)
|
|
|
|
CPRINTLN(DEBUG_FRIENDS, "Private_HasPlayerAttackedAmbFriend() - RETURNING TRUE ---------------------------------------")
|
|
RETURN TRUE
|
|
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
FUNC BOOL Private_HasAnyoneAttackedAmbFriend(structAmbFriend& friend, BOOL bCheckAngryPeds, PED_INDEX& hAngryPed)
|
|
|
|
// VEHICLE_INDEX hVehicle = NULL
|
|
// IF IS_PED_IN_ANY_VEHICLE(friend.hPed)
|
|
// hVehicle = GET_VEHICLE_PED_IS_IN(friend.hPed)
|
|
// ENDIF
|
|
|
|
// If anyone nearby is in combat with friend, or friend has been damaged by someone
|
|
IF (bCheckAngryPeds AND COUNT_PEDS_IN_COMBAT_WITH_TARGET_WITHIN_RADIUS(friend.hPed, GET_ENTITY_COORDS(friend.hPed), 75.0) > 0)
|
|
|
|
OR HAS_ENTITY_BEEN_DAMAGED_BY_ANY_PED(friend.hPed)
|
|
|
|
// Check 12 nearest peds
|
|
PED_INDEX nearbyPeds[12]
|
|
INT i, iNearbyCount = GET_PED_NEARBY_PEDS(friend.hPed, nearbyPeds)
|
|
REPEAT iNearbyCount i
|
|
|
|
hAngryPed = nearbyPeds[i]
|
|
IF NOT IS_PED_INJURED(hAngryPed)
|
|
|
|
// If ped is in combat with friend (and is near) or has damaged friend
|
|
IF IS_PED_IN_COMBAT(hAngryPed, friend.hPed)
|
|
|
|
IF HAS_ENTITY_BEEN_DAMAGED_BY_ENTITY(friend.hPed, hAngryPed)
|
|
|
|
// OR ( DOES_ENTITY_EXIST(hVehicle) AND HAS_ENTITY_BEEN_DAMAGED_BY_ENTITY(hVehicle, hAngryPed) )
|
|
|
|
OR (bCheckAngryPeds AND Util_IsPedInsideRangePed(hAngryPed, friend.hPed, 75.0))
|
|
|
|
CPRINTLN(DEBUG_FRIENDS, "Private_HasAnyoneAttackedAmbFriend() - RETURNING TRUE ---------------------------------------")
|
|
hAngryPed = nearbyPeds[i]
|
|
|
|
CLEAR_ENTITY_LAST_DAMAGE_ENTITY(friend.hPed)
|
|
// CLEAR_ENTITY_LAST_WEAPON_DAMAGE(friend.hPed)
|
|
RETURN TRUE
|
|
|
|
ENDIF
|
|
|
|
ENDIF
|
|
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
hAngryPed = NULL
|
|
ENDIF
|
|
|
|
// CLEAR_ENTITY_LAST_DAMAGE_ENTITY(friend.hPed)
|
|
// CLEAR_ENTITY_LAST_WEAPON_DAMAGE(friend.hPed)
|
|
RETURN FALSE
|
|
|
|
ENDFUNC
|
|
|
|
FUNC BOOL Private_HasPlayerThreatenedAmbFriend(structAmbGroup& group, structAmbFriend& friend)
|
|
|
|
// Check if player is threatening ped
|
|
// IF IS_ENTITY_AT_ENTITY(friend.hPed, PLAYER_PED_ID(), <<15.0, 15.0, 15.0>>)//<<45.0, 45.0, 45.0>>)
|
|
IF IS_PLAYER_VISIBLY_TARGETTING_PED(friend.hPed, 170.0)
|
|
|
|
// Don't count as threaten if agreed to hangout with friend
|
|
IF friend.eState = AMBFRIEND_GREET
|
|
AND group.eConvChar = friend.eChar
|
|
IF group.eConvState = AMBCONV_OFFER_YES1
|
|
OR group.eConvState = AMBCONV_OFFER_YES2
|
|
OR group.eConvState = AMBCONV_OFFER_LAUNCH1
|
|
OR group.eConvState = AMBCONV_OFFER_LAUNCH2
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// Return true
|
|
CPRINTLN(DEBUG_FRIENDS, "Private_HasPlayerThreatenedAmbFriend() - RETURNING TRUE ---------------------------------------")
|
|
RETURN TRUE
|
|
|
|
ENDIF
|
|
// ENDIF
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
FUNC BOOL Private_HasPlayerStolenCarAmbFriend(structAmbGroup& group, structAmbFriend& friend)
|
|
|
|
// Check if player is threatening ped
|
|
IF IS_VEHICLE_DRIVEABLE(friend.hVehicle) AND IS_PED_IN_VEHICLE(PLAYER_PED_ID(), friend.hVehicle)
|
|
|
|
// Don't count as a jack if agreed to hangout with friend
|
|
IF friend.eState = AMBFRIEND_GREET
|
|
AND group.eConvChar = friend.eChar
|
|
IF group.eConvState = AMBCONV_OFFER_YES1
|
|
OR group.eConvState = AMBCONV_OFFER_YES2
|
|
OR group.eConvState = AMBCONV_OFFER_LAUNCH1
|
|
OR group.eConvState = AMBCONV_OFFER_LAUNCH2
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// Return true
|
|
CPRINTLN(DEBUG_FRIENDS, "Private_HasPlayerStolenCarAmbFriend() - RETURNING TRUE ---------------------------------------")
|
|
RETURN TRUE
|
|
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
FUNC BOOL Private_AmbFriendTasks_IsVehicleUsable(structAmbFriend& friend, VEHICLE_INDEX hVehicle, BOOL bMustBeDriver)
|
|
IF IS_VEHICLE_DRIVEABLE(hVehicle)
|
|
AND GET_ENTITY_HEALTH(hVehicle) > 600
|
|
AND NOT IS_ENTITY_UPSIDEDOWN(hVehicle)
|
|
AND GET_ENTITY_MODEL(hVehicle) <> CADDY
|
|
AND GET_ENTITY_MODEL(hVehicle) <> CADDY2
|
|
AND IS_ENTITY_AT_ENTITY(friend.hPed, hVehicle, <<150.0, 150.0, 150.0>>)
|
|
IF bMustBeDriver = FALSE OR (GET_PED_IN_VEHICLE_SEAT(GET_VEHICLE_PED_IS_IN(friend.hPed), VS_DRIVER) = friend.hPed)
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
FUNC BOOL Private_IsPlayerJackable()
|
|
|
|
// Don't jack the player if player control is off
|
|
IF IS_PLAYER_CONTROL_ON(PLAYER_ID())
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
PROC Private_AmbFriendTasks_LeaveAnyVehicle(structAmbFriend& friend)
|
|
// Stop and get out
|
|
IF ABSF(GET_ENTITY_SPEED(friend.hPed)) > 5.0
|
|
IF GET_PED_IN_VEHICLE_SEAT(GET_VEHICLE_PED_IS_IN(friend.hPed), VS_DRIVER) = friend.hPed
|
|
IF NOT IsPedPerformingTask(friend.hPed, SCRIPT_TASK_VEHICLE_MISSION)
|
|
CLEAR_PED_TASKS(friend.hPed)
|
|
TASK_VEHICLE_MISSION(friend.hPed, GET_VEHICLE_PED_IS_IN(friend.hPed), NULL, MISSION_STOP, 0.0, DRIVINGMODE_STOPFORCARS, 0.0, 0.0)
|
|
ENDIF
|
|
ENDIF
|
|
ELSE
|
|
IF NOT IsPedPerformingTask(friend.hPed, SCRIPT_TASK_LEAVE_ANY_VEHICLE)
|
|
CLEAR_PED_TASKS(friend.hPed)
|
|
TASK_LEAVE_ANY_VEHICLE(friend.hPed)
|
|
ENDIF
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
PROC Private_AmbFriendTasks_DriveWander(structAmbFriend& friend, FLOAT fSpeed, DRIVINGMODE mode=DRIVINGMODE_STOPFORCARS)
|
|
// Drive at given speed
|
|
IF NOT IsPedPerformingTask(friend.hPed, SCRIPT_TASK_VEHICLE_DRIVE_WANDER)
|
|
CLEAR_PED_TASKS(friend.hPed)
|
|
TASK_VEHICLE_DRIVE_WANDER(friend.hPed, GET_VEHICLE_PED_IS_IN(friend.hPed), fSpeed, mode)
|
|
ELSE
|
|
SET_DRIVE_TASK_CRUISE_SPEED(friend.hPed, fSpeed)
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
PROC Private_AmbFriendTasks_JackVehicle(structAmbFriend& friend)
|
|
IF IS_ENTITY_AT_ENTITY(friend.hPed, friend.hVehicle, <<75.0, 75.0, 75.0>>)
|
|
VEHICLE_SEAT eSeat = GET_SEAT_PED_IS_IN(PLAYER_PED_ID())
|
|
IF eSeat = VS_DRIVER
|
|
IF NOT IsPedPerformingTask(friend.hPed, SCRIPT_TASK_ENTER_VEHICLE)
|
|
CLEAR_PED_TASKS(friend.hPed)
|
|
TASK_ENTER_VEHICLE(friend.hPed, friend.hVehicle, DEFAULT_TIME_NEVER_WARP, VS_DRIVER, PEDMOVE_RUN, ECF_RESUME_IF_INTERRUPTED|ECF_JACK_ANYONE|ECF_JUST_PULL_PED_OUT)
|
|
ENDIF
|
|
ELSE
|
|
IF NOT IsPedPerformingTask(friend.hPed, SCRIPT_TASK_TURN_PED_TO_FACE_ENTITY)
|
|
CLEAR_PED_TASKS(friend.hPed)
|
|
TASK_TURN_PED_TO_FACE_ENTITY(friend.hPed, PLAYER_PED_ID(), -1)
|
|
ENDIF
|
|
ENDIF
|
|
ELSE
|
|
friend.hVehicle = NULL
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
PROC Private_AmbFriendTasks_EnterVehicle(structAmbFriend& friend)
|
|
IF NOT IsPedPerformingTask(friend.hPed, SCRIPT_TASK_ENTER_VEHICLE)
|
|
CLEAR_PED_TASKS(friend.hPed)
|
|
TASK_ENTER_VEHICLE(friend.hPed, friend.hVehicle, DEFAULT_TIME_NEVER_WARP, VS_DRIVER, PEDMOVE_WALK, ECF_RESUME_IF_INTERRUPTED|ECF_WARP_IF_DOOR_IS_BLOCKED|ECF_WARP_IF_SHUFFLE_LINK_IS_BLOCKED)
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
PROC Private_AmbFriendTasks_WalkWander(structAmbFriend& friend)
|
|
IF NOT IsPedPerformingTask(friend.hPed, SCRIPT_TASK_WANDER_STANDARD)
|
|
CLEAR_PED_TASKS(friend.hPed)
|
|
TASK_WANDER_STANDARD(friend.hPed)
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
PROC Private_AmbFriendTasks_Flee(structAmbFriend& friend, PED_INDEX hTargetPed)
|
|
IF NOT IsPedPerformingTask(friend.hPed, SCRIPT_TASK_SMART_FLEE_PED)
|
|
CLEAR_PED_TASKS(friend.hPed)
|
|
TASK_SMART_FLEE_PED(friend.hPed, hTargetPed, 1000.0, -1, FALSE)
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
|
|
PROC Private_SetAmbFriendDismissMode(structAmbFriend& friend, enumAmbDismissMode eMode, BOOL bShout = FALSE, PED_INDEX hTargetPed = NULL)
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
TEXT_LABEL_31 tChar = GetLabel_enumCharacterList(friend.eChar)
|
|
TEXT_LABEL_31 tMode = GetLabel_enumAmbDismissMode(eMode)
|
|
|
|
IF bShout
|
|
CPRINTLN(DEBUG_FRIENDS, "Private_SetAmbFriendDismissMode(", tChar, ", ", tMode, ", bShout=TRUE)")
|
|
ELSE
|
|
CPRINTLN(DEBUG_FRIENDS, "Private_SetAmbFriendDismissMode(", tChar, ", ", tMode, ", bShout=FALSE)")
|
|
ENDIF
|
|
#ENDIF
|
|
|
|
friend.bInitDismissMode = TRUE
|
|
friend.eDismissMode = eMode
|
|
friend.hTargetPed = hTargetPed
|
|
|
|
// If already dismissed, reset dismissed time
|
|
IF Private_GET_FRIEND_LAST_CONTACT_TYPE(g_eDefaultPlayerChar, friend.eChar) = FRIEND_CONTACT_DISMISSED
|
|
IF Private_GET_FRIEND_LAST_CONTACT_TIME(g_eDefaultPlayerChar, friend.eChar) < 3.0*60.0
|
|
|
|
RESET_FRIEND_LAST_CONTACT_TIMER(g_eDefaultPlayerChar, friend.eChar, FRIEND_CONTACT_DISMISSED)
|
|
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF bShout
|
|
friend.bDismissAudioRequest = TRUE
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
PROC Private_SetAmbFriendThreatResponse(structAmbFriend& friend, BOOL bShout = FALSE, PED_INDEX hTargetPed = NULL)
|
|
|
|
IF friend.bIsVulnerable AND hTargetPed = PLAYER_PED_ID()
|
|
Private_SetAmbFriendDismissMode(friend, AMBMODE_FIGHT, bShout, hTargetPed)
|
|
ELSE
|
|
Private_SetAmbFriendDismissMode(friend, AMBMODE_FLEE, bShout, hTargetPed)
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
|
|
FUNC BOOL Private_UpdateAmbFriend_Dismissed(structAmbGroup& group, structAmbFriend& friend, structPedsForConversation& convPeds, FLOAT fDist2)
|
|
|
|
PED_INDEX hAngryPed = NULL
|
|
|
|
//-- Tasks
|
|
|
|
//-------------------------------------------------------------------------------------------------------- AMBMODE_REJECTED
|
|
IF friend.eDismissMode = AMBMODE_REJECTED
|
|
|
|
// Attacked...
|
|
IF Private_HasPlayerAttackedAmbFriend(friend)
|
|
CLEAR_PED_TASKS(friend.hPed)
|
|
Private_SetAmbFriendThreatResponse(friend, TRUE, PLAYER_PED_ID())
|
|
|
|
ELIF Private_HasAnyoneAttackedAmbFriend(friend, TRUE, hAngryPed)
|
|
CLEAR_PED_TASKS(friend.hPed)
|
|
Private_SetAmbFriendDismissMode(friend, AMBMODE_FLEE, FALSE, hAngryPed)
|
|
|
|
// Finished rejection tasks...
|
|
ELIF NOT IsPedPerformingTask(friend.hPed, SCRIPT_TASK_PERFORM_SEQUENCE)
|
|
CLEAR_PED_TASKS(friend.hPed)
|
|
Private_SetAmbFriendDismissMode(friend, AMBMODE_WANDER)
|
|
ENDIF
|
|
|
|
//-------------------------------------------------------------------------------------------------------- AMBMODE_WANDER
|
|
ELIF friend.eDismissMode = AMBMODE_WANDER
|
|
|
|
IF friend.bDismissAudioRequest
|
|
IF NOT IS_ANY_SPEECH_PLAYING(friend.hPed) AND NOT IS_PED_RAGDOLL(friend.hPed) AND NOT IS_PED_RUNNING_RAGDOLL_TASK(friend.hPed)
|
|
PLAY_PED_AMBIENT_SPEECH(friend.hPed, "GENERIC_WHATEVER", SPEECH_PARAMS_FORCE)
|
|
IF IS_AMBIENT_SPEECH_PLAYING(friend.hPed)
|
|
CPRINTLN(DEBUG_FRIENDS, "AMBMODE_WANDER - PLAY_PED_AMBIENT_SPEECH(GENERIC_WHATEVER)")
|
|
friend.bDismissAudioRequest = FALSE
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// Attacked...
|
|
IF Private_HasPlayerAttackedAmbFriend(friend)
|
|
CLEAR_PED_TASKS(friend.hPed)
|
|
Private_SetAmbFriendThreatResponse(friend, TRUE, PLAYER_PED_ID())
|
|
|
|
ELIF Private_HasAnyoneAttackedAmbFriend(friend, TRUE, hAngryPed)
|
|
CLEAR_PED_TASKS(friend.hPed)
|
|
Private_SetAmbFriendDismissMode(friend, AMBMODE_FLEE, FALSE, hAngryPed)
|
|
|
|
// In car...
|
|
ELIF IS_PED_IN_ANY_VEHICLE(friend.hPed)
|
|
|
|
// Car health ok, drive around
|
|
IF Private_AmbFriendTasks_IsVehicleUsable(friend, GET_VEHICLE_PED_IS_IN(friend.hPed), TRUE)
|
|
|
|
friend.hVehicle = GET_VEHICLE_PED_IS_IN(friend.hPed)
|
|
|
|
IF IS_POINT_ON_ROAD(GET_ENTITY_COORDS(friend.hPed), friend.hVehicle)
|
|
Private_AmbFriendTasks_DriveWander(friend, 17.0)
|
|
ELSE
|
|
Private_AmbFriendTasks_DriveWander(friend, 10.0)
|
|
ENDIF
|
|
|
|
// Car unusable, get out
|
|
ELSE
|
|
friend.hVehicle = NULL
|
|
Private_AmbFriendTasks_LeaveAnyVehicle(friend)
|
|
ENDIF
|
|
|
|
// On foot...
|
|
ELSE
|
|
|
|
// Car usable, get in
|
|
IF Private_AmbFriendTasks_IsVehicleUsable(friend, friend.hVehicle, FALSE)
|
|
|
|
// Go to vehicle and get in / jack player
|
|
IF NOT IS_PED_INJURED(PLAYER_PED_ID()) AND IS_PED_IN_VEHICLE(PLAYER_PED_ID(), friend.hVehicle)
|
|
|
|
IF GET_PLAYER_PED_PERSONAL_VEHICLE_BELONGS_TO(friend.hVehicle) = friend.eChar AND Private_IsPlayerJackable()
|
|
CLEAR_PED_TASKS(friend.hPed)
|
|
Private_SetAmbFriendDismissMode(friend, AMBMODE_JACKED, TRUE)
|
|
ELSE
|
|
friend.hVehicle = NULL
|
|
Private_AmbFriendTasks_WalkWander(friend)
|
|
ENDIF
|
|
|
|
ELSE
|
|
Private_AmbFriendTasks_EnterVehicle(friend)
|
|
ENDIF
|
|
|
|
// Car unusable, walk around
|
|
ELSE
|
|
friend.hVehicle = NULL
|
|
Private_AmbFriendTasks_WalkWander(friend)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
//-------------------------------------------------------------------------------------------------------- AMBMODE_JACKED
|
|
ELIF friend.eDismissMode = AMBMODE_JACKED
|
|
|
|
IF friend.bDismissAudioRequest
|
|
IF NOT IS_ANY_SPEECH_PLAYING(friend.hPed) AND NOT IS_PED_RAGDOLL(friend.hPed) AND NOT IS_PED_RUNNING_RAGDOLL_TASK(friend.hPed)
|
|
PLAY_PED_AMBIENT_SPEECH(friend.hPed, "JACKED_GENERIC", SPEECH_PARAMS_FORCE)
|
|
IF IS_AMBIENT_SPEECH_PLAYING(friend.hPed)
|
|
CPRINTLN(DEBUG_FRIENDS, "AMBMODE_JACKED - PLAY_PED_AMBIENT_SPEECH(JACKED_GENERIC)")
|
|
friend.bDismissAudioRequest = FALSE
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF friend.iProgress < 1
|
|
friend.iProgress = 1
|
|
ENDIF
|
|
|
|
// Player control is off, so don't jack them...
|
|
IF NOT Private_IsPlayerJackable()
|
|
CPRINTLN(DEBUG_FRIENDS, "Aboted AMBMODE_JACKED ambfriend state, as cutscene started")
|
|
CLEAR_PED_TASKS(friend.hPed)
|
|
friend.hVehicle = NULL
|
|
Private_SetAmbFriendDismissMode(friend, AMBMODE_WANDER)
|
|
|
|
// Attacked...
|
|
ELIF Private_HasPlayerAttackedAmbFriend(friend)
|
|
CLEAR_PED_TASKS(friend.hPed)
|
|
Private_SetAmbFriendThreatResponse(friend, TRUE, PLAYER_PED_ID())
|
|
|
|
ELIF Private_HasAnyoneAttackedAmbFriend(friend, TRUE, hAngryPed)
|
|
CLEAR_PED_TASKS(friend.hPed)
|
|
Private_SetAmbFriendDismissMode(friend, AMBMODE_FLEE, FALSE, hAngryPed)
|
|
|
|
ELIF NOT Private_AmbFriendTasks_IsVehicleUsable(friend, friend.hVehicle, FALSE)
|
|
CLEAR_PED_TASKS(friend.hPed)
|
|
friend.hVehicle = NULL
|
|
Private_SetAmbFriendDismissMode(friend, AMBMODE_WANDER)
|
|
|
|
ELIF IS_PED_IN_ANY_VEHICLE(friend.hPed)
|
|
CLEAR_PED_TASKS(friend.hPed)
|
|
Private_SetAmbFriendDismissMode(friend, AMBMODE_WANDER)
|
|
|
|
ELIF IS_PED_INJURED(PLAYER_PED_ID()) OR NOT IS_PED_IN_VEHICLE(PLAYER_PED_ID(), friend.hVehicle)
|
|
CLEAR_PED_TASKS(friend.hPed)
|
|
Private_SetAmbFriendDismissMode(friend, AMBMODE_WANDER)
|
|
|
|
ELSE
|
|
Private_AmbFriendTasks_JackVehicle(friend)
|
|
ENDIF
|
|
|
|
|
|
//-------------------------------------------------------------------------------------------------------- AMBMODE_FLEE
|
|
ELIF friend.eDismissMode = AMBMODE_FLEE
|
|
|
|
IF friend.bDismissAudioRequest
|
|
IF NOT IS_ANY_SPEECH_PLAYING(friend.hPed) AND NOT IS_PED_RAGDOLL(friend.hPed) AND NOT IS_PED_RUNNING_RAGDOLL_TASK(friend.hPed)
|
|
PLAY_PED_AMBIENT_SPEECH(friend.hPed, "EXTREME_GRIEFING" /*"GENERIC_INSULT_HIGH"*/, SPEECH_PARAMS_SHOUTED_CRITICAL)//SPEECH_PARAMS_FORCE_FRONTEND)//SPEECH_PARAMS_FORCE)
|
|
IF IS_AMBIENT_SPEECH_PLAYING(friend.hPed)
|
|
CPRINTLN(DEBUG_FRIENDS, "AMBMODE_FLEE - PLAY_PED_AMBIENT_SPEECH(EXTREME_GRIEFING)")
|
|
friend.bDismissAudioRequest = FALSE
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF friend.bInitDismissMode
|
|
CLEAR_PED_TASKS(friend.hPed)
|
|
friend.bInitDismissMode = FALSE
|
|
ENDIF
|
|
|
|
IF friend.hTargetPed = PLAYER_PED_ID()
|
|
IF friend.iProgress < 2
|
|
friend.iProgress = 2
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// #IF IS_DEBUG_BUILD
|
|
// SET_DEBUG_LINES_AND_SPHERES_DRAWING_ACTIVE(TRUE)
|
|
// IF NOT IS_PED_INJURED(friend.hTargetPed)
|
|
// DRAW_DEBUG_LINE(GET_ENTITY_COORDS(friend.hPed), GET_ENTITY_COORDS(friend.hTargetPed), 0, 255, 175, 255)
|
|
// ELSE
|
|
// DRAW_DEBUG_SPHERE(GET_ENTITY_COORDS(friend.hPed), 1.0, 255, 0, 0, 255)
|
|
// ENDIF
|
|
// #ENDIF
|
|
|
|
// Target invalid...
|
|
IF IS_PED_INJURED(friend.hTargetPed)
|
|
Private_SetAmbFriendDismissMode(friend, AMBMODE_WANDER)
|
|
|
|
// In car...
|
|
ELIF IS_PED_IN_ANY_VEHICLE(friend.hPed)
|
|
|
|
IF Private_AmbFriendTasks_IsVehicleUsable(friend, GET_VEHICLE_PED_IS_IN(friend.hPed), TRUE)
|
|
|
|
friend.hVehicle = GET_VEHICLE_PED_IS_IN(friend.hPed)
|
|
|
|
IF Util_IsPedInsideRangePed(friend.hPed, friend.hTargetPed, 150.0)
|
|
INT iFleeMode = ENUM_TO_INT(DF_SwerveAroundAllCars)|ENUM_TO_INT(DF_SteerAroundStationaryCars)|ENUM_TO_INT(DF_SteerAroundPeds)|ENUM_TO_INT(DF_SteerAroundObjects)|ENUM_TO_INT(DF_GoOffRoadWhenAvoiding)|ENUM_TO_INT(DF_DriveIntoOncomingTraffic)|ENUM_TO_INT(DF_ChangeLanesAroundObstructions)
|
|
Private_AmbFriendTasks_DriveWander(friend, 55.0, INT_TO_ENUM(DRIVINGMODE, iFleeMode))//40
|
|
ELSE
|
|
CLEAR_PED_TASKS(friend.hPed)
|
|
Private_SetAmbFriendDismissMode(friend, AMBMODE_WANDER)
|
|
ENDIF
|
|
|
|
ELSE
|
|
friend.hVehicle = NULL
|
|
Private_AmbFriendTasks_LeaveAnyVehicle(friend)
|
|
ENDIF
|
|
|
|
// On foot...
|
|
ELSE
|
|
|
|
IF Util_IsPedInsideRangePed(friend.hPed, friend.hTargetPed, 150.0) OR IS_ENTITY_ON_SCREEN(friend.hPed)
|
|
Private_AmbFriendTasks_Flee(friend, friend.hTargetPed)
|
|
ELSE
|
|
CLEAR_PED_TASKS(friend.hPed)
|
|
Private_SetAmbFriendDismissMode(friend, AMBMODE_WANDER)
|
|
ENDIF
|
|
|
|
ENDIF
|
|
|
|
//-------------------------------------------------------------------------------------------------------- AMBMODE_FLEE
|
|
ELIF friend.eDismissMode = AMBMODE_FIGHT
|
|
|
|
IF friend.bDismissAudioRequest
|
|
IF NOT IS_ANY_SPEECH_PLAYING(friend.hPed) AND NOT IS_PED_RAGDOLL(friend.hPed) AND NOT IS_PED_RUNNING_RAGDOLL_TASK(friend.hPed)
|
|
PLAY_PED_AMBIENT_SPEECH(friend.hPed, "EXTREME_GRIEFING" /*"GENERIC_INSULT_HIGH"*/, SPEECH_PARAMS_SHOUTED_CRITICAL)//SPEECH_PARAMS_FORCE_FRONTEND)//SPEECH_PARAMS_FORCE)
|
|
IF IS_AMBIENT_SPEECH_PLAYING(friend.hPed)
|
|
CPRINTLN(DEBUG_FRIENDS, "AMBMODE_FIGHT - PLAY_PED_AMBIENT_SPEECH(EXTREME_GRIEFING)")
|
|
friend.bDismissAudioRequest = FALSE
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF friend.bInitDismissMode
|
|
CLEAR_PED_TASKS(friend.hPed)
|
|
// SET_CURRENT_PED_WEAPON(friend.hPed, WEAPONTYPE_UNARMED, TRUE)
|
|
friend.bInitDismissMode = FALSE
|
|
ENDIF
|
|
|
|
IF friend.hTargetPed = PLAYER_PED_ID()
|
|
IF friend.iProgress < 2
|
|
friend.iProgress = 2
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// #IF IS_DEBUG_BUILD
|
|
// SET_DEBUG_LINES_AND_SPHERES_DRAWING_ACTIVE(TRUE)
|
|
// IF NOT IS_PED_INJURED(friend.hTargetPed)
|
|
// DRAW_DEBUG_LINE(GET_ENTITY_COORDS(friend.hPed), GET_ENTITY_COORDS(friend.hTargetPed), 255, 0, 70, 255)
|
|
// ELSE
|
|
// DRAW_DEBUG_SPHERE(GET_ENTITY_COORDS(friend.hPed), 1.0, 255, 0, 0, 255)
|
|
// ENDIF
|
|
// #ENDIF
|
|
|
|
// Target invalid...
|
|
IF IS_PED_INJURED(friend.hTargetPed)
|
|
Private_SetAmbFriendDismissMode(friend, AMBMODE_WANDER)
|
|
|
|
// In car...
|
|
ELIF IS_PED_IN_ANY_VEHICLE(friend.hPed)
|
|
Private_AmbFriendTasks_LeaveAnyVehicle(friend)
|
|
|
|
// On foot...
|
|
ELSE
|
|
IF NOT IS_PED_RAGDOLL(friend.hPed) AND NOT IS_PED_RUNNING_RAGDOLL_TASK(friend.hPed)
|
|
IF NOT IsPedPerformingTask(friend.hPed, SCRIPT_TASK_COMBAT)
|
|
CPRINTLN(DEBUG_FRIENDS, "--- AMBMODE_FIGHT - TASK_COMBAT_PED()")
|
|
CLEAR_PED_TASKS(friend.hPed)
|
|
TASK_COMBAT_PED(friend.hPed, friend.hTargetPed, COMBAT_PED_PREVENT_CHANGING_TARGET)
|
|
// ELSE
|
|
//
|
|
// IF GET_PEDS_CURRENT_WEAPON(friend.hPed) <> WEAPONTYPE_UNARMED
|
|
//
|
|
// IF GET_PEDS_CURRENT_WEAPON(friend.hTargetPed) = WEAPONTYPE_UNARMED
|
|
// GIVE_WEAPON_TO_PED(friend.hPed, WEAPONTYPE_UNARMED, 1, TRUE, TRUE)
|
|
// ENDIF
|
|
//
|
|
// ENDIF
|
|
|
|
ENDIF
|
|
ENDIF
|
|
|
|
|
|
// IF NOT IsPedPerformingTask(friend.hPed, SCRIPT_TASK_COMBAT)
|
|
// IF NOT IS_PED_RAGDOLL(friend.hPed) AND NOT IS_PED_RUNNING_RAGDOLL_TASK(friend.hPed)
|
|
// CLEAR_PED_TASKS(friend.hPed)
|
|
// //IF GET_PEDS_CURRENT_WEAPON(friend.hTargetPed) = WEAPONTYPE_UNARMED
|
|
// GIVE_WEAPON_TO_PED(friend.hPed, WEAPONTYPE_UNARMED, 1, TRUE, TRUE)
|
|
// //ENDIF
|
|
// TASK_COMBAT_PED(friend.hPed, friend.hTargetPed, COMBAT_PED_PREVENT_CHANGING_TARGET)
|
|
// ENDIF
|
|
//// ELSE
|
|
//// IF GET_PEDS_CURRENT_WEAPON(friend.hTargetPed) <> WEAPONTYPE_UNARMED
|
|
//// IF GET_PEDS_CURRENT_WEAPON(friend.hPed) = WEAPONTYPE_UNARMED
|
|
//// WEAPON_TYPE eBestWeapon = GET_BEST_PED_WEAPON(friend.hPed)
|
|
//// IF eBestWeapon <> WEAPONTYPE_UNARMED
|
|
//// SET_CURRENT_PED_WEAPON(friend.hPed, eBestWeapon, TRUE)
|
|
//// ENDIF
|
|
//// ENDIF
|
|
//// ENDIF
|
|
// ENDIF
|
|
ENDIF
|
|
|
|
ENDIF
|
|
|
|
//-- Run dialogue sequence...
|
|
TEXT_LABEL tRoot, tBlock
|
|
|
|
// IF NOT IS_VEHICLE_DRIVEABLE(friend.hVehicle) OR NOT IS_PED_IN_VEHICLE(PLAYER_PED_ID(), friend.hVehicle)
|
|
IF friend.eDismissMode <> AMBMODE_JACKED
|
|
AND friend.eDismissMode <> AMBMODE_FIGHT
|
|
AND (friend.eDismissMode <> AMBMODE_FLEE OR friend.hTargetPed = PLAYER_PED_ID())
|
|
|
|
IF GET_INTERIOR_FROM_ENTITY(PLAYER_PED_ID()) = NULL
|
|
AND GET_INTERIOR_FROM_ENTITY(friend.hPed) = NULL
|
|
|
|
IF NOT IS_PED_IN_ANY_VEHICLE(friend.hPed)
|
|
OR IS_PED_ON_ANY_BIKE(friend.hPed)
|
|
OR (IS_VEHICLE_A_CONVERTIBLE(GET_VEHICLE_PED_IS_IN(friend.hPed), TRUE) AND
|
|
(GET_CONVERTIBLE_ROOF_STATE(GET_VEHICLE_PED_IS_IN(friend.hPed)) = CRS_LOWERED OR GET_CONVERTIBLE_ROOF_STATE(GET_VEHICLE_PED_IS_IN(friend.hPed)) = CRS_ROOF_STUCK_LOWERED))
|
|
|
|
IF friend.iProgress = 0
|
|
// SET_DEBUG_LINES_AND_SPHERES_DRAWING_ACTIVE(TRUE)
|
|
friend.iProgress++
|
|
|
|
ELIF friend.iProgress = 1
|
|
IF Private_CanAmbFriendConverse(group)
|
|
IF Private_GET_FRIEND_LAST_CONTACT_TIME(g_eDefaultPlayerChar, friend.eChar) > 15.0
|
|
IF fDist2 < 8.0*8.0
|
|
IF Private_CanAmbFriendBlank(friend)
|
|
Private_GetFriendActivityPhrase(g_eDefaultPlayerChar, friend.eChar, FAP_AMBIENT_STALK_FT, tBlock, tRoot)
|
|
ELSE
|
|
Private_GetFriendActivityPhrase(g_eDefaultPlayerChar, friend.eChar, FAP_AMBIENT_STALK_1, tBlock, tRoot)
|
|
ENDIF
|
|
ADD_FRIEND_CHAR_FOR_DIALOGUE(convPeds, friend.eChar, friend.hPed, FALSE)
|
|
IF CREATE_CONVERSATION(convPeds, tBlock, tRoot, CONV_PRIORITY_AMBIENT_HIGH)
|
|
IF NOT IsPedPerformingTask(friend.hPed, SCRIPT_TASK_LOOK_AT_ENTITY)
|
|
TASK_LOOK_AT_ENTITY(friend.hPed, PLAYER_PED_ID(), 4000, SLF_WHILE_NOT_IN_FOV|SLF_USE_TORSO|SLF_WIDEST_PITCH_LIMIT, SLF_LOOKAT_VERY_HIGH)
|
|
ENDIF
|
|
RESET_FRIEND_LAST_CONTACT_TIMER(g_eDefaultPlayerChar, friend.eChar, FRIEND_CONTACT_DISMISSED)
|
|
friend.iProgress++
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ELIF friend.iProgress = 2
|
|
IF Private_CanAmbFriendConverse(group)
|
|
IF Private_GET_FRIEND_LAST_CONTACT_TIME(g_eDefaultPlayerChar, friend.eChar) > 10.0
|
|
IF fDist2 < 8.0*8.0
|
|
IF Private_CanAmbFriendBlank(friend)
|
|
Private_GetFriendActivityPhrase(g_eDefaultPlayerChar, friend.eChar, FAP_AMBIENT_STALK_FT, tBlock, tRoot)
|
|
ELSE
|
|
Private_GetFriendActivityPhrase(g_eDefaultPlayerChar, friend.eChar, FAP_AMBIENT_STALK_2, tBlock, tRoot)
|
|
ENDIF
|
|
ADD_FRIEND_CHAR_FOR_DIALOGUE(convPeds, friend.eChar, friend.hPed, FALSE)
|
|
IF CREATE_CONVERSATION(convPeds, tBlock, tRoot, CONV_PRIORITY_AMBIENT_HIGH)
|
|
IF NOT IsPedPerformingTask(friend.hPed, SCRIPT_TASK_LOOK_AT_ENTITY)
|
|
TASK_LOOK_AT_ENTITY(friend.hPed, PLAYER_PED_ID(), 4000, SLF_WHILE_NOT_IN_FOV|SLF_USE_TORSO|SLF_WIDEST_PITCH_LIMIT, SLF_LOOKAT_VERY_HIGH)
|
|
ENDIF
|
|
RESET_FRIEND_LAST_CONTACT_TIMER(g_eDefaultPlayerChar, friend.eChar, FRIEND_CONTACT_DISMISSED)
|
|
friend.iProgress++
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ELIF friend.iProgress = 3
|
|
IF Private_CanAmbFriendConverse(group)
|
|
IF Private_GET_FRIEND_LAST_CONTACT_TIME(g_eDefaultPlayerChar, friend.eChar) > 10.0
|
|
IF fDist2 < 8.0*8.0
|
|
IF Private_CanAmbFriendBlank(friend)
|
|
Private_GetFriendActivityPhrase(g_eDefaultPlayerChar, friend.eChar, FAP_AMBIENT_STALK_FT, tBlock, tRoot)
|
|
ELSE
|
|
Private_GetFriendActivityPhrase(g_eDefaultPlayerChar, friend.eChar, FAP_AMBIENT_STALK_3, tBlock, tRoot)
|
|
ENDIF
|
|
ADD_FRIEND_CHAR_FOR_DIALOGUE(convPeds, friend.eChar, friend.hPed, FALSE)
|
|
IF CREATE_CONVERSATION(convPeds, tBlock, tRoot, CONV_PRIORITY_AMBIENT_HIGH)
|
|
IF NOT IsPedPerformingTask(friend.hPed, SCRIPT_TASK_LOOK_AT_ENTITY)
|
|
TASK_LOOK_AT_ENTITY(friend.hPed, PLAYER_PED_ID(), 4000, SLF_WHILE_NOT_IN_FOV|SLF_USE_TORSO|SLF_WIDEST_PITCH_LIMIT, SLF_LOOKAT_VERY_HIGH)
|
|
ENDIF
|
|
RESET_FRIEND_LAST_CONTACT_TIMER(g_eDefaultPlayerChar, friend.eChar, FRIEND_CONTACT_DISMISSED)
|
|
friend.iProgress++
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ELIF friend.iProgress = 4
|
|
IF fDist2 < 8.0*8.0
|
|
|
|
IF Private_GET_FRIEND_LAST_CONTACT_TIME(g_eDefaultPlayerChar, friend.eChar) > 10.0
|
|
CPRINTLN(DEBUG_FRIENDS, "Private_UpdateAmbFriend_Dismissed() wants to do knockout...")
|
|
IF GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(HASH("appInternet")) = 0
|
|
IF g_bAllowAmbientFriendStalking
|
|
AND group.eConvState = AMBCONV_NULL
|
|
// AND NOT IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
|
|
AND (NOT IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID()) OR (IS_PED_ON_ANY_BIKE(PLAYER_PED_ID())) AND ABSF(GET_ENTITY_SPEED(PLAYER_PED_ID())) < 10.0)
|
|
AND NOT IS_PED_IN_ANY_VEHICLE(friend.hPed)
|
|
AND NOT IS_ENTITY_IN_AIR(PLAYER_PED_ID())
|
|
AND NOT IS_ENTITY_IN_AIR(friend.hPed)
|
|
AND NOT IS_PED_RAGDOLL(PLAYER_PED_ID())
|
|
AND NOT IS_PED_RAGDOLL(friend.hPed)
|
|
// AND GET_INTERIOR_FROM_ENTITY(PLAYER_PED_ID()) = NULL
|
|
// AND GET_INTERIOR_FROM_ENTITY(friend.hPed) = NULL
|
|
AND NOT IS_PLAYER_PED_SWITCH_IN_PROGRESS()
|
|
AND NOT IS_PLAYER_SWITCH_IN_PROGRESS()
|
|
AND Private_CheckAmbFriendOutroArea(group, friend)
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF Private_GET_FRIEND_LAST_CONTACT_TIME(g_eDefaultPlayerChar, friend.eChar) > 15.0
|
|
IF Private_CanAmbFriendConverse(group)
|
|
IF Private_CanAmbFriendBlank(friend)
|
|
Private_GetFriendActivityPhrase(g_eDefaultPlayerChar, friend.eChar, FAP_AMBIENT_STALK_FT, tBlock, tRoot)
|
|
ELSE
|
|
Private_GetFriendActivityPhrase(g_eDefaultPlayerChar, friend.eChar, FAP_AMBIENT_STALK_3, tBlock, tRoot)
|
|
ENDIF
|
|
ADD_FRIEND_CHAR_FOR_DIALOGUE(convPeds, friend.eChar, friend.hPed, FALSE)
|
|
IF CREATE_CONVERSATION(convPeds, tBlock, tRoot, CONV_PRIORITY_AMBIENT_HIGH)
|
|
IF NOT IsPedPerformingTask(friend.hPed, SCRIPT_TASK_LOOK_AT_ENTITY)
|
|
TASK_LOOK_AT_ENTITY(friend.hPed, PLAYER_PED_ID(), 4000, SLF_WHILE_NOT_IN_FOV|SLF_USE_TORSO|SLF_WIDEST_PITCH_LIMIT, SLF_LOOKAT_VERY_HIGH)
|
|
ENDIF
|
|
RESET_FRIEND_LAST_CONTACT_TIMER(g_eDefaultPlayerChar, friend.eChar, FRIEND_CONTACT_DISMISSED)
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
|
|
//------------------------------------------------------------------------------------------------------------------------------
|
|
// AmbFriend - Outro state
|
|
//------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
FUNC BOOL Private_TryStartAmbFriendOutro(structAmbGroup& group, structAmbFriend& friend)
|
|
|
|
CPRINTLN(DEBUG_FRIENDS, "Private_TryStartAmbFriendOutro()...")
|
|
|
|
m_enumMissionCandidateReturnValue allowLaunch = Request_Mission_Launch(group.hOutroCandidate, MCTID_MEET_CHARACTER, MISSION_TYPE_GRIEFING)
|
|
|
|
IF allowLaunch = MCRET_ACCEPTED
|
|
CPRINTLN(DEBUG_FRIENDS, "Private_TryStartAmbFriendOutro() - Started MISSION_TYPE_GRIEFING (candidate ", group.hOutroCandidate, ")")
|
|
|
|
// IF NOT GET_MISSION_FLAG()
|
|
// SET_MISSION_FLAG(TRUE)
|
|
// ENDIF
|
|
|
|
// Init vars
|
|
group.bOutroActive = TRUE
|
|
group.hOutroScenarioBlock = NULL
|
|
group.eOutroChar = friend.eChar
|
|
group.iOutroSpeechVariation = -1
|
|
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
PROC Private_GetAmbFriendOutroAnims(enumCharacterList eChar, FLOAT& fHitTime, TEXT_LABEL_63& tAnimDict, TEXT_LABEL_31& tPlayerAnim, TEXT_LABEL_31& tFriendAnim, TEXT_LABEL_31& tCameraAnim)
|
|
SWITCH eChar
|
|
CASE CHAR_MICHAEL
|
|
tAnimDict = "friends@frm@ig_2"
|
|
tPlayerAnim = "knockout_player"
|
|
tFriendAnim = "knockout_mic"
|
|
tCameraAnim = "knockout_cam"
|
|
fHitTime = 0.231//0.287
|
|
BREAK
|
|
CASE CHAR_FRANKLIN
|
|
tAnimDict = "friends@frf@ig_2"
|
|
tPlayerAnim = "knockout_plyr"
|
|
tFriendAnim = "knockout_fra"
|
|
tCameraAnim = "knockout_cam"
|
|
fHitTime = 0.224//0.255
|
|
BREAK
|
|
CASE CHAR_TREVOR FALLTHRU
|
|
DEFAULT
|
|
tAnimDict = "friends@frt@ig_2"
|
|
tPlayerAnim = "knockout_player"
|
|
tFriendAnim = "knockout_trevor"
|
|
tCameraAnim = "knockout_cam"
|
|
fHitTime = 0.388//0.386//0.4//0.415
|
|
BREAK
|
|
ENDSWITCH
|
|
ENDPROC
|
|
|
|
PROC Private_GetAmbFriendOutroFaceAnimsForPlayer(enumCharacterList ePlayerChar, enumCharacterList eFriendChar, TEXT_LABEL_63& tPlayerFaceDict, TEXT_LABEL_31& tPlayerFaceAnim)
|
|
IF ePlayerChar = CHAR_MICHAEL
|
|
|
|
IF eFriendChar = CHAR_FRANKLIN
|
|
tPlayerFaceDict = "FRIENDS@FRF@IG_2"
|
|
tPlayerFaceAnim = "KNOCKOUT_FRF_MIC_facial"
|
|
ELIF eFriendChar = CHAR_TREVOR
|
|
tPlayerFaceDict = "FRIENDS@FRT@IG_2"
|
|
tPlayerFaceAnim = "KNOCKOUT_FRT_MIC_facial"
|
|
ELSE
|
|
SCRIPT_ASSERT("Private_GetAmbFriendOutroFaceAnimsForPlayer() - Bad eFriendChar")
|
|
ENDIF
|
|
|
|
ELIF ePlayerChar = CHAR_FRANKLIN
|
|
|
|
IF eFriendChar = CHAR_MICHAEL
|
|
tPlayerFaceDict = "FRIENDS@FRM@IG_2"
|
|
tPlayerFaceAnim = "KNOCKOUT_FRM_FRA_facial"
|
|
ELIF eFriendChar = CHAR_TREVOR
|
|
tPlayerFaceDict = "FRIENDS@FRT@IG_2"
|
|
tPlayerFaceAnim = "KNOCKOUT_FRT_FRA_facial"
|
|
ELSE
|
|
SCRIPT_ASSERT("Private_GetAmbFriendOutroFaceAnimsForPlayer() - Bad eFriendChar")
|
|
ENDIF
|
|
|
|
ELIF ePlayerChar = CHAR_TREVOR
|
|
|
|
IF eFriendChar = CHAR_MICHAEL
|
|
tPlayerFaceDict = "FRIENDS@FRM@IG_2"
|
|
tPlayerFaceAnim = "KNOCKOUT_FRM_TRV_facial"
|
|
ELIF eFriendChar = CHAR_FRANKLIN
|
|
tPlayerFaceDict = "FRIENDS@FRF@IG_2"
|
|
tPlayerFaceAnim = "KNOCKOUT_FRF_TRV_facial"
|
|
ELSE
|
|
SCRIPT_ASSERT("Private_GetAmbFriendOutroFaceAnimsForPlayer() - Bad eFriendChar")
|
|
ENDIF
|
|
|
|
ELSE
|
|
SCRIPT_ASSERT("Private_GetAmbFriendOutroFaceAnimsForPlayer() - Bad ePlayerChar")
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
PROC Private_GetAmbFriendOutroFaceAnimsForFriend(enumCharacterList eFriendChar, /*PED_INDEX hFriendPed,*/ INT& iVariation, TEXT_LABEL_63& tFriendFaceDict, TEXT_LABEL_31& tFriendFaceAnim, TEXT_LABEL_63& tFriendAudioStream, TEXT_LABEL_31& tSubtitleLabel, FLOAT& fSubtitleStart, INT& iSubtitleDuration)
|
|
BOOL bFirstTime = FALSE
|
|
IF iVariation <= 0
|
|
bFirstTime = TRUE
|
|
ENDIF
|
|
|
|
IF eFriendChar = CHAR_MICHAEL
|
|
IF iVariation <= 0
|
|
iVariation = GET_RANDOM_INT_IN_RANGE(1, 4)
|
|
ENDIF
|
|
|
|
tFriendFaceDict = "FRIENDS@FRM@IG_2"
|
|
tFriendFaceAnim = "MICHAEL_KNOCKS_OUT_ANYONE_0"
|
|
tFriendFaceAnim += iVariation
|
|
tFriendAudioStream = "MICHAEL_KNOCKOUT_FAFM_ANAA_0"
|
|
tFriendAudioStream += iVariation
|
|
|
|
tSubtitleLabel = "FrOUT_M_0"
|
|
tSubtitleLabel += iVariation
|
|
|
|
IF iVariation = 1
|
|
fSubtitleStart = 0.04
|
|
iSubtitleDuration = 1500
|
|
ELIF iVariation = 2
|
|
fSubtitleStart = 0.00
|
|
iSubtitleDuration = 1650
|
|
ELIF iVariation = 3
|
|
fSubtitleStart = 0.0
|
|
iSubtitleDuration = 1650
|
|
ELSE
|
|
fSubtitleStart = 0.0
|
|
iSubtitleDuration = 2000
|
|
ENDIF
|
|
|
|
ELIF eFriendChar = CHAR_FRANKLIN
|
|
IF iVariation <= 0
|
|
iVariation = GET_RANDOM_INT_IN_RANGE(1, 8)//5)
|
|
ENDIF
|
|
|
|
tFriendFaceDict = "FRIENDS@FRF@IG_2"
|
|
tFriendFaceAnim = "FRANKLIN_KNOCKS_OUT_ANYONE_0"
|
|
tFriendFaceAnim += iVariation
|
|
tFriendAudioStream = "FRANKLIN_KNOCKOUT_FAMF_APAA_0"
|
|
tFriendAudioStream += iVariation
|
|
|
|
tSubtitleLabel = "FrOUT_F_0"
|
|
tSubtitleLabel += iVariation
|
|
|
|
IF iVariation = 1
|
|
fSubtitleStart = 0.0
|
|
iSubtitleDuration = 2000
|
|
ELIF iVariation = 2
|
|
fSubtitleStart = 0.065
|
|
iSubtitleDuration = 2500
|
|
ELIF iVariation = 3
|
|
fSubtitleStart = 0.05
|
|
iSubtitleDuration = 1750
|
|
ELIF iVariation = 4
|
|
fSubtitleStart = 0.05
|
|
iSubtitleDuration = 2180
|
|
ELIF iVariation = 5
|
|
fSubtitleStart = 0.075
|
|
iSubtitleDuration = 1200
|
|
ELIF iVariation = 6
|
|
fSubtitleStart = 0.075
|
|
iSubtitleDuration = 1200
|
|
ELIF iVariation = 7
|
|
fSubtitleStart = 0.058
|
|
iSubtitleDuration = 1200
|
|
ELSE
|
|
fSubtitleStart = 0.0
|
|
iSubtitleDuration = 2000
|
|
ENDIF
|
|
|
|
ELIF eFriendChar = CHAR_TREVOR
|
|
IF iVariation <= 0
|
|
iVariation = GET_RANDOM_INT_IN_RANGE(1, 5)
|
|
ENDIF
|
|
|
|
tFriendFaceDict = "FRIENDS@FRT@IG_2"
|
|
tFriendFaceAnim = "TREVOR_KNOCKS_OUT_ANYONE_0"
|
|
tFriendFaceAnim += iVariation
|
|
tFriendAudioStream = "TREVOR_KNOCKOUT_FAMT_ANAA_0"
|
|
tFriendAudioStream += iVariation
|
|
|
|
tSubtitleLabel = "FrOUT_T_0"
|
|
tSubtitleLabel += iVariation
|
|
|
|
IF iVariation = 1
|
|
fSubtitleStart = 0.02
|
|
iSubtitleDuration = 2400
|
|
ELIF iVariation = 2
|
|
fSubtitleStart = 0.02
|
|
iSubtitleDuration = 2600
|
|
ELIF iVariation = 3
|
|
fSubtitleStart = 0.0
|
|
iSubtitleDuration = 2800
|
|
ELIF iVariation = 4
|
|
fSubtitleStart = 0.078
|
|
iSubtitleDuration = 1750
|
|
ELSE
|
|
fSubtitleStart = 0.0
|
|
iSubtitleDuration = 2000
|
|
ENDIF
|
|
|
|
ELSE
|
|
SCRIPT_ASSERT("Private_GetAmbFriendOutroFaceAnimsForFriend() - Bad eFriendChar")
|
|
tFriendFaceDict = ""
|
|
tFriendFaceAnim = ""
|
|
ENDIF
|
|
|
|
IF bFirstTime
|
|
#IF IS_DEBUG_BUILD
|
|
TEXT_LABEL_31 tChar = GetLabel_enumCharacterList(eFriendChar)
|
|
CPRINTLN(DEBUG_FRIENDS, "Private_GetAmbFriendOutroFaceAnimsForFriend(", tChar, ") - iVariation = ", iVariation, ", anim = ", tFriendFaceAnim)
|
|
#ENDIF
|
|
// INIT_SYNCH_SCENE_AUDIO_WITH_ENTITY(tFriendAudioStream, hFriendPed)
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
|
|
FUNC BOOL Private_UpdateAmbFriend_Outro(structAmbGroup& group, structAmbFriend& friend)
|
|
|
|
// TEXT_LABEL tBlock, tRoot
|
|
|
|
TEXT_LABEL_63 tAnimDict
|
|
TEXT_LABEL_31 tPlayerAnim
|
|
TEXT_LABEL_31 tFriendAnim
|
|
TEXT_LABEL_31 tCameraAnim
|
|
|
|
TEXT_LABEL_63 tPlayerFaceDict
|
|
TEXT_LABEL_31 tPlayerFaceAnim
|
|
|
|
TEXT_LABEL_63 tFriendFaceDict
|
|
TEXT_LABEL_31 tFriendFaceAnim
|
|
|
|
TEXT_LABEL_63 tFriendAudioStream
|
|
|
|
TEXT_LABEL_31 tSubtitleLabel
|
|
FLOAT fSubtitleStart
|
|
INT iSubtitleDuration
|
|
|
|
FLOAT fHitTime
|
|
|
|
CPRINTLN(DEBUG_FRIENDS, "Private_UpdateAmbFriend_Outro() ", friend.iProgress, " - ", GET_FRAME_COUNT())
|
|
|
|
Private_GetAmbFriendOutroAnims(friend.eChar, fHitTime, tAnimDict, tPlayerAnim, tFriendAnim, tCameraAnim)
|
|
|
|
Private_GetAmbFriendOutroFaceAnimsForPlayer(g_eDefaultPlayerChar, friend.eChar, tPlayerFaceDict, tPlayerFaceAnim)
|
|
|
|
Private_GetAmbFriendOutroFaceAnimsForFriend(friend.eChar, /*friend.hPed,*/ group.iOutroSpeechVariation, tFriendFaceDict, tFriendFaceAnim, tFriendAudioStream, tSubtitleLabel, fSubtitleStart, iSubtitleDuration)
|
|
|
|
SET_THIS_IS_A_TRIGGER_SCRIPT(TRUE)
|
|
|
|
//-- Load anim dict and start scene...
|
|
IF friend.iProgress = 0
|
|
|
|
IF IS_SCREEN_FADED_OUT() OR IS_PED_INJURED(PLAYER_PED_ID()) OR IS_PED_INJURED(friend.hPed)
|
|
friend.iProgress++
|
|
ELSE
|
|
REQUEST_ANIM_DICT(tAnimDict)
|
|
REQUEST_ANIM_DICT(tPlayerFaceDict)
|
|
REQUEST_ANIM_DICT(tFriendFaceDict)
|
|
|
|
IF HAS_ANIM_DICT_LOADED(tAnimDict)
|
|
AND HAS_ANIM_DICT_LOADED(tPlayerFaceDict)
|
|
AND HAS_ANIM_DICT_LOADED(tFriendFaceDict)
|
|
|
|
IF PREPARE_SYNCHRONIZED_AUDIO_EVENT(tFriendAudioStream, 0)
|
|
|
|
// Calc scene position
|
|
VECTOR vPlayerToFriend = GET_ENTITY_COORDS(friend.hPed) - GET_ENTITY_COORDS(PLAYER_PED_ID())
|
|
VECTOR vRot = << 0.0, 0.0, GET_HEADING_FROM_VECTOR_2D(vPlayerToFriend.x, vPlayerToFriend.y) >>
|
|
VECTOR vAnchor = GET_ENTITY_COORDS(PLAYER_PED_ID())
|
|
GET_GROUND_Z_FOR_3D_COORD(vAnchor, vAnchor.z)
|
|
|
|
group.vOutroAnchor = vAnchor
|
|
|
|
// Start cutscene
|
|
RC_START_CUTSCENE_MODE(vAnchor, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE)
|
|
|
|
// Create cam
|
|
group.hOutroCamera = CREATE_CAM("DEFAULT_ANIMATED_CAMERA", TRUE)
|
|
|
|
// Remove bike if on one
|
|
IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
|
|
VEHICLE_INDEX hBike = GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID())
|
|
IF DOES_ENTITY_EXIST(hBike)
|
|
SET_ENTITY_COORDS(PLAYER_PED_ID(), GET_ENTITY_COORDS(PLAYER_PED_ID()))
|
|
DELETE_VEHICLE(hBike)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// Clear area
|
|
CLEAR_AREA_OF_VEHICLES(vAnchor, 10.0, FALSE, FALSE, TRUE, TRUE)
|
|
CLEAR_AREA_OF_PEDS(vAnchor, 5.0)
|
|
group.hOutroScenarioBlock = ADD_SCENARIO_BLOCKING_AREA_FROM_POSITION_AND_RADIUS(vAnchor, 5.0)
|
|
|
|
CLEAR_PED_TASKS_IMMEDIATELY(PLAYER_PED_ID())
|
|
CLEAR_PED_TASKS_IMMEDIATELY(friend.hPed)
|
|
|
|
FORCE_PED_AI_AND_ANIMATION_UPDATE(PLAYER_PED_ID(), TRUE)
|
|
FORCE_PED_AI_AND_ANIMATION_UPDATE(friend.hPed, TRUE)
|
|
|
|
SET_CURRENT_PED_WEAPON(PLAYER_PED_ID(), WEAPONTYPE_UNARMED, TRUE)
|
|
SET_CURRENT_PED_WEAPON(friend.hPed, WEAPONTYPE_UNARMED, TRUE)
|
|
|
|
// Block paths
|
|
VECTOR vBlockMin = group.vOutroAnchor - <<10,10,10>>
|
|
VECTOR vBlockMax = group.vOutroAnchor + <<10,10,10>>
|
|
SET_ROADS_IN_AREA(vBlockMin, vBlockMax, FALSE)
|
|
SET_PED_PATHS_IN_AREA(vBlockMin, vBlockMax, FALSE)
|
|
|
|
// Create scene
|
|
group.hOutroScene = CREATE_SYNCHRONIZED_SCENE(vAnchor, vRot)
|
|
TASK_SYNCHRONIZED_SCENE(PLAYER_PED_ID(), group.hOutroScene, tAnimDict, tPlayerAnim, NORMAL_BLEND_IN, REALLY_SLOW_BLEND_OUT)
|
|
TASK_SYNCHRONIZED_SCENE(friend.hPed, group.hOutroScene, tAnimDict, tFriendAnim, NORMAL_BLEND_IN, REALLY_SLOW_BLEND_OUT)
|
|
PLAY_SYNCHRONIZED_CAM_ANIM(group.hOutroCamera, group.hOutroScene, tCameraAnim, tAnimDict)
|
|
|
|
PLAY_FACIAL_ANIM(PLAYER_PED_ID(), tPlayerFaceAnim, tPlayerFaceDict)
|
|
PLAY_FACIAL_ANIM(friend.hPed, tFriendFaceAnim, tFriendFaceDict)
|
|
|
|
PLAY_SYNCHRONIZED_AUDIO_EVENT(group.hOutroScene)
|
|
|
|
IF IS_SYNCHRONIZED_SCENE_HOLD_LAST_FRAME(group.hOutroScene)
|
|
SET_SYNCHRONIZED_SCENE_HOLD_LAST_FRAME(group.hOutroScene, FALSE)
|
|
ENDIF
|
|
|
|
// Enable camera
|
|
RENDER_SCRIPT_CAMS(TRUE, FALSE)
|
|
friend.iProgress++
|
|
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ELIF friend.iProgress = 1
|
|
|
|
// Wait for impact time
|
|
IF NOT IS_SYNCHRONIZED_SCENE_RUNNING(group.hOutroScene) OR IS_SCREEN_FADED_OUT() OR IS_PED_INJURED(PLAYER_PED_ID()) OR IS_PED_INJURED(friend.hPed)
|
|
friend.iProgress++
|
|
|
|
ELIF GET_SYNCHRONIZED_SCENE_PHASE(group.hOutroScene) >= fSubtitleStart
|
|
IF IS_SUBTITLE_PREFERENCE_SWITCHED_ON()
|
|
PRINT_NOW(tSubtitleLabel, iSubtitleDuration, 0)
|
|
ENDIF
|
|
friend.iProgress++
|
|
ENDIF
|
|
|
|
ELIF friend.iProgress = 2
|
|
|
|
// Wait for impact time
|
|
IF NOT IS_SYNCHRONIZED_SCENE_RUNNING(group.hOutroScene) OR IS_SCREEN_FADED_OUT() OR IS_PED_INJURED(PLAYER_PED_ID()) OR IS_PED_INJURED(friend.hPed)
|
|
OR GET_SYNCHRONIZED_SCENE_PHASE(group.hOutroScene) >= fHitTime
|
|
friend.iProgress++
|
|
ENDIF
|
|
|
|
ELIF friend.iProgress = 3
|
|
|
|
// Kill player
|
|
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
|
|
SET_ENTITY_HEALTH(PLAYER_PED_ID(), 0)
|
|
ENDIF
|
|
|
|
// Cleanup when faded out
|
|
IF IS_SCREEN_FADED_OUT()
|
|
SET_THIS_IS_A_TRIGGER_SCRIPT(FALSE)
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
ENDIF
|
|
|
|
SET_THIS_IS_A_TRIGGER_SCRIPT(FALSE)
|
|
RETURN FALSE
|
|
|
|
ENDFUNC
|
|
|
|
PROC Private_CleanupAmbFriendOutro(structAmbGroup& group)
|
|
|
|
CPRINTLN(DEBUG_FRIENDS, "Private_CleanupAmbFriendOutro()...")
|
|
|
|
TEXT_LABEL_63 tAnimDict
|
|
TEXT_LABEL_31 tPlayerAnim
|
|
TEXT_LABEL_31 tFriendAnim
|
|
TEXT_LABEL_31 tCameraAnim
|
|
FLOAT fHitTime
|
|
TEXT_LABEL_63 tPlayerFaceDict
|
|
TEXT_LABEL_31 tPlayerFaceAnim
|
|
|
|
Private_GetAmbFriendOutroAnims(group.eOutroChar, fHitTime, tAnimDict, tPlayerAnim, tFriendAnim, tCameraAnim)
|
|
|
|
Private_GetAmbFriendOutroFaceAnimsForPlayer(g_eDefaultPlayerChar, group.eOutroChar, tPlayerFaceDict, tPlayerFaceAnim)
|
|
|
|
// Clear tasks (in case aborting early)
|
|
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
|
|
CLEAR_PED_TASKS(PLAYER_PED_ID())
|
|
ENDIF
|
|
IF NOT IS_PED_INJURED(group.mFriends[group.eOutroChar].hPed)
|
|
CLEAR_PED_TASKS(group.mFriends[group.eOutroChar].hPed)
|
|
ENDIF
|
|
|
|
// Unblock scenario
|
|
IF group.hOutroScenarioBlock <> NULL
|
|
REMOVE_SCENARIO_BLOCKING_AREA(group.hOutroScenarioBlock)
|
|
group.hOutroScenarioBlock = NULL
|
|
ENDIF
|
|
|
|
// Unblock paths
|
|
VECTOR vBlockMin = group.vOutroAnchor - <<10,10,10>>
|
|
VECTOR vBlockMax = group.vOutroAnchor + <<10,10,10>>
|
|
SET_ROADS_BACK_TO_ORIGINAL(vBlockMin, vBlockMax)
|
|
SET_PED_PATHS_BACK_TO_ORIGINAL(vBlockMin, vBlockMax)
|
|
|
|
// Destroy cam
|
|
IF DOES_CAM_EXIST(group.hOutroCamera)
|
|
DESTROY_CAM(group.hOutroCamera)
|
|
ENDIF
|
|
RENDER_SCRIPT_CAMS(FALSE, FALSE)
|
|
|
|
// Unload resources
|
|
REMOVE_ANIM_DICT(tAnimDict)
|
|
|
|
// Restore control
|
|
RC_END_CUTSCENE_MODE(TRUE, FALSE)
|
|
|
|
IF (group.hOutroCandidate <> NO_CANDIDATE_ID)
|
|
CPRINTLN(DEBUG_FRIENDS, "Private_CleanupAmbFriendOutro() - Candidate ID: ", group.hOutroCandidate)
|
|
Mission_Over(group.hOutroCandidate)
|
|
ELSE
|
|
SCRIPT_ASSERT("Private_CleanupAmbFriendOutro() - No candidate ID")
|
|
ENDIF
|
|
|
|
group.hOutroCandidate = NO_CANDIDATE_ID
|
|
group.eOutroChar = NO_CHARACTER
|
|
group.bOutroActive = FALSE
|
|
|
|
ENDPROC
|
|
|
|
|
|
//-------------------------------------------------------------------------------------------------------------------------------------------
|
|
// AmbFriend - State utils
|
|
//-------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
PROC Private_InitAmbFriend(structAmbFriend& friend, enumCharacterList eChar)
|
|
friend.eState = AMBFRIEND_NULL
|
|
friend.iProgress = 0
|
|
friend.eChar = eChar
|
|
friend.hPed = NULL
|
|
friend.hTargetPed = NULL
|
|
friend.eGrabMode = AMBGRAB_NORMAL
|
|
friend.eDismissMode = AMBMODE_WANDER
|
|
friend.bDismissAudioRequest = FALSE
|
|
friend.bInitDismissMode = FALSE
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
friend.hDebugGrabFail = NULL
|
|
#ENDIF
|
|
|
|
friend.hOriginalGroup = RELGROUPHASH_NO_RELATIONSHIP
|
|
friend.hOriginalDefaultGroup = RELGROUPHASH_NO_RELATIONSHIP
|
|
friend.bIsVulnerable = FALSE
|
|
ENDPROC
|
|
|
|
PROC Private_SetAmbFriendState(structAmbGroup& group, structAmbFriend& friend, enumAmbFriendState eState, BOOL bVerbose = TRUE)
|
|
|
|
IF bVerbose
|
|
#IF IS_DEBUG_BUILD
|
|
TEXT_LABEL_63 tChar = GetLabel_enumCharacterList(friend.eChar)
|
|
TEXT_LABEL_63 tState = GetLabel_enumAmbFriendState(eState)
|
|
CPRINTLN(DEBUG_FRIENDS, "Private_SetAmbFriendState(", tChar, ", ", tState, ") ", GET_FRAME_COUNT())
|
|
IF group.bIsSwitchActive = FALSE
|
|
ENDIF
|
|
#ENDIF
|
|
ENDIF
|
|
|
|
// Exit old state
|
|
SWITCH friend.eState
|
|
CASE AMBFRIEND_GREET FALLTHRU
|
|
CASE AMBFRIEND_GREET_SAFEHOUSE FALLTHRU
|
|
CASE AMBFRIEND_GREET_OUTSIDE
|
|
IF NOT IS_PED_INJURED(friend.hPed)
|
|
TASK_CLEAR_LOOK_AT(friend.hPed)
|
|
ENDIF
|
|
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
|
|
TASK_CLEAR_LOOK_AT(PLAYER_PED_ID())
|
|
ENDIF
|
|
group.iGreetCount--
|
|
BREAK
|
|
CASE AMBFRIEND_OUTRO
|
|
Private_CleanupAmbFriendOutro(group)
|
|
BREAK
|
|
ENDSWITCH
|
|
|
|
// Set new state
|
|
friend.eState = eState
|
|
friend.iProgress = 0
|
|
|
|
IF friend.eState = AMBFRIEND_GREET
|
|
OR friend.eState = AMBFRIEND_GREET_SAFEHOUSE
|
|
OR friend.eState = AMBFRIEND_GREET_OUTSIDE
|
|
|
|
group.iGreetCount++
|
|
|
|
ELIF friend.eState = AMBFRIEND_DISMISSED
|
|
|
|
friend.eDismissMode = AMBMODE_WANDER
|
|
friend.bInitDismissMode = TRUE
|
|
friend.bDismissAudioRequest = FALSE
|
|
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
//-------------------------------------------------------------------------------------------------------------------------------------------
|
|
// AmbFriend - Group utils
|
|
//-------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
FUNC BOOL Private_IsAmbFriendDismissed(structAmbFriend& friend)
|
|
enumFriendContactType eContactType = Private_GET_FRIEND_LAST_CONTACT_TYPE(g_eDefaultPlayerChar, friend.eChar)
|
|
|
|
IF eContactType = FRIEND_CONTACT_DISMISSED
|
|
IF Private_GET_FRIEND_LAST_CONTACT_TIME(g_eDefaultPlayerChar, friend.eChar) < 3.0*60.0
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
FUNC BOOL Private_IsAmbFriendContactRecent(structAmbFriend& friend)
|
|
enumFriendContactType eContactType = Private_GET_FRIEND_LAST_CONTACT_TYPE(g_eDefaultPlayerChar, friend.eChar)
|
|
|
|
IF eContactType = FRIEND_CONTACT_FACE
|
|
OR eContactType = FRIEND_CONTACT_DISMISSED
|
|
IF Private_GET_FRIEND_LAST_CONTACT_TIME(g_eDefaultPlayerChar, friend.eChar) < 6.0*60.0
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
FUNC BOOL Private_IsAmbFriendDismissedByAnyone(structAmbFriend& friend)
|
|
enumCharacterList eLoopChar
|
|
REPEAT NUM_OF_PLAYABLE_PEDS eLoopChar
|
|
IF eLoopChar <> friend.eChar
|
|
IF Private_GET_FRIEND_LAST_CONTACT_TYPE(eLoopChar, friend.eChar) = FRIEND_CONTACT_DISMISSED
|
|
IF Private_GET_FRIEND_LAST_CONTACT_TIME(eLoopChar, friend.eChar) < 3.0*60.0
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
FUNC BOOL Private_IsAmbGroupAllowed()
|
|
|
|
IF IS_PED_INJURED(PLAYER_PED_ID())
|
|
OR IS_PLAYER_BEING_ARRESTED(PLAYER_ID())
|
|
// OR IS_PED_FALLING(PLAYER_PED_ID())
|
|
OR g_bPlayerIsInTaxi
|
|
OR IS_TRANSITION_ACTIVE()
|
|
OR IS_SCRIPT_HUD_DISPLAYING(HUDPART_TRANSITIONHUD)
|
|
OR IS_RESULT_SCREEN_DISPLAYING()
|
|
OR IS_PLAYER_BROWSING_ITEMS_IN_ANY_SHOP()
|
|
OR NOT IS_PLAYER_CONTROL_ON(PLAYER_ID())
|
|
// OR NOT IS_SCREEN_FADED_IN()
|
|
// OR IS_PED_RAGDOLL(PLAYER_PED_ID())
|
|
// OR IS_PED_IN_COMBAT(PLAYER_PED_ID()) // TODO: Think about this one
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
//FUNC BOOL Private_IsAmbGroupOutOfRange(structAmbGroup& group)
|
|
// VECTOR vPlayerPos = GET_ENTITY_COORDS(PLAYER_PED_ID())
|
|
//
|
|
// BOOL bAreAnyInRange = FALSE
|
|
// enumCharacterList eLoopChar
|
|
// REPEAT NUM_OF_PLAYABLE_PEDS eLoopChar
|
|
// IF eLoopChar <> g_eDefaultPlayerChar
|
|
// IF NOT IS_PED_INJURED(group.mFriends[eLoopChar].hPed)
|
|
// FLOAT fDist2 = VDIST2(vPlayerPos, GET_ENTITY_COORDS(group.mFriends[eLoopChar].hPed))
|
|
// IF fDist2 < 30.0*30.0//20.0*20.0//50.0*50.0//
|
|
// bAreAnyInRange = TRUE
|
|
// ENDIF
|
|
// ENDIF
|
|
// ENDIF
|
|
// ENDREPEAT
|
|
//
|
|
// IF bAreAnyInRange = TRUE
|
|
// RETURN FALSE
|
|
// ENDIF
|
|
//
|
|
// RETURN TRUE
|
|
//ENDFUNC
|
|
|
|
FUNC BOOL Private_CanAmbFriendGreet(structAmbGroup& group, structAmbFriend& friend)
|
|
|
|
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
|
|
|
|
// Do LOS test to player
|
|
IF (friend.hLosTest = NULL)
|
|
|
|
INT iFlags = SCRIPT_INCLUDE_MOVER|SCRIPT_INCLUDE_VEHICLE|SCRIPT_INCLUDE_PED|SCRIPT_INCLUDE_OBJECT|SCRIPT_INCLUDE_FOLIAGE
|
|
VECTOR vPlayerHead = GET_PED_BONE_COORDS(PLAYER_PED_ID(), BONETAG_HEAD, <<0.0, 0.0, 0.0>>)
|
|
VECTOR vFriendHead = GET_PED_BONE_COORDS(friend.hPed, BONETAG_HEAD, <<0.0, 0.0, 0.0>>)
|
|
|
|
VEHICLE_INDEX hPlayerVehicle = NULL
|
|
IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
|
|
hPlayerVehicle = GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID())
|
|
ENDIF
|
|
|
|
friend.hLosTest = START_SHAPE_TEST_LOS_PROBE(vPlayerHead, vFriendHead, iFlags, hPlayerVehicle, SCRIPT_SHAPETEST_OPTION_DEFAULT)
|
|
|
|
ELSE
|
|
|
|
INT iHitCount
|
|
VECTOR vHitPoint, vHitNormal
|
|
ENTITY_INDEX hHitEntity
|
|
SHAPETEST_STATUS eStatus = GET_SHAPE_TEST_RESULT(friend.hLosTest, iHitCount, vHitPoint, vHitNormal, hHitEntity)
|
|
|
|
IF eStatus = SHAPETEST_STATUS_RESULTS_READY
|
|
|
|
VEHICLE_INDEX hFriendVehicle = NULL
|
|
IF IS_PED_IN_ANY_VEHICLE(friend.hPed)
|
|
hFriendVehicle = GET_VEHICLE_PED_IS_IN(friend.hPed)
|
|
ENDIF
|
|
|
|
// TEXT_LABEL_63 tText = "HtCnt:"
|
|
// tText += iHitCount
|
|
// tText += ", HtExst:"
|
|
// IF DOES_ENTITY_EXIST(hHitEntity) tText += "T"
|
|
// ELSE tText += "F" ENDIF
|
|
// tText += ", HtEnt:"
|
|
// tText += NATIVE_TO_INT(hHitEntity)
|
|
// tText += ", CrEnt:"
|
|
// tText += NATIVE_TO_INT(hFriendVehicle)
|
|
// DISPLAY_TEXT_WITH_LITERAL_STRING(0.1, 0.1, "STRING", tText)
|
|
|
|
IF iHitCount = 0
|
|
OR (DOES_ENTITY_EXIST(hHitEntity) AND hHitEntity = GET_ENTITY_FROM_PED_OR_VEHICLE(friend.hPed))
|
|
OR (DOES_ENTITY_EXIST(hHitEntity) AND hHitEntity = GET_ENTITY_FROM_PED_OR_VEHICLE(hFriendVehicle))
|
|
friend.iLosTestTime = GET_GAME_TIMER()
|
|
ENDIF
|
|
|
|
friend.hLosTest = NULL
|
|
|
|
ELIF eStatus = SHAPETEST_STATUS_NONEXISTENT
|
|
friend.hLosTest = NULL
|
|
ENDIF
|
|
|
|
ENDIF
|
|
|
|
// // Debug - how long since last sighting was registered
|
|
// INT iTime = GET_GAME_TIMER() - friend.iLosTestTime
|
|
// TEXT_LABEL tTime
|
|
// IF iTime < 500
|
|
// tTime = "YES "
|
|
// ELSE
|
|
// tTime = "NO "
|
|
// ENDIF
|
|
// tTime += iTime
|
|
// DISPLAY_TEXT_WITH_LITERAL_STRING(0.1, 0.1, "STRING", tTime)
|
|
|
|
// If sighting has been registered in the last 0.5 seconds
|
|
IF GET_GAME_TIMER() - friend.iLosTestTime < 500
|
|
|
|
IF (NOT IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID()) OR ABSF(GET_ENTITY_SPEED(PLAYER_PED_ID())) < 10.0)
|
|
AND (NOT IS_PED_IN_ANY_VEHICLE(friend.hPed) OR ABSF(GET_ENTITY_SPEED(friend.hPed)) < 10.0)
|
|
|
|
IF NOT IS_PED_RAGDOLL(friend.hPed)
|
|
|
|
// Can pass in distance to another ped, but defaults to checking if near to player
|
|
FLOAT fDist2 = VDIST2(GET_ENTITY_COORDS(PLAYER_PED_ID()), GET_ENTITY_COORDS(friend.hPed))
|
|
FLOAT fRange = 13.0
|
|
|
|
IF Private_CanAmbFriendBlank(friend)
|
|
fRange = 5.0//6.0
|
|
ELIF group.iGreetCount > 0
|
|
fRange = 25.0
|
|
ENDIF
|
|
|
|
IF fDist2 < fRange*fRange
|
|
|
|
IF NOT Private_IsAmbFriendDismissed(friend)
|
|
|
|
IF friend.eState = AMBFRIEND_DISMISSED
|
|
IF friend.eDismissMode = AMBMODE_FIGHT
|
|
OR friend.eDismissMode = AMBMODE_FLEE
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF IS_ENTITY_ON_SCREEN(friend.hPed) AND NOT IS_ENTITY_OCCLUDED(friend.hPed)
|
|
|
|
IF Private_IsAmbGroupAllowed()
|
|
AND g_flowUnsaved.bFlowControllerBusy = FALSE
|
|
|
|
RETURN TRUE
|
|
|
|
ENDIF
|
|
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
FUNC BOOL Private_CanAmbFriendSafehouseGreet(structAmbFriend& friend, BOOL bMustBeInTrailer, FLOAT fDist)
|
|
|
|
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
|
|
|
|
BOOL bIsInTrailer = FALSE
|
|
IF GET_INTERIOR_FROM_ENTITY(PLAYER_PED_ID()) <> NULL
|
|
bIsInTrailer = TRUE
|
|
ENDIF
|
|
|
|
IF bMustBeInTrailer = bIsInTrailer
|
|
|
|
// Can pass in distance to another ped, but defaults to checking if near to player
|
|
FLOAT fDist2 = VDIST2(GET_ENTITY_COORDS(PLAYER_PED_ID()), GET_ENTITY_COORDS(friend.hPed))
|
|
FLOAT fRange = fDist//30.0
|
|
|
|
IF fDist2 < fRange*fRange
|
|
|
|
IF Private_IsAmbGroupAllowed()
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
FUNC BOOL Private_CanAmbFriendHangout(structAmbFriend& friend)
|
|
IF (g_eFriendMissionZoneState = FRIEND_MISSION_ZONE_OFF OR IS_BIT_SET(g_iFriendMissionZoneAcceptBitset, ENUM_TO_INT(friend.eChar)))
|
|
AND NOT IS_FRIEND_BLOCK_FLAG_SET(g_eDefaultPlayerChar, friend.eChar, FRIEND_BLOCK_FLAG_HIATUS)
|
|
AND NOT IS_FRIEND_BLOCK_FLAG_SET(g_eDefaultPlayerChar, friend.eChar, FRIEND_BLOCK_FLAG_CLASH)
|
|
AND g_savedGlobals.sCommsControlData.eCharacterPriorityLevel[g_eDefaultPlayerChar] <> CPR_VERY_HIGH // TODO: Think about this one
|
|
|
|
// AND NOT ARE_ANY_CONNECTIONS_PENDING_OR_PHONE() // TODO: Think about this one
|
|
// AND NOT IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
|
|
// AND NOT IS_PED_IN_ANY_VEHICLE(friend.hPed)
|
|
// AND NOT g_isPlayerDrunk
|
|
|
|
// Make sure connections are ok
|
|
enumFriendConnection eDesiredConnection
|
|
enumFriendConnection eActiveConnection
|
|
|
|
IF GET_CONNECTION(g_eDefaultPlayerChar, friend.eChar, eDesiredConnection)
|
|
|
|
INT iActiveConnections = GET_PENDING_OR_ACTIVE_CONNECTIONS(eActiveConnection)
|
|
|
|
IF eActiveConnection <> eDesiredConnection
|
|
IF iActiveConnections = 0
|
|
RETURN TRUE
|
|
|
|
ELIF iActiveConnections = 1
|
|
enumFriendConnection eCommonConnection
|
|
|
|
IF GET_COMMON_CONNECTION(eDesiredConnection, eActiveConnection, eCommonConnection)
|
|
AND GET_CONNECTION_STATE(eCommonConnection) = FC_STATE_ContactWait
|
|
|
|
IF g_SavedGlobals.sFriendsData.g_FriendConnectData[eCommonConnection].blockBits = 0
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ENDIF
|
|
|
|
ENDIF
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
#if USE_CLF_DLC
|
|
FUNC BOOL Private_IsPlayerAtOwnSafehouseCLF()
|
|
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
|
|
enumCharacterList ePlayerChar = GET_CURRENT_PLAYER_PED_ENUM()
|
|
|
|
IF ePlayerChar = CHAR_MICHAEL
|
|
|
|
IF Is_Savehouse_Respawn_Available(SAVEHOUSEclf_MICHAEL_BH)
|
|
IF IS_ENTITY_AT_COORD(PLAYER_PED_ID(), <<-816.692261,169.942932,70.514229>>, <<115.0,115.0,115.0>>)//80.0)
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF Is_Savehouse_Respawn_Available(SAVEHOUSEclf_MICHAEL_CS)
|
|
IF IS_ENTITY_AT_COORD(PLAYER_PED_ID(), <<1977.231934,3812.881348,31.357803>>, <<150.0,150.0,150.0>>)//80.0)
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ELIF ePlayerChar = CHAR_FRANKLIN
|
|
|
|
IF Is_Savehouse_Respawn_Available(SAVEHOUSEclf_FRANKLIN_SC)
|
|
VECTOR vMin = <<-31.631046,-1459.370483,35.043587>> - <<84.500000,50.250000,9.000000>>
|
|
VECTOR vMax = <<-31.631046,-1459.370483,35.043587>> + <<84.500000,50.250000,9.000000>>
|
|
IF IS_ENTITY_IN_AREA(PLAYER_PED_ID(), vMin, vMax)
|
|
RETURN TRUE
|
|
ENDIF
|
|
// IF IS_ENTITY_AT_COORD(PLAYER_PED_ID(), <<-31.631046,-1459.370483,35.043587>>, 150.0)//80.0)
|
|
// RETURN TRUE
|
|
// ENDIF
|
|
ENDIF
|
|
|
|
IF Is_Savehouse_Respawn_Available(SAVEHOUSEclf_FRANKLIN_VH)
|
|
VECTOR vMin = <<4.536090,528.395142,158.115036>> - <<152.500000,74.750000,28.500000>>
|
|
VECTOR vMax = <<4.536090,528.395142,158.115036>> + <<152.500000,74.750000,28.500000>>
|
|
IF IS_ENTITY_IN_AREA(PLAYER_PED_ID(), vMin, vMax)
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ELIF ePlayerChar = CHAR_TREVOR
|
|
|
|
IF Is_Savehouse_Respawn_Available(SAVEHOUSEclf_TREVOR_CS)
|
|
IF IS_ENTITY_AT_COORD(PLAYER_PED_ID(), <<1977.231934,3812.881348,31.357803>>, <<150.0,150.0,150.0>>)//80.0)
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF Is_Savehouse_Respawn_Available(SAVEHOUSEclf_TREVOR_VB)
|
|
IF IS_ENTITY_AT_COORD(PLAYER_PED_ID(), <<-1155.240479,-1519.908447,3.350527>>, <<150.0,150.0,150.0>>)//80.0)
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF Is_Savehouse_Respawn_Available(SAVEHOUSEclf_TREVOR_SC)
|
|
IF IS_ENTITY_AT_COORD(PLAYER_PED_ID(), <<131.592010,-1303.622437,28.226076>>, <<100.0,100.0,100.0>>)
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ENDIF
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
#endif
|
|
#if USE_NRM_DLC
|
|
FUNC BOOL Private_IsPlayerAtOwnSafehouseNRM()
|
|
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
|
|
enumCharacterList ePlayerChar = GET_CURRENT_PLAYER_PED_ENUM()
|
|
|
|
IF ePlayerChar = CHAR_MICHAEL
|
|
|
|
IF Is_Savehouse_Respawn_Available(SAVEHOUSENRM_BH)
|
|
IF IS_ENTITY_AT_COORD(PLAYER_PED_ID(), <<-816.692261,169.942932,70.514229>>, <<115.0,115.0,115.0>>)//80.0)
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF Is_Savehouse_Respawn_Available(SAVEHOUSENRM_CHATEAU)
|
|
IF IS_ENTITY_AT_COORD(PLAYER_PED_ID(), <<1977.231934,3812.881348,31.357803>>, <<150.0,150.0,150.0>>)//80.0)
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ELIF ePlayerChar = CHAR_FRANKLIN
|
|
|
|
|
|
ELIF ePlayerChar = CHAR_TREVOR
|
|
|
|
|
|
ENDIF
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
#endif
|
|
FUNC BOOL Private_IsPlayerAtOwnSafehouse()
|
|
#if USE_CLF_DLC
|
|
return Private_IsPlayerAtOwnSafehouseCLF()
|
|
#endif
|
|
#if USE_NRM_DLC
|
|
return Private_IsPlayerAtOwnSafehouseNRM()
|
|
#endif
|
|
#if not USE_CLF_DLC
|
|
#if not USE_NRM_DLC
|
|
|
|
|
|
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
|
|
enumCharacterList ePlayerChar = GET_CURRENT_PLAYER_PED_ENUM()
|
|
|
|
IF ePlayerChar = CHAR_MICHAEL
|
|
|
|
IF Is_Savehouse_Respawn_Available(SAVEHOUSE_MICHAEL_BH)
|
|
IF IS_ENTITY_AT_COORD(PLAYER_PED_ID(), <<-816.692261,169.942932,70.514229>>, <<115.0,115.0,115.0>>)//80.0)
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF Is_Savehouse_Respawn_Available(SAVEHOUSE_MICHAEL_CS)
|
|
IF IS_ENTITY_AT_COORD(PLAYER_PED_ID(), <<1977.231934,3812.881348,31.357803>>, <<150.0,150.0,150.0>>)//80.0)
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ELIF ePlayerChar = CHAR_FRANKLIN
|
|
|
|
IF Is_Savehouse_Respawn_Available(SAVEHOUSE_FRANKLIN_SC)
|
|
VECTOR vMin = <<-31.631046,-1459.370483,35.043587>> - <<84.500000,50.250000,9.000000>>
|
|
VECTOR vMax = <<-31.631046,-1459.370483,35.043587>> + <<84.500000,50.250000,9.000000>>
|
|
IF IS_ENTITY_IN_AREA(PLAYER_PED_ID(), vMin, vMax)
|
|
RETURN TRUE
|
|
ENDIF
|
|
// IF IS_ENTITY_AT_COORD(PLAYER_PED_ID(), <<-31.631046,-1459.370483,35.043587>>, 150.0)//80.0)
|
|
// RETURN TRUE
|
|
// ENDIF
|
|
ENDIF
|
|
|
|
IF Is_Savehouse_Respawn_Available(SAVEHOUSE_FRANKLIN_VH)
|
|
VECTOR vMin = <<4.536090,528.395142,158.115036>> - <<152.500000,74.750000,28.500000>>
|
|
VECTOR vMax = <<4.536090,528.395142,158.115036>> + <<152.500000,74.750000,28.500000>>
|
|
IF IS_ENTITY_IN_AREA(PLAYER_PED_ID(), vMin, vMax)
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ELIF ePlayerChar = CHAR_TREVOR
|
|
|
|
IF Is_Savehouse_Respawn_Available(SAVEHOUSE_TREVOR_CS)
|
|
IF IS_ENTITY_AT_COORD(PLAYER_PED_ID(), <<1977.231934,3812.881348,31.357803>>, <<150.0,150.0,150.0>>)//80.0)
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF Is_Savehouse_Respawn_Available(SAVEHOUSE_TREVOR_VB)
|
|
IF IS_ENTITY_AT_COORD(PLAYER_PED_ID(), <<-1155.240479,-1519.908447,3.350527>>, <<150.0,150.0,150.0>>)//80.0)
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF Is_Savehouse_Respawn_Available(SAVEHOUSE_TREVOR_SC)
|
|
IF IS_ENTITY_AT_COORD(PLAYER_PED_ID(), <<131.592010,-1303.622437,28.226076>>, <<100.0,100.0,100.0>>)
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ENDIF
|
|
ENDIF
|
|
RETURN FALSE
|
|
#endif
|
|
#endif
|
|
ENDFUNC
|
|
|
|
FUNC enumAmbConvState Private_GetAmbFriendConvRequest(structAmbFriend& friend)
|
|
|
|
enumFriendConnection eConnection
|
|
IF GET_CONNECTION(g_eDefaultPlayerChar, friend.eChar, eConnection)
|
|
#if not USE_CLF_DLC
|
|
#if not USE_NRM_DLC
|
|
IF friend.eGrabMode = AMBGRAB_SAFEHOUSE_TRAILER // Safehouse: Trevor says "Oh, it's you again"
|
|
OR friend.eGrabMode = AMBGRAB_SAFEHOUSE_OUTSIDE // Safehouse: Trevor says "Oh, it's you again"
|
|
RETURN AMBCONV_SAFEHOUSE_TRAILER1
|
|
|
|
ELIF friend.eGrabMode = AMBGRAB_SAFEHOUSE_DRUNK // Safehouse: Says nothing (drunk)
|
|
RETURN AMBCONV_SAFEHOUSE_TRAILER3
|
|
|
|
ELIF eConnection = FC_MICHAEL_FRANKLIN // Set piece: Michael/Franklin after showroom crash
|
|
AND NOT GET_MISSION_COMPLETE_STATE(SP_MISSION_FAMILY_1)
|
|
IF NOT IS_BIT_SET(g_SavedGlobals.sFriendsData.g_iAmbChatBitfield, ENUM_TO_INT(AMBCHATBIT_MFSHOWROOM))
|
|
RETURN AMBCONV_MFSHOWROOM_HELLO
|
|
ELSE
|
|
RETURN AMBCONV_DEFBLOCK_HELLO
|
|
ENDIF
|
|
|
|
ELIF eConnection = FC_TREVOR_MICHAEL // Set piece: Michael/Trevor whilst fallen out
|
|
AND GET_MISSION_FLOW_FLAG_STATE(FLOWFLAG_MICHAEL_TREVOR_HAVE_FALLEN_OUT)
|
|
IF NOT IS_BIT_SET(g_SavedGlobals.sFriendsData.g_iAmbChatBitfield, ENUM_TO_INT(AMBCHATBIT_MTFALLOUT))
|
|
RETURN AMBCONV_MTFALLOUT_HELLO
|
|
ELSE
|
|
RETURN AMBCONV_ANGRY_HELLO
|
|
ENDIF
|
|
|
|
ELIF eConnection = FC_FRANKLIN_TREVOR // Set piece: Franklin/Trevor after killing Michael
|
|
AND GET_MISSION_FLOW_FLAG_STATE(FLOWFLAG_MICHAEL_KILLED)
|
|
IF NOT IS_BIT_SET(g_SavedGlobals.sFriendsData.g_iAmbChatBitfield, ENUM_TO_INT(AMBCHATBIT_KILLEDM))
|
|
RETURN AMBCONV_KILLEDM_HELLO
|
|
ELSE
|
|
RETURN AMBCONV_ANGRY_HELLO
|
|
ENDIF
|
|
|
|
ELIF eConnection = FC_MICHAEL_FRANKLIN // Set piece: Franklin/Michael after killing Trevor
|
|
AND GET_MISSION_FLOW_FLAG_STATE(FLOWFLAG_TREVOR_KILLED)
|
|
IF NOT IS_BIT_SET(g_SavedGlobals.sFriendsData.g_iAmbChatBitfield, ENUM_TO_INT(AMBCHATBIT_KILLEDT))
|
|
RETURN AMBCONV_KILLEDT_HELLO
|
|
ELSE
|
|
RETURN AMBCONV_ANGRY_HELLO
|
|
ENDIF
|
|
|
|
ELIF IS_FRIEND_BLOCK_FLAG_SET(g_eDefaultPlayerChar, friend.eChar, FRIEND_BLOCK_FLAG_MISSION) // Friend activity blocked by mission
|
|
|
|
IF PRIVATE_FriendAcceptsPlayer_missionBlock_AnswerPhone(GET_FRIEND_FROM_CHAR(g_eDefaultPlayerChar), GET_FRIEND_FROM_CHAR(friend.eChar))
|
|
IF Private_IsPlayerAtOwnSafehouse() RETURN AMBCONV_MISBLOCK_HELLO_HOME
|
|
ELSE RETURN AMBCONV_MISBLOCK_HELLO
|
|
ENDIF
|
|
ELSE
|
|
IF Private_IsPlayerAtOwnSafehouse() RETURN AMBCONV_DEFBLOCK_HELLO_HOME // If Michael/Trevor blocked for Michael1, don't talk as if they know there's a mission coming
|
|
ELSE RETURN AMBCONV_DEFBLOCK_HELLO
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ELIF Private_CanAmbFriendHangout(friend) // Friend activity available
|
|
IF Private_IsPlayerAtOwnSafehouse() RETURN AMBCONV_OFFER_HELLO_HOME
|
|
ELSE RETURN AMBCONV_OFFER_HELLO
|
|
ENDIF
|
|
|
|
ELSE // Default: "I'm busy"
|
|
IF Private_IsPlayerAtOwnSafehouse() RETURN AMBCONV_DEFBLOCK_HELLO_HOME
|
|
ELSE RETURN AMBCONV_DEFBLOCK_HELLO
|
|
ENDIF
|
|
ENDIF
|
|
#endif
|
|
#endif
|
|
ENDIF
|
|
|
|
// TODO: Might not need to assert here, just means that conv won't be counted when sorting highest priority?
|
|
#IF IS_DEBUG_BUILD
|
|
TEXT_LABEL_63 tPlayer = GetLabel_enumCharacterList(g_eDefaultPlayerChar)
|
|
TEXT_LABEL_63 tFriend = GetLabel_enumCharacterList(friend.eChar)
|
|
CPRINTLN(DEBUG_FRIENDS, "Private_GetAmbFriendConvRequest() - No connection between chars: ", tPlayer, "/", tFriend)
|
|
SCRIPT_ASSERT("Private_GetAmbFriendConvRequest() - No connection between chars")
|
|
#ENDIF
|
|
|
|
RETURN AMBCONV_NULL
|
|
|
|
ENDFUNC
|
|
|
|
PROC Private_DismissAmbFriend(structAmbGroup& group, structAmbFriend& friend)
|
|
|
|
CPRINTLN(DEBUG_FRIENDS, "Private_DismissAmbFriend(", GetLabel_enumCharacterList(friend.eChar), ")")
|
|
DEBUG_PRINTCALLSTACK()
|
|
|
|
// Reset last contact timer (to player and friends in group)
|
|
IF friend.eState = AMBFRIEND_GREET OR friend.eState = AMBFRIEND_IDLE OR friend.eState = AMBFRIEND_DISMISSED OR friend.eState = AMBFRIEND_GREET_SAFEHOUSE OR friend.eState = AMBFRIEND_GREET_OUTSIDE
|
|
enumCharacterList eLoopChar
|
|
REPEAT NUM_OF_PLAYABLE_PEDS eLoopChar
|
|
IF friend.eChar <> eLoopChar
|
|
|
|
IF group.mFriends[eLoopChar].eState = AMBFRIEND_PLAYER
|
|
OR group.mFriends[eLoopChar].eState = AMBFRIEND_GREET
|
|
OR group.mFriends[eLoopChar].eState = AMBFRIEND_GREET_SAFEHOUSE
|
|
OR group.mFriends[eLoopChar].eState = AMBFRIEND_GREET_OUTSIDE
|
|
RESET_FRIEND_LAST_CONTACT_TIMER(friend.eChar, eLoopChar, FRIEND_CONTACT_DISMISSED)
|
|
ENDIF
|
|
|
|
ENDIF
|
|
ENDREPEAT
|
|
ENDIF
|
|
|
|
// Normal dismiss...
|
|
IF friend.eState = AMBFRIEND_GREET OR friend.eState = AMBFRIEND_IDLE OR friend.eState = AMBFRIEND_DISMISSED
|
|
|
|
// Set state to dismissed
|
|
IF friend.eState <> AMBFRIEND_DISMISSED
|
|
Private_SetAmbFriendState(group, friend, AMBFRIEND_DISMISSED)
|
|
ENDIF
|
|
|
|
|
|
// Dismiss safehouse ped...
|
|
ELIF friend.eState = AMBFRIEND_GREET_SAFEHOUSE
|
|
OR friend.eState = AMBFRIEND_GREET_OUTSIDE
|
|
|
|
// Mark for never picking up again
|
|
// IF NOT IS_PED_INJURED(friend.hPed)
|
|
// DECOR_SET_BOOL(friend.hPed, "BlockFriendGrab", TRUE)
|
|
// ENDIF
|
|
|
|
// Set state to released
|
|
Private_SetAmbFriendState(group, friend, AMBFRIEND_NULL)
|
|
Private_InitAmbFriend(friend, friend.eChar)
|
|
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
PROC Private_DismissAmbGroup(structAmbGroup& group)
|
|
|
|
enumCharacterList eChar
|
|
REPEAT NUM_OF_PLAYABLE_PEDS eChar
|
|
IF group.mFriends[eChar].eState = AMBFRIEND_GREET
|
|
OR group.mFriends[eChar].eState = AMBFRIEND_GREET_SAFEHOUSE
|
|
OR group.mFriends[eChar].eState = AMBFRIEND_GREET_OUTSIDE
|
|
Private_DismissAmbFriend(group, group.mFriends[eChar])
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
ENDPROC
|
|
|
|
PROC Private_DismissAmbGroup_IfBlocked(structAmbGroup& group)
|
|
|
|
enumCharacterList eChar
|
|
REPEAT NUM_OF_PLAYABLE_PEDS eChar
|
|
IF group.mFriends[eChar].eState = AMBFRIEND_GREET
|
|
OR group.mFriends[eChar].eState = AMBFRIEND_GREET_SAFEHOUSE
|
|
OR group.mFriends[eChar].eState = AMBFRIEND_GREET_OUTSIDE
|
|
enumAmbConvState eConv = Private_GetAmbFriendConvRequest(group.mFriends[eChar])
|
|
|
|
IF eConv = AMBCONV_MISBLOCK_HELLO
|
|
OR eConv = AMBCONV_MISBLOCK_HELLO_HOME
|
|
OR eConv = AMBCONV_DEFBLOCK_HELLO
|
|
OR eConv = AMBCONV_DEFBLOCK_HELLO_HOME
|
|
Private_DismissAmbFriend(group, group.mFriends[eChar])
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
ENDPROC
|
|
|
|
PROC Private_DismissAmbGroup_IfAngry(structAmbGroup& group)
|
|
|
|
enumCharacterList eChar
|
|
REPEAT NUM_OF_PLAYABLE_PEDS eChar
|
|
IF group.mFriends[eChar].eState = AMBFRIEND_GREET
|
|
OR group.mFriends[eChar].eState = AMBFRIEND_GREET_SAFEHOUSE
|
|
OR group.mFriends[eChar].eState = AMBFRIEND_GREET_OUTSIDE
|
|
enumAmbConvState eConv = Private_GetAmbFriendConvRequest(group.mFriends[eChar])
|
|
|
|
IF eConv = AMBCONV_ANGRY_HELLO
|
|
OR eConv = AMBCONV_MTFALLOUT_HELLO
|
|
OR eConv = AMBCONV_KILLEDM_HELLO
|
|
OR eConv = AMBCONV_KILLEDT_HELLO
|
|
Private_DismissAmbFriend(group, group.mFriends[eChar])
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
ENDPROC
|
|
|
|
PROC Private_DismissAmbGroup_IfSecondary(structAmbGroup& group)
|
|
|
|
enumCharacterList eChar
|
|
REPEAT NUM_OF_PLAYABLE_PEDS eChar
|
|
IF group.mFriends[eChar].eState = AMBFRIEND_GREET
|
|
OR group.mFriends[eChar].eState = AMBFRIEND_GREET_SAFEHOUSE
|
|
OR group.mFriends[eChar].eState = AMBFRIEND_GREET_OUTSIDE
|
|
IF eChar <> group.eConvChar
|
|
Private_DismissAmbFriend(group, group.mFriends[eChar])
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
ENDPROC
|
|
|
|
PROC Private_DismissAmbGroup_IfOffer(structAmbGroup& group)
|
|
|
|
enumCharacterList eChar
|
|
REPEAT NUM_OF_PLAYABLE_PEDS eChar
|
|
IF group.mFriends[eChar].eState = AMBFRIEND_GREET
|
|
OR group.mFriends[eChar].eState = AMBFRIEND_GREET_SAFEHOUSE
|
|
OR group.mFriends[eChar].eState = AMBFRIEND_GREET_OUTSIDE
|
|
enumAmbConvState eConv = Private_GetAmbFriendConvRequest(group.mFriends[eChar])
|
|
|
|
IF eConv = AMBCONV_OFFER_HELLO
|
|
OR eConv = AMBCONV_OFFER_HELLO_HOME
|
|
Private_DismissAmbFriend(group, group.mFriends[eChar])
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
ENDPROC
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------------------------------------------------------------------------------
|
|
// AmbFriend - FSM
|
|
//-------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
PROC Private_SetAmbFriendVulnerable(structAmbGroup& group, structAmbFriend& friend, BOOL bEnable)
|
|
|
|
IF bEnable
|
|
IF friend.bIsVulnerable = FALSE
|
|
AND friend.eChar <> g_eDefaultPlayerChar
|
|
CPRINTLN(DEBUG_FRIENDS, "Private_SetAmbFriendVulnerable(", GetLabel_enumCharacterList(friend.eChar), ", TRUE)")
|
|
|
|
friend.hOriginalGroup = GET_PED_RELATIONSHIP_GROUP_DEFAULT_HASH(friend.hPed)
|
|
friend.hOriginalDefaultGroup = GET_PED_RELATIONSHIP_GROUP_DEFAULT_HASH(friend.hPed)
|
|
|
|
SET_PED_RELATIONSHIP_GROUP_DEFAULT_HASH(friend.hPed, group.hEmptyGroup)
|
|
SET_PED_RELATIONSHIP_GROUP_HASH(friend.hPed, group.hEmptyGroup)
|
|
|
|
friend.bIsVulnerable = TRUE
|
|
ENDIF
|
|
ELSE
|
|
IF friend.bIsVulnerable = TRUE
|
|
CPRINTLN(DEBUG_FRIENDS, "Private_SetAmbFriendVulnerable(", GetLabel_enumCharacterList(friend.eChar), ", FALSE)")
|
|
IF friend.eChar = g_eDefaultPlayerChar
|
|
SCRIPT_ASSERT("Private_SetAmbFriendVulnerable(FALSE) - Can't call on player, skipping over (ignorable)")
|
|
ELSE
|
|
IF IsPedPerformingTask(friend.hPed, SCRIPT_TASK_COMBAT)
|
|
CLEAR_PED_TASKS(friend.hPed)
|
|
ENDIF
|
|
SET_PED_RELATIONSHIP_GROUP_HASH(friend.hPed, friend.hOriginalGroup)
|
|
SET_PED_RELATIONSHIP_GROUP_DEFAULT_HASH(friend.hPed, friend.hOriginalDefaultGroup)
|
|
ENDIF
|
|
friend.bIsVulnerable = FALSE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
PROC Private_SetAmbFriendAttribs(structAmbGroup& group, structAmbFriend& friend, structPedsForConversation& convPeds)
|
|
|
|
CPRINTLN(DEBUG_FRIENDS, "Private_SetAmbFriendAttribs(", GetLabel_enumCharacterList(friend.eChar), ")")
|
|
|
|
IF NOT IS_PED_INJURED(friend.hPed)
|
|
|
|
IF IS_PED_USING_ACTION_MODE(friend.hPed)
|
|
SET_PED_USING_ACTION_MODE(friend.hPed, FALSE)
|
|
ENDIF
|
|
|
|
IF IS_PED_IN_ANY_VEHICLE(friend.hPed)
|
|
VEHICLE_INDEX hVehicle = GET_VEHICLE_PED_IS_IN(friend.hPed)
|
|
IF IS_VEHICLE_DRIVEABLE(hVehicle) AND GET_PED_IN_VEHICLE_SEAT(hVehicle, VS_DRIVER) = friend.hPed
|
|
friend.hVehicle = hVehicle
|
|
ENDIF
|
|
ENDIF
|
|
|
|
CLEAR_ENTITY_LAST_DAMAGE_ENTITY(friend.hPed)
|
|
IF DOES_ENTITY_EXIST(friend.hVehicle) AND NOT IS_ENTITY_DEAD(friend.hVehicle)
|
|
CLEAR_ENTITY_LAST_DAMAGE_ENTITY(friend.hVehicle)
|
|
ENDIF
|
|
|
|
//ENUM_TO_INT(RBF_PLAYER_IMPACT)|ENUM_TO_INT(RBF_PLAYER_BUMP)|ENUM_TO_INT(RBF_PLAYER_RAGDOLL_BUMP)|ENUM_TO_INT(RBF_PED_RAGDOLL_BUMP)
|
|
SET_RAGDOLL_BLOCKING_FLAGS(friend.hPed, RBF_PLAYER_IMPACT)
|
|
// SET_RAGDOLL_BLOCKING_FLAGS(friend.hPed, RBF_MELEE)
|
|
|
|
ADD_FRIEND_CHAR_FOR_DIALOGUE(convPeds, g_eDefaultPlayerChar, PLAYER_PED_ID(), FALSE)
|
|
ADD_FRIEND_CHAR_FOR_DIALOGUE(convPeds, friend.eChar, friend.hPed, FALSE)
|
|
// SET_PED_CAN_PLAY_AMBIENT_ANIMS(friend.hPed, TRUE)
|
|
// SET_PED_CAN_PLAY_AMBIENT_BASE_ANIMS(friend.hPed, TRUE)
|
|
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(friend.hPed, TRUE)
|
|
STOP_PED_SPEAKING(friend.hPed, FALSE)
|
|
|
|
SET_CURRENT_PED_WEAPON(friend.hPed, WEAPONTYPE_UNARMED, TRUE)
|
|
|
|
//#1665158
|
|
FREEZE_ENTITY_POSITION(friend.hPed, FALSE)
|
|
|
|
PRINTLN("//#1665158 - FREEZE_ENTITY_POSITION(friend.hPed, FALSE)")
|
|
|
|
SET_ENTITY_SHOULD_FREEZE_WAITING_ON_COLLISION(friend.hPed, TRUE)
|
|
|
|
// If bringing Trevor/Franklin together before FBI2, allow them to fight...
|
|
IF Private_CanAmbFriendBlank(friend, FALSE)
|
|
Private_SetAmbFriendVulnerable(group, friend, TRUE)
|
|
ENDIF
|
|
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
PROC Private_ClearAmbFriendAttribs(structAmbGroup& group, structAmbFriend& friend)
|
|
|
|
CPRINTLN(DEBUG_FRIENDS, "Private_ClearAmbFriendAttribs(", GetLabel_enumCharacterList(friend.eChar), ")")
|
|
|
|
IF NOT IS_PED_INJURED(friend.hPed)
|
|
|
|
SET_PED_SHOULD_PLAY_NORMAL_SCENARIO_EXIT(friend.hPed)
|
|
CLEAR_RAGDOLL_BLOCKING_FLAGS(friend.hPed, RBF_PLAYER_IMPACT)
|
|
// CLEAR_RAGDOLL_BLOCKING_FLAGS(friend.hPed, RBF_MELEE)
|
|
|
|
SET_PED_CAN_SWITCH_WEAPON(friend.hPed, TRUE)
|
|
|
|
Private_SetAmbFriendVulnerable(group, friend, FALSE)
|
|
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
FUNC BOOL Private_GrabAmbFriendPed(structAmbGroup& group, structAmbFriend& friend, structPedsForConversation& convPeds)
|
|
|
|
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
|
|
|
|
// Get player ped
|
|
IF friend.eChar = g_eDefaultPlayerChar
|
|
|
|
friend.hPed = PLAYER_PED_ID()
|
|
ADD_FRIEND_CHAR_FOR_DIALOGUE(convPeds, friend.eChar, friend.hPed, FALSE)
|
|
friend.eGrabMode = AMBGRAB_NORMAL
|
|
RETURN TRUE
|
|
|
|
// Get queued ped
|
|
ELIF NOT IS_PED_INJURED(g_pDismissPeds[friend.eChar])
|
|
|
|
friend.hPed = g_pDismissPeds[friend.eChar]
|
|
friend.eGrabMode = g_pDismissMode[friend.eChar]
|
|
|
|
// Grab ped
|
|
SET_ENTITY_AS_MISSION_ENTITY(friend.hPed, TRUE, TRUE)
|
|
|
|
IF DOES_ENTITY_BELONG_TO_THIS_SCRIPT(friend.hPed)
|
|
CPRINTLN(DEBUG_FRIENDS, "Private_GrabAmbFriendPed(", GetLabel_enumCharacterList(friend.eChar), ") - Grabbed as queued char")
|
|
|
|
Private_SetAmbFriendAttribs(group, friend, convPeds)
|
|
|
|
g_pDismissPeds[friend.eChar] = NULL
|
|
friend.hVehicle = NULL
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
// Get non-player ped
|
|
ELSE
|
|
// Grab ped if allowed
|
|
SELECTOR_SLOTS_ENUM eSelectorSlot = GET_SELECTOR_SLOT_FROM_PLAYER_PED_ENUM(friend.eChar)
|
|
friend.hPed = g_sPlayerPedRequest.sSelectorPeds.pedID[eSelectorSlot]
|
|
IF NOT IS_PED_INJURED(friend.hPed)
|
|
|
|
// Is this ped a non-lead in char
|
|
IF IS_BIT_SET(g_sPlayerPedRequest.iBitsetPedInLeadIn, ENUM_TO_INT(eSelectorSlot))
|
|
#IF IS_DEBUG_BUILD
|
|
IF friend.hDebugGrabFail <> friend.hPed
|
|
CPRINTLN(DEBUG_FRIENDS, "Private_GrabAmbFriendPed(", GetLabel_enumCharacterList(friend.eChar), ") - Cannot grab - Ped tagged as lead-in scene character")
|
|
friend.hDebugGrabFail = friend.hPed
|
|
ENDIF
|
|
#ENDIF
|
|
|
|
// Make sure ped hasn't already been added to delete queue
|
|
ELIF Private_IsPedInDeleteQueue(friend.hPed)
|
|
#IF IS_DEBUG_BUILD
|
|
IF friend.hDebugGrabFail <> friend.hPed
|
|
CPRINTLN(DEBUG_FRIENDS, "Private_GrabAmbFriendPed(", GetLabel_enumCharacterList(friend.eChar), ") - Cannot grab - Ped is in delete queue")
|
|
friend.hDebugGrabFail = friend.hPed
|
|
ENDIF
|
|
#ENDIF
|
|
|
|
ELSE
|
|
// Does a friend connection exist and is ready
|
|
enumFriendConnection eConnection
|
|
IF GET_CONNECTION(g_eDefaultPlayerChar, friend.eChar, eConnection)
|
|
AND GET_CONNECTION_STATE(eConnection) = FC_STATE_ContactWait
|
|
|
|
STRING sOwnerScript = ""
|
|
INT hOwnerScript = 0
|
|
sOwnerScript = GET_ENTITY_SCRIPT(friend.hPed, hOwnerScript)
|
|
|
|
IF NOT IS_STRING_NULL_OR_EMPTY(sOwnerScript)
|
|
|
|
VECTOR vPlayerPos = GET_ENTITY_COORDS(PLAYER_PED_ID())
|
|
VECTOR vFriendPos = GET_ENTITY_COORDS(friend.hPed)
|
|
FLOAT fDist2 = VDIST2(vPlayerPos, vFriendPos)
|
|
|
|
IF fDist2 < 200.0 * 200.0
|
|
|
|
// Grabbing from player controller...
|
|
IF (ARE_STRINGS_EQUAL(sOwnerScript, "player_controller") OR ARE_STRINGS_EQUAL(sOwnerScript, "player_controller_b"))
|
|
|
|
// Grab ped
|
|
SET_ENTITY_AS_MISSION_ENTITY(friend.hPed, TRUE, TRUE)
|
|
|
|
IF DOES_ENTITY_BELONG_TO_THIS_SCRIPT(friend.hPed)
|
|
CPRINTLN(DEBUG_FRIENDS, "Private_GrabAmbFriendPed(", GetLabel_enumCharacterList(friend.eChar), ") - Grabbed as normal open-world char")
|
|
|
|
friend.eGrabMode = AMBGRAB_NORMAL
|
|
Private_SetAmbFriendAttribs(group, friend, convPeds)
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
// Grabbing from trevor family scene
|
|
ELIF friend.eChar = CHAR_TREVOR
|
|
AND ARE_STRINGS_EQUAL(sOwnerScript, "family_scene_t0")
|
|
|
|
SWITCH g_eCurrentFamilyEvent[FM_TREVOR_0_TREVOR]
|
|
CASE FE_T0_TREVOR_blowing_shit_up
|
|
CASE FE_T0_TREVOR_and_kidnapped_wife_walk
|
|
IF Private_CanAmbFriendSafehouseGreet(friend, FALSE, 12.0)
|
|
CPRINTLN(DEBUG_FRIENDS, "Private_GrabAmbFriendPed(", GetLabel_enumCharacterList(friend.eChar), ") - Grabbed as trevor family scene (outside)")
|
|
friend.eGrabMode = AMBGRAB_SAFEHOUSE_OUTSIDE
|
|
Private_SetAmbFriendAttribs(group, friend, convPeds)
|
|
RETURN TRUE
|
|
ENDIF
|
|
BREAK
|
|
CASE FE_T0_TREVOR_and_kidnapped_wife_stare
|
|
//CASE FE_T0_TREVOR_and_kidnapped_wife_laugh
|
|
#IF NOT IS_JAPANESE_BUILD
|
|
CASE FE_T0_TREVOR_doing_a_shit
|
|
#ENDIF
|
|
IF Private_CanAmbFriendSafehouseGreet(friend, TRUE, 30.0)
|
|
CPRINTLN(DEBUG_FRIENDS, "Private_GrabAmbFriendPed(", GetLabel_enumCharacterList(friend.eChar), ") - Grabbed as trevor family scene (inside)")
|
|
friend.eGrabMode = AMBGRAB_SAFEHOUSE_TRAILER
|
|
Private_SetAmbFriendAttribs(group, friend, convPeds)
|
|
RETURN TRUE
|
|
ENDIF
|
|
BREAK
|
|
CASE FE_T0_TREVOR_smoking_crystal
|
|
CASE FE_T0_TREVOR_passed_out_naked_drunk
|
|
IF Private_CanAmbFriendSafehouseGreet(friend, TRUE, 30.0)
|
|
CPRINTLN(DEBUG_FRIENDS, "Private_GrabAmbFriendPed(", GetLabel_enumCharacterList(friend.eChar), ") - Grabbed as trevor family scene (drunk)")
|
|
friend.eGrabMode = AMBGRAB_SAFEHOUSE_DRUNK
|
|
Private_SetAmbFriendAttribs(group, friend, convPeds)
|
|
RETURN TRUE
|
|
ENDIF
|
|
BREAK
|
|
ENDSWITCH
|
|
|
|
ELSE
|
|
#IF IS_DEBUG_BUILD
|
|
IF friend.hDebugGrabFail <> friend.hPed
|
|
CPRINTLN(DEBUG_FRIENDS, "Private_GrabAmbFriendPed(", GetLabel_enumCharacterList(friend.eChar), ") - Cannot grab - Not owned by player_controller or family_scene_t0 scripts")
|
|
friend.hDebugGrabFail = friend.hPed
|
|
ENDIF
|
|
#ENDIF
|
|
ENDIF
|
|
|
|
ENDIF
|
|
ELSE
|
|
#IF IS_DEBUG_BUILD
|
|
IF friend.hDebugGrabFail <> friend.hPed
|
|
CPRINTLN(DEBUG_FRIENDS, "Private_GrabAmbFriendPed(", GetLabel_enumCharacterList(friend.eChar), ") - Cannot grab - Not owned by any script")
|
|
friend.hDebugGrabFail = friend.hPed
|
|
ENDIF
|
|
#ENDIF
|
|
ENDIF
|
|
ELSE
|
|
#IF IS_DEBUG_BUILD
|
|
IF friend.hDebugGrabFail <> friend.hPed
|
|
IF GET_CONNECTION(g_eDefaultPlayerChar, friend.eChar, eConnection)
|
|
CPRINTLN(DEBUG_FRIENDS, "Private_GrabAmbFriendPed(", GetLabel_enumCharacterList(friend.eChar), ") - Cannot grab - Connection not in ContactWait")
|
|
CPRINTLN(DEBUG_FRIENDS, "Private_GrabAmbFriendPed() - [state is ", GetLabel_enumFriendConnectionState(GET_CONNECTION_STATE(eConnection)), "]")
|
|
ELSE
|
|
CPRINTLN(DEBUG_FRIENDS, "Private_GrabAmbFriendPed(", GetLabel_enumCharacterList(friend.eChar), ") - Cannot grab - Connection doesn't exist")
|
|
ENDIF
|
|
friend.hDebugGrabFail = friend.hPed
|
|
ENDIF
|
|
#ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
PROC Private_ReleaseAmbFriend(structAmbGroup& group, structAmbFriend& friend, BOOL bDelete = FALSE, BOOL bVerbose = TRUE, BOOL bStorePlayerPedInfoOnDelete = TRUE)
|
|
|
|
IF friend.eState <> AMBFRIEND_NULL
|
|
|
|
// Clean up current state
|
|
Private_SetAmbFriendState(group, friend, AMBFRIEND_NULL, bVerbose)
|
|
|
|
// If ped exists and I own it
|
|
IF DOES_ENTITY_EXIST(friend.hPed) AND DOES_ENTITY_BELONG_TO_THIS_SCRIPT(friend.hPed, FALSE) AND NOT Private_IsPedInDeleteQueue(friend.hPed)
|
|
|
|
// If dead, force to hospital switch scene and release ped
|
|
IF IS_PED_INJURED(friend.hPed)
|
|
g_SavedGlobals.sPlayerSceneData.g_ePlayerLastScene[friend.eChar] = PR_SCENE_DEAD
|
|
SAFE_AMBIENT_STORE_PLAYER_PED_INFO(friend.hPed) //STORE_PLAYER_PED_INFO(friend.hPed)
|
|
g_savedGlobals.sPlayerData.sInfo.sLastTimeActive[friend.eChar] = GET_CURRENT_TIMEOFDAY()
|
|
|
|
SET_PED_AS_NO_LONGER_NEEDED(friend.hPed)
|
|
|
|
//Private_AddPedToDeleteQueue(friend.hPed)
|
|
|
|
// Otherwise, store last known position and remove (delete now or add to queue)
|
|
ELSE
|
|
Private_ClearAmbFriendAttribs(group, friend)
|
|
|
|
IF bDelete
|
|
IF bStorePlayerPedInfoOnDelete
|
|
SAFE_AMBIENT_STORE_PLAYER_PED_INFO(friend.hPed) //STORE_PLAYER_PED_INFO(friend.hPed)
|
|
ENDIF
|
|
DELETE_PED(friend.hPed)
|
|
ELSE
|
|
Private_AddPedToDeleteQueue(friend.hPed)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ENDIF
|
|
|
|
ENDIF
|
|
|
|
// Reset all vars
|
|
Private_InitAmbFriend(friend, friend.eChar)
|
|
|
|
ENDPROC
|
|
|
|
PROC Private_UpdateAmbFriend(structAmbGroup& group, structAmbFriend& friend, structPedsForConversation& convPeds)
|
|
|
|
FLOAT fDist2 = 0.0
|
|
FLOAT fGround
|
|
PED_INDEX hAngryPed = NULL
|
|
|
|
//-- Handle instant shutdowns
|
|
IF REPLAY_SYSTEM_HAS_REQUESTED_A_SCRIPT_CLEANUP()
|
|
IF friend.eState <> AMBFRIEND_NULL
|
|
CPRINTLN(DEBUG_FRIENDS, "Private_UpdateAmbFriend(", GetLabel_enumCharacterList(friend.eChar), ") - Shutting down for playback replay")
|
|
Private_ReleaseAmbFriend(group, friend, TRUE, TRUE, FALSE)
|
|
ENDIF
|
|
EXIT
|
|
|
|
ELIF group.bOutroActive AND friend.eState <> AMBFRIEND_OUTRO
|
|
IF friend.eState <> AMBFRIEND_NULL
|
|
CPRINTLN(DEBUG_FRIENDS, "Private_UpdateAmbFriend(", GetLabel_enumCharacterList(friend.eChar), ") - Shutting down for outro")
|
|
Private_ReleaseAmbFriend(group, friend)
|
|
ENDIF
|
|
EXIT
|
|
|
|
// Alive checks
|
|
ELIF friend.eState <> AMBFRIEND_NULL AND friend.eState <> AMBFRIEND_PLAYER
|
|
|
|
IF IS_PED_INJURED(friend.hPed)
|
|
|
|
// Display fail reason
|
|
IF DOES_ENTITY_EXIST(friend.hPed) AND NOT IS_PED_INJURED(PLAYER_PED_ID())
|
|
VECTOR vPlayerPos = GET_ENTITY_COORDS(PLAYER_PED_ID())
|
|
VECTOR vFriendPos = GET_ENTITY_COORDS(friend.hPed, FALSE)
|
|
IF VDIST2(vPlayerPos, vFriendPos) < 150.0
|
|
// Get friend name
|
|
enumFriend eFriend = GET_FRIEND_FROM_CHAR(friend.eChar)
|
|
IF eFriend < MAX_FRIENDS
|
|
|
|
// Add fail reason to flow queue
|
|
ADD_HELP_WITH_SUBSTRING_TO_FLOW_QUEUE("FR_X_INJ_1m", g_sCharacterSheetAll[friend.eChar].label, FHP_VERY_HIGH, 0, 20000)
|
|
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// Start failed timer
|
|
enumFriend eFriend = GET_FRIEND_FROM_CHAR(friend.eChar)
|
|
CC_CommID eCommID = GET_COMM_ID_FOR_FRIEND_FAIL(eFriend)
|
|
|
|
START_FRIEND_FAIL_TIMER(eFriend, eCommID)
|
|
|
|
// Should the player get an angry text message from the hospital
|
|
IF NOT Private_CanAmbFriendBlank(friend)
|
|
IF eCommID != COMM_NONE
|
|
CC_CodeID eHospitalCID = Private_GetHospitalChargeCID(friend.hPed)
|
|
|
|
// Send angry text message, if allowed, and not already an angry message queued
|
|
IF eHospitalCID != CID_BLANK
|
|
IF NOT IS_COMMUNICATION_REGISTERED(eCommID)
|
|
OR GET_COMMUNICATION_STATUS(eCommID) = CS_ERROR
|
|
REGISTERED_FRIEND_TEXT_MESSAGE_TO_PLAYER(g_eDefaultPlayerChar, friend.eChar, FTM_FRIEND_HOSPITAL, FALSE, eHospitalCID, eCommID)
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
Private_ReleaseAmbFriend(group, friend, FALSE)
|
|
EXIT
|
|
|
|
ELIF friend.hPed = PLAYER_PED_ID()
|
|
Private_ReleaseAmbFriend(group, friend, FALSE, FALSE)
|
|
|
|
IF friend.eChar = g_eDefaultPlayerChar AND Private_GrabAmbFriendPed(group, friend, convPeds)
|
|
Private_SetAmbFriendState(group, friend, AMBFRIEND_PLAYER)
|
|
EXIT
|
|
ELSE
|
|
Private_SetAmbFriendState(group, friend, AMBFRIEND_NULL)
|
|
EXIT
|
|
ENDIF
|
|
|
|
ELIF Private_IsPedInDeleteQueue(friend.hPed)
|
|
CPRINTLN(DEBUG_FRIENDS, "Private_UpdateAmbFriend(", GetLabel_enumCharacterList(friend.eChar), ") - Ped (", NATIVE_TO_INT(friend.hPed), ") is in delete queue")
|
|
Private_ReleaseAmbFriend(group, friend, FALSE)
|
|
EXIT
|
|
|
|
ELIF NOT DOES_ENTITY_BELONG_TO_THIS_SCRIPT(friend.hPed) AND friend.eState <> AMBFRIEND_GREET_SAFEHOUSE AND friend.eState <> AMBFRIEND_GREET_OUTSIDE
|
|
CPRINTLN(DEBUG_FRIENDS, "Private_UpdateAmbFriend(", GetLabel_enumCharacterList(friend.eChar), ") - Ped (", NATIVE_TO_INT(friend.hPed), ") doesn't belong to script")
|
|
#IF IS_DEBUG_BUILD
|
|
IF NOT Private_IsEntityOwnedBy(friend.hPed, "friendActivity")
|
|
SCRIPT_ASSERT("Private_UpdateAmbFriend() - Ped doesn't belong to script")
|
|
ENDIF
|
|
#ENDIF
|
|
Private_ReleaseAmbFriend(group, friend, FALSE)
|
|
EXIT
|
|
|
|
ELIF friend.hPed <> g_sPlayerPedRequest.sSelectorPeds.pedID[GET_SELECTOR_SLOT_FROM_PLAYER_PED_ENUM(friend.eChar)]
|
|
CPRINTLN(DEBUG_FRIENDS, "Private_UpdateAmbFriend(", GetLabel_enumCharacterList(friend.eChar), ") - Ped (", NATIVE_TO_INT(friend.hPed), ") out of sync with selector (", NATIVE_TO_INT(g_sPlayerPedRequest.sSelectorPeds.pedID[GET_SELECTOR_SLOT_FROM_PLAYER_PED_ENUM(friend.eChar)]), ")")
|
|
SCRIPT_ASSERT("Private_UpdateAmbFriend() - Ped out of sync with selector")
|
|
Private_ReleaseAmbFriend(group, friend, FALSE)
|
|
EXIT
|
|
|
|
ELIF (IS_PED_FALLING(friend.hPed) OR IS_PED_IN_PARACHUTE_FREE_FALL(friend.hPed))
|
|
AND ((NOT HAS_COLLISION_LOADED_AROUND_ENTITY(friend.hPed)and NOT IS_PED_INJURED(friend.hPed)) OR NOT GET_GROUND_Z_FOR_3D_COORD(GET_ENTITY_COORDS(friend.hPed), fGround) OR fGround < -200.0)
|
|
|
|
CPRINTLN(DEBUG_FRIENDS, "Private_UpdateAmbFriend(", GetLabel_enumCharacterList(friend.eChar), ") - Ped (", NATIVE_TO_INT(friend.hPed), ") fallen through world?")
|
|
// SCRIPT_ASSERT("Private_UpdateAmbFriend() - Ped fallen through world?")
|
|
DELETE_PED(friend.hPed)
|
|
Private_ReleaseAmbFriend(group, friend, TRUE)
|
|
EXIT
|
|
|
|
ELIF NOT IS_PED_INJURED(PLAYER_PED_ID())
|
|
fDist2 = VDIST2(GET_ENTITY_COORDS(PLAYER_PED_ID()), GET_ENTITY_COORDS(friend.hPed))
|
|
|
|
IF fDist2 > 300.0*300.0
|
|
Private_ReleaseAmbFriend(group, friend, TRUE)
|
|
EXIT
|
|
ENDIF
|
|
|
|
ENDIF
|
|
|
|
IF group.bUpdateAfterSwitch
|
|
IF Private_CanAmbFriendBlank(friend)
|
|
Private_SetAmbFriendVulnerable(group, friend, TRUE)
|
|
ELSE
|
|
Private_SetAmbFriendVulnerable(group, friend, FALSE)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ENDIF
|
|
|
|
// Handle state
|
|
SWITCH friend.eState
|
|
|
|
//------------------------------------------------------------------------------------------------- AMBFRIEND_NULL
|
|
CASE AMBFRIEND_NULL
|
|
IF g_bAllowAmbientFriendLaunching
|
|
// AND (NOT IS_CURRENTLY_ON_MISSION_OF_ANY_TYPE() OR IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_FRIEND_ACTIVITY))
|
|
|
|
IF Private_GrabAmbFriendPed(group, friend, convPeds)
|
|
|
|
IF friend.hPed = PLAYER_PED_ID()
|
|
Private_SetAmbFriendState(group, friend, AMBFRIEND_PLAYER)
|
|
|
|
|
|
ELIF friend.eGrabMode = AMBGRAB_SAFEHOUSE_TRAILER
|
|
Private_SetAmbFriendState(group, friend, AMBFRIEND_GREET_SAFEHOUSE)
|
|
|
|
ELIF friend.eGrabMode = AMBGRAB_SAFEHOUSE_DRUNK
|
|
Private_SetAmbFriendState(group, friend, AMBFRIEND_GREET_SAFEHOUSE)
|
|
|
|
ELIF friend.eGrabMode = AMBGRAB_SAFEHOUSE_OUTSIDE
|
|
Private_SetAmbFriendState(group, friend, AMBFRIEND_GREET_OUTSIDE)
|
|
|
|
|
|
ELIF friend.eGrabMode = AMBGRAB_TRANSFER_REJECTED
|
|
Private_SetAmbFriendState(group, friend, AMBFRIEND_DISMISSED)
|
|
Private_SetAmbFriendDismissMode(friend, AMBMODE_REJECTED, TRUE)
|
|
friend.eGrabMode = AMBGRAB_NORMAL
|
|
|
|
ELIF friend.eGrabMode = AMBGRAB_TRANSFER_WANDER
|
|
Private_SetAmbFriendState(group, friend, AMBFRIEND_DISMISSED)
|
|
Private_SetAmbFriendDismissMode(friend, AMBMODE_WANDER, TRUE)
|
|
friend.eGrabMode = AMBGRAB_NORMAL
|
|
|
|
ELIF friend.eGrabMode = AMBGRAB_TRANSFER_FLEE
|
|
Private_SetAmbFriendState(group, friend, AMBFRIEND_DISMISSED)
|
|
Private_SetAmbFriendDismissMode(friend, AMBMODE_FLEE, TRUE, PLAYER_PED_ID())
|
|
friend.eGrabMode = AMBGRAB_NORMAL
|
|
|
|
|
|
ELIF Private_CanAmbFriendGreet(group, friend)
|
|
|
|
IF Private_CanAmbFriendBlank(friend)
|
|
Private_DismissAmbFriend(group, friend)
|
|
Private_SetAmbFriendState(group, friend, AMBFRIEND_DISMISSED)
|
|
ELSE
|
|
Private_SetAmbFriendState(group, friend, AMBFRIEND_GREET)
|
|
ENDIF
|
|
|
|
ELIF Private_IsAmbFriendDismissedByAnyone(friend)
|
|
Private_SetAmbFriendState(group, friend, AMBFRIEND_DISMISSED)
|
|
|
|
ELSE
|
|
Private_SetAmbFriendState(group, friend, AMBFRIEND_IDLE)
|
|
|
|
ENDIF
|
|
|
|
ENDIF
|
|
|
|
ENDIF
|
|
BREAK
|
|
|
|
//------------------------------------------------------------------------------------------------- AMBFRIEND_PLAYER
|
|
CASE AMBFRIEND_PLAYER
|
|
IF IS_PED_INJURED(friend.hPed)
|
|
Private_SetAmbFriendState(group, friend, AMBFRIEND_NULL)
|
|
|
|
ELIF friend.hPed <> PLAYER_PED_ID()
|
|
|
|
IF NOT Private_GrabAmbFriendPed(group, friend, convPeds)
|
|
Private_SetAmbFriendState(group, friend, AMBFRIEND_NULL)
|
|
|
|
|
|
ELIF friend.eGrabMode = AMBGRAB_TRANSFER_REJECTED
|
|
Private_SetAmbFriendState(group, friend, AMBFRIEND_DISMISSED)
|
|
Private_SetAmbFriendDismissMode(friend, AMBMODE_REJECTED, TRUE)
|
|
friend.eGrabMode = AMBGRAB_NORMAL
|
|
|
|
ELIF friend.eGrabMode = AMBGRAB_TRANSFER_WANDER
|
|
Private_SetAmbFriendState(group, friend, AMBFRIEND_DISMISSED)
|
|
Private_SetAmbFriendDismissMode(friend, AMBMODE_WANDER, TRUE)
|
|
friend.eGrabMode = AMBGRAB_NORMAL
|
|
|
|
ELIF friend.eGrabMode = AMBGRAB_TRANSFER_FLEE
|
|
Private_SetAmbFriendState(group, friend, AMBFRIEND_DISMISSED)
|
|
Private_SetAmbFriendDismissMode(friend, AMBMODE_FLEE, TRUE, PLAYER_PED_ID())
|
|
friend.eGrabMode = AMBGRAB_NORMAL
|
|
|
|
|
|
ELIF Private_CanAmbFriendGreet(group, friend)
|
|
|
|
IF Private_CanAmbFriendBlank(friend)
|
|
Private_DismissAmbFriend(group, friend)
|
|
Private_SetAmbFriendState(group, friend, AMBFRIEND_DISMISSED)
|
|
ELSE
|
|
Private_SetAmbFriendState(group, friend, AMBFRIEND_GREET)
|
|
ENDIF
|
|
|
|
ELIF Private_IsAmbFriendDismissed(friend)
|
|
Private_SetAmbFriendState(group, friend, AMBFRIEND_DISMISSED)
|
|
|
|
ELSE
|
|
Private_SetAmbFriendState(group, friend, AMBFRIEND_IDLE)
|
|
|
|
ENDIF
|
|
|
|
ELIF GET_FRAME_COUNT() % 30 = 0
|
|
IF IS_PED_SITTING_IN_ANY_VEHICLE(friend.hPed)
|
|
VEHICLE_INDEX hCurVehicle
|
|
hCurVehicle = GET_VEHICLE_PED_IS_IN(friend.hPed)
|
|
IF IS_VEHICLE_DRIVEABLE(hCurVehicle) AND GET_PED_IN_VEHICLE_SEAT(hCurVehicle, VS_DRIVER) = friend.hPed
|
|
friend.hVehicle = hCurVehicle
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
BREAK
|
|
|
|
//------------------------------------------------------------------------------------------------- AMBFRIEND_IDLE
|
|
CASE AMBFRIEND_IDLE
|
|
|
|
IF Private_IsAmbFriendDismissed(friend)
|
|
Private_SetAmbFriendState(group, friend, AMBFRIEND_DISMISSED)
|
|
|
|
ELIF Private_CanAmbFriendGreet(group, friend)
|
|
|
|
IF Private_CanAmbFriendBlank(friend, TRUE)
|
|
Private_DismissAmbFriend(group, friend)
|
|
Private_SetAmbFriendState(group, friend, AMBFRIEND_DISMISSED)
|
|
ELSE
|
|
Private_SetAmbFriendState(group, friend, AMBFRIEND_GREET)
|
|
ENDIF
|
|
|
|
ELIF Private_HasPlayerAttackedAmbFriend(friend)
|
|
Private_DismissAmbFriend(group, friend)
|
|
Private_SetAmbFriendThreatResponse(friend, TRUE, PLAYER_PED_ID())
|
|
|
|
ELIF Private_HasAnyoneAttackedAmbFriend(friend, FALSE, hAngryPed)
|
|
Private_SetAmbFriendState(group, friend, AMBFRIEND_DISMISSED) // Only set state to dimiss, don't update timer (want dimiss to end if player meets them when flee is done)
|
|
Private_SetAmbFriendDismissMode(friend, AMBMODE_FLEE, FALSE, hAngryPed)
|
|
|
|
// ELIF Private_HasPlayerThreatenedAmbFriend(friend)
|
|
// Private_DismissAmbFriend(group, friend)
|
|
|
|
ELSE
|
|
Private_UpdateAmbFriend_Idle(group, friend)
|
|
|
|
ENDIF
|
|
|
|
BREAK
|
|
|
|
//------------------------------------------------------------------------------------------------- AMBFRIEND_GREET
|
|
CASE AMBFRIEND_GREET
|
|
|
|
IF Private_IsAmbFriendDismissed(friend)
|
|
Private_SetAmbFriendState(group, friend, AMBFRIEND_DISMISSED)
|
|
|
|
ELIF group.iGreetCount > 1 AND fDist2 > 35.0*35.0
|
|
Private_DismissAmbFriend(group, friend)
|
|
|
|
ELIF group.iGreetCount = 1 AND fDist2 > 25.0*25.0
|
|
Private_DismissAmbFriend(group, friend)
|
|
|
|
ELIF Private_HasPlayerAttackedAmbFriend(friend)
|
|
Private_DismissAmbFriend(group, friend)
|
|
Private_SetAmbFriendThreatResponse(friend, TRUE, PLAYER_PED_ID())
|
|
|
|
ELIF Private_HasAnyoneAttackedAmbFriend(friend, FALSE, hAngryPed)
|
|
Private_DismissAmbFriend(group, friend)
|
|
Private_SetAmbFriendDismissMode(friend, AMBMODE_FLEE, FALSE, hAngryPed)
|
|
|
|
ELIF Private_HasPlayerThreatenedAmbFriend(group, friend)
|
|
Private_DismissAmbFriend(group, friend)
|
|
Private_SetAmbFriendDismissMode(friend, AMBMODE_WANDER, TRUE)
|
|
|
|
ELIF Private_HasPlayerStolenCarAmbFriend(group, friend)
|
|
Private_DismissAmbFriend(group, friend)
|
|
Private_SetAmbFriendDismissMode(friend, AMBMODE_JACKED, TRUE)
|
|
|
|
ELIF IS_PED_RAGDOLL(friend.hPed)
|
|
Private_DismissAmbFriend(group, friend)
|
|
|
|
ELSE
|
|
Private_UpdateAmbFriend_Greet(friend)
|
|
|
|
ENDIF
|
|
|
|
BREAK
|
|
|
|
//------------------------------------------------------------------------------------------------- AMBFRIEND_GREET_SAFEHOUSE
|
|
CASE AMBFRIEND_GREET_SAFEHOUSE
|
|
|
|
IF GET_INTERIOR_FROM_ENTITY(PLAYER_PED_ID()) = NULL
|
|
Private_DismissAmbFriend(group, friend)
|
|
|
|
ELSE
|
|
Private_UpdateAmbFriend_Greet(friend, FALSE)
|
|
|
|
ENDIF
|
|
|
|
BREAK
|
|
|
|
//------------------------------------------------------------------------------------------------- AMBFRIEND_GREET_OUTSIDE
|
|
CASE AMBFRIEND_GREET_OUTSIDE
|
|
|
|
IF GET_INTERIOR_FROM_ENTITY(PLAYER_PED_ID()) <> NULL
|
|
OR fDist2 > 20.0*20.0
|
|
Private_DismissAmbFriend(group, friend)
|
|
|
|
ELSE
|
|
Private_UpdateAmbFriend_Greet(friend, FALSE)
|
|
|
|
ENDIF
|
|
|
|
BREAK
|
|
|
|
//------------------------------------------------------------------------------------------------- AMBFRIEND_DISMISSED
|
|
CASE AMBFRIEND_DISMISSED
|
|
|
|
IF Private_CanAmbFriendGreet(group, friend)
|
|
Private_SetAmbFriendState(group, friend, AMBFRIEND_GREET)
|
|
|
|
ELSE
|
|
IF Private_UpdateAmbFriend_Dismissed(group, friend, convPeds, fDist2)
|
|
|
|
IF Private_TryStartAmbFriendOutro(group, friend)
|
|
Private_SetAmbFriendState(group, friend, AMBFRIEND_OUTRO)
|
|
ENDIF
|
|
|
|
ENDIF
|
|
ENDIF
|
|
|
|
BREAK
|
|
|
|
//------------------------------------------------------------------------------------------------- AMBFRIEND_OUTRO
|
|
CASE AMBFRIEND_OUTRO
|
|
IF Private_UpdateAmbFriend_Outro(group, friend)
|
|
Private_ReleaseAmbFriend(group, friend, TRUE)
|
|
ENDIF
|
|
BREAK
|
|
|
|
ENDSWITCH
|
|
|
|
ENDPROC
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------------------------------------------------------------------------------
|
|
// AmbConv
|
|
//-------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
PROC Private_SetAmbConvState(structAmbGroup& group, enumAmbConvState eState)
|
|
IF group.eConvState <> eState
|
|
CPRINTLN(DEBUG_FRIENDS, "Private_SetAmbConvState(", GetLabel_enumAmbConvState(eState), ")")
|
|
|
|
// Clear context button help
|
|
IF group.hConvInput <> NEW_CONTEXT_INTENTION
|
|
RELEASE_CONTEXT_INTENTION(group.hConvInput)
|
|
group.hConvInput = NEW_CONTEXT_INTENTION
|
|
ENDIF
|
|
|
|
// Set new state
|
|
group.eConvState = eState
|
|
group.bInitConvState = TRUE
|
|
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
PROC Private_StopAmbConv(structAmbGroup& group, BOOL bFinishCurrentLine = FALSE)
|
|
|
|
// Stop conversation
|
|
IF group.eConvState <> AMBCONV_NULL
|
|
STOP_SCRIPTED_CONVERSATION(bFinishCurrentLine)
|
|
Private_SetAmbConvState(group, AMBCONV_NULL)
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
FUNC BOOL Private_IsMichaelTrevorSafehouse(structAmbFriend& friend)
|
|
#if USE_CLF_DLC
|
|
unused_parameter(friend)
|
|
#endif
|
|
#if USE_NRM_DLC
|
|
unused_parameter(friend)
|
|
#endif
|
|
#if not USE_CLF_DLC
|
|
#if not USE_NRM_DLC
|
|
IF Is_Savehouse_Respawn_Available(SAVEHOUSE_MICHAEL_CS)
|
|
|
|
IF (g_eDefaultPlayerChar = CHAR_MICHAEL AND friend.eChar = CHAR_TREVOR)
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
IF (g_eDefaultPlayerChar = CHAR_TREVOR AND friend.eChar = CHAR_MICHAEL)
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
ENDIF
|
|
#endif
|
|
#endif
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
FUNC enumFriendActivityPhrase Private_GetAmbConvGreetPhrase(structAmbGroup& group, BOOL bIsSafehouse = FALSE)
|
|
IF bIsSafeHouse
|
|
|
|
RETURN FAP_AMBIENT_TRAILER_1r
|
|
|
|
// IF Private_IsAmbFriendContactRecent(group.mFriends[group.eConvChar])
|
|
// RETURN FAP_AMBIENT_TRAILER_1r
|
|
// ELSE
|
|
// RETURN FAP_AMBIENT_TRAILER_1
|
|
// ENDIF
|
|
|
|
ELSE
|
|
|
|
IF Private_IsAmbFriendContactRecent(group.mFriends[group.eConvChar])
|
|
RETURN FAP_AMBIENT_HELLO_RECENT
|
|
ELSE
|
|
RETURN FAP_AMBIENT_HELLO_OK
|
|
ENDIF
|
|
|
|
ENDIF
|
|
|
|
ENDFUNC
|
|
|
|
FUNC enumFriendActivityPhrase Private_GetAmbConvPooPhrase()
|
|
INT iRandom = GET_RANDOM_INT_IN_RANGE(0, 3)
|
|
IF iRandom = 0 RETURN FAP_AMBIENT_POO_1a
|
|
ELIF iRandom = 1 RETURN FAP_AMBIENT_POO_1b
|
|
ELSE RETURN FAP_AMBIENT_POO_1c
|
|
ENDIF
|
|
ENDFUNC
|
|
|
|
FUNC BOOL Private_PlayAmbConvState(structAmbGroup& group, structPedsForConversation& convPeds, enumCharacterList ePlayer, enumCharacterList eFriend, enumFriendActivityPhrase ePhrase, BOOL bInterruptDialogue = TRUE)
|
|
|
|
TEXT_LABEL tBlock, tRoot
|
|
|
|
IF group.bInitConvState
|
|
IF bInterruptDialogue OR NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
|
|
IF NOT Private_GetFriendActivityPhrase(ePlayer, eFriend, ePhrase, tBlock, tRoot)
|
|
OR CREATE_CONVERSATION(convPeds, tBlock, tRoot, CONV_PRIORITY_AMBIENT_HIGH)
|
|
group.bInitConvState = FALSE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ELIF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
|
|
ENDFUNC
|
|
|
|
FUNC BOOL Private_PlayAmbConvChat(structAmbGroup& group, structPedsForConversation& convPeds, enumCharacterList ePlayer, enumCharacterList eFriend, INT iIndex, enumAmbChatBitIndex eBitIndex)
|
|
|
|
TEXT_LABEL tBlock, tRoot
|
|
|
|
IF group.bInitConvState
|
|
IF NOT Private_GetAmbFriendChat(ePlayer, eFriend, iIndex, tBlock, tRoot)
|
|
OR CREATE_CONVERSATION(convPeds, tBlock, tRoot, CONV_PRIORITY_AMBIENT_HIGH)
|
|
CPRINTLN(DEBUG_FRIENDS, "Private_PlayAmbConvChat() - Set g_SavedGlobals.sFriendsData.g_iAmbChatBitfield / bit ", ENUM_TO_INT(eBitIndex))
|
|
SET_BIT(g_SavedGlobals.sFriendsData.g_iAmbChatBitfield, ENUM_TO_INT(eBitIndex))
|
|
group.bInitConvState = FALSE
|
|
ENDIF
|
|
|
|
ELIF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
|
|
ENDFUNC
|
|
|
|
PROC Private_StartAmbConv(structAmbGroup& group)
|
|
|
|
// Ask each friend in greet state to request a conversation...
|
|
enumAmbConvState eRequestState = AMBCONV_NULL
|
|
enumCharacterList eRequestChar = NO_CHARACTER
|
|
|
|
enumCharacterList eLoopChar
|
|
REPEAT NUM_OF_PLAYABLE_PEDS eLoopChar
|
|
IF group.mFriends[eLoopChar].eState = AMBFRIEND_GREET
|
|
OR group.mFriends[eLoopChar].eState = AMBFRIEND_GREET_SAFEHOUSE
|
|
OR group.mFriends[eLoopChar].eState = AMBFRIEND_GREET_OUTSIDE
|
|
enumAmbConvState eThisRequest = Private_GetAmbFriendConvRequest(group.mFriends[eLoopChar])
|
|
|
|
IF eRequestState = AMBCONV_NULL
|
|
OR eRequestState > eThisRequest
|
|
eRequestState = eThisRequest
|
|
eRequestChar = group.mFriends[eLoopChar].eChar
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
// If request is valid...
|
|
IF eRequestState <> AMBCONV_NULL
|
|
AND IS_PLAYER_PED_PLAYABLE(eRequestChar)
|
|
|
|
// Start highest priority conversation
|
|
Private_SetAmbConvState(group, eRequestState)
|
|
group.eConvChar = eRequestChar
|
|
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
PROC Private_UpdateAmbConv(structAmbGroup& group, structPedsForConversation& convPeds)
|
|
|
|
enumFriendConnection eConnection
|
|
|
|
// Process conversation state
|
|
SWITCH group.eConvState
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------------- AMBCONV_SAFEHOUSE_TRAILER1
|
|
CASE AMBCONV_SAFEHOUSE_TRAILER1
|
|
IF (Private_GET_FRIEND_LAST_CONTACT_TIME(g_eDefaultPlayerChar, group.eConvChar) > 2.0*60.0 OR Private_GET_FRIEND_LAST_CONTACT_TYPE(g_eDefaultPlayerChar, group.eConvChar) <> FRIEND_CONTACT_DISMISSED)
|
|
Private_SetAmbConvState(group, AMBCONV_SAFEHOUSE_TRAILER2)
|
|
ELSE
|
|
Private_SetAmbConvState(group, AMBCONV_SAFEHOUSE_TRAILER3)
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE AMBCONV_SAFEHOUSE_TRAILER2
|
|
IF Private_PlayAmbConvState(group, convPeds, g_eDefaultPlayerChar, group.eConvChar, FAP_AMBIENT_TRAILER_1r, FALSE) // "Oh, it's you again"
|
|
Private_SetAmbConvState(group, AMBCONV_SAFEHOUSE_TRAILER3)
|
|
group.bHasSaidHello = TRUE
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE AMBCONV_SAFEHOUSE_TRAILER3
|
|
// Empty
|
|
BREAK
|
|
|
|
// NB: Trailer conv works differently to all the others, it holds on at the end, and relies on the state (AMBFRIEND_GREET_SAFEHOUSE) to end everything when the player leaves the trailer/area
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------------- AMBCONV_MFSHOWROOM_HELLO
|
|
CASE AMBCONV_MFSHOWROOM_HELLO
|
|
IF group.bHasSaidHello
|
|
OR Private_PlayAmbConvState(group, convPeds, g_eDefaultPlayerChar, group.eConvChar, FAP_AMBIENT_HELLO_OK) // "Hello!"
|
|
Private_SetAmbConvState(group, AMBCONV_MFSHOWROOM_CHAT)
|
|
group.bHasSaidHello = TRUE
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE AMBCONV_MFSHOWROOM_CHAT
|
|
IF Private_PlayAmbConvChat(group, convPeds, g_eDefaultPlayerChar, group.eConvChar, 0, AMBCHATBIT_MFSHOWROOM) // [showroom chat]
|
|
Private_DismissAmbFriend(group, group.mFriends[group.eConvChar])
|
|
ENDIF
|
|
BREAK
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------------- AMBCONV_MTFALLOUT_HELLO
|
|
CASE AMBCONV_MTFALLOUT_HELLO
|
|
IF group.bHasSaidHello
|
|
OR Private_PlayAmbConvState(group, convPeds, g_eDefaultPlayerChar, group.eConvChar, FAP_AMBIENT_HELLO_IRATE) // "Hello asshole"
|
|
Private_SetAmbConvState(group, AMBCONV_MTFALLOUT_CHAT)
|
|
group.bHasSaidHello = TRUE
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE AMBCONV_MTFALLOUT_CHAT
|
|
Private_DismissAmbGroup_IfSecondary(group)
|
|
|
|
IF Private_PlayAmbConvChat(group, convPeds, g_eDefaultPlayerChar, group.eConvChar, 0, AMBCHATBIT_MTFALLOUT) // [fallout chat]
|
|
Private_DismissAmbFriend(group, group.mFriends[group.eConvChar])
|
|
ENDIF
|
|
BREAK
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------------- AMBCONV_KILLEDM_HELLO
|
|
CASE AMBCONV_KILLEDM_HELLO
|
|
IF group.bHasSaidHello
|
|
OR Private_PlayAmbConvState(group, convPeds, g_eDefaultPlayerChar, group.eConvChar, FAP_AMBIENT_HELLO_IRATE) // "Hello asshole"
|
|
Private_SetAmbConvState(group, AMBCONV_KILLEDM_CHAT)
|
|
group.bHasSaidHello = TRUE
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE AMBCONV_KILLEDM_CHAT
|
|
IF Private_PlayAmbConvChat(group, convPeds, g_eDefaultPlayerChar, group.eConvChar, 0, AMBCHATBIT_KILLEDM) // [killed M chat]
|
|
Private_DismissAmbFriend(group, group.mFriends[group.eConvChar])
|
|
ENDIF
|
|
BREAK
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------------- AMBCONV_KILLEDT_HELLO
|
|
CASE AMBCONV_KILLEDT_HELLO
|
|
IF group.bHasSaidHello
|
|
OR Private_PlayAmbConvState(group, convPeds, g_eDefaultPlayerChar, group.eConvChar, FAP_AMBIENT_HELLO_IRATE) // "Hello asshole"
|
|
Private_SetAmbConvState(group, AMBCONV_KILLEDT_CHAT)
|
|
group.bHasSaidHello = TRUE
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE AMBCONV_KILLEDT_CHAT
|
|
IF Private_PlayAmbConvChat(group, convPeds, g_eDefaultPlayerChar, group.eConvChar, 1, AMBCHATBIT_KILLEDT) // [killed T chat]
|
|
Private_DismissAmbFriend(group, group.mFriends[group.eConvChar])
|
|
ENDIF
|
|
BREAK
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------------- AMBCONV_ANGRY_HELLO
|
|
CASE AMBCONV_ANGRY_HELLO
|
|
IF group.bHasSaidHello
|
|
OR Private_PlayAmbConvState(group, convPeds, g_eDefaultPlayerChar, group.eConvChar, FAP_AMBIENT_HELLO_IRATE) // "Hello asshole"
|
|
Private_SetAmbConvState(group, AMBCONV_ANGRY_GOODBYE)
|
|
group.bHasSaidHello = TRUE
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE AMBCONV_ANGRY_GOODBYE
|
|
IF Private_PlayAmbConvState(group, convPeds, group.eConvChar, g_eDefaultPlayerChar, FAP_AMBIENT_GOODBYE_IRATE) // "Fuck you"
|
|
Private_DismissAmbFriend(group, group.mFriends[group.eConvChar])
|
|
ENDIF
|
|
BREAK
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------------- AMBCONV_OFFER_HELLO
|
|
CASE AMBCONV_OFFER_HELLO
|
|
Private_DismissAmbGroup_IfAngry(group)
|
|
|
|
IF group.bHasSaidHello
|
|
OR group.bHasJoined
|
|
OR Private_PlayAmbConvState(group, convPeds, g_eDefaultPlayerChar, group.eConvChar, Private_GetAmbConvGreetPhrase(group)) // "Hello" / "Hello again"
|
|
Private_SetAmbConvState(group, AMBCONV_OFFER_ASK)
|
|
group.bHasSaidHello = TRUE
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE AMBCONV_OFFER_HELLO_HOME
|
|
Private_DismissAmbGroup_IfAngry(group)
|
|
|
|
IF NOT Private_IsMichaelTrevorSafehouse(group.mFriends[group.eConvChar])
|
|
IF group.bHasSaidHello
|
|
OR group.bHasJoined
|
|
OR Private_PlayAmbConvState(group, convPeds, group.eConvChar, g_eDefaultPlayerChar, Private_GetAmbConvGreetPhrase(group)) // "Hello" / "Hello again" (reversed speaker/listener)
|
|
Private_SetAmbConvState(group, AMBCONV_OFFER_ASK)
|
|
group.bHasSaidHello = TRUE
|
|
ENDIF
|
|
ELSE
|
|
IF group.bHasSaidHello
|
|
OR group.bHasJoined
|
|
OR Private_PlayAmbConvState(group, convPeds, g_eDefaultPlayerChar, group.eConvChar, Private_GetAmbConvGreetPhrase(group, TRUE)) // "Hello" / "Hello again" (house version)
|
|
Private_SetAmbConvState(group, AMBCONV_OFFER_ASK)
|
|
group.bHasSaidHello = TRUE
|
|
ENDIF
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE AMBCONV_OFFER_ASK
|
|
Private_DismissAmbGroup_IfAngry(group)
|
|
|
|
IF group.bHasJoined
|
|
OR Private_PlayAmbConvState(group, convPeds, g_eDefaultPlayerChar, group.eConvChar, FAP_AMBIENT_OFFER_QUESTION) // "Want to get a drink?"
|
|
RESTART_TIMER_NOW(group.mOfferTimer)
|
|
|
|
IF GET_ACTIVE_CONNECTIONS(eConnection) = 0
|
|
Private_SetAmbConvState(group, AMBCONV_OFFER_INPUT)
|
|
ELSE
|
|
Private_SetAmbConvState(group, AMBCONV_OFFER_LAUNCH1)
|
|
ENDIF
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE AMBCONV_OFFER_INPUT
|
|
Private_DismissAmbGroup_IfAngry(group)
|
|
|
|
IF NOT TIMER_DO_WHEN_READY(group.mOfferTimer, 30.0)
|
|
IF group.hConvInput = NEW_CONTEXT_INTENTION // [wait for input]
|
|
IF group.eConvChar = CHAR_MICHAEL
|
|
REGISTER_CONTEXT_INTENTION(group.hConvInput, CP_MAXIMUM_PRIORITY, "FR_PK_AMB_M")
|
|
ELIF group.eConvChar = CHAR_FRANKLIN
|
|
REGISTER_CONTEXT_INTENTION(group.hConvInput, CP_MAXIMUM_PRIORITY, "FR_PK_AMB_F")
|
|
ELSE
|
|
REGISTER_CONTEXT_INTENTION(group.hConvInput, CP_MAXIMUM_PRIORITY, "FR_PK_AMB_T")
|
|
ENDIF
|
|
|
|
ELIF HAS_CONTEXT_BUTTON_TRIGGERED(group.hConvInput, FALSE)
|
|
Private_SetAmbConvState(group, AMBCONV_OFFER_YES1)
|
|
|
|
ELIF IS_CONTEXT_INTENTION_HELP_DISPLAYING(group.hConvInput) AND IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_CONTEXT_SECONDARY)
|
|
Private_SetAmbConvState(group, AMBCONV_OFFER_NO1)
|
|
|
|
ENDIF
|
|
|
|
SET_INPUT_EXCLUSIVE(PLAYER_CONTROL, INPUT_CONTEXT_SECONDARY)
|
|
ELSE
|
|
Private_SetAmbConvState(group, AMBCONV_OFFER_NO2)
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE AMBCONV_OFFER_NO1
|
|
IF Private_PlayAmbConvState(group, convPeds, g_eDefaultPlayerChar, group.eConvChar, FAP_AMBIENT_OFFER_NO1) // "No"
|
|
Private_SetAmbConvState(group, AMBCONV_OFFER_NO2)
|
|
ENDIF
|
|
|
|
Private_DismissAmbGroup_IfAngry(group)
|
|
BREAK
|
|
|
|
CASE AMBCONV_OFFER_NO2
|
|
IF Private_PlayAmbConvState(group, convPeds, g_eDefaultPlayerChar, group.eConvChar, FAP_AMBIENT_GOODBYE_OK) // "Ok, see you later."
|
|
Private_DismissAmbFriend(group, group.mFriends[group.eConvChar])
|
|
Private_DismissAmbGroup_IfOffer(group)
|
|
ENDIF
|
|
|
|
Private_DismissAmbGroup_IfAngry(group)
|
|
BREAK
|
|
|
|
CASE AMBCONV_OFFER_YES1
|
|
Private_DismissAmbGroup_IfAngry(group)
|
|
|
|
IF Private_PlayAmbConvState(group, convPeds, g_eDefaultPlayerChar, group.eConvChar, FAP_AMBIENT_OFFER_YES1) // "Yes"
|
|
Private_SetAmbConvState(group, AMBCONV_OFFER_YES2)
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE AMBCONV_OFFER_YES2
|
|
Private_DismissAmbGroup_IfAngry(group)
|
|
|
|
IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
|
|
OR Private_PlayAmbConvState(group, convPeds, g_eDefaultPlayerChar, group.eConvChar, FAP_AMBIENT_OFFER_YES2) // "Get a car"
|
|
Private_SetAmbConvState(group, AMBCONV_OFFER_LAUNCH1)
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE AMBCONV_OFFER_LAUNCH1
|
|
Private_DismissAmbGroup_IfAngry(group)
|
|
|
|
IF GET_CONNECTION(g_eDefaultPlayerChar, group.eConvChar, eConnection) // [request launch]
|
|
AND GET_CONNECTION_STATE(eConnection) = FC_STATE_ContactWait
|
|
SET_CONNECTION_STATE(eConnection, FC_STATE_Init)
|
|
SET_CONNECTION_MODE(eConnection, FC_MODE_Ambient)
|
|
group.bHasJoined = TRUE
|
|
ENDIF
|
|
|
|
Private_SetAmbConvState(group, AMBCONV_OFFER_LAUNCH2)
|
|
BREAK
|
|
|
|
CASE AMBCONV_OFFER_LAUNCH2
|
|
Private_DismissAmbGroup_IfAngry(group)
|
|
|
|
IF NOT GET_CONNECTION(g_eDefaultPlayerChar, group.eConvChar, eConnection) // [wait for launch, dismiss on fail]
|
|
OR (GET_CONNECTION_STATE(eConnection) <> FC_STATE_Init AND GET_CONNECTION_STATE(eConnection) <> FC_STATE_Active)
|
|
Private_DismissAmbFriend(group, group.mFriends[group.eConvChar])
|
|
ENDIF
|
|
BREAK
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------------- AMBCONV_MISBLOCK_HELLO
|
|
CASE AMBCONV_MISBLOCK_HELLO
|
|
IF group.bHasSaidHello
|
|
OR Private_PlayAmbConvState(group, convPeds, g_eDefaultPlayerChar, group.eConvChar, Private_GetAmbConvGreetPhrase(group)) // "Hello" / "Hello again"
|
|
Private_SetAmbConvState(group, AMBCONV_MISBLOCK_BUSY)
|
|
group.bHasSaidHello = TRUE
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE AMBCONV_MISBLOCK_HELLO_HOME
|
|
IF NOT Private_IsMichaelTrevorSafehouse(group.mFriends[group.eConvChar])
|
|
IF group.bHasSaidHello
|
|
OR Private_PlayAmbConvState(group, convPeds, group.eConvChar, g_eDefaultPlayerChar, Private_GetAmbConvGreetPhrase(group)) // "Hello" / "Hello again" (reversed speaker/listener)
|
|
Private_SetAmbConvState(group, AMBCONV_MISBLOCK_BUSY)
|
|
group.bHasSaidHello = TRUE
|
|
ENDIF
|
|
ELSE
|
|
IF group.bHasSaidHello
|
|
OR Private_PlayAmbConvState(group, convPeds, g_eDefaultPlayerChar, group.eConvChar, Private_GetAmbConvGreetPhrase(group, TRUE)) // "Hello" / "Hello again" (house version)
|
|
Private_SetAmbConvState(group, AMBCONV_MISBLOCK_BUSY)
|
|
group.bHasSaidHello = TRUE
|
|
ENDIF
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE AMBCONV_MISBLOCK_BUSY
|
|
IF Private_PlayAmbConvState(group, convPeds, g_eDefaultPlayerChar, group.eConvChar, FAP_AMBIENT_BLOCKED_MISSION) // "We got stuff to do."
|
|
Private_SetAmbConvState(group, AMBCONV_MISBLOCK_GOODBYE)
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE AMBCONV_MISBLOCK_GOODBYE
|
|
IF Private_PlayAmbConvState(group, convPeds, group.eConvChar, g_eDefaultPlayerChar, FAP_AMBIENT_GOODBYE_OK) // "Ok, see you later."
|
|
Private_DismissAmbGroup_IfBlocked(group)
|
|
ENDIF
|
|
BREAK
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------------- AMBCONV_DEFBLOCK_HELLO
|
|
CASE AMBCONV_DEFBLOCK_HELLO
|
|
IF group.bHasSaidHello
|
|
OR Private_PlayAmbConvState(group, convPeds, g_eDefaultPlayerChar, group.eConvChar, Private_GetAmbConvGreetPhrase(group)) // "Hello" / "Hello again"
|
|
Private_SetAmbConvState(group, AMBCONV_DEFBLOCK_BUSY)
|
|
group.bHasSaidHello = TRUE
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE AMBCONV_DEFBLOCK_HELLO_HOME
|
|
IF NOT Private_IsMichaelTrevorSafehouse(group.mFriends[group.eConvChar])
|
|
IF group.bHasSaidHello
|
|
OR Private_PlayAmbConvState(group, convPeds, group.eConvChar, g_eDefaultPlayerChar, Private_GetAmbConvGreetPhrase(group)) // "Hello" / "Hello again" (reversed speaker/listener)
|
|
Private_SetAmbConvState(group, AMBCONV_DEFBLOCK_BUSY)
|
|
group.bHasSaidHello = TRUE
|
|
ENDIF
|
|
ELSE
|
|
IF group.bHasSaidHello
|
|
OR Private_PlayAmbConvState(group, convPeds, g_eDefaultPlayerChar, group.eConvChar, Private_GetAmbConvGreetPhrase(group, TRUE)) // "Hello" / "Hello again" (house version)
|
|
Private_SetAmbConvState(group, AMBCONV_DEFBLOCK_BUSY)
|
|
group.bHasSaidHello = TRUE
|
|
ENDIF
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE AMBCONV_DEFBLOCK_BUSY
|
|
IF Private_PlayAmbConvState(group, convPeds, g_eDefaultPlayerChar, group.eConvChar, FAP_AMBIENT_BLOCKED_OK) // "I'm busy."
|
|
Private_SetAmbConvState(group, AMBCONV_DEFBLOCK_GOODBYE)
|
|
ENDIF
|
|
BREAK
|
|
|
|
CASE AMBCONV_DEFBLOCK_GOODBYE
|
|
IF Private_PlayAmbConvState(group, convPeds, group.eConvChar, g_eDefaultPlayerChar, FAP_AMBIENT_GOODBYE_OK) // "Ok, see you later."
|
|
Private_DismissAmbGroup_IfBlocked(group)
|
|
ENDIF
|
|
BREAK
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------------- END
|
|
DEFAULT
|
|
CPRINTLN(DEBUG_FRIENDS, "Private_UpdateAmbConv() - Unhandled state: ", GetLabel_enumAmbConvState(group.eConvState))
|
|
SCRIPT_ASSERT("Private_UpdateAmbConv() - Unhandled state")
|
|
Private_DismissAmbGroup(group)
|
|
BREAK
|
|
|
|
ENDSWITCH
|
|
|
|
// Disable selector during conversations
|
|
IF group.eConvState <> AMBCONV_NULL AND group.eConvState <> AMBCONV_SAFEHOUSE_TRAILER3
|
|
DISABLE_SELECTOR_THIS_FRAME()
|
|
DISABLE_CELLPHONE_THIS_FRAME_ONLY()
|
|
ENDIF
|
|
|
|
ENDPROC
|
|
|
|
|
|
//-------------------------------------------------------------------------------------------------------------------------------------------
|
|
// AmbGroup
|
|
//-------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
PROC Private_InitAmbGroup(structAmbGroup& group)
|
|
|
|
group.bIsSwitchActive = FALSE
|
|
group.iGreetCount = 0
|
|
group.bHasSaidHello = FALSE
|
|
group.bHasJoined = FALSE
|
|
|
|
group.eConvState = AMBCONV_NULL
|
|
group.eConvChar = NO_CHARACTER
|
|
group.hConvInput = NEW_CONTEXT_INTENTION
|
|
|
|
group.bOutroActive = FALSE
|
|
group.eOutroChar = NO_CHARACTER
|
|
group.hOutroCandidate = NO_CANDIDATE_ID
|
|
group.hOutroScenarioBlock = NULL
|
|
group.hOutroCamera = NULL
|
|
|
|
IF ADD_RELATIONSHIP_GROUP("AmbFriendEmpty", group.hEmptyGroup)
|
|
// SET_RELATIONSHIP_BETWEEN_GROUPS(ACQUAINTANCE_TYPE_PED_DISLIKE, RELGROUPHASH_PLAYER, group.hEmptyGroup)
|
|
// SET_RELATIONSHIP_BETWEEN_GROUPS(ACQUAINTANCE_TYPE_PED_DISLIKE, group.hEmptyGroup, RELGROUPHASH_PLAYER)
|
|
ENDIF
|
|
|
|
group.bAttemptResumeFightAfterSwitch = FALSE
|
|
group.bUpdateAfterSwitch = FALSE
|
|
|
|
enumCharacterList eChar
|
|
REPEAT NUM_OF_PLAYABLE_PEDS eChar
|
|
Private_InitAmbFriend(group.mFriends[eChar], eChar)
|
|
ENDREPEAT
|
|
|
|
ENDPROC
|
|
|
|
PROC Private_CleanupAmbGroup(structAmbGroup& group, BOOL bDelete = FALSE)
|
|
|
|
Private_StopAmbConv(group)
|
|
|
|
IF group.iGreetCount > 0
|
|
Private_DismissAmbGroup(group)
|
|
ENDIF
|
|
|
|
enumCharacterList eChar
|
|
REPEAT NUM_OF_PLAYABLE_PEDS eChar
|
|
Private_ReleaseAmbFriend(group, group.mFriends[eChar], bDelete)
|
|
ENDREPEAT
|
|
|
|
REMOVE_RELATIONSHIP_GROUP(group.hEmptyGroup)
|
|
|
|
Private_InitAmbGroup(group)
|
|
|
|
ENDPROC
|
|
|
|
PROC Private_UpdateAmbGroup(structAmbGroup& group, structPedsForConversation& convPeds)
|
|
|
|
//-- Handle switch
|
|
IF IS_PLAYER_PED_SWITCH_IN_PROGRESS() OR IS_PLAYER_SWITCH_IN_PROGRESS()
|
|
|
|
IF group.bIsSwitchActive = FALSE
|
|
CPRINTLN(DEBUG_FRIENDS, "Private_UpdateAmbGroup() - Switch started")
|
|
|
|
// Clear tasks on dest player ped
|
|
IF IS_PLAYER_PED_PLAYABLE(g_sPlayerPedRequest.ePed)
|
|
AND NOT IS_PED_INJURED(group.mFriends[g_sPlayerPedRequest.ePed].hPed)
|
|
CLEAR_PED_TASKS(group.mFriends[g_sPlayerPedRequest.ePed].hPed)
|
|
ENDIF
|
|
|
|
// Dismiss any group
|
|
Private_DismissAmbGroup(group)
|
|
Private_StopAmbConv(group)
|
|
|
|
// Store if any members are in fight mode
|
|
enumCharacterList eCharLoop
|
|
REPEAT NUM_OF_PLAYABLE_PEDS eCharLoop
|
|
IF group.mFriends[eCharLoop].eState = AMBFRIEND_DISMISSED
|
|
AND group.mFriends[eCharLoop].eDismissMode = AMBMODE_FIGHT
|
|
group.bAttemptResumeFightAfterSwitch = TRUE
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
group.bUpdateAfterSwitch = TRUE
|
|
group.bIsSwitchActive = TRUE
|
|
ENDIF
|
|
|
|
// Remove phone for current player ped
|
|
// Private_DeleteAmbFriendPhone(group.mFriends[g_eDefaultPlayerChar])
|
|
|
|
ELIF group.bIsSwitchActive
|
|
group.bIsSwitchActive = FALSE
|
|
|
|
//-- Handle early outs
|
|
ELIF g_OnMissionState = MISSION_TYPE_STORY_PREP // IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_STORY_PREP)
|
|
|
|
|
|
// DR: Commenting out these debug outputs as it spams the TTY
|
|
// Sam - should this function be getting called repeatedly or should be it be a one time thing?
|
|
// CPRINTLN(DEBUG_FRIENDS, "Private_UpdateAmbFriend() - Shutting down for mission")
|
|
Private_CleanupAmbGroup(group)
|
|
|
|
ELIF (g_OnMissionState = MISSION_TYPE_FRIEND_ACTIVITY OR g_OnMissionState = MISSION_TYPE_FRIEND_ACTIVITY_WITH_MG)
|
|
AND g_eCurrentActivityLoc < MAX_ACTIVITY_LOCATIONS
|
|
|
|
// CPRINTLN(DEBUG_FRIENDS, "Private_UpdateAmbFriend() - Shutting down for friend minigame")
|
|
Private_CleanupAmbGroup(group)
|
|
|
|
ELIF g_bInMultiplayer
|
|
|
|
// CPRINTLN(DEBUG_FRIENDS, "Private_UpdateAmbFriend() - Shutting down for multiplayer")
|
|
Private_CleanupAmbGroup(group)
|
|
|
|
ELSE
|
|
// #IF IS_DEBUG_BUILD
|
|
// IF IS_KEYBOARD_KEY_JUST_PRESSED(KEY_K)
|
|
// enumCharacterList eTempChar
|
|
// REPEAT NUM_OF_PLAYABLE_PEDS eTempChar
|
|
// IF eTempChar <> g_eDefaultPlayerChar
|
|
// AND group.mFriends[eTempChar].eState <> AMBFRIEND_NULL
|
|
// Private_SetAmbFriendVulnerable(group, group.mFriends[eTempChar], FALSE)
|
|
// ENDIF
|
|
// ENDREPEAT
|
|
// ENDIF
|
|
// #ENDIF
|
|
|
|
//-- Update friends
|
|
enumCharacterList eChar
|
|
REPEAT NUM_OF_PLAYABLE_PEDS eChar
|
|
Private_UpdateAmbFriend(group, group.mFriends[eChar], convPeds)
|
|
ENDREPEAT
|
|
|
|
|
|
// If Trevor/Franklin were fighting, resume fight
|
|
IF group.bAttemptResumeFightAfterSwitch
|
|
IF group.mFriends[CHAR_FRANKLIN].eState = AMBFRIEND_DISMISSED
|
|
IF group.mFriends[CHAR_TREVOR].eState = AMBFRIEND_DISMISSED OR group.mFriends[CHAR_TREVOR].eState = AMBFRIEND_PLAYER
|
|
IF NOT IS_PED_INJURED(group.mFriends[CHAR_TREVOR].hPed)
|
|
Private_SetAmbFriendThreatResponse(group.mFriends[CHAR_FRANKLIN], FALSE, group.mFriends[CHAR_TREVOR].hPed)
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
IF group.mFriends[CHAR_TREVOR].eState = AMBFRIEND_DISMISSED
|
|
IF group.mFriends[CHAR_FRANKLIN].eState = AMBFRIEND_DISMISSED OR group.mFriends[CHAR_FRANKLIN].eState = AMBFRIEND_PLAYER
|
|
IF NOT IS_PED_INJURED(group.mFriends[CHAR_FRANKLIN].hPed)
|
|
Private_SetAmbFriendThreatResponse(group.mFriends[CHAR_TREVOR], FALSE, group.mFriends[CHAR_FRANKLIN].hPed)
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
group.bAttemptResumeFightAfterSwitch = FALSE
|
|
ENDIF
|
|
|
|
group.bUpdateAfterSwitch = FALSE
|
|
|
|
|
|
// Manage greet behaviour
|
|
IF group.bOutroActive = FALSE
|
|
|
|
IF group.iGreetCount > 0
|
|
// If greet exists, but isn't allowed, dismiss group members
|
|
IF NOT Private_IsAmbGroupAllowed()
|
|
Private_DismissAmbGroup(group)
|
|
Private_StopAmbConv(group)
|
|
ENDIF
|
|
|
|
// If greet still exists, start conversation
|
|
IF group.eConvState = AMBCONV_NULL
|
|
IF group.iGreetCount > 0
|
|
Private_StartAmbConv(group)
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// If greet has ended, reset everything
|
|
IF group.iGreetCount = 0
|
|
group.bHasSaidHello = FALSE
|
|
group.bHasJoined = FALSE
|
|
ENDIF
|
|
|
|
// Update conversation
|
|
IF group.eConvState <> AMBCONV_NULL
|
|
IF IS_PLAYER_PED_PLAYABLE(group.eConvChar)
|
|
AND (group.mFriends[group.eConvChar].eState = AMBFRIEND_GREET OR group.mFriends[group.eConvChar].eState = AMBFRIEND_GREET_SAFEHOUSE OR group.mFriends[group.eConvChar].eState = AMBFRIEND_GREET_OUTSIDE)
|
|
|
|
Private_UpdateAmbConv(group, convPeds)
|
|
|
|
ELSE
|
|
IF IS_PLAYER_PED_PLAYABLE(group.eConvChar)
|
|
Private_DismissAmbFriend(group, group.mFriends[group.eConvChar])
|
|
ENDIF
|
|
Private_StopAmbConv(group)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ENDIF
|
|
|
|
ENDIF
|
|
|
|
// Print debug output
|
|
#IF IS_DEBUG_BUILD
|
|
DEBUG_DisplayAmbGroupInfo(group)
|
|
#ENDIF
|
|
|
|
ENDPROC
|
|
|