1880 lines
72 KiB
Scheme
Executable File
1880 lines
72 KiB
Scheme
Executable File
USING "globals.sch"
|
|
#if not USE_CLF_DLC
|
|
#if not USE_NRM_DLC
|
|
USING "randomChar_Public.sch"
|
|
#endif
|
|
#endif
|
|
USING "commands_brains.sch"
|
|
USING "RC_Helper_Functions.sch"
|
|
USING "replay_public.sch"
|
|
USING "RC_Area_public.sch"
|
|
USING "RC_Threat_public.sch"
|
|
USING "rich_presence_public.sch"
|
|
|
|
// *****************************************************************************************
|
|
// *****************************************************************************************
|
|
// *****************************************************************************************
|
|
//
|
|
// MISSION NAME : rc_launcher_public.sch
|
|
// CREATED : Sean F/ Dave R
|
|
// MAINTAINED : Andrew Minghella
|
|
// DESCRIPTION : Contains all public functions for the RC launcher.
|
|
//
|
|
// *****************************************************************************************
|
|
// *****************************************************************************************
|
|
// *****************************************************************************************
|
|
|
|
// ===========================================================================================================
|
|
// Idle / Beckon animation support
|
|
// ===========================================================================================================
|
|
/// PURPOSE: Has a launcher animation dictionary and idle animation been specified?
|
|
/// RETURNS: TRUE if the initial scenes have specified a dictionary and animation.
|
|
/// NOTE: The existence of valid strings does not guarantee that these are valid dictionaries/animations.
|
|
FUNC BOOL IS_LAUNCHER_IDLE_ANIM_SETUP(RC_LAUNCHER_ANIMS &launcherAnims)
|
|
IF IS_STRING_NULL_OR_EMPTY(launcherAnims.sDictionary)
|
|
OR IS_STRING_NULL_OR_EMPTY(launcherAnims.sIdleAnim)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE: Has a launcher beckon animation been specified?
|
|
/// RETURNS: TRUE if the initial scenes have specified a beckon animation.
|
|
/// NOTE: The existence of a valid string does not guarantee that this is a valid animation.
|
|
FUNC BOOL IS_LAUNCHER_BECKON_ANIM_SETUP(RC_LAUNCHER_ANIMS &launcherAnims)
|
|
IF IS_STRING_NULL_OR_EMPTY(launcherAnims.sBeckonAnim)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE: Sets up the idle animation and beckon animation (if one exists) for the initial scenes.
|
|
/// and loads the required animation dictionary.
|
|
/// If you need to set vAnimPos and vAnimRot, make sure you set their values after this function,
|
|
/// as they are initialised to zero vectors in here
|
|
PROC SETUP_LAUNCHER_ANIMS(RC_LAUNCHER_ANIMS &launcherAnims, STRING sDictionary, STRING sIdleAnim, STRING sBeckonAnim=NULL)
|
|
|
|
// Pass in dictionary and animation names
|
|
launcherAnims.sDictionary = sDictionary
|
|
launcherAnims.sIdleAnim = sIdleAnim
|
|
launcherAnims.sBeckonAnim = sBeckonAnim
|
|
|
|
// Request dictionary as priority
|
|
REQUEST_ANIM_DICT(launcherAnims.sDictionary)
|
|
|
|
// Reset position and rotation
|
|
launcherAnims.vAnimPos = <<0,0,0>>
|
|
launcherAnims.vAnimRot = <<0,0,0>>
|
|
|
|
// Initialise state
|
|
launcherAnims.eState = LAS_DONE_SETUP
|
|
launcherAnims.bBeckonPerformed = FALSE
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Checks if all of the launcher anims have loaded
|
|
/// PARAMS:
|
|
/// launcherAnims - launcher anim struct we're checking
|
|
/// RETURNS:
|
|
/// TRUE if anims loaded, false otherwise
|
|
FUNC BOOL HAVE_LAUNCHER_ANIMS_LOADED(RC_LAUNCHER_ANIMS &launcherAnims)
|
|
// Sanity check for valid strings
|
|
IF IS_LAUNCHER_IDLE_ANIM_SETUP(launcherAnims)
|
|
REQUEST_ANIM_DICT(launcherAnims.sDictionary)
|
|
IF HAS_ANIM_DICT_LOADED(launcherAnims.sDictionary)
|
|
RETURN TRUE
|
|
ENDIF
|
|
ELSE
|
|
SCRIPT_ASSERT("HAVE_LAUNCHER_ANIMS_LOADED called without first calling SETUP_LAUNCHER_ANIMS")
|
|
ENDIF
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE: Removes the RC launcher animation dictionary if one has been loaded.
|
|
/// RETURNS: FALSE if the idle animations aren't specified or the dictionary has already unloaded.
|
|
FUNC BOOL REMOVE_LAUNCHER_ANIM_DICT(RC_LAUNCHER_ANIMS &launcherAnims)
|
|
|
|
// Sanity check for valid strings
|
|
IF IS_LAUNCHER_IDLE_ANIM_SETUP(launcherAnims)
|
|
IF HAS_ANIM_DICT_LOADED(launcherAnims.sDictionary)
|
|
REMOVE_ANIM_DICT(launcherAnims.sDictionary)
|
|
|
|
// clear the anim names
|
|
launcherAnims.sDictionary = ""
|
|
launcherAnims.sIdleAnim = ""
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE: Checks if the RC ped needs to rotate to face the player.
|
|
FUNC BOOL DOES_PED_NEED_TO_FACE_PLAYER(g_eRC_MissionIDs eMissionID)
|
|
|
|
IF eMissionID = RC_EXTREME_1
|
|
OR eMissionID = RC_EXTREME_4
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
//PURPOSE: Checks that a particular conversation root is currently playing.
|
|
//PARAMS: RootToCheck - The conversation root we want to check is playing.
|
|
//RETURNS: TRUE if the root is currently playing, FALSE otherwise.
|
|
FUNC BOOL RC_IS_THIS_CONVERSATION_ROOT_PLAYING(STRING RootToCheck)
|
|
TEXT_LABEL_23 blah
|
|
blah = GET_CURRENTLY_PLAYING_STANDARD_CONVERSATION_ROOT()
|
|
IF ARE_STRINGS_EQUAL(blah,RootToCheck)
|
|
RETURN TRUE
|
|
ENDIF
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Checks if the conversation passed is ongoing and stops it if it is
|
|
/// PARAMS:
|
|
/// sRootToCheck - the conversation we are checking for
|
|
PROC RC_STOP_LAUNCHER_DIALOGUE(STRING sRootToCheck)
|
|
IF NOT IS_STRING_NULL_OR_EMPTY(sRootToCheck)
|
|
IF RC_IS_THIS_CONVERSATION_ROOT_PLAYING(sRootToCheck)
|
|
CPRINTLN(DEBUG_RANDOM_CHAR, "RC_STOP_LAUNCHER_DIALOGUE: Killing conversation: ", sRootToCheck)
|
|
KILL_FACE_TO_FACE_CONVERSATION_DO_NOT_FINISH_LAST_LINE()
|
|
ENDIF
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
/// PURPOSE: Play a conversation in full, looped, from the RC ped every so often
|
|
/// v_ped_pos = Pass in the vInCoords from your launcher file
|
|
/// s_dialogue_slot = Dialogue file to load eg EXT3AUD
|
|
/// s_dialogue_to_play = Root to play eg EXT_AMB
|
|
/// ped_dialogue_number = index of the ped in the Dialogue Star file
|
|
/// ped_dialogue_name = string name of the ped in the Dialogue Star file
|
|
/// i_time_delay_before_repeat = time delay before the ped will repeat dialogue
|
|
FUNC BOOL PLAY_LAUNCHER_FULL_CONVERSATION(g_structRCScriptArgs& sData, VECTOR v_ped_pos, STRING s_dialogue_slot, STRING s_dialogue_to_play, INT ped_dialogue_number, STRING ped_dialogue_name, INT i_time_delay_before_repeat = 5000)
|
|
|
|
IF IS_IT_SAFE_TO_TRIGGER_SCRIPT_TYPE(ST_RANDOM_CHARACTER)
|
|
|
|
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
|
|
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
|
|
AND IS_ENTITY_ALIVE(sData.pedID[0])
|
|
AND (GET_GAME_TIMER() - sData.iConversationTimer) > i_time_delay_before_repeat
|
|
AND GET_DISTANCE_BETWEEN_ENTITY_AND_COORD(PLAYER_PED_ID(), v_ped_pos) < 20.0
|
|
structPedsForConversation s_conversation
|
|
ADD_PED_FOR_DIALOGUE(s_conversation, ped_dialogue_number, sData.pedID[0], ped_dialogue_name)
|
|
ADD_NON_CRITICAL_STANDARD_CONVERSATION_TO_BUFFER(s_conversation, s_dialogue_slot, s_dialogue_to_play, CONV_PRIORITY_MEDIUM)
|
|
sData.iConversationTimer = GET_GAME_TIMER()
|
|
RETURN TRUE
|
|
ENDIF
|
|
ELSE
|
|
IF RC_IS_THIS_CONVERSATION_ROOT_PLAYING(s_dialogue_to_play)
|
|
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
|
|
IF GET_DISTANCE_BETWEEN_ENTITY_AND_COORD(PLAYER_PED_ID(), v_ped_pos) >= 20.0
|
|
KILL_ANY_CONVERSATION()
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
|
|
ENDFUNC
|
|
|
|
/// PURPOSE: Play ambient dialogue from the RC ped every so often
|
|
/// v_ped_pos = Pass in the vInCoords from your launcher file
|
|
/// s_dialogue_slot = Dialogue file to load eg EXT3AUD
|
|
/// s_dialogue_to_play = Root to play eg EXT_AMB
|
|
/// ped_dialogue_number = index of the ped in the Dialogue Star file
|
|
/// ped_dialogue_name = string name of the ped in the Dialogue Star file
|
|
/// i_time_delay_before_repeat = time delay before the ped will repeat dialogue
|
|
/// f_distance = the distance at which the dialogue will play from (default 20m)
|
|
FUNC BOOL PLAY_LAUNCHER_AMBIENT_DIALOGUE(g_structRCScriptArgs& sData, VECTOR v_ped_pos, STRING s_dialogue_slot, STRING s_dialogue_to_play, INT ped_dialogue_number, STRING ped_dialogue_name, INT i_time_delay_before_repeat = 5000, FLOAT f_distance = 20.0)
|
|
|
|
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
|
|
AND IS_ENTITY_ALIVE(sData.pedID[0])
|
|
AND NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
|
|
AND (GET_GAME_TIMER() - sData.iConversationTimer) > i_time_delay_before_repeat
|
|
AND GET_DISTANCE_BETWEEN_ENTITY_AND_COORD(PLAYER_PED_ID(), v_ped_pos) < f_distance
|
|
structPedsForConversation s_conversation
|
|
ADD_PED_FOR_DIALOGUE(s_conversation, ped_dialogue_number, sData.pedID[0], ped_dialogue_name)
|
|
ADD_NON_CRITICAL_STANDARD_CONVERSATION_TO_BUFFER(s_conversation, s_dialogue_slot, s_dialogue_to_play, CONV_PRIORITY_MEDIUM)
|
|
sData.iConversationTimer = GET_GAME_TIMER()
|
|
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE: Updates the launcher animations on scene peds
|
|
PROC UPDATE_LAUNCHER_ANIMS(PED_INDEX iPed, RC_LAUNCHER_ANIMS &launcherAnims, g_eRC_MissionIDs eMissionID)
|
|
|
|
// Entity check
|
|
IF IS_ENTITY_ALIVE(iPed)
|
|
|
|
// Process launcher animations
|
|
SWITCH launcherAnims.eState
|
|
|
|
CASE LAS_DONE_SETUP
|
|
|
|
// Does this mission have idle animations specified?
|
|
IF IS_LAUNCHER_IDLE_ANIM_SETUP(launcherAnims)
|
|
IF HAS_ANIM_DICT_LOADED(launcherAnims.sDictionary)
|
|
CLEAR_PED_TASKS_IMMEDIATELY(iPed)
|
|
// Want to disable leg and arm IK for Fanatic 1's idle animation, because the curb and fence at the location break the animation otherwise -IG
|
|
IF eMissionID != RC_FANATIC_1
|
|
IF ARE_VECTORS_EQUAL(launcherAnims.vAnimPos, <<0,0,0>>)
|
|
TASK_PLAY_ANIM(iPed, launcherAnims.sDictionary, launcherAnims.sIdleAnim, NORMAL_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_LOOPING|AF_USE_KINEMATIC_PHYSICS|AF_NOT_INTERRUPTABLE)
|
|
ELSE
|
|
//TASK_PLAY_ANIM_ADVANCED(iPed, launcherAnims.sDictionary, launcherAnims.sIdleAnim, launcherAnims.vAnimPos, launcherAnims.vAnimRot, INSTANT_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_LOOPING|AF_USE_KINEMATIC_PHYSICS|AF_NOT_INTERRUPTABLE)
|
|
// For some reason, the ped won't sit properly on his first anim task so using a sequence here
|
|
// Playing the beckon anim if that exists as it's shorter (the full anim has to play or it doesn't work)
|
|
SEQUENCE_INDEX siStart
|
|
OPEN_SEQUENCE_TASK(siStart)
|
|
IF IS_LAUNCHER_BECKON_ANIM_SETUP(launcherAnims)
|
|
TASK_PLAY_ANIM_ADVANCED(null, launcherAnims.sDictionary, launcherAnims.sBeckonAnim, launcherAnims.vAnimPos, launcherAnims.vAnimRot, INSTANT_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_USE_KINEMATIC_PHYSICS|AF_NOT_INTERRUPTABLE)
|
|
ELSE
|
|
TASK_PLAY_ANIM_ADVANCED(null, launcherAnims.sDictionary, launcherAnims.sIdleAnim, launcherAnims.vAnimPos, launcherAnims.vAnimRot, INSTANT_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_USE_KINEMATIC_PHYSICS|AF_NOT_INTERRUPTABLE)
|
|
ENDIF
|
|
TASK_PLAY_ANIM_ADVANCED(null, launcherAnims.sDictionary, launcherAnims.sIdleAnim, launcherAnims.vAnimPos, launcherAnims.vAnimRot, NORMAL_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_LOOPING|AF_USE_KINEMATIC_PHYSICS|AF_NOT_INTERRUPTABLE)
|
|
CLOSE_SEQUENCE_TASK(siStart)
|
|
TASK_PERFORM_SEQUENCE(iPed, siStart)
|
|
CLEAR_SEQUENCE_TASK(siStart)
|
|
ENDIF
|
|
ELSE
|
|
TASK_PLAY_ANIM_ADVANCED(iPed, launcherAnims.sDictionary, launcherAnims.sIdleAnim, launcherAnims.vAnimPos, launcherAnims.vAnimRot, NORMAL_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_LOOPING|AF_USE_KINEMATIC_PHYSICS|AF_NOT_INTERRUPTABLE, DEFAULT, DEFAULT, AIK_DISABLE_ARM_IK|AIK_DISABLE_LEG_IK)
|
|
ENDIF
|
|
launcherAnims.eState = LAS_PLAYING_IDLE
|
|
ELSE
|
|
SCRIPT_ASSERT("RC Launcher animations have failed to load.")
|
|
launcherAnims.eState = LAS_INACTIVE
|
|
ENDIF
|
|
ELSE
|
|
// This mission doesn't require any idle animations (in theory should never hit this part of the script)
|
|
launcherAnims.eState = LAS_INACTIVE
|
|
ENDIF
|
|
|
|
BREAK
|
|
|
|
CASE LAS_PLAYING_IDLE
|
|
|
|
IF NOT IS_LAUNCHER_BECKON_ANIM_SETUP(launcherAnims) // Fix for B*845846
|
|
OR NOT IS_ENTITY_PLAYING_ANIM(iPed, launcherAnims.sDictionary, launcherAnims.sBeckonAnim) // Let the beckon play out before attempting to turn the ped
|
|
IF DOES_PED_NEED_TO_FACE_PLAYER(eMissionID)
|
|
AND NOT IS_PED_FACING_PED(iPed, PLAYER_PED_ID(), 25)
|
|
TASK_TURN_PED_TO_FACE_ENTITY(iPed, PLAYER_PED_ID())
|
|
launcherAnims.eState = LAS_TURNING_TO_PLAYER
|
|
ELSE
|
|
IF IS_LAUNCHER_BECKON_ANIM_SETUP(launcherAnims)
|
|
AND launcherAnims.bBeckonPerformed = FALSE
|
|
AND GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), GET_ENTITY_COORDS(iPed)) < RC_BECKON_ANIM_DISTANCE // Player has walked near to the scene ped
|
|
launcherAnims.eState = LAS_WAITING_FOR_BECKON
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
BREAK
|
|
|
|
CASE LAS_WAITING_FOR_BECKON
|
|
|
|
SEQUENCE_INDEX seq
|
|
// Scene ped plays beckon animation and reverts back to looping idle animation
|
|
OPEN_SEQUENCE_TASK(seq)
|
|
IF ARE_VECTORS_EQUAL(launcherAnims.vAnimPos, <<0,0,0>>)
|
|
TASK_PLAY_ANIM(null, launcherAnims.sDictionary, launcherAnims.sBeckonAnim, SLOW_BLEND_IN, SLOW_BLEND_OUT, -1, AF_USE_KINEMATIC_PHYSICS) // See B*887597 - changed to slow blends
|
|
TASK_PLAY_ANIM(null, launcherAnims.sDictionary, launcherAnims.sIdleAnim, NORMAL_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_LOOPING|AF_USE_KINEMATIC_PHYSICS|AF_NOT_INTERRUPTABLE)
|
|
ELSE
|
|
TASK_PLAY_ANIM_ADVANCED(null, launcherAnims.sDictionary, launcherAnims.sBeckonAnim, launcherAnims.vAnimPos, launcherAnims.vAnimRot, SLOW_BLEND_IN, SLOW_BLEND_OUT, -1, AF_USE_KINEMATIC_PHYSICS|AF_NOT_INTERRUPTABLE)
|
|
TASK_PLAY_ANIM_ADVANCED(null, launcherAnims.sDictionary, launcherAnims.sIdleAnim, launcherAnims.vAnimPos, launcherAnims.vAnimRot, NORMAL_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_LOOPING|AF_USE_KINEMATIC_PHYSICS|AF_NOT_INTERRUPTABLE)
|
|
ENDIF
|
|
CLOSE_SEQUENCE_TASK(seq)
|
|
TASK_PERFORM_SEQUENCE(iPed, seq)
|
|
CLEAR_SEQUENCE_TASK(seq)
|
|
|
|
launcherAnims.bBeckonPerformed = TRUE
|
|
IF DOES_PED_NEED_TO_FACE_PLAYER(eMissionID)
|
|
launcherAnims.eState = LAS_PLAYING_IDLE
|
|
ELSE
|
|
launcherAnims.eState = LAS_INACTIVE
|
|
ENDIF
|
|
|
|
BREAK
|
|
|
|
CASE LAS_TURNING_TO_PLAYER
|
|
|
|
IF NOT DOES_PED_NEED_TO_FACE_PLAYER(eMissionID)
|
|
OR IS_PED_FACING_PED(iPed, PLAYER_PED_ID(), 10)
|
|
IF ARE_VECTORS_EQUAL(launcherAnims.vAnimPos, <<0,0,0>>)
|
|
TASK_PLAY_ANIM(iPed, launcherAnims.sDictionary, launcherAnims.sIdleAnim, NORMAL_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_LOOPING|AF_USE_KINEMATIC_PHYSICS|AF_NOT_INTERRUPTABLE)
|
|
ELSE
|
|
TASK_PLAY_ANIM_ADVANCED(iPed, launcherAnims.sDictionary, launcherAnims.sIdleAnim, launcherAnims.vAnimPos, launcherAnims.vAnimRot, NORMAL_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_LOOPING|AF_USE_KINEMATIC_PHYSICS|AF_NOT_INTERRUPTABLE)
|
|
ENDIF
|
|
launcherAnims.eState = LAS_PLAYING_IDLE
|
|
ENDIF
|
|
|
|
BREAK
|
|
|
|
ENDSWITCH
|
|
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
// ===========================================================================================================
|
|
// General
|
|
// ===========================================================================================================
|
|
|
|
|
|
/// PURPOSE:
|
|
/// Runs general script that must happen every time a new RC launcher script starts running.
|
|
PROC RC_LAUNCHER_START()
|
|
PRINT_LAUNCHER_DEBUG("Running start routines.")
|
|
g_iNoRCLeadinsActive++
|
|
ENDPROC
|
|
|
|
|
|
/// PURPOSE:
|
|
/// Runs general script that must happen every time an RC launcher script stops running.
|
|
PROC RC_LAUNCHER_END()
|
|
PRINT_LAUNCHER_DEBUG("Running end routines.")
|
|
g_iNoRCLeadinsActive--
|
|
ENDPROC
|
|
|
|
|
|
/// PURPOSE:
|
|
/// Checks if all models in array have loaded. (Used by RC initial scenes)
|
|
/// PARAMS:
|
|
/// mModel - array of model names
|
|
/// RETURNS:
|
|
/// TRUE if all have loaded, false otherwise
|
|
FUNC BOOL HAVE_ALL_MODELS_IN_ARRAY_LOADED(MODEL_NAMES &mModel[])
|
|
INT iModel
|
|
|
|
FOR iModel = 0 TO COUNT_OF(mModel) -1
|
|
IF NOT HAS_MODEL_LOADED(mModel[iModel])
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDFOR
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
|
|
|
|
/// PURPOSE:
|
|
/// Loads the script specified
|
|
/// PARAMS:
|
|
/// sRCCommonData - launcher data struct
|
|
/// RETURNS:
|
|
/// TRUE if the script is loaded. FALSE if the script name is invalid.
|
|
FUNC BOOL LOAD_REQUIRED_SCRIPT(STRING sScriptName)
|
|
IF NOT Is_String_Null_Or_Empty(sScriptName)
|
|
REQUEST_SCRIPT(sScriptName)
|
|
WHILE NOT HAS_SCRIPT_LOADED(sScriptName)
|
|
REQUEST_SCRIPT(sScriptName)
|
|
WAIT(0)
|
|
ENDWHILE
|
|
CPRINTLN(DEBUG_RANDOM_CHAR, "******** LAUNCH *******", sScriptName)
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
// Invalid script file so terminate script
|
|
PRINT_LAUNCHER_DEBUG("Attempting to launch invalid script file [TERMINATING]")
|
|
SCRIPT_ASSERT("RC Launcher attempting to launch invalid script file")
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Whether the player's helmet should be removed when activating this RCM
|
|
FUNC BOOL REMOVE_HELMET_FOR_RC_MISSION(g_eRC_MissionIDs eRCMission)
|
|
|
|
SWITCH eRCMission
|
|
CASE RC_BARRY_3A
|
|
CASE RC_BARRY_3C
|
|
CASE RC_NIGEL_1A
|
|
CASE RC_NIGEL_1B
|
|
CASE RC_NIGEL_1C
|
|
CASE RC_NIGEL_1D
|
|
CASE RC_PAPARAZZO_3A
|
|
CASE RC_PAPARAZZO_3B
|
|
CASE RC_TONYA_3
|
|
CASE RC_TONYA_4
|
|
RETURN FALSE
|
|
BREAK
|
|
ENDSWITCH
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Gets called when an RC mission is about to launch to handle common requirements
|
|
/// Currently used by rampages + Ambient Hunting too. Will split this up if required.
|
|
PROC RC_MISSION_STARTING(g_eRC_MissionIDs eMissionID)
|
|
#if USE_CLF_DLC
|
|
eMissionID = eMissionID
|
|
#endif
|
|
#if USE_NRM_DLC
|
|
eMissionID = eMissionID
|
|
#endif
|
|
#if not USE_CLF_DLC
|
|
#if not USE_NRM_DLC
|
|
// Ensure cellphone isn't in sleep mode when starting this RC mission
|
|
SET_CELLPHONE_PROFILE_TO_NORMAL()
|
|
|
|
//Stop player fly through windscreens.
|
|
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
|
|
SET_PED_CONFIG_FLAG(PLAYER_PED_ID(), PCF_WillFlyThroughWindscreen, FALSE)
|
|
SET_PED_CONFIG_FLAG(PLAYER_PED_ID(), PCF_WillTakeDamageWhenVehicleCrashes, FALSE)
|
|
ENDIF
|
|
|
|
// Make sure the player removes their helmet
|
|
IF REMOVE_HELMET_FOR_RC_MISSION(eMissionID)
|
|
REMOVE_PED_HELMET(PLAYER_PED_ID(), FALSE)
|
|
ENDIF
|
|
|
|
// Stop ambient peds attacking the player during mission
|
|
SET_ALL_RANDOM_PEDS_FLEE(PLAYER_ID(), TRUE)
|
|
|
|
// Ensure mission brief is cleared
|
|
CLEAR_ADDITIONAL_TEXT(MISSION_TEXT_SLOT, TRUE)
|
|
CLEAR_ADDITIONAL_TEXT(MINIGAME_TEXT_SLOT, TRUE) // Used on Tonya RCM
|
|
CLEAR_ADDITIONAL_TEXT(ODDJOB_TEXT_SLOT, TRUE)
|
|
|
|
// Sober the player up
|
|
IF g_isPlayerDrunk = TRUE
|
|
IF IS_PED_UNINJURED(PLAYER_PED_ID())
|
|
Make_Ped_Sober(PLAYER_PED_ID())
|
|
ENDIF
|
|
ENDIF
|
|
|
|
|
|
// mission title stuff- not needed on a replay
|
|
IF NOT IS_REPLAY_IN_PROGRESS()
|
|
|
|
// Reset mission title system ready to display title on mission
|
|
IF eMissionID < MAX_RC_MISSIONS
|
|
RANDOM_CHAR_DISPLAY_MISSION_TITLE(eMissionID)
|
|
|
|
//Pass code the name of the mission we're on.
|
|
TEXT_LABEL_7 tMissionName = GET_RC_MISSION_NAME_LABEL(INT_TO_ENUM(g_eRC_MissionIDs, eMissionID))
|
|
CPRINTLN(DEBUG_RANDOM_CHAR, "RC_MISSION_STARTING calling SET_MISSION_NAME, tMissionName= ", tMissionName)
|
|
SET_MISSION_NAME(TRUE, tMissionName)
|
|
ENDIF
|
|
ENDIF
|
|
#endif
|
|
#endif
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Whether the player's weapon should be holstered when activating this RCM
|
|
FUNC BOOL HOLSTER_WEAPON_FOR_RC_MISSION(g_eRC_MissionIDs eRCMission = NO_RC_MISSION)
|
|
|
|
SWITCH eRCMission
|
|
CASE RC_BARRY_3A
|
|
CASE RC_BARRY_3C
|
|
CASE RC_EPSILON_6
|
|
CASE RC_NIGEL_1A
|
|
CASE RC_NIGEL_1B
|
|
CASE RC_NIGEL_1C
|
|
CASE RC_NIGEL_1D
|
|
CASE RC_PAPARAZZO_3A
|
|
CASE RC_PAPARAZZO_3B
|
|
CASE RC_RAMPAGE_1
|
|
CASE RC_RAMPAGE_2
|
|
CASE RC_RAMPAGE_3
|
|
CASE RC_RAMPAGE_4
|
|
CASE RC_RAMPAGE_5
|
|
RETURN FALSE
|
|
BREAK
|
|
ENDSWITCH
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Should the RC mission stop the player's vehicle upon activation
|
|
FUNC BOOL RC_MISSION_SHOULD_HALT_VEHICLE(g_eRC_MissionIDs eMissionID)
|
|
|
|
SWITCH eMissionID
|
|
|
|
CASE RC_BARRY_3A
|
|
CASE RC_BARRY_3C
|
|
CASE RC_EPSILON_6
|
|
CASE RC_EPSILON_8
|
|
CASE RC_NIGEL_1A
|
|
CASE RC_NIGEL_1B
|
|
CASE RC_NIGEL_1C
|
|
CASE RC_NIGEL_1D
|
|
CASE RC_PAPARAZZO_3A
|
|
CASE RC_PAPARAZZO_3B
|
|
RETURN FALSE
|
|
BREAK
|
|
|
|
ENDSWITCH
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Loads the RC script, calls common startup function, launches script and passes cut-scene over to it.
|
|
/// PARAMS:
|
|
/// sRCLauncherData - launcher data struct
|
|
/// RETURNS:
|
|
/// TRUE if script is loaded and launched. FALSE if it fails to load.
|
|
FUNC BOOL REQUEST_AND_LAUNCH_RC(g_structRCScriptArgs &sRCLauncherData)
|
|
|
|
IF LOAD_REQUIRED_SCRIPT(sRCLauncherData.sScriptName)
|
|
|
|
// Ensure missions that start with a lead-in, cutscene or scripted sequence
|
|
// make the area safe and that all mission entities are invincible
|
|
IF NOT IS_STRING_NULL_OR_EMPTY(sRCLauncherData.sIntroCutscene)
|
|
|
|
// Clear area of projectiles - no longer disables player control
|
|
RC_PRE_REQUEST_CUTSCENE(TRUE)
|
|
|
|
// Make entities invincible as we go into the mission
|
|
RC_SET_ENTITY_PROOFS_FOR_CUTSCENE(sRCLauncherData, TRUE, HOLSTER_WEAPON_FOR_RC_MISSION(sRCLauncherData.eMissionID))
|
|
ENDIF
|
|
|
|
// Ensure player exits vehicle...
|
|
IF sRCLauncherData.bAllowVehicleActivation
|
|
IF RC_MISSION_SHOULD_HALT_VEHICLE(sRCLauncherData.eMissionID)
|
|
WHILE NOT IS_PED_ON_FOOT(PLAYER_PED_ID())
|
|
RC_PLAYER_TRIGGER_SCENE_LOCK_IN()
|
|
WAIT(0)
|
|
ENDWHILE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// Setup common requirements
|
|
RC_MISSION_STARTING(sRCLauncherData.eMissionID)
|
|
|
|
// Launch script
|
|
THREADID rcThread = START_NEW_SCRIPT_WITH_ARGS(sRCLauncherData.sScriptName, sRCLauncherData, SIZE_OF(g_structRCScriptArgs), MISSION_STACK_SIZE)
|
|
|
|
// Allow script to be released when no longer running
|
|
SET_SCRIPT_AS_NO_LONGER_NEEDED(sRCLauncherData.sScriptName)
|
|
|
|
// Allow script to trigger cutscene
|
|
IF HAS_CUTSCENE_LOADED()
|
|
PRINT_LAUNCHER_DEBUG("Initial cutscene loaded and passing to RC mission.")
|
|
SET_SCRIPT_CAN_START_CUTSCENE(rcThread)
|
|
ELSE
|
|
PRINT_LAUNCHER_DEBUG("Initial cutscene wasn't loaded in time to pass to RC mission.")
|
|
REMOVE_CUTSCENE()
|
|
ENDIF
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
//In debug build inform the autoplay system we are on a RC mission now.
|
|
g_txtFlowAutoplayRunningMission = sRCLauncherData.sScriptName
|
|
#ENDIF
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// checks that the mission is within tolerance range of the world point, it is active and not completed
|
|
/// PARAMS:
|
|
/// eRCMission - The RC mission we are checking
|
|
/// vInCoords - world point position
|
|
/// fTolerance - WORLD_POINT_COORD_TOLERANCE of this launcher
|
|
/// eRCInfo - struct of launcher data
|
|
/// RETURNS:
|
|
/// TRUE if it finds an RC mission within range that is active and not completed
|
|
FUNC BOOL IS_RC_IN_RANGE_AND_WAITING(g_eRC_MissionIDs eRCMission,VECTOR vInCoords, FLOAT fTolerance, g_structRCScriptArgs &eRCInfo)
|
|
|
|
BOOL bMissionIsReady = FALSE
|
|
|
|
g_structRCMissionsStatic sRCMissionDetails
|
|
Retrieve_Random_Character_Static_Mission_Details(eRCMission, sRCMissionDetails)
|
|
|
|
//CPRINTLN(DEBUG_RANDOM_CHAR, sRCMissionDetails.rcScriptName, " MissPos:", sRCMissionDetails.rcCoords, " TestPos:", vInCoords)
|
|
|
|
IF ARE_VECTORS_ALMOST_EQUAL(sRCMissionDetails.rcCoords, vInCoords, fTolerance)
|
|
IF IS_BIT_SET(g_savedGlobals.sRandomChars.savedRC[eRCMission].rcFlags, ENUM_TO_INT(RC_FLAG_ACTIVATED))
|
|
IF NOT IS_BIT_SET(g_savedGlobals.sRandomChars.savedRC[eRCMission].rcFlags, ENUM_TO_INT(RC_FLAG_COMPLETED))
|
|
// In range, active and not already completed.
|
|
bMissionIsReady = TRUE
|
|
ELSE
|
|
CPRINTLN(DEBUG_RANDOM_CHAR, sRCMissionDetails.rcScriptName, " [Already complete]")
|
|
ENDIF
|
|
ELSE
|
|
CPRINTLN(DEBUG_RANDOM_CHAR, sRCMissionDetails.rcScriptName, " [Not activated]")
|
|
ENDIF
|
|
|
|
// ok for mission to already be complete or not be activated if we are repeat playing it
|
|
IF IsThisRCBeingRepeatPlayed(ENUM_TO_INT(eRCMission))
|
|
CPRINTLN(DEBUG_RANDOM_CHAR, sRCMissionDetails.rcScriptName, " is being repeat played")
|
|
bMissionIsReady = TRUE
|
|
ENDIF
|
|
ELSE
|
|
CPRINTLN(DEBUG_RANDOM_CHAR, sRCMissionDetails.rcScriptName, " [Position mismatch]")
|
|
ENDIF
|
|
|
|
IF bMissionIsReady = TRUE
|
|
eRCInfo.eMissionID = eRCMission
|
|
eRCInfo.sScriptName = sRCMissionDetails.rcScriptName
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
// Mission failed to meet requirements
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Determines which RC we are trying to launch. Also wiats for gameflow to finish configuring.
|
|
/// PARAMS:
|
|
/// eRCMissions - array of RC missions in this strand
|
|
/// eRCInfo - struct of launcher data
|
|
/// vInCoords - world point position
|
|
/// fTolerance - WORLD_POINT_COORD_TOLERANCE of this launcher
|
|
/// RETURNS:
|
|
/// TRUE if it has found an RC that can launch. FALSE otherwise
|
|
FUNC BOOL DETERMINE_RC_TO_LAUNCH(g_eRC_MissionIDs &eRCMissions[], g_structRCScriptArgs &eRCInfo, VECTOR vInCoords, FLOAT fTolerance)
|
|
|
|
// If the flow is in the process of being configured, we wait for it to finish
|
|
#IF IS_DEBUG_BUILD
|
|
WHILE g_flowUnsaved.bUpdatingGameflow
|
|
WAIT(0)
|
|
ENDWHILE
|
|
#ENDIF
|
|
|
|
IF COUNT_OF(eRCMissions) = 1
|
|
// This strand only has 1 RC mission, so just check that
|
|
IF IS_RC_IN_RANGE_AND_WAITING(eRCMissions[0], vInCoords, fTolerance, eRCInfo)
|
|
// Valid mission found + set to launch. Return
|
|
CPRINTLN(DEBUG_RANDOM_CHAR, "DetermineRCToLaunch: Found mission ", eRCInfo.sScriptName)
|
|
RETURN TRUE
|
|
ENDIF
|
|
ELSE
|
|
// Check if there is an RC mission in this strand that can be launched
|
|
INT iMission = 0
|
|
WHILE iMission < COUNT_OF(eRCMissions)
|
|
IF IS_RC_IN_RANGE_AND_WAITING(eRCMissions[iMission], vInCoords, fTolerance, eRCInfo)
|
|
// Valid mission found + set to launch. Return
|
|
CPRINTLN(DEBUG_RANDOM_CHAR, "DetermineRCToLaunch: Found mission ", eRCInfo.sScriptName)
|
|
iMission = COUNT_OF(eRCMissions)
|
|
RETURN TRUE
|
|
ENDIF
|
|
iMission++
|
|
ENDWHILE
|
|
ENDIF
|
|
|
|
// Failed to find an RC to launch
|
|
PRINT_LAUNCHER_DEBUG("DETERMINE_RC_TO_LAUNCH - Unable to find mission to launch [TERMINATING]")
|
|
CPRINTLN(DEBUG_RANDOM_CHAR, "Original Position ", vInCoords)
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Check with the Random Character Controller to see if this script is allowed to launch
|
|
/// PARAMS:
|
|
/// eRCMission - the RC mission we are checking
|
|
/// RETURNS:
|
|
/// TRUE if allowed, FALSE when denied.
|
|
FUNC BOOL CAN_RC_LAUNCH(g_eRC_MissionIDs eRCMission = NO_RC_MISSION)
|
|
|
|
// Safeguard against RC launchers ever running in MP.
|
|
IF g_bInMultiplayer
|
|
PRINT_LAUNCHER_DEBUG("STEP_3_COMMON_CanRCLaunch - Script denied. Multiplayer is running [TERMINATING]")
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
// Safeguard against RCs launching outside of flow
|
|
IF NOT g_savedGlobals.sFlow.isGameflowActive
|
|
AND NOT IS_REPEAT_PLAY_ACTIVE(TRUE)
|
|
PRINT_LAUNCHER_DEBUG("STEP_3_COMMON_CanRCLaunch - Script denied, game flow is not active")
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
IF NOT (Random_Character_Is_Allowed_To_Launch(eRCMission))
|
|
// Force update in the blip controller to remove ? blip
|
|
g_RandomChars[eRCMission].rcIsAwaitingTrigger = TRUE
|
|
PRINT_LAUNCHER_DEBUG("STEP_3_COMMON_CanRCLaunch - Script denied by RC Controller [TERMINATING]")
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
//Is a RC replay for this mission in the process of being configured? If so delay launching.
|
|
IF g_replay.replayType = REPLAY_TYPE_RANDOM_CHARACTER
|
|
IF ENUM_TO_INT(g_replay.replayStageID) < ENUM_TO_INT(RS_ACTIVATE)
|
|
g_structRCMissionsStatic sRCMissionDetails
|
|
Retrieve_Random_Character_Static_Mission_Details(eRCMission, sRCMissionDetails)
|
|
IF ARE_STRINGS_EQUAL(g_replay.replayScriptName, sRCMissionDetails.rcScriptName)
|
|
PRINT_LAUNCHER_DEBUG("STEP_3_COMMON_CanRCLaunch - Script denied as a replay for this RC is being configured. [TERMINATING]")
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// B*1594664 - Prevent mission requesting launch before candidate controller has started up
|
|
IF GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(HASH("candidate_controller")) = 0
|
|
g_RandomChars[eRCMission].rcIsAwaitingTrigger = TRUE
|
|
PRINT_LAUNCHER_DEBUG("STEP_3_COMMON_CanRCLaunch - Script denied as candidate_controller is not running. [TERMINATING]")
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Handles Dom jumping off the Maze Tower
|
|
PROC MAKE_DOM_JUMP(PED_INDEX pedID)
|
|
|
|
IF IS_ENTITY_ALIVE(PLAYER_PED_ID()) AND IS_ENTITY_ALIVE(pedID)
|
|
|
|
SEQUENCE_INDEX iSeq
|
|
|
|
// Already requested by initial_scene_extreme.sch but request it just in case...
|
|
REQUEST_ANIM_DICT("rcmextreme3")
|
|
WHILE NOT HAS_ANIM_DICT_LOADED("rcmextreme3")
|
|
WAIT(0)
|
|
ENDWHILE
|
|
|
|
// Task Dom to jump off the tower
|
|
OPEN_SEQUENCE_TASK(iSeq)
|
|
TASK_PLAY_ANIM(NULL, "rcmextreme3", "jump_fall", INSTANT_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_NOT_INTERRUPTABLE)
|
|
TASK_SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(NULL, TRUE) // B*1958266 Prevent Dom reacting and trying to flee on foot if the player shoots at him while parachuting away
|
|
TASK_PARACHUTE_TO_TARGET(NULL, <<64.6,-737.8,44.2>>)
|
|
TASK_SMART_FLEE_PED(NULL, PLAYER_PED_ID(), 10000, -1)
|
|
CLOSE_SEQUENCE_TASK(iSeq)
|
|
TASK_PERFORM_SEQUENCE(pedID, iSeq)
|
|
CLEAR_SEQUENCE_TASK(iSeq)
|
|
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Makes all of the peds in the initial scene for this RC mission flee the player
|
|
PROC MAKE_ALL_INITIAL_SCENE_PEDS_FLEE(g_structRCScriptArgs& sData)
|
|
|
|
INT i
|
|
SEQUENCE_INDEX seqCustomPedFlee
|
|
|
|
// special case for rampage 1
|
|
IF (sData.eMissionID = RC_RAMPAGE_1)
|
|
CPRINTLN(DEBUG_RAMPAGE, "SPECIAL CASE - MAKE_ALL_INITIAL_SCENE_PEDS_FLEE - RAMPAGE 1")
|
|
SAFE_DELETE_OBJECT(sData.objID[1])
|
|
SAFE_DELETE_OBJECT(sData.objID[2])
|
|
ENDIF
|
|
|
|
|
|
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
|
|
FOR i = 0 to COUNT_OF(sData.pedID) - 1
|
|
IF IS_PED_UNINJURED(sData.pedID[i])
|
|
|
|
IF NOT IS_PED_IN_ANY_VEHICLE(sData.pedID[i]) // Added to fix assert (can't turn on peds collision if they are in a vehicle)
|
|
SET_ENTITY_COLLISION(sData.pedID[i], TRUE) // Turn ped's collision on (some launcher peds have collision turned off for playing anims)
|
|
FREEZE_ENTITY_POSITION(sData.pedID[0], FALSE)
|
|
ENDIF
|
|
|
|
// Remove attached entities
|
|
/*
|
|
IF DOES_ENTITY_EXIST(sData.objID[i])
|
|
IF IS_ENTITY_ATTACHED_TO_ENTITY(sData.objID[i], sData.pedID[i])
|
|
DETACH_ENTITY(sData.objID[i])
|
|
ENDIF
|
|
ENDIF
|
|
*/
|
|
|
|
// Keep scripted task
|
|
SET_PED_KEEP_TASK(sData.pedID[i], TRUE)
|
|
|
|
// Need to put collision back on for Manuel's chair
|
|
IF sData.eMissionID = RC_MINUTE_3
|
|
IF IS_ENTITY_ALIVE(sData.objID[0])
|
|
SET_ENTITY_COLLISION(sData.objID[0], TRUE)
|
|
FREEZE_ENTITY_POSITION(sData.objID[0], FALSE)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
SWITCH sData.eMissionID
|
|
|
|
// To fix B*735172 - Dom has nowhere to flee to if player interferes with scene
|
|
CASE RC_EXTREME_3
|
|
MAKE_DOM_JUMP(sData.pedID[i])
|
|
BREAK
|
|
|
|
CASE RC_DREYFUSS_1 // To fix B*1176001 - Dreyfuss has to stand up from the lotus position
|
|
REQUEST_ANIM_DICT("rcmcollect_paperleadinout@") // Already requested by initial_scene_dreyfuss.sch but request it just in case
|
|
WHILE NOT HAS_ANIM_DICT_LOADED("rcmcollect_paperleadinout@")
|
|
WAIT(0)
|
|
ENDWHILE
|
|
OPEN_SEQUENCE_TASK(seqCustomPedFlee)
|
|
TASK_PLAY_ANIM(NULL, "rcmcollect_paperleadinout@", "meditate_getup", NORMAL_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_NOT_INTERRUPTABLE)
|
|
TASK_SMART_FLEE_PED(NULL, PLAYER_PED_ID(), 10000, -1)
|
|
CLOSE_SEQUENCE_TASK(seqCustomPedFlee)
|
|
TASK_PERFORM_SEQUENCE(sData.pedID[i], seqCustomPedFlee)
|
|
CLEAR_SEQUENCE_TASK(seqCustomPedFlee)
|
|
BREAK
|
|
|
|
CASE RC_ABIGAIL_1
|
|
CASE RC_ABIGAIL_2
|
|
REQUEST_ANIM_DICT("rcmabigail") // Already requested by initial_scene_abigail.sch but request it just in case
|
|
WHILE NOT HAS_ANIM_DICT_LOADED("rcmabigail")
|
|
WAIT(0)
|
|
ENDWHILE
|
|
OPEN_SEQUENCE_TASK(seqCustomPedFlee)
|
|
TASK_PLAY_ANIM(NULL, "rcmabigail", "breakout_base", NORMAL_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_NOT_INTERRUPTABLE)
|
|
TASK_SMART_FLEE_PED(NULL, PLAYER_PED_ID(), 10000, -1)
|
|
CLOSE_SEQUENCE_TASK(seqCustomPedFlee)
|
|
TASK_PERFORM_SEQUENCE(sData.pedID[i], seqCustomPedFlee)
|
|
CLEAR_SEQUENCE_TASK(seqCustomPedFlee)
|
|
BREAK
|
|
|
|
CASE RC_MINUTE_1
|
|
REQUEST_ANIM_DICT("rcmminute1") // Already requested by initial_scene_minute.sch but request it just in case
|
|
WHILE NOT HAS_ANIM_DICT_LOADED("rcmminute1")
|
|
WAIT(0)
|
|
ENDWHILE
|
|
OPEN_SEQUENCE_TASK(seqCustomPedFlee)
|
|
IF i = 0
|
|
TASK_PLAY_ANIM(NULL, "rcmminute1", "base_to_idle_joe", NORMAL_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_NOT_INTERRUPTABLE|AF_TAG_SYNC_OUT)
|
|
ELSE
|
|
TASK_PLAY_ANIM(NULL, "rcmminute1", "base_to_idle_josef", NORMAL_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_NOT_INTERRUPTABLE|AF_TAG_SYNC_OUT)
|
|
ENDIF
|
|
TASK_SMART_FLEE_PED(NULL, PLAYER_PED_ID(), 10000, -1)
|
|
CLOSE_SEQUENCE_TASK(seqCustomPedFlee)
|
|
TASK_PERFORM_SEQUENCE(sData.pedID[i], seqCustomPedFlee)
|
|
CLEAR_SEQUENCE_TASK(seqCustomPedFlee)
|
|
BREAK
|
|
|
|
CASE RC_HAO_1
|
|
REQUEST_ANIM_DICT("special_ped@hao@base") // Already requested by initial_scene_abigail.sch but request it just in case
|
|
WHILE NOT HAS_ANIM_DICT_LOADED("special_ped@hao@base")
|
|
WAIT(0)
|
|
ENDWHILE
|
|
OPEN_SEQUENCE_TASK(seqCustomPedFlee)
|
|
TASK_PLAY_ANIM(NULL, "special_ped@hao@base", "hao_exit", NORMAL_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_NOT_INTERRUPTABLE | AF_TURN_OFF_COLLISION)
|
|
TASK_SMART_FLEE_PED(NULL, PLAYER_PED_ID(), 10000, -1)
|
|
CLOSE_SEQUENCE_TASK(seqCustomPedFlee)
|
|
TASK_PERFORM_SEQUENCE(sData.pedID[i], seqCustomPedFlee)
|
|
CLEAR_SEQUENCE_TASK(seqCustomPedFlee)
|
|
BREAK
|
|
|
|
DEFAULT
|
|
CLEAR_PED_SECONDARY_TASK(sData.pedID[i]) // fix for B*951280
|
|
TASK_SMART_FLEE_PED(sData.pedID[i], PLAYER_PED_ID(), 10000, -1)
|
|
BREAK
|
|
|
|
ENDSWITCH
|
|
ENDIF
|
|
ENDFOR
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Makes all of the peds in the initial scene for this RC mission attack the player
|
|
PROC MAKE_ALL_INITIAL_SCENE_PEDS_ATTACK_PLAYER(g_structRCScriptArgs& sData)
|
|
INT i
|
|
|
|
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
|
|
FOR i = 0 to COUNT_OF(sData.pedID) - 1
|
|
IF IS_PED_UNINJURED(sData.pedID[i])
|
|
SET_PED_COMBAT_ATTRIBUTES(sData.pedID[i],CA_USE_VEHICLE,FALSE) //Don't want them chasing you in a vehicle
|
|
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(sData.pedID[i],FALSE)
|
|
SET_PED_KEEP_TASK(sData.pedID[i], TRUE)
|
|
TASK_COMBAT_PED(sData.pedID[i], PLAYER_PED_ID())
|
|
SET_PED_AS_NO_LONGER_NEEDED(sData.pedID[i])
|
|
ENDIF
|
|
ENDFOR
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Checks to see whether the vehicles in the initial scene have been destroyed, damaged or if the player is interfering with the vehicles
|
|
FUNC BOOL CHECK_VEHICLES_OK(g_structRCScriptArgs& sData, BOOL bCheckAllCars, BOOL bCheckInterference=FALSE)
|
|
|
|
INT i
|
|
INT iLimit
|
|
|
|
IF bCheckAllCars
|
|
iLimit = COUNT_OF(sData.vehID) - 1
|
|
ELSE
|
|
iLimit = 0
|
|
ENDIF
|
|
|
|
IF IS_PED_UNINJURED(PLAYER_PED_ID())
|
|
FOR i = 0 to iLimit
|
|
IF DOES_ENTITY_EXIST(sData.vehID[i])
|
|
|
|
// Check if the vehicle has been destroyed
|
|
IF IS_ENTITY_DEAD(sData.vehID[i])
|
|
PRINT_LAUNCHER_DEBUG("STEP_5_COMMON_RCfineAndInRange - CHECK_VEHICLES_OK() - Random character vehicle is dead [TERMINATING]")
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
// Check if the vehicle is driveable
|
|
IF NOT IS_VEHICLE_DRIVEABLE(sData.vehID[i])
|
|
PRINT_LAUNCHER_DEBUG("STEP_5_COMMON_RCfineAndInRange - CHECK_VEHICLES_OK() - Random character vehicle is not driveable [TERMINATING]")
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
// Check if the vehicle has been damaged
|
|
// Don't check for the player's vehicle damaging the scene vehicle as this is done in the bCheckInterference checks
|
|
IF HAS_ENTITY_BEEN_DAMAGED_BY_ENTITY(sData.vehID[i], PLAYER_PED_ID(), FALSE)
|
|
PRINT_LAUNCHER_DEBUG("STEP_5_COMMON_RCfineAndInRange - CHECK_VEHICLES_OK() - Random character vehicle has been damaged by player [TERMINATING]")
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
// Check if the vehicle health has been reduced more than 150HP - the player is allowed some leniency (see B*910454)
|
|
IF GET_ENTITY_HEALTH(sData.vehID[i]) < 850
|
|
PRINT_LAUNCHER_DEBUG("STEP_5_COMMON_RCfineAndInRange - CHECK_VEHICLES_OK() - Random character vehicle health is less than 850 [TERMINATING]")
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
// (Optional) Check for player interfering with scene vehicles
|
|
IF bCheckInterference
|
|
|
|
IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
|
|
|
|
// Player has collided with scene vehicle at speed, the player is allowed some leniency (see B*910454)
|
|
IF IS_ENTITY_TOUCHING_ENTITY(sData.vehID[i], PLAYER_PED_ID())
|
|
AND GET_ENTITY_SPEED(PLAYER_PED_ID()) > 5
|
|
PRINT_LAUNCHER_DEBUG("STEP_5_COMMON_RCfineAndInRange - CHECK_VEHICLES_OK() - Random character vehicle has collided with the player vehicle at speed [TERMINATING]")
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
// Player is towing scene vehicle
|
|
VEHICLE_INDEX viPlayer = GET_PLAYERS_LAST_VEHICLE()
|
|
|
|
IF IS_VEHICLE_OK(viPlayer)
|
|
IF GET_ENTITY_MODEL(viPlayer) = TOWTRUCK
|
|
OR GET_ENTITY_MODEL(viPlayer) = TOWTRUCK2
|
|
IF IS_VEHICLE_OK(sData.vehID[i])
|
|
IF IS_VEHICLE_ATTACHED_TO_TOW_TRUCK(viPlayer, sData.vehID[i])
|
|
PRINT_LAUNCHER_DEBUG("STEP_5_COMMON_RCfineAndInRange - CHECK_VEHICLES_OK() - Random character vehicle is being towed by player [TERMINATING]")
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ELSE
|
|
// Fix for B*1273632 - in case the player has bailed out of their vehicle at speed and it collides with a scene vehicle
|
|
VEHICLE_INDEX veh = GET_PLAYERS_LAST_VEHICLE()
|
|
|
|
IF IS_VEHICLE_OK(veh)
|
|
IF IS_ENTITY_TOUCHING_ENTITY(sData.vehID[i], veh)
|
|
AND GET_ENTITY_SPEED(veh) > 6
|
|
PRINT_LAUNCHER_DEBUG("STEP_5_COMMON_RCfineAndInRange - CHECK_VEHICLES_OK() - Random character vehicle has collided with the player's last known vehicle at speed (player bailed out?) [TERMINATING]")
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF sData.eMissionID = RC_EPSILON_8
|
|
IF IS_CHAR_USING_VEHICLE(PLAYER_PED_ID(),sData.vehID[i])
|
|
PRINT_LAUNCHER_DEBUG("STEP_5_COMMON_RCfineAndInRange - CHECK_VEHICLES_OK() - Player attempting to jack Epsilon vehicle [TERMINATING]")
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDFOR
|
|
ENDIF
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// For some missions the initial scene characters are seated, they can't flee properly from their seated anims
|
|
/// Call this to check if the mission uses a seated ped
|
|
/// RETURNS:
|
|
/// TRUE if the mission ped is standing, FALSE if they're seated
|
|
FUNC BOOL IS_PED_STANDING(g_eRC_MissionIDs missionID)
|
|
IF missionID = RC_BARRY_1
|
|
OR missionID = RC_BARRY_2
|
|
OR missionID = RC_MINUTE_3
|
|
OR missionID = RC_EPSILON_3
|
|
OR missionID = RC_RAMPAGE_1
|
|
OR missionID = RC_RAMPAGE_2
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Checks if the RC mission is a rampage
|
|
/// RETURNS:
|
|
/// TRUE if the mission is a rampage, false if its any other RC mission
|
|
FUNC BOOL IS_MISSION_A_RAMPAGE(g_eRC_MissionIDs missionID)
|
|
IF missionID = RC_RAMPAGE_1
|
|
OR missionID = RC_RAMPAGE_2
|
|
OR missionID = RC_RAMPAGE_3
|
|
OR missionID = RC_RAMPAGE_4
|
|
OR missionID = RC_RAMPAGE_5
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Should the RC ped ignore nearby explosions? (typically used for seated peds)
|
|
FUNC BOOL SHOULD_RC_MISSION_IGNORE_EXPLOSIONS(g_eRC_MissionIDs missionID)
|
|
|
|
IF missionID = RC_BARRY_1
|
|
OR MissionID = RC_BARRY_2
|
|
OR missionID = RC_RAMPAGE_1
|
|
OR missionID = RC_RAMPAGE_2
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Checks to see whether the peds in the initial scene have been killed, damaged or pushed around
|
|
/// PARAMS:
|
|
/// bPedsAttack - If true peds will attack player, otherwise flee from player
|
|
FUNC BOOL CHECK_PEDS_OK(g_structRCScriptArgs& sData, BOOL bCheckAllPeds, BOOL bPedsAttack = FALSE)
|
|
|
|
INT i
|
|
INT iLimit
|
|
|
|
IF bCheckAllPeds
|
|
iLimit = COUNT_OF(sData.pedID) - 1
|
|
ELSE
|
|
iLimit = 0
|
|
ENDIF
|
|
|
|
// For B*900468 - Security attack the player if he interferes with Epsilon 8 initial scene
|
|
IF sData.eMissionID = RC_EPSILON_8
|
|
bPedsAttack = TRUE
|
|
ENDIF
|
|
|
|
// For B*968838 - Cops attack player and Josh runs off
|
|
IF sData.eMissionID = RC_JOSH_4
|
|
bPedsAttack = TRUE
|
|
ENDIF
|
|
|
|
IF IS_PED_UNINJURED(PLAYER_PED_ID())
|
|
FOR i = 0 to iLimit
|
|
IF DOES_ENTITY_EXIST(sData.pedID[i]) // Don't use is entity alive for this as it takes a while for ped to get created.
|
|
IF NOT IS_PED_INJURED(sData.pedID[i])
|
|
|
|
// 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(), sData.pedID[i])
|
|
IF bPedsAttack = FALSE
|
|
MAKE_ALL_INITIAL_SCENE_PEDS_FLEE(sData)
|
|
ELSE
|
|
MAKE_ALL_INITIAL_SCENE_PEDS_ATTACK_PLAYER(sData)
|
|
ENDIF
|
|
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
|
|
KILL_ANY_CONVERSATION()
|
|
ENDIF
|
|
PRINT_LAUNCHER_DEBUG("STEP_5_COMMON_RCfineAndInRange - Random character is being pushed by car [TERMINATING]")
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// Check for RC ped taking damage
|
|
IF HAS_ENTITY_BEEN_DAMAGED_BY_ANY_PED(sData.pedID[i])
|
|
OR HAS_ENTITY_BEEN_DAMAGED_BY_ANY_VEHICLE(sData.pedID[i])
|
|
OR HAS_ENTITY_BEEN_DAMAGED_BY_ANY_OBJECT(sData.pedID[i])
|
|
IF bPedsAttack = FALSE
|
|
MAKE_ALL_INITIAL_SCENE_PEDS_FLEE(sData)
|
|
ELSE
|
|
MAKE_ALL_INITIAL_SCENE_PEDS_ATTACK_PLAYER(sData)
|
|
ENDIF
|
|
PRINT_LAUNCHER_DEBUG("STEP_5_COMMON_RCfineAndInRange - Random character has been damaged by something [TERMINATING]")
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
// check for RC ped being psuehd over by the player
|
|
IF IS_PED_RAGDOLL(sData.pedID[i])
|
|
IF IS_ENTITY_AT_ENTITY(sData.pedID[i], PLAYER_PED_ID(), <<3.0, 3.0, 3.0>>) // Player close (so they bumped into them)
|
|
IF bPedsAttack = FALSE
|
|
MAKE_ALL_INITIAL_SCENE_PEDS_FLEE(sData)
|
|
ELSE
|
|
MAKE_ALL_INITIAL_SCENE_PEDS_ATTACK_PLAYER(sData)
|
|
ENDIF
|
|
PRINT_LAUNCHER_DEBUG("STEP_5_COMMON_RCfineAndInRange - Random character is in ragdoll [TERMINATING]")
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// Only perform these checks if the ped is standing
|
|
IF IS_PED_STANDING(sData.eMissionID)
|
|
IF NOT IS_MISSION_A_RAMPAGE(sData.eMissionID)
|
|
// Check for player shooting nearby
|
|
IF IS_PLAYER_SHOOTING_NEAR_PED(sData.pedID[i])
|
|
IF bPedsAttack = FALSE
|
|
MAKE_ALL_INITIAL_SCENE_PEDS_FLEE(sData)
|
|
ELSE
|
|
MAKE_ALL_INITIAL_SCENE_PEDS_ATTACK_PLAYER(sData)
|
|
ENDIF
|
|
PRINT_LAUNCHER_DEBUG("STEP_5_COMMON_RCfineAndInRange - Player is shooting near the Random Character [TERMINATING]")
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// Check for explosions nearby
|
|
IF IS_EXPLOSION_IN_SPHERE(EXP_TAG_DONTCARE, GET_ENTITY_COORDS(sData.pedID[i]), 15)
|
|
IF bPedsAttack = FALSE
|
|
MAKE_ALL_INITIAL_SCENE_PEDS_FLEE(sData)
|
|
ELSE
|
|
MAKE_ALL_INITIAL_SCENE_PEDS_ATTACK_PLAYER(sData)
|
|
ENDIF
|
|
PRINT_LAUNCHER_DEBUG("STEP_5_COMMON_RCfineAndInRange - There was an explosion near the Random Character [TERMINATING]")
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
// check for player aiming at RC character
|
|
IF IS_PLAYER_VISIBLY_TARGETTING_PED(sData.pedID[i])
|
|
IF bPedsAttack = FALSE
|
|
MAKE_ALL_INITIAL_SCENE_PEDS_FLEE(sData)
|
|
ELSE
|
|
MAKE_ALL_INITIAL_SCENE_PEDS_ATTACK_PLAYER(sData)
|
|
ENDIF
|
|
PRINT_LAUNCHER_DEBUG("STEP_5_COMMON_RCfineAndInRange - Random character is in combat [TERMINATING]")
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF NOT SHOULD_RC_MISSION_IGNORE_EXPLOSIONS(sData.eMissionID)
|
|
|
|
// Check for explosions nearby
|
|
IF IS_EXPLOSION_IN_SPHERE(EXP_TAG_DONTCARE, GET_ENTITY_COORDS(sData.pedID[i]), 5)
|
|
IF bPedsAttack = FALSE
|
|
MAKE_ALL_INITIAL_SCENE_PEDS_FLEE(sData)
|
|
ELSE
|
|
MAKE_ALL_INITIAL_SCENE_PEDS_ATTACK_PLAYER(sData)
|
|
ENDIF
|
|
PRINT_LAUNCHER_DEBUG("STEP_5_COMMON_RCfineAndInRange - There was an explosion near the Random Character [TERMINATING]")
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
// Check for player having wanted level
|
|
IF GET_PLAYER_WANTED_LEVEL(PLAYER_ID()) > 0
|
|
IF bPedsAttack = FALSE
|
|
MAKE_ALL_INITIAL_SCENE_PEDS_FLEE(sData)
|
|
ELSE
|
|
MAKE_ALL_INITIAL_SCENE_PEDS_ATTACK_PLAYER(sData)
|
|
ENDIF
|
|
PRINT_LAUNCHER_DEBUG("STEP_5_COMMON_RCfineAndInRange - Player has a wanted level [TERMINATING]")
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDIF
|
|
ELSE
|
|
PRINT_LAUNCHER_DEBUG("STEP_5_COMMON_RCfineAndInRange - Random character injured / dead [TERMINATING]")
|
|
// Need to put collision back on for Manuel's chair
|
|
IF sData.eMissionID = RC_MINUTE_3
|
|
IF IS_ENTITY_ALIVE(sData.objID[0])
|
|
SET_ENTITY_COLLISION(sData.objID[0], TRUE)
|
|
FREEZE_ENTITY_POSITION(sData.objID[0], FALSE)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDIF
|
|
ENDFOR
|
|
ENDIF
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Checks if there are any reasons for the script to terminate.
|
|
/// Such as the initial scene peds being threatened/ damaged etc.
|
|
/// PARAMS:
|
|
/// sData - struct of launcher data
|
|
/// bAutoUpdateLaunchAnims - set this to auto update launch anims
|
|
/// RETURNS:
|
|
/// FALSE if the launcher should now terminate, TRUE otherswise
|
|
FUNC BOOL IS_RC_FINE_AND_IN_RANGE(g_structRCScriptArgs& sData, BOOL bAutoUpdateLaunchAnims = TRUE)
|
|
|
|
// Safeguard against RC launchers ever running in MP.
|
|
IF g_bInMultiplayer
|
|
PRINT_LAUNCHER_DEBUG("IS_RC_FINE_AND_IN_RANGE(): The game is running Multiplayer [TERMINATING]")
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
g_structRCMissionsStatic sRCMissionDetails
|
|
Retrieve_Random_Character_Static_Mission_Details(sData.eMissionID, sRCMissionDetails)
|
|
|
|
// Skip these checks on replays or repeat play
|
|
IF IsThisRCBeingRepeatPlayed(ENUM_TO_INT(sData.eMissionID))
|
|
OR IS_THIS_RC_MISSION_BEING_PROCESSED_FOR_REPLAY(sData.eMissionID)
|
|
OR g_bSceneAutoTrigger = TRUE
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
// Check if the player is still in range of the random character
|
|
IF NOT IS_WORLD_POINT_WITHIN_BRAIN_ACTIVATION_RANGE()
|
|
PRINT_LAUNCHER_DEBUG("IS_RC_FINE_AND_IN_RANGE(): Player out of range [TERMINATING]")
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
// Does Controller still allow this Random Character to check for the mission being triggered?
|
|
IF SHOULD_RC_TERMINATE(sData.eMissionID)
|
|
|
|
// Ensure Dom jumps!
|
|
IF (sData.eMissionID = RC_EXTREME_3)
|
|
MAKE_DOM_JUMP(sData.pedID[0])
|
|
ENDIF
|
|
|
|
PRINT_LAUNCHER_DEBUG("IS_RC_FINE_AND_IN_RANGE(): Script denied by RC Controller [TERMINATING]")
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
// We need to check all peds in this scene...
|
|
IF sData.bPedsCritical = TRUE
|
|
IF NOT CHECK_PEDS_OK(sData, TRUE)
|
|
RETURN FALSE
|
|
ENDIF
|
|
ELSE
|
|
// Just need to check main RC character
|
|
IF sData.triggerType = RC_TRIG_CHAR
|
|
IF NOT CHECK_PEDS_OK(sData, FALSE)
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// Check interference with scene vehicles (e.g. colliding/towing) for certain RCM's
|
|
IF sData.eMissionID = RC_EPSILON_8
|
|
OR sData.eMissionID = RC_EPSILON_1
|
|
OR sData.eMissionID = RC_EXTREME_2
|
|
OR sData.eMissionID = RC_FANATIC_2
|
|
OR sData.eMissionID = RC_MINUTE_1
|
|
OR sData.eMissionID = RC_PAPARAZZO_4
|
|
|
|
IF NOT CHECK_VEHICLES_OK(sData, TRUE, TRUE)
|
|
IF sData.eMissionID = RC_EPSILON_8
|
|
MAKE_ALL_INITIAL_SCENE_PEDS_ATTACK_PLAYER(sData)
|
|
ELSE
|
|
MAKE_ALL_INITIAL_SCENE_PEDS_FLEE(sData)
|
|
ENDIF
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
ELIF sData.eMissionID = RC_HAO_1
|
|
|
|
IF NOT CHECK_VEHICLES_OK(sData, FALSE, TRUE)
|
|
MAKE_ALL_INITIAL_SCENE_PEDS_FLEE(sData)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
ELIF sData.eMissionID = RC_BARRY_3C
|
|
// B*2034445 - don't fail for damaging tow truck, only the stash car
|
|
IF NOT CHECK_VEHICLES_OK(sData, FALSE, TRUE)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
// We need to check all scene vehicles ..
|
|
ELIF sData.bVehsCritical = TRUE
|
|
IF NOT CHECK_VEHICLES_OK(sData, TRUE)
|
|
MAKE_ALL_INITIAL_SCENE_PEDS_FLEE(sData)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
// Just need to check main RC vehicle
|
|
ELSE
|
|
IF sData.triggerType = RC_TRIG_ENTER_VEHICLE
|
|
OR sData.triggerType = RC_TRIG_NEAR_VEHICLE
|
|
IF NOT CHECK_VEHICLES_OK(sData, FALSE)
|
|
MAKE_ALL_INITIAL_SCENE_PEDS_FLEE(sData)
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// Check for Trigger vehicles being moved away from their initial position
|
|
IF sData.triggerType = RC_TRIG_ENTER_VEHICLE
|
|
OR sData.triggerType = RC_TRIG_NEAR_VEHICLE
|
|
|
|
IF IS_ENTITY_ALIVE(sData.vehID[0])
|
|
IF NOT IS_ENTITY_AT_COORD(sData.vehID[0], sRCMissionDetails.rcCoords, <<8.0, 8.0, 8.0>> )
|
|
CPRINTLN(DEBUG_RANDOM_CHAR, "RC Trigger vehicle moved too far from initial position. [TERMINATING]")
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// Special case detection of fire in mission trigger area
|
|
IF sData.eMissionID = RC_EPSILON_2
|
|
IF IS_EXPLOSION_IN_SPHERE(EXP_TAG_DONTCARE, sData.triggerLocate[0], 8.0)
|
|
PRINT_LAUNCHER_DEBUG("IS_RC_FINE_AND_IN_RANGE(): Explosion near mission trigger [TERMINATING]")
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// Check for the player character switching to an invalid character whilst launcher is active
|
|
// Tonya is exception - to be removed when Michael/Trevor interaction is special ped script
|
|
IF sRCMissionDetails.rcStrandID <> RCS_TONYA
|
|
IF NOT IS_BIT_SET(sRCMissionDetails.rcPlayableChars, ENUM_TO_INT(GET_CURRENT_PLAYER_PED_ENUM()))
|
|
PRINT_LAUNCHER_DEBUG("IS_RC_FINE_AND_IN_RANGE(): No longer a valid player character to launch mission")
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// Handle launcher anims - To be moved outside of this check...
|
|
IF IS_LAUNCHER_IDLE_ANIM_SETUP(sData.sAnims) AND (bAutoUpdateLaunchAnims)
|
|
// Update idle animations on the RC character.
|
|
// If one exists, beckon animation triggered when the player gets within range.
|
|
UPDATE_LAUNCHER_ANIMS(sData.pedID[0], sData.sAnims, sData.eMissionID)
|
|
ENDIF
|
|
|
|
// Whether mission is ok to proceed
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE: Checks whether the player is ok to activate the mission
|
|
/// PARAMS: bAllowVehicle - Mission can be triggered in a vehicle
|
|
/// RETURNS: TRUE if the mission can be activated, FALSE otherwise
|
|
FUNC BOOL IS_PLAYER_OK_TO_ACTIVATE_MISSION(BOOL bAllowVehicle=FALSE)
|
|
|
|
IF IS_PLAYER_PLAYING(GET_PLAYER_INDEX())
|
|
|
|
// Check for player being on foot
|
|
IF IS_PED_ON_FOOT(PLAYER_PED_ID())
|
|
RETURN TRUE
|
|
ELSE
|
|
// Check for players vehicle being on the ground
|
|
IF bAllowVehicle
|
|
IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
|
|
VEHICLE_INDEX playerVehicle = GET_PLAYERS_LAST_VEHICLE()
|
|
IF IS_VEHICLE_OK(playerVehicle)
|
|
|
|
IF IS_PED_IN_ANY_HELI(PLAYER_PED_ID())
|
|
OR IS_PED_IN_ANY_PLANE(PLAYER_PED_ID())
|
|
IF NOT HAS_ENTITY_COLLIDED_WITH_ANYTHING(playerVehicle) AND NOT IS_ENTITY_IN_AIR(playerVehicle) AND (GET_ENTITY_SPEED(playerVehicle) < 1.0)
|
|
RETURN TRUE
|
|
ENDIF
|
|
ELSE
|
|
IF NOT IS_ENTITY_IN_AIR(playerVehicle)
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// If this vehicle allows vehicle activation and player is in vehicle it brings him to a halt
|
|
/// And tells him to get out of the vehicle
|
|
PROC RC_STOP_PLAYER_VEHICLE_CHECK(BOOL bAllowVehicleActivation, g_eRC_MissionIDs eMissionID)
|
|
IF bAllowVehicleActivation = TRUE
|
|
|
|
IF NOT RC_MISSION_SHOULD_HALT_VEHICLE(eMissionID)
|
|
EXIT
|
|
ENDIF
|
|
|
|
IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
|
|
PRINT_LAUNCHER_DEBUG("RC_STOP_PLAYER_VEHICLE_CHECK: Stopping player's vehicle.")
|
|
|
|
IF IS_PED_IN_ANY_HELI(PLAYER_PED_ID())
|
|
OR IS_PED_IN_ANY_PLANE(PLAYER_PED_ID())
|
|
PRINT_LAUNCHER_DEBUG("RC_STOP_PLAYER_VEHICLE_CHECK: Turning off engine for plane or helicopter.")
|
|
SET_VEHICLE_ENGINE_ON(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()),FALSE, TRUE)
|
|
ENDIF
|
|
|
|
RC_PLAYER_TRIGGER_SCENE_LOCK_IN()
|
|
ENDIF
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
FUNC BOOL IS_PLAYER_WITHIN_PED_ACTIVATION_RANGE(g_structRCScriptArgs& sData)
|
|
|
|
IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
|
|
AND sData.bAllowVehicleActivation
|
|
|
|
FLOAT fStopping
|
|
|
|
// If Josh 1 or 4, only add 1 meter to the range so the player doesn't get sucked into the trigger while driving past on the road
|
|
// Otherwise, add 5 meters for all other missions
|
|
IF sData.eMissionID = RC_JOSH_1
|
|
OR sData.eMissionID = RC_JOSH_4
|
|
fStopping = 1.0
|
|
ELSE
|
|
fStopping = 5.0
|
|
ENDIF
|
|
|
|
// Add x.0m to activation range if in a vehicle (increased for bug 1113835)
|
|
IF (GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), GET_ENTITY_COORDS(sData.pedID[0])) < sData.activationRange + fStopping)
|
|
RETURN TRUE
|
|
ENDIF
|
|
ELSE
|
|
IF (GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), GET_ENTITY_COORDS(sData.pedID[0])) < sData.activationRange)
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Checks if the player has met the conditions necessary to launch this RC mission.
|
|
/// PARAMS:
|
|
/// sData - struct of launcher data
|
|
/// bStoreVehicleSnapshot - do we want to store the vehicle snapshot for this mission?
|
|
/// RETURNS:
|
|
/// TRUE if the player has met the conditions to launch this RC mission. FALSE otherwise.
|
|
FUNC BOOL ARE_RC_TRIGGER_CONDITIONS_MET(g_structRCScriptArgs& sData, BOOL bStoreVehicleSnapshot = FALSE)
|
|
|
|
//Check if they are close enough
|
|
SWITCH (sData.triggerType)
|
|
|
|
// Triggers when player is near to Random Character
|
|
CASE RC_TRIG_CHAR
|
|
|
|
// Epsilon 4 - Check area behind the bush to see if the player is there, and make the activation range much smaller if this is the case
|
|
IF sData.eMissionID = RC_EPSILON_4
|
|
IF IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<1826.630615,4699.115234,35.380890>>, <<1812.877563,4710.457031,42.053535>>, 23.75)
|
|
IF(IS_ENTITY_ALIVE(sData.pedID[0]))
|
|
IF (GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), GET_ENTITY_COORDS(sData.pedID[0])) < 3.0)
|
|
IF IS_IT_SAFE_TO_TRIGGER_SCRIPT_TYPE(ST_RANDOM_CHARACTER)
|
|
IF IS_PLAYER_OK_TO_ACTIVATE_MISSION(sData.bAllowVehicleActivation)
|
|
RC_STOP_PLAYER_VEHICLE_CHECK(sData.bAllowVehicleActivation, sData.eMissionID)
|
|
PRINT_LAUNCHER_DEBUG("ARE_RC_TRIGGER_CONDITIONS_MET: RC_TRIG_CHAR - Used special case Eps 4 trigger.")
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ELSE
|
|
//PRINT_LAUNCHER_DEBUG("ARE_RC_TRIGGER_CONDITIONS_MET: RC_TRIG_CHAR - IS_ENTITY_ALIVE(sData.pedID[0]) failed.")
|
|
RETURN FALSE
|
|
ENDIF
|
|
ELSE
|
|
IF(IS_ENTITY_ALIVE(sData.pedID[0]))
|
|
IF IS_PLAYER_WITHIN_PED_ACTIVATION_RANGE(sData)
|
|
IF IS_IT_SAFE_TO_TRIGGER_SCRIPT_TYPE(ST_RANDOM_CHARACTER)
|
|
IF IS_PLAYER_OK_TO_ACTIVATE_MISSION(sData.bAllowVehicleActivation)
|
|
RC_STOP_PLAYER_VEHICLE_CHECK(sData.bAllowVehicleActivation, sData.eMissionID)
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ELSE
|
|
//PRINT_LAUNCHER_DEBUG("ARE_RC_TRIGGER_CONDITIONS_MET: RC_TRIG_CHAR - IS_ENTITY_ALIVE(sData.pedID[0]) failed.")
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// Fanatic 1 - Check along the cliffside of the fence and stop the mission launching there (B*1350755)
|
|
ELIF sData.eMissionID = RC_FANATIC_1
|
|
IF NOT IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<-1895.787964,-434.019226,40.301258>>, <<-1883.037598,-444.081116,50.245090>>, 8.5)
|
|
AND NOT IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<-1883.576416,-443.643372,36.405807>>, <<-1874.825806,-448.079712,49.151619>>, 8.5)
|
|
AND NOT IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<-1876.342651,-446.221405,35.646370>>, <<-1866.951904,-456.560059,49.044197>>, 8.5)
|
|
AND NOT IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<-1882.997314,-438.992157,44.172462>>, <<-1874.079346,-443.342041,48.691788>>, 0.750)
|
|
OR IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<-1878.822266,-441.765503,44.917503>>, <<-1877.940918,-439.952209,47.289818>>, 1.25)
|
|
IF(IS_ENTITY_ALIVE(sData.pedID[0]))
|
|
IF IS_PLAYER_WITHIN_PED_ACTIVATION_RANGE(sData)
|
|
IF IS_IT_SAFE_TO_TRIGGER_SCRIPT_TYPE(ST_RANDOM_CHARACTER)
|
|
IF IS_PLAYER_OK_TO_ACTIVATE_MISSION(sData.bAllowVehicleActivation)
|
|
RC_STOP_PLAYER_VEHICLE_CHECK(sData.bAllowVehicleActivation, sData.eMissionID)
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ELSE
|
|
//PRINT_LAUNCHER_DEBUG("ARE_RC_TRIGGER_CONDITIONS_MET: RC_TRIG_CHAR - IS_ENTITY_ALIVE(sData.pedID[0]) failed.")
|
|
RETURN FALSE
|
|
ENDIF
|
|
ELSE
|
|
RETURN FALSE // Player is on the wrong side of the fence
|
|
ENDIF
|
|
|
|
// Fanatic 2 - Don't trigger the mission on the side of the hill
|
|
ELIF sData.eMissionID = RC_FANATIC_2
|
|
IF NOT IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<837.073059,1261.086182,366.159180>>, <<780.838257,1260.828613,351.404999>>, 17.750)
|
|
IF(IS_ENTITY_ALIVE(sData.pedID[0]))
|
|
IF IS_PLAYER_WITHIN_PED_ACTIVATION_RANGE(sData)
|
|
IF IS_IT_SAFE_TO_TRIGGER_SCRIPT_TYPE(ST_RANDOM_CHARACTER)
|
|
IF IS_PLAYER_OK_TO_ACTIVATE_MISSION(sData.bAllowVehicleActivation)
|
|
RC_STOP_PLAYER_VEHICLE_CHECK(sData.bAllowVehicleActivation, sData.eMissionID)
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ELSE
|
|
//PRINT_LAUNCHER_DEBUG("ARE_RC_TRIGGER_CONDITIONS_MET: RC_TRIG_CHAR - IS_ENTITY_ALIVE(sData.pedID[0]) failed.")
|
|
RETURN FALSE
|
|
ENDIF
|
|
ELSE
|
|
RETURN FALSE // Player is on the wrong side of the fence
|
|
ENDIF
|
|
// If this is any other mission, do what should be done normally
|
|
ELSE
|
|
IF(IS_ENTITY_ALIVE(sData.pedID[0]))
|
|
IF IS_PLAYER_WITHIN_PED_ACTIVATION_RANGE(sData)
|
|
IF IS_IT_SAFE_TO_TRIGGER_SCRIPT_TYPE(ST_RANDOM_CHARACTER)
|
|
IF IS_PLAYER_OK_TO_ACTIVATE_MISSION(sData.bAllowVehicleActivation)
|
|
RC_STOP_PLAYER_VEHICLE_CHECK(sData.bAllowVehicleActivation, sData.eMissionID)
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ELSE
|
|
//PRINT_LAUNCHER_DEBUG("ARE_RC_TRIGGER_CONDITIONS_MET: RC_TRIG_CHAR - IS_ENTITY_ALIVE(sData.pedID[0]) failed.")
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDIF
|
|
BREAK
|
|
|
|
// Triggers when player enters specified vehicle
|
|
CASE RC_TRIG_ENTER_VEHICLE
|
|
|
|
IF IS_ENTITY_ALIVE(sData.vehID[0])
|
|
IF IS_PED_IN_VEHICLE(PLAYER_PED_ID(),sData.vehID[0])
|
|
IF IS_IT_SAFE_TO_TRIGGER_SCRIPT_TYPE(ST_RCM_VEHICLE)
|
|
RC_STOP_PLAYER_VEHICLE_CHECK(sData.bAllowVehicleActivation, sData.eMissionID)
|
|
RETURN TRUE
|
|
ENDIF
|
|
ELSE
|
|
IF bStoreVehicleSnapshot = TRUE
|
|
// Not in vehicle, but script has not terminated yet (store player's vehicle for snapshot)
|
|
STORE_START_PLAYER_VEHICLE_SNAPSHOT()
|
|
ENDIF
|
|
ENDIF
|
|
ELSE
|
|
//PRINT_LAUNCHER_DEBUG("ARE_RC_TRIGGER_CONDITIONS_MET: RC_TRIG_ENTER_VEHICLE - IS_ENTITY_ALIVE(sData.vehID[0]) failed.")
|
|
RETURN FALSE
|
|
ENDIF
|
|
BREAK
|
|
|
|
// Triggers when player is near to a specified vehicle
|
|
CASE RC_TRIG_NEAR_VEHICLE
|
|
|
|
IF DOES_ENTITY_EXIST(sData.vehID[0])
|
|
IF NOT IS_ENTITY_DEAD(sData.vehID[0])
|
|
IF (GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), GET_ENTITY_COORDS(sData.vehID[0])) < sData.activationRange)
|
|
IF IS_IT_SAFE_TO_TRIGGER_SCRIPT_TYPE(ST_RANDOM_CHARACTER)
|
|
IF IS_PLAYER_OK_TO_ACTIVATE_MISSION(sData.bAllowVehicleActivation)
|
|
RC_STOP_PLAYER_VEHICLE_CHECK(sData.bAllowVehicleActivation, sData.eMissionID)
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ELSE
|
|
//PRINT_LAUNCHER_DEBUG("ARE_RC_TRIGGER_CONDITIONS_MET: RC_TRIG_NEAR_VEHICLE - DOES_ENTITY_EXIST(sData.vehID[0]) failed.")
|
|
RETURN FALSE
|
|
ENDIF
|
|
BREAK
|
|
|
|
// Player has got within activation range of trigger coords
|
|
CASE RC_TRIG_LOCATE_POINT
|
|
|
|
IF (GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), sData.triggerLocate[0]) < sData.activationRange)
|
|
IF IS_IT_SAFE_TO_TRIGGER_SCRIPT_TYPE(ST_RANDOM_CHARACTER)
|
|
IF IS_PLAYER_OK_TO_ACTIVATE_MISSION(sData.bAllowVehicleActivation)
|
|
RC_STOP_PLAYER_VEHICLE_CHECK(sData.bAllowVehicleActivation, sData.eMissionID)
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
ELSE
|
|
//PRINT_LAUNCHER_DEBUG("ARE_RC_TRIGGER_CONDITIONS_MET: RC_TRIG_LOCATE_POINT - GET_DISTANCE_BETWEEN_COORDS() failed.")
|
|
RETURN FALSE
|
|
ENDIF
|
|
BREAK
|
|
|
|
// Player has entered axis aligned locate
|
|
CASE RC_TRIG_LOCATE_AXIS
|
|
|
|
IF IS_ENTITY_AT_COORD(PLAYER_PED_ID(), sData.triggerLocate[0], sData.triggerLocate[1])
|
|
IF IS_IT_SAFE_TO_TRIGGER_SCRIPT_TYPE(ST_RANDOM_CHARACTER)
|
|
IF IS_PLAYER_OK_TO_ACTIVATE_MISSION(sData.bAllowVehicleActivation)
|
|
RC_STOP_PLAYER_VEHICLE_CHECK(sData.bAllowVehicleActivation, sData.eMissionID)
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
ELSE
|
|
//PRINT_LAUNCHER_DEBUG("RC5_IN_ACTIVATION_RANGE: RC_TRIG_LOCATE_AXIS - IS_ENTITY_AT_COORD failed.")
|
|
RETURN FALSE
|
|
ENDIF
|
|
BREAK
|
|
|
|
// Player has entered non-axis aligned locate
|
|
CASE RC_TRIG_LOCATE_NONAXIS
|
|
|
|
// Barry 3C can trigger if the player attaches a tow truck or cargobob to the stash car
|
|
IF sData.eMissionID = RC_BARRY_3C
|
|
IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
|
|
IF IS_ENTITY_ALIVE(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()))
|
|
IF IS_VEHICLE_MODEL(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()), TOWTRUCK)
|
|
OR IS_VEHICLE_MODEL(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()), TOWTRUCK2)
|
|
IF IS_VEHICLE_ATTACHED_TO_TOW_TRUCK(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()), sData.vehID[0])
|
|
IF IS_IT_SAFE_TO_TRIGGER_SCRIPT_TYPE(ST_RCM_VEHICLE)
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
ELIF IS_VEHICLE_MODEL(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()), CARGOBOB)
|
|
OR IS_VEHICLE_MODEL(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()), CARGOBOB2)
|
|
OR IS_VEHICLE_MODEL(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()), CARGOBOB3)
|
|
IF DOES_CARGOBOB_HAVE_PICK_UP_ROPE(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()))
|
|
AND IS_VEHICLE_ATTACHED_TO_CARGOBOB(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()), sData.vehID[0])
|
|
IF IS_IT_SAFE_TO_TRIGGER_SCRIPT_TYPE(ST_RCM_VEHICLE)
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// B*1334138 - Special case for Epsilon 2
|
|
ELIF sData.eMissionID = RC_EPSILON_2
|
|
IF GET_PED_DESIRED_MOVE_BLEND_RATIO(PLAYER_PED_ID()) >= PEDMOVEBLENDRATIO_RUN
|
|
IF IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<245.888489,371.903412,103.988426>>, <<241.589844,359.645752,107.346123>>, 1.25)
|
|
IF IS_IT_SAFE_TO_TRIGGER_SCRIPT_TYPE(ST_RANDOM_CHARACTER)
|
|
IF IS_PLAYER_OK_TO_ACTIVATE_MISSION(sData.bAllowVehicleActivation)
|
|
RC_STOP_PLAYER_VEHICLE_CHECK(sData.bAllowVehicleActivation, sData.eMissionID)
|
|
PRINT_LAUNCHER_DEBUG("RC5_IN_ACTIVATION_RANGE: RC_TRIG_LOCATE_NONAXIS - Eps 2 special case trigger used")
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// B*1426354 - special case exclusion zone for Paparazzo 1
|
|
ELIF sData.eMissionID = RC_PAPARAZZO_1
|
|
IF IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<-164.204559,277.486633,91.553215>>, <<-153.599960,277.406067,97.338135>>, 10.000000)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
// B*1394562 - special case force launch in vehicle when close to Maude for Maude 1
|
|
ELIF sData.eMissionID = RC_MAUDE_1
|
|
IF IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<2728.948242,4143.439941,42.292946>>, <<2722.213379,4144.521484,45.431824>>, 10.000000)
|
|
IF IS_IT_SAFE_TO_TRIGGER_SCRIPT_TYPE(ST_RANDOM_CHARACTER)
|
|
IF IS_PLAYER_OK_TO_ACTIVATE_MISSION(TRUE)
|
|
RC_STOP_PLAYER_VEHICLE_CHECK(TRUE, sData.eMissionID)
|
|
PRINT_LAUNCHER_DEBUG("RC_IN_ACTIVATION_RANGE: RC_TRIG_LOCATE_NONAXIS - RC_MAUDE_1 special case vehicle launch area")
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
// B*1533146 - special case launch extra area cover garden for Nigel 1B
|
|
ELIF sData.eMissionID = RC_NIGEL_1B
|
|
IF IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<-992.499451,358.745453,96.373505>>, <<-1021.940125,361.888763,65.361481>>, 30.000000)
|
|
IF NOT IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<-983.542603,369.110352,68.460175>>, <<-1028.566284,395.461334,94.572449>>, 15.000000) // exclude the road (North side)
|
|
IF NOT IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<-983.875000,346.755646,68.020958>>, <<-1021.451416,336.345825,93.187141>>, 14.500000) // exclude the road (South side)
|
|
IF IS_IT_SAFE_TO_TRIGGER_SCRIPT_TYPE(ST_RANDOM_CHARACTER)
|
|
IF IS_PLAYER_OK_TO_ACTIVATE_MISSION(sData.bAllowVehicleActivation)
|
|
RC_STOP_PLAYER_VEHICLE_CHECK(sData.bAllowVehicleActivation, sData.eMissionID)
|
|
PRINT_LAUNCHER_DEBUG("RC_IN_ACTIVATION_RANGE: RC_TRIG_LOCATE_NONAXIS - RC_NIGEL_1B special case vehicle launch area")
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), sData.triggerLocate[0], sData.triggerLocate[1], sData.triggerWidth)
|
|
// Had to expand the trigger width for Omega 2 for B*1427155, but this means if you walk behind the trailer, the mission triggers
|
|
// and the lead-in plays when Omega is obscured
|
|
// So if the player is in the trigger area but in this special area, don't trigger the mission
|
|
IF sData.eMissionID = RC_OMEGA_2
|
|
IF IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<2338.696533,2597.037354,45.390518>>, <<2324.003418,2597.185059,47.749607>>, 8.5)
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDIF
|
|
IF IS_IT_SAFE_TO_TRIGGER_SCRIPT_TYPE(ST_RANDOM_CHARACTER)
|
|
IF IS_PLAYER_OK_TO_ACTIVATE_MISSION(sData.bAllowVehicleActivation)
|
|
RC_STOP_PLAYER_VEHICLE_CHECK(sData.bAllowVehicleActivation, sData.eMissionID)
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
ELSE
|
|
//PRINT_LAUNCHER_DEBUG("RC5_IN_ACTIVATION_RANGE: RC_TRIG_LOCATE_NONAXIS - IS_ENTITY_IN_ANGLED_AREA failed.")
|
|
RETURN FALSE
|
|
ENDIF
|
|
BREAK
|
|
|
|
// Shouldn't reach this section...
|
|
CASE RC_TRIG_NOT_SET
|
|
// Invalid script file so terminate script
|
|
SCRIPT_ASSERT("NO RC Trigger Type Set")
|
|
BREAK
|
|
ENDSWITCH
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Checks if the player has entered the custom polygon defined for this RCM
|
|
FUNC BOOL ARE_RC_TRIGGER_POLY_CONDITIONS_MET(g_structRCScriptArgs& sData, TEST_POLY& pMissionTrigger)
|
|
|
|
IF IS_POINT_IN_POLY_2D(pMissionTrigger, GET_ENTITY_COORDS(PLAYER_PED_ID()))
|
|
IF IS_IT_SAFE_TO_TRIGGER_SCRIPT_TYPE(ST_RANDOM_CHARACTER)
|
|
IF IS_PLAYER_OK_TO_ACTIVATE_MISSION(sData.bAllowVehicleActivation)
|
|
RC_STOP_PLAYER_VEHICLE_CHECK(sData.bAllowVehicleActivation, sData.eMissionID)
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Common stat function shared amongst RC launcher and ambient launched RC missions
|
|
PROC PRIME_STATS_FOR_RC_MISSION(g_eRC_MissionIDs eMissionID, STRING sScriptName)
|
|
|
|
// Script name only referenced in debug output
|
|
DUMMY_REFERENCE_STRING(sScriptName)
|
|
|
|
//old stat procedure
|
|
CPRINTLN(DEBUG_FLOW, "PRIME_STATS_FOR_RC_MISSION(", sScriptName, ")" )
|
|
CLEAR_BIT(g_savedGlobals.sRandomChars.savedRC[eMissionID].rcFlags, ENUM_TO_INT(RC_FLAG_STATWATCHER_RUNNING))
|
|
IF GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(HASH("mission_stat_watcher")) > 0
|
|
WHILE GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(HASH("mission_stat_watcher")) > 0
|
|
TERMINATE_STAT_WATCHER()
|
|
CPRINTLN(DEBUG_FLOW, "PRIME_STATS_FOR_RC_MISSION(", sScriptName, "): Waiting for old stat watcher to terminate. Flag is : ", g_bMissionStatSystemResetFlag )
|
|
//IS_BIT_SET(g_savedGlobals.sRandomChars.savedRC[eMissionID].rcFlags, RC_FLAG_STATWATCHER_RUNNING)
|
|
WAIT(0)
|
|
ENDWHILE
|
|
ENDIF
|
|
//watcher needs to be running
|
|
IF GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(HASH("mission_stat_watcher")) < 1
|
|
g_bMissionStatSystemResetFlag = FALSE
|
|
REQUEST_SCRIPT("mission_stat_watcher")
|
|
WHILE NOT HAS_SCRIPT_LOADED("mission_stat_watcher")
|
|
CPRINTLN(DEBUG_FLOW, "PRIME_STATS_FOR_RC_MISSION(", sScriptName, "): Waiting for stat watcher script to load.")
|
|
WAIT(0)
|
|
ENDWHILE
|
|
START_NEW_SCRIPT("mission_stat_watcher", SPECIAL_ABILITY_STACK_SIZE)
|
|
SET_SCRIPT_AS_NO_LONGER_NEEDED("mission_stat_watcher")
|
|
|
|
ENDIF
|
|
|
|
WHILE NOT IS_BIT_SET(g_savedGlobals.sRandomChars.savedRC[eMissionID].rcFlags, ENUM_TO_INT(RC_FLAG_STATWATCHER_RUNNING))
|
|
CPRINTLN(DEBUG_FLOW, "PRIME_STATS_FOR_RC_MISSION(", sScriptName, "): Waiting for watcher thread to start.")
|
|
IF GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(HASH("mission_stat_watcher")) > 0
|
|
SET_BIT(g_savedGlobals.sRandomChars.savedRC[eMissionID].rcFlags, ENUM_TO_INT(RC_FLAG_STATWATCHER_RUNNING))
|
|
ENDIF
|
|
ENDWHILE
|
|
|
|
|
|
//WAIT(10)
|
|
|
|
// Setup mission stats
|
|
//IF NOT IS_REPLAY_IN_PROGRESS() // (not needed for replays) //yes it needed is due to priming issue
|
|
// This condition was the cause of 1381672
|
|
FLOW_PRIME_STATS_FOR_RC_MISSION(eMissionID)
|
|
//ENDIF
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Attempts to launch the specified RC mission.
|
|
/// If successful it also updates playstats system and stores starting snapshot.
|
|
/// PARAMS:
|
|
/// sData - struct of launcher data.
|
|
/// RETURNS:
|
|
/// TRUE if mission launch is succesful, FALSE otherwise.
|
|
FUNC BOOL LAUNCH_RC_MISSION(g_structRCScriptArgs& sData)
|
|
|
|
IF NOT IS_REPLAY_IN_PROGRESS() //(replays already have permission to run)
|
|
// 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(sData.eMissionID)
|
|
|
|
//Prevent player from still running after focus push during rampages
|
|
IF IS_MISSION_A_RAMPAGE( sData.eMissionID )
|
|
RC_PLAYER_TRIGGER_SCENE_LOCK_IN()
|
|
ENDIF
|
|
|
|
// Not yet given permission to run, should the script terminate?
|
|
IF NOT IS_RC_FINE_AND_IN_RANGE(sData, sData.eMissionID <> RC_BARRY_1)
|
|
PRINT_LAUNCHER_DEBUG("LAUNCH_RC_MISSION - NOT IS_RC_FINE_AND_IN_RANGE() [TERMINATING]")
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
WAIT(0)
|
|
ENDWHILE
|
|
ENDIF
|
|
|
|
// Kill any conversation, e.g. AMB dialogue
|
|
IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
|
|
KILL_ANY_CONVERSATION()
|
|
ENDIF
|
|
|
|
// 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.
|
|
IF NOT REQUEST_AND_LAUNCH_RC(sData)
|
|
PRINT_LAUNCHER_DEBUG("STEP_7_COMMON_LaunchMission - Trying to launch a null script string name")
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
// Tell the playstats system that we're starting an RC mission.
|
|
g_structRCMissionsStatic sRCMissionDetails
|
|
Retrieve_Random_Character_Static_Mission_Details(sData.eMissionID, sRCMissionDetails)
|
|
TEXT_LABEL tStatLabel = GET_RC_STAT_ID(sData.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(sData.eMissionID)
|
|
|
|
// Store start snapshot if this isn't a replay
|
|
IF NOT IS_REPLAY_IN_PROGRESS()
|
|
IF sData.triggerType = RC_TRIG_ENTER_VEHICLE
|
|
Store_RC_Replay_Starting_Snapshot(sData.sScriptName, FALSE) // enter vehicle missions, don't store vehicle info
|
|
ELSE
|
|
Store_RC_Replay_Starting_Snapshot(sData.sScriptName, TRUE) // normal missions, store vehicle info
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// Setup mission ready for stats
|
|
PRIME_STATS_FOR_RC_MISSION(sData.eMissionID, sRCMissionDetails.rcScriptName)
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Waits until launcher is safe to terminate.
|
|
/// This gets set by RC_CLEANUP_LAUNCHER().
|
|
/// PARAMS:
|
|
/// eRCMissionToLaunch - the RC mission that is being launched.
|
|
/// RETURNS:
|
|
/// TRUE when the launcher should terminate.
|
|
FUNC BOOL IS_RC_LAUNCHER_SAFE_TO_TERMINATE(g_eRC_MissionIDs& eRCMissionToLaunch)
|
|
|
|
CPRINTLN(DEBUG_RANDOM_CHAR, "IS_RC_LAUNCHER_SAFE_TO_TERMINATE() - WAITING...")
|
|
|
|
WHILE NOT (g_RandomChars[eRCMissionToLaunch].rcTerminateLauncher)
|
|
WAIT(0)
|
|
ENDWHILE
|
|
|
|
CPRINTLN(DEBUG_RANDOM_CHAR, "IS_RC_LAUNCHER_SAFE_TO_TERMINATE() - RETURNING TRUE")
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE: Reset all basic values of the data, so each scene has to set them up correctly.
|
|
PROC RC_Reset_LauncherData(g_structRCScriptArgs& sData)
|
|
|
|
sData.eMissionID = NO_RC_MISSION
|
|
sData.sScriptName = ""
|
|
sData.activationRange = RANDOMCHAR_ACTIVATE_MISSION_RANGE
|
|
sData.triggerType = RC_TRIG_NOT_SET
|
|
sData.bPedsCritical = FALSE
|
|
sData.bVehsCritical = FALSE
|
|
sData.bAllowVehicleActivation = FALSE
|
|
ENDPROC
|
|
|
|
/// PURPOSE: Sets the visibility states of all entities within a scene.
|
|
PROC RC_SetScenePedsVisible(g_structRCScriptArgs& sData, Bool bOn)
|
|
|
|
INT i = 0
|
|
|
|
FOR i=0 TO COUNT_OF(sData.pedID) - 1
|
|
IF DOES_ENTITY_EXIST(sData.pedID[i])
|
|
SET_ENTITY_VISIBLE(sData.pedID[i], bOn)
|
|
ENDIF
|
|
ENDFOR
|
|
ENDPROC
|