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

489 lines
14 KiB
Python
Executable File

//////////////////////////////////////////////////////////////////////////////////////////
// //
// SCRIPT NAME : ambient_Tonya.sc //
// AUTHOR : //
// DESCRIPTION : Handles launching the Tonya mission via phonecall //
// //
//////////////////////////////////////////////////////////////////////////////////////////
//Compile out Title Update changes to header functions.
//Must be before includes.
//CONST_INT USE_TU_CHANGES 0 // Removed by Kenneth R.
// Includes
USING "commands_entity.sch"
USING "RC_helper_functions.sch"
USING "RC_launcher_public.sch"
USING "rich_presence_public.sch"
USING "savegame_public.sch"
// Enums
ENUM MAIN_STATE
MS_INIT,
MS_CHECK_FOR_CALL,
MS_PROCESS_PHONE_ACCEPT,
MS_PROCESS_PHONE_REFUSE,
MS_LAUNCH_MISSION,
MS_ON_MISSION,
MS_CLEANUP
ENDENUM
ENUM SUB_STATE
SS_SETUP,
SS_UPDATE,
SS_CLEANUP
ENDENUM
// Constants
CONST_INT XVERSION_NUMBER(101)
// Variables
MAIN_STATE eStage = MS_INIT
SUB_STATE sProgress = SS_SETUP
structPedsForConversation pedConversation
BOOL bCallActive = FALSE
BOOL bCallConnected = FALSE
THREADID missionThread
// -----------------------------------------------------------------------------------------------------------
// Script Cleanup
// -----------------------------------------------------------------------------------------------------------
/// PURPOSE:
/// Script Cleanup
PROC SCRIPT_CLEANUP()
CPRINTLN(DEBUG_AMBIENT, "Ambient - Tonya: SCRIPT_CLEANUP()")
// No longer require the script to be relaunched when loading from a savegame.
IF IS_THIS_RANDOM_CHARACTER_MISSION_COMPLETED(RC_TONYA_4)
OR IS_THIS_RANDOM_CHARACTER_MISSION_COMPLETED(RC_TONYA_5)
Remove_Script_From_Relaunch_List(LAUNCH_BIT_RC_AMB_TONYA)
ENDIF
TERMINATE_THIS_THREAD()
ENDPROC
// -----------------------------------------------------------------------------------------------------------
// Script Functions
// -----------------------------------------------------------------------------------------------------------
/// PURPOSE:
/// Is this towing mission allowed to launch
FUNC BOOL CAN_LAUNCH_TONYA_PHONE_MISSION()
// Mission checks
IF IS_CURRENTLY_ON_MISSION_TO_TYPE(MISSION_TYPE_STORY)
RETURN FALSE
ENDIF
IF IS_MISSION_AVAILABLE(SP_MISSION_FRANKLIN_1)
RETURN FALSE
ENDIF
IF IS_THIS_RANDOM_CHARACTER_MISSION_COMPLETED(RC_TONYA_3)
AND NOT GET_MISSION_FLOW_FLAG_STATE(FLOWFLAG_TONYA4_TEXT_RECEIVED)
RETURN FALSE
ELIF IS_THIS_RANDOM_CHARACTER_MISSION_COMPLETED(RC_TONYA_2)
AND NOT GET_MISSION_FLOW_FLAG_STATE(FLOWFLAG_TONYA3_TEXT_RECEIVED)
RETURN FALSE
ENDIF
// Player is wanted
IF (GET_PLAYER_WANTED_LEVEL(PLAYER_ID()) > 0)
RETURN FALSE
ENDIF
RETURN TRUE
ENDFUNC
/// PURPOSE:
/// Request and launch RCM script
PROC CUSTOM_REQUEST_AND_LAUNCH_RC(g_eRC_MissionIDs eMissionID)
// Get correct script name
STRING sScriptName
IF eMissionID = RC_TONYA_3
sScriptName = "Tonya3"
ELSE
sScriptName = "Tonya4"
ENDIF
// Load script
REQUEST_SCRIPT(sScriptName)
WHILE NOT HAS_SCRIPT_LOADED(sScriptName)
REQUEST_SCRIPT(sScriptName)
WAIT(0)
ENDWHILE
// Setup common requirements
RC_MISSION_STARTING(eMissionID)
// Launch script
missionThread = START_NEW_SCRIPT(sScriptName, MISSION_STACK_SIZE)
// Allow script to be released when no longer running
SET_SCRIPT_AS_NO_LONGER_NEEDED(sScriptName)
#IF IS_DEBUG_BUILD
//In debug build inform the autoplay system we are on a RC mission now.
g_txtFlowAutoplayRunningMission = sScriptName
#ENDIF
ENDPROC
/// PURPOSE:
/// Launch RCM through the phone call
FUNC BOOL CUSTOM_LAUNCH_RC_MISSION(g_eRC_MissionIDs eMissionID)
// NOTE: Need to stay in this loop until the mission is given permission to run.
// After first asking permission to run, a decision is usually made
// within a few frames - if it returns FALSE, check if it should terminate or not.
WHILE NOT RC_REQUEST_PERMISSION_TO_RUN(eMissionID)
// Not yet given permission to run, should the script terminate?
IF SHOULD_RC_TERMINATE(eMissionID)
PRINT_LAUNCHER_DEBUG("LAUNCH_RC_MISSION - Script denied by RC Controller")
RETURN FALSE
ENDIF
WAIT(0)
ENDWHILE
// NOTE: The Random Character mission is now safe to start so request the script and launch.
// The activity MUST trigger because scripts now think the game is OnMission.
CUSTOM_REQUEST_AND_LAUNCH_RC(eMissionID)
// Tell the playstats system that we're starting an RC mission.
g_structRCMissionsStatic sRCMissionDetails
Retrieve_Random_Character_Static_Mission_Details(eMissionID, sRCMissionDetails)
TEXT_LABEL tStatLabel = GET_RC_STAT_ID(eMissionID)
SCRIPT_PLAYSTATS_MISSION_STARTED(tStatLabel, sRCMissionDetails.rcStatVariation)
CPRINTLN(DEBUG_FLOW, "Flagging playstat MISSION STARTED for RC mission. Script:", sRCMissionDetails.rcScriptName, " Variation:", sRCMissionDetails.rcStatVariation, " RC Stat ID = ",tStatLabel)
// Set console rich presence values as we go on mission (friend dashboard status message).
SET_RICH_PRESENCE_FOR_SP_RC_MISSION(eMissionID)
// Store start snapshot if this isn't a replay
IF NOT IS_REPLAY_IN_PROGRESS()
IF eMissionID = RC_TONYA_3
Store_RC_Replay_Starting_Snapshot("Tonya3", TRUE)
ELSE
Store_RC_Replay_Starting_Snapshot("Tonya4", TRUE)
ENDIF
ENDIF
// Setup mission ready for stats
PRIME_STATS_FOR_RC_MISSION(eMissionID, sRCMissionDetails.rcScriptName)
RETURN TRUE
ENDFUNC
// -----------------------------------------------------------------------------------------------------------
// State Functions
// -----------------------------------------------------------------------------------------------------------
/// PURPOSE:
/// Script initialisation
PROC DO_INITALIZE()
// Ensure Tonya is a contact.
ADD_CONTACT_TO_PHONEBOOK(CHAR_TOW_TONYA, FRANKLIN_BOOK, FALSE)
// Update
eStage = MS_CHECK_FOR_CALL
sProgress = SS_SETUP
CPRINTLN(DEBUG_AMBIENT, "Ambient - Tonya: Setting stage to MS_CHECK_FOR_CALL()")
ENDPROC
/// PURPOSE:
/// Check for Franklin calling Tonya
PROC CHECK_FOR_CALL()
SWITCH sProgress
CASE SS_SETUP
bCallActive = FALSE
sProgress = SS_UPDATE
BREAK
CASE SS_UPDATE
// Check for contacting Tonya
IF IS_CALLING_CONTACT(CHAR_TOW_TONYA)
bCallActive = TRUE
ELSE
bCallActive = FALSE
ENDIF
// Franklin is calling Tonya...
IF bCallActive
// We are allowed to go on mission
IF CAN_LAUNCH_TONYA_PHONE_MISSION()
CPRINTLN(DEBUG_AMBIENT, "Ambient - Tonya: Setting stage to MS_PROCESS_PHONE_ACCEPT()")
eStage = MS_PROCESS_PHONE_ACCEPT
sProgress = SS_SETUP
ELSE
CPRINTLN(DEBUG_AMBIENT, "Ambient - Tonya: Setting stage to MS_PROCESS_PHONE_REFUSE()")
eStage = MS_PROCESS_PHONE_REFUSE
sProgress = SS_UPDATE
ENDIF
ENDIF
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE:
/// Phone call has been connected and going on mission
PROC PROCESS_PHONE_ACCEPT()
SWITCH sProgress
CASE SS_SETUP
IF NOT HAS_CELLPHONE_JUST_BEEN_FORCED_AWAY()
IF IS_CALLING_CONTACT(CHAR_TOW_TONYA)
// Add Franklin and Tonya
ADD_PED_FOR_DIALOGUE(pedConversation, 1, PLAYER_PED_ID(), "FRANKLIN")
ADD_PED_FOR_DIALOGUE(pedConversation, 3, NULL, "TONYA")
// Handle phone call for Tonya 4
IF IS_THIS_RANDOM_CHARACTER_MISSION_COMPLETED(RC_TONYA_3)
CPRINTLN(DEBUG_TRIGGER, "<TONYA> Initialising triggering call for Tonya4.")
PLAYER_CALL_CHAR_CELLPHONE(pedConversation, CHAR_TOW_TONYA, "TOWAUD", "TOW_CALL_02", CONV_PRIORITY_AMBIENT_HIGH)
// Phone call is for Tonya 3
ELSE
CPRINTLN(DEBUG_TRIGGER, "<TONYA> Initialising triggering call for Tonya3.")
PLAYER_CALL_CHAR_CELLPHONE(pedConversation, CHAR_TOW_TONYA, "TOWAUD", "TOW_CALL_01", CONV_PRIORITY_AMBIENT_HIGH)
ENDIF
bCallConnected = FALSE
sProgress = SS_UPDATE
ELSE
// Player has hung up too early
eStage = MS_CHECK_FOR_CALL
sProgress = SS_SETUP
ENDIF
ENDIF
BREAK
CASE SS_UPDATE
// Call has connected to Tonya
IF NOT bCallConnected
IF IS_CONTACT_IN_CONNECTED_CALL(CHAR_TOW_TONYA)
CPRINTLN(DEBUG_TRIGGER, "<TONYA> Noted the call connected for Tonya triggering call.")
bCallConnected = TRUE
ENDIF
ENDIF
// Check for call ending.
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
CPRINTLN(DEBUG_TRIGGER, "<TONYA> Noted the call ended for Tonya triggering call.")
IF NOT HAS_CELLPHONE_JUST_BEEN_FORCED_AWAY()
IF bCallConnected
// Attempt to launch RCM
CPRINTLN(DEBUG_AMBIENT, "Ambient - Tonya: Setting stage to MS_LAUNCH_MISSION()")
eStage = MS_LAUNCH_MISSION
sProgress = SS_SETUP
ELSE
// Player hasn't connected - try again
eStage = MS_PROCESS_PHONE_ACCEPT
sProgress = SS_SETUP
ENDIF
ELSE
CPRINTLN(DEBUG_TRIGGER, "<TONYA> The phone was forced away mid call. Call not considered complete.")
CPRINTLN(DEBUG_TRIGGER, "<TONYA> Returning to call setup stage.")
eStage = MS_PROCESS_PHONE_ACCEPT
sProgress = SS_SETUP
ENDIF
ENDIF
ELSE
CPRINTLN(DEBUG_TRIGGER, "<TONYA> The player died during the call. Call not considered complete.")
CPRINTLN(DEBUG_TRIGGER, "<TONYA> Returning to call setup stage.")
eStage = MS_PROCESS_PHONE_ACCEPT
sProgress = SS_SETUP
ENDIF
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE:
/// Cannot go on mission - Tonya will be engaged
PROC PROCESS_PHONE_REFUSE()
// Just wait until the player isn't calling Tonya.
IF NOT IS_CALLING_CONTACT(CHAR_TOW_TONYA)
eStage = MS_CHECK_FOR_CALL
sProgress = SS_SETUP
ENDIF
ENDPROC
/// PURPOSE:
/// Attempt to launch Tonya RC mission
PROC LAUNCH_TONYA_MISSION()
// Is the player close enough to start the mission off
IF IS_IT_SAFE_TO_TRIGGER_SCRIPT_TYPE(ST_RANDOM_CHARACTER)
// Work out mission to launch
g_eRC_MissionIDs eMissionID
// Pass through mission from repeat play
IF IS_REPEAT_PLAY_ACTIVE()
eMissionID = INT_TO_ENUM(g_eRC_MissionIDs, g_RepeatPlayData.iMissionIndex)
ELSE
IF IS_THIS_RANDOM_CHARACTER_MISSION_COMPLETED(RC_TONYA_3)
eMissionID = RC_TONYA_4
ELSE
eMissionID = RC_TONYA_3
ENDIF
ENDIF
// Launch the mission script
IF CUSTOM_LAUNCH_RC_MISSION(eMissionID)
// No need to update every frame
bCallActive = FALSE
// We are now on mission - keep ambient script running to detect completion
CPRINTLN(DEBUG_AMBIENT, "Ambient - Tonya: Setting stage to MS_ON_MISSION()")
eStage = MS_ON_MISSION
ELSE
// Permission has been refused - drop back to check for call state
eStage = MS_CHECK_FOR_CALL
ENDIF
sProgress = SS_SETUP
ENDIF
ENDPROC
/// PURPOSE:
/// Attempt to launch Tonya RC mission
PROC MONITOR_TONYA_MISSION()
// Mission script has finished...
IF NOT IS_THREAD_ACTIVE(missionThread)
// Phone call missions have been completed
IF IS_THIS_RANDOM_CHARACTER_MISSION_COMPLETED(RC_TONYA_4)
CPRINTLN(DEBUG_AMBIENT, "Ambient - Tonya: Setting stage to MS_CLEANUP()")
eStage = MS_CLEANUP
ELSE
CPRINTLN(DEBUG_AMBIENT, "Ambient - Tonya: Setting stage to MS_CHECK_FOR_CALL()")
eStage = MS_CHECK_FOR_CALL
ENDIF
sProgress = SS_SETUP
ENDIF
ENDPROC
//----------------------
// MAIN SCRIPT
//----------------------
SCRIPT
IF HAS_FORCE_CLEANUP_OCCURRED(FORCE_CLEANUP_FLAG_DEBUG_MENU|FORCE_CLEANUP_FLAG_SP_TO_MP|FORCE_CLEANUP_FLAG_REPEAT_PLAY)
CPRINTLN(DEBUG_AMBIENT, "Ambient - Tonya: FORCE CLEANUP")
SCRIPT_CLEANUP()
ENDIF
IF GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH (HASH("ambient_Tonya")) > 1
CPRINTLN(DEBUG_AMBIENT, "Ambient - Tonya: Attempting to launch with an instance already active...")
TERMINATE_THIS_THREAD()
ENDIF
IF IS_REPEAT_PLAY_ACTIVE()
CPRINTLN(DEBUG_AMBIENT, "Ambient - Tonya: Launching via repeat play!")
eStage = MS_LAUNCH_MISSION
ELSE
// Register the script so that it can be relaunched when loading from a savegame.
Register_Script_To_Relaunch_List(LAUNCH_BIT_RC_AMB_TONYA)
ENDIF
// We are a go-go!
CPRINTLN(DEBUG_AMBIENT, "Ambient - Tonya: Initializing version ", XVERSION_NUMBER)
// Main loop
WHILE (TRUE)
// Entity check
IS_PLAYER_PLAYING(PLAYER_ID())
// Cleanup checks when playing in flow
IF NOT IS_REPEAT_PLAY_ACTIVE()
// Immediately cleanup if this script has been completed via debug
IF GET_MISSION_FLOW_BITSET_BIT_STATE(FLOWBITSET_MINIGAME_ACTIVE, ENUM_TO_INT(MINIGAME_TOWING))
CPRINTLN(DEBUG_AMBIENT, "Ambient - Tonya: Cleaning up as towing minigame is active!")
SCRIPT_CLEANUP()
ENDIF
// Immediately cleanup when Tonya 4 is completed
IF IS_THIS_RANDOM_CHARACTER_MISSION_COMPLETED(RC_TONYA_4)
CPRINTLN(DEBUG_AMBIENT, "Ambient - Tonya: Cleaning up as Tonya 4 has been completed!")
SCRIPT_CLEANUP()
ENDIF
ENDIF
// Update current player
enumCharacterList ePlayer
ePlayer = GET_CURRENT_PLAYER_PED_ENUM()
// Current player is Michael or Trevor
IF ePlayer <> CHAR_FRANKLIN
// No need to update this script regularly
WAIT(5000)
// Only allow mission to trigger if we are Franklin
ELSE
// Script update
SWITCH eStage
CASE MS_INIT
DO_INITALIZE()
BREAK
CASE MS_CHECK_FOR_CALL
CHECK_FOR_CALL()
BREAK
CASE MS_PROCESS_PHONE_ACCEPT
PROCESS_PHONE_ACCEPT()
BREAK
CASE MS_PROCESS_PHONE_REFUSE
PROCESS_PHONE_REFUSE()
BREAK
CASE MS_LAUNCH_MISSION
LAUNCH_TONYA_MISSION()
BREAK
CASE MS_ON_MISSION
MONITOR_TONYA_MISSION()
BREAK
CASE MS_CLEANUP
SCRIPT_CLEANUP()
BREAK
ENDSWITCH
// No need to update every frame
IF NOT bCallActive
WAIT(1000)
ELSE
WAIT(0)
ENDIF
ENDIF
ENDWHILE
ENDSCRIPT