Files
gtav-src/script/dev_ng/singleplayer/scripts/RandomChar/Maude/Maude1.sc
T
2025-09-29 00:52:08 +02:00

1128 lines
49 KiB
Python
Executable File

//Compile out Title Update changes to header functions.
//Must be before includes.
//CONST_INT USE_TU_CHANGES 0 // Removed by Kenneth R.
USING "rage_builtins.sch"
USING "globals.sch"
USING "cutscene_public.sch"
USING "commands_cutscene.sch"
USING "commands_entity.sch"
USING "commands_script.sch"
USING "script_player.sch"
USING "randomChar_public.sch"
USING "replay_public.sch"
USING "RC_Helper_Functions.sch"
USING "RC_Threat_Public.sch"
USING "initial_scenes_Maude.sch"
USING "commands_recording.sch"
#IF IS_DEBUG_BUILD
USING "select_mission_stage.sch"
#ENDIF
// *****************************************************************************************
// *****************************************************************************************
// *****************************************************************************************
//
// MISSION NAME : Maude1.sc
// AUTHOR : Ahron M
// DESCRIPTION : Trevor meets Maude which unlocks Bail Bonds oddjob
//
// *****************************************************************************************
// *****************************************************************************************
// *****************************************************************************************
//*************************************************************************************************************************************************
// :ENUMS:
//*************************************************************************************************************************************************
ENUM MAUDE_1_MISSION_STAGE
MISSION_STAGE_CUTSCENE,
MISSION_STAGE_LEAVE_AREA,
MISSION_STAGE_MISSION_FAILED_WAIT_FOR_FADE
ENDENUM
ENUM SUB_STAGE
SS_SETUP,
SS_UPDATE,
SS_CLEANUP
ENDENUM
ENUM MAUDE_1_FAIL_REASON
FAIL_REASON_MAUDE_DEAD,
FAIL_REASON_MAUDE_SPOOKED,
FAIL_REASON_DEFAULT
ENDENUM
//*************************************************************************************************************************************************
// :STRUCTURES:
//*************************************************************************************************************************************************
//*************************************************************************************************************************************************
// :CONSTANTS:
//*************************************************************************************************************************************************
CONST_INT MAUDE_1_MAUDE_SPEAKER_ID 4 // Conversation speaker ID
CONST_INT MAUDE_1_Z_SKIP_START_CUTSCENE 0
CONST_INT MAUDE_1_Z_SKIP_LEAVE_AREA 1
CONST_INT MAUDE_1_Z_SKIP_MISSION_PASSED 2
//*************************************************************************************************************************************************
// :VARIABLES:
//*************************************************************************************************************************************************
g_structRCScriptArgs sRCLauncherDataLocal
MAUDE_1_MISSION_STAGE eMissionStage = MISSION_STAGE_CUTSCENE
SUB_STAGE eSubStage = SS_SETUP
MAUDE_1_FAIL_REASON eFailReason = FAIL_REASON_DEFAULT
BOOL bHasSetExitStateFromIntroMocapForGameplayCam
BOOL bSetMaudeFleeSyncSceneExit
INT iMaudeSyncSceneIndex = -1
INT iFocusPushStage = 0
INT iFocusPushTimer = -1
INT iSyncScene_MaudeReact = -1
INT iMaxNumMaudeLeaveLines = 4
INT iTimer_MaudeDialogue = 0
INT iCounterMaudeLines = 0
OBJECT_INDEX objMaudeChair
OBJECT_INDEX objMaudeLaptop
OBJECT_INDEX objMaudeTable
OBJECT_INDEX objMaudeRadio
PED_INDEX pedMaude
STRING sSceneHandle_Trevor = "Trevor"
STRING sSceneHandle_Maude = "Maude"
STRING sSceneHandle_MaudeChair = "maude_chair"
STRING sSceneHandle_MaudeLaptop = "maude_laptop"
structPedsForConversation sDialogue
VEHICLE_INDEX vehIndex_MissionReplayRestore
#IF IS_DEBUG_BUILD // stage skipping
CONST_INT MAX_SKIP_MENU_LENGTH 3
MissionStageMenuTextStruct mSkipMenu[MAX_SKIP_MENU_LENGTH]
#ENDIF
VECTOR vRespotVehicleCoord
// ===========================================================================================================
// CLEANUP FUNCTIONS
// ===========================================================================================================
/// PURPOSE:
/// initialise data needed for scene
PROC INIT_DATA()
// Stage skipping
#IF IS_DEBUG_BUILD
mSkipMenu[MAUDE_1_Z_SKIP_START_CUTSCENE].sTxtLabel = "Mocap: MAUDE_MCS_1"
mSkipMenu[MAUDE_1_Z_SKIP_LEAVE_AREA].sTxtLabel = "Leave the area."
mSkipMenu[MAUDE_1_Z_SKIP_MISSION_PASSED].sTxtLabel = "Mission Passed"
#ENDIF
eMissionStage = MISSION_STAGE_CUTSCENE
eSubStage = SS_SETUP
iMaudeSyncSceneIndex = -1
iFocusPushStage = 0
iFocusPushTimer = -1
iSyncScene_MaudeReact = -1
iMaxNumMaudeLeaveLines = 4
iTimer_MaudeDialogue = 0
iCounterMaudeLines = 0
bSetMaudeFleeSyncSceneExit = FALSE
bHasSetExitStateFromIntroMocapForGameplayCam = FALSE
SET_START_CHECKPOINT_AS_FINAL() // tells replay controller to display "skip mission" for shitskips
ENDPROC
/// PURPOSE:
/// Deletes all of the mission entities checking if they exist
/// Used in Mission Failed, when faded out.
/// PARAMS:
/// bDelete - if true all entities will be deleted, else released
PROC CLEANUP_ALL_MISSION_ENTITIES(BOOL bDelete = FALSE)
SAFE_DELETE_PED(pedMaude) // always make sure Maude is removed
SAFE_RELEASE_OBJECT(objMaudeTable) // can't delete an object that was created from the world
SAFE_RELEASE_OBJECT(objMaudeRadio) // can't delete an object that was created from the world
IF bDelete
SAFE_DELETE_OBJECT(objMaudeChair)
SAFE_DELETE_OBJECT(objMaudeLaptop)
ELSE
SAFE_RELEASE_OBJECT(objMaudeChair)
SAFE_RELEASE_OBJECT(objMaudeLaptop)
ENDIF
ENDPROC
/// PURPOSE:
/// Safely cleans up the script
PROC MISSION_CLEANUP()
IF IS_GAMEPLAY_HINT_ACTIVE()
STOP_GAMEPLAY_HINT()
ENDIF
// proc from initial scene so they match up
SETUP_AREA_FOR_MISSION(RC_MAUDE_1, FALSE)
REMOVE_ANIM_DICT("special_ped@maude@base")
CLEANUP_ALL_MISSION_ENTITIES()
ENDPROC
/// PURPOSE:
/// Handles call to MISSION_CLEANUP and terminates the thread
PROC Script_Cleanup()
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), " : Script Cleanup")
// Ensure launcher is cleaned up
RC_CLEANUP_LAUNCHER()
// If the mission was triggered then additional mission cleanup will be required.
IF (Random_Character_Cleanup_If_Triggered())
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), " : Script triggered, additional cleanup required...")
MISSION_CLEANUP()
ENDIF
//Cleanup the scene created by the launcher
RC_CleanupSceneEntities(sRCLauncherDataLocal)
TERMINATE_THIS_THREAD()
ENDPROC
/// PURPOSE:
/// Adds needed contacts, completion %, cleans up and passes script.
PROC Script_Passed()
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), " : Passed")
ADD_HELP_TO_FLOW_QUEUE("BBONDS_UNLOCK", FHP_MEDIUM, 0, FLOW_HELP_NEVER_EXPIRES, DEFAULT_HELP_TEXT_TIME, BIT_TREVOR, CID_BLANK, CID_BLANK, FHF_SAVED)
ADD_CONTACT_TO_PHONEBOOK(CHAR_MAUDE, TREVOR_BOOK)
// Bail bond missions now open. Trevor will receive emails from Maude with further details.
Random_Character_Passed(CP_RAND_C_MAU1)
Script_Cleanup()
ENDPROC
/// PURPOSE:
/// will return the enumSubtitlesState needed to allow a dialogue line to play
/// without subtitles if a message is being displayed
/// RETURNS:
/// enumSubtitlesState
FUNC enumSubtitlesState GET_SUBTITLES_STATE_FOR_NON_CLASH_WITH_MESSAGES()
IF IS_MESSAGE_BEING_DISPLAYED()
RETURN DO_NOT_DISPLAY_SUBTITLES
ENDIF
RETURN DISPLAY_SUBTITLES
ENDFUNC
/// PURPOSE:
/// requests and checks if the assets are loaded
/// RETURNS:
/// TRUE if loaded
FUNC BOOL HAVE_MISSION_ASSETS_LOADED()
REQUEST_ANIM_DICT("special_ped@maude@base")
REQUEST_ADDITIONAL_TEXT("MAUDE1", MISSION_TEXT_SLOT)
IF HAS_ANIM_DICT_LOADED("special_ped@maude@base")
AND HAS_ADDITIONAL_TEXT_LOADED(MISSION_TEXT_SLOT)
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// gets a handle to Maude's radio which is an object created by map data
/// Need to set it as a mission entity to prevent bug 1712317
PROC GET_HANDLE_TO_MAUDES_RADIO()
// get handle to Maude's Radio (done set as mission entity since created by map instead uses para on DOES_OBJECT_OF_TYPE_EXIST_AT_COORDS)
IF NOT DOES_ENTITY_EXIST(objMaudeRadio)
VECTOR vRadioPosition = << 2727.29, 4145.90, 44.16 >>
MODEL_NAMES modelNameRadio = PROP_RADIO_01
IF IS_ENTITY_IN_RANGE_COORDS(PLAYER_PED_ID(), vRadioPosition, 150.0)
IF DOES_OBJECT_OF_TYPE_EXIST_AT_COORDS(vRadioPosition, 10.0, modelNameRadio)
objMaudeRadio = GET_CLOSEST_OBJECT_OF_TYPE(vRadioPosition, 10.0, modelNameRadio, TRUE)
#IF IS_DEBUG_BUILD PRINTLN(DEBUG_MISSION, "GET_HANDLE_TO_MAUDES_RADIO : ", "grabbed handle to radio") #ENDIF
ENDIF
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// checks to see if Maude should flee
/// PARAMS:
/// bCheckPlayerWanted - if TRUE checks the player's wanted level and returns TRUE if he has one
/// RETURNS:
/// TRUE if reason for Maude to flee
FUNC BOOL SHOULD_MAUDE_FLEE(BOOL bCheckPlayerWanted = FALSE)
IF IS_PED_UNINJURED(pedMaude)
// Check for Maude taking damage
IF HAS_ENTITY_BEEN_DAMAGED_BY_ANY_PED(pedMaude)
OR HAS_ENTITY_BEEN_DAMAGED_BY_ANY_VEHICLE(pedMaude)
OR HAS_ENTITY_BEEN_DAMAGED_BY_ANY_OBJECT(pedMaude)
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), " : SHOULD_MAUDE_FLEE() return TRUE : Maude took damage : FC = ", GET_FRAME_COUNT())
RETURN TRUE
ENDIF
// Check for player pushing them with their car
IF IS_PED_SITTING_IN_ANY_VEHICLE(PLAYER_PED_ID()) // Ignore player knocking them with car door (in vehicle, but not sitting= must be exiting)
IF IS_ENTITY_TOUCHING_ENTITY(PLAYER_PED_ID(), pedMaude)
//OR HAS_ENTITY_COLLIDED_WITH_ANYTHING(objMaudeTable)
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), " : SHOULD_MAUDE_FLEE() return TRUE : Maude pushed by player vehicle : FC = ", GET_FRAME_COUNT())
RETURN TRUE
ENDIF
IF DOES_ENTITY_EXIST(objMaudeChair)
IF IS_ENTITY_TOUCHING_ENTITY(PLAYER_PED_ID(), objMaudeChair)
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), " : SHOULD_MAUDE_FLEE() return TRUE : Maude's chair pushed by player vehicle : FC = ", GET_FRAME_COUNT())
RETURN TRUE
ENDIF
ENDIF
IF DOES_ENTITY_EXIST(objMaudeTable)
IF IS_ENTITY_TOUCHING_ENTITY(PLAYER_PED_ID(), objMaudeTable)
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), " : SHOULD_MAUDE_FLEE() return TRUE : Maude's table pushed by player vehicle : FC = ", GET_FRAME_COUNT())
RETURN TRUE
ENDIF
ENDIF
IF DOES_ENTITY_EXIST(objMaudeLaptop)
IF IS_ENTITY_TOUCHING_ENTITY(PLAYER_PED_ID(), objMaudeLaptop)
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), " : SHOULD_MAUDE_FLEE() return TRUE : Maude's laptop pushed by player vehicle : FC = ", GET_FRAME_COUNT())
RETURN TRUE
ENDIF
ENDIF
ENDIF
// code event check for EVENT_POTENTIAL_GET_RUN_OVER
IF HAS_PED_RECEIVED_EVENT(pedMaude, EVENT_POTENTIAL_GET_RUN_OVER)
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), " : SHOULD_MAUDE_FLEE() return TRUE : Maude's received event EVENT_POTENTIAL_GET_RUN_OVER : FC = ", GET_FRAME_COUNT())
RETURN TRUE
ENDIF
// check for ragdoll
IF IS_PED_RAGDOLL(pedMaude)
IF IS_ENTITY_AT_ENTITY(pedMaude, PLAYER_PED_ID(), <<3.0, 3.0, 3.0>>) // Player close (so they bumped into them)
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), " : SHOULD_MAUDE_FLEE() return TRUE : Maude's ragdolled with player close by : FC = ", GET_FRAME_COUNT())
RETURN TRUE
ENDIF
ENDIF
// code event check for EVENT_PED_COLLISION_WITH_PLAYER
IF HAS_PED_RECEIVED_EVENT(pedMaude, EVENT_PED_COLLISION_WITH_PLAYER)
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), " : SHOULD_MAUDE_FLEE() return TRUE : Maude's received event EVENT_PED_COLLISION_WITH_PLAYER : FC = ", GET_FRAME_COUNT())
RETURN TRUE
ENDIF
// check for player aiming at RC character
IF IS_PLAYER_VISIBLY_TARGETTING_PED(pedMaude)
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), " : SHOULD_MAUDE_FLEE() return TRUE : Player visibly targetting Maude : FC = ", GET_FRAME_COUNT())
RETURN TRUE
ENDIF
// Check for player shooting nearby
IF IS_PLAYER_SHOOTING_NEAR_PED(pedMaude)
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), " : SHOULD_MAUDE_FLEE() return TRUE : Player shooting near Maude : FC = ", GET_FRAME_COUNT())
RETURN TRUE
ENDIF
// Check for explosions nearby
IF IS_EXPLOSION_IN_SPHERE(EXP_TAG_DONTCARE, GET_ENTITY_COORDS(pedMaude), 15)
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), " : SHOULD_MAUDE_FLEE() return TRUE : Explosion near Maude : FC = ", GET_FRAME_COUNT())
RETURN TRUE
ENDIF
// code event check for EVENT_RESPONDED_TO_THREAT
IF HAS_PED_RECEIVED_EVENT(pedMaude, EVENT_RESPONDED_TO_THREAT)
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), " : SHOULD_MAUDE_FLEE() return TRUE : Maude's received event EVENT_RESPONDED_TO_THREAT : FC = ", GET_FRAME_COUNT())
RETURN TRUE
ENDIF
// flee if player is wanted
IF bCheckPlayerWanted
IF IS_PLAYER_WANTED_LEVEL_GREATER(PLAYER_ID(), 0)
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), " : SHOULD_MAUDE_FLEE() return TRUE : player has wanted level : FC = ", GET_FRAME_COUNT())
RETURN TRUE
ENDIF
ENDIF
ELSE
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), " : SHOULD_MAUDE_FLEE() return TRUE : Maude injured : FC = ", GET_FRAME_COUNT())
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// task Maude with the exit from sync scene anim
/// RETURNS:
/// TRUE if anim was applied or if Maude isn't playing the sync scene to apply it
FUNC BOOL SET_MAUDE_PLAY_FLEE_EXIT_ANIM()
IF IS_PED_UNINJURED(pedMaude)
IF IS_ENTITY_PLAYING_ANIM(pedMaude, "special_ped@maude@base", "base")
//OR IsPedPerformingTask(pedMaude, SCRIPT_TASK_SYNCHRONIZED_SCENE) // removed since this still returned true when she was ragdolling
IF NOT IS_PED_RAGDOLL(pedMaude)
OR IS_PED_GETTING_UP(pedMaude)
REQUEST_ANIM_DICT("special_ped@maude@exit_flee")
IF HAS_ANIM_DICT_LOADED("special_ped@maude@exit_flee")
iSyncScene_MaudeReact = CREATE_SYNCHRONIZED_SCENE(<< 2727.40, 4145.56, 43.68 >>, << 0.0, 0.0, -92.17 >>)
SET_SYNCHRONIZED_SCENE_LOOPED(iSyncScene_MaudeReact, FALSE)
SET_SYNCHRONIZED_SCENE_HOLD_LAST_FRAME(iSyncScene_MaudeReact, FALSE)
IF IsPedPerformingTask(pedMaude, SCRIPT_TASK_SYNCHRONIZED_SCENE)
STOP_SYNCHRONIZED_ENTITY_ANIM(pedMaude, INSTANT_BLEND_OUT, TRUE)
ENDIF
TASK_SYNCHRONIZED_SCENE(pedMaude, iSyncScene_MaudeReact, "special_ped@maude@exit_flee", "female_Flee_Table_Left_Maude", INSTANT_BLEND_IN, SLOW_BLEND_OUT,
SYNCED_SCENE_ABORT_ON_WEAPON_DAMAGE | SYNCED_SCENE_ACTIVATE_RAGDOLL_ON_COLLISION | SYNCED_SCENE_VEHICLE_ABORT_ON_LARGE_IMPACT | SYNCED_SCENE_TAG_SYNC_OUT)
//SYNCED_SCENE_ABORT_ON_WEAPON_DAMAGE | SYNCED_SCENE_USE_PHYSICS | SYNCED_SCENE_VEHICLE_ABORT_ON_LARGE_IMPACT | SYNCED_SCENE_TAG_SYNC_OUT) // SYNCED_SCENE_ACTIVATE_RAGDOLL_ON_COLLISION)
FORCE_PED_AI_AND_ANIMATION_UPDATE(pedMaude)
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), " : SET_MAUDE_PLAY_FLEE_EXIT_ANIM() Maude given exit sync scene this frame FC = ", GET_FRAME_COUNT())
IF IS_ENTITY_ALIVE(objMaudeChair)
IF IS_ENTITY_PLAYING_ANIM(objMaudeChair, "special_ped@maude@base", "base_chair")
STOP_SYNCHRONIZED_ENTITY_ANIM(objMaudeChair, FAST_BLEND_OUT, FALSE)
ENDIF
INT iEntitySyncedSceneFlags = 0
iEntitySyncedSceneFlags += ENUM_TO_INT(SYNCED_SCENE_ABORT_ON_WEAPON_DAMAGE)
iEntitySyncedSceneFlags += ENUM_TO_INT(SYNCED_SCENE_LOOP_WITHIN_SCENE)
iEntitySyncedSceneFlags += ENUM_TO_INT(SYNCED_SCENE_ACTIVATE_RAGDOLL_ON_COLLISION)
iEntitySyncedSceneFlags += ENUM_TO_INT(SYNCED_SCENE_VEHICLE_ABORT_ON_LARGE_IMPACT)
PLAY_SYNCHRONIZED_ENTITY_ANIM(objMaudeChair, iSyncScene_MaudeReact, "Female_Flee_Table_Left_Maude_Chair", "special_ped@maude@exit_flee", FAST_BLEND_IN, SLOW_BLEND_OUT, iEntitySyncedSceneFlags)
ENDIF
RETURN TRUE // needs to wait a frame for anim to register
ELSE
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), " : SET_MAUDE_PLAY_FLEE_EXIT_ANIM() return FALSE loading anim dict...")
ENDIF
ELSE
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), " : SET_MAUDE_PLAY_FLEE_EXIT_ANIM() return TRUE Maude ragdoll / getting up so skipping exit anim")
RETURN TRUE
ENDIF
ELSE
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), " : SET_MAUDE_PLAY_FLEE_EXIT_ANIM() return TRUE Maude not playing sync scene to exit from so skipping exit anim")
RETURN TRUE
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// stop any ongoing Maude mission passed ambient dialogue
/// PARAMS:
/// bFinishCurrentLine - if TRUE ongoing convo is allowed to finish current line, otherwise gets cut off
PROC KILL_ANY_ONGOING_MAUDE_MISSION_PASSED_DIALOGUE(BOOL bFinishCurrentLine = FALSE)
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
TEXT_LABEL_23 tlCurrentRoot = GET_CURRENTLY_PLAYING_STANDARD_CONVERSATION_ROOT()
//if current root matches passed in string return true
IF ARE_STRINGS_EQUAL(tlCurrentRoot, "MAUDE_loiter")
IF bFinishCurrentLine
KILL_FACE_TO_FACE_CONVERSATION()
ELSE
KILL_FACE_TO_FACE_CONVERSATION_DO_NOT_FINISH_LAST_LINE()
ENDIF
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), " : KILL_ANY_ONGOING_MAUDE_MISSION_PASSED_DIALOGUE - convo killed : ", tlCurrentRoot, " bFinishCurrentLine = ", bFinishCurrentLine)
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// triggers Maude's ambient dialogue lines
/// PARAMS:
/// vMaudeCoords - Maude's position used in proximity check
/// vPlayerCoords - Player's position used in proximity check
/// RETURNS:
/// TRUE if Dialogue was added to the non critical standard buffer
FUNC BOOL TRIGGER_MAUDE_AMBIENT_MISSION_PASSED_DIALOGUE(VECTOR vMaudeCoords, VECTOR vPlayerCoords, INT iTimeDelay = 18000, FLOAT fTriggerRange = 20.0)
IF iCounterMaudeLines < iMaxNumMaudeLeaveLines
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
IF (VDIST2(vPlayerCoords, vMaudeCoords) < (fTriggerRange * fTriggerRange))
IF (GET_GAME_TIMER() - iTimer_MaudeDialogue) > (iTimeDelay + GET_RANDOM_INT_IN_RANGE(0, 2000))
ADD_PED_FOR_DIALOGUE(sDialogue, 3, pedMaude, "MAUDE") // vMAUDE_1_MAUDE_SPEAKER_ID - this one has been setup for 3 though
ADD_NON_CRITICAL_STANDARD_CONVERSATION_TO_BUFFER(sDialogue, "MAUDEAU", "MAUDE_loiter", CONV_PRIORITY_MEDIUM)
// I'd really appreciate the help, and you know how grateful I can be.
// Don't let me hold you up, Trevor. I'll send you the file.
// Go on now, I'll give you a nice share of the proceeds.
// You best get goin'. I'm on the hook for that bond if he doesn't show.
iTimer_MaudeDialogue = GET_GAME_TIMER()
iCounterMaudeLines++
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), " : TRIGGER_MAUDE_AMBIENT_DIALOGUE - return TRUE")
RETURN TRUE
ENDIF
ENDIF
ELSE
iTimer_MaudeDialogue = GET_GAME_TIMER()
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// handes the calls resolve vehicles inside angled area and setting mission start vehicle as a vehicle gen
PROC REPOSITION_PLAYER_VEHICLE_FOR_INTRO()
VECTOR vResolveArea_Pos1, vResolveArea_Pos2, vVehRespotPosSizeLimit
FLOAT fResolveArea_Width
//GET_RESOLVE_VEHICLES_AT_MAUDE_ANGLED_AREA_VALUES(vResolveArea_Pos1, vResolveArea_Pos2, fResolveArea_Width)
vResolveArea_Pos1 = <<2728.995117,4143.165039,41.029861>>
vResolveArea_Pos2 = <<2719.125977,4144.691406,47.885429>>
fResolveArea_Width = 13.0
vVehRespotPosSizeLimit = << 3.0, 11.0, 6.0 >> // GET_DEFAULT_ALLOWABLE_VEHICLE_SIZE_VECTOR()
// set the vehicle the player triggered the mission in to regenerate and clear the area - use alternative location for bigger vehicles
IF IS_REPLAY_START_VEHICLE_UNDER_SIZE_LIMIT(vVehRespotPosSizeLimit, FALSE)
RESOLVE_VEHICLES_INSIDE_ANGLED_AREA(vResolveArea_Pos1, vResolveArea_Pos2, fResolveArea_Width, <<2719.87, 4143.46, 43.46>>, 261.91)
SET_MISSION_START_VEHICLE_AS_VEHICLE_GEN(<<2719.87, 4143.46, 43.46>>, 261.91, FALSE)
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), " : REPOSITION_PLAYER_VEHICLE_FOR_INTRO() - resolved vehicles in area and setup standard vehicle gen - framecount : ", GET_FRAME_COUNT())
vRespotVehicleCoord = <<2719.87, 4143.46, 43.46>>
ELSE
RESOLVE_VEHICLES_INSIDE_ANGLED_AREA(vResolveArea_Pos1, vResolveArea_Pos2, fResolveArea_Width, <<2710.6646, 4149.0752, 42.7026>>, 180.9488)
SET_MISSION_START_VEHICLE_AS_VEHICLE_GEN(<<2710.6646, 4149.0752, 42.7026>>, 180.9488, FALSE)
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), " : REPOSITION_PLAYER_VEHICLE_FOR_INTRO() - resolved vehicles in area and setup large vehicle gen - framecount : ", GET_FRAME_COUNT())
vRespotVehicleCoord = <<2710.6646, 4149.0752, 42.7026>>
ENDIF
ENDPROC
/// PURPOSE:
/// set everything up for retrying mission after fail - set to leave the area state
PROC SETUP_FOR_REPLAY()
// if a shit skip has been offered and accepted it will be to skip the mission so don't repawn Maude
IF g_bShitskipAccepted
CREATE_VEHICLE_FOR_REPLAY(vehIndex_MissionReplayRestore, <<2662.6438, 4284.5347, 43.5787>>, 19.8376, FALSE, FALSE, TRUE, FALSE, FALSE)
START_REPLAY_SETUP(<<2672.4619, 4288.7773, 43.6070>>, 78.1133, FALSE) // position towards the main road away from Maudes
RC_START_Z_SKIP()
WAIT(500) // allow a frame for START_REPLAY_SETUP to process before calling END_REPLAY_SETUP()
END_REPLAY_SETUP()
RC_END_Z_SKIP()
eMissionStage = MISSION_STAGE_LEAVE_AREA
eSubStage = SS_CLEANUP
// ensure we are fully faded in if we have skipped to the mission passed stage, since the mission passed GUI doesn't display if not (seems to need a frame wait too)
SAFE_FADE_SCREEN_IN_FROM_BLACK()
CPRINTLN(DEBUG_MISSION, " IS_REPLAY_IN_PROGRESS : SETUP_FOR_REPLAY() done setup for shit skip backup FADE UP!")
ELSE
//Set up the initial scene for replays
g_bSceneAutoTrigger = TRUE
eInitialSceneStage = IS_REQUEST_SCENE
WHILE NOT SetupScene_MAUDE_1(sRCLauncherDataLocal)
CPRINTLN(DEBUG_MISSION, " IS_REPLAY_IN_PROGRESS - SETUP_FOR_REPLAY() waiting on SetupScene_MAUDE_1")
WAIT(0)
ENDWHILE
RC_SET_ENTITY_PROOFS_FOR_CUTSCENE(sRCLauncherDataLocal, FALSE)
RC_TakeEntityOwnership(sRCLauncherDataLocal)
// take ownership of the sync scene index from the initial scene (needs to happen before launcher terminates)
// take ownership from the initial scene (needs to happen before launcher terminates) must check is running, could get here from replay and not be setup
IF IS_SYNCHRONIZED_SCENE_RUNNING(sRCLauncherDataLocal.iSyncSceneIndex)
TAKE_OWNERSHIP_OF_SYNCHRONIZED_SCENE(sRCLauncherDataLocal.iSyncSceneIndex)
iMaudeSyncSceneIndex = sRCLauncherDataLocal.iSyncSceneIndex
CPRINTLN(DEBUG_MISSION, " SETUP_FOR_REPLAY() - TAKE_OWNERSHIP_OF_SYNCHRONIZED_SCENE : sRCLauncherDataLocal.iSyncSceneIndex = ", sRCLauncherDataLocal.iSyncSceneIndex,
" iMaudeSyncSceneIndex = ", iMaudeSyncSceneIndex)
ENDIF
g_bSceneAutoTrigger = FALSE
ASSIGN_PED_INDEX(pedMaude, sRCLauncherDataLocal.pedID[0])
ASSIGN_OBJECT_INDEX(objMaudeChair, sRCLauncherDataLocal.objID[0])
ASSIGN_OBJECT_INDEX(objMaudeLaptop, sRCLauncherDataLocal.objID[1])
// B*1994227 - only needed if original is still present
IF NOT DOES_ENTITY_EXIST(GET_MISSION_START_VEHICLE_INDEX())
CREATE_VEHICLE_FOR_REPLAY(vehIndex_MissionReplayRestore, <<2704.0776, 4152.2397, 42.2514>>, 175.1930, FALSE, FALSE, FALSE, FALSE, FALSE) // Across from Maude's
CPRINTLN(DEBUG_MISSION, " IS_REPLAY_IN_PROGRESS - SETUP_FOR_REPLAY() creating vehicle for replay")
ELSE
CPRINTLN(DEBUG_MISSION, " IS_REPLAY_IN_PROGRESS - SETUP_FOR_REPLAY() skipped replay veh create since GET_MISSION_START_VEHICLE_INDEX() still exists")
ENDIF
START_REPLAY_SETUP(<<2718.6489, 4147.2075, 42.7043>>, 76.7892, FALSE)
RC_START_Z_SKIP()
// proc from initial scene so they match up
REPOSITION_PLAYER_VEHICLE_FOR_INTRO()
SETUP_AREA_FOR_MISSION(RC_MAUDE_1, TRUE, FALSE) // B*1544717 - reduce calls to clear areas this frame (not convinced this is a good idea since stuff might spawn in)
WAIT(0) // allow a frame for START_REPLAY_SETUP to process before calling END_REPLAY_SETUP()
WHILE NOT HAVE_MISSION_ASSETS_LOADED()
CPRINTLN(DEBUG_MISSION, " SETUP_FOR_REPLAY() waiting on assets to load")
WAIT(0)
ENDWHILE
END_REPLAY_SETUP()
RC_END_Z_SKIP()
eMissionStage = MISSION_STAGE_LEAVE_AREA
eSubStage = SS_SETUP
CPRINTLN(DEBUG_MISSION, " IS_REPLAY_IN_PROGRESS : SETUP_FOR_REPLAY() done setup after cutscene")
ENDIF
ENDPROC
/// PURPOSE:
/// handles the focus push when arriving to trigger the cutscene
/// basically a gives player cam a hint to focus on Maude and gets player walking over there
/// RETURNS:
/// TRUE if it's done
FUNC BOOL HAS_FOCUS_PUSH_FINSHED()
// don't do anything for replay
IF IS_REPLAY_IN_PROGRESS()
OR IS_REPEAT_PLAY_ACTIVE()
OR IS_REPLAY_BEING_SET_UP()
RETURN TRUE
ENDIF
// setup the hint camera or just turn to face if close already
IF iFocusPushStage = 0
IF IS_ENTITY_ALIVE(sRCLauncherDataLocal.pedID[0])
IF NOT IS_ENTITY_IN_RANGE_ENTITY(PLAYER_PED_ID(), sRCLauncherDataLocal.pedID[0], 7.0) // don't trigger if we are close
SET_GAMEPLAY_ENTITY_HINT(sRCLauncherDataLocal.pedID[0], (<<0, 0, 0>>), TRUE, -1, DEFAULT_INTERP_IN_TIME)
SET_GAMEPLAY_HINT_FOLLOW_DISTANCE_SCALAR(0.35)
SET_GAMEPLAY_HINT_CAMERA_RELATIVE_SIDE_OFFSET(-0.8) // over left shoulder // -0.01) over right shoulder
SET_GAMEPLAY_HINT_CAMERA_RELATIVE_VERTICAL_OFFSET(0.1) //-0.05)
SET_GAMEPLAY_HINT_BASE_ORBIT_PITCH_OFFSET(0.0)
SET_GAMEPLAY_HINT_FOV(35.0)
SET_GAMEPLAY_HINT_CAMERA_BLEND_TO_FOLLOW_PED_MEDIUM_VIEW_MODE(TRUE)
IF NOT IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
TASK_FOLLOW_TO_OFFSET_OF_ENTITY(PLAYER_PED_ID(), sRCLauncherDataLocal.pedID[0], <<0, 1.2, 0>>, PEDMOVEBLENDRATIO_WALK)
CPRINTLN(DEBUG_MISSION, " HAS_FOCUS_PUSH_FINSHED() : hint cam set with goto task ****")
ENDIF
iFocusPushTimer = GET_GAME_TIMER()
ELSE
IF NOT IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
TASK_TURN_PED_TO_FACE_ENTITY(PLAYER_PED_ID(), sRCLauncherDataLocal.pedID[0])
CPRINTLN(DEBUG_MISSION, " HAS_FOCUS_PUSH_FINSHED() : turn to face task only")
ENDIF
iFocusPushTimer = -1
ENDIF
TASK_LOOK_AT_ENTITY(PLAYER_PED_ID(), sRCLauncherDataLocal.pedID[0], 4000)
ENDIF
iFocusPushStage++
CPRINTLN(DEBUG_MISSION, " HAS_FOCUS_PUSH_FINSHED() : iFocusPushStage++ =", iFocusPushStage)
// wait for the timer to finsh
ELIF iFocusPushStage = 1
IF iFocusPushTimer = -1
OR (GET_GAME_TIMER() - iFocusPushTimer) > 3000 // hint needs to remain for a second (takes 3 seconds to interpolate)
OR (IS_ENTITY_ALIVE(sRCLauncherDataLocal.pedID[0])
AND IS_ENTITY_IN_RANGE_ENTITY(PLAYER_PED_ID(), sRCLauncherDataLocal.pedID[0], 4.5)) // range at which player walks into scene from
RETURN TRUE
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// Starts up the vehicle engine after the intro if it is a plane
/// Fixes B*1935165 - Parking a Besra at the mission trigger causes the plane to be non-functional after the cutscene
PROC RESTART_PLAYER_PLANE_AFTER_CUTSCENE()
VEHICLE_INDEX veh = GET_PLAYERS_LAST_VEHICLE()
IF NOT IS_ENTITY_ALIVE(veh)
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), " : RESTART_PLAYER_PLANE_AFTER_CUTSCENE() : FAILED - PLAYER'S LAST VEHICLE IS DEAD? - TRY RANDOM VEHICLE IN SPHERE - Framecount : ", GET_FRAME_COUNT())
veh = GET_RANDOM_VEHICLE_IN_SPHERE(vRespotVehicleCoord, 10.0, DUMMY_MODEL_FOR_SCRIPT, VEHICLE_SEARCH_FLAG_RETURN_PLANES_ONLY | VEHICLE_SEARCH_FLAG_RETURN_MISSION_VEHICLES | VEHICLE_SEARCH_FLAG_RETURN_RANDOM_VEHICLES)
IF NOT IS_ENTITY_ALIVE(veh)
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), " : RESTART_PLAYER_PLANE_AFTER_CUTSCENE() : FAILED - TRY RANDOM VEHICLE IN SPHERE IS NULL - Framecount : ", GET_FRAME_COUNT())
EXIT
ENDIF
ENDIF
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), " : RESTART_PLAYER_PLANE_AFTER_CUTSCENE() : TURNING VEHICLE ENGINE BACK ON - Framecount : ", GET_FRAME_COUNT())
SET_VEHICLE_ENGINE_ON(veh, TRUE, TRUE)
ENDPROC
/// PURPOSE:
/// Plays the mocap cutscene - "maude_mcs_1"
PROC STAGE_CUTSCENE()
SWITCH eSubStage
CASE SS_SETUP
RC_REQUEST_CUTSCENE("MAUDE_MCS_1")
IF IS_ENTITY_ALIVE(pedMaude)
IF CAN_REQUEST_ASSETS_FOR_CUTSCENE_ENTITY()
SET_CUTSCENE_PED_COMPONENT_VARIATION_FROM_PED(sSceneHandle_Maude, pedMaude)
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), " : STAGE_CUTSCENE - SET_CUTSCENE_PED_COMPONENT_VARIATION_FROM_PED Maude set this frame : ", GET_FRAME_COUNT())
ENDIF
ENDIF
RC_PLAYER_TRIGGER_SCENE_LOCK_IN() // prevent player controls (keeps movement) whilst waiting for foucs push to finish and mocap to trigger
IF NOT IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID()) // B*1394562 - ensure player is out the veh before launching cutscene, RC_PLAYER_TRIGGER_SCENE_LOCK_IN handles exit vehicle
IF HAS_FOCUS_PUSH_FINSHED() // see B*1424962
IF RC_IS_CUTSCENE_OK_TO_START(TRUE)
// Grab Maude ped
RC_SET_ENTITY_PROOFS_FOR_CUTSCENE(sRCLauncherDataLocal, FALSE)
ASSIGN_PED_INDEX(pedMaude, sRCLauncherDataLocal.pedID[0])
ASSIGN_OBJECT_INDEX(objMaudeChair, sRCLauncherDataLocal.objID[0])
ASSIGN_OBJECT_INDEX(objMaudeLaptop, sRCLauncherDataLocal.objID[1])
GET_HANDLE_TO_MAUDES_RADIO()
REGISTER_ENTITY_FOR_CUTSCENE(PLAYER_PED_ID(), sSceneHandle_Trevor, CU_ANIMATE_EXISTING_SCRIPT_ENTITY)
IF IS_ENTITY_ALIVE(pedMaude)
REGISTER_ENTITY_FOR_CUTSCENE(pedMaude, sSceneHandle_Maude, CU_ANIMATE_EXISTING_SCRIPT_ENTITY)
ENDIF
IF IS_ENTITY_ALIVE(objMaudeChair)
REGISTER_ENTITY_FOR_CUTSCENE(objMaudeChair, sSceneHandle_MaudeChair, CU_ANIMATE_EXISTING_SCRIPT_ENTITY)
ENDIF
IF IS_ENTITY_ALIVE(objMaudeLaptop)
REGISTER_ENTITY_FOR_CUTSCENE(objMaudeLaptop, sSceneHandle_MaudeLaptop, CU_ANIMATE_EXISTING_SCRIPT_ENTITY)
ENDIF
REPLAY_START_EVENT(REPLAY_IMPORTANCE_HIGHEST)
START_CUTSCENE()
WAIT(0) //needed because cutscene doesn't start straight away, causing player to see vehicles getting removed.
IF IS_GAMEPLAY_HINT_ACTIVE()
STOP_GAMEPLAY_HINT()
ENDIF
RC_CLEANUP_LAUNCHER() // ensure called same frame as mission blocking area are setup
CPRINTLN(DEBUG_MISSION, "DOES SNAPSHOT VEHICLE EXIST = ", DOES_ENTITY_EXIST(g_startSnapshot.mVehicleIndex))
RC_START_CUTSCENE_MODE(<< 2727.58, 4144.19, 43.95 >>, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE) //has to be after start_cutscene and wait(0)
REPOSITION_PLAYER_VEHICLE_FOR_INTRO()
// proc from initial scene so they match up
SETUP_AREA_FOR_MISSION(RC_MAUDE_1, TRUE, FALSE) // B*1544717 - reduce calls to clear areas this frame (not convinced this is a good idea since stuff might spawn in)
HAVE_MISSION_ASSETS_LOADED()
bHasSetExitStateFromIntroMocapForGameplayCam = FALSE
eSubStage = SS_UPDATE
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), " : STAGE_CUTSCENE - ", "SS_SETUP done framecount : ", GET_FRAME_COUNT())
ENDIF
ELSE
SET_SCRIPTS_SAFE_FOR_CUTSCENE(TRUE)
ENDIF
ELSE
SET_SCRIPTS_SAFE_FOR_CUTSCENE(TRUE)
ENDIF
BREAK
CASE SS_UPDATE
// set exit state for Maude on her chair
IF IS_ENTITY_ALIVE(objMaudeChair)
IF IS_PED_UNINJURED(pedMaude)
// Set exit state for Maude
IF CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY(sSceneHandle_Maude)
AND CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY(sSceneHandle_MaudeChair)
IF HAS_ANIM_DICT_LOADED("special_ped@maude@base")
INT iEntitySyncedSceneFlags
iMaudeSyncSceneIndex = CREATE_SYNCHRONIZED_SCENE(<< 2727.40, 4145.56, 43.68 >>, << 0.0, 0.0, -92.17 >>)
SET_SYNCHRONIZED_SCENE_LOOPED(iMaudeSyncSceneIndex, TRUE)
SET_SYNCHRONIZED_SCENE_HOLD_LAST_FRAME(iMaudeSyncSceneIndex, FALSE)
TASK_SYNCHRONIZED_SCENE(pedMaude, iMaudeSyncSceneIndex, "special_ped@maude@base", "base", INSTANT_BLEND_IN, NORMAL_BLEND_OUT,
SYNCED_SCENE_ABORT_ON_WEAPON_DAMAGE | SYNCED_SCENE_LOOP_WITHIN_SCENE | SYNCED_SCENE_ACTIVATE_RAGDOLL_ON_COLLISION | SYNCED_SCENE_VEHICLE_ABORT_ON_LARGE_IMPACT)
iEntitySyncedSceneFlags = 0
iEntitySyncedSceneFlags = ENUM_TO_INT(SYNCED_SCENE_ABORT_ON_WEAPON_DAMAGE)
iEntitySyncedSceneFlags = ENUM_TO_INT(SYNCED_SCENE_LOOP_WITHIN_SCENE)
iEntitySyncedSceneFlags = ENUM_TO_INT(SYNCED_SCENE_ACTIVATE_RAGDOLL_ON_COLLISION)
iEntitySyncedSceneFlags = ENUM_TO_INT(SYNCED_SCENE_VEHICLE_ABORT_ON_LARGE_IMPACT)
PLAY_SYNCHRONIZED_ENTITY_ANIM(objMaudeChair, iMaudeSyncSceneIndex, "base_chair", "special_ped@maude@base", INSTANT_BLEND_IN, NORMAL_BLEND_OUT, iEntitySyncedSceneFlags)
SET_PED_KEEP_TASK(pedMaude, TRUE)
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), " : STAGE_INTRO_MOCAP_SCENE - set sync Scene pedMaude and sSceneHandle_MaudeChair - FC = ", GET_FRAME_COUNT())
ENDIF
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), " : STAGE_INTRO_MOCAP_SCENE - CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY - pedMaude and sSceneHandle_MaudeChair - FC = ", GET_FRAME_COUNT())
ENDIF
ENDIF
ENDIF
// Set exit state for Trevor
IF CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY(sSceneHandle_Trevor)
REPLAY_STOP_EVENT()
IF WAS_CUTSCENE_SKIPPED()
AND IS_SCREEN_FADED_OUT()
SET_GAMEPLAY_CAM_RELATIVE_HEADING(0.0)
SET_GAMEPLAY_CAM_RELATIVE_PITCH(0.0)
CPRINTLN(DEBUG_MISSION, "STAGE_CUTSCENE - ", "SS_UPDATE - Camera - set skipped mocap Frame Count : ", GET_FRAME_COUNT())
ENDIF
FORCE_PED_MOTION_STATE(PLAYER_PED_ID(), MS_ON_FOOT_WALK, FALSE, FAUS_CUTSCENE_EXIT)
SIMULATE_PLAYER_INPUT_GAIT(PLAYER_ID(), PEDMOVEBLENDRATIO_WALK, 2000)
bHasSetExitStateFromIntroMocapForGameplayCam = TRUE // stop setting the gameplay cam now.
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), " : STAGE_CUTSCENE : ", "SS_UPDATE * done - bHasSetExitStateFromIntroMocapForGameplayCam set TRUE by can set exit state for Trevor framecount = ", GET_FRAME_COUNT())
ENDIF
// unfortunately the only way to ensure the mocap camera blends out to gameplay cam at a sensible position is to spam this until the player's character exit state has fired
IF NOT bHasSetExitStateFromIntroMocapForGameplayCam
SET_GAMEPLAY_CAM_RELATIVE_HEADING(0.0)
SET_GAMEPLAY_CAM_RELATIVE_PITCH(0.0)
ENDIF
IF NOT IS_CUTSCENE_PLAYING()
eSubStage = SS_CLEANUP
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), " : STAGE_CUTSCENE - ", "SS_UPDATE done framecount : ", GET_FRAME_COUNT())
ENDIF
BREAK
CASE SS_CLEANUP
IF IS_CUTSCENE_PLAYING()
STOP_CUTSCENE()
ELSE
IF HAS_CUTSCENE_LOADED()
REMOVE_CUTSCENE()
ENDIF
IF IS_GAMEPLAY_HINT_ACTIVE()
STOP_GAMEPLAY_HINT()
ENDIF
RC_END_CUTSCENE_MODE()
RESTART_PLAYER_PLANE_AFTER_CUTSCENE()
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), " : STAGE_CUTSCENE : ", "SS_CLEANUP * done framecount : ", GET_FRAME_COUNT())
eMissionStage = MISSION_STAGE_LEAVE_AREA
eSubStage = SS_SETUP
ENDIF
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE:
/// Additional state to leave Maude's after the mocap for B*1496815
PROC STAGE_LEAVE_THE_AREA()
SWITCH eSubStage
CASE SS_SETUP
// get handle to Maude's table (done set as mission entity since created by map instead uses para on DOES_OBJECT_OF_TYPE_EXIST_AT_COORDS)
IF NOT DOES_ENTITY_EXIST(objMaudeTable)
IF DOES_OBJECT_OF_TYPE_EXIST_AT_COORDS(<< 2727.40, 4145.56, 43.68 >>, 10.0, prop_table_03b)
objMaudeTable = GET_CLOSEST_OBJECT_OF_TYPE(<< 2727.40, 4145.56, 43.68 >>, 10.0, prop_table_03b, TRUE)
IF IS_ENTITY_ALIVE(objMaudeTable)
SET_ENTITY_COORDS(objMaudeTable, << 2727.40, 4145.56, 43.68 >>)
SET_ENTITY_HEADING(objMaudeTable, -92.17)
FREEZE_ENTITY_POSITION(objMaudeTable, TRUE)
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), " : STAGE_CUTSCENE : ", " SS_CLEANUP :grabbed handle to table")
ENDIF
ENDIF
ENDIF
IF IS_PED_UNINJURED(pedMaude)
IF NOT IS_PED_HEADTRACKING_PED(pedMaude, PLAYER_PED_ID())
TASK_LOOK_AT_ENTITY(pedMaude, PLAYER_PED_ID(), -1)
ENDIF
SET_PED_KEEP_TASK(pedMaude, TRUE)
ENDIF
REQUEST_ADDITIONAL_TEXT("MAUDE1", MISSION_TEXT_SLOT)
IF HAS_ADDITIONAL_TEXT_LOADED(MISSION_TEXT_SLOT)
PRINT_NOW("MAUDE_01", DEFAULT_GOD_TEXT_TIME, 0) // Leave the area.
iTimer_MaudeDialogue = GET_GAME_TIMER()
eSubStage = SS_UPDATE
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), GET_THIS_SCRIPT_NAME(), " : STAGE_LEAVE_AREA_MAUDES - SS_SETUP done framecount : ", GET_FRAME_COUNT())
ELSE
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), GET_THIS_SCRIPT_NAME(), " : STAGE_LEAVE_AREA_MAUDES - loading text slot framecount : ", GET_FRAME_COUNT())
ENDIF
BREAK
CASE SS_UPDATE
VECTOR vMaudePos
VECTOR vPlayerPos
vPlayerPos = GET_ENTITY_COORDS(PLAYER_PED_ID())
IF IS_PED_UNINJURED(pedMaude)
vMaudePos = GET_ENTITY_COORDS(pedMaude, FALSE)
IF NOT SHOULD_MAUDE_FLEE()
IF VDIST2(vMaudePos, GET_ENTITY_COORDS(PLAYER_PED_ID(), FALSE)) > (120*120)
IF NOT IS_SPHERE_VISIBLE(vMaudePos, 2.5)
OR IS_ENTITY_OCCLUDED(pedMaude)
eSubStage = SS_CLEANUP
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), GET_THIS_SCRIPT_NAME(), " : STAGE_LEAVE_AREA_MAUDES - SS_UPDATE done framecount : ", GET_FRAME_COUNT())
ENDIF
ELSE
TRIGGER_MAUDE_AMBIENT_MISSION_PASSED_DIALOGUE(vMaudePos, vPlayerPos)
ENDIF
ELSE
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), " : STAGE_LEAVE_THE_AREA -> ", "MISSION_STAGE_MISSION_FAILED_WAIT_FOR_FADE : Maude should flee framecount : ", GET_FRAME_COUNT())
eFailReason = FAIL_REASON_MAUDE_SPOOKED
eMissionStage = MISSION_STAGE_MISSION_FAILED_WAIT_FOR_FADE
eSubStage = SS_SETUP
ENDIF
ELSE
IF DOES_ENTITY_EXIST(pedMaude)
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), " : STAGE_LEAVE_THE_AREA -> ", "MISSION_STAGE_MISSION_FAILED_WAIT_FOR_FADE : Maude injured framecount : ", GET_FRAME_COUNT())
eFailReason = FAIL_REASON_MAUDE_DEAD
eMissionStage = MISSION_STAGE_MISSION_FAILED_WAIT_FOR_FADE
eSubStage = SS_SETUP
ENDIF
ENDIF
BREAK
CASE SS_CLEANUP
KILL_ANY_ONGOING_MAUDE_MISSION_PASSED_DIALOGUE(FALSE)
IF IS_THIS_PRINT_BEING_DISPLAYED("MAUDE_01") // Leave the area.
CLEAR_THIS_PRINT("MAUDE_01")
ENDIF
SAFE_DELETE_PED(pedMaude)
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), GET_THIS_SCRIPT_NAME(), " : STAGE_LEAVE_AREA_MAUDES - SS_CLEANUP done framecount : ", GET_FRAME_COUNT())
Script_Passed()
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE:
/// Waits for the screen to fade out then updates failed reason
PROC STAGE_MISSION_FAILED_WAIT_FOR_FADE()
STRING sFailReason = NULL
SWITCH eSubStage
CASE SS_SETUP
CLEAR_PRINTS()
CLEAR_HELP()
KILL_ANY_ONGOING_MAUDE_MISSION_PASSED_DIALOGUE()
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
KILL_ANY_CONVERSATION()
ENDIF
//DELETE_ALL_MISSION_BLIPS()
// ensure these aren't frozen for flee
IF DOES_ENTITY_EXIST(objMaudeLaptop)
FREEZE_ENTITY_POSITION(objMaudeLaptop, FALSE)
ENDIF
IF DOES_ENTITY_EXIST(objMaudeTable)
FREEZE_ENTITY_POSITION(objMaudeTable, FALSE)
ENDIF
// set the fail reason
IF eFailReason = FAIL_REASON_MAUDE_SPOOKED
REQUEST_ANIM_DICT("special_ped@maude@exit_flee") // begin request for flee anim
// flee comment from Maude
IF IS_PED_UNINJURED(pedMaude)
REMOVE_PED_FOR_DIALOGUE(sDialogue, 3) // leave area comments - remove Maude
MAKE_PED_SCREAM(pedMaude, FALSE)
IF NOT IS_AMBIENT_SPEECH_PLAYING(pedMaude)
IF IS_ENTITY_IN_RANGE_COORDS(pedMaude, GET_ENTITY_COORDS(PLAYER_PED_ID(), FALSE), 35.0)
STOP_PED_SPEAKING(pedMaude, FALSE)
PLAY_PED_AMBIENT_SPEECH_WITH_VOICE(pedMaude, "GENERIC_FRIGHTENED_HIGH", "MAUDE", SPEECH_PARAMS_FORCE) // GENERIC_SHOCKED_HIGH
CPRINTLN(DEBUG_BAIL_BOND, GET_THIS_SCRIPT_NAME(), " : TRIGGER_MAUDE_FLEE_DIALOGUE_LINE - requested to trigger ambient speech line GENERIC_FRIGHTENED_HIGH")
ENDIF
ELSE
CPRINTLN(DEBUG_BAIL_BOND, GET_THIS_SCRIPT_NAME(), " : TRIGGER_MAUDE_FLEE_DIALOGUE_LINE - failed already ambient Maude speech playing")
ENDIF
ENDIF
IF SET_MAUDE_PLAY_FLEE_EXIT_ANIM()
bSetMaudeFleeSyncSceneExit = TRUE
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), " : STAGE_FAILED_WAIT_FOR_FADE : maude exit sync scene done")
ENDIF
sFailReason = "MAUDE_F1" // ~w~Maude was spooked.~s~
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), "STAGE_FAILED_WAIT_FOR_FADE string set : BB_FAILED_MAUDE_ATTACKED")
ELIF eFailReason = FAIL_REASON_MAUDE_DEAD
sFailReason = "MAUDE_F2" // ~w~Maude died.~s~
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), "STAGE_FAILED_WAIT_FOR_FADE string set : BB_FAILED_MAUDE_DIED")
ELSE
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), "STAGE_FAILED_WAIT_FOR_FADE string set : FAIL_REASON_DEFAULT")
ENDIF
//Check if fail reason needs to be displayed
IF eFailReason = FAIL_REASON_DEFAULT
RANDOM_CHARACTER_FAILED()
ELSE
RANDOM_CHARACTER_FAILED_WITH_REASON(sFailReason)
ENDIF
eSubStage = SS_UPDATE
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), "STAGE_FAILED_WAIT_FOR_FADE - SS_SETUP done")
BREAK
CASE SS_UPDATE
IF GET_MISSION_FLOW_SAFE_TO_CLEANUP()
// Do a check here to see if we need to warp the player at all
// (only set the fail warp locations if we can't leave the player where he was)
//---- Do any specific cleanup here----
CLEANUP_ALL_MISSION_ENTITIES(TRUE)
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), "STAGE_FAILED_WAIT_FOR_FADE - SS_UPDATE done")
Script_Cleanup()
ELSE
// not finished fading out
IF eFailReason = FAIL_REASON_MAUDE_SPOOKED
IF IS_PED_UNINJURED(pedMaude)
// Handle Maude's flee exit
IF NOT bSetMaudeFleeSyncSceneExit
REQUEST_ANIM_DICT("special_ped@maude@exit_flee") // begin request for flee anim
IF SET_MAUDE_PLAY_FLEE_EXIT_ANIM()
bSetMaudeFleeSyncSceneExit = TRUE
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), " : STAGE_FAILED_WAIT_FOR_FADE : maude exit sync scene done")
ENDIF
ELSE
IF IS_PED_UNINJURED(pedMaude)
IF NOT IsPedPerformingTask(pedMaude, SCRIPT_TASK_SMART_FLEE_PED)
IF NOT IS_PED_FLEEING(pedMaude)
IF NOT IS_ENTITY_PLAYING_ANIM(pedMaude, "special_ped@maude@exit_flee", "female_Flee_Table_Left_Maude")
SET_PED_FLEE_ATTRIBUTES(pedMaude, FA_USE_VEHICLE, FALSE)
SET_PED_FLEE_ATTRIBUTES(pedMaude, FA_RETURN_TO_ORIGNAL_POSITION_AFTER_FLEE, FALSE)
SET_PED_FLEE_ATTRIBUTES(pedMaude, FA_DISABLE_HANDS_UP, FALSE)
SET_PED_FLEE_ATTRIBUTES(pedMaude, FA_PREFER_PAVEMENTS, FALSE)
SET_PED_FLEE_ATTRIBUTES(pedMaude, FA_USE_COVER, FALSE)
SET_PED_FLEE_ATTRIBUTES(pedMaude, FA_LOOK_FOR_CROWDS, FALSE)
SET_PED_COMBAT_ATTRIBUTES(pedMaude, CA_ALWAYS_FIGHT, FALSE)
SET_PED_COMBAT_ATTRIBUTES(pedMaude, CA_ALWAYS_FLEE, TRUE)
TASK_SMART_FLEE_PED(pedMaude, PLAYER_PED_ID(), 50, -1) // keep small to inprove latency path finding issue (should be faded by dist reached)
SET_PED_KEEP_TASK(pedMaude, TRUE) // Keep scripted task
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), " : STAGE_FAILED_WAIT_FOR_FADE : maude flee task applied")
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
ENDIF
BREAK
ENDSWITCH
ENDPROC
// ===========================================================================================================
// DEBUG FUNCTIONS
// ===========================================================================================================
#IF IS_DEBUG_BUILD
/// PURPOSE:
/// reset's everything ready to retrigger the cutscene
PROC RESET_CUTSCENE()
WAIT_FOR_CUTSCENE_TO_STOP()
RC_END_CUTSCENE_MODE()
eMissionStage = MISSION_STAGE_CUTSCENE
eSubStage = SS_SETUP
// skip focus push
iFocusPushStage = 1
iFocusPushTimer = -1
ENDPROC
PROC DEBUG_Check_Debug_Keys()
INT iNewStage
IF IS_KEYBOARD_KEY_JUST_PRESSED(KEY_S)
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), " : DEBUG: S Skip")
WAIT_FOR_CUTSCENE_TO_STOP()
Script_Passed()
ELIF IS_KEYBOARD_KEY_JUST_PRESSED(KEY_J)
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), " : DEBUG: J Skip")
IF eMissionStage = MISSION_STAGE_CUTSCENE
IF eSubStage = SS_UPDATE //in script skips where we change the eSubStage, need to safe gaurd that the SS_SETUP has already had chance to run.
IF IS_CUTSCENE_PLAYING()
STOP_CUTSCENE()
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), " : DEBUG: J Skip MISSION_STAGE_CUTSCENE : STOPPING CUTSCENE framecount : ", GET_FRAME_COUNT())
ENDIF
ENDIF
ELIF eMissionStage = MISSION_STAGE_LEAVE_AREA
IF eSubStage = SS_UPDATE
eSubStage = SS_CLEANUP
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), " : DEBUG: J Skip MISSION_STAGE_LEAVE_AREA framecount : ", GET_FRAME_COUNT())
ENDIF
ENDIF
ELIF (IS_KEYBOARD_KEY_JUST_PRESSED(KEY_F))
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), " : DEBUG: F Skip")
WAIT_FOR_CUTSCENE_TO_STOP()
RC_END_CUTSCENE_MODE()
eMissionStage = MISSION_STAGE_MISSION_FAILED_WAIT_FOR_FADE
eSubStage = SS_SETUP
ELIF (IS_KEYBOARD_KEY_JUST_PRESSED(KEY_P))
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), " : DEBUG: P Skip")
RESET_CUTSCENE()
eSubStage = SS_SETUP
ELIF LAUNCH_MISSION_STAGE_MENU(mSkipMenu, iNewStage)
IF iNewStage = MAUDE_1_Z_SKIP_START_CUTSCENE
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), " : DEBUG: Z Skip to MAUDE_1_Z_SKIP_START_CUTSCENE")
RESET_CUTSCENE()
eSubStage = SS_SETUP
ELIF iNewStage = MAUDE_1_Z_SKIP_LEAVE_AREA
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), " : DEBUG: Z Skip to SS_SETUP")
WAIT_FOR_CUTSCENE_TO_STOP()
SET_GAMEPLAY_CAM_RELATIVE_HEADING(0.0)
SET_GAMEPLAY_CAM_RELATIVE_PITCH(0.0)
eMissionStage = MISSION_STAGE_LEAVE_AREA
eSubStage = SS_SETUP
ELIF iNewStage = MAUDE_1_Z_SKIP_MISSION_PASSED
CPRINTLN(DEBUG_MISSION, GET_THIS_SCRIPT_NAME(), " : DEBUG: Z Skip to SS_SETUP")
WAIT_FOR_CUTSCENE_TO_STOP()
eMissionStage = MISSION_STAGE_LEAVE_AREA
eSubStage = SS_CLEANUP
SET_GAMEPLAY_CAM_RELATIVE_HEADING(0.0)
SET_GAMEPLAY_CAM_RELATIVE_PITCH(0.0)
ENDIF
ENDIF
ENDPROC
#ENDIF
// ===========================================================================================================
// Script Loop
// ===========================================================================================================
SCRIPT(g_structRCScriptArgs sRCLauncherDataIn)
sRCLauncherDataLocal = sRCLauncherDataIn
RC_TakeEntityOwnership(sRCLauncherDataLocal)
// take ownership of the sync scene index from the initial scene (needs to happen before launcher terminates)
// take ownership from the initial scene (needs to happen before launcher terminates) must check is running, could get here from replay and not be setup
IF IS_SYNCHRONIZED_SCENE_RUNNING(sRCLauncherDataLocal.iSyncSceneIndex)
TAKE_OWNERSHIP_OF_SYNCHRONIZED_SCENE(sRCLauncherDataLocal.iSyncSceneIndex)
iMaudeSyncSceneIndex = sRCLauncherDataLocal.iSyncSceneIndex
CPRINTLN(DEBUG_MISSION, " TAKE_OWNERSHIP_OF_SYNCHRONIZED_SCENE : sRCLauncherDataLocal.iSyncSceneIndex = ", sRCLauncherDataLocal.iSyncSceneIndex,
" iMaudeSyncSceneIndex = ", iMaudeSyncSceneIndex)
ENDIF
SET_MISSION_FLAG(TRUE)
// Setup callback when player is killed, arrested or goes to multiplayer
IF (HAS_FORCE_CLEANUP_OCCURRED(DEFAULT_FORCE_CLEANUP_FLAGS|FORCE_CLEANUP_FLAG_DEBUG_MENU))
PRINT_LAUNCHER_DEBUG("Force cleanup [TERMINATING]")
Random_Character_Failed()
Script_Cleanup()
ENDIF
INIT_DATA()
IF IS_REPLAY_IN_PROGRESS() // handle replay checkpoints (only restart after intro available)
SETUP_FOR_REPLAY()
ENDIF
// Loop within here until the mission passes or fails
WHILE(TRUE)
REPLAY_CHECK_FOR_EVENT_THIS_FRAME("SF_Maude")
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
IF eMissionStage = MISSION_STAGE_CUTSCENE
STAGE_CUTSCENE()
ELIF eMissionStage = MISSION_STAGE_LEAVE_AREA
STAGE_LEAVE_THE_AREA()
ELIF eMissionStage = MISSION_STAGE_MISSION_FAILED_WAIT_FOR_FADE
STAGE_MISSION_FAILED_WAIT_FOR_FADE()
ENDIF
ENDIF
// Check debug completion/failure
#IF IS_DEBUG_BUILD
IF eMissionStage != MISSION_STAGE_MISSION_FAILED_WAIT_FOR_FADE
DEBUG_Check_Debug_Keys()
ENDIF
#ENDIF
WAIT(0)
ENDWHILE
// Script should never reach here. Always terminate with cleanup function.
ENDSCRIPT