//- 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