1177 lines
38 KiB
Scheme
Executable File
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
|
|
|