//Compile out Title Update changes to header functions. //Must be before includes. //CONST_INT USE_TU_CHANGES 0 // Removed by Kenneth R. USING "cutscene_public.sch" USING "RC_launcher_public.sch" USING "RC_Setup_public.sch" USING "initial_scenes_Barry.sch" // ***************************************************************************************** // SCRIPT NAME : launcher_Barry.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---------------------- // Constants 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. INT iVehicleSnapshotLastStored = 0 // Game timer value when the vehicle snapshot was last stored SCENARIO_BLOCKING_INDEX mScenarioBlocker BLIP_INDEX biLeadIn // Blip for lead-in sequence STRUCT AMB_ANIMBLOCK STRING sTalkAnim[5] INT iMaxAnims = 0 INT iLastAnim = -1 ENDSTRUCT ENUM CONV_STATE CONV_WAITING, CONV_DOLINE, CONV_SPEAKING ENDENUM AMB_ANIMBLOCK ambDiagAnimBlock CONV_STATE Barry3ConvState = CONV_WAITING structPedsForConversation convStruct INT iConvTimer /// PURPOSE: /// Unfreeze Barry and objects for Barry 1 and 2 PROC UNFREEZE_ENTITIES_IN_BARRY_1_AND_2(g_structRCScriptArgs& sData) IF (sData.eMissionID = RC_BARRY_1) OR (sData.eMissionID = RC_BARRY_2) CPRINTLN(DEBUG_AMBIENT, "LAUNCHER_BARRY - Unfreezing entities!") // Objects INT i FOR i = 0 TO RC_MAX_SCENE_OBJS - 1 IF IS_ENTITY_ALIVE(sData.objID[i]) FREEZE_ENTITY_POSITION(sData.objID[i], FALSE) ENDIF ENDFOR // Barry IF IS_ENTITY_ALIVE(sData.pedID[0]) FREEZE_ENTITY_POSITION(sData.pedID[0], FALSE) SET_PED_TO_RAGDOLL(sData.pedID[0], 100, 500, TASK_RELAX) TASK_SMART_FLEE_PED(sData.pedID[0], PLAYER_PED_ID(),10000,-1) ENDIF // Delete floating papers SAFE_DELETE_OBJECT(sData.objID[2]) ENDIF ENDPROC /// 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, BOOL bCleanupEntities=TRUE) IF bCleanupEntities PRINT_LAUNCHER_DEBUG("SCRIPT TERMINATING: Cleaning up entities in Launcher") // Unfreeze desk and props only if we're releasing entities anyway UNFREEZE_ENTITIES_IN_BARRY_1_AND_2(sData) RC_CleanupSceneEntities(sData, FALSE) ENDIF // Remove lead-in blip IF DOES_BLIP_EXIST(biLeadIn) REMOVE_BLIP(biLeadIn) ENDIF // 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 // Remove scenario blocking areas IF sData.eMissionID = RC_BARRY_3C REMOVE_SCENARIO_BLOCKING_AREA(mScenarioBlocker) ENDIF // Unload launcher animation dictionary REMOVE_LAUNCHER_ANIM_DICT(sData.sAnims) // Stop launcher conversation STRING sConversationRoot SWITCH sData.eMissionID CASE RC_BARRY_3 sConversationRoot = "BARRY3_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 PROC RESET_AMBIENT_DIALOG_ANIMBLOCK(AMB_ANIMBLOCK &amb) INT i REPEAT COUNT_OF(amb.sTalkAnim) i amb.sTalkAnim[i] = NULL ENDREPEAT amb.iMaxAnims = 0 amb.iLastAnim = -1 ENDPROC PROC ADD_ANIM_TO_AMBIENT_ANIMBLOCK(AMB_ANIMBLOCK &amb, STRING sAnim) IF (amb.iMaxAnims >= COUNT_OF(amb.sTalkAnim)) SCRIPT_ASSERT("INCREASE THE SIZE OF AMB_ANIMBLOCK:sTalkAnim") EXIT ENDIF amb.sTalkAnim[amb.iMaxAnims] = sAnim amb.iMaxAnims ++ ENDPROC /// PURPOSE: /// Handles playing a random set of ambient animations - plays the anim then goes into idle /// PARAMS: /// sData - Script Arg Data /// amb - The Anim Block Set /// pedNum - Index of Ped To Play the anims PROC PLAY_LAUNCHER_AMBIENT_DIALOG_ANIMS(g_structRCScriptArgs& sData, AMB_ANIMBLOCK amb, BOOL bIsSeated = FALSE, INT pedNum = 0) SEQUENCE_INDEX seq ANIMATION_FLAGS flg = AF_TAG_SYNC_OUT IF NOT IS_ENTITY_ALIVE(sData.pedID[pedNum]) EXIT ENDIF IF (bIsSeated) flg |= AF_TURN_OFF_COLLISION ENDIF amb.iLastAnim = GET_RANDOM_INT_IN_RANGE(0, amb.iMaxAnims) OPEN_SEQUENCE_TASK(seq) TASK_PLAY_ANIM(null, sData.sAnims.sDictionary, amb.sTalkAnim[amb.iLastAnim], SLOW_BLEND_IN, SLOW_BLEND_OUT, -1, AF_DEFAULT | flg) // See B*887597 - changed to slow blends TASK_PLAY_ANIM(null, sData.sAnims.sDictionary, sData.sAnims.sIdleAnim, NORMAL_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_LOOPING | flg) CLOSE_SEQUENCE_TASK(seq) TASK_PERFORM_SEQUENCE(sData.pedID[pedNum], seq) CLEAR_SEQUENCE_TASK(seq) ENDPROC // ----------Functions ------------------------- /// PURPOSE: // plays a conversation if player is near enough /// PARAMS: /// convState - the conversation state /// pedLoc - location of the ped that will be speaking /// textBlock - the text block for the conversation /// rootLabel - the root label for the conversation PROC DO_AMB_CONVERSATION(CONV_STATE &convState, VECTOR pedLoc, STRING textBlock, STRING rootLabel) SWITCH convState CASE CONV_WAITING IF (GET_GAME_TIMER() - iConvTimer) > 5000 // 5.0 sec delay between each 'call' convState = CONV_DOLINE ENDIF BREAK CASE CONV_DOLINE IF GET_DISTANCE_BETWEEN_ENTITY_AND_COORD(PLAYER_PED_ID(), pedLoc) <= 20.0 IF CREATE_CONVERSATION(convStruct, textBlock, rootLabel, CONV_PRIORITY_HIGH) convState = CONV_SPEAKING ENDIF ENDIF BREAK CASE CONV_SPEAKING // If the conversation finishes, reset to play again // If the player moves away from location, kill the convo and reset IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED() iConvTimer = GET_GAME_TIMER() convState = CONV_WAITING ELIF GET_DISTANCE_BETWEEN_ENTITY_AND_COORD(PLAYER_PED_ID(), pedLoc) >= 25.0 KILL_ANY_CONVERSATION() convState = CONV_WAITING ENDIF BREAK ENDSWITCH ENDPROC /// PURPOSE: /// Checks if this mission is a weed stash mission (barry3a-e) /// PARAMS: /// eRCMission - the mission we are checking /// RETURNS: /// TRUE if it is a weed stash mission, false otherwise FUNC BOOL Is_Weed_Stash_Mission(g_eRC_MissionIDs eRCMission) SWITCH eRCMission CASE RC_BARRY_3A CASE RC_BARRY_3C RETURN TRUE BREAK ENDSWITCH RETURN FALSE ENDFUNC /// PURPOSE: /// Creates the initial scene /// PARAMS: /// sData - launcher data struct FUNC BOOL LOAD_INITIAL_SCENE(g_structRCScriptArgs& sData) //Setup the correct initial scene SWITCH sData.eMissionID CASE RC_BARRY_1 IF NOT SetupScene_BARRY_1(sData) RETURN FALSE ENDIF BREAK CASE RC_BARRY_2 IF NOT SetupScene_BARRY_2(sData) RETURN FALSE ENDIF BREAK CASE RC_BARRY_3 IF NOT SetupScene_BARRY_3(sData) RETURN FALSE ENDIF BREAK CASE RC_BARRY_3A IF NOT SetupScene_BARRY_3A(sData) RETURN FALSE ENDIF BREAK CASE RC_BARRY_3C IF NOT SetupScene_BARRY_3C(sData) RETURN FALSE ENDIF BREAK CASE RC_BARRY_4 IF NOT SetupScene_BARRY_4(sData) RETURN FALSE ENDIF BREAK ENDSWITCH // Specific setup for Barry 1 IF sData.eMissionID = RC_BARRY_1 RESET_AMBIENT_DIALOG_ANIMBLOCK(ambDiagAnimBlock) ADD_ANIM_TO_AMBIENT_ANIMBLOCK(ambDiagAnimBlock, "democ_only_works") ADD_ANIM_TO_AMBIENT_ANIMBLOCK(ambDiagAnimBlock, "gift_from_god") ADD_ANIM_TO_AMBIENT_ANIMBLOCK(ambDiagAnimBlock, "rigged_vote") ADD_ANIM_TO_AMBIENT_ANIMBLOCK(ambDiagAnimBlock, "suck_my") ADD_ANIM_TO_AMBIENT_ANIMBLOCK(ambDiagAnimBlock, "tyranny") ENDIF // Scene creation successful PRINT_LAUNCHER_DEBUG("Created initial scene") RETURN TRUE ENDFUNC /// PURPOSE: /// Ensure Barry dies for a nearby explosion, and unfreeze objects (not always happening?) PROC HANDLE_BARRY_1_AND_2_EXPLOSIONS(g_structRCScriptArgs& sData) IF IS_ENTITY_ALIVE(sData.pedID[0]) SET_PED_RESET_FLAG(sData.pedID[0], PRF_BlockWeaponReactionsUnlessDead, TRUE) SET_PED_RESET_FLAG(sData.pedID[0], PRF_DisablePotentialBlastReactions, TRUE) IF IS_EXPLOSION_IN_SPHERE(EXP_TAG_DONTCARE, GET_ENTITY_COORDS(sData.pedID[0]), 5.1) CPRINTLN(DEBUG_AMBIENT, "LAUNCHER_BARRY - Explosion detected!") UNFREEZE_ENTITIES_IN_BARRY_1_AND_2(sData) IF IS_ENTITY_ALIVE(sData.pedID[0]) APPLY_DAMAGE_TO_PED(sData.pedID[0], 1000, TRUE) ENDIF ENDIF ENDIF ENDPROC /// PURPOSE: /// Diable player control in volume around the trigger volume PROC HANDLE_BARRY_1_AND_2_PRE_LEAD_IN() VECTOR vBarryPos = << 190.2424, -956.4790, 29.08 >> FLOAT fRadius = 12.00 IF IS_ENTITY_ALIVE(PLAYER_PED_ID()) IF IS_ENTITY_IN_RANGE_COORDS(PLAYER_PED_ID(), vBarryPos, fRadius) RC_DISABLE_CONTROL_ACTIONS_FOR_LEAD_IN() ENDIF ENDIF ENDPROC /// PURPOSE: /// Determines which RC we are trying to launch. Also waits for gameflow to finish configuring. /// Need custom version of this function as both Barry 1 and 2 exist at the same world point /// and can be triggered at the same time /// PARAMS: /// 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_CUSTOM(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 // Determine which RC mission we are attempting to launch // Check Barry 1 IF GET_CURRENT_PLAYER_PED_ENUM() = CHAR_MICHAEL IF IS_RC_IN_RANGE_AND_WAITING(RC_BARRY_1, vInCoords, fTolerance, eRCInfo) CPRINTLN(DEBUG_RANDOM_CHAR, GET_THIS_SCRIPT_NAME(),": DetermineRCToLaunchCustom - Found mission ", eRCInfo.sScriptName) RETURN TRUE ENDIF // Check Barry 2 ELIF GET_CURRENT_PLAYER_PED_ENUM() = CHAR_TREVOR IF IS_RC_IN_RANGE_AND_WAITING(RC_BARRY_2, vInCoords, fTolerance, eRCInfo) CPRINTLN(DEBUG_RANDOM_CHAR, GET_THIS_SCRIPT_NAME(),": DetermineRCToLaunchCustom - Found mission ", eRCInfo.sScriptName) RETURN TRUE ENDIF ENDIF // Check remaining missions in Barry strand g_eRC_MissionIDs eRCMissions[4] eRCMissions[0] = RC_BARRY_3 eRCMissions[1] = RC_BARRY_3A eRCMissions[2] = RC_BARRY_3C eRCMissions[3] = RC_BARRY_4 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, GET_THIS_SCRIPT_NAME(),": DetermineRCToLaunchCustom - Found mission ", eRCInfo.sScriptName) iMission = COUNT_OF(eRCMissions) RETURN TRUE ENDIF iMission++ ENDWHILE // Failed to find an RC to launch CPRINTLN(DEBUG_RANDOM_CHAR, GET_THIS_SCRIPT_NAME(),": DetermineRCToLaunchCustom - Unable to find mission to launch [TERMINATING]") CPRINTLN(DEBUG_RANDOM_CHAR, GET_THIS_SCRIPT_NAME(),": Original Position = ", vInCoords) RETURN FALSE 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 //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] // 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) ENDIF // Pick which mission activated us IF NOT DETERMINE_RC_TO_LAUNCH_CUSTOM(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 // Halt launcher as 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 so set up the initial scene WHILE NOT LOAD_INITIAL_SCENE(sRCLauncherData) WAIT(0) IF NOT IS_WORLD_POINT_WITHIN_BRAIN_ACTIVATION_RANGE() PRINT_LAUNCHER_DEBUG("Player out of range [TERMINATING]") Script_Cleanup(sRCLauncherData) ENDIF ENDWHILE // Add scenario blocking area if required IF sRCLauncherData.eMissionID = RC_BARRY_3C mScenarioBlocker = Barry3C_Scenario_Blocker() ENDIF // Clears area of non-mission entities and blood decals CLEAR_AREA(vInCoords, sRCLauncherData.activationRange, TRUE) IF sRCLauncherData.eMissionID = RC_BARRY_3 ADD_PED_FOR_DIALOGUE(ConvStruct, 3, sRCLauncherData.pedID[0], "BARRY") iConvTimer = GET_GAME_TIMER() ENDIF // Loop to check conditions - should script terminate? or is player close enough to trigger mission? WHILE (TRUE) WAIT(0) IF (sRCLauncherData.eMissionID = RC_BARRY_1) OR (sRCLauncherData.eMissionID = RC_BARRY_2) HANDLE_BARRY_1_AND_2_EXPLOSIONS(sRCLauncherData) HANDLE_BARRY_1_AND_2_PRE_LEAD_IN() IF CAN_REQUEST_ASSETS_FOR_CUTSCENE_ENTITY() SET_CUTSCENE_PED_PROP_VARIATION("Barry", ANCHOR_EYES, 0) ENDIF ELIF (sRCLauncherData.eMissionID = RC_BARRY_3) IF CAN_REQUEST_ASSETS_FOR_CUTSCENE_ENTITY() SET_CUTSCENE_PED_PROP_VARIATION("BARRY", ANCHOR_EYES, 0) ENDIF ENDIF // Is the player still in activation range IF NOT IS_RC_FINE_AND_IN_RANGE(sRCLauncherData, (sRCLauncherData.eMissionID <> RC_BARRY_1)) Script_Cleanup(sRCLauncherData) ENDIF // Update launcher blip + preload intro SET_RC_AWAITING_TRIGGER(sRCLauncherData.eMissionID) MANAGE_PRELOADING_RC_CUTSCENE(iCutsceneLoadRequestID, sRCLauncherData.sIntroCutscene, vInCoords) IF IS_ENTITY_ALIVE(sRCLauncherData.pedID[0]) IF (sRCLauncherData.eMissionID = RC_BARRY_1) IF PLAY_LAUNCHER_AMBIENT_DIALOGUE(sRCLauncherData, GET_ENTITY_COORDS(sRCLauncherData.pedID[0]), "BARY1AU", "BARY1_PRELEA", 5, "BARRY", 10000, 23.0) PLAY_LAUNCHER_AMBIENT_DIALOG_ANIMS(sRCLauncherData, ambDiagAnimBlock, TRUE) ENDIF ELIF (sRCLauncherData.eMissionID = RC_BARRY_2) IF PLAY_LAUNCHER_AMBIENT_DIALOGUE(sRCLauncherData, GET_ENTITY_COORDS(sRCLauncherData.pedID[0]), "BARY2AU", "BARY2_AMB", 3, "BARRY", 10000, 23.0) //PLAY_LAUNCHER_AMBIENT_DIALOG_ANIMS(sRCLauncherData, ambDiagAnimBlock, TRUE) ENDIF ELIF (sRCLauncherData.eMissionID = RC_BARRY_3) DO_AMB_CONVERSATION(Barry3ConvState, GET_ENTITY_COORDS(sRCLauncherData.pedID[0]), "BARR3AU", "BARRY3_AMB") ENDIF ENDIF // Check to see whether we need to reset help prompt // and check if we should update the vehicle snapshot (only for Barry3A-3C) BOOL bStoreVehicleSnapshot = FALSE IF Is_Weed_Stash_Mission(sRCLauncherData.eMissionID) IF GET_GAME_TIMER() - iVehicleSnapshotLastStored > 5000 bStoreVehicleSnapshot = TRUE iVehicleSnapshotLastStored = GET_GAME_TIMER() ENDIF ENDIF //Is the player close enough to start the mission off IF ARE_RC_TRIGGER_CONDITIONS_MET(sRCLauncherData, bStoreVehicleSnapshot) // 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) 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) // No need to clean up entities, as we should have passed them over to the mission script Script_Cleanup(sRCLauncherData, FALSE) ENDIF ENDIF ENDWHILE // Script should never reach here. Always terminate with cleanup function. ENDSCRIPT