Files
2025-09-29 00:52:08 +02:00

920 lines
30 KiB
Python
Executable File

//////////////////////////////////////////////////////////////////////////////////////////
// //
// SCRIPT NAME : epsDesert.sc //
// AUTHOR : Sam Hackett //
// DESCRIPTION : Monitors the player to see when he has //
// run x miles in the desert. //
// //
//////////////////////////////////////////////////////////////////////////////////////////
//Compile out Title Update changes to header functions.
//Must be before includes.
//CONST_INT USE_TU_CHANGES 0 // Removed by Kenneth R.
// Includes
USING "rage_builtins.sch"
USING "globals.sch"
USING "commands_entity.sch"
USING "commands_hud.sch"
USING "commands_object.sch"
USING "commands_script.sch"
USING "commands_streaming.sch"
USING "commands_zone.sch"
USING "CompletionPercentage_public.sch"
USING "flow_public_core.sch"
USING "player_ped_public.sch"
USING "script_player.sch"
USING "flow_public_game.sch"
USING "RC_Helper_Functions.sch"
USING "script_conversion.sch"
// Constants
PED_COMP_NAME_ENUM EPSILON_OUTFIT = OUTFIT_P0_EPSILON_WITH_MEDAL
CONST_FLOAT DEBUG_INFO_X 0.8
CONST_FLOAT DEBUG_INFO_Y 0.3
CONST_FLOAT METRES_PER_MILE 1609.0
CONST_FLOAT METRES_PER_TENTH_MILE 160.9
CONST_INT TARGET_MILES 5
CONST_FLOAT MINIMUM_CHAT_DELAY 120000.0
CONST_FLOAT MAXIMUM_CHAT_DELAY 240000.0
PED_INDEX pedMarnie
PED_INDEX pedJimmy
PED_INDEX pedTom
structPedsForConversation ConvStruct
BOOL bGotMarnie
BOOL bGotJimmy
BOOL bGotTom
INT iConvTimer
FLOAT fNewThreshold
// Enums
ENUM DESERT_STAGE_ENUM
STAGE_INITIALISE = 0,
STAGE_PROCESS,
STAGE_CLEANUP
ENDENUM
// Variables
DESERT_STAGE_ENUM eStage = STAGE_INITIALISE
FLOAT DISTANCE_TO_RUN = METRES_PER_MILE * TARGET_MILES //FEET_PER_MILE * 50
BOOL bDisplayDebugInfo = FALSE
BOOL bForceOutfitOn = FALSE
BOOL bForceOutfitOff = FALSE
BOOL bAddMile = FALSE
VECTOR vPreviousPos
FLOAT fMessageMiles = 0.0
VECTOR vAbandonmentPos
BOOL bInZone = FALSE
BOOL bDoKifflom = FALSE
BOOL bDoChatter = FALSE
BOOL bDoCrisCall = FALSE
BOOL bDoAbandonmentWarning = TRUE
BOOL bDoAbandonmentReset = TRUE
INT iKifflomTimes = -1
INT iKifflomCount = 0
INT iKifflomDelay
INT iKifflomTimer
FLOAT fChatterDelay
INT iLastChatterTime
#IF IS_DEBUG_BUILD
USING "shared_debug.sch"
WIDGET_GROUP_ID widgetGroup
BOOL bDebug_PrintToTTY = TRUE
/// PURPOSE:
/// Initialises the widgets for the script
PROC SETUP_DESERT_WIDGETS()
widgetGroup = START_WIDGET_GROUP("Epsilon desert ambient")
ADD_WIDGET_FLOAT_SLIDER("Distance run (metres)", g_savedGlobals.sAmbient.fDistRunInDesert, 0.0, DISTANCE_TO_RUN, 0.1)
ADD_WIDGET_FLOAT_READ_ONLY("Target distance (metres)", DISTANCE_TO_RUN)
ADD_WIDGET_BOOL("Is player inside zone? (Don't try changing this)", bInZone)
ADD_WIDGET_BOOL("Enable on-screen progress info", bDisplayDebugInfo)
ADD_WIDGET_BOOL("Force outfit on", bForceOutfitOn)
ADD_WIDGET_BOOL("Force outfit off", bForceOutfitOff)
ADD_WIDGET_STRING("Tick this to add just under 1 mile to Michael's total - walk forward ~15 meters to trigger the next progress message")
ADD_WIDGET_BOOL("Add just under 0.1 miles to total run distance", bAddMile)
ADD_WIDGET_BOOL("Force Michael to play CULT_TALK (only works if player is inside the zone)", bDoChatter)
STOP_WIDGET_GROUP()
ENDPROC
/// PURPOSE:
/// Cleans up the widgets for the script
PROC CLEANUP_DESERT_WIDGETS()
IF DOES_WIDGET_GROUP_EXIST(widgetGroup)
DELETE_WIDGET_GROUP(widgetGroup)
ENDIF
ENDPROC
#ENDIF
FUNC BOOL IN_DIRECTOR_MODE_OR_TRANSITION()
IF IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_DIRECTOR)
RETURN TRUE
ELIF IS_SCREEN_FADED_OUT()
// If the screen is faded out, we might be transitioning out of Director Mode in the few frames before it teleports the player back to the old position
CPRINTLN(DEBUG_MISSION, "EpsDesert.sc - not in Director Mode, but the screen is faded out, pretending we are anyway...")
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// Tries to grab Marnie from the 32 closest peds around the player when called
/// RETURNS:
/// True if found Marnie
FUNC BOOL GrabMarnie()
INT cnt
INT i
PED_INDEX tmpArray[32]
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
cnt = GET_PED_NEARBY_PEDS(PLAYER_PED_ID(), tmpArray)
ENDIF
REPEAT cnt i
IF IS_ENTITY_ALIVE(tmpArray[i])
IF (GET_ENTITY_MODEL(tmpArray[i]) = GET_NPC_PED_MODEL(CHAR_MARNIE))
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_AMBIENT, "Eps Robes: - Marnie get!")
#ENDIF
pedMarnie = tmpArray[i]
IF NOT IS_ENTITY_A_MISSION_ENTITY(pedMarnie)
SET_ENTITY_AS_MISSION_ENTITY(pedMarnie)
ENDIF
SET_PED_MONEY(pedMarnie, 0)
SET_PED_CAN_BE_TARGETTED(pedMarnie, FALSE)
SET_PED_NAME_DEBUG(pedMarnie, "POSTMARNIE")
SET_PED_RELATIONSHIP_GROUP_HASH(pedMarnie, RELGROUPHASH_PLAYER)
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(pedMarnie, FALSE)
ADD_PED_FOR_DIALOGUE(ConvStruct, 4, pedMarnie, "MARNIE", TRUE)
RETURN TRUE
ENDIF
ENDIF
ENDREPEAT
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// Tries to grab Jimmy from the 32 closest peds around the player when called
/// RETURNS:
/// True if found Jimmy
FUNC BOOL GrabJimmy()
INT cnt
INT i
PED_INDEX tmpArray[32]
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
cnt = GET_PED_NEARBY_PEDS(PLAYER_PED_ID(), tmpArray)
ENDIF
REPEAT cnt i
IF IS_ENTITY_ALIVE(tmpArray[i])
IF (GET_ENTITY_MODEL(tmpArray[i]) = GET_NPC_PED_MODEL(CHAR_JIMMY_BOSTON))
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_AMBIENT, "Eps Robes: - Jimmy get!")
#ENDIF
pedJimmy = tmpArray[i]
IF NOT IS_ENTITY_A_MISSION_ENTITY(pedJimmy)
SET_ENTITY_AS_MISSION_ENTITY(pedJimmy)
ENDIF
SET_PED_MONEY(pedJimmy, 0)
SET_PED_CAN_BE_TARGETTED(pedJimmy, FALSE)
SET_PED_NAME_DEBUG(pedJimmy, "POSTJIMMY")
SET_PED_RELATIONSHIP_GROUP_HASH(pedJimmy, RELGROUPHASH_PLAYER)
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(pedJimmy, FALSE)
ADD_PED_FOR_DIALOGUE(ConvStruct, 3, pedJimmy, "JIMMYBOSTON", TRUE)
RETURN TRUE
ENDIF
ENDIF
ENDREPEAT
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// Tries to grab Tom from the 32 closest peds around the player when called
/// RETURNS:
/// True if found Tom
FUNC BOOL GrabTom()
INT cnt
INT i
PED_INDEX tmpArray[32]
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
cnt = GET_PED_NEARBY_PEDS(PLAYER_PED_ID(), tmpArray)
ENDIF
REPEAT cnt i
IF IS_ENTITY_ALIVE(tmpArray[i])
IF (GET_ENTITY_MODEL(tmpArray[i]) = IG_TOMEPSILON)
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_AMBIENT, "Eps Robes: - Tom get!")
#ENDIF
pedTom = tmpArray[i]
IF NOT IS_ENTITY_A_MISSION_ENTITY(pedTom)
SET_ENTITY_AS_MISSION_ENTITY(pedTom)
ENDIF
SET_PED_MONEY(pedTom, 0)
SET_PED_CAN_BE_TARGETTED(pedTom, FALSE)
SET_PED_NAME_DEBUG(pedTom, "POSTTOM")
SET_PED_RELATIONSHIP_GROUP_HASH(pedTom, RELGROUPHASH_PLAYER)
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(pedTom, FALSE)
ADD_PED_FOR_DIALOGUE(ConvStruct, 5, pedTom, "TOM", TRUE)
RETURN TRUE
ENDIF
ENDIF
ENDREPEAT
RETURN FALSE
ENDFUNC
/// PURPOSE: Sets up the ambient desert script
PROC DO_INITIALISE()
#IF IS_DEBUG_BUILD
IF bDebug_PrintToTTY
CPRINTLN(DEBUG_MISSION, "STAGE_INITIALISE")
ENDIF
#ENDIF
IF g_savedGlobals.sAmbient.fDistRunInDesert < DISTANCE_TO_RUN
bGotMarnie = GrabMarnie()
bGotJimmy = GrabJimmy()
bGotTom = GrabTom()
IF IS_PLAYER_PLAYING(PLAYER_ID())
IF DOES_ENTITY_EXIST(PLAYER_PED_ID())
IF NOT IS_ENTITY_DEAD(PLAYER_PED_ID())
vPreviousPos = GET_ENTITY_COORDS(PLAYER_PED_ID())
ENDIF
ENDIF
fMessageMiles = g_savedGlobals.sAmbient.fDistRunInDesert / METRES_PER_TENTH_MILE
fNewThreshold = (METRES_PER_MILE*TARGET_MILES)
eStage = STAGE_PROCESS
fChatterDelay = GET_RANDOM_FLOAT_IN_RANGE(MINIMUM_CHAT_DELAY, MAXIMUM_CHAT_DELAY)
iLastChatterTime = GET_GAME_TIMER()
#IF IS_DEBUG_BUILD
IF bDebug_PrintToTTY
CPRINTLN(DEBUG_AMBIENT, "STAGE_PROCESS")
ENDIF
#ENDIF
ENDIF
ELSE
eStage = STAGE_CLEANUP
ENDIF
ENDPROC
/// PURPOSE:
/// Occasional Epsilonism chatter while Michael is doing his desert run
PROC HANDLE_CHATTER()
IF NOT IS_CURRENTLY_ON_MISSION_OF_ANY_TYPE()
AND NOT IS_ENTITY_DEAD(PLAYER_PED_ID())
AND NOT IS_PED_INJURED(PLAYER_PED_ID())
AND NOT IS_AMBIENT_SPEECH_PLAYING(PLAYER_PED_ID())
IF bDoChatter = TRUE
IF IS_PED_WALKING(PLAYER_PED_ID()) // This will only sound right if Michael's walking
OR IS_PED_STILL(PLAYER_PED_ID())
PLAY_PED_AMBIENT_SPEECH(PLAYER_PED_ID(), "CULT_TALK", SPEECH_PARAMS_FORCE_FRONTEND)
fChatterDelay = GET_RANDOM_FLOAT_IN_RANGE(MINIMUM_CHAT_DELAY, MAXIMUM_CHAT_DELAY)
iLastChatterTime = GET_GAME_TIMER()
bDoChatter = FALSE
#IF IS_DEBUG_BUILD
IF bDebug_PrintToTTY
CPRINTLN(DEBUG_MISSION, "EpsDesert.sc - played Michael cult talk")
ENDIF
#ENDIF
ENDIF
ELSE
IF (GET_GAME_TIMER() - iLastChatterTime) > fChatterDelay
bDoChatter = TRUE // Do a bit of chatter
ENDIF
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Handle Michael's "kifflom" speech as he sprints in the desert
PROC HANDLE_CHANTS()
IF NOT IS_CURRENTLY_ON_MISSION_OF_ANY_TYPE()
AND NOT IS_ENTITY_DEAD(PLAYER_PED_ID())
AND NOT IS_PED_INJURED(PLAYER_PED_ID())
AND NOT IS_AMBIENT_SPEECH_PLAYING(PLAYER_PED_ID())
IF bDoKifflom = TRUE
// This should be -1 the first time we enter this function, then won't do anything until we start another chant
IF iKifflomTimes = -1
iKifflomTimes = GET_RANDOM_INT_IN_RANGE(2, 5)
iKifflomTimer = GET_GAME_TIMER()
iKifflomDelay = GET_RANDOM_INT_IN_RANGE(500, 750)
ENDIF
// Play a Kifflom if the count is less than the times we want
IF iKifflomCount < iKifflomTimes
IF NOT IS_AMBIENT_SPEECH_PLAYING(PLAYER_PED_ID())
// Check the delay before trying to play a Kifflom, to make it sound more natural
IF (GET_GAME_TIMER() - iKifflomTimer) >= iKifflomDelay
IF IS_PED_SPRINTING(PLAYER_PED_ID())
PLAY_PED_AMBIENT_SPEECH(PLAYER_PED_ID(), "KIFFLOM_SPRINTING", SPEECH_PARAMS_FORCE_FRONTEND)
ELSE
PLAY_PED_AMBIENT_SPEECH(PLAYER_PED_ID(), "KIFFLOM_RUNNING", SPEECH_PARAMS_FORCE_FRONTEND)
ENDIF
iKifflomCount++
iKifflomDelay = GET_RANDOM_INT_IN_RANGE(500, 750) // Get a new delay
#IF IS_DEBUG_BUILD
IF bDebug_PrintToTTY
CPRINTLN(DEBUG_MISSION, "EpsDesert: Mike Ambient speech")
ENDIF
#ENDIF
ELSE
#IF IS_DEBUG_BUILD
IF bDebug_PrintToTTY
CPRINTLN(DEBUG_MISSION, "EpsDesert: Delaying Kifflom by ", iKifflomDelay, "ms...")
ENDIF
#ENDIF
ENDIF
ELSE
iKifflomTimer = GET_GAME_TIMER() // Continually reset the timer while previous Kifflom is playing
ENDIF
ELSE
// Otherwise, we've played the amount we want, stop the chant and reset vars
iKifflomCount = 0
iKifflomTimes = -1
bDoKifflom = FALSE
ENDIF
ENDIF
ENDIF
ENDPROC
PROC HANDLE_RESET_INFO() // Epsilon pilgrimage abandoned. Come back another time to try again.
IF bDoAbandonmentReset
PRINT_HELP("EPSDES_WARN2")
bDoAbandonmentReset = FALSE
ENDIF
ENDPROC
PROC HANDLE_RESET_WARNING() // If you do not return to the desert, your Epsilonism pilgrimage will be abandoned.
IF bDoAbandonmentWarning
IF NOT IS_HELP_MESSAGE_BEING_DISPLAYED()
PRINT_HELP("EPSDES_WARN")
bDoAbandonmentWarning = FALSE
ENDIF
ENDIF
ENDPROC
PROC RESET_PROGRESS()
g_savedGlobals.sAmbient.fDistRunInDesert = 0
fMessageMiles = 0
fNewThreshold = (METRES_PER_MILE*TARGET_MILES)
ENDPROC
VECTOR vNewPlayerPos
STRING sZoneName
/// PURPOSE:
/// Add conditions for considering whether the player is in a valid robe area (including special cases)
/// RETURNS:
/// TRUE if in area, FALSE otherwise
FUNC BOOL IS_PLAYER_IN_AREA()
sZoneName = GET_NAME_OF_ZONE(vNewPlayerPos)
IF ARE_STRINGS_EQUAL(sZoneName, "DESRT")
OR ARE_STRINGS_EQUAL(sZoneName, "SENORA")
OR ARE_STRINGS_EQUAL(sZoneName, "HARMO")
OR ARE_STRINGS_EQUAL(sZoneName, "RTRAK")
OR ARE_STRINGS_EQUAL(sZoneName, "SANDY")
OR ARE_STRINGS_EQUAL(sZoneName, "Zancudo")
OR ARE_STRINGS_EQUAL(sZoneName, "Alamo")
OR ARE_STRINGS_EQUAL(sZoneName, "Jail")
OR ARE_STRINGS_EQUAL(sZoneName, "zQ_UAR")
OR ARE_STRINGS_EQUAL(sZoneName, "COSI")
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE: Monitors how far player has run within valid areas
PROC DO_PROCESS()
FLOAT fDist
PED_INDEX hPlayer
IF g_savedGlobals.sAmbient.fDistRunInDesert < DISTANCE_TO_RUN
IF bInZone = FALSE
IF NOT IS_VECTOR_ZERO(vAbandonmentPos)
AND NOT IN_DIRECTOR_MODE_OR_TRANSITION() // Fix for B*2193487
IF VDIST(vAbandonmentPos, GET_ENTITY_COORDS(PLAYER_PED_ID(), FALSE)) >= 10.0
RESET_PROGRESS()
vAbandonmentPos = <<0,0,0>>
HANDLE_RESET_INFO()
BEGIN_TEXT_COMMAND_THEFEED_POST("EPSDES_WIPE")
END_TEXT_COMMAND_THEFEED_POST_TICKER(FALSE)
ELSE
HANDLE_RESET_WARNING()
ENDIF
ENDIF
ENDIF
IF bGotMarnie
IF IS_ENTITY_ALIVE(pedMarnie)
// If the player is <=3m from Marnie, play one of his ambient lines, with an 8sec delay between them
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
AND NOT IS_PED_FLEEING(pedMarnie)
AND NOT IS_PED_RAGDOLL(pedMarnie)
AND NOT IS_PED_PRONE(pedMarnie)
AND NOT IS_PED_INJURED(pedMarnie)
IF GET_DISTANCE_BETWEEN_ENTITIES(pedMarnie, PLAYER_PED_ID()) <= 3.0
IF (GET_GAME_TIMER() - iConvTimer) > 8000
IF CREATE_CONVERSATION(ConvStruct, "EPSDAUD", "EPSD_FOLLOW", CONV_PRIORITY_MEDIUM)
iConvTimer = GET_GAME_TIMER()
ENDIF
ENDIF
ENDIF
ENDIF
IF GET_DISTANCE_BETWEEN_ENTITIES(pedMarnie, PLAYER_PED_ID()) > 150.0
SAFE_RELEASE_PED(pedMarnie) // Marnie won't be alive after this, it'll set the bool to false the frame after
ENDIF
ELSE
SAFE_RELEASE_PED(pedMarnie) // In case she still exists but is dead - no point holding onto the ped index anymore
bGotMarnie = FALSE
ENDIF
ENDIF
IF bGotJimmy
IF IS_ENTITY_ALIVE(pedJimmy)
// If the player is <=3m from Jimmy, play one of his ambient lines, with an 8sec delay between them
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
AND NOT IS_PED_FLEEING(pedJimmy)
AND NOT IS_PED_RAGDOLL(pedJimmy)
AND NOT IS_PED_PRONE(pedJimmy)
AND NOT IS_PED_INJURED(pedJimmy)
IF GET_DISTANCE_BETWEEN_ENTITIES(pedJimmy, PLAYER_PED_ID()) <= 3.0
IF (GET_GAME_TIMER() - iConvTimer) > 8000
IF CREATE_CONVERSATION(ConvStruct, "EPSDAUD", "EPSD_FOLJIM", CONV_PRIORITY_MEDIUM)
iConvTimer = GET_GAME_TIMER()
ENDIF
ENDIF
ENDIF
ENDIF
IF GET_DISTANCE_BETWEEN_ENTITIES(pedJimmy, PLAYER_PED_ID()) > 150.0
SAFE_RELEASE_PED(pedJimmy) // Jimmy won't be alive after this, it'll set the bool to false the frame after
ENDIF
ELSE
SAFE_RELEASE_PED(pedJimmy) // In case he still exists but is dead - no point holding onto the ped index anymore
bGotJimmy = FALSE
ENDIF
ENDIF
IF bGotTom
IF IS_ENTITY_ALIVE(pedTom)
// If the player is <=3m from Tom, play one of his ambient lines, with an 8sec delay between them
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
AND NOT IS_PED_FLEEING(pedTom)
AND NOT IS_PED_RAGDOLL(pedTom)
AND NOT IS_PED_PRONE(pedTom)
AND NOT IS_PED_INJURED(pedTom)
IF GET_DISTANCE_BETWEEN_ENTITIES(pedTom, PLAYER_PED_ID()) <= 3.0
IF (GET_GAME_TIMER() - iConvTimer) > 8000
IF CREATE_CONVERSATION(ConvStruct, "EPSDAUD", "EPSD_TOMFOL", CONV_PRIORITY_MEDIUM)
iConvTimer = GET_GAME_TIMER()
ENDIF
ENDIF
ENDIF
ENDIF
IF GET_DISTANCE_BETWEEN_ENTITIES(pedTom, PLAYER_PED_ID()) > 150.0
SAFE_RELEASE_PED(pedTom) // Tom won't be alive after this, it'll set the bool to false the frame after
ENDIF
ELSE
SAFE_RELEASE_PED(pedTom) // In case he still exists but is dead - no point holding onto the ped index anymore
bGotTom = FALSE
ENDIF
ENDIF
IF IS_PED_THE_CURRENT_PLAYER_PED(CHAR_MICHAEL)
IF IS_PLAYER_PLAYING(PLAYER_ID())
HANDLE_CHANTS()
IF DOES_ENTITY_EXIST(PLAYER_PED_ID())
IF NOT IS_ENTITY_DEAD(PLAYER_PED_ID())
vNewPlayerPos = GET_ENTITY_COORDS(PLAYER_PED_ID())
fDist = GET_DISTANCE_BETWEEN_COORDS(vPreviousPos, vNewPlayerPos)
vPreviousPos = vNewPlayerPos
ENDIF
ENDIF
IF IS_PED_ON_FOOT(PLAYER_PED_ID())
AND NOT IS_PED_FALLING(PLAYER_PED_ID())
AND NOT IS_PED_SWIMMING(PLAYER_PED_ID())
AND NOT IS_PED_ON_VEHICLE(PLAYER_PED_ID())
AND NOT IS_PED_RAGDOLL(PLAYER_PED_ID())
AND NOT IS_PED_PRONE(PLAYER_PED_ID())
AND NOT IS_PED_GETTING_UP(PLAYER_PED_ID())
IF IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<3155.104004,4091.060303,7.974625>>, <<-322.830872,2861.711914,250.525055>>, 2250.0)
//IF IS_ENTITY_AT_COORD(PLAYER_PED_ID(), << 1658.4313, 3410.6929, 35.7253 >>, <<2500,2500,2500>>)
IF IS_PED_COMP_ITEM_CURRENT_SP(PLAYER_PED_ID(), COMP_TYPE_OUTFIT, EPSILON_OUTFIT)
// PRINTSTRING("::::: ZONE: ") // Temp
// PRINTSTRING(sZoneName)
// PRINTSTRING("\n")
IF IS_PLAYER_IN_AREA()
AND NOT IN_DIRECTOR_MODE_OR_TRANSITION() // Fix for B*2193487
// Update notification text to tell player they're inside the zone
IF bInZone = FALSE
BEGIN_TEXT_COMMAND_THEFEED_POST("EPSDES_IN")
END_TEXT_COMMAND_THEFEED_POST_TICKER(FALSE)
bInZone = TRUE
ENDIF
HANDLE_CHATTER() // Only do the cult chatter if the player is in the area
IF fDist > 0.01
IF fDist > 0.4
fDist = 0.4
ENDIF
g_savedGlobals.sAmbient.fDistRunInDesert += fDist
IF DOES_CURRENT_LANGUAGE_USE_METRIC_SYSTEM()
IF g_savedGlobals.sAmbient.fDistRunInDesert >= 8000.0
g_savedGlobals.sAmbient.fDistRunInDesert = DISTANCE_TO_RUN
ENDIF
ENDIF
IF g_savedGlobals.sAmbient.fDistRunInDesert < (METRES_PER_MILE * TARGET_MILES)
AND ((METRES_PER_MILE*TARGET_MILES) - g_savedGlobals.sAmbient.fDistRunInDesert) < (fNewThreshold - METRES_PER_TENTH_MILE)
IF DOES_CURRENT_LANGUAGE_USE_METRIC_SYSTEM()
FLOAT fTemp = CONVERT_METERS_TO_KILOMETERS(g_savedGlobals.sAmbient.fDistRunInDesert)
fMessageMiles = fTemp
ELSE
FLOAT fTemp = (g_savedGlobals.sAmbient.fDistRunInDesert/METRES_PER_TENTH_MILE)
INT iMiles = FLOOR(fTemp)
FLOAT fTemp2 = TO_FLOAT(iMiles)
fTemp2 = fTemp2/10
fMessageMiles = fTemp2
ENDIF
fNewThreshold = (METRES_PER_MILE*TARGET_MILES)-g_savedGlobals.sAmbient.fDistRunInDesert
// If we're running metric, ignore the final 45m and skip to the goal now
IF DOES_CURRENT_LANGUAGE_USE_METRIC_SYSTEM()
IF fMessageMiles >= 7.95
g_savedGlobals.sAmbient.fDistRunInDesert = DISTANCE_TO_RUN
EXIT
ENDIF
ENDIF
// "You have walked x miles in the desert in your robes."
BEGIN_TEXT_COMMAND_THEFEED_POST("EPSDES_01")
ADD_TEXT_COMPONENT_FLOAT(fMessageMiles, 1)
END_TEXT_COMMAND_THEFEED_POST_TICKER(FALSE)
bDoKifflom = TRUE
MAKE_AUTOSAVE_REQUEST() // Autosave progress now
//Disabled for now as conflicts with mile notifications - will need to add a delay for each one
FLOAT fPenultimateCallDist
IF DOES_CURRENT_LANGUAGE_USE_METRIC_SYSTEM()
fPenultimateCallDist = 6.4
ELSE
fPenultimateCallDist = 4.0
ENDIF
IF fMessageMiles >= fPenultimateCallDist
IF NOT bDoCrisCall
#IF IS_DEBUG_BUILD
IF bDebug_PrintToTTY
CPRINTLN(DEBUG_AMBIENT, "Eps Desert: Hit 4 miles/6.4 km, schedule a call...")
ENDIF
#ENDIF
WHILE NOT REGISTER_CALL_FROM_CHARACTER_TO_PLAYER(CALL_EPSILON_DESERT_NEAR, CT_AMBIENT, BIT_MICHAEL, CHAR_CRIS, 6, 10000, 30000)
WAIT(0)
ENDWHILE
bDoCrisCall = TRUE
ENDIF
ENDIF
//SWITCH fMessageMiles
/*
CASE 1
#IF IS_DEBUG_BUILD
IF bDebug_PrintToTTY
CPRINTLN(DEBUG_MISSION, "Eps Desert: Hit 1 mile, send a text...")
ENDIF
WHILE REGISTER_TEXT_MESSAGE_FROM_CHARACTER_TO_PLAYER(CT_AMBIENT, BIT_MICHAEL, CHAR_MARNIE, "EPSDES_MARNIE",TXTMSG_UNLOCKED,TXTMSG_CRITICAL,500) = -1
WAIT(0)
ENDWHILE
#ENDIF
BREAK
CASE 2
#IF IS_DEBUG_BUILD
IF bDebug_PrintToTTY
CPRINTLN(DEBUG_MISSION, "Eps Desert: Hit 2 miles, send a text...")
ENDIF
WHILE REGISTER_TEXT_MESSAGE_FROM_CHARACTER_TO_PLAYER(CT_AMBIENT, BIT_MICHAEL, CHAR_JIMMY_BOSTON, "EPSDES_JIMMY",TXTMSG_UNLOCKED,TXTMSG_CRITICAL,500) = -1
WAIT(0)
ENDWHILE
#ENDIF
BREAK
CASE 3
#IF IS_DEBUG_BUILD
IF bDebug_PrintToTTY
CPRINTLN(DEBUG_MISSION, "Eps Desert: Hit 3 miles, schedule a call...")
ENDIF
WHILE REGISTER_CALL_FROM_CHARACTER_TO_PLAYER(CT_AMBIENT, BIT_MICHAEL, CHAR_TREVOR, 2, 500,"EPSDAUD","EPSD_TREV","NONE","NONE") = -1
WAIT(0)
ENDWHILE
#ENDIF
BREAK
*/
// CASE 4
// #IF IS_DEBUG_BUILD
// IF bDebug_PrintToTTY
// CPRINTLN(DEBUG_AMBIENT, "Eps Desert: Hit 4 miles, schedule a call...")
// ENDIF
// #ENDIF
// WHILE NOT REGISTER_CALL_FROM_CHARACTER_TO_PLAYER(CALL_EPSILON_DESERT_NEAR, CT_AMBIENT, BIT_MICHAEL, CHAR_CRIS, 6, 10000, 30000)
// WAIT(0)
// ENDWHILE
//
// BREAK
// ENDSWITCH
ELSE
#IF IS_DEBUG_BUILD
IF bDebug_PrintToTTY
CPRINTLN(DEBUG_AMBIENT, "EpsDesert: ", ((METRES_PER_MILE*TARGET_MILES) - g_savedGlobals.sAmbient.fDistRunInDesert), " > ", (fNewThreshold - METRES_PER_TENTH_MILE), " (fNewThreshold - METRES_PER_TENTH_MILE)")
ENDIF
#ENDIF
ENDIF
ENDIF
ELIF IN_DIRECTOR_MODE_OR_TRANSITION() // Fix for B*2193487
// Do nothing - player is in Director Mode and this script shouldn't count anything
ELSE
// Player is inside the locate but not inside the correct map zone
IF bInZone = TRUE
#IF IS_DEBUG_BUILD
IF bDebug_PrintToTTY
CPRINTLN(DEBUG_MISSION, "EpsDesert: Player inside locate but NOT in a correct map zone")
ENDIF
#ENDIF
BEGIN_TEXT_COMMAND_THEFEED_POST("EPSDES_OUT")
END_TEXT_COMMAND_THEFEED_POST_TICKER(FALSE)
vAbandonmentPos = GET_ENTITY_COORDS(PLAYER_PED_ID(), FALSE)
bInZone = FALSE
ENDIF
ENDIF
ELSE
// #IF IS_DEBUG_BUILD
// IF bDebug_PrintToTTY
// CPRINTLN(DEBUG_MISSION, "EpsDesert: Player's outfit is not the Epsilon one")
// ENDIF
// #ENDIF
ENDIF
ELSE
// Player is not inside the locate at all, definitely not in range
IF bInZone = TRUE
AND NOT IN_DIRECTOR_MODE_OR_TRANSITION() // Fix for B*2193487
#IF IS_DEBUG_BUILD
IF bDebug_PrintToTTY
VECTOR vTemp = GET_PLAYER_COORDS(PLAYER_ID())
CPRINTLN(DEBUG_MISSION, "EpsDesert: Player is not inside main locate, pos: ", vTemp)
ENDIF
#ENDIF
BEGIN_TEXT_COMMAND_THEFEED_POST("EPSDES_OUT")
END_TEXT_COMMAND_THEFEED_POST_TICKER(FALSE)
vAbandonmentPos = GET_ENTITY_COORDS(PLAYER_PED_ID(), FALSE)
bInZone = FALSE
ENDIF
ENDIF
ELSE
// #IF IS_DEBUG_BUILD
// IF bDebug_PrintToTTY
// CPRINTLN(DEBUG_MISSION, "EpsDesert: One of the conditions not valid to count miles...")
// ENDIF
// #ENDIF
// Notification checks - the miles aren't being counted here because one of the conditions isn't true (e.g. player might be in a car)
// but the player would probably appreciate being told anyway
IF IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<3155.104004,4091.060303,7.974625>>, <<-322.830872,2861.711914,250.525055>>, 2250.0)
IF NOT IS_PLAYER_IN_AREA()
// Player is inside the locate but not inside the correct map zone
IF bInZone = TRUE
AND NOT IN_DIRECTOR_MODE_OR_TRANSITION() // Fix for B*2193487
#IF IS_DEBUG_BUILD
IF bDebug_PrintToTTY
CPRINTLN(DEBUG_MISSION, "EpsDesert: Player is inside main locate, but not correct map zone (2)")
ENDIF
#ENDIF
BEGIN_TEXT_COMMAND_THEFEED_POST("EPSDES_OUT")
END_TEXT_COMMAND_THEFEED_POST_TICKER(FALSE)
vAbandonmentPos = GET_ENTITY_COORDS(PLAYER_PED_ID(), FALSE)
bInZone = FALSE
ENDIF
ELSE
// Update notification text to tell player they're inside the zone
IF bInZone = FALSE
AND NOT IN_DIRECTOR_MODE_OR_TRANSITION() // Fix for B*2193487
BEGIN_TEXT_COMMAND_THEFEED_POST("EPSDES_IN")
END_TEXT_COMMAND_THEFEED_POST_TICKER(FALSE)
bInZone = TRUE
ENDIF
ENDIF
ELSE
// Player is not inside the locate at all, definitely not in range
IF bInZone = TRUE
AND NOT IN_DIRECTOR_MODE_OR_TRANSITION() // Fix for B*2193487
#IF IS_DEBUG_BUILD
IF bDebug_PrintToTTY
CPRINTLN(DEBUG_MISSION, "EpsDesert: Player is not inside main locate (2)")
ENDIF
#ENDIF
BEGIN_TEXT_COMMAND_THEFEED_POST("EPSDES_OUT")
END_TEXT_COMMAND_THEFEED_POST_TICKER(FALSE)
vAbandonmentPos = GET_ENTITY_COORDS(PLAYER_PED_ID(), FALSE)
bInZone = FALSE
ENDIF
ENDIF
ENDIF
IF bForceOutfitOn
hPlayer = PLAYER_PED_ID()
SET_PED_COMP_ITEM_CURRENT_SP(hPlayer, COMP_TYPE_OUTFIT, EPSILON_OUTFIT, FALSE)
bForceOutfitOn = FALSE
ENDIF
IF bForceOutfitOff
hPlayer = PLAYER_PED_ID()
SET_PED_COMP_ITEM_CURRENT_SP(hPlayer, COMP_TYPE_OUTFIT, OUTFIT_P0_DEFAULT)
bForceOutfitOff = FALSE
ENDIF
IF bAddMile
g_savedGlobals.sAmbient.fDistRunInDesert += (METRES_PER_TENTH_MILE - 5)
bAddMile = FALSE
ENDIF
ELSE
IF DOES_ENTITY_EXIST(PLAYER_PED_ID())
IF NOT IS_ENTITY_DEAD(PLAYER_PED_ID())
// Reset the stored previous pos because the player may have warped and we don't want that to count
vPreviousPos = GET_ENTITY_COORDS(PLAYER_PED_ID())
ENDIF
ENDIF
IF NOT IS_PLAYER_PLAYING(PLAYER_ID())
#IF IS_DEBUG_BUILD
IF bDebug_PrintToTTY
CPRINTLN(DEBUG_MISSION, "EpsDesert: Player is no longer playing!")
ENDIF
#ENDIF
ENDIF
ENDIF
IF bDisplayDebugInfo
DISPLAY_TEXT_WITH_FLOAT(DEBUG_INFO_X, DEBUG_INFO_Y, "EPSDES_D0", DISTANCE_TO_RUN - g_savedGlobals.sAmbient.fDistRunInDesert, 1)
//DISPLAY_TEXT_WITH_NUMBER(0.1, 0.3, "EPSDES_D1", iMessageMiles)
DISPLAY_TEXT_WITH_FLOAT(0.1, 0.4, "EPSDES_D2", fMessageMiles, 1)
ENDIF
ENDIF
ELSE
// "You have walked 5 miles in the desert and completed the Epsilonist trial."
BEGIN_TEXT_COMMAND_THEFEED_POST("EPSDES_02")
END_TEXT_COMMAND_THEFEED_POST_TICKER(TRUE)
// Ambient passed music
MISSION_FLOW_PLAY_END_OF_MISSION_MUSIC(TRUE)
// Cris sends Michael a congratulatory text message
// Don't use CT_END_OF_MISSION for this communication as that blocks
// switching and a number of other things until it is sent! -BenR
WHILE NOT REGISTER_CALL_FROM_CHARACTER_TO_PLAYER(CALL_EPSILON_DESERT_DONE, CT_AMBIENT, BIT_MICHAEL, CHAR_CRIS, 6, 10000, 30000)
WAIT(0)
ENDWHILE
eStage = STAGE_CLEANUP
ENDIF
ENDPROC
/// PURPOSE: Cleans up any assets that were created
PROC CLEANUP_SCRIPT()
#IF IS_DEBUG_BUILD
IF bDebug_PrintToTTY
CPRINTLN(DEBUG_MISSION, "STAGE_CLEANUP")
ENDIF
#ENDIF
// Register completion stats when completing normally or via debug
IF g_savedGlobals.sAmbient.fDistRunInDesert >= DISTANCE_TO_RUN
OR GET_MISSION_FLOW_FLAG_STATE(FLOWFLAG_EPSILON_DESERT_DONE) = TRUE
MAKE_AUTOSAVE_REQUEST() // Autosave now
// Set the flow flag so the Epsilon Random Character mission can be started
Set_Mission_Flow_Flag_State(FLOWFLAG_EPSILON_DESERT_DONE, TRUE)
//Set epsilon step stat
INT iCurrent
STAT_GET_INT(NUM_EPSILON_STEP,iCurrent)
IF iCurrent < 19
STAT_SET_INT(NUM_EPSILON_STEP,19)
SET_ACHIEVEMENT_PROGRESS_SAFE(ENUM_TO_INT(ACH20),19)
CPRINTLN(debug_dan,"Epsilon progress:",19)
ENDIF
// No longer require the script to be relaunched when loading from a savegame.
Remove_Script_From_Relaunch_List(LAUNCH_BIT_RC_AMB_EPSILON_DESERT)
// Flag completion to the 100% system
REGISTER_SCRIPT_IN_COMPLETION_PERCENTAGE_TOTAL ( CP_RAND_C_EPS7 )
ENDIF
#IF IS_DEBUG_BUILD
CLEANUP_DESERT_WIDGETS()
#ENDIF
TERMINATE_THIS_THREAD()
ENDPROC
SCRIPT
// Setup callback
IF HAS_FORCE_CLEANUP_OCCURRED(FORCE_CLEANUP_FLAG_DEBUG_MENU|FORCE_CLEANUP_FLAG_SP_TO_MP|FORCE_CLEANUP_FLAG_DIRECTOR)
CLEANUP_SCRIPT()
ENDIF
// Register the script so that it can be relaunched when loading from a savegame.
Register_Script_To_Relaunch_List(LAUNCH_BIT_RC_AMB_EPSILON_DESERT)
#IF IS_DEBUG_BUILD
SETUP_DESERT_WIDGETS()
#ENDIF
// Main loop
WHILE TRUE
WAIT(0)
// Immediately cleanup if this script has been completed via debug
IF GET_MISSION_FLOW_FLAG_STATE(FLOWFLAG_EPSILON_DESERT_DONE) = TRUE
CLEANUP_SCRIPT()
ENDIF
// State handler
SWITCH eStage
CASE STAGE_INITIALISE
DO_INITIALISE()
BREAK
CASE STAGE_PROCESS
DO_PROCESS()
BREAK
CASE STAGE_CLEANUP
CLEANUP_SCRIPT()
BREAK
ENDSWITCH
ENDWHILE
ENDSCRIPT