//Compile out Title Update changes to header functions. //Must be before includes. //CONST_INT USE_TU_CHANGES 0 // Removed by Kenneth R. USING "RC_Setup_public.sch" USING "cutscene_public.sch" USING "RC_launcher_public.sch" USING "RC_Setup_public.sch" USING "initial_scenes_Nigel.sch" // ***************************************************************************************** // SCRIPT NAME : launcher_Nigel.sc // // AUTHOR : David Roberts / Andrew Minghella // // DESCRIPTION : Launcher script that determines which RC mission scene to setup. // This launcher script should be attached to appropriate world point. // // If multiple missions share same coord or are within close proximity, // we should just add one world point, and adjust the tolerance float. // ***************************************************************************************** // ------------Variables---------------------- CONST_FLOAT WORLD_POINT_COORD_TOLERANCE 1.0 INT iCutsceneLoadRequestID = NULL_OFFMISSION_CUTSCENE_REQUEST // ID to register off-mission cutscene load request with cutscene_controller. BLIP_INDEX biLeadIn ENUM convPauseState CONVPS_READY, CONVPS_PAUSED, CONVPS_PLAYING, CONVPS_COMPLETE ENDENUM convPauseState convState = CONVPS_READY // ----------Functions ------------------------- /// PURPOSE: Play a conversation in full from two RC peds FUNC BOOL PLAY_LAUNCHER_FULL_CONVERSATION_ONCE(g_structRCScriptArgs& sData, VECTOR v_ped_pos, STRING s_dialogue_slot, STRING s_dialogue_to_play, INT ped0_dialogue_number, STRING ped0_dialogue_name, INT ped1_dialogue_number, STRING ped1_dialogue_name, convPauseState& convPS) IF NOT (convPS = CONVPS_COMPLETE) 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 IS_ENTITY_ALIVE(sData.pedID[1]) AND GET_DISTANCE_BETWEEN_ENTITY_AND_COORD(PLAYER_PED_ID(), v_ped_pos) < 20.0 PRINT_LAUNCHER_DEBUG("start conversation") structPedsForConversation s_conversation IF (convPS = CONVPS_READY) ADD_PED_FOR_DIALOGUE(s_conversation, ped0_dialogue_number, sData.pedID[0], ped0_dialogue_name) ADD_PED_FOR_DIALOGUE(s_conversation, ped1_dialogue_number, sData.pedID[1], ped1_dialogue_name) ADD_NON_CRITICAL_STANDARD_CONVERSATION_TO_BUFFER(s_conversation, s_dialogue_slot, s_dialogue_to_play, CONV_PRIORITY_MEDIUM) convPS = CONVPS_PLAYING ELIF (convPS = CONVPS_PLAYING) PRINT_LAUNCHER_DEBUG("conversation ended") convPS = CONVPS_COMPLETE RETURN TRUE ENDIF ENDIF ELSE IF RC_IS_THIS_CONVERSATION_ROOT_PLAYING(s_dialogue_to_play) AND NOT (convPS = CONVPS_PAUSED) AND IS_ENTITY_ALIVE(PLAYER_PED_ID()) AND GET_DISTANCE_BETWEEN_ENTITY_AND_COORD(PLAYER_PED_ID(), v_ped_pos) >= 20.0 PRINT_LAUNCHER_DEBUG("pause conversation") PAUSE_FACE_TO_FACE_CONVERSATION(TRUE) convPS = CONVPS_PAUSED ENDIF ENDIF IF (GET_DISTANCE_BETWEEN_ENTITY_AND_COORD(PLAYER_PED_ID(), v_ped_pos) < 20.0) AND (convPS = CONVPS_PAUSED) PRINT_LAUNCHER_DEBUG("unpause conversation") PAUSE_FACE_TO_FACE_CONVERSATION(FALSE) convPS = CONVPS_PLAYING ENDIF ENDIF ENDIF RETURN FALSE ENDFUNC /// PURPOSE: /// Checks for if the player has damaged any peds in the RC initial scene /// Used only for Nigel 1D, to fix B*1897651 /// PARAMS: /// sData - launcher data struct /// RETURNS: /// True if player has damaged any of the peds, false otherwise FUNC BOOL HAS_PLAYER_DAMAGED_ANY_N1D_PEDS(g_structRCScriptArgs& sData) INT iCount = 0 IF IS_ENTITY_ALIVE(PLAYER_PED_ID()) FOR iCount = 0 to COUNT_OF(sData.pedID)-1 IF DOES_ENTITY_EXIST(sData.pedID[iCount]) IF IS_ENTITY_ALIVE(sData.pedID[iCount]) IF HAS_ENTITY_BEEN_DAMAGED_BY_ENTITY(sData.pedID[iCount], PLAYER_PED_ID()) OR IS_BULLET_IN_AREA(GET_ENTITY_COORDS(sData.pedID[iCount]), 7.5) IF IS_IT_SAFE_TO_TRIGGER_SCRIPT_TYPE(ST_RANDOM_CHARACTER) RC_STOP_PLAYER_VEHICLE_CHECK(sData.bAllowVehicleActivation, sData.eMissionID) RETURN TRUE ELSE PRINT_LAUNCHER_DEBUG("Player damaged the N1D peds but it's not safe to trigger the mission!") ENDIF ENDIF ELSE IF IS_IT_SAFE_TO_TRIGGER_SCRIPT_TYPE(ST_RANDOM_CHARACTER) RC_STOP_PLAYER_VEHICLE_CHECK(sData.bAllowVehicleActivation, sData.eMissionID) RETURN TRUE ELSE PRINT_LAUNCHER_DEBUG("Player killed a N1D ped but it's not safe to trigger the mission!") ENDIF ENDIF ENDIF ENDFOR ENDIF RETURN FALSE ENDFUNC /// PURPOSE: /// Does any necessary cleanup and terminates the launcher's thread. /// PARAMS: /// sData - launcher data struct /// bCleanupEntities - do we want to cleanup the entities in the launcher struct PROC Script_Cleanup(g_structRCScriptArgs& sData, BOOT_EVENT_VARS& beVars, BOOL bCleanupEntities = TRUE) // Have to delete Al from boot before general cleanup IF sData.eMissionID = RC_NIGEL_3 SAFE_DELETE_PED(sData.pedID[1]) ENDIF // Remove lead-in blip IF DOES_BLIP_EXIST(biLeadIn) REMOVE_BLIP(biLeadIn) ENDIF // Remove scene entities IF bCleanupEntities PRINT_LAUNCHER_DEBUG("SCRIPT TERMINATING: Cleaning up entities in Launcher") //B*1470358 - disable the interior in the launcher cleanup if the mission didn't launch (enabled in the initial scene) IF sData.eMissionID = RC_NIGEL_1A SET_INTERIOR_CAPPED(INTERIOR_V_ROCKCLUB, TRUE) CLEANUP_NIGEL1A_SYNC_SCENE(sData) PRINT_LAUNCHER_DEBUG(" Script_Cleanup - SET_INTERIOR_CAPPED(INTERIOR_V_ROCKCLUB, TRUE)") ELIF sData.eMissionID = RC_NIGEL_1B CLEANUP_NIGEL1B_SYNC_SCENE(sData) ENDIF RC_CleanupSceneEntities(sData, FALSE) ENDIF // Ensure mission areas and scenarios are restored SETUP_AREA_FOR_MISSION(sData.eMissionID, FALSE) // Mission specific cleanup SWITCH sData.eMissionID // Cleanup boot sound effects CASE RC_NIGEL_3 IF beVars.iSoundID <> -1 RELEASE_SOUND_ID(beVars.iSoundID) ENDIF BREAK ENDSWITCH // Unload launcher animation dictionary REMOVE_LAUNCHER_ANIM_DICT(sData.sAnims) // Clear any cutscene requests with controller. IF iCutsceneLoadRequestID != NULL_OFFMISSION_CUTSCENE_REQUEST PRINT_LAUNCHER_DEBUG("SCRIPT TERMINATING: Ending off-mission cutscene request") END_OFFMISSION_CUTSCENE_REQUEST(iCutsceneLoadRequestID) ENDIF // Stop launcher conversation STRING sConversationRoot SWITCH sData.eMissionID CASE RC_NIGEL_1 sConversationRoot = "NIG1A_AMB" BREAK ENDSWITCH RC_STOP_LAUNCHER_DIALOGUE(sConversationRoot) //B*1574385 - Force update to blip in RandChar Controller if mission wasn't launched IF bCleanupEntities SET_RC_AWAITING_TRIGGER(sData.eMissionID) ENDIF RC_LAUNCHER_END() // Kill the thread PRINT_LAUNCHER_DEBUG("SCRIPT TERMINATED") TERMINATE_THIS_THREAD() ENDPROC /// PURPOSE: /// Creates the initial scene /// PARAMS: /// sData - launcher data struct FUNC BOOL LOAD_INITIAL_SCENE(g_structRCScriptArgs& sData, TEST_POLY& pTrigger) //Setup the correct initial scene SWITCH sData.eMissionID CASE RC_NIGEL_1 IF NOT SetupScene_NIGEL_1(sData) RETURN FALSE ENDIF BREAK CASE RC_NIGEL_1A IF NOT SetupScene_NIGEL_1A(sData) RETURN FALSE ENDIF BREAK CASE RC_NIGEL_1B IF NOT SetupScene_NIGEL_1B(sData) RETURN FALSE ENDIF BREAK CASE RC_NIGEL_1C IF NOT SetupScene_NIGEL_1C(sData) RETURN FALSE ENDIF BREAK CASE RC_NIGEL_1D IF NOT SetupScene_NIGEL_1D(sData, pTrigger) RETURN FALSE ENDIF BREAK CASE RC_NIGEL_2 IF NOT SetupScene_NIGEL_2(sData) RETURN FALSE ENDIF BREAK CASE RC_NIGEL_3 IF NOT SetupScene_NIGEL_3(sData) RETURN FALSE ENDIF BREAK ENDSWITCH // Scene creation successful PRINT_LAUNCHER_DEBUG("Created initial scene") RETURN TRUE ENDFUNC /// PURPOSE: /// Main script loops /// PARAMS: /// in_coords - world point co-ords SCRIPT(coords_struct in_coords) // Launcher priority for streaming requests SET_THIS_IS_A_TRIGGER_SCRIPT(TRUE) RC_LAUNCHER_START() g_structRCScriptArgs sRCLauncherData // Scene information to pass to mission script VECTOR vInCoords = <<0,0,0>> // Stores world point location TEST_POLY pMissionTrigger // Custom area used for Nigel sub-missions BOOT_EVENT_VARS bevNigel3 // Needed in Nigel3 initial scene //Reset all basic values of the data, so each scene has to set them up correctly RC_Reset_LauncherData(sRCLauncherData) // Update world point vInCoords = in_coords.vec_coord[0] // Set soundID to -1 so we know whether it needs releasing bevNigel3.iSoundID = -1 // Determine which RC mission we are attempting to launch (currently done on a launcher by launcher basis) g_eRC_MissionIDs eRCMissions[7] eRCMissions[0] = RC_NIGEL_1 eRCMissions[1] = RC_NIGEL_1A eRCMissions[2] = RC_NIGEL_1B eRCMissions[3] = RC_NIGEL_1C eRCMissions[4] = RC_NIGEL_1D eRCMissions[5] = RC_NIGEL_2 eRCMissions[6] = RC_NIGEL_3 // 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|FORCE_CLEANUP_FLAG_REPEAT_PLAY)) PRINT_LAUNCHER_DEBUG("Force cleanup [TERMINATING]") // Ensure candidate id is released in the event that the player has died // or been arrested prior to mission launch IF sRCLauncherData.eMissionID <> NO_RC_MISSION IF (g_RandomChars[sRCLauncherData.eMissionID].rcMissionCandidateID <> NO_CANDIDATE_ID) PRINT_LAUNCHER_DEBUG("Relinquishing candidate id...") Mission_Over(g_RandomChars[sRCLauncherData.eMissionID].rcMissionCandidateID) ENDIF ENDIF // Standard cleanup Script_Cleanup(sRCLauncherData, bevNigel3) ENDIF //Pick which mission activated us IF NOT DETERMINE_RC_TO_LAUNCH(eRCMissions, sRCLauncherData, vInCoords, WORLD_POINT_COORD_TOLERANCE) RC_LAUNCHER_END() PRINT_LAUNCHER_DEBUG("SCRIPT TERMINATED") TERMINATE_THIS_THREAD() // B* 1510945 - don't call cleanup if nothing has been setup yet ENDIF // Check with the Random Character Controller to see if this script is allowed to launch IF NOT CAN_RC_LAUNCH(sRCLauncherData.eMissionID) RC_LAUNCHER_END() PRINT_LAUNCHER_DEBUG("SCRIPT TERMINATED") TERMINATE_THIS_THREAD() // B* 1510945 - don't call cleanup if nothing has been setup yet ENDIF // Shutdown launcher when we are incorrect character IF Random_Character_Blocked_Due_To_Character(sRCLauncherData.eMissionID) RC_LAUNCHER_END() PRINT_LAUNCHER_DEBUG("SCRIPT TERMINATED") TERMINATE_THIS_THREAD() // B* 1510945 - don't call cleanup if nothing has been setup yet ENDIF // The script is allowed to launch - set up the initial scene WHILE NOT LOAD_INITIAL_SCENE(sRCLauncherData, pMissionTrigger) WAIT(0) IF NOT IS_WORLD_POINT_WITHIN_BRAIN_ACTIVATION_RANGE() PRINT_LAUNCHER_DEBUG("Player out of range [TERMINATING]") Script_Cleanup(sRCLauncherData, bevNigel3) ENDIF ENDWHILE // Handle special case car boot thumps in Nigel 3 IF sRCLauncherData.eMissionID = RC_NIGEL_3 bevNigel3.timedSound = BE_INIT ENDIF // Clears area of non-mission entities and blood decals CLEAR_AREA(vInCoords, sRCLauncherData.activationRange, TRUE) // Loop to check conditions - should script terminate? or is player close enough to trigger mission? WHILE (TRUE) WAIT(0) //Is the player still in activation range IF NOT IS_RC_FINE_AND_IN_RANGE(sRCLauncherData) Script_Cleanup(sRCLauncherData, bevNigel3) ENDIF SET_RC_AWAITING_TRIGGER(sRCLauncherData.eMissionID) MANAGE_PRELOADING_RC_CUTSCENE(iCutsceneLoadRequestID, sRCLauncherData.sIntroCutscene, vInCoords) // B*1347748 - set Di Napoli to trouser's variation IF sRCLauncherData.eMissionID = RC_NIGEL_2 IF CAN_REQUEST_ASSETS_FOR_CUTSCENE_ENTITY() SET_CUTSCENE_PED_COMPONENT_VARIATION(GET_AL_DI_NAPOLI_SCENE_HANDLE(), PED_COMP_LEG, 0, 0, GET_AL_DI_NAPOLI_PED_MODEL()) PRINT_LAUNCHER_DEBUG("Nigel 2 : set Di Napoli's cutscene trousers variation in launcher") ENDIF ENDIF // Handle extra launcher anims for Nigel 1 IF IS_LAUNCHER_IDLE_ANIM_SETUP(extraAnims) AND sRCLauncherData.eMissionID = RC_NIGEL_1 // Update idle and beckon animations on the second RC character. UPDATE_LAUNCHER_ANIMS(sRCLauncherData.pedID[1], extraAnims, sRCLauncherData.eMissionID) ENDIF IF sRCLauncherData.eMissionID = RC_NIGEL_1 // B*1359585 PLAY_LAUNCHER_FULL_CONVERSATION_ONCE(sRCLauncherData, vInCoords, "NIG1AAU", "NIG1A_AMB", 0, "NIGEL", 1, "MRSTHORNHILL", convState) // Handle ambient lead in dialogue for Nigel 2 ELIF sRCLauncherData.eMissionID = RC_NIGEL_2 PLAY_LAUNCHER_AMBIENT_DIALOGUE(sRCLauncherData, vInCoords, "NIG2AUD", "NIG2_AMB", 4, "NIGEL", DEFAULT, 14) // Handle special case car boot thumps and pre-launch dialogue in Nigel 3 ELIF sRCLauncherData.eMissionID = RC_NIGEL_3 BOOT_THUMP_CYCLE(bevNigel3, sRCLauncherData.vehID[0], srcLauncherData.pedID[1]) PLAY_LAUNCHER_AMBIENT_DIALOGUE(sRCLauncherData, << -44.75, -1289.86, 29.16 >>, "NIGE3AU", "NIGEL3_AMB", 4, "NIGEL", 8000) ENDIF // Determine whether player is close enough to launch mission - Nigel 1D checks a poly // Probably need to improve this somewhat BOOL bLaunchMission = FALSE IF sRCLauncherData.eMissionID = RC_NIGEL_1D IF ARE_RC_TRIGGER_POLY_CONDITIONS_MET(sRCLauncherData, pMissionTrigger) OR HAS_PLAYER_DAMAGED_ANY_N1D_PEDS(sRCLauncherData) bLaunchMission = TRUE ENDIF ELSE IF ARE_RC_TRIGGER_CONDITIONS_MET(sRCLauncherData) bLaunchMission = TRUE ENDIF ENDIF // Is the player close enough to start the mission off IF bLaunchMission //B* 2157539: Activate the multihead blinders instantly IF sRCLauncherData.eMissionID = RC_NIGEL_2 SET_MULTIHEAD_SAFE(TRUE) // Wait(500) ENDIF // Create mission blip that persists for lead-in scene // Original will be removed when RC controller shuts down IF DOES_RC_MISSION_HAVE_LEAD_IN(sRCLauncherData.eMissionID) CREATE_BLIP_FOR_LEAD_IN(sRCLauncherData.eMissionID, biLeadIn) ENDIF //Launch the mission script IF NOT LAUNCH_RC_MISSION(sRCLauncherData) Script_Cleanup(sRCLauncherData, bevNigel3) ENDIF //Waits in a loop until we can terminate the launcher - flagged from mission at the moment IF IS_RC_LAUNCHER_SAFE_TO_TERMINATE(sRCLauncherData.eMissionID) Script_Cleanup(sRCLauncherData, bevNigel3, FALSE) //No need to clean up entities, as we should have passed them over to the mission script ENDIF ENDIF ENDWHILE // Script should never reach here. Always terminate with cleanup function. ENDSCRIPT