////////////////////////////////////////////////////////////////////////////////////////// // // // SCRIPT NAME : ambient_sonar.sc // // AUTHOR : Joanna Wright // // DESCRIPTION : Sets up 50 items scraps around the map for the // // player to collect in a submarine // // // ////////////////////////////////////////////////////////////////////////////////////////// //Compile out Title Update changes to header functions. //Must be before includes. //CONST_INT USE_TU_CHANGES 0 // Removed by Kenneth R. //---------------------- // INCLUDES //---------------------- USING "email_public.sch" USING "RC_Helper_Functions.sch" USING "rgeneral_include.sch" USING "commands_entity.sch" USING "CompletionPercentage_public.sch" USING "properties_private.sch" USING "savegame_public.sch" USING "scrap_common.sch" USING "achievement_public.sch" USING "net_system_activity_feed.sch" //---------------------- // ENUMS //---------------------- ENUM MISSION_STATUS MS_INIT, MS_IN_SUB, MS_OUT_OF_SUB, MS_CLEANUP ENDENUM //---------------------- // CONSTS //---------------------- CONST_INT XVERSION_NUMBER 106 CONST_FLOAT CREATE_CULL_SPHERE_DISTANCE 100.0 CONST_FLOAT REMOVE_CULL_SPHERE_DISTANCE 105.0 //--------------------- // VARIABLES //---------------------- SCRAP_MISSION_DATA sMissionData SCRAP_PICKUP_DATA sSonarPickups[NUMBER_OF_SONAR_PICKUPS] VEHICLE_INDEX viSub BLIP_INDEX biSub MISSION_STATUS eStage = MS_INIT BOOL bTrkRestartHelpDisplayed = FALSE INT iTrackifyUpdateCounter = 0 INT iNearestScrapIndex = -1 INT iScrapsPerFrame = 5 INT iMessageStage = 0 SCALEFORM_INDEX siMessage INT iSphereIndexOnPickup[NUMBER_OF_SONAR_PICKUPS] #IF IS_DEBUG_BUILD WIDGET_GROUP_ID mWidgetGroup BOOL bMapAllScraps BOOL bWarpToScrap[NUMBER_OF_SONAR_PICKUPS] BOOL bCreateSub BOOL bDebugQuitScript BOOL bDebugAllowWarping BOOL bCollectAllScraps BOOL bResetScrapCollection BOOL bSimulateScrapCollect INT iSimulateScrapCollect = 1 #ENDIF //---------------------- // PLAYER FUNCTIONS //---------------------- /// PURPOSE: /// Set the correct stage and revert it to setup PROC SET_STAGE(MISSION_STATUS stage) eStage = stage ENDPROC /// PURPOSE: /// Removes sub blip PROC REMOVE_SUB_BLIP() IF DOES_BLIP_EXIST(biSub) REMOVE_BLIP(biSub) ENDIF ENDPROC /// PURPOSE: /// Remove blip and release sub PROC RELEASE_SUB() REMOVE_SUB_BLIP() IF DOES_ENTITY_EXIST(viSub) SET_VEHICLE_AS_NO_LONGER_NEEDED(viSub) ENDIF ENDPROC /// PURPOSE: /// Is the player inside a submersible FUNC BOOL IS_PLAYER_IN_SUBMERSIBLE() IF IS_PLAYER_PLAYING(PLAYER_ID()) IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID()) VEHICLE_INDEX veh = GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()) IF DOES_ENTITY_EXIST(veh) IF GET_ENTITY_MODEL(veh) = SUBMERSIBLE RETURN TRUE ENDIF ENDIF ENDIF ENDIF RETURN FALSE ENDFUNC //--------------------- // ARRAY FUNCTIONS //---------------------- /// PURPOSE: /// Returns the coordinate of the scrap piece specified by the index. FUNC VECTOR GET_SONAR_COORD(INT index) SWITCH index CASE 0 RETURN << -1435.61, 5781.12, -29.87 >> BREAK CASE 1 RETURN << -1956.54, -1125.07, -37.21 >> BREAK CASE 2 RETURN << 2752.88, -1212.78, -22.41 >> BREAK CASE 3 RETURN << 3188.04, -1668.19, -146.88 >> BREAK CASE 4 RETURN << 2555.04, -2372.47, -112.01 >> BREAK CASE 5 RETURN << 2945.90, 6537.41, -27.36 >> BREAK CASE 6 RETURN << -1266.69, 6261.75, -34.17 >> BREAK CASE 7 RETURN << 3034.72, 6550.42, -35.20 >> BREAK CASE 8 RETURN << 1694.53, 6991.69, -137.62 >> BREAK CASE 9 RETURN << 1233.43, 7081.15, -141.72 >> BREAK CASE 10 RETURN << -3413.73, 830.23, -12.95 >> BREAK CASE 11 RETURN << 1422.50, 6854.67, -38.20 >> BREAK CASE 12 RETURN << -3345.10, 3547.80, -59.10 >> BREAK CASE 13 RETURN << -3437.93, 3069.57, -54.85 >> BREAK CASE 14 RETURN << -2909.28, 4204.32, -111.62 >> BREAK CASE 15 RETURN << -3179.12, 2151.28, -31.86 >> BREAK CASE 16 RETURN << 4146.09, 3825.86, -40.96 >> BREAK CASE 17 RETURN << 2716.61, 6956.91, -157.17 >> BREAK CASE 18 RETURN << 2487.50, 7001.69, -143.56 >> BREAK CASE 19 RETURN << -3043.23, -212.16, -23.48 >> BREAK CASE 20 RETURN << -2871.10, 4268.19, -152.47 >> BREAK CASE 21 RETURN << -777.21, 6726.71, -30.89 >> BREAK CASE 22 RETURN << -3008.33, 2877.73, -27.76 >> BREAK CASE 23 RETURN << -1843.12, -1260.67, -22.17 >> BREAK CASE 24 RETURN << -2591.62, -470.34, -30.40 >> BREAK CASE 25 RETURN << 3824.99, 3729.17, -16.17 >> BREAK CASE 26 RETURN << 3885.44, 3797.19, -24.26 >> BREAK CASE 27 RETURN << 2153.90, -2826.37, -50.76 >> BREAK CASE 28 RETURN << 1873.50, -3012.60, -47.00 >> BREAK CASE 29 RETURN << -2325.06, -1046.70, -70.67 >> BREAK ENDSWITCH SCRIPT_ASSERT("Ambient Sonar: Invalid index passed to GET_SONAR_COORD()") RETURN << 0.0, 0.0, 0.0 >> ENDFUNC /// PURPOSE: /// Fill Sonar Scrap Array PROC INITIALIZE_SONAR_SCRAP_POSITIONS() sSonarPickups[0].vCoords = GET_SONAR_COORD(0) sSonarPickups[0].fHeading = 179.47 sSonarPickups[1].vCoords = GET_SONAR_COORD(1) sSonarPickups[1].fHeading = 104.00 sSonarPickups[2].vCoords = GET_SONAR_COORD(2) sSonarPickups[2].fHeading = 321.50 sSonarPickups[3].vCoords = GET_SONAR_COORD(3) sSonarPickups[3].fHeading = -29.79 sSonarPickups[4].vCoords = GET_SONAR_COORD(4) sSonarPickups[4].fHeading = -165.60 sSonarPickups[5].vCoords = GET_SONAR_COORD(5) sSonarPickups[5].fHeading = 116.00 sSonarPickups[6].vCoords = GET_SONAR_COORD(6) sSonarPickups[6].fHeading = -68.65 sSonarPickups[7].vCoords = GET_SONAR_COORD(7) sSonarPickups[7].fHeading = 40.00 sSonarPickups[8].vCoords = GET_SONAR_COORD(8) sSonarPickups[8].fHeading = 40.00 sSonarPickups[9].vCoords = GET_SONAR_COORD(9) sSonarPickups[9].fHeading = 40.00 sSonarPickups[10].vCoords = GET_SONAR_COORD(10) sSonarPickups[10].fHeading = 40.00 sSonarPickups[11].vCoords = GET_SONAR_COORD(11) sSonarPickups[11].fHeading = 27.04 sSonarPickups[12].vCoords = GET_SONAR_COORD(12) sSonarPickups[12].fHeading = 40.00 sSonarPickups[13].vCoords = GET_SONAR_COORD(13) sSonarPickups[13].fHeading = 40.00 sSonarPickups[14].vCoords = GET_SONAR_COORD(14) sSonarPickups[14].fHeading = 40.00 sSonarPickups[15].vCoords = GET_SONAR_COORD(15) sSonarPickups[15].fHeading = 40.00 sSonarPickups[16].vCoords = GET_SONAR_COORD(16) sSonarPickups[16].vRot = <<89.94, 61.93, 90.94>> sSonarPickups[17].vCoords = GET_SONAR_COORD(17) sSonarPickups[17].fHeading = 40.00 sSonarPickups[18].vCoords = GET_SONAR_COORD(18) sSonarPickups[18].fHeading = 40.00 sSonarPickups[19].vCoords = GET_SONAR_COORD(19) sSonarPickups[19].fHeading = 40.00 sSonarPickups[20].vCoords = GET_SONAR_COORD(20) sSonarPickups[20].fHeading = 40.00 sSonarPickups[21].vCoords = GET_SONAR_COORD(21) sSonarPickups[21].fHeading = 40.00 sSonarPickups[22].vCoords = GET_SONAR_COORD(22) sSonarPickups[22].fHeading = 40.00 sSonarPickups[23].vCoords = GET_SONAR_COORD(23) sSonarPickups[23].fHeading = 40.00 sSonarPickups[24].vCoords = GET_SONAR_COORD(24) sSonarPickups[24].fHeading = 40.00 sSonarPickups[25].vCoords = GET_SONAR_COORD(25) sSonarPickups[25].fHeading = 198.00 sSonarPickups[26].vCoords = GET_SONAR_COORD(26) sSonarPickups[26].fHeading = 198.00 sSonarPickups[27].vCoords = GET_SONAR_COORD(27) sSonarPickups[27].fHeading = 198.00 sSonarPickups[28].vCoords = GET_SONAR_COORD(28) sSonarPickups[28].fHeading = 198.00 sSonarPickups[29].vCoords = GET_SONAR_COORD(29) sSonarPickups[29].fHeading = -109.43 SET_PICKUPS_ACTIVE_TO_FALSE(sSonarPickups) // Init cull sphere tracking vars INT i REPEAT NUMBER_OF_SONAR_PICKUPS i iSphereIndexOnPickup[i] = -1 ENDREPEAT ENDPROC /// PURPOSE: /// Sets the nearest coord on trackify device PROC SET_NEAREST_SCRAP_COORD_ON_TRACKIFY() SET_TRACKIFY_TARGET_VECTOR(GET_SONAR_COORD(iNearestScrapIndex), TRUE, TRUE) iTrackifyUpdateCounter = 1 ENDPROC /// PURPOSE: /// Prevent certain pickups from creating the grass cull sphere /// PARAMS: /// iCurrentPickup - pickup to check /// RETURNS: /// TRUE if we need to create a cull sphere on this pickup FUNC BOOL CULL_SPHERE_NEEDED_FOR_PICKUP(INT iCurrentPickup) IF iCurrentPickup = 23 // End of the pier - not on proc mesh and right by a peyote pickup RETURN FALSE ENDIF RETURN TRUE ENDFUNC /// PURPOSE: /// Handles which grass cull sphere is active, if any /// PARAMS: /// iCurrentScrap - scrap index to check /// bCollected - if the scrap is collected (only need to worry about cleaning up existing cull sphere in this case) PROC HANDLE_CULL_SPHERE(INT iCurrentPickup, BOOL bCollected) IF CULL_SPHERE_NEEDED_FOR_PICKUP(iCurrentPickup) = FALSE EXIT ENDIF IF iSphereIndexOnPickup[iCurrentPickup] = -1 IF NOT bCollected AND NOT IS_ENTITY_DEAD(PLAYER_PED_ID()) IF VDIST2(GET_ENTITY_COORDS(PLAYER_PED_ID()), sSonarPickups[iCurrentPickup].vCoords) < (CREATE_CULL_SPHERE_DISTANCE*CREATE_CULL_SPHERE_DISTANCE) INT iSphere IF IS_A_CULLSPHERE_AVAILABLE(iSphere) CPRINTLN(DEBUG_AMBIENT, "Adding grass cull sphere ", iSphere, " on pickup ", iCurrentPickup) PROCGRASS_ENABLE_CULLSPHERE(iSphere, sSonarPickups[iCurrentPickup].vCoords, 8.0) iSphereIndexOnPickup[iCurrentPickup] = iSphere ENDIF ENDIF ENDIF ELSE IF NOT IS_ENTITY_DEAD(PLAYER_PED_ID()) IF VDIST2(GET_ENTITY_COORDS(PLAYER_PED_ID()), sSonarPickups[iCurrentPickup].vCoords) > (REMOVE_CULL_SPHERE_DISTANCE*REMOVE_CULL_SPHERE_DISTANCE) CPRINTLN(DEBUG_AMBIENT, "Removing the grass cull sphere ", iSphereIndexOnPickup[iCurrentPickup], " on pickup ", iCurrentPickup) IF iSphereIndexOnPickup[iCurrentPickup] >= 0 AND iSphereIndexOnPickup[iCurrentPickup] < NUMBER_AVAILABLE_CULLSPHERES PROCGRASS_DISABLE_CULLSPHERE(iSphereIndexOnPickup[iCurrentPickup]) iSphereIndexOnPickup[iCurrentPickup] = -1 ENDIF ENDIF ENDIF ENDIF ENDPROC /// PURPOSE: /// Updates the scrap array /// PARAMS: /// data - mission scrap data reference /// array - reference to mission scrap array /// extarray - reference to scrap extras array /// iCurrentIndex - reference to the current index we are updating FUNC BOOL UPDATE_SONAR_PICKUPS(SCRAP_MISSION_DATA &missionData, SCRAP_PICKUP_DATA &pickupData[]) INT i VECTOR vPos BOOL bScrapCollected // cache the player position and do is injured check to stop asserts IS_PED_INJURED(PLAYER_PED_ID()) vPos = GET_ENTITY_COORDS(PLAYER_PED_ID()) REPEAT iScrapsPerFrame i bScrapCollected = HAS_SCRAP_BEEN_COLLECTED(missionData.scrapData, missionData.iCurrentCheckIndex) // If the pickup isn't active... IF NOT pickupData[missionData.iCurrentCheckIndex].bActive // And hasn't yet been collected... IF NOT bScrapCollected IF NOT ARE_VECTORS_EQUAL(pickupData[missionData.iCurrentCheckIndex].vRot, <<0,0,0>>) CREATE_SCRAP_WHEN_IN_RANGE(pickupData[missionData.iCurrentCheckIndex], missionData.packageMdl, PICKUP_CUSTOM_SCRIPT, FALSE, TRUE, EULER_XYZ) ELSE CREATE_SCRAP_WHEN_IN_RANGE(pickupData[missionData.iCurrentCheckIndex], missionData.packageMdl) ENDIF ENDIF ELSE // Check for collecting pickup IF (NOT bScrapCollected) // Update trackify and credit bank account when collecting a pickup IF UPDATE_SCRAP_PICKUP(missionData, pickupData, vPos) IF GET_NEAREST_PICKUP_INDEX(missionData, pickupData, vPos, iNearestScrapIndex) PROPERTY_PAY_INCOME(PROPERTY_SONAR_COLLECTIONS, 23000) SET_NEAREST_SCRAP_COORD_ON_TRACKIFY() ENDIF ENDIF ENDIF ENDIF // Toggle the grass cull sphere on or off HANDLE_CULL_SPHERE(missionData.iCurrentCheckIndex, bScrapCollected) // Increase the current index - make sure it doesn't overrun missionData.iCurrentCheckIndex ++ IF (missionData.iCurrentCheckIndex >= COUNT_OF(pickupData)) missionData.iCurrentCheckIndex = 0 ENDIF ENDREPEAT IF NOT g_bResultScreenDisplaying UPDATE_DISPLAY_MESSAGE(missionData.bDisplayMessage, missionData.bMessageOnDisplay, missionData.iMessageTimer, SCRAP_SUB, iMessageStage, siMessage, "SUBM_TITLE", "SUBM_COLLECT") ELSE CDEBUG1LN(debug_ambient,"Can't display diving message, results screen is currently active") ENDIF IF (missionData.scrapData.iScrapsCollected >= missionData.scrapData.iMaxScraps) CPRINTLN(DEBUG_AMBIENT, "Sonar Pickups: Turning off Trackify") REMOVE_TRACKIFY_TARGET() ENABLE_SECOND_SCREEN_TRACKIFY_APP(FALSE) HANG_UP_AND_PUT_AWAY_PHONE() ENDIF // Send the complete flag once everything is collected and messsage has stopped IF NOT missionData.bMessageOnDisplay AND NOT missionData.bDisplayMessage RETURN (missionData.scrapData.iScrapsCollected >= missionData.scrapData.iMaxScraps) ENDIF RETURN FALSE ENDFUNC //---------------------- // DEBUG FUNCTIONS //---------------------- #IF IS_DEBUG_BUILD /// PURPOSE: /// Setups Debug Widgets PROC SETUP_DEBUG_WIDGETS(SCRAP_MISSION_DATA &missionData, SCRAP_PICKUP_DATA& pickupData[]) INT iScrap TEXT_LABEL_63 tlTemp mWidgetGroup = START_WIDGET_GROUP("Ambient: Sonar Collections") ADD_WIDGET_BOOL("Force Quit Script", bDebugQuitScript) ADD_WIDGET_BOOL("Allow debug tty", bShowScrapDebugTTY) ADD_WIDGET_BOOL("Allow Debug Warping", bDebugAllowWarping) ADD_WIDGET_BOOL("Show all scraps on map", bMapAllScraps) ADD_WIDGET_BOOL("Create Submersible", bCreateSub) ADD_WIDGET_INT_SLIDER("Scraps Per Frame", iScrapsPerFrame, 1, COUNT_OF(pickupData), 1) START_WIDGET_GROUP("Collection") ADD_WIDGET_BOOL("Collect all scraps", bCollectAllScraps) ADD_WIDGET_BOOL("Reset scraps collection", bResetScrapCollection) ADD_WIDGET_BOOL("Simulate Scrap Collect", bSimulateScrapCollect) ADD_WIDGET_INT_SLIDER("Sim Scraps to Collect", iSimulateScrapCollect, 1, COUNT_OF(pickupData), 1) STOP_WIDGET_GROUP() START_WIDGET_GROUP("Stats") ADD_WIDGET_BOOL("Track Restart Help Shown", bTrkRestartHelpDisplayed) ADD_WIDGET_INT_READ_ONLY("Scraps Collected", missionData.scrapData.iScrapsCollected) ADD_WIDGET_INT_READ_ONLY("Total Scraps", missionData.scrapData.iMaxScraps) ADD_WIDGET_INT_READ_ONLY("Nearest Scrap", iNearestScrapIndex) ADD_WIDGET_INT_READ_ONLY("Trackify Update", iTrackifyUpdateCounter) STOP_WIDGET_GROUP() START_WIDGET_GROUP("Positions") REPEAT COUNT_OF(pickupData) iScrap tlTemp = "Scrap " tlTemp += iScrap START_WIDGET_GROUP(tlTemp) ADD_WIDGET_BOOL("bWarp", bWarpToScrap[iScrap]) ADD_WIDGET_FLOAT_READ_ONLY("X Position", pickupData[iScrap].vCoords.x) ADD_WIDGET_FLOAT_READ_ONLY("Y Position", pickupData[iScrap].vCoords.y) ADD_WIDGET_FLOAT_READ_ONLY("Z Position", pickupData[iScrap].vCoords.z) STOP_WIDGET_GROUP() ENDREPEAT STOP_WIDGET_GROUP() STOP_WIDGET_GROUP() ENDPROC /// PURPOSE: /// Updates all The Widgets PROC UPDATE_DEBUG_WIDGETS(SCRAP_MISSION_DATA &missionData, SCRAP_PICKUP_DATA &pickupData[]) INT i INT cnt = 0 VEHICLE_INDEX sub VECTOR pos IF (bResetScrapCollection) CPRINTLN(DEBUG_AMBIENT, "Ambient Sonar: Resetting all sonar pickups...") STAT_SET_INT(missionData.packageStat, 0) REPEAT COUNT_OF(pickupData) i SAFE_REMOVE_PICKUP(pickupData[i].pickup) SAFE_REMOVE_BLIP(pickupData[i].blip) SET_SCRAP_AS_COLLECTED(missionData.scrapData, i, FALSE) pickupData[i].bActive = FALSE ENDREPEAT SET_PACKED_STATS_FROM_SCRAP_COLLECT_DATA(missionData.scrapData) bResetScrapCollection = FALSE bMapAllScraps = TRUE SET_AUTOSAVE_IGNORES_ON_MISSION_FLAG(TRUE) MAKE_AUTOSAVE_REQUEST() ENDIF IF (bSimulateScrapCollect) CPRINTLN(DEBUG_AMBIENT, "Ambient Sonar: Collecting sonar pickup: ", iSimulateScrapCollect) REPEAT COUNT_OF(pickupData) i IF NOT HAS_SCRAP_BEEN_COLLECTED(missionData.scrapData, i) COLLECT_SCRAP(missionData, pickupData, i) cnt ++ ENDIF IF (cnt >= iSimulateScrapCollect) i = COUNT_OF(pickupData) + 1 // so we break out of array ENDIF ENDREPEAT bMapAllScraps = FALSE bSimulateScrapCollect = FALSE SET_AUTOSAVE_IGNORES_ON_MISSION_FLAG(TRUE) MAKE_AUTOSAVE_REQUEST() ENDIF IF (bCollectAllScraps) CPRINTLN(DEBUG_AMBIENT, "Ambient Sonar: Collecting all sonar pickups...") STAT_SET_INT(missionData.packageStat, 0) REPEAT COUNT_OF(pickupData) i COLLECT_SCRAP(missionData, pickupData, i) ENDREPEAT bCollectAllScraps = FALSE bMapAllScraps = FALSE SET_AUTOSAVE_IGNORES_ON_MISSION_FLAG(TRUE) MAKE_AUTOSAVE_REQUEST() ENDIF IF (bMapAllScraps) BLIP_SCRAP_POSITIONS(missionData, pickupData) bMapAllScraps = FALSE ENDIF // Handle warping IF (bDebugAllowWarping) REPEAT COUNT_OF(pickupData) i IF (bWarpToScrap[i]) CPRINTLN(DEBUG_AMBIENT, "Ambient Sonar: Warping to sonar pickup: ", i) LOAD_SCENE(pickupData[i].vCoords) IF IS_ENTITY_ALIVE(PLAYER_PED_ID()) IF IS_PED_IN_ANY_SUB(PLAYER_PED_ID()) SET_ENTITY_COORDS(GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()), pickupData[i].vCoords + <<0.0, 0.0, 10.0>>) ELSE SET_ENTITY_COORDS(PLAYER_PED_ID(), pickupData[i].vCoords + <<0.0, 0.0, 10.0>>) bCreateSub = TRUE ENDIF SET_ENTITY_HEADING(PLAYER_PED_ID(), 0.0) ENDIF bWarpToScrap[i] = FALSE ENDIF ENDREPEAT ENDIF IF (bCreateSub) IF IS_ENTITY_ALIVE(PLAYER_PED_ID()) IF NOT IS_PED_IN_ANY_SUB(PLAYER_PED_ID()) AND IS_ENTITY_IN_WATER(PLAYER_PED_ID()) SECURE_REQUEST_AND_LOAD_MODEL(SUBMERSIBLE) i = 0 IS_ENTITY_OK(PLAYER_PED_ID()) pos = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(PLAYER_PED_ID(), <<0, 0, 5.0>>) WHILE (i = 0) sub = CREATE_VEHICLE(SUBMERSIBLE, pos) IF DOES_ENTITY_EXIST(sub) CPRINTLN(DEBUG_AMBIENT, "Sonar Pickups: Player warped into Submarine.") SET_PED_INTO_VEHICLE(PLAYER_PED_ID(), sub) i = 1 ENDIF ENDWHILE ENDIF ENDIF bCreateSub = FALSE ENDIF ENDPROC /// PURPOSE: /// Cleans up All The Widgets PROC CLEANUP_DEBUG_WIDGETS() IF DOES_WIDGET_GROUP_EXIST(mWidgetGroup) DELETE_WIDGET_GROUP(mWidgetGroup) ENDIF ENDPROC #ENDIF //---------------------- // SCRIPT FUNCTIONS //---------------------- /// PURPOSE: /// Add rewards and clean up script PROC SCRIPT_PASS() CPRINTLN(DEBUG_AMBIENT, "Ambient Sonar: All sonar pickups have been collected") PROPERTY_PAY_INCOME(PROPERTY_SONAR_COLLECTIONS, 250000) //extra reward REGISTER_SCRIPT_IN_COMPLETION_PERCENTAGE_TOTAL (CP_SONCOLL) AWARD_ACHIEVEMENT(ACH17) // Waste Management REQUEST_SYSTEM_ACTIVITY_TYPE_COLLECTED_SONAR() // Push a PS4 activity feed message. SET_STAGE(MS_CLEANUP) ENDPROC /// PURPOSE: /// Script Cleanup PROC SCRIPT_CLEANUP() CPRINTLN(DEBUG_AMBIENT, "Ambient Sonar: Cleanup!") SET_MAX_WANTED_LEVEL(5) #IF IS_DEBUG_BUILD CLEANUP_DEBUG_WIDGETS() #ENDIF // Release submersible RELEASE_SUB() INT i REPEAT COUNT_OF(sSonarPickups) i SAFE_REMOVE_BLIP(sSonarPickups[i].blip) SAFE_REMOVE_PICKUP(sSonarPickups[i].pickup) IF iSphereIndexOnPickup[i] >= 0 AND iSphereIndexOnPickup[i] < NUMBER_AVAILABLE_CULLSPHERES PROCGRASS_DISABLE_CULLSPHERE(iSphereIndexOnPickup[i]) ENDIF ENDREPEAT IF HAVE_ALL_SCRAPS_BEEN_COLLECTED(sMissionData.scrapData) CPRINTLN(DEBUG_AMBIENT, "Ambient Sonar: All Parts Collected - Removing Ambient Script") Remove_Script_From_Relaunch_List(LAUNCH_BIT_RC_AMB_SONAR_COLLECTION) ENDIF // Ensure Trackify app is disabled CPRINTLN(DEBUG_AMBIENT, "Sonar Pickups: Turning off Trackify") REMOVE_TRACKIFY_TARGET() ENABLE_SECOND_SCREEN_TRACKIFY_APP(FALSE) HANG_UP_AND_PUT_AWAY_PHONE() SET_MODEL_AS_NO_LONGER_NEEDED(sMissionData.packageMdl) TERMINATE_THIS_THREAD() ENDPROC //---------------------- // STATES //---------------------- /// PURPOSE: /// Initialization PROC DO_INITALIZE() iMessageStage = 0 INITIALIZE_SONAR_SCRAP_POSITIONS() SETUP_SCRAP_MISSION(sMissionData, SCRAP_SUB, Prop_Rad_Waste_Barrel_01, "SUBM_COLLECT") SETUP_SCRAP_MISSION_STATS(sMissionData, NUM_HIDDEN_PACKAGES_3, PACKSTAT_SONAR_START, NUMBER_OF_SONAR_PICKUPS) #IF IS_DEBUG_BUILD SETUP_DEBUG_WIDGETS(sMissionData, sSonarPickups) #ENDIF IF IS_ENTITY_ALIVE(PLAYER_PED_ID()) IF IS_PED_IN_ANY_SUB(PLAYER_PED_ID()) CPRINTLN(DEBUG_AMBIENT, "Ambient Sonar: Initial stage set to MS_IN_SUB") SET_MAX_WANTED_LEVEL(0) SET_STAGE(MS_IN_SUB) ELSE CPRINTLN(DEBUG_AMBIENT, "Ambient Sonar: Initial stage set to MS_OUT_OF_SUB") SET_MAX_WANTED_LEVEL(5) SET_STAGE(MS_OUT_OF_SUB) ENDIF ENDIF ENDPROC /// PURPOSE: /// Set the position nearest sonar pickup on the Trackify app /// Only updates when the player is in water PROC UPDATE_TRACKIFY_APP() iTrackifyUpdateCounter ++ IF (iTrackifyUpdateCounter % 30 = 0) OR (iNearestScrapIndex = -1) IF GET_NEAREST_PICKUP_INDEX(sMissionData, sSonarPickups, GET_ENTITY_COORDS(PLAYER_PED_ID()), iNearestScrapIndex) SET_NEAREST_SCRAP_COORD_ON_TRACKIFY() ENDIF ENDIF ENDPROC /// PURPOSE: /// Handle player when they are in a submarine PROC STAGE_IN_SUB() // Detect the player exiting the submarine IF IS_ENTITY_ALIVE(PLAYER_PED_ID()) IF NOT IS_PED_IN_ANY_SUB(PLAYER_PED_ID()) CPRINTLN(DEBUG_AMBIENT, "Ambient Sonar: Player exited submarine, deactivate Trackify...") ENABLE_SECOND_SCREEN_TRACKIFY_APP(FALSE) HANG_UP_AND_PUT_AWAY_PHONE() SET_MAX_WANTED_LEVEL(5) SET_STAGE(MS_OUT_OF_SUB) ELSE // Display help for using Trackify to locate sonar pickups IF NOT HAS_ONE_TIME_HELP_DISPLAYED(FHM_SONAR_COLLECT_LOAD_TRACKIFY) CPRINTLN(DEBUG_AMBIENT, "Ambient Sonar: Help - Follow the sonar blips on Trackify to locate treasure lost on the sea bed.") ADD_HELP_TO_FLOW_QUEUE("SUBM_HELP1", FHP_MEDIUM) SET_ONE_TIME_HELP_MESSAGE_DISPLAYED(FHM_SONAR_COLLECT_LOAD_TRACKIFY) ENDIF // Display help for restarting trackify if the player cancels it IF NOT IS_CELLPHONE_TRACKIFY_IN_USE() ENABLE_SECOND_SCREEN_TRACKIFY_APP(TRUE) IF NOT bTrkRestartHelpDisplayed AND NOT (sMissionData.scrapData.iScrapsCollected >= sMissionData.scrapData.iMaxScraps) //if completed all scraps, we don't want this message CPRINTLN(DEBUG_AMBIENT, "Ambient Sonar: Help - To restart Trackify, select the Trackify app on the second page of the mobile phone.") ADD_HELP_TO_FLOW_QUEUE("SUBM_TRKHELP", FHP_MEDIUM) bTrkRestartHelpDisplayed = TRUE ENDIF ENDIF // Update trackify app - all characters can use this now UPDATE_TRACKIFY_APP() // Update sonar pickups IF UPDATE_SONAR_PICKUPS(sMissionData, sSonarPickups) SCRIPT_PASS() ENDIF ENDIF ENDIF ENDPROC /// PURPOSE: /// Handles the player when outside of a submarine PROC STAGE_OUT_OF_SUB() // Reset help message when the player gets out of the submarine bTrkRestartHelpDisplayed = FALSE IF IS_ENTITY_ALIVE(PLAYER_PED_ID()) IF IS_PLAYER_PLAYING(PLAYER_ID()) // Update sonar pickups - currently we are allowing the player to collect whilst swimming... IF UPDATE_SONAR_PICKUPS(sMissionData, sSonarPickups) SCRIPT_PASS() ELSE // Player has entered submarine IF IS_PED_IN_ANY_SUB(PLAYER_PED_ID()) CPRINTLN(DEBUG_AMBIENT, "Ambient Sonar: Player is in submarine, activate Trackify...") viSub = GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID()) // Launch trackify ENABLE_SECOND_SCREEN_TRACKIFY_APP(TRUE) LAUNCH_TRACKIFY_IMMEDIATELY() IF IS_ENTITY_ALIVE(PLAYER_PED_ID()) IF GET_NEAREST_PICKUP_INDEX(sMissionData, sSonarPickups, GET_ENTITY_COORDS(PLAYER_PED_ID()), iNearestScrapIndex) SET_NEAREST_SCRAP_COORD_ON_TRACKIFY() ENDIF ENDIF // Cannot get wanted in submersible SET_MAX_WANTED_LEVEL(0) // Remove blip REMOVE_SUB_BLIP() // Player has entered submarine SET_STAGE(MS_IN_SUB) ELSE // Blip the sub! IF IS_ENTITY_ALIVE(viSub) IF VDIST2(GET_ENTITY_COORDS(PLAYER_PED_ID()), GET_ENTITY_COORDS(viSub)) > 250*250 RELEASE_SUB() CPRINTLN(DEBUG_AMBIENT, "Ambient Sonar: Sub status = OUT OF RANGE!") ELSE IF NOT DOES_BLIP_EXIST(biSub) biSub = CREATE_BLIP_FOR_VEHICLE(viSub) SET_BLIP_SPRITE(biSub, RADAR_TRACE_SUB) ENDIF ENDIF ELSE // Remove blip REMOVE_SUB_BLIP() ENDIF ENDIF ENDIF ENDIF ENDIF ENDPROC //---------------------- // MAIN SCRIPT //---------------------- SCRIPT IF HAS_FORCE_CLEANUP_OCCURRED(FORCE_CLEANUP_FLAG_DEBUG_MENU|FORCE_CLEANUP_FLAG_SP_TO_MP|FORCE_CLEANUP_FLAG_REPEAT_PLAY|FORCE_CLEANUP_FLAG_DIRECTOR) SCRIPT_CLEANUP() ENDIF IF GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH (HASH("ambient_Sonar")) > 1 CPRINTLN(DEBUG_AMBIENT, "Ambient Sonar: Attempting to launch with an instance already active...") TERMINATE_THIS_THREAD() ENDIF // Register the script so that it can be relaunched when loading from a savegame. Register_Script_To_Relaunch_List(LAUNCH_BIT_RC_AMB_SONAR_COLLECTION) // Setup Arrays and everything else CPRINTLN(DEBUG_AMBIENT, "Ambient Sonar: Initializing.. - Version:", XVERSION_NUMBER) // Ensure Trackify app is disabled ENABLE_SECOND_SCREEN_TRACKIFY_APP(FALSE) // Main loop WHILE (TRUE) WAIT(0) IS_ENTITY_OK(PLAYER_PED_ID()) SWITCH eStage CASE MS_INIT DO_INITALIZE() BREAK CASE MS_IN_SUB STAGE_IN_SUB() BREAK CASE MS_OUT_OF_SUB STAGE_OUT_OF_SUB() BREAK CASE MS_CLEANUP SCRIPT_CLEANUP() BREAK ENDSWITCH // Debug widgets #IF IS_DEBUG_BUILD UPDATE_DEBUG_WIDGETS(sMissionData, sSonarPickups) IF (bDebugQuitScript) SCRIPT_CLEANUP() ENDIF #ENDIF ENDWHILE ENDSCRIPT