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

700 lines
24 KiB
Python
Executable File

//////////////////////////////////////////////////////////////////////////////////////////
// //
// SCRIPT NAME : epsRobes.sc //
// AUTHOR : Sam Hackett (based on epsDesert.sc) //
// DESCRIPTION : Monitors the player to see when he has worn epsilon robes //
// for x days. //
// //
//////////////////////////////////////////////////////////////////////////////////////////
//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_script.sch"
USING "commands_entity.sch"
USING "commands_streaming.sch"
USING "commands_object.sch"
USING "script_player.sch"
USING "email_public.sch"
USING "RC_Helper_Functions.sch"
USING "website_public.sch"
USING "comms_control_public.sch"
USING "CompletionPercentage_public.sch"
USING "flow_public_core.sch"
USING "player_ped_public.sch"
USING "RC_Time_public.sch"
// Enums
ENUM MISSION_STAGE
STAGE_INITIALISE = 0,
STAGE_PROCESS,
STAGE_CLEANUP
ENDENUM
ENUM MISSION_SUBSTAGE
SS_BUY_ROBES,
SS_WAIT_FOR_DELIVERY,
SS_NOT_WEARING_ROBES,
SS_WEARING_ROBES,
SS_WEARING_COMPLETED
ENDENUM
// Constants
CONST_INT TARGET_DAYS 10
CONST_INT TARGET_HOURS 10*24
CONST_FLOAT DEBUG_INFO_X 0.8
CONST_FLOAT DEBUG_INFO_Y 0.3
CONST_FLOAT MINIMUM_CHAT_DELAY 120000.0
CONST_FLOAT MAXIMUM_CHAT_DELAY 240000.0
CONST_INT EMERGENCY_DELAY_DAY 2
// Variables
PED_COMP_NAME_ENUM EPSILON_OUTFIT = OUTFIT_P0_EPSILON
BOOL bInformPlayerDayHasPassed = FALSE
BOOL bDoChatter = FALSE
BOOL bDoneMikeRobeComment = FALSE
FLOAT fChatterDelay
INT iLastChatterTime
PED_INDEX pedMarnie
structPedsForConversation ConvStruct
BOOL bGotMarnie
INT iConvTimer
MISSION_STAGE eStage
MISSION_SUBSTAGE eSubStage
TIMEOFDAY currentTOD
TIMEOFDAY previousTOD
TIMEOFDAY nextTOD
INT iDeliveryDay
#IF IS_DEBUG_BUILD
USING "shared_debug.sch"
WIDGET_GROUP_ID widgetGroup
BOOL bDisplayDebugInfo = FALSE
BOOL bForceOutfitOn = FALSE
BOOL bForceOutfitOff = FALSE
BOOL bDebug_PrintToTTY = TRUE
BOOL bKillScript = FALSE
BOOL bIsFlowFlagSet = FALSE
BOOL bPlayerOutfitAvail = FALSE
BOOL bPlayerOutfitAcqui = FALSE
BOOL bShowCurrentTOD = FALSE
STRING sStateString = "SS_BUY_ROBES"
INT iStateEnum = 0
INT iFrameCount = 0
/// PURPOSE:
/// Initialises the widgets for the script
PROC SETUP_ROBES_WIDGETS()
widgetGroup = START_WIDGET_GROUP("Epsilon robes ambient")
ADD_WIDGET_STRING("Current state: ")
ADD_WIDGET_STRING(sStateString)
ADD_WIDGET_INT_READ_ONLY("State Enum", iStateEnum)
ADD_WIDGET_INT_READ_ONLY("Update Counter", iFrameCount)
ADD_WIDGET_INT_SLIDER("Hours in robes", g_savedGlobals.sAmbient.iEpsilonRobesHours, 0, TARGET_HOURS, 6)
ADD_WIDGET_INT_READ_ONLY("Buying Day", g_savedGlobals.sAmbient.iEpsilonLastEmailSentDay)
ADD_WIDGET_INT_READ_ONLY("Delivery Day", iDeliveryDay)
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_BOOL("Has Player Avaliable Robes", bPlayerOutfitAvail)
ADD_WIDGET_BOOL("Has Player Acquired Robes", bPlayerOutfitAcqui)
ADD_WIDGET_BOOL("Have Robes Been Bought", bIsFlowFlagSet)
ADD_WIDGET_BOOL("Show Current TOD", bShowCurrentTOD)
ADD_WIDGET_BOOL("Kill Script", bKillScript)
STOP_WIDGET_GROUP()
ENDPROC
/// PURPOSE:
/// Cleans up the widgets for the script
PROC CLEANUP_ROBES_WIDGETS()
IF DOES_WIDGET_GROUP_EXIST(widgetGroup)
DELETE_WIDGET_GROUP(widgetGroup)
ENDIF
ENDPROC
PROC UPDATE_ROBES_WIDGETS()
IF NOT IS_ENTITY_ALIVE(PLAYER_PED_ID())
EXIT
ENDIF
bPlayerOutfitAvail = IS_PED_COMP_ITEM_AVAILABLE_SP(GET_PLAYER_PED_MODEL(CHAR_MICHAEL), COMP_TYPE_OUTFIT, OUTFIT_P0_EPSILON)
bPlayerOutfitAcqui = IS_PED_COMP_ITEM_ACQUIRED_SP(GET_PLAYER_PED_MODEL(CHAR_MICHAEL), COMP_TYPE_OUTFIT, OUTFIT_P0_EPSILON)
bIsFlowFlagSet = GET_MISSION_FLOW_FLAG_STATE(FLOWFLAG_EPSILON_ROBES_BOUGHT)
TIMEOFDAY ctd
ctd = GET_CURRENT_TIMEOFDAY()
IF (bShowCurrentTOD)
CPRINTLN(DEBUG_AMBIENT, "Current Time:")
PRINT_TIMEOFDAY(ctd, DEBUG_AMBIENT)
bShowCurrentTOD = FALSE
ENDIF
ENDPROC
#ENDIF
/// PURPOSE:
/// Tries to grab Josh from the 32 closest peds around the player when called
/// RETURNS:
/// True if found Josh
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
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_AMBIENT, "EpsRobes.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: Sets up the Epsilon robe ambient script
PROC DO_INITIALISE()
#IF IS_DEBUG_BUILD
IF bDebug_PrintToTTY
CPRINTLN(DEBUG_MISSION, "STAGE_INITIALISE")
ENDIF
#ENDIF
bGotMarnie = GrabMarnie()
fChatterDelay = GET_RANDOM_FLOAT_IN_RANGE(MINIMUM_CHAT_DELAY, MAXIMUM_CHAT_DELAY)
iLastChatterTime = GET_GAME_TIMER()
IF g_savedGlobals.sAmbient.iEpsilonRobesHours < TARGET_HOURS
// Set sub-state for processing
IF NOT GET_MISSION_FLOW_FLAG_STATE(FLOWFLAG_EPSILON_ROBES_BOUGHT)
g_savedGlobals.sAmbient.iEpsilonRobesHours = 0
bDoneMikeRobeComment = FALSE
CPRINTLN(DEBUG_AMBIENT, "[EPSROBES] DO_INITIALIZE: Robes Haven't Been Bought")
eSubStage = SS_BUY_ROBES
ELIF NOT IS_PED_COMP_ITEM_ACQUIRED_SP(GET_PLAYER_PED_MODEL(CHAR_MICHAEL), COMP_TYPE_OUTFIT, OUTFIT_P0_EPSILON)
CPRINTLN(DEBUG_AMBIENT, "[EPSROBES] DO_INITIALIZE: Robes Not Delivered Yet")
currentTOD = GET_CURRENT_TIMEOFDAY()
nextTOD = INT_TO_ENUM(TIMEOFDAY, g_savedGlobals.sAmbient.iEpsilonRobesDeliveryTime)
//nextTOD = GET_CURRENT_TIMEOFDAY()
//ADD_TIME_TO_TIMEOFDAY(nextTOD, 0, 0, 0, 1, 0, 0)
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_AMBIENT, "Current Time:")
PRINT_TIMEOFDAY(currentTOD, DEBUG_AMBIENT)
CPRINTLN(DEBUG_AMBIENT, "Robes Delivery Time:")
PRINT_TIMEOFDAY(nextTOD, DEBUG_AMBIENT)
#ENDIF
iDeliveryDay = (g_savedGlobals.sAmbient.iEpsilonLastEmailSentDay + EMERGENCY_DELAY_DAY) % GET_NUMBER_OF_DAYS_IN_MONTH(INT_TO_ENUM(MONTH_OF_YEAR, GET_CLOCK_MONTH()), GET_CLOCK_YEAR())
g_savedGlobals.sAmbient.iEpsilonRobesHours = 0
bDoneMikeRobeComment = TRUE
eSubStage = SS_WAIT_FOR_DELIVERY
ELIF NOT IS_PED_COMP_ITEM_CURRENT_SP(PLAYER_PED_ID(), COMP_TYPE_OUTFIT, EPSILON_OUTFIT)
CPRINTLN(DEBUG_AMBIENT, "[EPSROBES] DO_INITIALIZE: Robes Not On")
g_savedGlobals.sAmbient.iEpsilonRobesHours = 0
bDoneMikeRobeComment = TRUE
eSubStage = SS_NOT_WEARING_ROBES
ELSE
CPRINTLN(DEBUG_AMBIENT, "[EPSROBES] DO_INITIALIZE: Robes On")
//GET_FUTURE_TIME(1, 0, timeCheck)
bDoneMikeRobeComment = TRUE
previousTOD = GET_CURRENT_TIMEOFDAY()
eSubStage = SS_WEARING_ROBES
ENDIF
eStage = STAGE_PROCESS
#IF IS_DEBUG_BUILD
IF bDebug_PrintToTTY
CPRINTLN(DEBUG_MISSION, "STAGE_PROCESS")
ENDIF
#ENDIF
ELSE
eStage = STAGE_CLEANUP
ENDIF
ENDPROC
/// PURPOSE: Monitors how long the player has been wearing the robes
PROC DO_PROCESS()
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, "EPS5AUD", "EP5_FOLLOW", CONV_PRIORITY_MEDIUM)
iConvTimer = GET_GAME_TIMER()
ENDIF
ENDIF
ENDIF
ENDIF
IF GET_DISTANCE_BETWEEN_ENTITIES(pedMarnie, PLAYER_PED_ID()) > 150.0
SAFE_DELETE_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
INT iRemainingDays
INT iPassedDays
#IF IS_DEBUG_BUILD
iStateEnum = ENUM_TO_INT(eSubStage)
#ENDIF
IF IS_PLAYER_PLAYING(PLAYER_ID())
AND IS_PED_THE_CURRENT_PLAYER_PED(CHAR_MICHAEL)
#IF IS_DEBUG_BUILD
iFrameCount ++
#ENDIF
SWITCH (eSubStage)
CASE SS_BUY_ROBES
// Has order been placed?
IF GET_MISSION_FLOW_FLAG_STATE(FLOWFLAG_EPSILON_ROBES_BOUGHT)
AND IS_PLAYER_CONTROL_ON(PLAYER_ID())
// Send order placed email
// commented out as this shouldn't be called after each e-mail only after the last one in the thread
// RELEASE_DYNAMIC_THREAD_HOLD_ON_BUFFER(DYNAMIC_THREAD_EPSILON_ROBES)
CPRINTLN(DEBUG_AMBIENT, "*** Robes bought!")
FIRE_EMAIL_INTO_DYNAMIC_THREAD(DYNAMIC_THREAD_EPSILON_ROBES, EMAIL_ORDER_PLACED)
OVERRIDE_CONTENT_FOR_DYNAMIC_THREAD(DYNAMIC_THREAD_EPSILON_ROBES, "EPSROBE_M1")
//PRINT_HELP("EPSROBE_H1") //You have an email from The Epsilon Program.
// Set delivery time
nextTOD = GET_CURRENT_TIMEOFDAY()
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_AMBIENT, "Robes Ordered Time:")
PRINT_TIMEOFDAY(nextTOD, DEBUG_AMBIENT)
#ENDIF
ADD_TIME_TO_TIMEOFDAY(nextTOD, 0, 0, 0, 1, 0, 0) // one day
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_AMBIENT, "Robes Expected Delivery Time:")
PRINT_TIMEOFDAY(nextTOD, DEBUG_AMBIENT)
#ENDIF
g_savedGlobals.sAmbient.iEpsilonLastEmailSentDay = GET_CLOCK_DAY_OF_MONTH()
iDeliveryDay = (g_savedGlobals.sAmbient.iEpsilonLastEmailSentDay + EMERGENCY_DELAY_DAY) % GET_NUMBER_OF_DAYS_IN_MONTH(INT_TO_ENUM(MONTH_OF_YEAR, GET_CLOCK_MONTH()), GET_CLOCK_YEAR())
g_savedGlobals.sAmbient.iEpsilonRobesDeliveryTime = ENUM_TO_INT(nextTOD)
CPRINTLN(DEBUG_AMBIENT, "Robes Emergency Order Day:", g_savedGlobals.sAmbient.iEpsilonLastEmailSentDay)
CPRINTLN(DEBUG_AMBIENT, "Robes Emergency Delivery Day:", iDeliveryDay)
#IF IS_DEBUG_BUILD
sStateString = "SS_WAIT_FOR_DELIVERY"
#ENDIF
eSubStage = SS_WAIT_FOR_DELIVERY
MAKE_AUTOSAVE_REQUEST()
ELIF NOT GET_MISSION_FLOW_FLAG_STATE(FLOWFLAG_EPSILON_ROBES_BOUGHT)
IF bDoneMikeRobeComment = FALSE
IF GET_CULT_ROBE_PAGE_VISITED()
ADD_PED_FOR_DIALOGUE(ConvStruct, 0, PLAYER_PED_ID(), "MICHAEL")
IF CREATE_CONVERSATION(ConvStruct, "EPS5AUD", "EP5_COST", CONV_PRIORITY_MEDIUM)
bDoneMikeRobeComment = TRUE
ENDIF
ENDIF
ENDIF
ENDIF
BREAK
CASE SS_WAIT_FOR_DELIVERY
// Is it time for delivery?
currentTOD = GET_CURRENT_TIMEOFDAY()
iDeliveryDay = (g_savedGlobals.sAmbient.iEpsilonLastEmailSentDay + EMERGENCY_DELAY_DAY) % GET_NUMBER_OF_DAYS_IN_MONTH(INT_TO_ENUM(MONTH_OF_YEAR, GET_CLOCK_MONTH()), GET_CLOCK_YEAR())
IF (IS_TIMEOFDAY_AFTER_TIMEOFDAY(currentTOD, nextTOD) OR (GET_CLOCK_DAY_OF_MONTH() = iDeliveryDay))
AND IS_PLAYER_CONTROL_ON(PLAYER_ID())
AND GET_ROOM_KEY_FROM_ENTITY(PLAYER_PED_ID()) != GET_HASH_KEY("V_Michael_1_M_Ward")
AND GET_ROOM_KEY_FROM_ENTITY(PLAYER_PED_ID()) != GET_HASH_KEY("V_Michael_1_Master")
// Send delivered email
CPRINTLN(DEBUG_AMBIENT, "Delivery Executed")
IF (GET_CLOCK_DAY_OF_MONTH() = iDeliveryDay)
CPRINTLN(DEBUG_AMBIENT, "EMERGENCY DELIVERY EXECUTED")
ENDIF
FIRE_EMAIL_INTO_DYNAMIC_THREAD(DYNAMIC_THREAD_EPSILON_ROBES, EMAIL_ORDER_DELIVERED)
OVERRIDE_CONTENT_FOR_DYNAMIC_THREAD(DYNAMIC_THREAD_EPSILON_ROBES, "EPSROBE_M2")
RELEASE_DYNAMIC_THREAD_HOLD_ON_BUFFER(DYNAMIC_THREAD_EPSILON_ROBES)
//PRINT_HELP("EPSROBE_H1") //You have an email from The Epsilon Program.
// Enable robes in wardrobe
SET_PED_COMP_ITEM_AVAILABLE_SP(GET_PLAYER_PED_MODEL(CHAR_MICHAEL), COMP_TYPE_OUTFIT, OUTFIT_P0_EPSILON, TRUE)
SET_PED_COMP_ITEM_ACQUIRED_SP(GET_PLAYER_PED_MODEL(CHAR_MICHAEL), COMP_TYPE_OUTFIT, OUTFIT_P0_EPSILON, TRUE)
MAKE_AUTOSAVE_REQUEST()
#IF IS_DEBUG_BUILD
sStateString = "SS_NOT_WEARING_ROBES"
#ENDIF
// Set next update time
eSubStage = SS_NOT_WEARING_ROBES
ENDIF
BREAK
CASE SS_NOT_WEARING_ROBES
// Has player put on robes?
IF IS_PED_COMP_ITEM_CURRENT_SP(PLAYER_PED_ID(), COMP_TYPE_OUTFIT, EPSILON_OUTFIT)
AND IS_PLAYER_CONTROL_ON(PLAYER_ID())
AND NOT IS_HELP_MESSAGE_BEING_DISPLAYED()
// Initial message when player first puts on outfit ("Wear for 50 days to quell antithesis")
PRINT_HELP("EPSROBE_H2") //Wear your robes for 50 days to quell your antithesis.
previousTOD = GET_CURRENT_TIMEOFDAY()
nextTOD = GET_CURRENT_TIMEOFDAY()
ADD_TIME_TO_TIMEOFDAY(nextTOD, 0, 0, 1, 0, 0, 0) // one hour - tracking by hour
// Set current time player has started wearing robes
// Reset chatter values
fChatterDelay = GET_RANDOM_FLOAT_IN_RANGE(MINIMUM_CHAT_DELAY, MAXIMUM_CHAT_DELAY)
iLastChatterTime = GET_GAME_TIMER()
#IF IS_DEBUG_BUILD
sStateString = "SS_WEARING_ROBES"
#ENDIF
MAKE_AUTOSAVE_REQUEST()
eSubStage = SS_WEARING_ROBES
ENDIF
BREAK
CASE SS_WEARING_ROBES
// Has player taken off robes?
IF NOT IS_PED_COMP_ITEM_CURRENT_SP(PLAYER_PED_ID(), COMP_TYPE_OUTFIT, EPSILON_OUTFIT)
AND NOT IS_PLAYER_CHANGING_CLOTHES()
// Reset robes timer
#IF IS_DEBUG_BUILD
sStateString = "SS_NOT_WEARING_ROBES"
#ENDIF
eSubStage = SS_NOT_WEARING_ROBES
// Is time complete?
ELIF g_savedGlobals.sAmbient.iEpsilonRobesHours >= TARGET_HOURS
#IF IS_DEBUG_BUILD
sStateString = "SS_WEARING_COMPLETED"
#ENDIF
eSubStage = SS_WEARING_COMPLETED
// Is it time for the next update?
ELIF NOT IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_DIRECTOR) // Fix for B*2189031
HANDLE_CHATTER()
currentTOD = GET_CURRENT_TIMEOFDAY()
IF IS_TIMEOFDAY_AFTER_TIMEOFDAY(currentTOD, nextTOD) // Check after an hour has passed
// Increment hours
// Need to create these other ints to return the difference values, unfortunately
INT iSeconds
INT iMinutes
INT iHours
INT iDays
INT iMonths
INT iYears
// CPRINTLN(DEBUG_AMBIENT, "previousTOD is: iMinutes = ", GET_TIMEOFDAY_MINUTE(previousTOD), ", iHours = ", GET_TIMEOFDAY_HOUR(previousTOD), ", iDays = ", GET_TIMEOFDAY_DAY(previousTOD), ", iMonth = ", GET_TIMEOFDAY_MONTH(previousTOD))
// CPRINTLN(DEBUG_AMBIENT, "currentTOD is: iMinutes = ", GET_TIMEOFDAY_MINUTE(currentTOD), ", iHours = ", GET_TIMEOFDAY_HOUR(currentTOD), ", iDays = ", GET_TIMEOFDAY_DAY(currentTOD), ", iMonth = ", GET_TIMEOFDAY_MONTH(currentTOD))
// CPRINTLN(DEBUG_AMBIENT, "nextTOD is: iMinutes = ", GET_TIMEOFDAY_MINUTE(nextTOD), ", iHours = ", GET_TIMEOFDAY_HOUR(nextTOD), ", iDays = ", GET_TIMEOFDAY_DAY(nextTOD), ", iMonth = ", GET_TIMEOFDAY_MONTH(nextTOD))
// previousTOD is the last time we incremented the timer - work out how much time has passed since then
GET_DIFFERENCE_BETWEEN_TIMEOFDAYS(currentTOD, previousTOD, iSeconds, iMinutes, iHours, iDays, iMonths, iYears)
// #IF IS_DEBUG_BUILD
// CPRINTLN(DEBUG_MISSION, "Robes tick")
// CPRINTLN(DEBUG_MISSION, "iSeconds: ", iSeconds)
// CPRINTLN(DEBUG_MISSION, "iMinutes: ", iMinutes)
// CPRINTLN(DEBUG_MISSION, "iHours: ", iHours)
// CPRINTLN(DEBUG_MISSION, "iDays: ", iDays)
// CPRINTLN(DEBUG_MISSION, "iMonths: ", iMonths)
// CPRINTLN(DEBUG_MISSION, "iYears: ", iYears)
// #ENDIF
IF iDays > 0
iHours += 24*iDays // Add 24 hours per number of days passed - don't think there's a situation where this would happen, but just in case
ENDIF
g_savedGlobals.sAmbient.iEpsilonRobesHours += iHours
previousTOD = GET_CURRENT_TIMEOFDAY() // Store the current TOD as the new 'last time we incremented the timer'
nextTOD = GET_CURRENT_TIMEOFDAY()
// Only check for an increment after 1 hour
ADD_TIME_TO_TIMEOFDAY(nextTOD, 0, 0, 1, 0, 0, 0)
IF g_savedGlobals.sAmbient.iEpsilonRobesHours % 24 = 0
bInformPlayerDayHasPassed = TRUE
ENDIF
ENDIF
ENDIF
IF bInformPlayerDayHasPassed
IF IS_PLAYER_CONTROL_ON(PLAYER_ID())
AND NOT IS_HELP_MESSAGE_BEING_DISPLAYED()
AND NOT IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_DIRECTOR) //B* 2189025: Ignore if in Director mode
// Just completed a day, inform player
iRemainingDays = TARGET_DAYS - (g_savedGlobals.sAmbient.iEpsilonRobesHours / 24)
iPassedDays = TARGET_DAYS - iRemainingDays
IF iPassedDays < 10
IF iPassedDays > 1
BEGIN_TEXT_COMMAND_THEFEED_POST("EPSROBE_01") //Wear your robes for ~1~ more days to quell your antithesis.
ADD_TEXT_COMPONENT_INTEGER(iPassedDays)
END_TEXT_COMMAND_THEFEED_POST_TICKER(FALSE)
ELSE
BEGIN_TEXT_COMMAND_THEFEED_POST("EPSROBE_00") //Wear your robes for 1 more day to quell your antithesis.
END_TEXT_COMMAND_THEFEED_POST_TICKER(FALSE)
ENDIF
ENDIF
MAKE_AUTOSAVE_REQUEST()
bInformPlayerDayHasPassed = FALSE
ENDIF
ENDIF
BREAK
CASE SS_WEARING_COMPLETED
IF IS_PLAYER_CONTROL_ON(PLAYER_ID())
AND NOT IS_HELP_MESSAGE_BEING_DISPLAYED()
BEGIN_TEXT_COMMAND_THEFEED_POST("EPSROBE_02")
END_TEXT_COMMAND_THEFEED_POST_TICKER(FALSE)
MAKE_AUTOSAVE_REQUEST()
WAIT(8000)
WHILE NOT SEND_TEXT_MESSAGE_TO_CURRENT_PLAYER(CHAR_CRIS, "EPSROBE_T", TXTMSG_UNLOCKED)
WAIT(0)
ENDWHILE
CPRINTLN(DEBUG_AMBIENT, "Added Cris to book")
ADD_CONTACT_TO_PHONEBOOK(CHAR_CRIS, MICHAEL_BOOK)
eStage = STAGE_CLEANUP
ENDIF
BREAK
ENDSWITCH
ENDIF
// Debug stuff
#IF IS_DEBUG_BUILD
IF IS_PLAYER_PLAYING(PLAYER_ID())
AND IS_PED_THE_CURRENT_PLAYER_PED(CHAR_MICHAEL)
// Debug force outfit on/off
IF bForceOutfitOn
SET_MISSION_FLOW_FLAG_STATE(FLOWFLAG_EPSILON_ROBES_BOUGHT, TRUE)
PED_INDEX hPlayer = PLAYER_PED_ID()
SET_PED_COMP_ITEM_AVAILABLE_SP(GET_PLAYER_PED_MODEL(CHAR_MICHAEL), COMP_TYPE_OUTFIT, OUTFIT_P0_EPSILON, TRUE)
SET_PED_COMP_ITEM_ACQUIRED_SP(GET_PLAYER_PED_MODEL(CHAR_MICHAEL), COMP_TYPE_OUTFIT, OUTFIT_P0_EPSILON, TRUE)
SET_PED_COMP_ITEM_CURRENT_SP(hPlayer, COMP_TYPE_OUTFIT, OUTFIT_P0_EPSILON, FALSE)
STORE_PLAYER_PED_VARIATIONS(PLAYER_PED_ID())
IF ENUM_TO_INT(eSubStage) < ENUM_TO_INT(SS_WEARING_ROBES)
previousTOD = GET_CURRENT_TIMEOFDAY() // Check how much time has passed against THIS
nextTOD = GET_CURRENT_TIMEOFDAY()
ADD_TIME_TO_TIMEOFDAY(nextTOD, 0, 0, 1, 0, 0, 0) // Only check for an increment after 1 hour
#IF IS_DEBUG_BUILD
sStateString = "SS_WEARING_ROBES"
#ENDIF
eSubStage = SS_WEARING_ROBES
ENDIF
bForceOutfitOn = FALSE
ENDIF
IF bForceOutfitOff
PED_INDEX hPlayer = PLAYER_PED_ID()
SET_PED_COMP_ITEM_CURRENT_SP(hPlayer, COMP_TYPE_OUTFIT, OUTFIT_P0_DEFAULT)
bForceOutfitOff = FALSE
ENDIF
ENDIF
IF bDisplayDebugInfo
DISPLAY_TEXT_WITH_NUMBER(DEBUG_INFO_X, DEBUG_INFO_Y, "EPSROBE_D0", TARGET_HOURS - g_savedGlobals.sAmbient.iEpsilonRobesHours)
ENDIF
#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.iEpsilonRobesHours >= TARGET_HOURS
OR GET_MISSION_FLOW_FLAG_STATE(FLOWFLAG_EPSILON_ROBES_DONE) = TRUE
// Text the player to inform them that a plane has been spotted near the Senora Freeway
// We wait 90 seconds - 85 seconds for text to get sent + 5 seconds after to register code id.
#IF IS_FINAL_BUILD
REGISTER_TEXT_MESSAGE_FROM_CHARACTER_TO_PLAYER( TEXT_RC_EPSILON6_UNLOCK,
CT_FLOW,
BIT_MICHAEL,
CHAR_JIMMY_BOSTON,
85000,
10000,
VID_LOCATION_EPSILON6_PLANE_400M,
CID_EPSILON_6_TEXT_RECIEVED)
#ENDIF
#IF IS_DEBUG_BUILD
IF GET_MISSION_FLOW_FLAG_STATE(FLOWFLAG_EPSILON_ROBES_DONE)
CPRINTLN(DEBUG_RANDOM_CHAR, "No need to send Epsilon 6 unlock text - debug skipping.")
ELSE
CPRINTLN(DEBUG_RANDOM_CHAR, "Sending Epsilon 6 unlock text from CID_EPSILON_6_TEXT_RECEIVED.")
REGISTER_TEXT_MESSAGE_FROM_CHARACTER_TO_PLAYER( TEXT_RC_EPSILON6_UNLOCK,
CT_FLOW,
BIT_MICHAEL,
CHAR_JIMMY_BOSTON,
85000,
10000,
VID_LOCATION_EPSILON6_PLANE_400M,
CID_EPSILON_6_TEXT_RECIEVED)
ENDIF
#ENDIF
// Set the flow flag so that Epsilon 6 can be started
SET_MISSION_FLOW_FLAG_STATE(FLOWFLAG_EPSILON_ROBES_DONE, TRUE)
//Set epsilon step stat
INT iCurrent
STAT_GET_INT(NUM_EPSILON_STEP,iCurrent)
IF iCurrent < 16
STAT_SET_INT(NUM_EPSILON_STEP,16)
SET_ACHIEVEMENT_PROGRESS_SAFE(ENUM_TO_INT(ACH20),16)
CPRINTLN(debug_dan,"Epsilon progress:",16)
ENDIF
// No longer require the script to be relaunched when loading from a savegame.
Remove_Script_From_Relaunch_List(LAUNCH_BIT_RC_AMB_EPSILON_ROBES)
// Flag completion to the 100% system
REGISTER_SCRIPT_IN_COMPLETION_PERCENTAGE_TOTAL(CP_RAND_C_EPS5)
ENDIF
#IF IS_DEBUG_BUILD
CLEANUP_ROBES_WIDGETS()
#ENDIF
TERMINATE_THIS_THREAD()
ENDPROC
SCRIPT
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_ROBES)
// Immediately cleanup if this script has been completed via debug
IF GET_MISSION_FLOW_FLAG_STATE(FLOWFLAG_EPSILON_ROBES_DONE) = TRUE
CLEANUP_SCRIPT()
ENDIF
#IF IS_DEBUG_BUILD
SETUP_ROBES_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_ROBES_DONE) = TRUE
CLEANUP_SCRIPT()
ENDIF
#IF IS_DEBUG_BUILD
UPDATE_ROBES_WIDGETS()
#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