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

1177 lines
38 KiB
Scheme
Executable File

//- commands headers -//
//- script headers -//
//- public headers -//
USING "cutscene_public.sch"
USING "rc_helper_functions.sch"
//- private headers -//
USING "friendActivity_system_private.sch"
#IF IS_DEBUG_BUILD
//- debug headers -//
#ENDIF
///private cutscene header for friend activity scripts
/// sam.hackett@rockstarleeds.com
///
// *******************************************************************************************
// CUTSCENE VARIABLES
// *******************************************************************************************
CONST_INT CONST_iSkipFadeTime 500
CONST_INT CONST_iCutsceneDelay 3000
MODEL_NAMES MODEL_TAXIDRIVER = S_M_M_AutoShop_02
MODEL_NAMES MODEL_TAXICAB = TAXI
CAMERA_INDEX hDropoffCams[2]
// *******************************************************************************************
// DROPOFF ON FOOT
// *******************************************************************************************
FUNC BOOL Dropoff_StartConversation(PED_INDEX hSpeaker, PED_INDEX hListener, enumFriendActivityPhrase ePhrase, structPedsForConversation& convPeds)
TEXT_LABEL tBlock
TEXT_LABEL tRoot
enumCharacterList eSpeakerChar = Private_GetCharFromPed(hSpeaker)
enumCharacterList eListenerChar = Private_GetCharFromPed(hListener)
ADD_FRIEND_CHAR_FOR_DIALOGUE(convPeds, eSpeakerChar, hSpeaker)
ADD_FRIEND_CHAR_FOR_DIALOGUE(convPeds, eListenerChar, hListener)
IF Private_GetFriendActivityPhrase(eSpeakerChar, eListenerChar, ePhrase, tBlock, tRoot)
IF CREATE_CONVERSATION(convPeds, tBlock, tRoot, CONV_PRIORITY_AMBIENT_HIGH, DISPLAY_SUBTITLES)
RETURN TRUE
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
FUNC BOOL Dropoff_ExecuteCamPan(structFCamPan& pan)
IF pan.bEnabled
// Create new cams
IF DOES_CAM_EXIST(hDropoffCams[0])
DESTROY_CAM(hDropoffCams[0])
ENDIF
IF DOES_CAM_EXIST(hDropoffCams[1])
DESTROY_CAM(hDropoffCams[1])
ENDIF
hDropoffCams[0] = CREATE_CAM("DEFAULT_SCRIPTED_CAMERA")
hDropoffCams[1] = CREATE_CAM("DEFAULT_SCRIPTED_CAMERA")
IF DOES_CAM_EXIST(hDropoffCams[0]) AND DOES_CAM_EXIST(hDropoffCams[1])
SET_CAM_COORD(hDropoffCams[0], pan.mStart.vPos)
SET_CAM_ROT(hDropoffCams[0], pan.mStart.vRot)
SET_CAM_FOV(hDropoffCams[0], pan.fFov)
SET_CAM_COORD(hDropoffCams[1], pan.mEnd.vPos)
SET_CAM_ROT(hDropoffCams[1], pan.mEnd.vRot)
SET_CAM_FOV(hDropoffCams[1], pan.fFov)
SHAKE_CAM(hDropoffCams[0], "HAND_SHAKE", 0.25)
SHAKE_CAM(hDropoffCams[1], "HAND_SHAKE", 0.25)
IF pan.fDuration > 0.1
SET_CAM_ACTIVE_WITH_INTERP(hDropoffCams[1], hDropoffCams[0], ROUND(pan.fDuration * 1000.0))
ELSE
SET_CAM_ACTIVE(hDropoffCams[0], TRUE)
ENDIF
RENDER_SCRIPT_CAMS(TRUE, FALSE)
RETURN TRUE
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
FUNC BOOL Dropoff_ExecuteCam(structFCam& cam, FLOAT fFov)
// Create new cams
IF DOES_CAM_EXIST(hDropoffCams[0])
DESTROY_CAM(hDropoffCams[0])
ENDIF
IF DOES_CAM_EXIST(hDropoffCams[1])
DESTROY_CAM(hDropoffCams[1])
ENDIF
hDropoffCams[0] = CREATE_CAM("DEFAULT_SCRIPTED_CAMERA")
IF DOES_CAM_EXIST(hDropoffCams[0])
SET_CAM_COORD(hDropoffCams[0], cam.vPos)
SET_CAM_ROT(hDropoffCams[0], cam.vRot)
SET_CAM_FOV(hDropoffCams[0], fFov)
SET_CAM_ACTIVE(hDropoffCams[0], TRUE)
RENDER_SCRIPT_CAMS(TRUE, FALSE)
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
FUNC VEHICLE_INDEX Dropoff_CreateTaxi(VECTOR vPos, FLOAT fRot)
CPRINTLN(DEBUG_FRIENDS, "Dropoff_CreateTaxi() - Creating...")
REQUEST_MODEL(MODEL_TAXIDRIVER)
REQUEST_MODEL(MODEL_TAXICAB)
IF HAS_MODEL_LOADED(MODEL_TAXIDRIVER) AND HAS_MODEL_LOADED(MODEL_TAXICAB)
CLEAR_AREA(vPos, 6.0, TRUE)
VEHICLE_INDEX hTaxi = CREATE_VEHICLE(MODEL_TAXICAB, vPos, fRot)
IF DOES_ENTITY_EXIST(hTaxi)
IF IS_VEHICLE_DRIVEABLE(hTaxi)
PED_INDEX hDriver = CREATE_PED_INSIDE_VEHICLE(hTaxi, PEDTYPE_CIVMALE, MODEL_TAXIDRIVER, VS_DRIVER)
IF NOT IS_PED_INJURED(hDriver)
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(hDriver, TRUE)
SET_MODEL_AS_NO_LONGER_NEEDED(MODEL_TAXIDRIVER)
SET_MODEL_AS_NO_LONGER_NEEDED(MODEL_TAXICAB)
RETURN hTaxi
ELSE
DELETE_VEHICLE(hTaxi)
ENDIF
ELSE
DELETE_VEHICLE(hTaxi)
ENDIF
ENDIF
ENDIF
RETURN NULL
ENDFUNC
FUNC enumFDropoffStyle Dropoff_GetStyle(structFDropoffScene& scene, VEHICLE_INDEX& hVehicle, PED_INDEX hFriendA, PED_INDEX hFriendB, VEHICLE_INDEX hFriendACar, VEHICLE_INDEX hFriendBCar, VEHICLE_INDEX hPlayerCar)
enumFDropoffStyle eStyle = FDROPOFF_NORMAL
// Choose how scene should deal with vehicles this time...
IF scene.bIsTaxiStyle = FALSE AND scene.mFootPans[5].bEnabled = FALSE //scene.bIsHomeLoc
// Friends home location, leave the car on the drive
hVehicle = hPlayerCar
eStyle = FDROPOFF_NORMAL
ELIF IS_PED_UNINJURED(hFriendA)
AND IS_VEHICLE_DRIVEABLE(hFriendACar)
AND IS_ENTITY_AT_COORD(hFriendACar, scene.vCarPos, <<60.0, 60.0, 60.0>>)//<<30.0, 30.0, 30.0>>)
// Friend A's car is nearby, drive off in that
hVehicle = hFriendACar
IF scene.bIsTaxiStyle
eStyle = FDROPOFF_TAXI
ELSE
eStyle = FDROPOFF_FRIENDACAR
ENDIF
ELIF IS_PED_UNINJURED(hFriendB)
AND IS_VEHICLE_DRIVEABLE(hFriendBCar)
AND IS_ENTITY_AT_COORD(hFriendBCar, scene.vCarPos, <<60.0, 60.0, 60.0>>)//<<30.0, 30.0, 30.0>>)
// Friend B's car is nearby, drive off in that
hVehicle = hFriendBCar
IF scene.bIsTaxiStyle
eStyle = FDROPOFF_TAXI
ELSE
eStyle = FDROPOFF_FRIENDBCAR
ENDIF
ELSE
// Default - use taxi if at cinema, otherwise just walk off
IF scene.bIsTaxiStyle
hVehicle = NULL
eStyle = FDROPOFF_TAXI
ELSE
hVehicle = hPlayerCar
eStyle = FDROPOFF_NORMAL
ENDIF
ENDIF
RETURN eStyle
ENDFUNC
FUNC BOOL Dropoff_ProcessScene(structFDropoffScene& scene, structFDropoff& dropoff, structPedsForConversation& sConvPeds, INT& iStage, INT& iDrunkTimer, PED_INDEX hFriendA, PED_INDEX hFriendB, VEHICLE_INDEX& hSceneVehicle, VEHICLE_INDEX hFriendACar = NULL, VEHICLE_INDEX hFriendBCar = NULL)
//-- Fade out if skip is pressed --
BOOL bTooLateToSkip = FALSE
IF scene.fFootFinalDelay < 2.0
IF iStage >= 402
bTooLateToSkip = TRUE
ENDIF
ELSE
IF iStage >= 403 AND TIMERA() > ROUND((scene.fFootFinalDelay - 2.0) * 1000.0)
bTooLateToSkip = TRUE
ENDIF
ENDIF
IF iStage > 301
AND iStage < 900
IF IS_SCREEN_FADED_OUT()
iStage = 900
// RETURN FALSE
ELIF bTooLateToSkip = FALSE
IF NOT IS_SCREEN_FADING_IN()
IF IS_CUTSCENE_SKIP_BUTTON_JUST_PRESSED_WITH_DELAY()
DO_SCREEN_FADE_OUT(CONST_iSkipFadeTime)
ENDIF
ENDIF
ENDIF
ENDIF
CPRINTLN(DEBUG_FRIENDS, "Dropoff_ProcessScene() - ", iStage)
// Stop peds sobering up
IF iStage > 0
IF iDrunkTimer < GET_GAME_TIMER()
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
IF IS_PED_DRUNK(PLAYER_PED_ID())
EXTEND_OVERALL_DRUNK_TIME(PLAYER_PED_ID(), 5000)
ENDIF
ENDIF
IF NOT IS_PED_INJURED(hFriendA)
IF IS_PED_DRUNK(hFriendA)
EXTEND_OVERALL_DRUNK_TIME(hFriendA, 5000)
ENDIF
ENDIF
IF NOT IS_PED_INJURED(hFriendB)
IF IS_PED_DRUNK(hFriendB)
EXTEND_OVERALL_DRUNK_TIME(hFriendB, 5000)
ENDIF
ENDIF
iDrunkTimer = GET_GAME_TIMER() + 5000
ENDIF
ENDIF
//-- Process scene --
//------------------------------------------------------------------------------------------- Choose setup type
IF iStage = 0
RC_START_CUTSCENE_MODE(scene.vCarPos, FALSE, FALSE, FALSE, FALSE, FALSE)
SET_PLAYER_CONTROL(PLAYER_ID(), FALSE)
KILL_ANY_CONVERSATION()
hSceneVehicle = NULL
SETTIMERA(0)
// Stop peds sobering up mid-scene
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
IF IS_PED_DRUNK(PLAYER_PED_ID())
EXTEND_OVERALL_DRUNK_TIME(PLAYER_PED_ID(), 6000)
ENDIF
ENDIF
IF NOT IS_PED_INJURED(hFriendA)
IF IS_PED_DRUNK(hFriendA)
EXTEND_OVERALL_DRUNK_TIME(hFriendA, 6000)
ENDIF
ENDIF
IF NOT IS_PED_INJURED(hFriendB)
IF IS_PED_DRUNK(hFriendB)
EXTEND_OVERALL_DRUNK_TIME(hFriendB, 6000)
ENDIF
ENDIF
iDrunkTimer = GET_GAME_TIMER() + 5000
// Player has brought vehicle, place it sensibly
VEHICLE_INDEX hPlayerLastVehicle = GET_PLAYERS_LAST_VEHICLE()
IF DOES_ENTITY_EXIST(hPlayerLastVehicle)
CPRINTLN(DEBUG_FRIENDS, "Dropoff_ProcessScene() - Grabbed players last vehicle for use in scene")
SET_ENTITY_AS_MISSION_ENTITY(hPlayerLastVehicle, TRUE, TRUE)
ENDIF
IF NOT IS_PED_INJURED(PLAYER_PED_ID()) AND IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID()) // Player is in vehicle - everybody get out
DO_SCREEN_FADE_IN(500)
iStage = 101
ELSE // Player is on foot - start scene
iStage = 301
ENDIF
//------------------------------------------------------------------------------------------- Vehicle setup (everybody gets out)
ELIF iStage = 101
SEQUENCE_INDEX seq
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
CLEAR_PED_TASKS(PLAYER_PED_ID())
OPEN_SEQUENCE_TASK(seq)
IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
TASK_LEAVE_ANY_VEHICLE(null)
ELSE
TASK_FOLLOW_NAV_MESH_TO_COORD(null, scene.vPlayerPos, PEDMOVE_WALK)
ENDIF
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(PLAYER_PED_ID(), seq)
CLEAR_SEQUENCE_TASK(seq)
ENDIF
IF NOT IS_PED_INJURED(hFriendA)
CLEAR_PED_TASKS(PLAYER_PED_ID())
OPEN_SEQUENCE_TASK(seq)
IF IS_PED_IN_ANY_VEHICLE(hFriendA)
TASK_LEAVE_ANY_VEHICLE(null, 550)
ELSE
TASK_FOLLOW_NAV_MESH_TO_COORD(null, scene.vPedPos[0], PEDMOVE_WALK)
ENDIF
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(hFriendA, seq)
CLEAR_SEQUENCE_TASK(seq)
ENDIF
IF NOT IS_PED_INJURED(hFriendB)
CLEAR_PED_TASKS(PLAYER_PED_ID())
OPEN_SEQUENCE_TASK(seq)
IF IS_PED_IN_ANY_VEHICLE(hFriendB)
TASK_LEAVE_ANY_VEHICLE(null, 800)
ELSE
TASK_FOLLOW_NAV_MESH_TO_COORD(null, scene.vPedPos[1], PEDMOVE_WALK)
ENDIF
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(hFriendB, seq)
CLEAR_SEQUENCE_TASK(seq)
ENDIF
SETTIMERA(0)
iStage++
ELIF iStage = 102
IF TIMERA() > 1500
SETTIMERA(0)
iStage = 301
ENDIF
//------------------------------------------------------------------------------------------- Start scene
ELIF iStage = 301
VEHICLE_INDEX hPlayerCar = GET_PLAYERS_LAST_VEHICLE()
// Choose style
dropoff.eStyle = Dropoff_GetStyle(scene, hSceneVehicle, hFriendA, hFriendB, hFriendACar, hFriendBCar, hPlayerCar)
// Create taxi if necessary
IF dropoff.eStyle = FDROPOFF_TAXI
IF NOT IS_VEHICLE_DRIVEABLE(hSceneVehicle)
IF TIMERA() < 15000
hSceneVehicle = Dropoff_CreateTaxi(scene.vCarPos, scene.fCarRot)
IF NOT IS_VEHICLE_DRIVEABLE(hSceneVehicle)
RETURN FALSE
ENDIF
ELSE
dropoff.eStyle = FDROPOFF_NORMAL
hSceneVehicle = hPlayerCar
ENDIF
ENDIF
ENDIF
IF DOES_ENTITY_EXIST(hSceneVehicle)
IF NOT DOES_ENTITY_BELONG_TO_THIS_SCRIPT(hSceneVehicle, FALSE)
SET_ENTITY_AS_MISSION_ENTITY(hSceneVehicle)
ENDIF
ENDIF
// Get rid of friend vehicles if they're not being used as the main vehicle
IF dropoff.eStyle != FDROPOFF_FRIENDACAR
IF hFriendACar != hSceneVehicle
IF DOES_ENTITY_EXIST(hFriendACar)
DELETE_VEHICLE(hFriendACar)
ENDIF
ENDIF
ENDIF
IF dropoff.eStyle != FDROPOFF_FRIENDBCAR
IF hFriendBCar != hSceneVehicle
IF DOES_ENTITY_EXIST(hFriendBCar)
DELETE_VEHICLE(hFriendBCar)
ENDIF
ENDIF
ENDIF
// Respot player vehicle if it's not being used as the main vehicle
IF dropoff.eStyle != FDROPOFF_NORMAL
IF hSceneVehicle != hPlayerCar
IF DOES_ENTITY_EXIST(hPlayerCar)
Private_RespotVehicle(hPlayerCar, scene.mExtraRespot)
ENDIF
ENDIF
ENDIF
// Now that cars have been setup/cleanedup - can set friendcarB to friendcarA for easier checking
IF dropoff.eStyle = FDROPOFF_FRIENDBCAR
dropoff.eStyle = FDROPOFF_FRIENDACAR
ENDIF
// Clear area
VECTOR vMin = scene.vPlayerPos - <<150.0, 150.0, 50.0>>
VECTOR vMax = scene.vPlayerPos + <<150.0, 150.0, 50.0>>
CLEAR_AREA_OF_VEHICLES(scene.vPlayerPos, 150.0)
CLEAR_AREA_OF_PEDS(scene.vPlayerPos, 150.0)
SET_PED_PATHS_IN_AREA(vMin, vMax, FALSE)
SET_ROADS_IN_AREA(vMin, vMax, FALSE)
// Setup peds
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
//-- Prepare peds
CLEAR_PED_TASKS(PLAYER_PED_ID())
STOP_PED_SPEAKING(PLAYER_PED_ID(), TRUE)
SET_PED_CONFIG_FLAG(PLAYER_PED_ID(), PCF_ForceSkinCharacterCloth, TRUE)
IF IS_PED_DRUNK(hFriendA)
EXTEND_OVERALL_DRUNK_TIME(PLAYER_PED_ID(), 20000)
ENDIF
IF IS_PED_UNINJURED(hFriendA)
CLEAR_PED_TASKS(hFriendA)
STOP_PED_SPEAKING(hFriendA, TRUE)
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(hFriendA, TRUE)
SET_PED_CONFIG_FLAG(hFriendA, PCF_ForceSkinCharacterCloth, TRUE)
IF IS_PED_IN_GROUP(hFriendA)
REMOVE_PED_FROM_GROUP(hFriendA)
ENDIF
IF IS_PED_DRUNK(hFriendA)
EXTEND_OVERALL_DRUNK_TIME(hFriendA, 20000)
ENDIF
ENDIF
IF IS_PED_UNINJURED(hFriendB)
CLEAR_PED_TASKS(hFriendB)
STOP_PED_SPEAKING(hFriendB, TRUE)
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(hFriendB, TRUE)
SET_PED_CONFIG_FLAG(hFriendB, PCF_ForceSkinCharacterCloth, TRUE)
IF IS_PED_IN_GROUP(hFriendB)
REMOVE_PED_FROM_GROUP(hFriendB)
ENDIF
IF IS_PED_DRUNK(hFriendB)
EXTEND_OVERALL_DRUNK_TIME(hFriendB, 20000)
ENDIF
ENDIF
//-- Setup peds for conversation
CLEAR_AREA(scene.vPlayerPos, 15.0, TRUE)
VECTOR vGroundPos
// Respot player
vGroundPos = scene.vPlayerPos+<<0.0,0.0,1.0>>
GET_GROUND_Z_FOR_3D_COORD(vGroundPos, vGroundPos.z)
SET_ENTITY_COORDS(PLAYER_PED_ID(), vGroundPos)
SET_ENTITY_FACING(PLAYER_PED_ID(), (scene.vPedPos[0] + scene.vPedPos[1]) * 0.5)
// Respot friend A
IF IS_PED_UNINJURED(hFriendA)
vGroundPos = scene.vPedPos[0]+<<0.0,0.0,1.0>>
GET_GROUND_Z_FOR_3D_COORD(vGroundPos, vGroundPos.z)
CLEAR_PED_TASKS_IMMEDIATELY(hFriendA)
SET_ENTITY_COORDS(hFriendA, vGroundPos)
SET_ENTITY_FACING(hFriendA, scene.vPlayerPos)
ENDIF
// Respot friend B
IF IS_PED_UNINJURED(hFriendB)
vGroundPos = scene.vPedPos[1]+<<0.0,0.0,1.0>>
GET_GROUND_Z_FOR_3D_COORD(vGroundPos, vGroundPos.z)
CLEAR_PED_TASKS_IMMEDIATELY(hFriendB)
SET_ENTITY_COORDS(hFriendB, vGroundPos)
SET_ENTITY_FACING(hFriendB, scene.vPlayerPos)
ENDIF
// Respot vehicle
IF DOES_ENTITY_EXIST(hSceneVehicle)
IF IS_ENTITY_DEAD(hSceneVehicle)
DELETE_VEHICLE(hSceneVehicle)
ELSE
CLEAR_AREA(scene.vCarPos, 15.0, TRUE)
SET_ENTITY_COORDS(hSceneVehicle, scene.vCarPos)
SET_ENTITY_HEADING(hSceneVehicle, scene.fCarRot)
IF dropoff.eStyle = FDROPOFF_FRIENDACAR
IF NOT IS_ENTITY_FACING_COORD(hSceneVehicle, scene.vCarFakeDrivePos)
SET_ENTITY_HEADING(hSceneVehicle, scene.fCarRot+180.0)
ENDIF
ENDIF
SET_VEHICLE_ON_GROUND_PROPERLY(hSceneVehicle)
SET_VEHICLE_DOORS_SHUT(hSceneVehicle, TRUE)
ENDIF
ENDIF
// Respot player vehicle if it's too big to be part of scene
IF dropoff.eStyle = FDROPOFF_NORMAL
IF hSceneVehicle = hPlayerCar
IF DOES_ENTITY_EXIST(hPlayerCar)
MODEL_NAMES eModel = GET_ENTITY_MODEL(hPlayerCar)
IF eModel <> DUMMY_MODEL_FOR_SCRIPT
VECTOR vBoxMin, vBoxMax
GET_MODEL_DIMENSIONS(eModel, vBoxMin, vBoxMax)
// IF vBoxMax.x > 3.0 OR vBoxMax.y > 5.0
// OR vBoxMin.x < -3.0 OR vBoxMin.y < -5.0
IF vBoxMax.x > 2.5 OR vBoxMax.y > 4.0 // Seems good dimensions, allows sandking, but not rental bus
OR vBoxMin.x < -2.5 OR vBoxMin.y < -4.0
CPRINTLN(DEBUG_FRIENDS, "Dropoff - Vehicle is large, using expandable respot to be safe")
Private_RespotVehicle(hPlayerCar, scene.mExtraRespot, TRUE)
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
//-- Setup camera pan
Dropoff_ExecuteCamPan(scene.mFootPans[0])
SETTIMERA(-(ROUND(scene.fFootSpeechDelay*1000.0)))
SETTIMERB(0)
ENDIF
IF NOT IS_SCREEN_FADED_IN()
DO_SCREEN_FADE_IN(1000)
ENDIF
iStage++
//------------------------------------------------------------------------------------------- Start player dialogue
ELIF iStage = 302
IF TIMERA() > 0
IF IS_PED_UNINJURED(PLAYER_PED_ID())
// Start player phrase
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
enumFriendActivityPhrase eDropoffPhrase
IF Is_Ped_Drunk(PLAYER_PED_ID())
eDropoffPhrase = FAP_DROPOFF_OPENER_DRUNK
ELIF IS_PED_UNINJURED(hFriendA) AND IS_PED_UNINJURED(hFriendB)
eDropoffPhrase = FAP_DROPOFF_OPENER_PLURAL
ELSE
eDropoffPhrase = FAP_DROPOFF_OPENER
ENDIF
PED_INDEX hListenerPed = hFriendA
IF IS_PED_INJURED(hFriendA)
hListenerPed = hFriendB
ENDIF
IF IS_PED_UNINJURED(hListenerPed)
IF Dropoff_StartConversation(PLAYER_PED_ID(), hListenerPed, eDropoffPhrase, sConvPeds)
TASK_LOOK_AT_ENTITY(PLAYER_PED_ID(), hListenerPed, -1, SLF_WHILE_NOT_IN_FOV, SLF_LOOKAT_VERY_HIGH)
iStage++
ENDIF
ELSE
iStage++
ENDIF
ENDIF
ELSE
iStage++
ENDIF
ENDIF
//------------------------------------------------------------------------------------------- Wait for player dialogue to end
ELIF iStage = 303
// Wait for player phrase to end
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF TIMERB() > ROUND(scene.mFootPans[0].fDuration*1000.0)
iStage++
ENDIF
ENDIF
//------------------------------------------------------------------------------------------- Wait for friends to finish getting out of car
ELIF iStage = 304
IF (IS_PED_INJURED(hFriendA) OR NOT IS_PED_IN_ANY_VEHICLE(hFriendA)) // Needs to timeout?
AND (IS_PED_INJURED(hFriendB) OR NOT IS_PED_IN_ANY_VEHICLE(hFriendB))
IF scene.bFootCam2IsAlternative AND NOT IS_PED_INJURED(hFriendB)
Dropoff_ExecuteCamPan(scene.mFootPans[2])
ELSE
Dropoff_ExecuteCamPan(scene.mFootPans[1])
ENDIF
iStage++
ENDIF
//------------------------------------------------------------------------------------------- Start friend A saying dialogue
ELIF iStage = 305
IF IS_PED_UNINJURED(PLAYER_PED_ID()) AND IS_PED_UNINJURED(hFriendA)
enumCharacterList ePlayerChar = GET_CURRENT_PLAYER_PED_ENUM()
enumCharacterList eFriendChar = Private_GetCharFromPed(hFriendA)
INT iLikeStat = 50
IF ePlayerChar <> NO_CHARACTER AND eFriendChar <> NO_CHARACTER
iLikeStat = GET_FRIEND_LIKE(ePlayerChar, eFriendChar)
ENDIF
enumFriendActivityPhrase eDropoffPhrase
IF Is_Ped_Drunk(hFriendA)
eDropoffPhrase = FAP_DROPOFF_DRUNK
// ELIF DOES_ENTITY_EXIST(hFriendACar) AND IS_PED_IN_VEHICLE(PLAYER_PED_ID(), hFriendACar) AND Private_IsVehicleOwnedByPed(hFriendACar, hFriendA)
// eDropoffPhrase = FAP_DROPOFF_GOTCAR
ELIF iLikeStat < 20
eDropoffPhrase = FAP_DROPOFF_VERY_IRATE
ELIF iLikeStat < 40
eDropoffPhrase = FAP_DROPOFF_IRATE
ELSE
eDropoffPhrase = FAP_DROPOFF_OK
ENDIF
IF Dropoff_StartConversation(PLAYER_PED_ID(), hFriendA, eDropoffPhrase, sConvPeds)
iStage++
ENDIF
ELSE
iStage++
ENDIF
//------------------------------------------------------------------------------------------- Wait for friend A dialogue to end
ELIF iStage = 306
// Wait for player phrase to end
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF scene.bFootCam2IsAlternative = FALSE AND NOT IS_PED_INJURED(hFriendB)
Dropoff_ExecuteCamPan(scene.mFootPans[2])
ENDIF
iStage++
ENDIF
//------------------------------------------------------------------------------------------- Start friend B saying dialogue
ELIF iStage = 307
IF IS_PED_UNINJURED(PLAYER_PED_ID()) AND IS_PED_UNINJURED(hFriendB)
enumCharacterList ePlayerChar = GET_CURRENT_PLAYER_PED_ENUM()
enumCharacterList eFriendChar = Private_GetCharFromPed(hFriendB)
INT iLikeStat = 50
IF ePlayerChar <> NO_CHARACTER AND eFriendChar <> NO_CHARACTER
iLikeStat = GET_FRIEND_LIKE(ePlayerChar, eFriendChar)
ENDIF
enumFriendActivityPhrase eDropoffPhrase
IF Is_Ped_Drunk(hFriendB)
eDropoffPhrase = FAP_DROPOFF_DRUNK
// ELIF DOES_ENTITY_EXIST(hFriendBCar) AND IS_PED_IN_VEHICLE(PLAYER_PED_ID(), hFriendBCar) AND Private_IsVehicleOwnedByPed(hFriendBCar, hFriendA)
// eDropoffPhrase = FAP_DROPOFF_GOTCAR
ELIF iLikeStat < 20
eDropoffPhrase = FAP_DROPOFF_VERY_IRATE
ELIF iLikeStat < 40
eDropoffPhrase = FAP_DROPOFF_IRATE
ELSE
eDropoffPhrase = FAP_DROPOFF_OK
ENDIF
IF Dropoff_StartConversation(PLAYER_PED_ID(), hFriendB, eDropoffPhrase, sConvPeds)
iStage++
ENDIF
ELSE
iStage++
ENDIF
//------------------------------------------------------------------------------------------- Wait for friend B dialogue to end
ELIF iStage = 308
// Wait for player phrase to end
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
iStage = 401
ENDIF
//------------------------------------------------------------------------------------------- Friends get in taxi / walk off
ELIF iStage = 401
IF IS_PED_UNINJURED(PLAYER_PED_ID())
IF dropoff.eStyle != FDROPOFF_FRIENDACAR
TASK_CLEAR_LOOK_AT(PLAYER_PED_ID())
// ELIF IS_PED_UNINJURED(hFriendA)
// TASK_TURN_PED_TO_FACE_ENTITY(PLAYER_PED_ID(), hFriendA)
ENDIF
ENDIF
VEHICLE_SEAT eFriendSeatA = VS_BACK_LEFT
VEHICLE_SEAT eFriendSeatB = VS_BACK_RIGHT
IF dropoff.eStyle = FDROPOFF_TAXI AND IS_VEHICLE_DRIVEABLE(hSceneVehicle)
IF NOT IS_PED_INJURED(hFriendA)
VECTOR vCarForward = GET_ENTITY_FORWARD_VECTOR(hSceneVehicle)
VECTOR vCarDoorDir = << vCarForward.y, -vCarForward.x, 0.0 >>
VECTOR vFriendDir = GET_ENTITY_COORDS(hFriendA) - GET_ENTITY_COORDS(hSceneVehicle)
IF DOT_PRODUCT_XY(vCarDoorDir, vFriendDir) > 0.0
eFriendSeatA = VS_BACK_RIGHT
eFriendSeatB = VS_BACK_LEFT
ENDIF
ENDIF
IF GET_ENTITY_MODEL(hSceneVehicle) <> MODEL_TAXICAB
IF NOT IS_PED_INJURED(hFriendA)
eFriendSeatA = VS_DRIVER
ELSE
eFriendSeatA = eFriendSeatB
eFriendSeatB = VS_DRIVER
ENDIF
ENDIF
ENDIF
// IF DOES_ENTITY_EXIST(hSceneVehicle)
// IF dropoff.eStyle = FDROPOFF_FRIENDACAR
// FREEZE_ENTITY_POSITION(hSceneVehicle, TRUE)
// SET_ENTITY_COLLISION(hSceneVehicle, TRUE)
// ENDIF
// ENDIF
IF IS_PED_UNINJURED(hFriendA)
TASK_CLEAR_LOOK_AT(hFriendA)
CLEAR_PED_TASKS(hFriendA)
IF dropoff.eStyle = FDROPOFF_FRIENDACAR
TASK_FOLLOW_NAV_MESH_TO_COORD(hFriendA, scene.vCarFakeWalkPos, PEDMOVE_WALK, DEFAULT_TIME_NEVER_WARP)
ELIF dropoff.eStyle = FDROPOFF_TAXI AND IS_VEHICLE_DRIVEABLE(hSceneVehicle)
TASK_ENTER_VEHICLE(hFriendA, hSceneVehicle, DEFAULT_TIME_BEFORE_WARP, eFriendSeatA, PEDMOVE_WALK)
ELSE
TASK_FOLLOW_NAV_MESH_TO_COORD(hFriendA, scene.vExitPos, PEDMOVE_WALK, DEFAULT_TIME_NEVER_WARP)
ENDIF
ENDIF
IF IS_PED_UNINJURED(hFriendB)
TASK_CLEAR_LOOK_AT(hFriendB)
CLEAR_PED_TASKS(hFriendB)
SEQUENCE_INDEX seq
OPEN_SEQUENCE_TASK(seq)
TASK_PAUSE(null, 500)
IF dropoff.eStyle = FDROPOFF_FRIENDACAR
TASK_FOLLOW_NAV_MESH_TO_COORD(null, scene.vCarFakeWalkPos, PEDMOVE_WALK, DEFAULT_TIME_NEVER_WARP)
ELIF dropoff.eStyle = FDROPOFF_TAXI AND IS_VEHICLE_DRIVEABLE(hSceneVehicle)
TASK_ENTER_VEHICLE(null, hSceneVehicle, DEFAULT_TIME_BEFORE_WARP, eFriendSeatB, PEDMOVE_WALK)
ELSE
TASK_FOLLOW_NAV_MESH_TO_COORD(null, scene.vExitPos, PEDMOVE_WALK, DEFAULT_TIME_NEVER_WARP)
ENDIF
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(hFriendB, seq)
CLEAR_SEQUENCE_TASK(seq)
ENDIF
iStage++
//------------------------------------------------------------------------------------------- Wait a beat before switching to exit cam
ELIF iStage = 402
IF TIMERA() > 500
IF dropoff.eStyle != FDROPOFF_FRIENDACAR
Dropoff_ExecuteCamPan(scene.mFootPans[3])
ELSE
Dropoff_ExecuteCamPan(scene.mFootPans[4])
ENDIF
SETTIMERA(0)
IF dropoff.eStyle != FDROPOFF_FRIENDACAR
iStage++
ELSE
iStage = 501
ENDIF
ENDIF
//------------------------------------------------------------------------------------------- Hold exit shot
ELIF iStage = 403
// If final shot duration is set, hold for that long
IF scene.fFootFinalDelay > 0.1
IF TIMERA() > ROUND(scene.fFootFinalDelay * 1000.0)
iStage = 900
ENDIF
// Otherwise use ped position
ELSE
// Timeout on 10 seconds
IF TIMERA() > 10000
IF NOT IS_SCREEN_FADING_IN()
DO_SCREEN_FADE_OUT(CONST_iSkipFadeTime)
ENDIF
ELIF TIMERA() > 2500
IF dropoff.eStyle != FDROPOFF_TAXI
IF (IS_PED_INJURED(hFriendA) OR NOT IS_ENTITY_AT_ENTITY(hFriendA, PLAYER_PED_ID(), <<4.0, 4.0, 4.0>>))
AND (IS_PED_INJURED(hFriendB) OR NOT IS_ENTITY_AT_ENTITY(hFriendB, PLAYER_PED_ID(), <<4.0, 4.0, 4.0>>))
iStage = 900
ELIF (NOT IS_PED_INJURED(hFriendA) AND IS_ENTITY_AT_COORD(hFriendA, scene.vExitPos, <<0.5, 0.5, 0.5>>))
OR (NOT IS_PED_INJURED(hFriendB) AND IS_ENTITY_AT_COORD(hFriendB, scene.vExitPos, <<0.5, 0.5, 0.5>>))
iStage = 900
ENDIF
ELSE
IF NOT IS_VEHICLE_DRIVEABLE(hSceneVehicle) OR NOT IS_ENTITY_AT_ENTITY(hSceneVehicle, PLAYER_PED_ID(), <<15.0, 15.0, 15.0>>)
iStage = 900
ELIF IS_VEHICLE_DRIVEABLE(hSceneVehicle) AND IS_ENTITY_AT_COORD(hSceneVehicle, scene.vCarFakeDrivePos, <<1.0, 1.0, 1.0>>)
iStage = 900
ENDIF
ENDIF
ENDIF
ENDIF
// If taxi style scene, have taxi drive off when the friends are in it
IF dropoff.eStyle = FDROPOFF_TAXI AND IS_VEHICLE_DRIVEABLE(hSceneVehicle)
IF (IS_PED_INJURED(hFriendA) OR IS_PED_IN_ANY_VEHICLE(hFriendA))
AND (IS_PED_INJURED(hFriendB) OR IS_PED_IN_ANY_VEHICLE(hFriendB))
PED_INDEX hDriver = GET_PED_IN_VEHICLE_SEAT(hSceneVehicle, VS_DRIVER)
IF NOT IS_PED_INJURED(hDriver)
IF NOT IsPedPerformingTask(hDriver, SCRIPT_TASK_VEHICLE_DRIVE_TO_COORD)
CLEAR_PED_TASKS(hDriver)
TASK_VEHICLE_DRIVE_TO_COORD(hDriver, hSceneVehicle, scene.vCarFakeDrivePos, 10.0, DRIVINGSTYLE_NORMAL, MODEL_TAXICAB, DRIVINGMODE_STOPFORCARS, 5.0, 5)
ENDIF
ENDIF
ENDIF
ENDIF
//------------------------------------------------------------------------------------------- Fake car walk off
ELIF iStage = 501
IF TIMERA() > 10000
SETTIMERA(0)
iStage++
ELIF (IS_PED_INJURED(hFriendA) OR NOT IS_ENTITY_ON_SCREEN(hFriendA))
AND (IS_PED_INJURED(hFriendB) OR NOT IS_ENTITY_ON_SCREEN(hFriendB))
SETTIMERA(0)
iStage++
ENDIF
ELIF iStage = 502
IF TIMERA() > ROUND(scene.fCarFinalDelay0 * 1000.0)
// IF TIMERA() > 1000//1500
PED_INDEX hDriver = NULL
// Setup driver
IF NOT IS_PED_INJURED(hFriendA)
SET_PED_INTO_VEHICLE(hFriendA, hSceneVehicle, VS_DRIVER)
IF NOT IS_PED_INJURED(hFriendB)
SET_PED_INTO_VEHICLE(hFriendB, hSceneVehicle, VS_FRONT_RIGHT)
ENDIF
hDriver = hFriendA
ELIF NOT IS_PED_INJURED(hFriendB)
SET_PED_INTO_VEHICLE(hFriendB, hSceneVehicle, VS_DRIVER)
hDriver = hFriendB
ENDIF
IF NOT IS_PED_INJURED(hDriver)
CLEAR_PED_TASKS(hDriver)
SEQUENCE_INDEX seq
OPEN_SEQUENCE_TASK(seq)
TASK_PAUSE(null, 750)
DRIVINGMODE eMode = INT_TO_ENUM(DRIVINGMODE, ENUM_TO_INT(DRIVINGMODE_AVOIDCARS) | ENUM_TO_INT(DF_DriveIntoOncomingTraffic))
TASK_VEHICLE_DRIVE_TO_COORD(null, hSceneVehicle, scene.vCarFakeDrivePos, 10.0, DRIVINGSTYLE_NORMAL, GET_ENTITY_MODEL(hSceneVehicle), eMode, 5.0, 5)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(hDriver, seq)
CLEAR_SEQUENCE_TASK(seq)
ENDIF
// Setup next shot
SETTIMERA(0)
Dropoff_ExecuteCamPan(scene.mFootPans[5])
IF IS_PED_UNINJURED(PLAYER_PED_ID())
SET_ENTITY_FACING(PLAYER_PED_ID(), scene.vCarPos)
ENDIF
iStage++
ENDIF
ELIF iStage = 503
IF scene.fCarFinalDelay > 0.1
IF TIMERA() > ROUND(scene.fCarFinalDelay * 1000.0)
iStage = 900
ENDIF
ELSE
IF TIMERA() > 20000
iStage = 900
ELIF (NOT IS_VEHICLE_DRIVEABLE(hSceneVehicle) OR NOT IS_ENTITY_ON_SCREEN(hSceneVehicle))
SETTIMERA(0)
iStage++
ENDIF
ENDIF
ELIF iStage = 504
IF TIMERA() > 2000
iStage = 900
ENDIF
//------------------------------------------------------------------------------------------- Final cam
ELIF iStage = 900
IF dropoff.eStyle != FDROPOFF_FRIENDACAR
Dropoff_ExecuteCam(scene.mFootCatchupCam, scene.fFootCatchupFov)
ELSE
Dropoff_ExecuteCam(scene.mCarCatchupCam, scene.fCarCatchupFov)
ENDIF
KILL_ANY_CONVERSATION()
// Reset player
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
CLEAR_PED_TASKS(PLAYER_PED_ID())
TASK_CLEAR_LOOK_AT(PLAYER_PED_ID())
ENDIF
// Lock car doors if a friend owns this car
IF DOES_ENTITY_EXIST(hSceneVehicle) AND NOT IS_ENTITY_DEAD(hSceneVehicle)
IF IS_PED_UNINJURED(hFriendA)
AND Private_IsVehicleOwnedByPed(hSceneVehicle, hFriendA)
SET_VEHICLE_DOORS_LOCKED(hSceneVehicle, VEHICLELOCK_LOCKED)
ENDIF
IF IS_PED_UNINJURED(gActivity.mFriendB.hPed)
AND Private_IsVehicleOwnedByPed(hSceneVehicle, hFriendB)
SET_VEHICLE_DOORS_LOCKED(hSceneVehicle, VEHICLELOCK_LOCKED)
ENDIF
ENDIF
// Store ped switch positions and delete peds
IF IS_PED_UNINJURED(hFriendA)
enumCharacterList eChar = Private_GetCharFromPed(hFriendA)
IF IS_PLAYER_PED_PLAYABLE(eChar)
IF IS_VEHICLE_DRIVEABLE(hSceneVehicle) AND IS_PED_IN_VEHICLE(hFriendA, hSceneVehicle) AND GET_PED_IN_VEHICLE_SEAT(hSceneVehicle, VS_DRIVER) = hFriendA
SET_ENTITY_COORDS(hSceneVehicle, scene.vSwitchPos[2])
SET_ENTITY_HEADING(hSceneVehicle, scene.fSwitchRot[2])
SET_VEHICLE_ON_GROUND_PROPERLY(hSceneVehicle)
ELSE
SET_ENTITY_COORDS(hFriendA, scene.vSwitchPos[0] - <<0.0, 0.0, 1.0>>)
SET_ENTITY_HEADING(hFriendA, scene.fSwitchRot[0])
ENDIF
STORE_PLAYER_PED_INFO(hFriendA)
STORE_VEH_DATA_FROM_PED(hFriendA,
g_sPlayerLastVeh[eChar],
g_vPlayerLastVehCoord[eChar],
g_fPlayerLastVehHead[eChar],
g_ePlayerLastVehState[eChar] #IF USE_TU_CHANGES , g_ePlayerLastVehGen[eChar] #ENDIF )
g_SavedGlobals.sPlayerSceneData.g_ePlayerLastScene[eChar] = PR_SCENE_INVALID
IF g_ePlayerLastVehState[eChar] = PTVS_1_playerWithVehicle
CPRINTLN(DEBUG_FRIENDS, "OVERRIDING g_ePlayerLastVehState[", GetLabel_enumCharacterList(eChar), "] with PTVS_0_noVehicle at end of friend dropoff scene.")
CPRINTLN(DEBUG_FRIENDS, " - This is because friend ped has been removed but vehicle remains (as it is also the players last vehicle).")
CPRINTLN(DEBUG_FRIENDS, " - So when the friend ped is created by the player controller (probably very soon), we don't want an extra instance of the car created.")
CPRINTLN(DEBUG_SWITCH, "OVERRIDING g_ePlayerLastVehState[", GetLabel_enumCharacterList(eChar), "] with PTVS_0_noVehicle at end of friend dropoff scene.")
CPRINTLN(DEBUG_SWITCH, " - This is because friend ped has been removed but vehicle remains (as it is also the players last vehicle).")
CPRINTLN(DEBUG_SWITCH, " - So when the friend ped is created by the player controller (probably very soon), we don't want an extra instance of the car created.")
g_ePlayerLastVehState[eChar] = PTVS_0_noVehicle
ENDIF
ENDIF
DELETE_PED(hFriendA)
ENDIF
IF IS_PED_UNINJURED(hFriendB)
enumCharacterList eChar = Private_GetCharFromPed(hFriendB)
IF IS_PLAYER_PED_PLAYABLE(eChar)
IF IS_VEHICLE_DRIVEABLE(hSceneVehicle) AND IS_PED_IN_VEHICLE(hFriendB, hSceneVehicle) AND GET_PED_IN_VEHICLE_SEAT(hSceneVehicle, VS_DRIVER) = hFriendB
SET_ENTITY_COORDS(hSceneVehicle, scene.vSwitchPos[2])
SET_ENTITY_HEADING(hSceneVehicle, scene.fSwitchRot[2])
SET_VEHICLE_ON_GROUND_PROPERLY(hSceneVehicle)
ELSE
SET_ENTITY_COORDS(hFriendB, scene.vSwitchPos[1] - <<0.0, 0.0, 1.0>>)
SET_ENTITY_HEADING(hFriendB, scene.fSwitchRot[1])
ENDIF
STORE_PLAYER_PED_INFO(hFriendB)
STORE_VEH_DATA_FROM_PED(hFriendB,
g_sPlayerLastVeh[eChar],
g_vPlayerLastVehCoord[eChar],
g_fPlayerLastVehHead[eChar],
g_ePlayerLastVehState[eChar] #IF USE_TU_CHANGES , g_ePlayerLastVehGen[eChar] #ENDIF )
g_SavedGlobals.sPlayerSceneData.g_ePlayerLastScene[eChar] = PR_SCENE_INVALID
IF g_ePlayerLastVehState[eChar] = PTVS_1_playerWithVehicle
CPRINTLN(DEBUG_FRIENDS, "OVERRIDING g_ePlayerLastVehState[", GetLabel_enumCharacterList(eChar), "] with PTVS_0_noVehicle at end of friend dropoff scene.")
CPRINTLN(DEBUG_FRIENDS, " - This is because friend ped has been removed but vehicle remains (as it is also the players last vehicle).")
CPRINTLN(DEBUG_FRIENDS, " - So when the friend ped is created by the player controller (probably very soon), we don't want an extra instance of the car created.")
CPRINTLN(DEBUG_SWITCH, "OVERRIDING g_ePlayerLastVehState[", GetLabel_enumCharacterList(eChar), "] with PTVS_0_noVehicle at end of friend dropoff scene.")
CPRINTLN(DEBUG_SWITCH, " - This is because friend ped has been removed but vehicle remains (as it is also the players last vehicle).")
CPRINTLN(DEBUG_SWITCH, " - So when the friend ped is created by the player controller (probably very soon), we don't want an extra instance of the car created.")
g_ePlayerLastVehState[eChar] = PTVS_0_noVehicle
ENDIF
ENDIF
DELETE_PED(hFriendB)
ENDIF
// Release/delete scene vehicle
IF DOES_ENTITY_EXIST(hSceneVehicle)
IF dropoff.eStyle != FDROPOFF_TAXI
IF dropoff.eStyle = FDROPOFF_FRIENDACAR
DELETE_VEHICLE(hSceneVehicle)
ELSE
SET_VEHICLE_AS_NO_LONGER_NEEDED(hSceneVehicle)
ENDIF
ELSE
IF NOT IS_ENTITY_DEAD(hSceneVehicle)
PED_INDEX hDriver = GET_PED_IN_VEHICLE_SEAT(hSceneVehicle, VS_DRIVER)
IF DOES_ENTITY_EXIST(hDriver)
DELETE_PED(hDriver)
ENDIF
ENDIF
DELETE_VEHICLE(hSceneVehicle)
ENDIF
ENDIF
SET_MODEL_AS_NO_LONGER_NEEDED(MODEL_TAXICAB)
SET_MODEL_AS_NO_LONGER_NEEDED(MODEL_TAXIDRIVER)
iStage++
//------------------------------------------------------------------------------------------- Cleanup
ELIF iStage = 901
// Reset camera
IF IS_SCREEN_FADED_OUT() AND GET_FOLLOW_PED_CAM_VIEW_MODE() = CAM_VIEW_MODE_FIRST_PERSON
RENDER_SCRIPT_CAMS(FALSE, FALSE)
ELSE
STOP_RENDERING_SCRIPT_CAMS_USING_CATCH_UP()
ENDIF
IF DOES_CAM_EXIST(hDropoffCams[0])
DESTROY_CAM(hDropoffCams[0])
ENDIF
IF DOES_CAM_EXIST(hDropoffCams[1])
DESTROY_CAM(hDropoffCams[1])
ENDIF
// Allow ped to do ambient dialogue again
IF IS_PED_UNINJURED(PLAYER_PED_ID())
STOP_PED_SPEAKING(PLAYER_PED_ID(), FALSE)
SET_PED_CONFIG_FLAG(PLAYER_PED_ID(), PCF_ForceSkinCharacterCloth, FALSE)
ENDIF
// Unblock area
VECTOR vMin = scene.vPlayerPos - <<150.0, 150.0, 50.0>>
VECTOR vMax = scene.vPlayerPos + <<150.0, 150.0, 50.0>>
SET_PED_PATHS_BACK_TO_ORIGINAL(vMin, vMax)
SET_ROADS_BACK_TO_ORIGINAL(vMin, vMax)
// Fade in (if necessary)
IF IS_SCREEN_FADED_OUT()
OR IS_SCREEN_FADING_OUT()
DO_SCREEN_FADE_IN(CONST_iSkipFadeTime)
ENDIF
RC_END_CUTSCENE_MODE(FALSE, FALSE)
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
// *******************************************************************************************
//
// *******************************************************************************************
FUNC BOOL PROCESS_DROPOFF_STATE(BOOL bIsFLocType)
//-- If replay (as in playback) system requested clear entities...
IF REPLAY_SYSTEM_HAS_REQUESTED_A_SCRIPT_CLEANUP()
Private_ClearObjective()
Private_SetActivityFailReason(FAF_PlaybackAbort)
RETURN FALSE
//-- Check if replay (as in retry failed mission) has been initiated
ELIF IS_REPLAY_BEING_PROCESSED()
IF GET_MISSION_FLOW_SAFE_TO_CLEANUP()
Private_SetActivityFailReason(FAF_RetryAbort)
RETURN FALSE
ENDIF
//-- Check if player is dead
ELIF NOT IS_PLAYER_PLAYING(PLAYER_ID()) OR IS_PED_INJURED(PLAYER_PED_ID())
Private_SetActivityFailReason(FAF_PlayerDeathArrest)
RETURN FALSE
//-- If player has started story mission...
ELIF IS_CURRENTLY_ON_MISSION_TO_TYPE(MISSION_TYPE_FRIEND_ACTIVITY)
AND NOT IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_FRIEND_ACTIVITY)
AND NOT IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_FRIEND_ACTIVITY_WITH_MG)
Private_SetActivityFailReason(FAF_PlayerOnMission)
RETURN FALSE
ELSE
structFDropoffScene scene
IF bIsFLocType
Private_FLOC_GetDropoffScene(gActivity.eDropoffLoc, scene)
ELSE
Private_ALOC_GetDropoffScene(g_ePreviousActivityLoc, scene)
ENDIF
IF Dropoff_ProcessScene(scene, gActivity.dropoffData, gActivity.convPedsDefault, gActivity.iStateProgress, gActivity.iDropoffDrunkTimer, gActivity.mFriendA.hPed, gActivity.mFriendB.hPed, gActivity.hDropoffCar, gActivity.mFriendA.hCar, gActivity.mFriendB.hCar)
// Count active connections towards 100% completion
enumFriendConnection eConnection
REPEAT MAX_FRIEND_CONNECTIONS eConnection
IF GET_CONNECTION_STATE(eConnection) = FC_STATE_Active
AND GET_CONNECTION_MODE(eConnection) = FC_MODE_Friend
SET_CONNECTION_PLAYED(eConnection)
ENDIF
ENDREPEAT
// Mark as successful in play stats
IF gActivity.mFriendA.eChar <> NO_CHARACTER
PLAYSTATS_FRIEND_ACTIVITY(ENUM_TO_INT(GET_FRIEND_FROM_CHAR(gActivity.mFriendA.eChar)), 0)
ENDIF
IF gActivity.mFriendB.eChar <> NO_CHARACTER
PLAYSTATS_FRIEND_ACTIVITY(ENUM_TO_INT(GET_FRIEND_FROM_CHAR(gActivity.mFriendB.eChar)), 0)
ENDIF
// Clear up members
Private_CleanupFriend(gActivity.mPlayer, MC_Delete, TRUE)
Private_CleanupFriend(gActivity.mFriendA, MC_Delete, TRUE)
Private_CleanupFriend(gActivity.mFriendB, MC_Delete, TRUE)
RETURN TRUE
ENDIF
ENDIF
RETURN FALSE
ENDFUNC