Files
gtav-src/script/dev_ng/singleplayer/scripts/email/email_controller.sc
T
2025-09-29 00:52:08 +02:00

441 lines
16 KiB
Python
Executable File

//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 "commands_script.sch"
USING "email_public.sch"
USING "comms_control_private.sch"
// *****************************************************************************************
// *****************************************************************************************
// *****************************************************************************************
//
// MISSION NAME : email_controller.sch
// AUTHOR : Ak
// DESCRIPTION : Watcher script for email functionality
//
// *****************************************************************************************
// *****************************************************************************************
// *****************************************************************************************
// ===========================================================================================================
// Cleanup
// ===========================================================================================================
// PURPOSE: Ensures that the script gets a chance to cleanup under specific circumstances (ie: moving from SP to MP)
//
PROC Script_Cleanup()
CPRINTLN(DEBUG_EMAIL, "Cleaning up email controller.")
TERMINATE_THIS_THREAD()
ENDPROC
SCRIPT
CPRINTLN(DEBUG_EMAIL, "Email controller started.")
// This script needs to cleanup only when the game moves from SP to MP.
IF (HAS_FORCE_CLEANUP_OCCURRED(FORCE_CLEANUP_FLAG_SP_TO_MP|FORCE_CLEANUP_FLAG_MAGDEMO))
CPRINTLN(DEBUG_EMAIL, "The email controller was forced to clean up. Flag: ", GET_CAUSE_OF_MOST_RECENT_FORCE_CLEANUP())
Script_Cleanup()
ENDIF
INT delays[TOTAL_EMAIL_THREADS_IN_GAME]
INITIALISE_EMAIL_SYSTEM_CONTENT()
LOAD_EMAIL_SYSTEM_STATE()
g_bDebugEmailDisplay = FALSE
TIMEOFDAY todCurrent = GET_CURRENT_TIMEOFDAY()
TIMEOFDAY todLast = GET_CURRENT_TIMEOFDAY()
INT delay_stride = 2000
//BEGIN_EMAIL_THREAD(CULT_CAR_STEAL_CHAIN)
//PROGRESS_EMAIL_THREAD(ENUM_TO_INT(CULT_CAR_STEAL_CHAIN))
//JUMP_EMAIL_THREAD_TO_STAGE(CULT_CAR_STEAL_CHAIN, CULT3,TRUE)
/*
//Test spam all the emails
BEGIN_EMAIL_THREAD(CULT_CAR_STEAL_CHAIN)
BEGIN_EMAIL_THREAD(CULT_MAIL_ORDER)
BEGIN_EMAIL_THREAD(ASS_THREAD_HOTEL)
BEGIN_EMAIL_THREAD(ASS_THREAD_MULTI)
BEGIN_EMAIL_THREAD(ASS_THREAD_VICE)
BEGIN_EMAIL_THREAD(ASS_THREAD_CONSTRUCTION)
BEGIN_EMAIL_THREAD(HEIST_THREAD_BANK_MIKE)
BEGIN_EMAIL_THREAD(HEIST_THREAD_BANK_FRAN)
BEGIN_EMAIL_THREAD(HEIST_THREAD_BANK_TREV)
BEGIN_EMAIL_THREAD(STOCKMARKET_TUTORIAL)
BEGIN_EMAIL_THREAD(LSC_MOD_UNLOCKS)
BEGIN_EMAIL_THREAD(WEAPON_STOCK_1)
BEGIN_EMAIL_THREAD(WEAPON_STOCK_2)
BEGIN_EMAIL_THREAD(WEAPON_STOCK_3)
BEGIN_EMAIL_THREAD(WEAPON_STOCK_4)
BEGIN_EMAIL_THREAD(WEAPON_STOCK_5)
BEGIN_EMAIL_THREAD(WEAPON_STOCK_6)
BEGIN_EMAIL_THREAD(WEAPON_STOCK_7)
BEGIN_EMAIL_THREAD(WEAPON_STOCK_8)
BEGIN_EMAIL_THREAD(PROPERTY_DMAIL_HELIPAD)
BEGIN_EMAIL_THREAD(PROPERTY_DMAIL_MARINA)
BEGIN_EMAIL_THREAD(PROPERTY_DMAIL_HANGAR)
BEGIN_EMAIL_THREAD(BIGSCOREPC_BAD_HACKER)
BEGIN_EMAIL_THREAD(BIGSCOREPC_MED_HACKER)
BEGIN_EMAIL_THREAD(BIGSCOREPC_GOOD_HACKER)
BEGIN_EMAIL_THREAD(OFFROAD_UNLOCK)
BEGIN_EMAIL_THREAD(WEAPON_STOCK_9)
BEGIN_EMAIL_THREAD(SEARACE_UNLOCK_MIKE)
BEGIN_EMAIL_THREAD(SEARACE_UNLOCK_FRANK)
BEGIN_EMAIL_THREAD(SEARACE_UNLOCK_TREV)
BEGIN_EMAIL_THREAD(PROPERTY_EMAIL_FRAMES_MIKE)
BEGIN_EMAIL_THREAD(PROPERTY_EMAIL_FRAMES_FRANK)
BEGIN_EMAIL_THREAD(PROPERTY_EMAIL_FRAMES_TREV)
BEGIN_EMAIL_THREAD(BAIL_BONDS)
BEGIN_EMAIL_THREAD(EPSILON_TRACT)
BEGIN_EMAIL_THREAD(CARSTEAL2_REWARD)
BEGIN_EMAIL_THREAD(DRFRIEDLANDER_EMAIL_A1)
BEGIN_EMAIL_THREAD(DRFRIEDLANDER_EMAIL_END)
BEGIN_EMAIL_THREAD(TRACEY_EMAIL_EXILE)
BEGIN_EMAIL_THREAD(DAVE_EMAIL_FBI1)
BEGIN_EMAIL_THREAD(AMANDA_EMAIL_FAM6)
BEGIN_EMAIL_THREAD(MERRYWETHER_EMAIL_EG)
BEGIN_EMAIL_THREAD(DAVE_EMAIL_EG)
BEGIN_EMAIL_THREAD(RON_EMAIL_EG)
BEGIN_EMAIL_THREAD(TANISHA_EMAIL_NG)
BEGIN_EMAIL_THREAD(DENISE_EMAIL_FNH)
BEGIN_EMAIL_THREAD(LAMAR_EMAIL_FNK0)
BEGIN_EMAIL_THREAD(LAMAR_EMAIL_EGKT)
BEGIN_EMAIL_THREAD(LAMAR_EMAIL_EGKM)
BEGIN_EMAIL_THREAD(LAMAR_EMAIL_EGSB)
BEGIN_EMAIL_THREAD(AMANDA_EMAIL_EGKM)
BEGIN_EMAIL_THREAD(TREVOR_EMAIL_EGKM)
BEGIN_EMAIL_THREAD(MICHAEL_EMAIL_EGKT)
BEGIN_EMAIL_THREAD(MICHAEL_EMAIL_EGSB)
BEGIN_EMAIL_THREAD(BRAD_EMAIL_TRV1)
BEGIN_EMAIL_THREAD(BRAD_EMAIL_FIB1)
BEGIN_EMAIL_THREAD(BRAD_EMAIL_MIC1)
BEGIN_EMAIL_THREAD(RON_EMAIL_FAM4)
BEGIN_EMAIL_THREAD(JIMMY_EMAIL_FAM4)
BEGIN_EMAIL_THREAD(PATRICIA_EMAIL_MIC4)
BEGIN_EMAIL_THREAD(DAVE_EMAIL_EGBB)
BEGIN_EMAIL_THREAD(REHO_BMS_EMAIL)
BEGIN_EMAIL_THREAD(CATH_NS_EMAIL)
BEGIN_EMAIL_THREAD(CULT_DONATE500)
BEGIN_EMAIL_THREAD(CULT_DONATE5000)
BEGIN_EMAIL_THREAD(NIGEL_CELEB_EMAIL)
BEGIN_EMAIL_THREAD(PROPERTY_DMAIL_GARAGE)
BEGIN_EMAIL_THREAD(RON_EMAIL_CULT)
BEGIN_EMAIL_THREAD(PRO_BAR_HOOKIES_M)
BEGIN_EMAIL_THREAD(PRO_BAR_HOOKIES_F)
BEGIN_EMAIL_THREAD(PRO_TOWING_IMPOUND_F)
BEGIN_EMAIL_THREAD(PRO_SONAR_COLLECTIONS_M)
BEGIN_EMAIL_THREAD(PRO_SONAR_COLLECTIONS_T)
BEGIN_EMAIL_THREAD(PRO_SONAR_COLLECTIONS_F)
BEGIN_EMAIL_THREAD(PRO_CAR_MOD_SHOP_F)
BEGIN_EMAIL_THREAD(PRO_CINEMA_VINEWOOD_M)
BEGIN_EMAIL_THREAD(PRO_CINEMA_DOWNTOWN_M)
BEGIN_EMAIL_THREAD(PRO_CAR_SCRAP_YARD_M)
BEGIN_EMAIL_THREAD(PRO_CAR_SCRAP_YARD_T)
BEGIN_EMAIL_THREAD(PRO_CAR_SCRAP_YARD_F)
BEGIN_EMAIL_THREAD(PRO_WEED_SHOP_F)
BEGIN_EMAIL_THREAD(PRO_BAR_TEQUILALA_M)
BEGIN_EMAIL_THREAD(PRO_BAR_TEQUILALA_T)
BEGIN_EMAIL_THREAD(PRO_BAR_TEQUILALA_F)
BEGIN_EMAIL_THREAD(PRO_BAR_PITCHERS_M)
BEGIN_EMAIL_THREAD(PRO_BAR_PITCHERS_T)
BEGIN_EMAIL_THREAD(PRO_BAR_PITCHERS_F)
BEGIN_EMAIL_THREAD(PRO_BAR_HEN_HOUSE_M)
BEGIN_EMAIL_THREAD(PRO_BAR_HEN_HOUSE_T)
BEGIN_EMAIL_THREAD(PRO_BAR_HEN_HOUSE_F)
BEGIN_EMAIL_THREAD(CULT_DONATE_10000)
BEGIN_EMAIL_THREAD(BITH_AA_EMAIL_M)
BEGIN_EMAIL_THREAD(BITH_AA_EMAIL_T)
BEGIN_EMAIL_THREAD(BITH_AA_EMAIL_F)
BEGIN_EMAIL_THREAD(VEHSITE_DMAILS_BIKE)
BEGIN_EMAIL_THREAD(VEHSITE_DMAILS_AUTO)
BEGIN_EMAIL_THREAD(HUSH_SMUSH_SPAM)
BEGIN_EMAIL_THREAD(HUSH_SMUSH_FOXYMAMA)
BEGIN_EMAIL_THREAD(HUSH_SMUSH_ALTAREGO)
BEGIN_EMAIL_THREAD(HUSH_SMUSH_BADKITTY)
BEGIN_EMAIL_THREAD(HUSH_SMUSH_7YEARBITCH)
BEGIN_EMAIL_THREAD(HUSH_SMUSH_FROGGY)
BEGIN_EMAIL_THREAD(HUSH_SMUSH_MISSCUDDLES)
BEGIN_EMAIL_THREAD(CATH_NS_T_EMAIL)
BEGIN_EMAIL_THREAD(CATH_NS_M_EMAIL)
BEGIN_EMAIL_THREAD(CATH_NS_F_EMAIL)
*/
//Test of dynamic emails
//Bailbonds test
/*
SENT_BAIL_BOND_EMAILTEST(BBI_QUARRY, FALSE)
SENT_BAIL_BOND_EMAILTEST(BBI_FARM, FALSE)
SENT_BAIL_BOND_EMAILTEST(BBI_MOUNTAIN, FALSE)
SENT_BAIL_BOND_EMAILTEST(BBI_HOBO, FALSE)
*/
//TEST_DYNAMIC_THREAD
/*
FIRE_EMAIL_INTO_DYNAMIC_THREAD(TEST_DYNAMIC_THREAD, CULT1)
FIRE_EMAIL_INTO_DYNAMIC_THREAD(TEST_DYNAMIC_THREAD, CULT2)
FIRE_EMAIL_INTO_DYNAMIC_THREAD(TEST_DYNAMIC_THREAD, CULT3)
FIRE_EMAIL_INTO_DYNAMIC_THREAD(TEST_DYNAMIC_THREAD, CULTINITIAL)
FIRE_EMAIL_INTO_DYNAMIC_THREAD(TEST_DYNAMIC_THREAD, CULT1)
FIRE_EMAIL_INTO_DYNAMIC_THREAD(TEST_DYNAMIC_THREAD, CULT2)
FIRE_EMAIL_INTO_DYNAMIC_THREAD(TEST_DYNAMIC_THREAD, CULT3)
FIRE_EMAIL_INTO_DYNAMIC_THREAD(TEST_DYNAMIC_THREAD, CULT1)
FIRE_EMAIL_INTO_DYNAMIC_THREAD(TEST_DYNAMIC_THREAD, CULT2)
FIRE_EMAIL_INTO_DYNAMIC_THREAD(TEST_DYNAMIC_THREAD, CULT3)
FIRE_EMAIL_INTO_DYNAMIC_THREAD(TEST_DYNAMIC_THREAD, CULTINITIAL)
FIRE_EMAIL_INTO_DYNAMIC_THREAD(TEST_DYNAMIC_THREAD, CULT1)
FIRE_EMAIL_INTO_DYNAMIC_THREAD(TEST_DYNAMIC_THREAD, CULT2)
FIRE_EMAIL_INTO_DYNAMIC_THREAD(TEST_DYNAMIC_THREAD, CULT3)
OVERRIDE_CONTENT_FOR_DYNAMIC_THREAD(TEST_DYNAMIC_THREAD, "TEST1")
ADD_CONTENT_FOR_DYNAMIC_THREAD_SUBSTRING(TEST_DYNAMIC_THREAD, "TEST2")
*/
//SCRIPT_ASSERT("Dynamic email test!")
g_bEmailSystemUpdated = TRUE
//SEND_DYNAMIC_EMAIL_FOR_PROPERTY_PURCHASE( VEHGEN_WEB_CAR_MICHAEL )
//SEND_DYNAMIC_EMAIL_FOR_PROPERTY_PURCHASE( VEHGEN_WEB_CAR_FRANKLIN )
//SEND_DYNAMIC_EMAIL_FOR_PROPERTY_PURCHASE( VEHGEN_WEB_CAR_TREVOR )
BOOL bTryDynamicRelease = TRUE
WHILE TRUE
INT i = 0
//If the bailbond thread is active and we're past that point release it from the dynamic registers
IF bTryDynamicRelease
IF IS_BIT_SET(g_savedGlobals.sBailBondData.iLauncherBitFlags, ENUM_TO_INT(MAX_BAILBOND_IDS)-1)
CPRINTLN(DEBUG_EMAIL, "Releasing DYNAMIC_THREAD_BAIL_BONDS due to being past that point in the game.")
RELEASE_DYNAMIC_THREAD_HOLD_ON_BUFFER(DYNAMIC_THREAD_BAIL_BONDS)
bTryDynamicRelease = FALSE
ENDIF
ENDIF
//for each active
//check for delay progress
//fire next step if nessessary
IF NOT g_bEmailSystemPaused //if the email system update is not paused
AND GET_GAME_TIMER() > g_iGlobalWaitTime
REPEAT TOTAL_EMAIL_THREADS_IN_GAME i
//active and not over and not blocking until a response
IF g_AllEmailThreads[i].bActive AND (NOT g_AllEmailThreads[i].bEnded) AND (NOT g_AllEmailThreads[i].bBLockedUntilResponse)
CDEBUG2LN(DEBUG_EMAIL, "Updating email thread ", i, "'s delay status. Time left until thread update is ", g_AllEmailThreads[i].iDelay - delays[i], "ms.")
delays[i] += delay_stride
IF delays[i] > g_AllEmailThreads[i].iDelay
CDEBUG1LN(DEBUG_EMAIL, "Found email thread ", i, " needs updating. Running communication safety checks.")
IF PRIVATE_Is_Safe_To_Start_Communication(7, CHAR_BLANK_ENTRY, CPR_MEDIUM)
PROGRESS_EMAIL_THREAD(i)
delays[i] = 0
g_bEmailSystemUpdated = TRUE
ENDIF
ENDIF
ENDIF
WAIT(0)
ENDREPEAT
//Maintain the dynamic email queue
//check for dynamic emails pending
//todLast = todCurrent
todCurrent = GET_CURRENT_TIMEOFDAY()
INT hdiff = 0
INT dummy = 0
INT k = 0
GET_DIFFERENCE_BETWEEN_TIMEOFDAYS(todCurrent, todLast, dummy, dummy, hdiff, dummy, dummy, dummy)
IF hdiff < 0
hdiff *= -1
ENDIF
IF hdiff > 0 AND (g_Cellphone.PhoneDS = PDS_AWAY) //
todLast = todCurrent
IF g_iDynamicEmailsPending > 0
CDEBUG3LN(DEBUG_EMAIL, "Detected hour change of ", hdiff, " and controller has ", g_iDynamicEmailsPending, " pending dynamic emails.")
INT iTodo = g_iDynamicEmailsPending
INT j = 0
//They could be anywhere in the list.
//For each instance of j
WHILE iTodo != 0
IF g_DynamicEmailsPending[j].RegIDOfTarget != 0
AND j < MAX_DYNAMIC_EMAILS_PENDING
AND g_DynamicEmailsPending[j].bNotSent
//Process the timer.
g_DynamicEmailsPending[j].iInGameHoursBeforeTrigger -= hdiff
CDEBUG1LN(DEBUG_EMAIL, "Pending dynamic email has ", g_DynamicEmailsPending[j].iInGameHoursBeforeTrigger," hours before trigger.")
BOOL bPurged = FALSE
//if the thread this is based on is still in the buffers
BOOL bInBuffers = FALSE
BOOL bFoundOrDone = FALSE
INT iDTBuffer = 0//threads
CDEBUG1LN(DEBUG_EMAIL, "Looking for thread with ID : ", g_DynamicEmailsPending[j].RegIDOfTarget, ".")
WHILE !bFoundOrDone
IF g_DynamicEmailThreadBuffers[iDTBuffer].registrationID != g_DynamicEmailsPending[j].RegIDOfTarget
++iDTBuffer //keep looking
ELSE
//target still in the buffer, this is still valid
bInBuffers = TRUE
bFoundOrDone = TRUE
ENDIF
IF iDTBuffer = DYNAMIC_EMAIL_THREAD_BUFFERS
//not in buffers at all. Clear this one
bFoundOrDone = TRUE
g_DynamicEmailsPending[j].RegIDOfTarget = 0
bPurged = TRUE
ENDIF
ENDWHILE
IF !bInBuffers
CDEBUG1LN(DEBUG_EMAIL, "Pending dynamic email ", j," was not in buffers.")
bPurged = TRUE
g_DynamicEmailsPending[j].bNotSent = FALSE
ELSE
//If it is still in the buffers check if the timer is 0 or less
//If so fire and purge it
IF g_DynamicEmailsPending[j].iInGameHoursBeforeTrigger < 1
CDEBUG1LN(DEBUG_EMAIL, "About to send pending dynamic email. bOverrideContent: ",
PICK_STRING(g_DynamicEmailsPending[j].bOverrideContent, "TRUE", "FALSE"),
" iOverrideAdditional:", g_DynamicEmailsPending[j].iOverrideAdditional, ".")
IF PRIVATE_Is_Safe_To_Start_Communication(7, NO_CHARACTER, CPR_MEDIUM)
BOOL bAboutToOverride = FALSE
IF (g_DynamicEmailsPending[j].bOverrideContent)
OR (g_DynamicEmailsPending[j].iOverrideAdditional > 0)
bAboutToOverride = TRUE
ENDIF
IF FIRE_EMAIL_INTO_DYNAMIC_THREAD(g_DynamicEmailsPending[j].eTargetThread, g_DynamicEmailsPending[j].eEmailID,bAboutToOverride)
BOOL noSubstrings = TRUE
IF g_DynamicEmailsPending[j].iOverrideAdditional > 0
noSubstrings = FALSE
ENDIF
IF g_DynamicEmailsPending[j].bOverrideContent
OVERRIDE_CONTENT_FOR_DYNAMIC_THREAD(g_DynamicEmailsPending[j].eTargetThread, g_DynamicEmailsPending[j].content,noSubstrings)
ENDIF
IF (g_DynamicEmailsPending[j].iOverrideAdditional > 0)
k = 0
REPEAT g_DynamicEmailsPending[j].iOverrideAdditional k
ADD_CONTENT_FOR_DYNAMIC_THREAD_SUBSTRING(g_DynamicEmailsPending[j].eTargetThread, g_DynamicEmailsPending[j].additional[k])
ENDREPEAT
ENDIF
IF bAboutToOverride AND NOT noSubstrings
PUSH_FEEDIFICATION_OF_DYNAMIC_THREAD(g_DynamicEmailsPending[j].eTargetThread)
ENDIF
RELEASE_DYNAMIC_THREAD_HOLD_ON_BUFFER(g_DynamicEmailsPending[j].eTargetThread)
ENDIF
//purge it
g_DynamicEmailsPending[j].RegIDOfTarget = 0
g_DynamicEmailsPending[j].bOverrideContent = FALSE
g_DynamicEmailsPending[j].iInGameHoursBeforeTrigger = 0
bPurged = TRUE
g_DynamicEmailsPending[j].bNotSent = FALSE
ENDIF
ENDIF
ENDIF
//remember to clear this from the list if it's been sent or purged
IF bPurged
--g_iDynamicEmailsPending
CDEBUG1LN(DEBUG_EMAIL, "Now ", g_iDynamicEmailsPending, " dynamic emails left still pending.")
ENDIF
--iTodo
ENDIF
++j
IF j = MAX_DYNAMIC_EMAILS_PENDING
//list fully processed failsafe
iTodo = 0
ENDIF
WAIT(0)
ENDWHILE
ENDIF
ENDIF
ENDIF
CDEBUG3LN(DEBUG_EMAIL, "Sleeping controller at point A for ", delay_stride, " milliseconds.")
WAIT(delay_stride)
g_iUnreadEmailsSP0 = 0
g_iUnreadEmailsSP1 = 0
g_iUnreadEmailsSP2 = 0
INT t = g_Inboxes[EMAILER_MICHAEL_DE_SANTO].iTotalMails
IF t > MAX_INBOX_LOGGED_MAILS_THREADS
t = MAX_INBOX_LOGGED_MAILS_THREADS
ENDIF
CDEBUG3LN(DEBUG_EMAIL, "Updating unread emails. StartP0:", g_iUnreadEmailsSP0, " StartP1:", g_iUnreadEmailsSP1, " StartP2:", g_iUnreadEmailsSP2, ".")
REPEAT t i
IF NOT g_Inboxes[EMAILER_MICHAEL_DE_SANTO].HasBeenViewed[i]
++g_iUnreadEmailsSP0
ENDIF
ENDREPEAT
t = g_Inboxes[EMAILER_FRANKLIN].iTotalMails
IF t > MAX_INBOX_LOGGED_MAILS_THREADS
t = MAX_INBOX_LOGGED_MAILS_THREADS
ENDIF
REPEAT t i
IF NOT g_Inboxes[EMAILER_FRANKLIN].HasBeenViewed[i]
++g_iUnreadEmailsSP1
ENDIF
ENDREPEAT
t = g_Inboxes[EMAILER_TREVOR_PHILIPS].iTotalMails
IF t > MAX_INBOX_LOGGED_MAILS_THREADS
t = MAX_INBOX_LOGGED_MAILS_THREADS
ENDIF
REPEAT t i
IF NOT g_Inboxes[EMAILER_TREVOR_PHILIPS].HasBeenViewed[i]
++g_iUnreadEmailsSP2
ENDIF
ENDREPEAT
CDEBUG3LN(DEBUG_EMAIL, "Sleeping controller at point B for ", delay_stride, " milliseconds.")
WAIT(delay_stride)
ENDWHILE
ENDSCRIPT