Files
2025-09-29 00:52:08 +02:00

480 lines
16 KiB
Python
Executable File

// *****************************************************************************************
//
// MISSION NAME : Epsilon2.sc
// AUTHOR : Aaron Gandaa
// DESCRIPTION : MICAHEL finds an empty store front at the address, he walks in.
//
// *****************************************************************************************
//Compile out Title Update changes to header functions.
//Must be before includes.
//CONST_INT USE_TU_CHANGES 0 // Removed by Kenneth R.
//----------------------
// INCLUDES
//----------------------
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 "RC_Helper_Functions.sch"
USING "CompletionPercentage_public.sch"
USING "email_public.sch"
USING "rgeneral_include.sch"
USING "initial_scenes_Epsilon.sch"
USING "commands_recording.sch"
//----------------------
// VARIABLES
//----------------------
CONST_INT MISSION_VERSION 101
CONST_INT MESSAGE_DELAY 15000
g_structRCScriptArgs sRCLauncherDataLocal
ENUM eRC_MainState
RC_MEET_MARNIE = 0,
RC_WAIT_FOR_PLAYER_TO_EXIT,
RC_CLEANUP
ENDENUM
ENUM eRC_SubState
SS_SETUP = 0,
SS_UPDATE,
SS_CLEANUP
ENDENUM
// Mission state
eRC_MainState m_eState = RC_MEET_MARNIE
eRC_SubState m_eSubState = SS_SETUP
MODEL_NAMES doorModel = V_ILev_EpsStoreDoor
INT iSendTextTimer = 0
BOOL bTriggeredMusic = FALSE
BOOL bMusicStopped = FALSE
BOOL bMessageSent = FALSE
BOOL bDoorLocked = FALSE
BOOL bMissionPassed = FALSE
#IF IS_DEBUG_BUILD
BOOL bDebug_PrintToTTY = TRUE
#ENDIF
// ===========================================================================================================
// Termination
// ===========================================================================================================
// -----------------------------------------------------------------------------------------------------------
// Script Cleanup
// -----------------------------------------------------------------------------------------------------------
/// PURPOSE:
/// Safely cleans up the script
PROC Script_Cleanup()
INT iPendingEMailID
// Ensure launcher is cleaned up
RC_CLEANUP_LAUNCHER()
// TODO: Move email into comms? We can reset donation in a code ID then...
IF NOT bMessageSent
AND (GET_DYNAMIC_EMAIL_THREAD_BUFFER_INDEX(DYNAMIC_THREAD_EPSILON_DONATE) = -1)
CPRINTLN(DEBUG_AMBIENT, "Epsilon 2 - PRIMING E-MAIL")
ASSIGN_BUFFER_TO_DYNAMIC_EMAIL_THREAD(DYNAMIC_THREAD_EPSILON_DONATE)
iPendingEMailID = PRIME_EMAIL_FOR_FIRING_INTO_DYNAMIC_THREAD_IN_HOURS(DYNAMIC_THREAD_EPSILON_DONATE, CULTDONATE5000, 1)
CPRINTLN(DEBUG_AMBIENT, "Epsilon 2 - PRIMING E-MAIL REFERENCE:", iPendingEMailID)
OVERRIDE_CONTENT_FOR_PENDING_DYNAMIC_EMAIL(iPendingEMailID, DYNAMIC_THREAD_EPSILON_DONATE, CULTDONATE5000, "EPS_EMAIL5K")
bMessageSent = TRUE
ELSE
CPRINTLN(DEBUG_AMBIENT, "Epsilon 2 - EPSILON E-MAIL THREAD ALREADY EXISTS")
ENDIF
// Reset donations - pity the fool who has donated more than asked for before this point..
CPRINTLN(DEBUG_RANDOM_CHAR, "Resetting donation to Epsilon Program for new mission request.")
g_savedGlobals.sRandomChars.g_iCurrentEpsilonPayment = 0
// If the mission was triggered then additional mission cleanup will be required.
IF (Random_Character_Cleanup_If_Triggered())
IF (Random_Character_Cleanup_If_Triggered())
#IF IS_DEBUG_BUILD
IF bDebug_PrintToTTY
CPRINTLN(DEBUG_MISSION, "...Random Character Script was triggered so additional cleanup required")
ENDIF
#ENDIF
ENDIF
ENDIF
SET_DOOR_STATE(DOORNAME_EPSILON2_STORAGE_ROOM, DOORSTATE_LOCKED)
SET_INTERIOR_CAPPED( INTERIOR_V_EPSILONISM, TRUE)
CLEAR_ADDITIONAL_TEXT(MISSION_TEXT_SLOT, TRUE)
g_quicksaveDisabledByScript = FALSE
//Cleanup the scene created by the launcher
RC_CleanupSceneEntities(sRCLauncherDataLocal)
TERMINATE_THIS_THREAD()
ENDPROC
// -----------------------------------------------------------------------------------------------------------
// Script Pass
// -----------------------------------------------------------------------------------------------------------
/// PURPOSE:
/// Adds needed contacts, completion %. Script passes, but for this mission it does not clean up here. The Player will have to exit the shop to truly close the mission
/// PARAMS:
/// None.
/// RETURNS:
/// N/A
PROC Script_Passed()
ADD_CONTACT_TO_PHONEBOOK(CHAR_MARNIE, MICHAEL_BOOK)
//Set epsilon step stat
INT iCurrent
STAT_GET_INT(NUM_EPSILON_STEP,iCurrent)
IF iCurrent < 4
STAT_SET_INT(NUM_EPSILON_STEP,4)
SET_ACHIEVEMENT_PROGRESS_SAFE(ENUM_TO_INT(ACH20),4)
CPRINTLN(debug_dan,"Epsilon progress:",4)
ENDIF
Random_Character_Passed(CP_RAND_C_EPS2, FALSE) // Don't want to clear the wanted level here in case the player causes some trouble and then walks away
ENDPROC
/// PURPOSE:
/// Sets the new mission state and initialises the substate.
/// PARAMS:
/// eRC_MainState in = new mission state
/// RETURNS:
/// N/A
PROC SetState(eRC_MainState in)
// Setup new mission state
m_eState = in
m_eSubState = SS_SETUP
ENDPROC
// ===========================================================================================================
// DEBUG FUNCTIONS
// ===========================================================================================================
#IF IS_DEBUG_BUILD
/// PURPOSE:
/// Check for Forced Pass or Fail
/// PARAMS:
/// None.
/// RETURNS:
/// N/A
PROC DEBUG_Check_Debug_Keys()
// Check for Pass
IF (IS_KEYBOARD_KEY_JUST_PRESSED(KEY_S) OR IS_KEYBOARD_KEY_JUST_PRESSED(KEY_J))
IF m_eState = RC_MEET_MARNIE
IF PREPARE_MUSIC_EVENT("EPS2_STOP")
IF TRIGGER_MUSIC_EVENT("EPS2_STOP")
#IF IS_DEBUG_BUILD IF bDebug_PrintToTTY CPRINTLN(DEBUG_MISSION, "Playing audio - EPS2_STOP")ENDIF #ENDIF
ENDIF
ENDIF
WAIT_FOR_CUTSCENE_TO_STOP()
SET_DOOR_STATE(DOORNAME_EPSILON2_STORAGE_ROOM, DOORSTATE_UNLOCKED)
RC_END_CUTSCENE_MODE()
// Set player location
SAFE_TELEPORT_ENTITY(PLAYER_PED_ID(), << 241.5036, 357.8237, 104.5874 >>, 66.5117) // Set player location
// Reset camera behind player
SET_GAMEPLAY_CAM_RELATIVE_PITCH(0.0)
SET_GAMEPLAY_CAM_RELATIVE_HEADING(0.0)
SET_DOOR_STATE(DOORNAME_EPSILON2_STORAGE_ROOM, DOORSTATE_FORCE_CLOSED_THIS_FRAME)
SET_DOOR_STATE(DOORNAME_EPSILON2_STORAGE_ROOM, DOORSTATE_LOCKED)
SetState(RC_CLEANUP)
ELSE
IF PREPARE_MUSIC_EVENT("EPS2_STOP")
IF TRIGGER_MUSIC_EVENT("EPS2_STOP")
#IF IS_DEBUG_BUILD IF bDebug_PrintToTTY CPRINTLN(DEBUG_MISSION, "Playing audio - EPS2_STOP")ENDIF #ENDIF
ENDIF
ENDIF
// Set player location
SAFE_TELEPORT_ENTITY(PLAYER_PED_ID(), << 241.5036, 357.8237, 104.5874 >>, 66.5117) // Set player location
// Reset camera behind player
SET_GAMEPLAY_CAM_RELATIVE_PITCH(0.0)
SET_GAMEPLAY_CAM_RELATIVE_HEADING(0.0)
SET_DOOR_STATE(DOORNAME_EPSILON2_STORAGE_ROOM, DOORSTATE_FORCE_CLOSED_THIS_FRAME)
SET_DOOR_STATE(DOORNAME_EPSILON2_STORAGE_ROOM, DOORSTATE_LOCKED)
SetState(RC_CLEANUP)
ENDIF
ENDIF
// Check for Fail
IF (IS_KEYBOARD_KEY_JUST_PRESSED(KEY_F))
IF m_eState <> RC_WAIT_FOR_PLAYER_TO_EXIT // player has passed the mission once he gets to this state
SAFE_TELEPORT_ENTITY(PLAYER_PED_ID(), << 241.5036, 357.8237, 104.5874 >>, 66.5117) // Set player location
WAIT_FOR_CUTSCENE_TO_STOP()
IF PREPARE_MUSIC_EVENT("EPS2_FAIL")
IF TRIGGER_MUSIC_EVENT("EPS2_FAIL")
#IF IS_DEBUG_BUILD IF bDebug_PrintToTTY CPRINTLN(DEBUG_MISSION, "Playing audio - EPS2_FAIL")ENDIF #ENDIF
ENDIF
ENDIF
Random_Character_Failed()
Script_Cleanup()
ENDIF
ENDIF
ENDPROC
#ENDIF
// ===========================================================================================================
// MISSION FUNCTIONS & PROCEDURES
// ===========================================================================================================
/// PURPOSE:
/// Triggers the mocap cutscene and completes mission once finished
/// PARAMS:
/// None.
/// RETURNS:
/// N/A
PROC STATE_MeetMarnie()
SWITCH m_eSubState
CASE SS_SETUP
#IF IS_DEBUG_BUILD
IF bDebug_PrintToTTY
CPRINTLN(DEBUG_MISSION, "Init RC_MEET_MARNIE")
ENDIF
#ENDIF
bTriggeredMusic = FALSE
bMusicStopped = FALSE
IF RC_IS_CUTSCENE_OK_TO_START()
// Cleanup all the actors in the scene. They are no longer needed so delete them...
RC_SET_ENTITY_PROOFS_FOR_CUTSCENE(sRCLauncherDataLocal, FALSE)
RC_CleanupSceneEntities(sRCLauncherDataLocal)
g_quicksaveDisabledByScript = TRUE // Make the quicksave button on the phone greyed-out until the script terminates
// Start mocap scene
RC_CLEANUP_LAUNCHER()
REPLAY_START_EVENT(REPLAY_IMPORTANCE_LOW)
START_CUTSCENE()
WAIT(0)
RESOLVE_VEHICLES_INSIDE_ANGLED_AREA(<<237.433273,359.011108,104.151039>>, <<245.558929,356.584595,108.070114>>, 6.5,
<<233.9369, 359.3106, 104.7277>>, 255.3827)
RESOLVE_VEHICLES_INSIDE_ANGLED_AREA(<<241.857742,360.671112,104.239014>>, <<245.365051,372.380188,108.030182>>, 10.0,
<<233.9369, 359.3106, 104.7277>>, 255.3827)
RC_START_CUTSCENE_MODE(<< 237.00, 360.00, 105.00 >>)
m_eSubState = SS_UPDATE // Monitor cutscene
ENDIF
BREAK
CASE SS_UPDATE
IF CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY("Michael")
REPLAY_STOP_EVENT()
#IF IS_DEBUG_BUILD IF bDebug_PrintToTTY CPRINTLN(DEBUG_MISSION, "Mike exit state")ENDIF #ENDIF
FORCE_PED_MOTION_STATE(PLAYER_PED_ID(), MS_ON_FOOT_IDLE, FALSE, FAUS_CUTSCENE_EXIT, TRUE)
ENDIF
IF CAN_SET_EXIT_STATE_FOR_CAMERA()
#IF IS_DEBUG_BUILD IF bDebug_PrintToTTY CPRINTLN(DEBUG_MISSION, "Camera exit state")ENDIF #ENDIF
// FORCE_PED_MOTION_STATE(PLAYER_PED_ID(), MS_ON_FOOT_IDLE, true, FAUS_CUTSCENE_EXIT, TRUE)
ENDIF
IF HAS_CUTSCENE_FINISHED()
#IF IS_DEBUG_BUILD IF bDebug_PrintToTTY CPRINTLN(DEBUG_MISSION, " Cutscene finished - ", " force unlock door") ENDIF #ENDIF
SET_DOOR_STATE(DOORNAME_EPSILON2_STORAGE_ROOM, DOORSTATE_UNLOCKED)
SET_GAMEPLAY_CAM_RELATIVE_PITCH(0.0)
SET_GAMEPLAY_CAM_RELATIVE_HEADING(0.0)
RC_END_CUTSCENE_MODE()
// Complete mission
m_eSubState = SS_CLEANUP
ELSE
SET_GAMEPLAY_CAM_RELATIVE_PITCH(0.0)
SET_GAMEPLAY_CAM_RELATIVE_HEADING(0.0)
IF NOT bTriggeredMusic
IF PREPARE_MUSIC_EVENT("EPS2_START")
IF TRIGGER_MUSIC_EVENT("EPS2_START")
#IF IS_DEBUG_BUILD IF bDebug_PrintToTTY CPRINTLN(DEBUG_MISSION, "Playing audio - EPS2_START")ENDIF #ENDIF
bTriggeredMusic = TRUE
ENDIF
ENDIF
ENDIF
IF (GET_CUTSCENE_TIME() >= 94789)
IF NOT bMusicStopped
IF PREPARE_MUSIC_EVENT("EPS2_STOP")
IF TRIGGER_MUSIC_EVENT("EPS2_STOP")
#IF IS_DEBUG_BUILD IF bDebug_PrintToTTY CPRINTLN(DEBUG_MISSION, "Playing audio - EPS2_STOP")ENDIF #ENDIF
ENDIF
ENDIF
bMusicStopped = TRUE
ENDIF
ENDIF
ENDIF
BREAK
CASE SS_CLEANUP
SetState(RC_WAIT_FOR_PLAYER_TO_EXIT)
#IF IS_DEBUG_BUILD
IF bDebug_PrintToTTY
CPRINTLN(DEBUG_MISSION, "Cleaned up RC_MEET_MARNIE")
ENDIF
#ENDIF
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE:
/// Pass mission but wait for Player to exit the shop door before completely closing the mission
/// PARAMS:
/// None.
/// RETURNS:
/// N/A
PROC STATE_WaitForPlayerToExit()
BOOL doorState
FLOAT doorRatio
GET_STATE_OF_CLOSEST_DOOR_OF_TYPE(doorModel, <<241.3494, 361.0303, 105.9036>>, doorState, doorRatio)
SWITCH m_eSubState
CASE SS_SETUP
#IF IS_DEBUG_BUILD
IF bDebug_PrintToTTY
CPRINTLN(DEBUG_MISSION, "Init RC_WAIT_FOR_PLAYER_TO_EXIT")
ENDIF
#ENDIF
bMessageSent = FALSE
bDoorLocked = FALSE
IF NOT bMusicStopped
IF PREPARE_MUSIC_EVENT("EPS2_STOP")
IF TRIGGER_MUSIC_EVENT("EPS2_STOP")
#IF IS_DEBUG_BUILD IF bDebug_PrintToTTY CPRINTLN(DEBUG_MISSION, "Playing audio - EPS2_STOP")ENDIF #ENDIF
ENDIF
ENDIF
bMusicStopped = TRUE
ENDIF
iSendTextTimer = GET_GAME_TIMER()
m_eSubState = SS_UPDATE
BREAK
CASE SS_UPDATE
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
IF NOT bMessageSent
AND ((GET_GAME_TIMER() - iSendTextTimer) > MESSAGE_DELAY)
IF REGISTER_EMAIL_FROM_CHARACTER_TO_PLAYER(EMAIL_EPSILON2_DONATE, CT_AMBIENT, BIT_MICHAEL, CHAR_MARNIE, 15000, 10000)
bMessageSent = TRUE
ENDIF
ENDIF
IF NOT bMissionPassed AND NOT IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<240.983170,358.868866,103.600464>>, <<246.031799,374.341461,109.650589>>, 9.000000)
IF NOT IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<240.983170,358.868866,103.600464>>, <<246.031799,374.341461,109.650589>>, 9.000000)
//B* 1772094: Instantly shut the door closed when off camera
IF NOT IS_SPHERE_VISIBLE(<<242.1,360.7,105.7>>, 1.5)
//DOOR_SYSTEM_SET_OPEN_RATIO(ENUM_TO_INT(DOORHASH_EPSILON2_STORAGE_ROOM), 0, FALSE, TRUE)
doorRatio=0
ENDIF
//B* 1772094: only pass the mission when the door is completely closed and locked
IF (ABSF(doorRatio) <= 0.05) AND NOT bMissionPassed
SET_DOOR_STATE(DOORNAME_EPSILON2_STORAGE_ROOM, DOORSTATE_FORCE_CLOSED_THIS_FRAME)
SET_DOOR_STATE(DOORNAME_EPSILON2_STORAGE_ROOM, DOORSTATE_LOCKED)
bDoorLocked = TRUE
bMissionPassed = TRUE
Script_Passed()
ENDIF
ENDIF
ENDIF
IF bMessageSent
AND bDoorLocked
m_eSubState = SS_CLEANUP
ENDIF
ENDIF
BREAK
CASE SS_CLEANUP
#IF IS_DEBUG_BUILD
IF bDebug_PrintToTTY
CPRINTLN(DEBUG_MISSION, "Clean up RC_WAIT_FOR_PLAYER_TO_EXIT")
ENDIF
#ENDIF
SetState(RC_CLEANUP)
BREAK
ENDSWITCH
ENDPROC
// ===========================================================================================================
// Script Loop
// ===========================================================================================================
SCRIPT(g_structRCScriptArgs sRCLauncherDataIn)
sRCLauncherDataLocal = sRCLauncherDataIn
RC_TakeEntityOwnership(sRCLauncherDataLocal)
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]")
IF m_eState <> RC_WAIT_FOR_PLAYER_TO_EXIT // player has passed the mission once he gets to this state
IF PREPARE_MUSIC_EVENT("EPS2_FAIL")
IF TRIGGER_MUSIC_EVENT("EPS2_FAIL")
#IF IS_DEBUG_BUILD IF bDebug_PrintToTTY CPRINTLN(DEBUG_MISSION, "Playing audio - EPS2_FAIL")ENDIF #ENDIF
ENDIF
ENDIF
Random_Character_Failed()
ELSE
Script_Passed()
ENDIF
Script_Cleanup()
ENDIF
IF Is_Replay_In_Progress() // Set up the initial scene for replays
g_bSceneAutoTrigger = TRUE
eInitialSceneStage = IS_REQUEST_SCENE
WHILE NOT SetupScene_EPSILON_2(sRCLauncherDataLocal)
WAIT(0)
ENDWHILE
g_bSceneAutoTrigger = FALSE
ENDIF
RC_REQUEST_CUTSCENE("ep_2_rcm")
SECURE_REQUEST_AND_LOAD_ADDITIONAL_TEXT("EPS2", MISSION_TEXT_SLOT, FALSE)
// Loop within here until the mission passes or fails
WHILE(TRUE)
REPLAY_CHECK_FOR_EVENT_THIS_FRAME("SF_AcTT")
WAIT(0)
UPDATE_MISSION_NAME_DISPLAYING(sRCLauncherDataLocal.sIntroCutscene)
SWITCH(m_eState)
CASE RC_MEET_MARNIE
STATE_MeetMarnie()
BREAK
CASE RC_WAIT_FOR_PLAYER_TO_EXIT
STATE_WaitForPlayerToExit()
BREAK
CASE RC_CLEANUP
Script_Cleanup()
BREAK
ENDSWITCH
// Check debug completion/failure
#IF IS_DEBUG_BUILD
DEBUG_Check_Debug_Keys()
#ENDIF
ENDWHILE
// Script should never reach here. Always terminate with cleanup function.
ENDSCRIPT