//Compile out Title Update changes to header functions. //Must be before includes. //CONST_INT USE_TU_CHANGES 0 // Removed by Kenneth R. USING "rage_builtins.sch" USING "globals.sch" USING "cutscene_public.sch" USING "commands_cutscene.sch" USING "commands_entity.sch" USING "commands_script.sch" USING "script_player.sch" USING "randomChar_public.sch" USING "dialogue_public.sch" USING "script_player.sch" USING "shared_hud_displays.sch" USING "CompletionPercentage_public.sch" USING "randomChar_public.sch" USING "RC_Helper_Functions.sch" USING "RC_Threat_public.sch" USING "RC_Area_public.sch" USING "initial_scenes_epsilon.sch" USING "commands_recording.sch" #IF IS_DEBUG_BUILD USING "select_mission_stage.sch" #ENDIF // ***************************************************************************************** // ***************************************************************************************** // ***************************************************************************************** // // MISSION NAME : Epsilon4.sc // AUTHOR : Sam Hackett (originally)/Ian Gander (July '12 onwards) // DESCRIPTION : Track down a "space" rock using a detector // // ***************************************************************************************** // ***************************************************************************************** // ***************************************************************************************** //******************************************************************************************************************* //******************************************************************************************************************* RC VARIABLES // Scene entities from mission launcher g_structRCScriptArgs sRCLauncherDataLocal CONST_INT ID_MARNIE 0 CONST_INT ID_JIMMY 1 //******************************************************************************************************************* //******************************************************************************************************************* POSITIONS VECTOR vPos_WoodsCentre = << 1813.2936, 4698.7852, 38.9553 >>//<< 1812.0585, 4697.6284, 39.0981 >> VECTOR vPos_PlayerReset = << 1827.1781, 4698.1138, 38.1653 >> FLOAT fRot_PlayerReset = 187.4554 VECTOR vPos_Epsilonian1 = << 1811.9602, 4697.0708, 39.1076 >> FLOAT fRot_Epsilonian1 = 330.5137 VECTOR vPos_Epsilonian2 = << 1814.0197, 4697.0508, 38.9678 >> FLOAT fRot_Epsilonian2 = 24.0044 //VECTOR vPos_PlayerFinalScene = << 1860.4711, 4657.4482, 36.3283 >> //FLOAT fRot_PlayerFinalScene = 177.3919 CONST_FLOAT fFindRange 6.2 //4.0//2.5 CONST_FLOAT fNearRange 9.0 //6.0//5.0//30.0//5.0//11.0//10.0//5.5 CONST_FLOAT fCloseDialogRange 20.0 CONST_FLOAT CAPSULE_SIZE 0.965 CONST_INT MAX_JGOOD_LINES 8 CONST_INT MAX_JBAD_LINES 8 CONST_INT MAX_MGOOD_LINES 8 CONST_INT MAX_MBAD_LINES 8 CONST_INT MAX_PGOOD_LINES 11 CONST_INT MAX_PBAD_LINES 12 WEAPON_TYPE weapon_Detector = WEAPONTYPE_DIGISCANNER MODEL_NAMES model_Detector = GET_WEAPONTYPE_MODEL(weapon_Detector) //STRING NO_RECENT_ANIM = "noAnim" STRING EMPTY_STRING = "empty" //1812.13, 4636.73, 37.78 //******************************************************************************************************************* //******************************************************************************************************************* DATATYPES //-- Rock STRUCT ROCK_DATA MODEL_NAMES model OBJECT_INDEX hObject VECTOR vPos VECTOR vRot VECTOR vCamPos VECTOR vCamRot FLOAT fCamFov VECTOR vEpsPos // FLOAT fEpsRot FLOAT fMeanderFactor0 FLOAT fMeanderFactor1 FLOAT fMeanderAmplitude FLOAT fStraightZone FLOAT fHotAngle FLOAT fMeterRange FLOAT fPostSceneRot VECTOR vAngledArea1 VECTOR vAngledArea2 FLOAT fAngledAreaWidth VECTOR vWarpCarPos FLOAT fWarpCarRot STRING sChat1Dialogue STRING sChat2Dialogue STRING sReturn1Dialogue STRING sReturn2Dialogue STRING sHintGoodDialogue STRING sHintBadDialogue STRING SHintCloseDialogue ENDSTRUCT STRUCT DETECTOR ENTITY_INDEX hObj BOOL bIsOnTarget INT hSndHum INT hSndBeep INT hSndFound INT hSndScan BOOL bIsFoundSoundOn BOOL bIsScanSoundOn FLOAT fMeanderFactor0 FLOAT fMeanderFactor1 FLOAT fMeanderAmplitude FLOAT fStraightZone FLOAT fHotAngle BOOL bLockSettings STRING sRecentAnim ENDSTRUCT //-- Anim markers ENUM ANIM_MARKER_TYPE ANIM_MARKER_FORAGE, ANIM_MARKER_DUMMY_JIMMY, ANIM_MARKER_DUMMY_PISS, ANIM_MARKER_DUMMY_DANCE ENDENUM STRUCT ANIM_MARKER VECTOR vPos FLOAT fRot ANIM_MARKER_TYPE type BOOL bIsInUse ENDSTRUCT //-- Eps characters ENUM EPS_STATE EPS_ST_NULL = 0, EPS_ST_MOVE, EPS_ST_MARKER, EPS_ST_IDLE, EPS_ST_FOLLOW, EPS_ST_CATCHUP ENDENUM ENUM STATE_MODE SETUP_STATE, UPDATE_STATE ENDENUM STRUCT EPS_DATA PED_INDEX hPed EPS_STATE state STATE_MODE mode INT iAnimMarker VECTOR vPlayerStartPos BOOL bNotUsingNavmeshMove = FALSE ENDSTRUCT //******************************************************************************************************************* //******************************************************************************************************************* VARIABLES SCENARIO_BLOCKING_INDEX mScenarioBlocker SCENARIO_BLOCKING_INDEX mScenarioBlockerPicnic BLIP_INDEX g_hBlip SCALEFORM_INDEX si_DetectorScaleform INT rt_ID SEQUENCE_INDEX seq structPedsForConversation pedsForConversation BOOL bDonePushIn = FALSE BOOL bLeadInPlayed = FALSE BOOL bLeadInConvo = FALSE BOOL bIsPlayerOnTarget = FALSE BOOL bIsPlayerAtRock = FALSE BOOL bHasPlayerFoundRock = FALSE BOOL bIsPlayerInWoods = TRUE BOOL bAudDoneChat1 = FALSE BOOL bAudDoneChat2 = FALSE BOOL bAudDoneChatAll = FALSE BOOL bAudDoneClose = FALSE BOOL bAudDoneReturn1 = FALSE BOOL bAudDoneReturn2 = FALSE BOOL bObjDoneHunt = FALSE BOOL bObjDoneExamine = FALSE BOOL bObjDoneReturnWoods = FALSE //BOOL bPlayerSkippedScene = FALSE //BOOL bCapsuleResized = FALSE BOOL bPlayerUsedAim = FALSE BOOL bFollowerDoingIdle = FALSE BOOL bLockAimPitch = FALSE BOOL bStillOnTarget = FALSE INT iCurrentRock = 0 INT iPhaseTimer = 0 INT iBeepOffTimer = 0 INT iSupressHintAudioTimer = 0 INT iSupressPickupAudioTimer = 0 INT iHintTimer INT iFoundWaitTimer GRASS_CULL_SPHERE_HANDLE grassCull CONST_FLOAT DIALOGUE_DIST 30.0 PED_INDEX hPrimaryBuddy VEHICLE_INDEX Eps_Vehicle CONST_INT ROCK_MAX 4 ROCK_DATA rockArray[ROCK_MAX] INT iRockCount = 0 INT iMidtroDelay CONST_INT ANIM_MARKER_MAX 11 ANIM_MARKER animMarkerArray[ANIM_MARKER_MAX] INT iAnimMarkerCount = 0 CONST_INT EPSILONIAN_MAX 2 EPS_DATA epsilonianArray[EPSILONIAN_MAX] BOOL epsKnockedOver = FALSE PED_INDEX epsPedKnockedOver DETECTOR gDetector FLOAT fReading CONST_INT LVL3_DISTANCE 80 CONST_INT LVL2_DISTANCE 50 OBJECT_INDEX DetectorCopy TEST_POLY g_polyPlayArea TEST_POLY g_polyFailArea INT iTutorialLine = 0 INT iTutorialTimer = 0 INT iCurrentMaxGoodLines = 0 INT iCurrentMaxBadLines = 0 INT iSaidGoodLines = 0 INT iSaidBadLines = 0 INT iSaidOnTargetLines = 0 INT iNonFollowerCloseLines = 0 INT iNonFollowerCloseLines1 = 0 // Used when both characters are wandering around during the third object and I need to keep track of two sets of lines... INT iNonFollowerCloseLinesTimer = 0 //INT g_hMarker_MarnieInitial //INT g_hMarker_JimmyInitial //INT g_hDummyMarker_Jimmy INT iFollowIdleTimer INT iFollowMessingAroundTimer INT iAimPromptLines = 0 INT iAimPromptTimer INT g_hDummyMarker_Piss INT g_hDummyMarker_Dance INT g_hDummyMarker_MarnieIntroForage INT g_hMarker_MarnieAngry INT iNavBlockerBush1 = -1 INT iNavBlockerBush2 = -1 INT iNavBlockerBush3 = -1 FLOAT fHintFov = 30.0 FLOAT fHintFollow = 0.35 FLOAT fHintPitchOrbit = 0.000 FLOAT fHintSide = 0.02 FLOAT fHintVert = -0.050 //******************************************************************************************************************* //******************************************************************************************************************* WIDGETS #IF IS_DEBUG_BUILD USING "shared_debug.sch" WIDGET_GROUP_ID widgetGroup BOOL g_DEBUG_DisplayInfo = FALSE BOOL bDebug_PrintToTTY = TRUE BOOL bDebug_VerboseDetector = FALSE PROC SETUP_EPS4_WIDGETS() widgetGroup = START_WIDGET_GROUP("Epsilon 4 widgets") ADD_WIDGET_FLOAT_SLIDER("Meander factor", gDetector.fMeanderFactor0, 0.0, 500.0, 1.0) ADD_WIDGET_FLOAT_SLIDER("Meander factor", gDetector.fMeanderFactor1, 0.0, 500.0, 1.0) ADD_WIDGET_FLOAT_SLIDER("Meander amplitude", gDetector.fMeanderAmplitude, -100.0, 100.0, 1.0) ADD_WIDGET_FLOAT_SLIDER("Striaght zone", gDetector.fStraightZone, 0.0, 100.0, 1.0) ADD_WIDGET_FLOAT_SLIDER("Hot angle", gDetector.fHotAngle, 0.0, 1.0, 1.0) ADD_WIDGET_BOOL("Show info", g_DEBUG_DisplayInfo) ADD_WIDGET_BOOL("Lock detector meander settings", gDetector.bLockSettings) ADD_WIDGET_BOOL("TTY Toggle - Print Mission Debug Info", bDebug_PrintToTTY) ADD_WIDGET_BOOL("Verbose detector debug output (requires TTY Toggle to be on)", bDebug_VerboseDetector) STOP_WIDGET_GROUP() ENDPROC PROC CLEANUP_EPS4_WIDGETS() IF DOES_WIDGET_GROUP_EXIST(widgetGroup) DELETE_WIDGET_GROUP(widgetGroup) ENDIF ENDPROC #ENDIF // =========================================================================================================== // Debug prints // =========================================================================================================== /// PURPOSE: Print a string to the console PROC DEBUG_PRINTSTRING(STRING s) #IF IS_DEBUG_BUILD IF bDebug_PrintToTTY CPRINTLN(DEBUG_MISSION, s) ENDIF #ENDIF // Stop release compile error s = s ENDPROC /// PURPOSE: Print a string with a float to the console PROC DEBUG_PRINTSF(STRING s, FLOAT f) #IF IS_DEBUG_BUILD IF bDebug_PrintToTTY CPRINTLN(DEBUG_MISSION, s, f) ENDIF #ENDIF // Stop release compile error s = s f = f ENDPROC /// PURPOSE: Print a string with an int to the console PROC DEBUG_PRINTSI(STRING s, INT i) #IF IS_DEBUG_BUILD IF bDebug_PrintToTTY CPRINTLN(DEBUG_MISSION, s, i) ENDIF #ENDIF // Stop release compile error s = s i = i ENDPROC /// PURPOSE: Print a string with an int to the console PROC DEBUG_PRINTBOOL(BOOL b) #IF IS_DEBUG_BUILD IF bDebug_PrintToTTY CPRINTLN(DEBUG_MISSION, b) ENDIF #ENDIF // Stop release compile error b = b ENDPROC /// PURPOSE: Print a string with an int to the console PROC DEBUG_PRINTVECTOR(STRING s, VECTOR v) #IF IS_DEBUG_BUILD IF bDebug_PrintToTTY CPRINTLN(DEBUG_MISSION, s, v) ENDIF #ENDIF // Stop release compile error s = S v = v ENDPROC //******************************************************************************************************************* //******************************************************************************************************************* ASSET FUNCTIONS /// PURPOSE: /// Request and check whether all text we want are loaded /// RETURNS: /// True when all the text has loaded, False otherwise FUNC BOOL LOAD_TEXT() // Request REQUEST_ADDITIONAL_TEXT("EPS4", MISSION_TEXT_SLOT) // Check IF HAS_ADDITIONAL_TEXT_LOADED(MISSION_TEXT_SLOT) RETURN TRUE ENDIF RETURN FALSE ENDFUNC /// PURPOSE: /// Request and check whether all models we want are loaded /// RETURNS: /// True when all models are loaded, False otherwise FUNC BOOL LOAD_MODELS() // Request INT i REPEAT iRockCount i REQUEST_MODEL(rockArray[i].model) ENDREPEAT REQUEST_MODEL(model_Detector) REQUEST_MODEL(Bison) // Check REPEAT iRockCount i IF NOT HAS_MODEL_LOADED(rockArray[i].model) RETURN FALSE ENDIF ENDREPEAT IF NOT HAS_MODEL_LOADED(model_Detector) OR NOT HAS_MODEL_LOADED(Bison) RETURN FALSE ENDIF RETURN TRUE ENDFUNC /// PURPOSE: /// Request and check for the animations being loaded /// RETURNS: /// True when all anims are loaded, False otherwise FUNC BOOL LOAD_ANIMS() // Request REQUEST_ANIM_DICT("rcm_epsilonism4") REQUEST_ANIM_DICT("rcm_epsilonism4leadinout") // Check IF HAS_ANIM_DICT_LOADED("rcm_epsilonism4") AND HAS_ANIM_DICT_LOADED("rcm_epsilonism4leadinout") RETURN TRUE ENDIF RETURN FALSE ENDFUNC /// PURPOSE: /// Request and check for all assets we wish to use for this mission /// RETURNS: /// True when all assets are loaded in, False otherwise FUNC BOOL LOAD_ASSETS() IF LOAD_TEXT() AND LOAD_MODELS() AND LOAD_ANIMS() RETURN TRUE ENDIF RETURN FALSE ENDFUNC /// PURPOSE: /// Release all requested anims PROC RELEASE_ANIMS() REMOVE_ANIM_DICT("rcm_epsilonism4") REMOVE_ANIM_DICT("rcm_epsilonism4leadinout") ENDPROC /// PURPOSE: /// Set up basic fields for the rock data /// PARAMS: /// sSceneDialogue - The dialogue string for the scripted scene /// model - The model to be used for the 'rock' /// vPos - The coords of the rock /// vRot - The rotation of the rock PROC ADD_ROCK(MODEL_NAMES model, VECTOR vPos, VECTOR vRot) IF iRockCount >= ROCK_MAX SCRIPT_ASSERT("ADD_ROCK: Rock array full\n") ENDIF INT idx = iRockCount iRockCount++ rockArray[idx].model = model rockArray[idx].vPos = vPos rockArray[idx].vRot = vRot rockArray[idx].fMeterRange = 150.0 rockArray[idx].fPostSceneRot = -1.0 rockArray[idx].sChat1Dialogue = EMPTY_STRING rockArray[idx].sChat2Dialogue = EMPTY_STRING rockArray[idx].sReturn1Dialogue = EMPTY_STRING rockArray[idx].sReturn2Dialogue = EMPTY_STRING rockArray[idx].sHintGoodDialogue = EMPTY_STRING rockArray[idx].sHintBadDialogue = EMPTY_STRING ENDPROC /// PURPOSE: /// Set up camera values for the scripted cutscene for the current rock /// PARAMS: /// vCamPos - The camera position /// vCamRot - The camera rotation /// fCamFov - The camera FOV PROC SETUP_ROCK_CAM(VECTOR vCamPos, VECTOR vCamRot, FLOAT fCamFov = 50.0) INT idx = iRockCount - 1 IF idx < 0 SCRIPT_ASSERT("SETUP_ROCK_CAM: Can't setup rock before adding one\n") ENDIF rockArray[idx].vCamPos = vCamPos rockArray[idx].vCamRot = vCamRot rockArray[idx].fCamFov = fCamFov ENDPROC /// PURPOSE: /// Set up the position the Epsilonists will walk to during the scripted cutscene /// PARAMS: /// vEpsPos - The coords the Epsilonist will walk to PROC SETUP_ROCK_EPS(VECTOR vEpsPos) INT idx = iRockCount - 1 IF idx < 0 SCRIPT_ASSERT("SETUP_ROCK_EPS: Can't setup rock before adding one\n") ENDIF rockArray[idx].vEpsPos = vEpsPos ENDPROC /// PURPOSE: /// Set up the meander values for the detector /// PARAMS: /// fMeanderFactor0 - Meander factor value 1 /// fMeanderFactor1 - Meander factor value 2 /// fMeanderAmplitude - Meander factor amplitude PROC SETUP_ROCK_MEANDER_PATH(FLOAT fMeanderFactor0, FLOAT fMeanderFactor1, FLOAT fMeanderAmplitude) INT idx = iRockCount - 1 IF idx < 0 SCRIPT_ASSERT("SETUP_ROCK_MEANDER_PATH: Can't setup rock before adding one\n") ENDIF rockArray[idx].fMeanderFactor0 = fMeanderFactor0 rockArray[idx].fMeanderFactor1 = fMeanderFactor1 rockArray[idx].fMeanderAmplitude = fMeanderAmplitude ENDPROC /// PURPOSE: /// Set up various detector params for the given rock /// PARAMS: /// fStraightZone - The straight zone value /// fMeterRange - The meter range value /// fHotAngle - The hot angle for the detector PROC SETUP_ROCK_DETECTION_PARAMS(FLOAT fStraightZone, FLOAT fMeterRange, FLOAT fHotAngle) INT idx = iRockCount - 1 IF idx < 0 SCRIPT_ASSERT("SETUP_ROCK_DETECTION_PARAMS: Can't setup rock before adding one\n") ENDIF rockArray[idx].fStraightZone = fStraightZone rockArray[idx].fMeterRange = fMeterRange rockArray[idx].fHotAngle = fHotAngle ENDPROC /// PURPOSE: /// Sets the range for the meter /// PARAMS: /// fMeterRange - The range we wish to set PROC SETUP_ROCK_METER_RANGE(FLOAT fMeterRange) INT idx = iRockCount - 1 IF idx < 0 SCRIPT_ASSERT("SETUP_ROCK_METER_RANGE: Can't setup rock before adding one\n") ENDIF rockArray[idx].fMeterRange = fMeterRange ENDPROC /// PURPOSE: /// Set up the rotation to be used after the scripted rock cutscene /// PARAMS: /// fRot - The rotation we wish to set PROC SETUP_ROCK_POST_SCENE_ROT(FLOAT fRot) INT idx = iRockCount - 1 IF idx < 0 SCRIPT_ASSERT("SETUP_ROCK_POST_SCENE_ROT: Can't setup rock before adding one\n") ENDIF rockArray[idx].fPostSceneRot = fRot ENDPROC PROC SETUP_ROCK_AREA(VECTOR vAngledArea1, VECTOR vAngledArea2, FLOAT fAreaWidth) INT idx = iRockCount - 1 IF idx < 0 SCRIPT_ASSERT("SETUP_ROCK_AREA: Can't setup rock before adding one\n") ENDIF rockArray[idx].vAngledArea1 = vAngledArea1 rockArray[idx].vAngledArea1 = vAngledArea2 rockArray[idx].fAngledAreaWidth = fAreaWidth ENDPROC /// PURPOSE: /// Sets up the location for a car in case needed for the cutscene mode switch /// PARAMS: /// vPos - The pos of the theoretical car /// fRot - The heading of the theoretical car PROC SETUP_ROCK_WARP_CAR(VECTOR vPos, FLOAT fRot) INT idx = iRockCount - 1 IF idx < 0 SCRIPT_ASSERT("SETUP_ROCK_WARP_CAR: Can't setup rock before adding one\n") ENDIF rockArray[idx].vWarpCarPos = vPos rockArray[idx].fWarpCarRot = fRot ENDPROC /// PURPOSE: /// Adds dialogue for misc chat while trying to find a certain rock /// PARAMS: /// sChat1 - First dialogue branch /// sChat2 - Second dialogue branch PROC SETUP_ROCK_CHAT_DIALOGUE(STRING sChat1, STRING sChat2) INT idx = iRockCount - 1 IF idx < 0 SCRIPT_ASSERT("SETUP_ROCK_CHAT_DIALOGUE: Can't setup rock before adding one\n") ENDIF rockArray[idx].sChat1Dialogue = sChat1 rockArray[idx].sChat2Dialogue = sChat2 ENDPROC /// PURPOSE: /// Adds dialogue for coming back to the rock path /// PARAMS: /// sReturn1 - First dialogue branch /// sReturn2 - Second dialogue branch PROC SETUP_ROCK_RETURN_DIALOGUE(STRING sReturn1, STRING sReturn2) INT idx = iRockCount - 1 IF idx < 0 SCRIPT_ASSERT("SETUP_ROCK_RETURN_DIALOGUE: Can't setup rock before adding one\n") ENDIF rockArray[idx].sReturn1Dialogue = sReturn1 rockArray[idx].sReturn2Dialogue = sReturn2 ENDPROC /// PURPOSE: /// Adds hint dialogue for current rock being set up /// PARAMS: /// sGood - The dialogue string for being on track /// sBad - The dialogue string for being off the track PROC SETUP_ROCK_HINT_DIALOGUE(STRING sGood, STRING sBad) INT idx = iRockCount - 1 IF idx < 0 SCRIPT_ASSERT("SETUP_ROCK_HINT_DIALOGUE: Can't setup rock before adding one\n") ENDIF rockArray[idx].sHintGoodDialogue = sGood rockArray[idx].sHintBadDialogue = sBad ENDPROC /// PURPOSE: /// Adds 'player is close' dialogue for current rock being set up /// PARAMS: /// sClose - The dialogue string for being close PROC SETUP_ROCK_CLOSE_DIALOGUE(STRING sClose) INT idx = iRockCount - 1 IF idx < 0 SCRIPT_ASSERT("SETUP_ROCK_CLOSE_DIALOGUE: Can't setup rock before adding one\n") ENDIF rockArray[idx].SHintCloseDialogue = sClose ENDPROC /// PURPOSE: /// Add an animation marker for the Epsilonists to use /// PARAMS: /// vPos - The coords of the marker /// fRot - The heading for the marker (for alignment) /// type - What type of marker it is, to set the correct anims /// RETURNS: /// The int index number of the new marker FUNC INT ADD_ANIM_MARKER(VECTOR vPos, FLOAT fRot, ANIM_MARKER_TYPE type) IF iAnimMarkerCount >= ANIM_MARKER_MAX SCRIPT_ASSERT("ADD_ANIM_MARKER: Marker array full\n") ENDIF INT idx = iAnimMarkerCount iAnimMarkerCount++ animMarkerArray[idx].vPos = vPos animMarkerArray[idx].fRot = fRot animMarkerArray[idx].type = type animMarkerArray[idx].bIsInUse = FALSE RETURN idx ENDFUNC /// PURPOSE: /// Initialise the data for the rocks and cameras the mission will use PROC INIT_DATA() // TV set ADD_ROCK(PROP_TV_TEST, << 1751.65, 4676.77, 43.03 >>, <<-2.33, 0.99, 91.36>>)//<< 1834.2987, 4760.5972, 37.9177 >>, 344.5698) SETUP_ROCK_CAM(<< 1755.4631, 4678.6196, 44.1477 >>, << -9.5251, -0.0000, 122.2955 >>, 50.8320) SETUP_ROCK_EPS(<<3,-4.5,0>>) SETUP_ROCK_WARP_CAR(<< 1689.9510, 4762.6133, 40.9216 >>, 272.5499) SETUP_ROCK_AREA(<<1779.514038,4691.447266,39.345768>>, <<1744.224976,4674.646484,46.848289>>, 16.5) SETUP_ROCK_CHAT_DIALOGUE("EPS4_JCHAT1", EMPTY_STRING)//"EPS4_JCHAT2") SETUP_ROCK_HINT_DIALOGUE("EPS4_JGOOD", "EPS4_JBAD") SETUP_ROCK_RETURN_DIALOGUE("EPS4_JRET1", "EPS4_JRET2") SETUP_ROCK_CLOSE_DIALOGUE("EPS4_JCLOSE") //SETUP_ROCK_MEANDER_PATH(113.0, 0.0, 47.0) // Meander settings SETUP_ROCK_MEANDER_PATH(0, 0, 0) SETUP_ROCK_DETECTION_PARAMS(30.0, 115.0, 0.9) // Old car battery ADD_ROCK(PROP_BATTERY_01, << 1756.68, 4832.28, 39.43 >>, <<90.00, 13.21, 78.57>>)//<< 1773.8232, 4792.0288, 38.8912 >>, 127.1792)//178.0357) SETUP_ROCK_CAM(<< 1758.0319, 4826.5605, 41.4590 >>, << -11.6785, -0.0000, 6.5381 >>, 34.3083)//<< 1773.5450, 4796.3384, 40.3945 >>, << -5.3621, -0.0000, -174.0904 >>, 34.3083)//<< 1773.4720, 4796.6479, 40.0057 >>, << -6.5347, 0.0000, -173.2800 >>, 45.0000)//<< 1770.4829, 4792.7202, 40.0238 >>, << -5.4930, 0.0000, -103.2162 >>, 50.8700)//<< 1755.5587, 4787.6787, 41.4211 >>, << -6.6573, 0.0000, -103.4049 >>, 30.2965) SETUP_ROCK_EPS(<<2,4,0>>) SETUP_ROCK_WARP_CAR(<< 1690.2666, 4769.9937, 40.9216 >>, 269.3043) SETUP_ROCK_AREA(<<1750.065308,4833.117188,36.870258>>, <<1763.223755,4831.822266,43.542503>>, 13.75) SETUP_ROCK_CHAT_DIALOGUE("EPS4_MCHAT1", "EPS4_MCHAT2") SETUP_ROCK_HINT_DIALOGUE("EPS4_MGOOD", "EPS4_MBAD") SETUP_ROCK_RETURN_DIALOGUE("EPS4_MRET1", "EPS4_MRET2") SETUP_ROCK_CLOSE_DIALOGUE("EPS4_MCLOSE") //SETUP_ROCK_MEANDER_PATH(307.5, 77.5, 24.0) SETUP_ROCK_MEANDER_PATH(0, 0, 0) SETUP_ROCK_DETECTION_PARAMS(30.0, 195.0, 0.9) // Old boot ADD_ROCK(PROP_OLD_BOOT, << 1847.8630, 4756.0591, 36.71 >>, <<-70.53, 75.48, 132.44>>)//<< 1874.7458, 4722.8452, 37.3642 >>, 76.8130)//<< 1869.2849, 4654.1274, 36.5388 >>, 304.6996)//<< 1876.32, 4725.66, 37.73 >>, -34.33) SETUP_ROCK_CAM(<< 1829.3098, 4756.1582, 42.4876 >>, << -23.5614, -0.0000, -92.2873 >>, 50.0000)//<< 1851.8960, 4753.5889, 38.3750 >>, << -11.3477, -0.0000, 47.3156 >>, 59.2875)//<< 1841.6384, 4756.7441, 39.5189 >>, << -18.2638, -0.0000, -95.7327 >>, 59.2875) SETUP_ROCK_EPS(<<7.5, -7.5, 0>>)//<<6.5, -2.4, 0>>)//(<<5.625, -1.875, 0>>)//(<<4.5, -1.5, 0>>) SETUP_ROCK_WARP_CAR(<< 1689.7749, 4777.7695, 40.9216 >>, 267.4597) SETUP_ROCK_AREA(<<1856.217773,4755.223145,34.671692>>, <<1841.114258,4755.488770,41.434017>>, 13.75) SETUP_ROCK_CHAT_DIALOGUE("EPS4_PCHAT1", "EPS4_PCHAT2") SETUP_ROCK_HINT_DIALOGUE("EPS4_PGOOD", "EPS4_PBAD") SETUP_ROCK_RETURN_DIALOGUE(EMPTY_STRING, "EPS4_PRET2") SETUP_ROCK_CLOSE_DIALOGUE("EPS4_PCLOSE") //SETUP_ROCK_MEANDER_PATH(206.5, 58.5, 25.0) SETUP_ROCK_MEANDER_PATH(0, 0, 0) SETUP_ROCK_DETECTION_PARAMS(20.5, 155.0, 0.9) // Add Jimmy + Marnie animation markers ADD_ANIM_MARKER(<< 1820.1013, 4701.0986, 38.5450 >>, 280.7432, ANIM_MARKER_FORAGE) ADD_ANIM_MARKER(<< 1803.0437, 4700.2441, 39.3123 >>, 72.1396, ANIM_MARKER_FORAGE) // Was originally Marnie initial marker ADD_ANIM_MARKER(<< 1820.4816, 4672.5347, 35.6368 >>, 253.4126, ANIM_MARKER_FORAGE) // Was originally Jimmy initial marker ADD_ANIM_MARKER(<< 1819.8701, 4694.0303, 38.4080 >>, 231.2265, ANIM_MARKER_FORAGE) ADD_ANIM_MARKER(<< 1807.1217, 4684.4185, 38.5566 >>, 150.6129, ANIM_MARKER_FORAGE) ADD_ANIM_MARKER(<< 1791.0580, 4689.4028, 40.5128 >>, 103.4073, ANIM_MARKER_FORAGE) ADD_ANIM_MARKER(<< 1872.6261, 4718.8271, 37.2889 >>, 210.8288, ANIM_MARKER_DUMMY_JIMMY) // g_hDummyMarker_Piss = ADD_ANIM_MARKER(<< 1875.7924, 4718.6582, 37.7000 >>, 179.1472, ANIM_MARKER_DUMMY_PISS) g_hDummyMarker_Piss = ADD_ANIM_MARKER(<< 1764.0890, 4665.8794, 42.3031 >>, 281.6336, ANIM_MARKER_DUMMY_PISS) g_hDummyMarker_MarnieIntroForage = ADD_ANIM_MARKER(<< 1814.27, 4651.32, 37.58 >>, 173.1089, ANIM_MARKER_FORAGE) g_hDummyMarker_Dance = ADD_ANIM_MARKER(<< 1846.5121, 4705.6143, 38.1214 >>, 25.7591, ANIM_MARKER_DUMMY_DANCE)//<< 1877.3870, 4692.0205, 38.8601 >>, 62.9845, ANIM_MARKER_DUMMY_DANCE) g_hMarker_MarnieAngry = ADD_ANIM_MARKER(<< 1790.4141, 4722.8970, 37.8533 >>, 221.4777, ANIM_MARKER_FORAGE) OPEN_TEST_POLY(g_polyPlayArea) ADD_TEST_POLY_VERT(g_polyPlayArea, << 1897.42, 4596.51, 36.40 >>) ADD_TEST_POLY_VERT(g_polyPlayArea, << 1912.20, 4676.93, 39.44 >>) ADD_TEST_POLY_VERT(g_polyPlayArea, << 1886.09, 4733.68, 39.48 >>) ADD_TEST_POLY_VERT(g_polyPlayArea, << 1800.24, 4820.64, 40.96 >>) ADD_TEST_POLY_VERT(g_polyPlayArea, << 1796.5560, 4893.5410, 40.4741 >>) ADD_TEST_POLY_VERT(g_polyPlayArea, << 1782.6514, 4916.3325, 41.4418 >>) ADD_TEST_POLY_VERT(g_polyPlayArea, << 1746.5521, 4942.3618, 42.8677 >>) ADD_TEST_POLY_VERT(g_polyPlayArea, << 1702.5366, 4893.8237, 36.7751 >>) ADD_TEST_POLY_VERT(g_polyPlayArea, << 1707.2734, 4814.8096, 40.9407 >>) ADD_TEST_POLY_VERT(g_polyPlayArea, << 1729.46, 4655.21, 42.61 >>) ADD_TEST_POLY_VERT(g_polyPlayArea, << 1772.0504, 4602.1426, 36.4570 >>) CLOSE_TEST_POLY(g_polyPlayArea) COPY_EXPANDED_POLY(g_polyFailArea, g_polyPlayArea, 20) ENDPROC //******************************************************************************************************************* //******************************************************************************************************************* MISSION STAGE DATATYPES ENUM MISSION_STAGE MS_NULL = -1, MS_LEADIN, MS_INTRO, MS_FINDROCK, MS_ROCKSCENE, MS_WAITTOPASS, MS_PASSED, MS_FAILED ENDENUM CONST_INT CP_INTRO 0 CONST_INT CP_FINDROCKA 1 CONST_INT CP_ROCKSCENEA 2 CONST_INT CP_FINDROCKB 3 CONST_INT CP_ROCKSCENEB 4 CONST_INT CP_FINDROCKC 5 CONST_INT CP_ROCKSCENEC 6 CONST_INT MAX_CP 7 CONST_INT MAX_SKIP_OPTIONS 8 ENUM STAGE_SECTION SECTION_SETUP = 0, SECTION_RUNNING, SECTION_FADEOUT, SECTION_CLEANUP, SECTION_SKIP ENDENUM ENUM FAIL_REASON FAIL_REASON_DEFAULT, FAIL_REASON_PLAYER_DEAD, FAIL_REASON_MARNIE_DEAD, FAIL_REASON_JIMMY_DEAD, FAIL_REASON_MARNIE_INJURED, FAIL_REASON_JIMMY_INJURED, FAIL_REASON_MARNIE_THREATENED, FAIL_REASON_JIMMY_THREATENED, FAIL_REASON_LEFT_AREA ENDENUM STRUCT MISSION_DATA MISSION_STAGE stage STAGE_SECTION section INT iEvent // A stage can store what stage should be next, then run through it's exit section. At the end of the exit section it will switch to this stage. BOOL bSyncForSkip BOOL bRequestJSkip BOOL bRequestPSkip BOOL bRequestCpSkip INT queueCpSkip MISSION_STAGE queueNextStage // When the mission goes to fail-state, it should set this so the right message can be displayed FAIL_REASON failReason ENDSTRUCT MISSION_DATA g_mission #IF IS_DEBUG_BUILD MissionStageMenuTextStruct zSkipMenu[MAX_SKIP_OPTIONS] #ENDIF //******************************************************************************************************************* //******************************************************************************************************************* MISSION STAGE FUNCTIONS /// PURPOSE: /// Initialise the mission data and bools PROC INIT_MISSION_DATA() g_mission.bRequestJSkip = FALSE g_mission.bRequestPSkip = FALSE g_mission.bRequestCpSkip = FALSE g_mission.bSyncForSkip = FALSE g_mission.queueNextStage = MS_NULL #IF IS_DEBUG_BUILD zSkipMenu[CP_INTRO].sTxtLabel = "Intro" zSkipMenu[CP_FINDROCKA].sTxtLabel = "Find rock A" zSkipMenu[CP_ROCKSCENEA].sTxtLabel = "Rock scene A" zSkipMenu[CP_FINDROCKB].sTxtLabel = "Find rock B" zSkipMenu[CP_ROCKSCENEB].sTxtLabel = "Rock scene B" zSkipMenu[CP_FINDROCKC].sTxtLabel = "Find rock C" zSkipMenu[CP_ROCKSCENEC].sTxtLabel = "Rock scene C" zSkipMenu[7].sTxtLabel = "Toggle Aim Camera pitch lock" INT i REPEAT MAX_CP i zSkipMenu[i].bSelectable = TRUE ENDREPEAT #ENDIF ENDPROC /// PURPOSE: /// Queue a mission stage skip to be executed later /// PARAMS: /// newStage - The stage we want to skip to PROC QUEUE_MISSION_STAGE(MISSION_STAGE newStage) g_mission.queueNextStage = newStage ENDPROC /// PURPOSE: /// Queue a skip to the given checkpoint to be executed later /// PARAMS: /// iCheckpoint - The checkpoint we want to skip to PROC QUEUE_CP_SKIP(INT iCheckpoint) g_mission.queueCpSkip = iCheckpoint g_mission.bRequestCpSkip = TRUE ENDPROC /// PURPOSE: /// Change the mission stage to the stored requested stage PROC CHANGE_MISSION_STAGE() // Handle skips IF g_mission.bRequestJSkip OR g_mission.bRequestPSkip OR g_mission.bRequestCpSkip g_mission.bSyncForSkip = TRUE IF g_mission.queueNextStage = MS_INTRO DEBUG_PRINTSTRING("Sync for skip is TRUE and Intro is queued!") ENDIF ELSE g_mission.bSyncForSkip = FALSE ENDIF IF g_mission.bRequestCpSkip SWITCH (g_mission.queueCpSkip) CASE CP_INTRO g_mission.queueNextStage = MS_INTRO BREAK CASE CP_FINDROCKA g_mission.queueNextStage = MS_FINDROCK iCurrentRock = 0 BREAK CASE CP_ROCKSCENEA g_mission.queueNextStage = MS_ROCKSCENE iCurrentRock = 0 BREAK CASE CP_FINDROCKB g_mission.queueNextStage = MS_FINDROCK iCurrentRock = 1 BREAK CASE CP_ROCKSCENEB g_mission.queueNextStage = MS_ROCKSCENE iCurrentRock = 1 BREAK CASE CP_FINDROCKC g_mission.queueNextStage = MS_FINDROCK iCurrentRock = 2 BREAK CASE CP_ROCKSCENEC g_mission.queueNextStage = MS_ROCKSCENE iCurrentRock = 2 BREAK ENDSWITCH ENDIF g_mission.bRequestJSkip = FALSE g_mission.bRequestPSkip = FALSE g_mission.bRequestCpSkip = FALSE // Change stage g_mission.stage = g_mission.queueNextStage g_mission.section = SECTION_SETUP g_mission.iEvent = 0 ENDPROC //******************************************************************************************************************* //******************************************************************************************************************* EPS FUNCTIONS /// PURPOSE: /// Create the Epsilonist we want and set default behaviours, or grab an existing ped index and reset their flags /// PARAMS: /// eps - The Epsilonist we want /// vPos - The position we want to create the Epsilonist at /// fRot - The heading of the Epsilonist /// hPed - An existing ped index we want to cast as the Epsilonist, if desired /// model - The model we want to use for the Epsilonist /// RETURNS: /// True if the ped exists and is uninjured, False if not FUNC BOOL CREATE_EPS(EPS_DATA& eps, VECTOR vPos, FLOAT fRot, PED_INDEX hPed = NULL, MODEL_NAMES model = DUMMY_MODEL_FOR_SCRIPT) IF hPed <> NULL eps.hPed = hPed DEBUG_PRINTSTRING("*** Epsilonist exists, grabbing ped index") ELSE eps.hPed = CREATE_PED(PEDTYPE_CIVFEMALE, model, vPos, fRot) DEBUG_PRINTSTRING("*** Epsilonist does not exist, creating new") ENDIF IF IS_PED_UNINJURED(eps.hPed) //SET_ENTITY_CAN_BE_DAMAGED(eps.hPed, FALSE) SET_PED_CONFIG_FLAG(eps.hPed, PCF_KeepRelationshipGroupAfterCleanUp, TRUE) SET_PED_RELATIONSHIP_GROUP_HASH(eps.hPed, RELGROUPHASH_PLAYER) SET_ENTITY_ONLY_DAMAGED_BY_PLAYER(eps.hPed, TRUE) SET_PED_CAN_BE_TARGETTED(eps.hPed, FALSE) SET_PED_CAN_RAGDOLL_FROM_PLAYER_IMPACT(eps.hPed, TRUE) //TASK_STAND_STILL(eps.hPed, -1) SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(eps.hPed, TRUE) SET_PED_KEEP_TASK(eps.hPed, TRUE) eps.state = EPS_ST_IDLE eps.mode = SETUP_STATE eps.iAnimMarker = -1 //SET_ENTITY_COORDS(eps.hPed, vPos) //SET_ENTITY_HEADING(eps.hPed, fRot) RETURN TRUE ENDIF RETURN FALSE ENDFUNC /// PURPOSE: /// Check for whether the given Epsilonist has been threatened by anyone /// PARAMS: /// eps - The Epsilonist we want to check /// RETURNS: /// True if threatened, False otherwise FUNC BOOL IS_EPS_THREATENED(EPS_DATA& eps) IF IS_ANYONE_SHOOTING_NEAR_PED(eps.hPed) RETURN TRUE ENDIF RETURN FALSE ENDFUNC /// PURPOSE: /// Remove the given Epsilonist from the world /// PARAMS: /// eps - The Epsilonist we want to delete PROC DELETE_EPS(EPS_DATA& eps) eps.state = EPS_ST_NULL eps.mode = SETUP_STATE SAFE_DELETE_PED(eps.hPed) ENDPROC /// PURPOSE: /// Set the passed-in Epsilonist to move around the area going to various destinations randomly, or to the passed in destination /// PARAMS: /// eps - The Epsilonist we want to move /// hDestinationMarker - The (optional) destination we want the Epsilonist to move to /// bNoNavmesh - Uses TASK_GO_TO_COORD instead which doesn't use navmesh - much faster, used for Marnie exiting the intro PROC SET_EPS_MOVE(EPS_DATA& eps, INT hDestinationMarker = -1) IF IS_PED_UNINJURED(eps.hPed) eps.state = EPS_ST_MOVE eps.mode = SETUP_STATE //CLEAR_PED_TASKS(eps.hPed) IF eps.iAnimMarker <> -1 animMarkerArray[eps.iAnimMarker].bIsInUse = FALSE ENDIF eps.iAnimMarker = hDestinationMarker ELSE eps.state = EPS_ST_NULL eps.mode = SETUP_STATE ENDIF ENDPROC /// PURPOSE: /// Set the passed in Epsilonists as idle and remove them from the player's group /// PARAMS: /// eps - The Epsilonist ped /// bClearTasksImmediately - Whether we want to clear tasks immediately rather than... not immediately PROC SET_EPS_IDLE(EPS_DATA& eps, BOOL bClearTasksImmediately = TRUE) IF IS_PED_UNINJURED(eps.hPed) eps.state = EPS_ST_IDLE eps.mode = SETUP_STATE IF bClearTasksImmediately CLEAR_PED_TASKS_IMMEDIATELY(eps.hPed) ELSE CLEAR_PED_TASKS(eps.hPed) ENDIF IF eps.iAnimMarker <> -1 animMarkerArray[eps.iAnimMarker].bIsInUse = FALSE eps.iAnimMarker = -1 ENDIF IF IS_PED_IN_GROUP(eps.hPed) REMOVE_PED_FROM_GROUP(eps.hPed) ENDIF ELSE eps.state = EPS_ST_NULL eps.mode = SETUP_STATE ENDIF ENDPROC /// PURPOSE: /// Immediately warp the given Epsilonist to the given marker /// PARAMS: /// eps - The Epsilonist /// hMarker - The marker ID we want to warp to PROC SET_EPS_WARP_TO_MARKER(EPS_DATA& eps, INT hMarker) IF IS_PED_UNINJURED(eps.hPed) IF eps.state = EPS_ST_MARKER animMarkerArray[hMarker].bIsInUse = FALSE ENDIF //CLEAR_PED_TASKS(eps.hPed) eps.state = EPS_ST_MARKER eps.mode = SETUP_STATE animMarkerArray[hMarker].bIsInUse = TRUE eps.iAnimMarker = hMarker IF IS_PED_IN_GROUP(eps.hPed) REMOVE_PED_FROM_GROUP(eps.hPed) ENDIF CLEAR_PED_TASKS_IMMEDIATELY(eps.hPed) SET_ENTITY_COORDS(eps.hPed, animMarkerArray[hMarker].vPos) SET_ENTITY_HEADING(eps.hPed, animMarkerArray[hMarker].fRot) ELSE eps.state = EPS_ST_NULL eps.mode = SETUP_STATE ENDIF ENDPROC /// PURPOSE: /// Set the given Epsilonist to follow the player around /// PARAMS: /// eps - The Epsilonist /// bTurnToFacePed - Whether want the ped to always try and face the player when they stop moving PROC SET_EPS_FOLLOW(EPS_DATA& eps, BOOL bTurnToFacePed = TRUE) IF IS_PED_UNINJURED(eps.hPed) AND IS_PED_UNINJURED(PLAYER_PED_ID()) eps.state = EPS_ST_FOLLOW eps.mode = SETUP_STATE //CLEAR_PED_TASKS(eps.hPed) TASK_LOOK_AT_ENTITY(eps.hPed, PLAYER_PED_ID(), -1) IF bTurnToFacePed TASK_TURN_PED_TO_FACE_ENTITY(eps.hPed, PLAYER_PED_ID()) ENDIF eps.vPlayerStartPos = GET_ENTITY_COORDS(PLAYER_PED_ID()) ELSE eps.state = EPS_ST_NULL eps.mode = SETUP_STATE ENDIF ENDPROC PROC CHECK_FOR_KNOCKDOWN(PED_INDEX epsPed) IF IS_PED_UNINJURED(epsPed) AND IS_ENTITY_ALIVE(PLAYER_PED_ID()) IF epsKnockedOver = FALSE IF IS_ENTITY_TOUCHING_ENTITY(PLAYER_PED_ID(), epsPed) AND IS_PED_RAGDOLL(epsPed) DEBUG_PRINTSTRING("Player knocked Eps over!") epsKnockedOver = TRUE epsPedKnockedOver = epsPed // Store which ped got knocked over CLEAR_PED_TASKS(epsPed) ENDIF ELSE IF IS_PED_UNINJURED(epsPedKnockedOver) IF IS_PED_GETTING_UP(epsPedKnockedOver) OR IS_PED_ON_FOOT(epsPedKnockedOver) IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED() AND NOT IS_MESSAGE_BEING_DISPLAYED() IF epsPedKnockedOver = epsilonianArray[ID_JIMMY].hPed IF CREATE_CONVERSATION(pedsForConversation, "EPS4AUD", "EPS4_JKNOCK", CONV_PRIORITY_MEDIUM) epsKnockedOver = FALSE epsPedKnockedOver = NULL ENDIF ELSE IF CREATE_CONVERSATION(pedsForConversation, "EPS4AUD", "EPS4_MKNOCK", CONV_PRIORITY_MEDIUM) epsKnockedOver = FALSE epsPedKnockedOver = NULL ENDIF ENDIF ENDIF ENDIF ENDIF ENDIF ENDIF ENDPROC /// PURPOSE: /// Continually update and check the given Epsilonists behaviour every frame /// PARAMS: /// eps - The Epsilonist PROC UPDATE_EPS(EPS_DATA& eps) IF IS_PED_UNINJURED(eps.hPed) AND IS_PED_IN_GROUP(eps.hPed) IF eps.state <> EPS_ST_FOLLOW AND eps.state <> EPS_ST_CATCHUP REMOVE_PED_FROM_GROUP(eps.hPed) ENDIF ENDIF CHECK_FOR_KNOCKDOWN(eps.hPed) SWITCH (eps.state) CASE EPS_ST_NULL BREAK CASE EPS_ST_IDLE BREAK CASE EPS_ST_MOVE IF NOT IS_PED_UNINJURED(eps.hPed) eps.state = EPS_ST_NULL eps.mode = SETUP_STATE ELIF eps.mode = SETUP_STATE // Try to find a marker to go to (a different one to the previous one) INT iRandMarker iRandMarker = GET_RANDOM_INT_IN_RANGE(0, iAnimMarkerCount) WHILE eps.iAnimMarker = -1 IF animMarkerArray[iRandMarker].bIsInUse = FALSE IF animMarkerArray[iRandMarker].type = ANIM_MARKER_FORAGE IF NOT IS_ENTITY_AT_COORD(eps.hPed, animMarkerArray[iRandMarker].vPos, <<3,3,3>>) DEBUG_PRINTSI("Telling ped to go to marker: ", iRandMarker) animMarkerArray[iRandMarker].bIsInUse = TRUE eps.iAnimMarker = iRandMarker ENDIF ENDIF ENDIF iRandMarker = (iRandMarker + 1) % iAnimMarkerCount ENDWHILE // Go to new marker TASK_FOLLOW_NAV_MESH_TO_COORD(eps.hPed, animMarkerArray[eps.iAnimMarker].vPos, PEDMOVE_WALK, DEFAULT_TIME_NEVER_WARP, DEFAULT_NAVMESH_RADIUS, ENAV_NO_STOPPING|ENAV_GO_FAR_AS_POSSIBLE_IF_TARGET_NAVMESH_NOT_LOADED) eps.mode = UPDATE_STATE ELIF eps.mode = UPDATE_STATE IF NOT eps.bNotUsingNavmeshMove IF GET_SCRIPT_TASK_STATUS(eps.hPed, SCRIPT_TASK_FOLLOW_NAV_MESH_TO_COORD) = FINISHED_TASK DEBUG_PRINTSTRING("Eps reached marker! (follow nav to coord)") eps.state = EPS_ST_MARKER eps.mode = SETUP_STATE ENDIF ELSE IF GET_SCRIPT_TASK_STATUS(eps.hPed, SCRIPT_TASK_GO_STRAIGHT_TO_COORD) = FINISHED_TASK DEBUG_PRINTSTRING("Eps reached marker! (go straight to coord)") eps.bNotUsingNavmeshMove = FALSE eps.state = EPS_ST_MARKER eps.mode = SETUP_STATE ENDIF ENDIF ENDIF BREAK CASE EPS_ST_MARKER IF NOT IS_PED_UNINJURED(eps.hPed) eps.state = EPS_ST_NULL eps.mode = SETUP_STATE ELIF eps.mode = SETUP_STATE DEBUG_PRINTSI("Telling ped do sequence for marker: ", eps.iAnimMarker) OPEN_SEQUENCE_TASK(seq) IF animMarkerArray[eps.iAnimMarker].type = ANIM_MARKER_FORAGE IF eps.hPed = epsilonianArray[ID_JIMMY].hPed TASK_PLAY_ANIM(null, "rcm_epsilonism4", "eps_4_ig_1_jimmy_lookaround_entry_jb", SLOW_BLEND_IN, SLOW_BLEND_OUT) TASK_PLAY_ANIM(null, "rcm_epsilonism4", "eps_4_ig_1_jimmy_lookaround_idle_a_jb", DEFAULT, SLOW_BLEND_OUT) TASK_PLAY_ANIM(null, "rcm_epsilonism4", "eps_4_ig_1_jimmy_lookaround_exit_jb", SLOW_BLEND_IN, SLOW_BLEND_OUT) ELSE TASK_PLAY_ANIM(null, "rcm_epsilonism4", "eps_4_ig_1_marnie_lookaround_entry_marnie", SLOW_BLEND_IN, SLOW_BLEND_OUT) TASK_PLAY_ANIM(null, "rcm_epsilonism4", "eps_4_ig_1_marnie_lookaround_idle_a_marnie", DEFAULT, SLOW_BLEND_OUT) TASK_PLAY_ANIM(null, "rcm_epsilonism4", "eps_4_ig_1_marnie_lookaround_exit_marnie", SLOW_BLEND_IN, SLOW_BLEND_OUT) ENDIF ELIF animMarkerArray[eps.iAnimMarker].type = ANIM_MARKER_DUMMY_PISS TASK_ACHIEVE_HEADING(null, animMarkerArray[eps.iAnimMarker].fRot) TASK_PLAY_ANIM(null, "rcm_epsilonism4", "peeing") ELIF animMarkerArray[eps.iAnimMarker].type = ANIM_MARKER_DUMMY_DANCE TASK_PLAY_ANIM(null, "rcm_epsilonism4", "hippy_a", NORMAL_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_LOOPING) ELIF animMarkerArray[eps.iAnimMarker].type = ANIM_MARKER_DUMMY_JIMMY TASK_PLAY_ANIM(null, "rcm_epsilonism4", "eps_4_ig_1_jimmy_lookaround_entry_jb", SLOW_BLEND_IN, SLOW_BLEND_OUT) TASK_PLAY_ANIM(null, "rcm_epsilonism4", "eps_4_ig_1_jimmy_lookaround_idle_a_jb", DEFAULT, SLOW_BLEND_OUT) TASK_PLAY_ANIM(null, "rcm_epsilonism4", "eps_4_ig_1_jimmy_lookaround_exit_jb", SLOW_BLEND_IN, SLOW_BLEND_OUT) ENDIF CLOSE_SEQUENCE_TASK(seq) TASK_PERFORM_SEQUENCE(eps.hPed, seq) CLEAR_SEQUENCE_TASK(seq) eps.mode = UPDATE_STATE ELIF eps.mode = UPDATE_STATE IF GET_SCRIPT_TASK_STATUS(eps.hPed, SCRIPT_TASK_PERFORM_SEQUENCE) = FINISHED_TASK animMarkerArray[eps.iAnimMarker].bIsInUse = FALSE eps.iAnimMarker = -1 eps.state = EPS_ST_MOVE eps.mode = SETUP_STATE ENDIF ENDIF BREAK CASE EPS_ST_FOLLOW IF NOT IS_PED_UNINJURED(eps.hPed) eps.state = EPS_ST_NULL eps.mode = SETUP_STATE ELIF eps.mode = SETUP_STATE IF NOT IS_ENTITY_AT_COORD(PLAYER_PED_ID(), eps.vPlayerStartPos, <<1,1,1>>)//<<1.5,1.5,1.5>>)//<<3,3,3>>)// OR iCurrentRock > 0 IF NOT IS_PED_IN_GROUP(eps.hPed) CLEAR_PED_TASKS(eps.hPed) SET_PED_AS_GROUP_MEMBER(eps.hPed, PLAYER_GROUP_ID()) SET_PED_CONFIG_FLAG(eps.hPed,PCF_DontEnterVehiclesInPlayersGroup, TRUE) ENDIF iFollowIdleTimer = GET_GAME_TIMER() IF iCurrentRock = 0 SET_GROUP_FORMATION(PLAYER_GROUP_ID(), FORMATION_LOOSE)//FORMATION_LINE_ABREAST)//FORMATION_LOOSE)// ELSE SET_GROUP_FORMATION(PLAYER_GROUP_ID(), FORMATION_LOOSE) ENDIF SET_GROUP_FORMATION_SPACING(PLAYER_GROUP_ID(), 4.0)//4.5)//5.0)//6.0//4.0)//3.0)//2.5)//2.2)//1.8) //1.375)//1.5)//2.2)//1.25) eps.mode = UPDATE_STATE ENDIF ELIF eps.mode = UPDATE_STATE IF NOT IS_PED_IN_GROUP(eps.hPed) eps.state = EPS_ST_CATCHUP eps.mode = SETUP_STATE ENDIF // If the follower isn't currently moving, wait a few seconds and then do an idle anim IF IS_PED_STILL(eps.hPed) // If the ped isn't doing the idle, keep checking if the time has passed and then do it IF NOT bFollowerDoingIdle IF GET_GAME_TIMER() - iFollowIdleTimer > 6000 OPEN_SEQUENCE_TASK(seq) IF eps.hPed = epsilonianArray[ID_JIMMY].hPed TASK_PLAY_ANIM(null, "rcm_epsilonism4", "eps_4_ig_1_jimmy_lookaround_entry_jb", SLOW_BLEND_IN, SLOW_BLEND_OUT) TASK_PLAY_ANIM(null, "rcm_epsilonism4", "eps_4_ig_1_jimmy_lookaround_idle_a_jb", DEFAULT, SLOW_BLEND_OUT) TASK_PLAY_ANIM(null, "rcm_epsilonism4", "eps_4_ig_1_jimmy_lookaround_exit_jb", SLOW_BLEND_IN, SLOW_BLEND_OUT) ELSE TASK_PLAY_ANIM(null, "rcm_epsilonism4", "eps_4_ig_1_marnie_lookaround_entry_marnie", SLOW_BLEND_IN, SLOW_BLEND_OUT) TASK_PLAY_ANIM(null, "rcm_epsilonism4", "eps_4_ig_1_marnie_lookaround_idle_a_marnie", DEFAULT, SLOW_BLEND_OUT) TASK_PLAY_ANIM(null, "rcm_epsilonism4", "eps_4_ig_1_marnie_lookaround_exit_marnie", SLOW_BLEND_IN, SLOW_BLEND_OUT) ENDIF CLOSE_SEQUENCE_TASK(seq) TASK_PERFORM_SEQUENCE(eps.hPed, seq) CLEAR_SEQUENCE_TASK(seq) IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED() AND NOT IS_MESSAGE_BEING_DISPLAYED() IF eps.hPed = epsilonianArray[ID_JIMMY].hPed CREATE_CONVERSATION(pedsForConversation, "EPS4AUD", "EPS4_DAWDJ", CONV_PRIORITY_MEDIUM) ELSE CREATE_CONVERSATION(pedsForConversation, "EPS4AUD", "EPS4_DAWDM", CONV_PRIORITY_MEDIUM) ENDIF ENDIF bFollowerDoingIdle = TRUE ENDIF ELSE // Otherwise, if they're doing it, keep resetting the timer, and keep checking if they're not doing it to reset the bool iFollowIdleTimer = GET_GAME_TIMER() IF NOT IsPedPerformingTask(eps.hPed, SCRIPT_TASK_PERFORM_SEQUENCE) bFollowerDoingIdle = FALSE ENDIF ENDIF ELSE iFollowIdleTimer = GET_GAME_TIMER() bFollowerDoingIdle = FALSE ENDIF // Check for player "messing around" and make the following Eps comment on it IF IS_PED_SPRINTING(PLAYER_PED_ID()) OR IS_PED_JUMPING(PLAYER_PED_ID()) IF GET_GAME_TIMER() - iFollowMessingAroundTimer > 7500 AND NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED() AND NOT IS_MESSAGE_BEING_DISPLAYED() AND NOT bIsPlayerAtRock IF eps.hPed = epsilonianArray[ID_JIMMY].hPed IF CREATE_CONVERSATION(pedsForConversation, "EPS4AUD", "EPS4_MESSJ", CONV_PRIORITY_MEDIUM) iFollowMessingAroundTimer = GET_GAME_TIMER() ENDIF ELSE IF CREATE_CONVERSATION(pedsForConversation, "EPS4AUD", "EPS4_MESSM", CONV_PRIORITY_MEDIUM) iFollowMessingAroundTimer = GET_GAME_TIMER() ENDIF ENDIF ENDIF ENDIF // If the player hasn't aimed the detector for a while, make the follower comment on it IF (GET_GAME_TIMER() - iAimPromptTimer) > 15000 // 15 secs? IF iAimPromptLines < 4 // Both characters only have 4 lines, so we can hard-code this to a number AND NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED() AND NOT IS_MESSAGE_BEING_DISPLAYED() AND NOT bIsPlayerAtRock AND NOT IS_PLAYER_IN_FIRST_PERSON_CAMERA() IF eps.hPed = epsilonianArray[ID_JIMMY].hPed IF CREATE_CONVERSATION(pedsForConversation, "EPS4AUD", "EPS4_PROMPTJ", CONV_PRIORITY_MEDIUM) iAimPromptTimer = GET_GAME_TIMER() iAimPromptLines++ ENDIF ELSE IF CREATE_CONVERSATION(pedsForConversation, "EPS4AUD", "EPS4_PROMPTM", CONV_PRIORITY_MEDIUM) iAimPromptTimer = GET_GAME_TIMER() iAimPromptLines++ ENDIF ENDIF ENDIF ENDIF ENDIF BREAK CASE EPS_ST_CATCHUP IF NOT IS_PED_UNINJURED(eps.hPed) eps.state = EPS_ST_NULL eps.mode = SETUP_STATE ELIF eps.mode = SETUP_STATE TASK_GO_TO_ENTITY(eps.hPed, PLAYER_PED_ID(), DEFAULT_TIME_BEFORE_WARP, 4.5) eps.mode = UPDATE_STATE ELIF eps.mode = UPDATE_STATE // DISPLAY_TEXT(0.1, 0.1, "CATCHUP") SET_PED_AS_GROUP_MEMBER(eps.hPed, PLAYER_GROUP_ID()) IF IS_PED_IN_GROUP(eps.hPed) eps.state = EPS_ST_FOLLOW eps.mode = SETUP_STATE ENDIF ENDIF BREAK DEFAULT SCRIPT_ASSERT("UPDATE_EPS(): State not supported\n") BREAK ENDSWITCH ENDPROC //******************************************************************************************************************* //******************************************************************************************************************* ROCK FUNCTIONS /// PURPOSE: /// Create the given rock in the world /// PARAMS: /// rock - The rock we want to create PROC CREATE_ROCK(ROCK_DATA& rock) VECTOR vPos = rock.vPos DEBUG_PRINTVECTOR("Rock created at: ", rock.vPos) rock.hObject = CREATE_OBJECT_NO_OFFSET(rock.model, vPos) IF DOES_ENTITY_EXIST(rock.hObject) SET_ENTITY_ROTATION(rock.hObject, rock.vRot, EULER_XYZ) DEBUG_PRINTVECTOR("Rock rot vector: ", GET_ENTITY_ROTATION(rock.hObject, EULER_XYZ)) DEBUG_PRINTVECTOR("Rock actual position: ", GET_ENTITY_COORDS(rock.hObject, FALSE)) SET_ENTITY_CAN_BE_DAMAGED(rock.hObject, FALSE) FREEZE_ENTITY_POSITION(rock.hObject, TRUE) ENDIF ENDPROC /// PURPOSE: /// Delete all the rocks in the mission PROC DELETE_ALL_ROCKS() INT i REPEAT iRockCount i SAFE_DELETE_OBJECT(rockArray[i].hObject) ENDREPEAT ENDPROC //******************************************************************************************************************* //******************************************************************************************************************* DETECTOR FUNCTIONS CONST_FLOAT CONST_fDefaultHotAngle 0.9200 /// PURPOSE: /// Initialise various detector variables PROC INIT_DETECTOR() gDetector.hSndHum = GET_SOUND_ID() gDetector.hSndBeep = GET_SOUND_ID() gDetector.hSndFound = GET_SOUND_ID() gDetector.hSndScan = GET_SOUND_ID() gDetector.fHotAngle = CONST_fDefaultHotAngle gDetector.bLockSettings = FALSE gDetector.sRecentAnim = "NO_RECENT_ANIM" si_DetectorScaleform = REQUEST_SCALEFORM_MOVIE("digiscanner") WHILE NOT HAS_SCALEFORM_MOVIE_LOADED(si_DetectorScaleform) WAIT(0) ENDWHILE IF NOT IS_NAMED_RENDERTARGET_REGISTERED("digiscanner") REGISTER_NAMED_RENDERTARGET("digiscanner") ENDIF LINK_NAMED_RENDERTARGET(model_Detector) IF IS_NAMED_RENDERTARGET_REGISTERED("digiscanner") rt_ID = GET_NAMED_RENDERTARGET_RENDER_ID("digiscanner") ENDIF ENDPROC /// PURPOSE: /// Turn the detector on /// PARAMS: /// fMeanderFactor0 - An override for the first meander factor /// fMeanderFactor1 - An override for the second meander factor /// fMeanderAmplitude - An override for the meader amplitude /// fStraightZone - An override for the straight zone /// fHotAngle - An override for the detector hot angle PROC START_DETECTOR(FLOAT fMeanderFactor0 = 50.0, FLOAT fMeanderFactor1 = 70.0, FLOAT fMeanderAmplitude = 25.0, FLOAT fStraightZone = 30.0, FLOAT fHotAngle = CONST_fDefaultHotAngle) // Play hum sound PLAY_SOUND_FROM_ENTITY(gDetector.hSndHum, "DEVICE", PLAYER_PED_ID(), "EPSILONISM_04_SOUNDSET") // Calculate meander factor IF gDetector.bLockSettings = FALSE gDetector.fMeanderFactor0 = fMeanderFactor0 gDetector.fMeanderFactor1 = fMeanderFactor1 gDetector.fMeanderAmplitude = fMeanderAmplitude gDetector.fStraightZone = fStraightZone gDetector.fHotAngle = fHotAngle ENDIF gDetector.bIsFoundSoundOn = FALSE gDetector.bIsScanSoundOn = FALSE gDetector.sRecentAnim = "NO_RECENT_ANIM" ENDPROC /// PURPOSE: /// Turn off the detector and prevent it reacting to the rock PROC STOP_DETECTOR() // Stop hum sound STOP_SOUND(gDetector.hSndHum) // Stop other sounds STOP_SOUND(gDetector.hSndBeep) STOP_SOUND(gDetector.hSndFound) STOP_SOUND(gDetector.hSndScan) gDetector.bIsFoundSoundOn = FALSE gDetector.bIsScanSoundOn = FALSE ENDPROC PROC FORCE_NOT_FOUND_SCREEN_ON_DETECTOR() BEGIN_SCALEFORM_MOVIE_METHOD(si_DetectorScaleform, "SET_COLOUR") SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(255) //BarsR SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(10) //BarsG SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(10) //BarsB SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(255) //LightsR SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(10) //LightsG SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(10) //LightsB SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(255) //WrongWayR SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(10) //WrongWayG SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(10) //WrongWayB END_SCALEFORM_MOVIE_METHOD() BEGIN_SCALEFORM_MOVIE_METHOD(si_DetectorScaleform, "SET_DISTANCE") SCALEFORM_MOVIE_METHOD_ADD_PARAM_FLOAT(10.0) END_SCALEFORM_MOVIE_METHOD() SET_TEXT_RENDER_ID(rt_ID) DRAW_SCALEFORM_MOVIE(si_DetectorScaleform, 0.100, 0.24000, 0.2100,0.51000, 100,100,100,255) ENDPROC PROC FORCE_FOUND_SCREEN_ON_DETECTOR() BEGIN_SCALEFORM_MOVIE_METHOD(si_DetectorScaleform, "SET_COLOUR") SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(67) //BarsR SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(200) //BarsG SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(255) //BarsB SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(255) //LightsR SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(209) //LightsG SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(67) //LightsB SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(255) //WrongWayR SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(0) //WrongWayG SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(0) //WrongWayB END_SCALEFORM_MOVIE_METHOD() BEGIN_SCALEFORM_MOVIE_METHOD(si_DetectorScaleform, "SET_DISTANCE") SCALEFORM_MOVIE_METHOD_ADD_PARAM_FLOAT(100.0) END_SCALEFORM_MOVIE_METHOD() SET_TEXT_RENDER_ID(rt_ID) DRAW_SCALEFORM_MOVIE(si_DetectorScaleform, 0.100, 0.24000, 0.2100,0.51000, 100,100,100,255) ENDPROC /// PURPOSE: /// Called every frame to update the detector while the player is searching for a rock /// PARAMS: /// rock - The rock the player is currently searching for PROC UPDATE_DETECTOR(ROCK_DATA& rock) CONST_FLOAT fBeepMinDist 6.5//3.0 CONST_FLOAT fBeepRange 40.0 //-- Calc dist, and if facing the target // Calc dist FLOAT fDist = VDIST(rock.vPos, GET_ENTITY_COORDS(PLAYER_PED_ID())) // Get distorted-angle forward-vector VECTOR vPlayerForward = GET_ENTITY_FORWARD_VECTOR(PLAYER_PED_ID()) VECTOR vDistortedForward IF fDist > gDetector.fStraightZone FLOAT fDistortionAngle = 0.0 IF gDetector.fMeanderFactor0 > 0.0 fDistortionAngle += SIN((fDist-gDetector.fStraightZone) * (360.0 / gDetector.fMeanderFactor0)) * gDetector.fMeanderAmplitude ENDIF IF gDetector.fMeanderFactor1 > 0.0 fDistortionAngle += SIN((fDist-gDetector.fStraightZone) * (360.0 / gDetector.fMeanderFactor1)) * (gDetector.fMeanderAmplitude * -0.7) ENDIF vDistortedForward.x = (vPlayerForward.x * COS(fDistortionAngle)) - (vPlayerForward.y * SIN(fDistortionAngle)) vDistortedForward.y = (vPlayerForward.y * COS(fDistortionAngle)) + (vPlayerForward.x * SIN(fDistortionAngle)) ELSE vDistortedForward = vPlayerForward ENDIF // Get other useful vectors VECTOR vPlayerToRock1 = rock.vPos - GET_ENTITY_COORDS(PLAYER_PED_ID()) // Is rock ahead of player? (180 degrees) VECTOR vPlayerToRock2 = rock.vPos - GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(PLAYER_PED_ID(), <<0,-5,0>>) // Is rock in cone? (starting cone slightly behind player) // Calc is-in-front BOOL bIsInFrontOfPlayer = vPlayerToRock1.x*vDistortedForward.x + vPlayerToRock1.y*vDistortedForward.y > 0.0 FLOAT fAngle = 1.0 - (GET_ANGLE_BETWEEN_2D_VECTORS(vDistortedForward.x, vDistortedForward.y, vPlayerToRock2.x, vPlayerToRock2.y) / 180.0) // Adjust the hot angle depending on distance to the artefact if fDist >= 10 gDetector.fHotAngle = CONST_fDefaultHotAngle ELSE gDetector.fHotAngle = 0.95 ENDIF BOOL bOnTarget = (fAngle > gDetector.fHotAngle) AND bIsInFrontOfPlayer #IF IS_DEBUG_BUILD IF g_DEBUG_DisplayInfo DRAW_RECT_FROM_CORNER(0.03, 0.18, 0.3, (0.2 + (0.05*4)) - 0.18, 0,0,0, 100) TEXT_LABEL_63 sDebugStr // sDebugStr = "Meander phase dist 0: " // sDebugStr += GET_STRING_FROM_FLOAT(gDetector.fMeanderFactor0) // SET_TEXT_SCALE(0.7, 0.6) // DISPLAY_TEXT_WITH_LITERAL_STRING(0.05, (0.2 + (0.05*1)), "STRING", sDebugStr) // // sDebugStr = "Meander phase dist 1: " // sDebugStr += GET_STRING_FROM_FLOAT(gDetector.fMeanderFactor1) // SET_TEXT_SCALE(0.7, 0.6) // DISPLAY_TEXT_WITH_LITERAL_STRING(0.05, (0.2 + (0.05*2)), "STRING", sDebugStr) // // sDebugStr = "Meander amplitude: " // sDebugStr += GET_STRING_FROM_FLOAT(gDetector.fMeanderAmplitude) // SET_TEXT_SCALE(0.7, 0.6) // DISPLAY_TEXT_WITH_LITERAL_STRING(0.05, (0.2 + (0.05*0)), "STRING", sDebugStr) sDebugStr = "Dist to target: " sDebugStr += GET_STRING_FROM_FLOAT(VDIST(GET_ENTITY_COORDS(PLAYER_PED_ID()), rock.vPos)) SET_TEXT_SCALE(0.7, 0.6) DISPLAY_TEXT_WITH_LITERAL_STRING(0.05, (0.2 + (0.05*3)), "STRING", sDebugStr) sDebugStr = "Current angle: " sDebugStr += GET_STRING_FROM_FLOAT(fAngle) SET_TEXT_SCALE(0.7, 0.6) DISPLAY_TEXT_WITH_LITERAL_STRING(0.05, (0.2 + (0.05*0)), "STRING", sDebugStr) // VECTOR vRockPos // vRockPos = GET_ENTITY_COORDS(rockArray[0].hObject, FALSE) // sDebugStr = "rock 0 z: " // sDebugStr += GET_STRING_FROM_FLOAT(vRockPos.z) // SET_TEXT_SCALE(0.7, 0.6) // DISPLAY_TEXT_WITH_LITERAL_STRING(0.05, (0.2 + (0.05*3)), "STRING", sDebugStr) // // vRockPos = GET_ENTITY_COORDS(rockArray[1].hObject, FALSE) // sDebugStr = "rock 1 z: " // sDebugStr += GET_STRING_FROM_FLOAT(vRockPos.z) // SET_TEXT_SCALE(0.7, 0.6) // DISPLAY_TEXT_WITH_LITERAL_STRING(0.05, (0.2 + (0.05*4)), "STRING", sDebugStr) // // vRockPos = GET_ENTITY_COORDS(rockArray[2].hObject, FALSE) // sDebugStr = "rock 2 z: " // sDebugStr += GET_STRING_FROM_FLOAT(vRockPos.z) // SET_TEXT_SCALE(0.7, 0.6) // DISPLAY_TEXT_WITH_LITERAL_STRING(0.05, (0.2 + (0.05*5)), "STRING", sDebugStr) ENDIF #ENDIF gDetector.bIsOnTarget = bOnTarget //-- Manage radar beep IF gDetector.bIsFoundSoundOn = TRUE SET_CONTROL_SHAKE(PLAYER_CONTROL, 200, 150) IF fDist > fBeepMinDist OR bOnTarget = FALSE STOP_SOUND(gDetector.hSndFound) gDetector.bIsFoundSoundOn = FALSE iPhaseTimer = 0 ENDIF ELIF iPhaseTimer < GET_GAME_TIMER() IF fDist <= fBeepMinDist AND bOnTarget STOP_SOUND(gDetector.hSndBeep) PLAY_SOUND_FROM_ENTITY(gDetector.hSndFound, "CONTINUAL_BEEP", PLAYER_PED_ID(), "EPSILONISM_04_SOUNDSET") gDetector.bIsFoundSoundOn = TRUE ELSE // Set cycle length FLOAT fBeepDist = fDist - (fBeepMinDist + 2.5) IF fBeepDist < 0 fBeepDist = 0 ENDIF INT iInterval = 125 + ROUND( (fBeepDist / fBeepRange) * (1250.0 - 125.0) ) IF iInterval > 1250 iInterval = 1250 ENDIF iPhaseTimer = GET_GAME_TIMER() + iInterval iInterval /= 3 IF iInterval < 100 iInterval = 100 ENDIF iBeepOffTimer = GET_GAME_TIMER() + iInterval // Play beep + shake pad PLAY_SOUND_FROM_ENTITY(gDetector.hSndBeep, "IDLE_BEEP", PLAYER_PED_ID(), "EPSILONISM_04_SOUNDSET") IF bOnTarget SET_CONTROL_SHAKE(PLAYER_CONTROL, 200, 150) ELSE SET_CONTROL_SHAKE(PLAYER_CONTROL, 200, 100) ENDIF ENDIF ENDIF // Stop beep sound IF iBeepOffTimer > 0 AND GET_GAME_TIMER() > iBeepOffTimer STOP_SOUND(gDetector.hSndBeep) iBeepOffTimer = 0 ENDIF //-- Manage on-target sound IF IS_AIM_CAM_ACTIVE() IF gDetector.bIsScanSoundOn = FALSE PLAY_SOUND_FROM_ENTITY(gDetector.hSndScan, "SCAN", PLAYER_PED_ID(), "EPSILONISM_04_SOUNDSET") gDetector.bIsScanSoundOn = TRUE ELSE IF bOnTarget SET_VARIABLE_ON_SOUND(gDetector.hSndScan, "IsOnTarget", 1.0) ELSE SET_VARIABLE_ON_SOUND(gDetector.hSndScan, "IsOnTarget", 0.0) ENDIF ENDIF iAimPromptTimer = GET_GAME_TIMER() // Keep resetting this timer while the player is aiming ELSE IF gDetector.bIsScanSoundOn = TRUE STOP_SOUND(gDetector.hSndScan) gDetector.bIsScanSoundOn = FALSE ENDIF ENDIF //-- Manage proximity meter IF NOT DOES_ENTITY_EXIST(gDetector.hObj) gDetector.hObj = GET_CURRENT_PED_WEAPON_ENTITY_INDEX(PLAYER_PED_ID()) ELSE FLOAT fProx = (fDist - fBeepMinDist) / (rock.fMeterRange - fBeepMinDist) // Normalise for range IF fProx < 0.0 fProx = 0.0 ELIF fProx > 1.0 fProx = 1.0 ENDIF IF gDetector.bIsOnTarget fReading = 100 - (fProx * 100.0) ELSE fReading = 100 - (fProx * 100.0) fReading = fReading*-1.0 ENDIF // IF IS_AIM_CAM_ACTIVE() // DRAW_SCALEFORM_MOVIE_FULLSCREEN(si_DetectorScaleform, 100, 100, 100, 255) // ENDIF IF NOT gDetector.bIsOnTarget BEGIN_SCALEFORM_MOVIE_METHOD(si_DetectorScaleform, "SET_COLOUR") SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(255) //BarsR SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(10) //BarsG SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(10) //BarsB SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(255) //LightsR SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(10) //LightsG SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(10) //LightsB SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(255) //WrongWayR SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(10) //WrongWayG SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(10) //WrongWayB END_SCALEFORM_MOVIE_METHOD() ELSE BEGIN_SCALEFORM_MOVIE_METHOD(si_DetectorScaleform, "SET_COLOUR") SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(67) //BarsR SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(200) //BarsG SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(255) //BarsB SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(255) //LightsR SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(209) //LightsG SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(67) //LightsB SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(255) //WrongWayR SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(0) //WrongWayG SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(0) //WrongWayB END_SCALEFORM_MOVIE_METHOD() ENDIF // Cap the reading value so the last bar doesn't get filled until you're very close IF fReading >= 95.0 AND fReading <= 99.8 fReading = 94.9 ELIF fReading <= -95.0 AND fReading >= -99.8 fReading = -94.9 ENDIF // If the player is at the find range for the object, force the distance bar to full just in case it's not IF IS_ENTITY_AT_COORD(PLAYER_PED_ID(), rockArray[iCurrentRock].vPos, << fFindRange,fFindRange,2.0 >>, FALSE, FALSE, TM_ON_FOOT) fReading = 100.0 ENDIF BEGIN_SCALEFORM_MOVIE_METHOD(si_DetectorScaleform, "SET_DISTANCE") SCALEFORM_MOVIE_METHOD_ADD_PARAM_FLOAT(fReading) END_SCALEFORM_MOVIE_METHOD() SET_TEXT_RENDER_ID(rt_ID) DRAW_SCALEFORM_MOVIE(si_DetectorScaleform, 0.100, 0.24000, 0.2100,0.51000, 100,100,100,255) // This is the old meter in the corner of the screen, from before the scaleform for the detector was created // Technically it's not needed anymore, but let's keep it around just in case it's handy for debug, // or if the scaleform breaks in a future build or something // IF IS_AIM_CAM_ACTIVE() // //PRINTFLOAT(fReading) PRINTNL() // IF bOnTarget // DRAW_TIMER_HUD(100 + (900 - CEIL(fProx * 900.0)), 1000, "EPS4_B0") // ELSE // DRAW_TIMER_HUD(0, 1000, "EPS4_B0") // ENDIF // ENDIF ENDIF //-- Manage player body anims IF IS_CONTROL_PRESSED(PLAYER_CONTROL, INPUT_AIM) // Player is using device -> start body anim, and pause on first frame SET_PED_MAX_MOVE_BLEND_RATIO(PLAYER_PED_ID(), PEDMOVEBLENDRATIO_WALK) DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_JUMP) IF bLockAimPitch SET_GAMEPLAY_CAM_RELATIVE_PITCH(15) DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_LOOK_UD) ENDIF bPlayerUsedAim = TRUE ELSE IF IS_PLAYER_IN_FIRST_PERSON_CAMERA() bPlayerUsedAim = TRUE ENDIF // Player not using device -> kill body anim // IF IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(), "rcm_epsilonism4", "detector_pulls_forwards_loop") // STOP_ANIM_TASK(PLAYER_PED_ID(), "rcm_epsilonism4", "detector_pulls_forwards_loop", WALK_BLEND_OUT) // ENDIF ENDIF ENDPROC //PROC ATTEMPT_GRAB_DETECTOR() // gDetector.hObj = GET_CURRENT_PED_WEAPON_ENTITY_INDEX(PLAYER_PED_ID()) // gDetector.sRecentAnim = NO_RECENT_ANIM // //// IF DOES_ENTITY_EXIST(gDetector.hObj) //// PLAY_ENTITY_ANIM(gDetector.hObj, "detector_level1_prop", "rcm_epsilonism4", INSTANT_BLEND_IN, TRUE, FALSE, FALSE) //// gDetector.sRecentAnim = detector_level1_prop //// ENDIF //ENDPROC /// PURPOSE: /// Checks if the detector exists in the world /// RETURNS: /// True if the detector exists, False otherwise FUNC BOOL DOES_DETECTOR_EXIST() IF DOES_ENTITY_EXIST(gDetector.hObj) RETURN TRUE ENDIF RETURN FALSE ENDFUNC FUNC BOOL CHECK_FAIL_CONDITIONS_DURING_CUTSCENE() IF IS_ENTITY_DEAD(PLAYER_PED_ID()) QUEUE_MISSION_STAGE(MS_FAILED) g_mission.failReason = FAIL_REASON_PLAYER_DEAD g_mission.section = SECTION_CLEANUP RETURN TRUE ELIF IS_ENTITY_DEAD(epsilonianArray[ID_MARNIE].hPed) IF iCurrentRock < 2 // Only check this if we're not on the final cutscene - otherwise when we delete the ped, this will trigger and fail the mission! QUEUE_MISSION_STAGE(MS_FAILED) g_mission.failReason = FAIL_REASON_MARNIE_DEAD g_mission.section = SECTION_CLEANUP DEBUG_PRINTSTRING("Mission failed: Marnie dead") RETURN TRUE ENDIF ELIF IS_ENTITY_DEAD(epsilonianArray[ID_JIMMY].hPed) IF iCurrentRock < 2 // Only check this if we're not on the final cutscene - otherwise when we delete the ped, this will trigger and fail the mission! QUEUE_MISSION_STAGE(MS_FAILED) g_mission.failReason = FAIL_REASON_JIMMY_DEAD g_mission.section = SECTION_CLEANUP DEBUG_PRINTSTRING("Mission failed: Jimmy dead") RETURN TRUE ENDIF ELIF HAS_ENTITY_BEEN_DAMAGED_BY_ENTITY(epsilonianArray[ID_MARNIE].hPed, PLAYER_PED_ID(), TRUE) AND HAS_ENTITY_BEEN_DAMAGED_BY_WEAPON(epsilonianArray[ID_MARNIE].hPed, WEAPONTYPE_INVALID, GENERALWEAPON_TYPE_ANYWEAPON) QUEUE_MISSION_STAGE(MS_FAILED) g_mission.failReason = FAIL_REASON_MARNIE_INJURED g_mission.section = SECTION_CLEANUP DEBUG_PRINTSTRING("Mission failed: Marnie injured") RETURN TRUE ELIF HAS_ENTITY_BEEN_DAMAGED_BY_ENTITY(epsilonianArray[ID_JIMMY].hPed, PLAYER_PED_ID(), TRUE) AND HAS_ENTITY_BEEN_DAMAGED_BY_WEAPON(epsilonianArray[ID_JIMMY].hPed, WEAPONTYPE_INVALID, GENERALWEAPON_TYPE_ANYWEAPON) QUEUE_MISSION_STAGE(MS_FAILED) g_mission.failReason = FAIL_REASON_JIMMY_INJURED g_mission.section = SECTION_CLEANUP DEBUG_PRINTSTRING("Mission failed: Jimmy injured") RETURN TRUE ENDIF RETURN FALSE ENDFUNC /// PURPOSE: /// Update the animations on the player and detector depending on the direction the player is currently facing /// PARAMS: /// bIsPlayerFacingTarget - Whether the player is facing the rock or not PROC UPDATE_PLAYER_AND_DETECTOR_ANIMS(BOOL bIsPlayerFacingTarget) //-- Player body anims // IF IS_AIM_CAM_ACTIVE() // // // Player is using device -> start body anim, and pause on first frame // IF NOT IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(), "rcm_epsilonism4", "detector_pulls_forwards_loop") // TASK_PLAY_ANIM(PLAYER_PED_ID(), "rcm_epsilonism4", "detector_pulls_forwards_loop", 2, -2, -1, AF_SECONDARY|AF_UPPERBODY|AF_LOOPING)//|AF_DELAY_BLEND_WHEN_FINISHED) // ELSE // SET_ENTITY_ANIM_CURRENT_TIME(PLAYER_PED_ID(), "rcm_epsilonism4", "detector_pulls_forwards_loop", 0.0) // SET_ENTITY_ANIM_SPEED(PLAYER_PED_ID(), "rcm_epsilonism4", "detector_pulls_forwards_loop", 0.0) // ENDIF // // ELSE // // // Player not using device -> kill body anim // IF IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(), "rcm_epsilonism4", "detector_pulls_forwards_loop") // STOP_ANIM_TASK(PLAYER_PED_ID(), "rcm_epsilonism4", "detector_pulls_forwards_loop", WALK_BLEND_OUT) // ENDIF // // ENDIF // Stop player from being able to autovault things //SET_PED_RESET_FLAG(PLAYER_PED_ID(), PRF_DisablePlayerAutoVaulting, TRUE) //-- Detector anims IF bIsPlayerFacingTarget = TRUE // Player is facing target -> Keep running random anims on the detector IF DOES_DETECTOR_EXIST() // If there is no anim runnning on the detector, start one IF ARE_STRINGS_EQUAL(gDetector.sRecentAnim, "NO_RECENT_ANIM") OR NOT IS_ENTITY_PLAYING_ANIM(gDetector.hObj, "rcm_epsilonism4", gDetector.sRecentAnim) OR GET_ENTITY_ANIM_CURRENT_TIME(gDetector.hObj, "rcm_epsilonism4", gDetector.sRecentAnim) >= 0.98 // Choose one of the detector reaction anims based on distance to the target IF fReading > LVL3_DISTANCE gDetector.sRecentAnim = "detector_level3_prop" ELIF fReading > LVL2_DISTANCE gDetector.sRecentAnim = "detector_level2_prop" ELSE gDetector.sRecentAnim = "detector_level1_prop" ENDIF // Play the anim (no looping) #IF IS_DEBUG_BUILD IF bDebug_VerboseDetector DEBUG_PRINTSF("fReading: ", fReading) DEBUG_PRINTSTRING("PLAY_ENTITY_ANIM: ") DEBUG_PRINTSTRING(gDetector.sRecentAnim) DEBUG_PRINTSI("Time: ", GET_GAME_TIMER()) ENDIF #ENDIF PLAY_ENTITY_ANIM(gDetector.hObj, gDetector.sRecentAnim, "rcm_epsilonism4", FAST_BLEND_IN, FALSE, FALSE, FALSE) ENDIF ENDIF ELSE // Player is facing away -> Stop any detector anims IF DOES_DETECTOR_EXIST() // Check if an animation is currently playing, it will need to be stopped IF NOT ARE_STRINGS_EQUAL(gDetector.sRecentAnim, "NO_RECENT_ANIM") IF IS_ENTITY_PLAYING_ANIM(gDetector.hObj, "rcm_epsilonism4", gDetector.sRecentAnim, ANIM_SCRIPT) IF GET_ENTITY_ANIM_CURRENT_TIME(gDetector.hObj, "rcm_epsilonism4", gDetector.sRecentAnim) <= 0.05 // Stop the anim #IF IS_DEBUG_BUILD IF bDebug_VerboseDetector DEBUG_PRINTSTRING("STOP_ENTITY_ANIM:") DEBUG_PRINTSTRING(gDetector.sRecentAnim) DEBUG_PRINTSI("Time: ", GET_GAME_TIMER()) DEBUG_PRINTSTRING("IS_ENTITY_PLAYING_ANIM: ") DEBUG_PRINTBOOL(IS_ENTITY_PLAYING_ANIM(gDetector.hObj, "rcm_epsilonism4", gDetector.sRecentAnim, ANIM_SCRIPT)) DEBUG_PRINTSTRING("HAS_ENTITY_ANIM_FINISHED: ") DEBUG_PRINTBOOL(HAS_ENTITY_ANIM_FINISHED(gDetector.hObj, "rcm_epsilonism4", gDetector.sRecentAnim, ANIM_SCRIPT)) ENDIF #ENDIF STOP_ENTITY_ANIM(gDetector.hObj, gDetector.sRecentAnim, "rcm_epsilonism4", SLOW_BLEND_OUT) gDetector.sRecentAnim = "NO_RECENT_ANIM" ENDIF ENDIF ENDIF ENDIF ENDIF ENDPROC FUNC BOOL DO_MICHAEL_EXIT() IF IS_ENTITY_ALIVE(PLAYER_PED_ID()) IF CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY("Michael") IF iCurrentRock >= 2 DEBUG_PRINTSTRING("*** Forcing Michael's move state (end cutscene)") FORCE_PED_MOTION_STATE(PLAYER_PED_ID(), MS_ON_FOOT_IDLE, FALSE, FAUS_CUTSCENE_EXIT) RETURN TRUE ELSE DEBUG_PRINTSTRING("*** Forcing Michael's move state") IF GET_PEDS_CURRENT_WEAPON(PLAYER_PED_ID()) != weapon_Detector GIVE_WEAPON_TO_PED(PLAYER_PED_ID(), weapon_Detector, INFINITE_AMMO, TRUE) ENDIF FORCE_PED_MOTION_STATE(PLAYER_PED_ID(), MS_ON_FOOT_IDLE, FALSE, FAUS_CUTSCENE_EXIT) RETURN TRUE ENDIF ENDIF ENDIF RETURN FALSE ENDFUNC PROC DO_DETECTOR_EXIT() IF IS_ENTITY_ALIVE(DetectorCopy) IF CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY("Artefact_Detector") IF iCurrentRock < 2 DEBUG_PRINTSTRING("*** Detector exit") GIVE_WEAPON_OBJECT_TO_PED(DetectorCopy, PLAYER_PED_ID()) SAFE_DELETE_OBJECT(DetectorCopy) IF NOT DOES_ENTITY_EXIST(gDetector.hObj) DEBUG_PRINTSTRING("*** Recreating gDetector.hObj after cutscene...") gDetector.hObj = GET_CURRENT_PED_WEAPON_ENTITY_INDEX(PLAYER_PED_ID()) ENDIF ELSE DEBUG_PRINTSTRING("*** Detector exit (end cutscene)") SAFE_DELETE_OBJECT(DetectorCopy) ENDIF ENDIF ENDIF ENDPROC SEQUENCE_INDEX seqExit PROC DO_MARNIE_INTRO_EXIT() IF IS_ENTITY_ALIVE(epsilonianArray[ID_MARNIE].hPed) IF CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY("Marnie") SET_EPS_MOVE(epsilonianArray[ID_MARNIE], g_hDummyMarker_MarnieIntroForage) epsilonianArray[ID_MARNIE].state = EPS_ST_MOVE epsilonianArray[ID_MARNIE].mode = UPDATE_STATE IF epsilonianArray[ID_MARNIE].iAnimMarker <> -1 animMarkerArray[epsilonianArray[ID_MARNIE].iAnimMarker].bIsInUse = FALSE ENDIF epsilonianArray[ID_MARNIE].iAnimMarkeR = g_hDummyMarker_MarnieIntroForage TASK_GO_STRAIGHT_TO_COORD(epsilonianArray[ID_MARNIE].hPed, animMarkerArray[epsilonianArray[ID_MARNIE].iAnimMarker].vPos, PEDMOVE_WALK, DEFAULT_TIME_NEVER_WARP) FORCE_PED_MOTION_STATE(epsilonianArray[ID_MARNIE].hPed, MS_ON_FOOT_WALK, FALSE, FAUS_CUTSCENE_EXIT, TRUE) epsilonianArray[ID_MARNIE].bNotUsingNavmeshMove = TRUE DEBUG_PRINTSTRING("Done Marnie intro exit state") ENDIF ENDIF ENDPROC PROC DO_MARNIE_EXIT() IF IS_ENTITY_ALIVE(epsilonianArray[ID_MARNIE].hPed) IF CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY("Marnie") IF iCurrentRock >= 2 IF IS_ENTITY_ALIVE(sRCLauncherDataLocal.pedID[ID_MARNIE]) AND IS_VEHICLE_OK(Eps_Vehicle) OPEN_SEQUENCE_TASK(seqExit) //TASK_FOLLOW_NAV_MESH_TO_COORD(NULL, GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(sRCLauncherDataLocal.pedID[ID_MARNIE], <<0, 4, 0>>), PEDMOVEBLENDRATIO_WALK, DEFAULT, DEFAULT, ENAV_NO_STOPPING|ENAV_GO_FAR_AS_POSSIBLE_IF_TARGET_NAVMESH_NOT_LOADED) TASK_WARP_PED_INTO_VEHICLE(NULL, Eps_Vehicle, VS_DRIVER) //TASK_ENTER_VEHICLE(NULL, Eps_Vehicle, DEFAULT, VS_DRIVER, PEDMOVEBLENDRATIO_WALK, ECF_WARP_IF_DOOR_IS_BLOCKED|ECF_RESUME_IF_INTERRUPTED) //TASK_PAUSE(NULL, 4500) TASK_VEHICLE_DRIVE_TO_COORD(NULL, Eps_Vehicle, <<1743.33, 4962.18, 45.16>>, 20, DRIVINGSTYLE_NORMAL, BISON, DRIVINGMODE_AVOIDCARS_STOPFORPEDS_OBEYLIGHTS, 5, -1) TASK_VEHICLE_DRIVE_WANDER(NULL, Eps_Vehicle, 30, DRIVINGMODE_STOPFORCARS_STRICT) CLOSE_SEQUENCE_TASK(seqExit) TASK_PERFORM_SEQUENCE(sRCLauncherDataLocal.pedID[ID_MARNIE], seqExit) CLEAR_SEQUENCE_TASK(seqExit) DEBUG_PRINTSTRING("Did Marnie pass exit") ENDIF ELSE TASK_FOLLOW_NAV_MESH_TO_COORD(sRCLauncherDataLocal.pedID[ID_MARNIE], GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(sRCLauncherDataLocal.pedID[ID_MARNIE], <<0, 7, 0>>), PEDMOVEBLENDRATIO_WALK, DEFAULT, DEFAULT, ENAV_NO_STOPPING|ENAV_GO_FAR_AS_POSSIBLE_IF_TARGET_NAVMESH_NOT_LOADED) DEBUG_PRINTSTRING("Did Marnie regular exit") ENDIF FORCE_PED_MOTION_STATE(epsilonianArray[ID_MARNIE].hPed, MS_ON_FOOT_WALK, FALSE, FAUS_CUTSCENE_EXIT) ENDIF ENDIF ENDPROC PROC DO_JIMMY_INTRO_EXIT() IF IS_ENTITY_ALIVE(epsilonianArray[ID_JIMMY].hPed) IF CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY("Jimmy_Boston") FLOAT fZ GET_GROUND_Z_FOR_3D_COORD(<<1829.80, 4693.48, 38.50>>, fZ) SET_ENTITY_COORDS(epsilonianArray[ID_JIMMY].hPed, <<1829.80, 4693.48, fZ>>) //FORCE_PED_MOTION_STATE(epsilonianArray[ID_MARNIE].hPed, MS_ON_FOOT_IDLE, FALSE, FAUS_CUTSCENE_EXIT, TRUE) ENDIF ENDIF ENDPROC PROC DO_JIMMY_EXIT() IF IS_ENTITY_ALIVE(epsilonianArray[ID_JIMMY].hPed) IF CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY("Jimmy_Boston") IF iCurrentRock >= 2 IF IS_ENTITY_ALIVE(sRCLauncherDataLocal.pedID[ID_JIMMY]) AND IS_VEHICLE_OK(Eps_Vehicle) OPEN_SEQUENCE_TASK(seqExit) //TASK_FOLLOW_NAV_MESH_TO_COORD(NULL, GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(sRCLauncherDataLocal.pedID[ID_JIMMY], <<0, 2, 0>>), PEDMOVEBLENDRATIO_WALK, DEFAULT, DEFAULT, ENAV_NO_STOPPING|ENAV_GO_FAR_AS_POSSIBLE_IF_TARGET_NAVMESH_NOT_LOADED) TASK_WARP_PED_INTO_VEHICLE(NULL, Eps_Vehicle, VS_FRONT_RIGHT) //TASK_ENTER_VEHICLE(NULL, Eps_Vehicle, DEFAULT, VS_FRONT_RIGHT, PEDMOVEBLENDRATIO_WALK, ECF_WARP_IF_DOOR_IS_BLOCKED|ECF_RESUME_IF_INTERRUPTED) CLOSE_SEQUENCE_TASK(seqExit) TASK_PERFORM_SEQUENCE(sRCLauncherDataLocal.pedID[ID_JIMMY], seqExit) CLEAR_SEQUENCE_TASK(seqExit) DEBUG_PRINTSTRING("Did Jimmy pass exit") ENDIF ELSE TASK_GO_STRAIGHT_TO_COORD(sRCLauncherDataLocal.pedID[ID_JIMMY], <<1764.0890, 4665.8794, 42.3031>>, PEDMOVEBLENDRATIO_WALK) DEBUG_PRINTSTRING("Did Jimmy regular exit") ENDIF FORCE_PED_MOTION_STATE(epsilonianArray[ID_JIMMY].hPed, MS_ON_FOOT_WALK, FALSE, FAUS_CUTSCENE_EXIT) ENDIF ENDIF ENDPROC // =========================================================================================================== // Termination // =========================================================================================================== // ----------------------------------------------------------------------------------------------------------- // Script Cleanup // ----------------------------------------------------------------------------------------------------------- /// PURPOSE: /// Clean up text in the script PROC Script_TextCleanup() // Could this be included in normal clean up? STOP_SCRIPTED_CONVERSATION(FALSE) CLEAR_PRINTS() IF IS_THIS_HELP_MESSAGE_BEING_DISPLAYED("EPS4_T0") OR IS_THIS_HELP_MESSAGE_BEING_DISPLAYED("EPS4_T1") CLEAR_HELP(TRUE) ENDIF ENDPROC /// PURPOSE: /// General script cleanup function PROC Script_Cleanup() // Ensure launcher is cleaned up RC_CLEANUP_LAUNCHER() // If the mission was triggered then additional mission cleanup will be required. IF (Random_Character_Cleanup_If_Triggered()) DEBUG_PRINTSTRING("...Random Character Script was triggered so additional cleanup required") PRINTNL() ENDIF // Cleanup scene entities created by the RC launcher //RC_CleanupSceneEntities(sRCLauncherDataLocal, FALSE) IF IS_PED_UNINJURED(PLAYER_PED_ID()) // Remove gadget REMOVE_WEAPON_FROM_PED(PLAYER_PED_ID(), weapon_Detector) SET_CURRENT_PED_WEAPON(PLAYER_PED_ID(), WEAPONTYPE_UNARMED, TRUE) CLEAR_PED_TASKS(PLAYER_PED_ID()) SET_PED_CAPSULE(PLAYER_PED_ID(), 0) ENDIF IF IS_NEW_LOAD_SCENE_ACTIVE() NEW_LOAD_SCENE_STOP() ENDIF REMOVE_GRASS_CULL_SPHERE(grassCull) IF IS_ENTITY_ALIVE(epsilonianArray[ID_MARNIE].hPed) AND IS_ENTITY_ALIVE(epsilonianArray[ID_JIMMY].hPed) IF IS_PED_IN_GROUP(epsilonianArray[ID_MARNIE].hPed) REMOVE_PED_FROM_GROUP(epsilonianArray[ID_MARNIE].hPed) ELIF IS_PED_IN_GROUP(epsilonianArray[ID_JIMMY].hPed) REMOVE_PED_FROM_GROUP(epsilonianArray[ID_JIMMY].hPed) ENDIF ENDIF SAFE_RELEASE_PED(epsilonianArray[ID_MARNIE].hPed, TRUE, TRUE) SAFE_RELEASE_PED(epsilonianArray[ID_JIMMY].hPed, TRUE, TRUE) RELEASE_NAMED_RENDERTARGET("digiscanner") REMOVE_SCENARIO_BLOCKING_AREA(mScenarioBlocker) REMOVE_SCENARIO_BLOCKING_AREA(mScenarioBlockerPicnic) REMOVE_NAVMESH_BLOCKING_OBJECT(iNavBlockerBush1) REMOVE_NAVMESH_BLOCKING_OBJECT(iNavBlockerBush2) REMOVE_NAVMESH_BLOCKING_OBJECT(iNavBlockerBush3) IF IS_AUDIO_SCENE_ACTIVE("EPSILONISM_04_MIX") DEBUG_PRINTSTRING("Stopping dynamic mix EPSILONISM_04_MIX") STOP_AUDIO_SCENE("EPSILONISM_04_MIX") ENDIF #IF IS_DEBUG_BUILD CLEANUP_EPS4_WIDGETS() #ENDIF TERMINATE_THIS_THREAD() ENDPROC // ----------------------------------------------------------------------------------------------------------- // Script Pass // ----------------------------------------------------------------------------------------------------------- PROC Script_Passed() HIDE_HUD_COMPONENT_THIS_FRAME(NEW_HUD_WEAPON_ICON) IF bPlayerUsedAim = FALSE INFORM_STAT_SYSTEM_OF_BOOL_STAT_HAPPENED(EP4_ARTIFACT_DETECTOR_USED) ENDIF STOP_DETECTOR() Script_TextCleanup() DISABLE_CELLPHONE(FALSE) ADD_CONTACT_TO_PHONEBOOK(CHAR_JIMMY_BOSTON, MICHAEL_BOOK) Random_Character_Passed(CP_RAND_C_EPS4) // Reset donations - pity the fool who has donated more than asked for before this point.. CPRINTLN(DEBUG_RANDOM_CHAR, "Resetting donation to Epsilon Program for new mission request.") g_savedGlobals.sRandomChars.g_iCurrentEpsilonPayment = 0 IF NOT IS_REPEAT_PLAY_ACTIVE() WHILE NOT REGISTER_EMAIL_FROM_CHARACTER_TO_PLAYER(EMAIL_EPSILON4_DONATE, CT_AMBIENT, BIT_MICHAEL, CHAR_MARNIE, 30000, 10000) WAIT(0) ENDWHILE CPRINTLN(DEBUG_RANDOM_CHAR, "Queued $10,000 donation reminder email") ENDIF // Wait 1 second before doing the holster animation, then do it, then clean up the script REQUEST_ANIM_DICT("weapons@holster_1h") WHILE GET_PEDS_CURRENT_WEAPON(PLAYER_PED_ID()) = weapon_Detector WAIT(0) HIDE_HUD_COMPONENT_THIS_FRAME(NEW_HUD_WEAPON_ICON) IF HAS_ANIM_DICT_LOADED("weapons@holster_1h") IF NOT IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(), "weapons@holster_1h", "holster") TASK_PLAY_ANIM(PLAYER_PED_ID(), "weapons@holster_1h", "holster") ELSE IF GET_ENTITY_ANIM_CURRENT_TIME(PLAYER_PED_ID(), "weapons@holster_1h", "holster") >= 0.5 SET_CURRENT_PED_WEAPON(PLAYER_PED_ID(), WEAPONTYPE_UNARMED, TRUE) ENDIF ENDIF ENDIF ENDWHILE //Set epsilon step stat INT iCurrent STAT_GET_INT(NUM_EPSILON_STEP,iCurrent) IF iCurrent < 12 STAT_SET_INT(NUM_EPSILON_STEP,12) SET_ACHIEVEMENT_PROGRESS_SAFE(ENUM_TO_INT(ACH20),12) CPRINTLN(debug_dan,"Epsilon progress:",12) ENDIF Script_Cleanup() ENDPROC //******************************************************************************************************************* //******************************************************************************************************************* PROC STAGE_LEADIN() // Disable controls and exit current vehicle RC_PLAYER_TRIGGER_SCENE_LOCK_IN() IF g_mission.bSyncForSkip = TRUE RC_START_Z_SKIP() DEBUG_PRINTSTRING("SKIP: Doing sync for leadin skip") RC_END_Z_SKIP() g_mission.bSyncForSkip = FALSE ENDIF IF g_mission.section = SECTION_SETUP iPhaseTimer = GET_GAME_TIMER() IF NOT IS_REPEAT_PLAY_ACTIVE() AND IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<1826.621216,4698.734375,41.368622>>, <<1831.157593,4680.191406,32.426258>>, 16.50) DEBUG_PRINTSTRING("Doing setup for leadin") ADD_PED_FOR_DIALOGUE(pedsForConversation, 4, sRCLauncherDataLocal.pedID[ID_MARNIE], "MARNIE") IF LOAD_ANIMS() // Loops here until anims are loaded g_mission.section = SECTION_RUNNING ENDIF ELSE DEBUG_PRINTSTRING("Skipping setup for leadin (repeat play/wrong area)") g_mission.section = SECTION_RUNNING ENDIF ENDIF IF g_mission.section = SECTION_RUNNING IF (GET_GAME_TIMER() - iPhaseTimer) > 1250 PLAY_SOUND_FROM_COORD(-1, "IDLE_BEEP_NPC", <<1827.06, 4700.52, 39.16>>, "EPSILONISM_04_SOUNDSET") iPhaseTimer = GET_GAME_TIMER() ENDIF IF NOT IS_REPEAT_PLAY_ACTIVE() // Don't do the leadin if we're on a repeat-play, just go into the cutscene AND IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<1826.621216,4698.734375,41.368622>>, <<1831.157593,4680.191406,32.426258>>, 16.50) IF GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), sRCLauncherDataLocal.pedID[ID_MARNIE]) >= 3.0 IF NOT IS_GAMEPLAY_HINT_ACTIVE() IF NOT bDonePushIn IF IS_ENTITY_ALIVE(sRCLauncherDataLocal.pedID[ID_MARNIE]) SET_GAMEPLAY_ENTITY_HINT(sRCLauncherDataLocal.pedID[ID_MARNIE], <<0,0,0.2>>, TRUE, 30000) SET_GAMEPLAY_HINT_FOV(fHintFov) SET_GAMEPLAY_HINT_FOLLOW_DISTANCE_SCALAR(fHintFollow) SET_GAMEPLAY_HINT_BASE_ORBIT_PITCH_OFFSET(fHintPitchOrbit) SET_GAMEPLAY_HINT_CAMERA_RELATIVE_SIDE_OFFSET(fHintSide) SET_GAMEPLAY_HINT_CAMERA_RELATIVE_VERTICAL_OFFSET(fHintVert) SET_GAMEPLAY_HINT_CAMERA_BLEND_TO_FOLLOW_PED_MEDIUM_VIEW_MODE(TRUE) IF IS_ENTITY_ALIVE(PLAYER_PED_ID()) OPEN_SEQUENCE_TASK(seq) TASK_LOOK_AT_ENTITY(NULL, sRCLauncherDataLocal.pedID[ID_MARNIE], 15000) TASK_FOLLOW_NAV_MESH_TO_COORD(NULL, <<1827.34, 4697.22, 38.02>>, PEDMOVEBLENDRATIO_WALK, DEFAULT_TIME_BEFORE_WARP, DEFAULT_NAVMESH_RADIUS, ENAV_NO_STOPPING) TASK_TURN_PED_TO_FACE_ENTITY(NULL, sRCLauncherDataLocal.pedID[ID_MARNIE]) CLOSE_SEQUENCE_TASK(seq) TASK_PERFORM_SEQUENCE(PLAYER_PED_ID(), seq) CLEAR_SEQUENCE_TASK(seq) SET_PLAYER_CONTROL(PLAYER_ID(), FALSE) ENDIF bDonePushIn = TRUE ENDIF ENDIF ELSE STOP_GAMEPLAY_HINT_BEING_CANCELLED_THIS_UPDATE(TRUE) ENDIF ELSE bDonePushIn = TRUE // Stop trying to do the push in ENDIF IF NOT bLeadInPlayed IF IS_PED_UNINJURED(sRCLauncherDataLocal.pedID[ID_MARNIE]) AND NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED() TASK_LOOK_AT_ENTITY(sRCLauncherDataLocal.pedID[ID_MARNIE], PLAYER_PED_ID(), -1, SLF_WIDEST_PITCH_LIMIT|SLF_WIDEST_YAW_LIMIT) TASK_PLAY_ANIM(sRCLauncherDataLocal.pedID[ID_MARNIE], "rcm_epsilonism4leadinout", "ep_4_rcm_leadin_marnie",NORMAL_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_HOLD_LAST_FRAME) // Marnie REMOVE_CUTSCENE() REQUEST_CUTSCENE_WITH_PLAYBACK_LIST("EP_4_RCM_CONCAT", CS_SECTION_2) DEBUG_PRINTSTRING("Done Marnie leadin anim - request concat cutscene") bLeadInPlayed = TRUE ENDIF ELSE IF IS_PED_UNINJURED(sRCLauncherDataLocal.pedID[ID_MARNIE]) IF IS_ENTITY_PLAYING_ANIM(sRCLauncherDataLocal.pedID[ID_MARNIE], "rcm_epsilonism4leadinout", "ep_4_rcm_leadin_marnie") IF GET_ENTITY_ANIM_CURRENT_TIME(sRCLauncherDataLocal.pedID[ID_MARNIE], "rcm_epsilonism4leadinout", "ep_4_rcm_leadin_marnie") > 0.25 IF NOT bLeadInConvo IF CREATE_CONVERSATION(pedsForConversation, "EPS4AUD", "ESP4_RCL", CONV_PRIORITY_HIGH) DEBUG_PRINTSTRING("Leadin convo done") bLeadInConvo = TRUE ENDIF ENDIF ENDIF IF GET_ENTITY_ANIM_CURRENT_TIME(sRCLauncherDataLocal.pedID[ID_MARNIE], "rcm_epsilonism4leadinout", "ep_4_rcm_leadin_marnie") > 0.95 DEBUG_PRINTSTRING("Leadin done, launch cutscene") QUEUE_MISSION_STAGE(MS_INTRO) g_mission.section = SECTION_CLEANUP ENDIF IF GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), sRCLauncherDataLocal.pedID[ID_MARNIE]) <= 1.5 // Stop the player if they get too close SET_PLAYER_CONTROL(PLAYER_ID(), FALSE) CLEAR_PED_TASKS(PLAYER_PED_ID()) ENDIF ENDIF ENDIF ENDIF ELSE DEBUG_PRINTSTRING("Replay in progress/wrong area, skipping leadin") QUEUE_MISSION_STAGE(MS_INTRO) g_mission.section = SECTION_CLEANUP ENDIF ENDIF IF g_mission.section = SECTION_CLEANUP DEBUG_PRINTSTRING("Doing leadin cleanup and progressing") CHANGE_MISSION_STAGE() ENDIF ENDPROC //STAGE: INTRO /// PURPOSE: /// Main loop for the intro stage PROC STAGE_INTRO() IF CAN_REQUEST_ASSETS_FOR_CUTSCENE_ENTITY() DEBUG_PRINTSTRING("Can request assets for cutscene entity in Eps 4") SET_CUTSCENE_PED_PROP_VARIATION("Jimmy_Boston", ANCHOR_EYES, 0) IF IS_ENTITY_ALIVE(PLAYER_PED_ID()) SET_CUTSCENE_PED_COMPONENT_VARIATION_FROM_PED_SAFE("Michael", PLAYER_PED_ID()) ENDIF ENDIF IF g_mission.bSyncForSkip = TRUE RC_START_Z_SKIP() REMOVE_CUTSCENE() DEBUG_PRINTSTRING("SKIP: Doing sync for intro skip") IF NOT IS_REPEAT_PLAY_ACTIVE() RC_END_Z_SKIP() ENDIF g_mission.bSyncForSkip = FALSE ENDIF IF g_mission.section = SECTION_SETUP // b* 2363991 - moved to inside SECTION_SETUP IF NOT IS_CUTSCENE_ACTIVE() REQUEST_CUTSCENE("ep_4_rcm_concat") ENDIF // Load/start cutscene DEBUG_PRINTSTRING("In Intro setup, waiting for cutscene to be ready...") IF RC_IS_CUTSCENE_OK_TO_START() DEBUG_PRINTSTRING("Starting intro cutscene...") IF IS_PED_UNINJURED(PLAYER_PED_ID()) REGISTER_ENTITY_FOR_CUTSCENE(PLAYER_PED_ID(), "Michael", CU_ANIMATE_EXISTING_SCRIPT_ENTITY) // Player ENDIF IF IS_PED_UNINJURED(sRCLauncherDataLocal.pedID[ID_MARNIE]) REGISTER_ENTITY_FOR_CUTSCENE(sRCLauncherDataLocal.pedID[ID_MARNIE], "Marnie", CU_ANIMATE_EXISTING_SCRIPT_ENTITY) // Marnie ENDIF IF IS_PED_UNINJURED(sRCLauncherDataLocal.pedID[ID_JIMMY]) FREEZE_ENTITY_POSITION(sRCLauncherDataLocal.pedID[ID_JIMMY], FALSE) IF IS_ENTITY_ALIVE(GET_CURRENT_PED_WEAPON_ENTITY_INDEX(sRCLauncherDataLocal.pedID[ID_JIMMY])) DetectorCopy = CREATE_WEAPON_OBJECT_FROM_PED_WEAPON_WITH_COMPONENTS(sRCLauncherDataLocal.pedID[ID_JIMMY], WEAPONTYPE_DIGISCANNER) REGISTER_ENTITY_FOR_CUTSCENE(DetectorCopy, "Artefact_Detector", CU_ANIMATE_EXISTING_SCRIPT_ENTITY) ENDIF REGISTER_ENTITY_FOR_CUTSCENE(sRCLauncherDataLocal.pedID[ID_JIMMY], "Jimmy_Boston", CU_ANIMATE_EXISTING_SCRIPT_ENTITY) // Jimmy ENDIF IF IS_PED_UNINJURED(PLAYER_PED_ID()) REGISTER_ENTITY_FOR_CUTSCENE(PLAYER_PED_ID(), "Michael", CU_ANIMATE_EXISTING_SCRIPT_ENTITY) // Jimmy ENDIF TRIGGER_MUSIC_EVENT("EPS4_START") // Ensure lead-in blip is cleaned up... RC_CLEANUP_LAUNCHER() REPLAY_START_EVENT(REPLAY_IMPORTANCE_LOW) // Start cutscene START_CUTSCENE() WAIT(0) STOP_GAMEPLAY_HINT() RC_END_Z_SKIP(TRUE, TRUE, FALSE) RESOLVE_VEHICLES_INSIDE_ANGLED_AREA_WITH_SIZE_LIMIT(<<1833.393188,4703.848633,32.502178>>, <<1819.368286,4693.412598,43.891628>>, 18.0, << 1816.55, 4683.33, 37.75 >>, 339.76, GET_DEFAULT_ALLOWABLE_VEHICLE_SIZE_VECTOR()) RC_START_CUTSCENE_MODE(<<1812, 4697, 39.1>>, TRUE, FALSE, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT) WHILE NOT LOAD_ASSETS() WAIT(0) ENDWHILE DEBUG_PRINTSTRING("Loaded all assets! Moving to intro run loop...") g_mission.section = SECTION_RUNNING ENDIF ENDIF IF g_mission.section = SECTION_RUNNING FORCE_NOT_FOUND_SCREEN_ON_DETECTOR() IF g_mission.bRequestJSkip STOP_CUTSCENE() QUEUE_MISSION_STAGE(MS_FINDROCK) g_mission.section = SECTION_CLEANUP ELIF g_mission.bRequestCpSkip STOP_CUTSCENE() g_mission.section = SECTION_CLEANUP // b* 2363991 - changed to is cutscene playing not ACTIVE ELIF NOT IS_CUTSCENE_PLAYING() // IS_CUTSCENE_ACTIVE() // Wait for cutscene to end SET_GAMEPLAY_CAM_RELATIVE_PITCH() SET_GAMEPLAY_CAM_RELATIVE_HEADING() QUEUE_MISSION_STAGE(MS_FINDROCK) g_mission.section = SECTION_CLEANUP ENDIF IF WAS_CUTSCENE_SKIPPED() SET_GAMEPLAY_CAM_RELATIVE_PITCH() SET_GAMEPLAY_CAM_RELATIVE_HEADING() ENDIF IF IS_ENTITY_ALIVE(PLAYER_PED_ID()) IF CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY("Michael") DEBUG_PRINTSTRING("*** Forcing Michael's move state") SAFE_TELEPORT_ENTITY(PLAYER_PED_ID(), <<1827.1611, 4698.6445, 38.0940>>, 184.1384) GIVE_WEAPON_TO_PED(PLAYER_PED_ID(), weapon_Detector, INFINITE_AMMO, TRUE) //FORCE_PED_MOTION_STATE(PLAYER_PED_ID(), MS_ON_FOOT_IDLE, FALSE, FAUS_DEFAULT) //FORCE_PED_AI_AND_ANIMATION_UPDATE(PLAYER_PED_ID()) //SET_GAMEPLAY_CAM_RELATIVE_PITCH() //SET_GAMEPLAY_CAM_RELATIVE_HEADING() ENDIF ENDIF IF CAN_SET_EXIT_STATE_FOR_CAMERA() REPLAY_STOP_EVENT() DEBUG_PRINTSTRING("*** Teleport Mike") SET_GAMEPLAY_CAM_RELATIVE_PITCH() SET_GAMEPLAY_CAM_RELATIVE_HEADING() SAFE_TELEPORT_ENTITY(PLAYER_PED_ID(), <<1827.1611, 4698.6445, 38.0940>>, 184.1384) ENDIF DO_MARNIE_INTRO_EXIT() DO_JIMMY_INTRO_EXIT() IF IS_ENTITY_ALIVE(DetectorCopy) IF CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY("Artefact_Detector") GIVE_WEAPON_OBJECT_TO_PED(DetectorCopy, PLAYER_PED_ID()) SAFE_DELETE_OBJECT(DetectorCopy) ENDIF ENDIF // IF CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY("Jimmy_Boston") // IF IS_ENTITY_ALIVE(epsilonianArray[ID_JIMMY].hPed) // SET_ENTITY_COORDS(epsilonianArray[ID_JIMMY].hPed, << 1825.0122, 4697.2227, 38.17 >>) // SET_ENTITY_HEADING(epsilonianArray[ID_JIMMY].hPed, 234.0331) // ENDIF // ENDIF // IF CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY("Marnie") // IF IS_ENTITY_ALIVE(epsilonianArray[ID_MARNIE].hPed) // SET_ENTITY_COORDS(epsilonianArray[ID_MARNIE].hPed, << 1825.0122, 4697.2227, 38.17 >>) // SET_ENTITY_HEADING(epsilonianArray[ID_MARNIE].hPed, 234.0331) // ENDIF // ENDIF ENDIF IF g_mission.section = SECTION_CLEANUP DEBUG_PRINTSTRING("Doing intro cleanup and progressing") IF NOT IS_CUTSCENE_PLAYING() iCurrentRock = 0 RC_END_CUTSCENE_MODE(TRUE, FALSE) RC_SET_ENTITY_PROOFS_FOR_CUTSCENE(sRCLauncherDataLocal, FALSE) CHANGE_MISSION_STAGE() ENDIF ENDIF ENDPROC //******************************************************************************************************************* //******************************************************************************************************************* /// PURPOSE: /// Main loop for the Find Rock stages of the mission PROC STAGE_FINDROCK() SET_ALL_RANDOM_PEDS_FLEE_THIS_FRAME(PLAYER_ID()) INT iEps IF g_mission.bSyncForSkip = TRUE RC_START_Z_SKIP() WAIT(0) WHILE NOT LOAD_ASSETS() WAIT(0) ENDWHILE IF IS_CUTSCENE_ACTIVE() STOP_CUTSCENE_IMMEDIATELY() REMOVE_CUTSCENE() ENDIF WHILE IS_CUTSCENE_ACTIVE() WAIT(0) ENDWHILE IF IS_REPLAY_BEING_SET_UP() END_REPLAY_SETUP() ENDIF IF iCurrentRock = 0 IF NOT IS_REPLAY_BEING_SET_UP() SET_ENTITY_COORDS(PLAYER_PED_ID(), vPos_PlayerReset) SET_ENTITY_HEADING(PLAYER_PED_ID(), fRot_PlayerReset) ENDIF SET_EPS_IDLE(epsilonianArray[ID_JIMMY], TRUE) SET_EPS_IDLE(epsilonianArray[ID_MARNIE], TRUE) // Got to do this here for the skip in case we don't watch the intro IF IS_PED_UNINJURED(epsilonianArray[ID_JIMMY].hPed) FREEZE_ENTITY_POSITION(sRCLauncherDataLocal.pedID[ID_JIMMY], FALSE) SET_ENTITY_COORDS(epsilonianArray[ID_JIMMY].hPed, << 1829.75, 4693.50, 38.51 >>) SET_ENTITY_HEADING(epsilonianArray[ID_JIMMY].hPed, 27.46) FLOAT groundZ VECTOR vTemp = GET_ENTITY_COORDS(epsilonianArray[ID_JIMMY].hPed) GET_GROUND_Z_FOR_3D_COORD(<< 1829.75, 4693.50, 38.51 >>, groundZ) SET_ENTITY_COORDS(epsilonianArray[ID_JIMMY].hPed, <>) DEBUG_PRINTSTRING("Setting Jimmy position (0)") //TASK_FOLLOW_NAV_MESH_TO_COORD(epsilonianArray[ID_JIMMY].hPed, << 1826.2458, 4696.5059, 38.1187 >>, PEDMOVE_WALK, DEFAULT_TIME_BEFORE_WARP) ENDIF IF IS_PED_UNINJURED(epsilonianArray[ID_MARNIE].hPed) SET_ENTITY_COORDS(epsilonianArray[ID_MARNIE].hPed, << 1827.32, 4692.59, 38.53 >>) SET_ENTITY_HEADING(epsilonianArray[ID_MARNIE].hPed, 171.22) DEBUG_PRINTSTRING("Setting Marnie position (0)") ENDIF ELIF iCurrentRock = 1 SET_ENTITY_COORDS(PLAYER_PED_ID(), <<1754.6337, 4675.7886, 42.9068>>) SET_ENTITY_HEADING(PLAYER_PED_ID(), 293.2275) IF IS_PED_UNINJURED(epsilonianArray[ID_JIMMY].hPed) SET_ENTITY_COORDS(epsilonianArray[ID_JIMMY].hPed, <<1758.5857, 4670.0854, 42.6276 >>) SET_ENTITY_HEADING(epsilonianArray[ID_JIMMY].hPed, 262.4368) DEBUG_PRINTSTRING("Setting Jimmy position (1)") ENDIF IF IS_PED_UNINJURED(epsilonianArray[ID_MARNIE].hPed) SET_ENTITY_COORDS(epsilonianArray[ID_MARNIE].hPed, << 1759.9169, 4683.5840, 42.7266 >>) SET_ENTITY_HEADING(epsilonianArray[ID_MARNIE].hPed, 148.3211) DEBUG_PRINTSTRING("Setting Marnie position (1)") ENDIF ELIF iCurrentRock = 2 SET_ENTITY_COORDS(PLAYER_PED_ID(), <<1758.4542, 4829.4307, 39.7290>>) SET_ENTITY_HEADING(PLAYER_PED_ID(), 168.2012) IF IS_PED_UNINJURED(epsilonianArray[ID_MARNIE].hPed) SET_ENTITY_COORDS(epsilonianArray[ID_MARNIE].hPed, << 1755.0052, 4827.3291, 40.0736 >>) SET_ENTITY_HEADING(epsilonianArray[ID_MARNIE].hPed, 169.6486) DEBUG_PRINTSTRING("Setting Marnie position (2)") ENDIF ENDIF WAIT(750) RC_END_Z_SKIP() g_mission.bSyncForSkip = FALSE ENDIF IF g_mission.section = SECTION_SETUP DEBUG_PRINTSI("Doing setup for FindRock section:", iCurrentRock) // Clear buddy tasks and state immediately SET_EPS_IDLE(epsilonianArray[ID_JIMMY], FALSE) //SET_EPS_IDLE(epsilonianArray[ID_MARNIE], FALSE) bFollowerDoingIdle = FALSE bStillOnTarget = FALSE epsKnockedOver = FALSE iFoundWaitTimer = -1 iNonFollowerCloseLines = 0 iNonFollowerCloseLines1 = 0 iNonFollowerCloseLinesTimer = GET_GAME_TIMER() iFollowMessingAroundTimer = GET_GAME_TIMER() iAimPromptLines = 0 // IF IS_PED_UNINJURED(PLAYER_PED_ID()) // // Reset the player capsule // SET_PED_CAPSULE(PLAYER_PED_ID(), 0) // bCapsuleResized = FALSE // ENDIF // Set initial positions/actions for player/buddies for each stage IF iCurrentRock = 0 IF IS_PED_UNINJURED(PLAYER_PED_ID()) IF GET_PEDS_CURRENT_WEAPON(PLAYER_PED_ID()) != weapon_Detector GIVE_WEAPON_TO_PED(PLAYER_PED_ID(), weapon_Detector, INFINITE_AMMO, TRUE) ENDIF DISABLE_CELLPHONE(TRUE) ENDIF IF IS_PED_UNINJURED(epsilonianArray[ID_JIMMY].hPed) REMOVE_WEAPON_FROM_PED(epsilonianArray[ID_JIMMY].hPed, weapon_Detector) // Make sure Jimmy definitely doesn't have the detector TASK_FOLLOW_NAV_MESH_TO_COORD(epsilonianArray[ID_JIMMY].hPed, << 1826.2458, 4696.5059, 38.1187 >>, PEDMOVE_WALK, DEFAULT_TIME_BEFORE_WARP, 0.1) ENDIF SET_EPS_FOLLOW(epsilonianArray[ID_JIMMY], TRUE) //SET_EPS_MOVE(epsilonianArray[ID_MARNIE]) // SET_GAMEPLAY_CAM_RELATIVE_HEADING(45) // SET_GAMEPLAY_CAM_RELATIVE_PITCH(-15) iCurrentMaxGoodLines = MAX_JGOOD_LINES iCurrentMaxBadLines = MAX_JBAD_LINES iSaidBadLines = 0 iSaidGoodLines = 0 WHILE IS_CUTSCENE_ACTIVE() WAIT(0) // Need to wait for the cutscene to completely finish before requesting the next one ENDWHILE ELIF iCurrentRock = 1 IF IS_PED_UNINJURED(PLAYER_PED_ID()) IF GET_PEDS_CURRENT_WEAPON(PLAYER_PED_ID()) != weapon_Detector GIVE_WEAPON_TO_PED(PLAYER_PED_ID(), weapon_Detector, INFINITE_AMMO, TRUE) DISABLE_CELLPHONE(TRUE) ENDIF ENDIF SET_EPS_FOLLOW(epsilonianArray[ID_MARNIE], FALSE) SET_EPS_MOVE(epsilonianArray[ID_JIMMY], g_hDummyMarker_Piss) iCurrentMaxGoodLines = MAX_MGOOD_LINES iCurrentMaxBadLines = MAX_MBAD_LINES iSaidBadLines = 0 iSaidGoodLines = 0 WHILE IS_CUTSCENE_ACTIVE() WAIT(0) // Need to wait for the cutscene to completely finish before requesting the next one ENDWHILE ELIF iCurrentRock = 2 IF IS_PED_UNINJURED(PLAYER_PED_ID()) IF GET_PEDS_CURRENT_WEAPON(PLAYER_PED_ID()) != weapon_Detector GIVE_WEAPON_TO_PED(PLAYER_PED_ID(), weapon_Detector, INFINITE_AMMO, TRUE) DISABLE_CELLPHONE(TRUE) ENDIF ENDIF SET_EPS_MOVE(epsilonianArray[ID_MARNIE], g_hMarker_MarnieAngry) SET_EPS_WARP_TO_MARKER(epsilonianArray[ID_JIMMY], g_hDummyMarker_Dance) iCurrentMaxGoodLines = MAX_PGOOD_LINES iCurrentMaxBadLines = MAX_PBAD_LINES iSaidBadLines = 0 iSaidGoodLines = 0 WHILE IS_CUTSCENE_ACTIVE() WAIT(0) // Need to wait for the cutscene to completely finish before requesting the next one ENDWHILE ENDIF // Setup dialogue participants ADD_PED_FOR_DIALOGUE(pedsForConversation, 0, PLAYER_PED_ID(), "MICHAEL") ADD_PED_FOR_DIALOGUE(pedsForConversation, 5, epsilonianArray[ID_JIMMY].hPed, "JIMMYBOSTON") ADD_PED_FOR_DIALOGUE(pedsForConversation, 4, epsilonianArray[ID_MARNIE].hPed, "MARNIE") IF iCurrentRock = 0 hPrimaryBuddy = epsilonianArray[ID_JIMMY].hPed ELSE hPrimaryBuddy = epsilonianArray[ID_MARNIE].hPed ENDIF // Switch on detector START_DETECTOR(rockArray[iCurrentRock].fMeanderFactor0, rockArray[iCurrentRock].fMeanderFactor1, rockArray[iCurrentRock].fMeanderAmplitude, rockArray[iCurrentRock].fStraightZone, rockArray[iCurrentRock].fHotAngle) // Reset all vars bIsPlayerOnTarget = FALSE bIsPlayerAtRock = FALSE bHasPlayerFoundRock = FALSE bIsPlayerInWoods = TRUE bAudDoneChat1 = FALSE bAudDoneChat2 = FALSE bAudDoneChatAll = FALSE bAudDoneClose = FALSE bAudDoneReturn1 = FALSE bAudDoneReturn2 = FALSE bObjDoneHunt = FALSE bObjDoneExamine = FALSE bObjDoneReturnWoods = FALSE iTutorialLine = 0 iTutorialTimer = 0 CLEAR_HELP(TRUE) iHintTimer = GET_GAME_TIMER() iTutorialTimer = GET_GAME_TIMER() + 1000 DEBUG_PRINTSI("Finished setup, moving to run loop for rock #:", iCurrentRock) g_mission.section = SECTION_RUNNING ENDIF IF g_mission.section = SECTION_RUNNING //-- Check for deaths IF IS_ENTITY_DEAD(PLAYER_PED_ID()) QUEUE_MISSION_STAGE(MS_FAILED) g_mission.failReason = FAIL_REASON_PLAYER_DEAD g_mission.section = SECTION_CLEANUP ELIF IS_ENTITY_DEAD(epsilonianArray[ID_MARNIE].hPed) QUEUE_MISSION_STAGE(MS_FAILED) g_mission.failReason = FAIL_REASON_MARNIE_DEAD g_mission.section = SECTION_CLEANUP ELIF IS_ENTITY_DEAD(epsilonianArray[ID_JIMMY].hPed) QUEUE_MISSION_STAGE(MS_FAILED) g_mission.failReason = FAIL_REASON_JIMMY_DEAD g_mission.section = SECTION_CLEANUP ELIF HAS_ENTITY_BEEN_DAMAGED_BY_ENTITY(epsilonianArray[ID_MARNIE].hPed, PLAYER_PED_ID(), TRUE) AND HAS_ENTITY_BEEN_DAMAGED_BY_WEAPON(epsilonianArray[ID_MARNIE].hPed, WEAPONTYPE_INVALID, GENERALWEAPON_TYPE_ANYWEAPON) QUEUE_MISSION_STAGE(MS_FAILED) g_mission.failReason = FAIL_REASON_MARNIE_INJURED g_mission.section = SECTION_CLEANUP ELIF HAS_ENTITY_BEEN_DAMAGED_BY_ENTITY(epsilonianArray[ID_JIMMY].hPed, PLAYER_PED_ID(), TRUE) AND HAS_ENTITY_BEEN_DAMAGED_BY_WEAPON(epsilonianArray[ID_JIMMY].hPed, WEAPONTYPE_INVALID, GENERALWEAPON_TYPE_ANYWEAPON) QUEUE_MISSION_STAGE(MS_FAILED) g_mission.failReason = FAIL_REASON_JIMMY_INJURED g_mission.section = SECTION_CLEANUP ELIF IS_EPS_THREATENED(epsilonianArray[ID_MARNIE]) QUEUE_MISSION_STAGE(MS_FAILED) g_mission.failReason = FAIL_REASON_MARNIE_THREATENED g_mission.section = SECTION_CLEANUP ELIF IS_EPS_THREATENED(epsilonianArray[ID_JIMMY]) QUEUE_MISSION_STAGE(MS_FAILED) g_mission.failReason = FAIL_REASON_JIMMY_THREATENED g_mission.section = SECTION_CLEANUP ELIF NOT IS_POINT_IN_POLY_2D(g_polyFailArea, GET_ENTITY_COORDS(PLAYER_PED_ID())) QUEUE_MISSION_STAGE(MS_FAILED) g_mission.failReason = FAIL_REASON_LEFT_AREA g_mission.section = SECTION_CLEANUP ELIF g_mission.bRequestCpSkip g_mission.section = SECTION_CLEANUP ELIF g_mission.bRequestJSkip QUEUE_MISSION_STAGE(MS_ROCKSCENE) g_mission.section = SECTION_CLEANUP ELIF g_mission.bRequestPSkip IF iCurrentRock = 0 QUEUE_MISSION_STAGE(MS_INTRO) DEBUG_PRINTSTRING("P skipping to intro...") ELSE iCurrentRock-- QUEUE_MISSION_STAGE(MS_ROCKSCENE) ENDIF g_mission.section = SECTION_CLEANUP ELSE // Update the epsilonians REPEAT EPSILONIAN_MAX iEps UPDATE_EPS(epsilonianArray[iEps]) ENDREPEAT // Start preloading the cutscene when < the default cutscene load distance IF DOES_ENTITY_EXIST(rockArray[iCurrentRock].hObject) IF iCurrentRock = 0 if GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), rockArray[iCurrentRock].hObject) < DEFAULT_CUTSCENE_LOAD_DIST IF NOT HAS_CUTSCENE_LOADED() REQUEST_CUTSCENE("EPS_4_MCS_1") DEBUG_PRINTSTRING("Requesting midtro now") ENDIF ELIF GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), rockArray[iCurrentRock].hObject) > DEFAULT_CUTSCENE_UNLOAD_DIST IF HAS_CUTSCENE_LOADED() DEBUG_PRINTSTRING("Player moved away - unloading midtro") REMOVE_CUTSCENE() ENDIF ENDIF ELIF iCurrentRock = 1 if GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), rockArray[iCurrentRock].hObject) < DEFAULT_CUTSCENE_LOAD_DIST IF NOT HAS_CUTSCENE_LOADED() REQUEST_CUTSCENE("EPS_4_MCS_2") DEBUG_PRINTSTRING("Requesting midtro now") ENDIF ELIF GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), rockArray[iCurrentRock].hObject) > DEFAULT_CUTSCENE_UNLOAD_DIST IF HAS_CUTSCENE_LOADED() DEBUG_PRINTSTRING("Player moved away - unloading midtro") REMOVE_CUTSCENE() ENDIF ENDIF ELSE if GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), rockArray[iCurrentRock].hObject) < DEFAULT_CUTSCENE_LOAD_DIST IF NOT HAS_CUTSCENE_LOADED() REQUEST_CUTSCENE("EPS_4_MCS_3") DEBUG_PRINTSTRING("Requesting midtro now") ENDIF ELIF GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), rockArray[iCurrentRock].hObject) > DEFAULT_CUTSCENE_UNLOAD_DIST IF HAS_CUTSCENE_LOADED() DEBUG_PRINTSTRING("Player moved away - unloading midtro") REMOVE_CUTSCENE() ENDIF ENDIF ENDIF ENDIF IF CAN_REQUEST_ASSETS_FOR_CUTSCENE_ENTITY() DEBUG_PRINTSTRING("Trying to set player component variation") IF IS_ENTITY_ALIVE(PLAYER_PED_ID()) SET_CUTSCENE_PED_COMPONENT_VARIATION_FROM_PED_SAFE("Michael", PLAYER_PED_ID()) ENDIF IF iCurrentRock = 0 OR iCurrentRock = 2 DEBUG_PRINTSTRING("Trying to set Jimmy prop variation") SET_CUTSCENE_PED_PROP_VARIATION("Jimmy_Boston", ANCHOR_EYES, 0) ENDIF ENDIF // Hide the ammo counter, as the detector doesn't need it (#736243) HIDE_HUD_COMPONENT_THIS_FRAME(NEW_HUD_WEAPON_ICON) // Disable the player from bringing up the weapon wheel so they're stuck with the detector // May need to look into this again for the PC version to disable the shortcut keys!! (#1022647) DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_SELECT_WEAPON) // Keep checking the Mike is holding the detector in case he puts it away when falling, etc IF IS_PED_UNINJURED(PLAYER_PED_ID()) IF GET_PEDS_CURRENT_WEAPON(PLAYER_PED_ID()) != weapon_Detector GIVE_WEAPON_TO_PED(PLAYER_PED_ID(), weapon_Detector, INFINITE_AMMO, TRUE) ENDIF ENDIF // Update the detector UPDATE_DETECTOR(rockArray[iCurrentRock]) // Update help IF iCurrentRock = 0 IF iTutorialLine = 0 IF iTutorialTimer < GET_GAME_TIMER() IF NOT IS_PLAYER_IN_FIRST_PERSON_CAMERA() PRINT_HELP_FOREVER("EPS4_T0") // "Hold ~INPUT_AIM~ to use the detector." iTutorialTimer = GET_GAME_TIMER() + DEFAULT_GOD_TEXT_TIME iTutorialLine++ iAimPromptTimer = GET_GAME_TIMER() // Reset this again to stop it happening until the first prompts are over ELSE // Player is in first person camera - skip the first bit of help text iTutorialLine = 2 ENDIF ENDIF ELIF iTutorialLine = 1 IF IS_CONTROL_JUST_PRESSED(PLAYER_CONTROL, INPUT_AIM) OR iTutorialTimer < GET_GAME_TIMER() CLEAR_HELP(TRUE) iTutorialTimer = GET_GAME_TIMER() + 1000 iTutorialLine++ iAimPromptTimer = GET_GAME_TIMER() // Reset this again to stop it happening until the first prompts are over ENDIF ELIF iTutorialLine = 2 IF iTutorialTimer < GET_GAME_TIMER() PRINT_HELP_FOREVER("EPS4_T1") // "The detector's proximity meter shows how far away the artifact is." iTutorialTimer = GET_GAME_TIMER() + DEFAULT_GOD_TEXT_TIME iTutorialLine++ iAimPromptTimer = GET_GAME_TIMER() // Reset this again to stop it happening until the first prompts are over ENDIF ELIF iTutorialLine = 3 IF iTutorialTimer < GET_GAME_TIMER() CLEAR_HELP(TRUE) iTutorialTimer = GET_GAME_TIMER() + 1000 iTutorialLine++ iAimPromptTimer = GET_GAME_TIMER() // Reset this again to stop it happening until the first prompts are over ENDIF ELIF iTutorialLine = 4 IF iTutorialTimer < GET_GAME_TIMER() PRINT_HELP_FOREVER("EPS4_T2") // "When facing toward the artifact, the detector's screen will turn blue." iTutorialTimer = GET_GAME_TIMER() + DEFAULT_GOD_TEXT_TIME iTutorialLine++ iAimPromptTimer = GET_GAME_TIMER() // Reset this again to stop it happening until the first prompts are over ENDIF ELIF iTutorialLine = 5 IF iTutorialTimer < GET_GAME_TIMER() CLEAR_HELP(TRUE) iTutorialTimer = GET_GAME_TIMER() + 1000 iTutorialLine++ ENDIF ENDIF ENDIF // Update anims UPDATE_PLAYER_AND_DETECTOR_ANIMS(gDetector.bIsOnTarget) //-- Monitor objectives // Player is in woods IF bIsPlayerInWoods = TRUE SAFE_REMOVE_BLIP(g_hBlip) IF NOT IS_POINT_IN_POLY_2D(g_polyPlayArea, GET_ENTITY_COORDS(PLAYER_PED_ID())) bIsPlayerInWoods = FALSE STOP_SCRIPTED_CONVERSATION(FALSE) CLEAR_PRINTS() ELIF bObjDoneExamine = FALSE AND bHasPlayerFoundRock IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED() iHintTimer = GET_GAME_TIMER() bObjDoneExamine = TRUE ENDIF ELIF bAudDoneChat1 = FALSE IF ARE_STRINGS_EQUAL(rockArray[iCurrentRock].sChat1Dialogue, EMPTY_STRING) OR CREATE_CONVERSATION(pedsForConversation, "EPS4AUD", rockArray[iCurrentRock].sChat1Dialogue, CONV_PRIORITY_MEDIUM) // We need the empty string check above to skip over the 1st chat in case it doesn't exist, but we don't want // the ped to look at Mike if there's no conversation being played, hence this extra check IF NOT ARE_STRINGS_EQUAL(rockArray[iCurrentRock].sChat1Dialogue, EMPTY_STRING) IF IS_ENTITY_ALIVE(hPrimaryBuddy) TASK_LOOK_AT_ENTITY(hPrimaryBuddy, PLAYER_PED_ID(), 10000) ENDIF ENDIF iAimPromptTimer = GET_GAME_TIMER() // Reset this again to stop it happening until the first prompts are over bAudDoneChat1 = TRUE ENDIF ELIF bObjDoneHunt = FALSE IF iCurrentRock = 0 IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED() PRINT_NOW("EPS4_A2", DEFAULT_GOD_TEXT_TIME, 0) // Find the artefact iHintTimer = GET_GAME_TIMER() bObjDoneHunt = TRUE ENDIF ELSE bObjDoneHunt = TRUE // Don't repeat goal if not on first artefact ENDIF ELIF bAudDoneChat2 = FALSE IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED() AND (GET_GAME_TIMER() - iHintTimer) >= DEFAULT_GOD_TEXT_TIME IF ARE_STRINGS_EQUAL(rockArray[iCurrentRock].sChat2Dialogue, EMPTY_STRING) OR NOT IS_ENTITY_AT_ENTITY(PLAYER_PED_ID(), hPrimaryBuddy, <>) OR CREATE_CONVERSATION(pedsForConversation, "EPS4AUD", rockArray[iCurrentRock].sChat2Dialogue, CONV_PRIORITY_MEDIUM) // We need the empty string check above to skip over the 2nd chat in case it doesn't exist, but we don't want // the ped to look at Mike if there's no conversation being played, hence this extra check IF NOT ARE_STRINGS_EQUAL(rockArray[iCurrentRock].sChat2Dialogue, EMPTY_STRING) IF IS_ENTITY_ALIVE(hPrimaryBuddy) TASK_LOOK_AT_ENTITY(hPrimaryBuddy, PLAYER_PED_ID(), 5000) ENDIF ENDIF bAudDoneChat2 = TRUE iAimPromptTimer = GET_GAME_TIMER() // Reset this again to stop it happening until the first prompts are over ENDIF ENDIF ELIF bAudDoneChatAll = FALSE IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED() bAudDoneChatAll = TRUE iSupressHintAudioTimer = GET_GAME_TIMER() iSupressPickupAudioTimer = 0 ENDIF ELIF bHasPlayerFoundRock = FALSE AND NOT IS_ENTITY_IN_RANGE_COORDS(PLAYER_PED_ID(), rockArray[iCurrentRock].vPos, fNearRange) // If we're close enough to do the close dialogue, fire it once - otherwise, keep doing the Good/Bad dialogue IF IS_ENTITY_IN_RANGE_COORDS(PLAYER_PED_ID(), rockArray[iCurrentRock].vPos, fCloseDialogRange) IF NOT bAudDoneClose IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED() IF CREATE_CONVERSATION(pedsForConversation, "EPS4AUD", rockArray[iCurrentRock].SHintCloseDialogue, CONV_PRIORITY_MEDIUM) IF IS_ENTITY_ALIVE(hPrimaryBuddy) TASK_LOOK_AT_ENTITY(hPrimaryBuddy, PLAYER_PED_ID(), 5000) ENDIF REPLAY_RECORD_BACK_FOR_TIME(3.0, 5.0, REPLAY_IMPORTANCE_LOWEST) bAudDoneClose = TRUE ENDIF ENDIF ENDIF ENDIF // Tutorial dialogue IF IS_AIM_CAM_ACTIVE() IF IS_ENTITY_IN_RANGE_ENTITY(PLAYER_PED_ID(), hPrimaryBuddy, DIALOGUE_DIST) OR iCurrentRock = 2 IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED() AND ((GET_GAME_TIMER() - iSupressHintAudioTimer) > 15000) IF bIsPlayerOnTarget IF bStillOnTarget = FALSE IF iSaidGoodLines < iCurrentMaxGoodLines IF ARE_STRINGS_EQUAL(rockArray[iCurrentRock].sHintGoodDialogue, EMPTY_STRING) OR CREATE_CONVERSATION(pedsForConversation, "EPS4AUD", rockArray[iCurrentRock].sHintGoodDialogue, CONV_PRIORITY_MEDIUM) IF IS_PED_UNINJURED(hPrimaryBuddy) TASK_LOOK_AT_ENTITY(hPrimaryBuddy, PLAYER_PED_ID(), 3000) ENDIF iSupressHintAudioTimer = GET_GAME_TIMER() iSaidGoodLines++ // We want Michael to mumble to himself if he carries on being on target, but only for the last artefact IF iCurrentRock = 2 bStillOnTarget = TRUE ENDIF ENDIF ENDIF ELSE IF iSaidOnTargetLines < 12 // We can hard-code this since this will only be used for artefact 3 IF ARE_STRINGS_EQUAL(rockArray[iCurrentRock].sHintGoodDialogue, EMPTY_STRING) OR CREATE_CONVERSATION(pedsForConversation, "EPS4AUD", "EPS4_HASSIG", CONV_PRIORITY_MEDIUM) iSupressHintAudioTimer = GET_GAME_TIMER() iSaidOnTargetLines++ ENDIF ENDIF ENDIF ELSE IF iSaidbadLines < iCurrentMaxBadLines IF ARE_STRINGS_EQUAL(rockArray[iCurrentRock].sHintBadDialogue, EMPTY_STRING) OR CREATE_CONVERSATION(pedsForConversation, "EPS4AUD", rockArray[iCurrentRock].sHintBadDialogue, CONV_PRIORITY_MEDIUM) IF IS_PED_UNINJURED(hPrimaryBuddy) TASK_LOOK_AT_ENTITY(hPrimaryBuddy, PLAYER_PED_ID(), 3000) ENDIF iSupressHintAudioTimer = GET_GAME_TIMER() iSaidBadLines++ ENDIF ENDIF ENDIF ELIF bIsPlayerOnTarget <> gDetector.bIsOnTarget bIsPlayerOnTarget = gDetector.bIsOnTarget // Don't reset bStillOnTarget to whatever gDetector.bIsOnTarget is at all times - we only set it true for rock 3, // and only after we've had at least one "NOW you're on target" lines IF gDetector.bIsOnTarget = FALSE bStillOnTarget = FALSE ENDIF IF bIsPlayerOnTarget IF iSupressPickupAudioTimer < GET_GAME_TIMER() IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED() STOP_SCRIPTED_CONVERSATION(TRUE) ENDIF iSupressHintAudioTimer = GET_GAME_TIMER() - 7500 iSupressPickupAudioTimer = GET_GAME_TIMER() ENDIF ELSE iSupressHintAudioTimer = GET_GAME_TIMER() - 7500 ENDIF ENDIF ENDIF ELSE iSupressHintAudioTimer = GET_GAME_TIMER() - 5000 ENDIF ENDIF //Handle dialogue from the non-buddy ped if the player walks towards them IF iCurrentRock = 0 IF iNonFollowerCloseLines < 5 IF (GET_GAME_TIMER() - iNonFollowerCloseLinesTimer) > 7500 AND NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED() AND NOT IS_MESSAGE_BEING_DISPLAYED() IF IS_ENTITY_ALIVE(epsilonianArray[ID_MARNIE].hPed) IF GET_DISTANCE_BETWEEN_ENTITIES(epsilonianArray[ID_MARNIE].hPed, PLAYER_PED_ID()) < 4 IF CREATE_CONVERSATION(pedsForConversation, "EPS4AUD", "EPS4_NEARM", CONV_PRIORITY_LOW) iNonFollowerCloseLines++ iNonFollowerCloseLinesTimer = GET_GAME_TIMER() ENDIF ENDIF ENDIF ENDIF ENDIF ELIF iCurrentRock = 1 IF iNonFollowerCloseLines < 4 IF (GET_GAME_TIMER() - iNonFollowerCloseLinesTimer) > 7500 AND NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED() AND NOT IS_MESSAGE_BEING_DISPLAYED() IF IS_ENTITY_ALIVE(epsilonianArray[ID_JIMMY].hPed) IF GET_DISTANCE_BETWEEN_ENTITIES(epsilonianArray[ID_JIMMY].hPed, PLAYER_PED_ID()) < 4 IF CREATE_CONVERSATION(pedsForConversation, "EPS4AUD", "EPS4_NEARJ", CONV_PRIORITY_LOW) iNonFollowerCloseLines++ iNonFollowerCloseLinesTimer = GET_GAME_TIMER() ENDIF ENDIF ENDIF ENDIF ENDIF ELSE // Must be the third rock IF iNonFollowerCloseLines < 3 // Track Jimmy's near lines IF (GET_GAME_TIMER() - iNonFollowerCloseLinesTimer) > 7500 AND NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED() AND NOT IS_MESSAGE_BEING_DISPLAYED() IF IS_ENTITY_ALIVE(epsilonianArray[ID_JIMMY].hPed) IF GET_DISTANCE_BETWEEN_ENTITIES(epsilonianArray[ID_JIMMY].hPed, PLAYER_PED_ID()) < 4 IF CREATE_CONVERSATION(pedsForConversation, "EPS4AUD", "EPS4_NEARJP", CONV_PRIORITY_LOW) iNonFollowerCloseLines++ iNonFollowerCloseLinesTimer = GET_GAME_TIMER() ENDIF ENDIF ENDIF ENDIF ENDIF IF iNonFollowerCloseLines1 < 4 // Track Marnie's near lines IF (GET_GAME_TIMER() - iNonFollowerCloseLinesTimer) > 7500 AND NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED() AND NOT IS_MESSAGE_BEING_DISPLAYED() IF IS_ENTITY_ALIVE(epsilonianArray[ID_MARNIE].hPed) IF GET_DISTANCE_BETWEEN_ENTITIES(epsilonianArray[ID_MARNIE].hPed, PLAYER_PED_ID()) < 4 IF CREATE_CONVERSATION(pedsForConversation, "EPS4AUD", "EPS4_NEARMP", CONV_PRIORITY_LOW) iNonFollowerCloseLines1++ iNonFollowerCloseLinesTimer = GET_GAME_TIMER() ENDIF ENDIF ENDIF ENDIF ENDIF ENDIF // Detect if found rock / near rock / far from rock IF IS_ENTITY_AT_COORD(PLAYER_PED_ID(), rockArray[iCurrentRock].vPos, << fFindRange,fFindRange,2.0 >>, FALSE, FALSE, TM_ON_FOOT) IF iFoundWaitTimer = -1 iFoundWaitTimer = GET_GAME_TIMER() ELIF (GET_GAME_TIMER() - iFoundWaitTimer) >= 1500 //FORCE_FOUND_SCREEN_ON_DETECTOR() IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED() KILL_ANY_CONVERSATION() ENDIF iMidtroDelay = GET_GAME_TIMER() QUEUE_MISSION_STAGE(MS_ROCKSCENE) g_mission.section = SECTION_CLEANUP ENDIF ELIF bIsPlayerAtRock = FALSE IF gDetector.bIsFoundSoundOn //IS_ENTITY_IN_RANGE_COORDS(PLAYER_PED_ID(), rockArray[iCurrentRock].vPos, fNearRange) // SET_GAMEPLAY_COORD_HINT(rockArray[iCurrentRock].vPos + <<0,0,1>>, -1) bIsPlayerAtRock = TRUE bHasPlayerFoundRock = TRUE ENDIF ELSE // If player moves away from rock after finding it, go back to previous state (but leave the blip) IF NOT IS_ENTITY_IN_RANGE_COORDS(PLAYER_PED_ID(), rockArray[iCurrentRock].vPos, fNearRange+2) // STOP_GAMEPLAY_HINT() bIsPlayerAtRock = FALSE ENDIF ENDIF // Player has strayed from woods ELSE IF NOT DOES_BLIP_EXIST(g_hBlip) g_hBlip = CREATE_COORD_BLIP(vPos_WoodsCentre, BLIPPRIORITY_MED, FALSE) ENDIF bIsPlayerOnTarget = gDetector.bIsOnTarget IF IS_POINT_IN_POLY_2D(g_polyPlayArea, GET_ENTITY_COORDS(PLAYER_PED_ID())) bIsPlayerInWoods = TRUE STOP_SCRIPTED_CONVERSATION(FALSE) CLEAR_PRINTS() ELIF bObjDoneReturnWoods = FALSE IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED() PRINT_NOW("EPS4_A1", DEFAULT_GOD_TEXT_TIME, 0) // Go back to the woods iHintTimer = GET_GAME_TIMER() bObjDoneReturnWoods = TRUE ENDIF ELIF bAudDoneReturn1 = FALSE IF iCurrentRock < 2 IF IS_ENTITY_AT_ENTITY(PLAYER_PED_ID(), hPrimaryBuddy, <>) IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED() AND NOT IS_MESSAGE_BEING_DISPLAYED() IF ARE_STRINGS_EQUAL(rockArray[iCurrentRock].sReturn1Dialogue, EMPTY_STRING) OR CREATE_CONVERSATION(pedsForConversation, "EPS4AUD", rockArray[iCurrentRock].sReturn1Dialogue, CONV_PRIORITY_MEDIUM) bAudDoneReturn1 = TRUE ENDIF ENDIF ENDIF ELSE IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED() AND NOT IS_MESSAGE_BEING_DISPLAYED() IF ARE_STRINGS_EQUAL(rockArray[iCurrentRock].sReturn1Dialogue, EMPTY_STRING) OR CREATE_CONVERSATION(pedsForConversation, "EPS4AUD", rockArray[iCurrentRock].sReturn1Dialogue, CONV_PRIORITY_MEDIUM) bAudDoneReturn1 = TRUE ENDIF ENDIF ENDIF ELIF bAudDoneReturn2 = FALSE IF iCurrentRock < 2 IF IS_ENTITY_AT_ENTITY(PLAYER_PED_ID(), hPrimaryBuddy, <>) IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED() AND (GET_GAME_TIMER() - iHintTimer) >= DEFAULT_GOD_TEXT_TIME AND NOT IS_MESSAGE_BEING_DISPLAYED() IF ARE_STRINGS_EQUAL(rockArray[iCurrentRock].sReturn2Dialogue, EMPTY_STRING) OR CREATE_CONVERSATION(pedsForConversation, "EPS4AUD", rockArray[iCurrentRock].sReturn2Dialogue, CONV_PRIORITY_MEDIUM) bAudDoneReturn2 = TRUE ENDIF ENDIF ENDIF ELSE IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED() AND (GET_GAME_TIMER() - iHintTimer) >= DEFAULT_GOD_TEXT_TIME AND NOT IS_MESSAGE_BEING_DISPLAYED() IF ARE_STRINGS_EQUAL(rockArray[iCurrentRock].sReturn2Dialogue, EMPTY_STRING) OR CREATE_CONVERSATION(pedsForConversation, "EPS4AUD", rockArray[iCurrentRock].sReturn2Dialogue, CONV_PRIORITY_MEDIUM) bAudDoneReturn2 = TRUE ENDIF ENDIF ENDIF ENDIF ENDIF ENDIF ENDIF IF g_mission.section = SECTION_CLEANUP // Hide the ammo counter, as the detector doesn't need it (#736243) HIDE_HUD_COMPONENT_THIS_FRAME(NEW_HUD_WEAPON_ICON) DEBUG_PRINTSTRING("In cleanup for FindRock") IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED() STOP_SCRIPTED_CONVERSATION(TRUE) ENDIF UPDATE_PLAYER_AND_DETECTOR_ANIMS(TRUE) FORCE_FOUND_SCREEN_ON_DETECTOR() SET_CONTROL_SHAKE(PLAYER_CONTROL, 200, 150) IF (GET_GAME_TIMER() - iMidtroDelay) > 750 // Disable detector STOP_DETECTOR() REPLAY_RECORD_BACK_FOR_TIME(5.0, 5.0, REPLAY_IMPORTANCE_LOWEST) REPLAY_RECORD_BACK_FOR_TIME(3.0) // Clear tasks CLEAR_PED_TASKS(PLAYER_PED_ID()) SET_EPS_IDLE(epsilonianArray[ID_JIMMY], FALSE) SET_EPS_IDLE(epsilonianArray[ID_MARNIE], FALSE) CHANGE_MISSION_STAGE() ENDIF ENDIF ENDPROC //******************************************************************************************************************* //******************************************************************************************************************* /// PURPOSE: /// Main loop for the rock scripted cutscenes during the mission PROC STAGE_ROCKSCENE() // Hide the ammo counter, as the detector doesn't need it (#736243) HIDE_HUD_COMPONENT_THIS_FRAME(NEW_HUD_WEAPON_ICON) IF g_mission.bSyncForSkip = TRUE RC_START_Z_SKIP() REMOVE_CUTSCENE() IF iCurrentRock = 0 RC_REQUEST_MID_MISSION_CUTSCENE("EPS_4_MCS_1") ELIF iCurrentRock = 1 RC_REQUEST_MID_MISSION_CUTSCENE("EPS_4_MCS_2") ELSE RC_REQUEST_MID_MISSION_CUTSCENE("EPS_4_MCS_3") ENDIF IF CAN_REQUEST_ASSETS_FOR_CUTSCENE_ENTITY() DEBUG_PRINTSTRING("Trying to set player component variation") IF IS_ENTITY_ALIVE(PLAYER_PED_ID()) SET_CUTSCENE_PED_COMPONENT_VARIATION_FROM_PED_SAFE("Michael", PLAYER_PED_ID()) ENDIF IF iCurrentRock = 0 OR iCurrentRock = 2 DEBUG_PRINTSTRING("Trying to set Jimmy prop variation") SET_CUTSCENE_PED_PROP_VARIATION("Jimmy_Boston", ANCHOR_EYES, 0) ENDIF ENDIF DEBUG_PRINTSTRING("SKIP: Doing sync for cutscene skip") RC_END_Z_SKIP() g_mission.bSyncForSkip = FALSE ENDIF IF g_mission.section = SECTION_SETUP DEBUG_PRINTSI("Doing setup for RockScene:", iCurrentRock) UPDATE_PLAYER_AND_DETECTOR_ANIMS(TRUE) FORCE_FOUND_SCREEN_ON_DETECTOR() SET_CONTROL_SHAKE(PLAYER_CONTROL, 200, 150) // IF IS_PED_UNINJURED(PLAYER_PED_ID()) // // Reset the capsule during the cutscenes so the Epsilonists aren't affected by it (#709181) // SET_PED_CAPSULE(PLAYER_PED_ID(), 0) // bCapsuleResized = FALSE // ENDIF IF CAN_REQUEST_ASSETS_FOR_CUTSCENE_ENTITY() DEBUG_PRINTSTRING("Trying to set player component variation") IF IS_ENTITY_ALIVE(PLAYER_PED_ID()) SET_CUTSCENE_PED_COMPONENT_VARIATION_FROM_PED_SAFE("Michael", PLAYER_PED_ID()) ENDIF IF iCurrentRock = 0 OR iCurrentRock = 2 DEBUG_PRINTSTRING("Trying to set Jimmy prop variation") SET_CUTSCENE_PED_PROP_VARIATION("Jimmy_Boston", ANCHOR_EYES, 0) ENDIF ENDIF IF NOT IS_VEHICLE_OK(Eps_Vehicle) Eps_Vehicle = CREATE_VEHICLE(Bison, <<1851.57, 4772.12, 39.80>>, 31.35) SET_VEHICLE_COLOURS(Eps_Vehicle, 157, 157) SET_VEHICLE_EXTRA_COLOURS(Eps_Vehicle, 5, 157) SET_VEHICLE_ON_GROUND_PROPERLY(Eps_Vehicle) ENDIF // Clear buddy tasks and state immediately SET_EPS_IDLE(epsilonianArray[ID_JIMMY]) SET_EPS_IDLE(epsilonianArray[ID_MARNIE]) IF IS_PED_UNINJURED(PLAYER_PED_ID()) // Final check to make sure the cutscene is ok to start WHILE NOT RC_IS_CUTSCENE_OK_TO_START() DEBUG_PRINTSTRING("Waiting for cutscene to be OK to start...") // Hide the ammo counter, as the detector doesn't need it (#736243) HIDE_HUD_COMPONENT_THIS_FRAME(NEW_HUD_WEAPON_ICON) UPDATE_PLAYER_AND_DETECTOR_ANIMS(TRUE) FORCE_FOUND_SCREEN_ON_DETECTOR() SET_CONTROL_SHAKE(PLAYER_CONTROL, 200, 150) // Request cutscene again using the RC version to 1) make sure it definitely gets loaded, and 2) to stop the player moving IF iCurrentRock = 0 RC_REQUEST_MID_MISSION_CUTSCENE("EPS_4_MCS_1") ELIF iCurrentRock = 1 RC_REQUEST_MID_MISSION_CUTSCENE("EPS_4_MCS_2") ELSE RC_REQUEST_MID_MISSION_CUTSCENE("EPS_4_MCS_3") ENDIF WAIT(0) ENDWHILE SET_PLAYER_FORCED_AIM(PLAYER_ID(), TRUE) INT iTimer = GET_GAME_TIMER() WHILE (GET_GAME_TIMER() - iTimer) < 500 DEBUG_PRINTSTRING("Doing 500ms pause") // Hide the ammo counter, as the detector doesn't need it (#736243) HIDE_HUD_COMPONENT_THIS_FRAME(NEW_HUD_WEAPON_ICON) SET_PLAYER_FORCED_AIM(PLAYER_ID(), TRUE) UPDATE_PLAYER_AND_DETECTOR_ANIMS(TRUE) FORCE_FOUND_SCREEN_ON_DETECTOR() SET_CONTROL_SHAKE(PLAYER_CONTROL, 200, 150) WAIT(0) ENDWHILE // Setup cutscene gumph here IF iCurrentRock = 0 IF IS_ENTITY_ALIVE(epsilonianArray[ID_JIMMY].hPed) REGISTER_ENTITY_FOR_CUTSCENE(epsilonianArray[ID_JIMMY].hPed, "Jimmy_Boston", CU_ANIMATE_EXISTING_SCRIPT_ENTITY) ENDIF IF IS_ENTITY_ALIVE(epsilonianArray[ID_MARNIE].hPed) REGISTER_ENTITY_FOR_CUTSCENE(epsilonianArray[ID_MARNIE].hPed, "Marnie", CU_ANIMATE_EXISTING_SCRIPT_ENTITY) ENDIF IF IS_ENTITY_ALIVE(PLAYER_PED_ID()) REGISTER_ENTITY_FOR_CUTSCENE(PLAYER_PED_ID(), "Michael", CU_ANIMATE_EXISTING_SCRIPT_ENTITY) ENDIF IF IS_ENTITY_ALIVE(gDetector.hObj) DetectorCopy = CREATE_WEAPON_OBJECT_FROM_PED_WEAPON_WITH_COMPONENTS(PLAYER_PED_ID(), WEAPONTYPE_DIGISCANNER) REGISTER_ENTITY_FOR_CUTSCENE(DetectorCopy, "Artefact_Detector", CU_ANIMATE_EXISTING_SCRIPT_ENTITY) ENDIF IF IS_ENTITY_ALIVE(rockArray[iCurrentRock].hObject) REGISTER_ENTITY_FOR_CUTSCENE(rockArray[iCurrentRock].hObject, "EPS_TV", CU_ANIMATE_EXISTING_SCRIPT_ENTITY) ENDIF ELIF iCurrentRock = 1 IF IS_ENTITY_ALIVE(epsilonianArray[ID_MARNIE].hPed) epsilonianArray[ID_MARNIE].bNotUsingNavmeshMove = FALSE REGISTER_ENTITY_FOR_CUTSCENE(epsilonianArray[ID_MARNIE].hPed, "Marnie", CU_ANIMATE_EXISTING_SCRIPT_ENTITY) ENDIF IF IS_ENTITY_ALIVE(PLAYER_PED_ID()) REGISTER_ENTITY_FOR_CUTSCENE(PLAYER_PED_ID(), "Michael", CU_ANIMATE_EXISTING_SCRIPT_ENTITY) ENDIF IF IS_ENTITY_ALIVE(gDetector.hObj) DetectorCopy = CREATE_WEAPON_OBJECT_FROM_PED_WEAPON_WITH_COMPONENTS(PLAYER_PED_ID(), WEAPONTYPE_DIGISCANNER) REGISTER_ENTITY_FOR_CUTSCENE(DetectorCopy, "Artefact_Detector", CU_ANIMATE_EXISTING_SCRIPT_ENTITY) ENDIF IF IS_ENTITY_ALIVE(rockArray[iCurrentRock].hObject) REGISTER_ENTITY_FOR_CUTSCENE(rockArray[iCurrentRock].hObject, "EPS_Battery", CU_ANIMATE_EXISTING_SCRIPT_ENTITY) ENDIF ELSE IF IS_ENTITY_ALIVE(epsilonianArray[ID_JIMMY].hPed) REGISTER_ENTITY_FOR_CUTSCENE(epsilonianArray[ID_JIMMY].hPed, "Jimmy_Boston", CU_ANIMATE_EXISTING_SCRIPT_ENTITY) ENDIF IF IS_ENTITY_ALIVE(epsilonianArray[ID_MARNIE].hPed) REGISTER_ENTITY_FOR_CUTSCENE(epsilonianArray[ID_MARNIE].hPed, "Marnie", CU_ANIMATE_EXISTING_SCRIPT_ENTITY) ENDIF IF IS_ENTITY_ALIVE(gDetector.hObj) DetectorCopy = CREATE_WEAPON_OBJECT_FROM_PED_WEAPON_WITH_COMPONENTS(PLAYER_PED_ID(), WEAPONTYPE_DIGISCANNER) REGISTER_ENTITY_FOR_CUTSCENE(DetectorCopy, "Artefact_Detector", CU_ANIMATE_EXISTING_SCRIPT_ENTITY) ENDIF IF IS_ENTITY_ALIVE(PLAYER_PED_ID()) REGISTER_ENTITY_FOR_CUTSCENE(PLAYER_PED_ID(), "Michael", CU_ANIMATE_EXISTING_SCRIPT_ENTITY) ENDIF IF IS_ENTITY_ALIVE(rockArray[iCurrentRock].hObject) REGISTER_ENTITY_FOR_CUTSCENE(rockArray[iCurrentRock].hObject, "Old_Boot", CU_ANIMATE_EXISTING_SCRIPT_ENTITY) ENDIF ENDIF // Start cutscene START_CUTSCENE() REPLAY_START_EVENT(REPLAY_IMPORTANCE_LOW) // Got to do this instead of wait(0) like other missions so we can call HIDE_HUD_COMPONENT_THIS_FRAME iTimer = GET_GAME_TIMER() WHILE (GET_GAME_TIMER() - iTimer) < 1 HIDE_HUD_COMPONENT_THIS_FRAME(NEW_HUD_WEAPON_ICON) WAIT(0) REPLAY_CHECK_FOR_EVENT_THIS_FRAME("SF_Epsilon4") ENDWHILE // Don't want Mike to have the detector after the last cutscene IF iCurrentRock >= 2 IF IS_ENTITY_ALIVE(PLAYER_PED_ID()) GIVE_WEAPON_TO_PED(PLAYER_PED_ID(), WEAPONTYPE_UNARMED, INFINITE_AMMO, TRUE) ENDIF ENDIF SET_PLAYER_FORCED_AIM(PLAYER_ID(), FALSE) RESOLVE_VEHICLES_INSIDE_ANGLED_AREA_WITH_SIZE_LIMIT(rockArray[iCurrentRock].vAngledArea1, rockArray[iCurrentRock].vAngledArea2, rockArray[iCurrentRock].fAngledAreaWidth, rockArray[iCurrentRock].vWarpCarPos, rockArray[iCurrentRock].fWarpCarRot, GET_DEFAULT_ALLOWABLE_VEHICLE_SIZE_VECTOR()) RC_START_CUTSCENE_MODE(rockArray[iCurrentRock].vPos, TRUE, FALSE, DEFAULT, DEFAULT, DEFAULT, DEFAULT, FALSE) ENDIF DEBUG_PRINTSI("Finished setup, moving to run loop for RockScene #:", iCurrentRock) g_mission.section = SECTION_RUNNING ENDIF IF g_mission.section = SECTION_RUNNING //-- Check for deaths IF CHECK_FAIL_CONDITIONS_DURING_CUTSCENE() ELIF g_mission.bRequestCpSkip g_mission.section = SECTION_CLEANUP ELIF g_mission.bRequestJSkip IF (iCurrentRock < iRockCount-1) QUEUE_MISSION_STAGE(MS_FINDROCK) ELSE QUEUE_MISSION_STAGE(MS_PASSED) ENDIF g_mission.section = SECTION_CLEANUP iCurrentRock++ ELIF g_mission.bRequestPSkip QUEUE_MISSION_STAGE(MS_FINDROCK) g_mission.section = SECTION_CLEANUP ELSE // Timeout + skip checks // IF IS_CUTSCENE_SKIP_BUTTON_JUST_PRESSED_WITH_DELAY() //// bPlayerSkippedScene = TRUE // g_mission.iEvent = -1 // ENDIF IF iCurrentRock >= 2 IF IS_CUTSCENE_PLAYING() IF GET_CUTSCENE_TIME() > 17000 IF NOT IS_NEW_LOAD_SCENE_ACTIVE() NEW_LOAD_SCENE_START(<<1847.4722, 4756.1572, 36.6968>>, GET_HEADING_AS_VECTOR(271.4718), 145.0) ENDIF ENDIF ENDIF ENDIF // Run events IF g_mission.iEvent = 0 FORCE_FOUND_SCREEN_ON_DETECTOR() // Keep spamming for the blend SET_GAMEPLAY_CAM_RELATIVE_PITCH() SET_GAMEPLAY_CAM_RELATIVE_HEADING() IF WAS_CUTSCENE_SKIPPED() SET_GAMEPLAY_CAM_RELATIVE_PITCH() SET_GAMEPLAY_CAM_RELATIVE_HEADING() g_mission.iEvent = 1 ENDIF DO_DETECTOR_EXIT() IF iCurrentRock >= 2 DO_MARNIE_EXIT() DO_JIMMY_EXIT() ELIF iCurrentRock = 1 IF DO_MICHAEL_EXIT() g_mission.iEvent = 1 ENDIF DO_MARNIE_EXIT() ELSE IF DO_MICHAEL_EXIT() g_mission.iEvent = 1 ENDIF DO_MARNIE_EXIT() DO_JIMMY_EXIT() ENDIF IF NOT IS_CUTSCENE_ACTIVE() g_mission.iEvent = -1 DEBUG_PRINTSTRING("Cutscene not active, setting event -1") ENDIF ENDIF IF g_mission.iEvent = 1 FORCE_NOT_FOUND_SCREEN_ON_DETECTOR() DO_MICHAEL_EXIT() DO_DETECTOR_EXIT() IF iCurrentRock >= 2 DO_MARNIE_EXIT() DO_JIMMY_EXIT() ELIF iCurrentRock = 1 DO_MARNIE_EXIT() ELSE DO_MARNIE_EXIT() DO_JIMMY_EXIT() ENDIF IF WAS_CUTSCENE_SKIPPED() SET_GAMEPLAY_CAM_RELATIVE_PITCH() SET_GAMEPLAY_CAM_RELATIVE_HEADING() ENDIF IF NOT IS_CUTSCENE_ACTIVE() g_mission.iEvent = -1 DEBUG_PRINTSTRING("Cutscene not active, setting event -1") ENDIF ENDIF // If complete... IF g_mission.iEvent = -1 DEBUG_PRINTSTRING("Doing event -1...") IF (iCurrentRock < iRockCount-1) QUEUE_MISSION_STAGE(MS_FINDROCK) ELSE QUEUE_MISSION_STAGE(MS_WAITTOPASS) ENDIF IF iCurrentRock >= 2 TRIGGER_MUSIC_EVENT("EPS4_STOP") SAFE_DELETE_OBJECT(rockArray[iCurrentRock].hObject) ENDIF g_mission.section = SECTION_CLEANUP iCurrentRock++ DEBUG_PRINTSI("END CUTSCENE: iCurrentRock = ", iCurrentRock) ENDIF ENDIF ENDIF IF g_mission.section = SECTION_CLEANUP REPLAY_STOP_EVENT() DEBUG_PRINTSTRING("Doing cleanup for RockScene") // IF IS_PED_UNINJURED(PLAYER_PED_ID()) // // Reset player in right direction // IF (iCurrentRock < iRockCount) // CLEAR_PED_TASKS_IMMEDIATELY(PLAYER_PED_ID()) // IF rockArray[iCurrentRock].fPostSceneRot >= 0.0 // SET_ENTITY_HEADING(PLAYER_PED_ID(), rockArray[iCurrentRock].fPostSceneRot) // ENDIF // ELSE // CLEAR_PED_TASKS(PLAYER_PED_ID()) // ENDIF // // // Stop looking at the object // TASK_CLEAR_LOOK_AT(PLAYER_PED_ID()) // ENDIF // End custcene // SET_GAMEPLAY_CAM_RELATIVE_HEADING() RC_END_CUTSCENE_MODE(TRUE, FALSE) // Change state CHANGE_MISSION_STAGE() ENDIF ENDPROC PROC STAGE_Passwait() SWITCH g_mission.section CASE SECTION_SETUP REQUEST_ANIM_DICT("weapons@holster_1h") WHILE GET_PEDS_CURRENT_WEAPON(PLAYER_PED_ID()) = weapon_Detector WAIT(0) HIDE_HUD_COMPONENT_THIS_FRAME(NEW_HUD_WEAPON_ICON) IF HAS_ANIM_DICT_LOADED("weapons@holster_1h") IF NOT IS_ENTITY_PLAYING_ANIM(PLAYER_PED_ID(), "weapons@holster_1h", "holster") TASK_PLAY_ANIM(PLAYER_PED_ID(), "weapons@holster_1h", "holster") ELSE IF GET_ENTITY_ANIM_CURRENT_TIME(PLAYER_PED_ID(), "weapons@holster_1h", "holster") >= 0.5 SET_CURRENT_PED_WEAPON(PLAYER_PED_ID(), WEAPONTYPE_UNARMED, TRUE) ENDIF ENDIF ENDIF ENDWHILE HIDE_HUD_COMPONENT_THIS_FRAME(NEW_HUD_WEAPON_ICON) REMOVE_WEAPON_FROM_PED(PLAYER_PED_ID(), weapon_Detector) g_mission.section = SECTION_RUNNING BREAK CASE SECTION_RUNNING HIDE_HUD_COMPONENT_THIS_FRAME(NEW_HUD_WEAPON_ICON) //-- Check for deaths IF IS_ENTITY_DEAD(PLAYER_PED_ID()) QUEUE_MISSION_STAGE(MS_FAILED) g_mission.failReason = FAIL_REASON_PLAYER_DEAD g_mission.section = SECTION_CLEANUP ELIF IS_ENTITY_DEAD(epsilonianArray[ID_MARNIE].hPed) QUEUE_MISSION_STAGE(MS_FAILED) g_mission.failReason = FAIL_REASON_MARNIE_DEAD g_mission.section = SECTION_CLEANUP ELIF IS_ENTITY_DEAD(epsilonianArray[ID_JIMMY].hPed) QUEUE_MISSION_STAGE(MS_FAILED) g_mission.failReason = FAIL_REASON_JIMMY_DEAD g_mission.section = SECTION_CLEANUP ELIF HAS_ENTITY_BEEN_DAMAGED_BY_ENTITY(epsilonianArray[ID_MARNIE].hPed, PLAYER_PED_ID(), TRUE) AND HAS_ENTITY_BEEN_DAMAGED_BY_WEAPON(epsilonianArray[ID_MARNIE].hPed, WEAPONTYPE_INVALID, GENERALWEAPON_TYPE_ANYWEAPON) QUEUE_MISSION_STAGE(MS_FAILED) g_mission.failReason = FAIL_REASON_MARNIE_INJURED g_mission.section = SECTION_CLEANUP ELIF HAS_ENTITY_BEEN_DAMAGED_BY_ENTITY(epsilonianArray[ID_JIMMY].hPed, PLAYER_PED_ID(), TRUE) AND HAS_ENTITY_BEEN_DAMAGED_BY_WEAPON(epsilonianArray[ID_JIMMY].hPed, WEAPONTYPE_INVALID, GENERALWEAPON_TYPE_ANYWEAPON) QUEUE_MISSION_STAGE(MS_FAILED) g_mission.failReason = FAIL_REASON_JIMMY_INJURED g_mission.section = SECTION_CLEANUP ELIF IS_EPS_THREATENED(epsilonianArray[ID_MARNIE]) QUEUE_MISSION_STAGE(MS_FAILED) g_mission.failReason = FAIL_REASON_MARNIE_THREATENED g_mission.section = SECTION_CLEANUP ELIF IS_EPS_THREATENED(epsilonianArray[ID_JIMMY]) QUEUE_MISSION_STAGE(MS_FAILED) g_mission.failReason = FAIL_REASON_JIMMY_THREATENED g_mission.section = SECTION_CLEANUP ELIF IS_ENTITY_ALIVE(epsilonianArray[ID_MARNIE].hPed) IF GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), epsilonianArray[ID_MARNIE].hPed) >= 50 IF IS_NEW_LOAD_SCENE_ACTIVE() NEW_LOAD_SCENE_STOP() ENDIF QUEUE_MISSION_STAGE(MS_PASSED) g_mission.section = SECTION_CLEANUP ENDIF ENDIF BREAK CASE SECTION_CLEANUP HIDE_HUD_COMPONENT_THIS_FRAME(NEW_HUD_WEAPON_ICON) CHANGE_MISSION_STAGE() BREAK ENDSWITCH ENDPROC //******************************************************************************************************************* //******************************************************************************************************************* STAGE: FailFade /// PURPOSE: /// Main stage for mission failure PROC STAGE_FailFade() SWITCH g_mission.section CASE SECTION_SETUP Script_TextCleanup() TRIGGER_MUSIC_EVENT("EPS_FAIL") // convert reason to string STRING sFailType sFailType = EMPTY_STRING SWITCH (g_mission.failReason) CASE FAIL_REASON_LEFT_AREA sFailType = "EPS4_X1" BREAK CASE FAIL_REASON_MARNIE_DEAD sFailType = "EPS4_X2" BREAK CASE FAIL_REASON_JIMMY_DEAD sFailType = "EPS4_X3" BREAK CASE FAIL_REASON_MARNIE_INJURED sFailType = "EPS4_X4" BREAK CASE FAIL_REASON_JIMMY_INJURED sFailType = "EPS4_X5" BREAK CASE FAIL_REASON_MARNIE_THREATENED sFailType = "EPS4_X7" BREAK CASE FAIL_REASON_JIMMY_THREATENED sFailType = "EPS4_X8" BREAK DEFAULT // no fail reason BREAK ENDSWITCH IF ARE_STRINGS_EQUAL(sFailType, EMPTY_STRING) Random_Character_Failed() ELSE Random_Character_Failed_With_Reason(sFailType) ENDIF g_mission.section = SECTION_RUNNING BREAK CASE SECTION_RUNNING IF GET_MISSION_FLOW_SAFE_TO_CLEANUP() // Do a check here to see if we need to warp the player at all // (only set the fail warp locations if we can't leave the player where he was) //MISSION_FLOW_SET_FAIL_WARP_LOCATION(<< 1831.4000, 4663.7002, 33.3069 >>, 2.1870) //SET_REPLAY_DECLINED_VEHICLE_WARP_LOCATION(<< 1826.57, 4665.27, 34.74 >>, 113.53) // delete everything here! DELETE_ALL_ROCKS() DELETE_EPS(epsilonianArray[ID_MARNIE]) DELETE_EPS(epsilonianArray[ID_JIMMY]) Script_Cleanup() ELSE // not finished fading out // you may want to handle dialogue etc here. ENDIF BREAK ENDSWITCH ENDPROC // =========================================================================================================== // DEBUG FUNCTIONS // =========================================================================================================== #IF IS_DEBUG_BUILD /// PURPOSE: Check for Forced Pass or Fail PROC DEBUG_Check_Debug_Keys() IF g_mission.section = SECTION_RUNNING INT iMenuSelection // Mission is running, so reset sync-for-skip flag g_mission.bSyncForSkip = FALSE // Check for Pass IF (IS_KEYBOARD_KEY_JUST_PRESSED(KEY_S)) WAIT_FOR_CUTSCENE_TO_STOP() TRIGGER_MUSIC_EVENT("EPS4_STOP") Script_Passed() // Check for Fail ELIF (IS_KEYBOARD_KEY_JUST_PRESSED(KEY_F)) WAIT_FOR_CUTSCENE_TO_STOP() QUEUE_MISSION_STAGE(MS_FAILED) g_mission.failReason = FAIL_REASON_DEFAULT g_mission.section = SECTION_CLEANUP // Check for J skip ELIF (IS_KEYBOARD_KEY_JUST_PRESSED(KEY_J)) g_mission.bRequestJSkip = TRUE // Check for P skip ELIF (IS_KEYBOARD_KEY_JUST_PRESSED(KEY_P)) g_mission.bRequestPSkip = TRUE // Check for Z skip ELIF LAUNCH_MISSION_STAGE_MENU(zSkipMenu, iMenuSelection, iMenuSelection) IF iMenuSelection < 7 g_mission.queueCpSkip = iMenuSelection g_mission.bRequestCpSkip = TRUE ELSE IF bLockAimPitch bLockAimPitch = FALSE ELSE bLockAimPitch = TRUE ENDIF ENDIF ENDIF ENDIF ENDPROC #ENDIF // =========================================================================================================== // Script Loop // =========================================================================================================== SCRIPT(g_structRCScriptArgs sRCLauncherDataIn) sRCLauncherDataLocal = sRCLauncherDataIn RC_TakeEntityOwnership(sRCLauncherDataLocal) SET_MISSION_FLAG(TRUE) // Setup callback when player is killed, arrested or goes to multiplayer IF (HAS_FORCE_CLEANUP_OCCURRED(DEFAULT_FORCE_CLEANUP_FLAGS|FORCE_CLEANUP_FLAG_DEBUG_MENU)) PRINT_LAUNCHER_DEBUG("Force cleanup [TERMINATING]") Random_Character_Failed() Script_Cleanup() ENDIF IF Is_Replay_In_Progress() // Set up the initial scene for replays OR IS_REPEAT_PLAY_ACTIVE() g_bSceneAutoTrigger = TRUE eInitialSceneStage = IS_REQUEST_SCENE WHILE NOT SetupScene_EPSILON_4(sRCLauncherDataLocal) WAIT(0) ENDWHILE g_bSceneAutoTrigger = FALSE ENDIF mScenarioBlocker = Eps4_Scenario_Blocker() mScenarioBlockerPicnic = ADD_SCENARIO_BLOCKING_AREA_FROM_POSITION_AND_RADIUS(<<1855.08, 4755.85, 36.81>>, 25.0) iNavBlockerBush1 = ADD_NAVMESH_BLOCKING_OBJECT(<<1815.39, 4698.00, 38.87>>, <<3.5,3.5,3>>, 0) iNavBlockerBush2 = ADD_NAVMESH_BLOCKING_OBJECT(<<1824.12, 4701.39, 38.29>>, <<2.5, 2.5, 2.5>>, 0) iNavBlockerBush3 = ADD_NAVMESH_BLOCKING_OBJECT(<<1801.28, 4700.25, 39.42>>, <<2,2,2>>, 0) IF NOT IS_AUDIO_SCENE_ACTIVE("EPSILONISM_04_MIX") DEBUG_PRINTSTRING("Starting dynamic mix EPSILONISM_04_MIX") START_AUDIO_SCENE("EPSILONISM_04_MIX") ENDIF //** Mission initialisation *************** #IF IS_DEBUG_BUILD SETUP_EPS4_WIDGETS() #ENDIF REGISTER_SCRIPT_WITH_AUDIO() SET_RELATIONSHIP_BETWEEN_GROUPS(ACQUAINTANCE_TYPE_PED_LIKE, RELGROUPHASH_PLAYER, RELGROUPHASH_PLAYER) SET_WANTED_LEVEL_MULTIPLIER(0.5) grassCull = SET_GRASS_CULL_SPHERE(<< 1751.65, 4676.77, 43.03 >>, 1.5) // Disable controls and exit current vehicle RC_PLAYER_TRIGGER_SCENE_LOCK_IN() INIT_DATA() INIT_MISSION_DATA() g_mission.stage = MS_LEADIN //-- Setup world INIT_DETECTOR() INT i REPEAT iRockCount i CREATE_ROCK(rockArray[i]) ENDREPEAT CREATE_EPS(epsilonianArray[ID_MARNIE], vPos_Epsilonian1, fRot_Epsilonian1, sRCLauncherDataLocal.pedID[ID_MARNIE]) CREATE_EPS(epsilonianArray[ID_JIMMY], vPos_Epsilonian2, fRot_Epsilonian2, sRCLauncherDataLocal.pedID[ID_JIMMY]) //-- Z-Skips / Replay check points IF Is_Replay_In_Progress() IF GET_REPLAY_MID_MISSION_STAGE() = 0 START_REPLAY_SETUP(vPos_PlayerReset, fRot_PlayerReset) QUEUE_CP_SKIP(CP_FINDROCKA) RC_SET_ENTITY_PROOFS_FOR_CUTSCENE(sRCLauncherDataLocal, FALSE) CHANGE_MISSION_STAGE() DEBUG_PRINTSTRING("Done replay setup") ELSE SCRIPT_ASSERT("Replay in progress: Unknown checkpoint selected") ENDIF ELIF IS_REPEAT_PLAY_ACTIVE() START_REPLAY_SETUP(vPos_PlayerReset, fRot_PlayerReset) QUEUE_CP_SKIP(CP_INTRO) RC_SET_ENTITY_PROOFS_FOR_CUTSCENE(sRCLauncherDataLocal, TRUE) CHANGE_MISSION_STAGE() ENDIF ADD_CONTACT_TO_PHONEBOOK(CHAR_MARNIE, MICHAEL_BOOK, FALSE) //-- Mission loop ************************* WHILE(TRUE) REPLAY_CHECK_FOR_EVENT_THIS_FRAME("SF_Epsilon4") UPDATE_MISSION_NAME_DISPLAYING(sRCLauncherDataLocal.sIntroCutscene) //DISPLAY_POLY2(g_polyPlayArea) // play area = red //DISPLAY_POLY(g_polyFailArea, 100, 100, 255) // fail area = blue SET_PLAYER_MAY_NOT_ENTER_ANY_VEHICLE(PLAYER_ID()) IF IS_PLAYER_IN_FIRST_PERSON_CAMERA() DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_SPRINT) ENDIF DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_SPECIAL_ABILITY) DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_DUCK) DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_COVER) IF IS_PED_UNINJURED(PLAYER_PED_ID()) IF GET_PEDS_CURRENT_WEAPON(PLAYER_PED_ID()) = weapon_Detector DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_ATTACK) DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_ATTACK2) ENDIF ENDIF SWITCH (g_mission.stage) CASE MS_LEADIN STAGE_LEADIN() BREAK CASE MS_INTRO STAGE_INTRO() BREAK CASE MS_FINDROCK STAGE_FINDROCK() BREAK CASE MS_ROCKSCENE STAGE_ROCKSCENE() BREAK CASE MS_WAITTOPASS STAGE_PASSWAIT() BREAK CASE MS_PASSED Script_Passed() BREAK CASE MS_FAILED STAGE_FailFade() BREAK ENDSWITCH WAIT(0) // Check debug completion/failure #IF IS_DEBUG_BUILD DEBUG_Check_Debug_Keys() #ENDIF ENDWHILE SCRIPT_ASSERT("Script should never reach here. Always terminate with cleanup function.") ENDSCRIPT