Files
gtav-src/script/dev_ng/singleplayer/include/public/mission_event_manager.sch
T
2025-09-29 00:52:08 +02:00

672 lines
20 KiB
Scheme
Executable File

//
//
// Author: Michael Wadelin Date: 30/10/2012
//
//
//
// Asset management system
//
//
USING "commands_misc.sch"
USING "commands_debug.sch"
USING "buildtype.sch"
#IF IS_DEBUG_BUILD
USING "commands_pad.sch"
USING "script_debug_display.sch"
#ENDIF
CONST_INT MISSION_EVENT_STAGE_START 1
CONST_INT MISSION_EVENT_STAGE_END -1
#IF IS_DEBUG_BUILD
#IF NOT USE_TU_CHANGES
BOOL g_bDisplayMissionEventDebug = FALSE // Used to toggle the rendering of event debug info to the screen
INT g_iMissionEventDebugPage
#ENDIF
#IF USE_TU_CHANGES
TEXT_LABEL_31 TL_MISSION_EVENTS_DEBUG_PAGE = "Mission Events"
#ENDIF
#ENDIF
ENUM EVENT_STATE
EVENTSTATE_EMPTY = -1, // event not set
EVENTSTATE_READY, // event is ready to run
// Running States
EVENTSTATE_RUNNING, // running normally
EVENTSTATE_DELAYED, // a delay between now and the next stage has been added
EVENTSTATE_PAUSED, // event is paused completely
#IF USE_CLF_DLC
EVENTSTATE_CLEANUP,
#ENDIF
EVENTSTATE_COMPLETED // event has completed or has been forced to stop now
ENDENUM
STRUCT MISSION_EVENT_DATA
EVENT_STATE eState = EVENTSTATE_EMPTY
INT iStage = MISSION_EVENT_STAGE_START
INT iGenericFlag = 0
STRING strEventName = NULL
INT iTSStartEnd = -1
INT iTSStage = -1
INT iStageDelay = 0
ENDSTRUCT
TYPEDEF PROC UpdateMissionEvent(MISSION_EVENT_DATA &sData)
///PURPOSE:
/// Holds all the data that describes an event
STRUCT MISSION_EVENT_LINK_STRUCT
MISSION_EVENT_DATA sData
UpdateMissionEvent EVENT_UPDATE_PROC
ENDSTRUCT
#IF IS_DEBUG_BUILD
#IF NOT USE_TU_CHANGES
///PURPOSE:
/// Draws event debug information to the screen
DEBUGONLY PROC DRAW_MISSION_EVENT_DEBUG_INFO(MISSION_EVENT_LINK_STRUCT &sEvents[])
CONST_FLOAT f_left 0.05 // 0.1
CONST_FLOAT f_top 0.05 // 0.1
CONST_FLOAT f_spacing 0.05
CONST_FLOAT f_txt_scale 0.4
CONST_INT i_event_offset 3
CONST_FLOAT f_name_offset 0.03
CONST_FLOAT f_status_offset 0.17
CONST_FLOAT f_stage_offset 0.265
INT i_active_count = 0
BOOL bShowAllEvents
IF IS_KEYBOARD_KEY_PRESSED(KEY_END)
bShowAllEvents = TRUE
ELSE
bShowAllEvents = FALSE
ENDIF
INT i, i_wants_to_be_active, i_running_count, i_start_from_here
i_start_from_here = -1
WHILE i >= 0
BOOL bIsActive = FALSE
IF bShowAllEvents
SWITCH sEvents[i].sData.eState
CASE EVENTSTATE_RUNNING
FALLTHRU
CASE EVENTSTATE_DELAYED
i_running_count++
FALLTHRU
CASE EVENTSTATE_READY
FALLTHRU
CASE EVENTSTATE_PAUSED
FALLTHRU
CASE EVENTSTATE_COMPLETED
bIsActive = TRUE
BREAK
ENDSWITCH
ELSE
SWITCH sEvents[i].sData.eState
CASE EVENTSTATE_RUNNING
FALLTHRU
CASE EVENTSTATE_DELAYED
i_running_count++
FALLTHRU
CASE EVENTSTATE_PAUSED
bIsActive = TRUE
BREAK
CASE EVENTSTATE_COMPLETED
IF((GET_GAME_TIMER() - sEvents[i].sData.iTSStartEnd) < 10000)
bIsActive = TRUE
ENDIF
BREAK
ENDSWITCH
ENDIF
// store the index of the start for the active event
IF bIsActive
i_wants_to_be_active++
IF i_wants_to_be_active > g_iMissionEventDebugPage*10
IF i_start_from_here = -1
i_start_from_here = i
ENDIF
IF i_active_count < 10
i_active_count++
ENDIF
ENDIF
ENDIF
i++
IF i > count_of(sEvents)-1
i = -1
ENDIF
ENDWHILE
// If none active then there will be one line in there saying nothing is active
INT i_additional_line
IF i_active_count > 0
i_additional_line = 2
ELSE
i_additional_line = 1
ENDIF
DRAW_RECT_FROM_CORNER(f_left-0.01, f_top-0.01, 0.39, (f_txt_scale * 0.05 * (i_active_count+i_event_offset+i_additional_line)) + 0.02, 0,0,0, 150)
TEXT_LABEL_31 str_debug_info = "Mission Event Debug"
SET_TEXT_SCALE(f_txt_scale, f_txt_scale)
DISPLAY_TEXT_WITH_LITERAL_STRING(f_left, f_top, "STRING", str_debug_info)
i_active_count = 0
SET_TEXT_SCALE(f_txt_scale, f_txt_scale)
DISPLAY_TEXT_WITH_LITERAL_STRING(f_left, f_top+((i_event_offset-1)*f_spacing*f_txt_scale), "STRING", "ID")
SET_TEXT_SCALE(f_txt_scale, f_txt_scale)
DISPLAY_TEXT_WITH_LITERAL_STRING(f_left+f_name_offset, f_top+((i_event_offset-1)*f_spacing*f_txt_scale), "STRING", "Name")
SET_TEXT_SCALE(f_txt_scale, f_txt_scale)
DISPLAY_TEXT_WITH_LITERAL_STRING(f_left+f_status_offset, f_top+((i_event_offset-1)*f_spacing*f_txt_scale), "STRING", "Status")
SET_TEXT_SCALE(f_txt_scale, f_txt_scale)
DISPLAY_TEXT_WITH_LITERAL_STRING(f_left+f_stage_offset, f_top+((i_event_offset-1)*f_spacing*f_txt_scale), "STRING", "Stage")
i = i_start_from_here
WHILE i >= 0
INT debug_draw_col_r, debug_draw_col_g, debug_draw_col_b
BOOL bDrawThisEvent
TEXT_LABEL_23 str_debug_status
bDrawThisEvent = FALSE
SWITCH sEvents[i].sData.eState
CASE EVENTSTATE_READY
str_debug_status = "Idle"
debug_draw_col_r = 77
debug_draw_col_g = 77
debug_draw_col_b = 77
IF bShowAllEvents
bDrawThisEvent = TRUE
i_active_count++
ENDIF
BREAK
CASE EVENTSTATE_RUNNING
str_debug_status = "Running"
debug_draw_col_r = 255
debug_draw_col_g = 191
debug_draw_col_b = 0
bDrawThisEvent = TRUE
i_active_count++
BREAK
CASE EVENTSTATE_DELAYED
str_debug_status = "Delayed"
debug_draw_col_r = 184
debug_draw_col_g = 184
debug_draw_col_b = 116
bDrawThisEvent = TRUE
i_active_count++
BREAK
CASE EVENTSTATE_PAUSED
str_debug_status = "Paused"
debug_draw_col_r = 255
debug_draw_col_g = 0
debug_draw_col_b = 255
bDrawThisEvent = TRUE
i_active_count++
BREAK
CASE EVENTSTATE_COMPLETED
#IF USE_CLF_DLC
CASE EVENTSTATE_COMPLETED
#ENDIF
str_debug_status = "Complete"
debug_draw_col_r = 68
debug_draw_col_g = 255
debug_draw_col_b = 40
IF bShowAllEvents
OR ((GET_GAME_TIMER() - sEvents[i].sData.iTSStartEnd) < 10000)
bDrawThisEvent = TRUE
i_active_count++
ENDIF
BREAK
ENDSWITCH
IF bDrawThisEvent
// ID
str_debug_info = ""
str_debug_info += i
SET_TEXT_COLOUR(debug_draw_col_r,debug_draw_col_g,debug_draw_col_b, 255)
SET_TEXT_SCALE(f_txt_scale, f_txt_scale)
DISPLAY_TEXT_WITH_LITERAL_STRING(f_left, f_top+((i_active_count+i_event_offset)*f_spacing*f_txt_scale), "STRING", str_debug_info)
// Name
str_debug_info = ""
str_debug_info += sEvents[i].sData.strEventName
SET_TEXT_COLOUR(debug_draw_col_r,debug_draw_col_g,debug_draw_col_b, 255)
SET_TEXT_SCALE(f_txt_scale, f_txt_scale)
DISPLAY_TEXT_WITH_LITERAL_STRING(f_left+f_name_offset, f_top+((i_active_count+i_event_offset)*f_spacing*f_txt_scale), "STRING", str_debug_info)
// Status
SET_TEXT_COLOUR(debug_draw_col_r,debug_draw_col_g,debug_draw_col_b, 255)
SET_TEXT_SCALE(f_txt_scale, f_txt_scale)
DISPLAY_TEXT_WITH_LITERAL_STRING(f_left+f_status_offset, f_top+((i_active_count+i_event_offset)*f_spacing*f_txt_scale), "STRING", str_debug_status)
// Stage
str_debug_info = ""
str_debug_info += sEvents[i].sData.iStage
SET_TEXT_COLOUR(debug_draw_col_r,debug_draw_col_g,debug_draw_col_b, 255)
SET_TEXT_SCALE(f_txt_scale, f_txt_scale)
DISPLAY_TEXT_WITH_LITERAL_STRING(f_left+f_stage_offset, f_top+((i_active_count+i_event_offset)*f_spacing*f_txt_scale), "STRING", str_debug_info)
ENDIF
i++
IF i > count_of(sEvents)-1
OR i_active_count >= 10
i = -1
ENDIF
ENDWHILE
IF i_active_count = 0
SET_TEXT_COLOUR(163, 163, 163, 255)
SET_TEXT_SCALE(f_txt_scale, f_txt_scale)
DISPLAY_TEXT_WITH_LITERAL_STRING(f_left, f_top+(i_event_offset*f_spacing*f_txt_scale), "STRING", "no active mission events")
ELSE
str_debug_info = "currently running "
str_debug_info += i_running_count
str_debug_info += " event(s)"
SET_TEXT_COLOUR(255,255,255, 255)
SET_TEXT_SCALE(f_txt_scale, f_txt_scale)
DISPLAY_TEXT_WITH_LITERAL_STRING(f_left, f_top+(((i_active_count+1)+i_event_offset)*f_spacing*f_txt_scale), "STRING", str_debug_info)
ENDIF
IF IS_KEYBOARD_KEY_JUST_PRESSED(KEY_INSERT)
g_iMissionEventDebugPage--
ELIF IS_KEYBOARD_KEY_JUST_PRESSED(KEY_DELETE)
g_iMissionEventDebugPage++
ENDIF
g_iMissionEventDebugPage = CLAMP_INT(g_iMissionEventDebugPage, 0, CEIL(i_wants_to_be_active/10.0)-1)
ENDPROC
#ENDIF
#IF USE_TU_CHANGES
///PURPOSE:
/// Draws event debug information to the screen
DEBUGONLY PROC DRAW_MISSION_EVENT_DEBUG_INFO(DEBUG_DISPLAY &sDebugData, MISSION_EVENT_LINK_STRUCT &sEvents[])
IF sEvents[0].sData.iStage = 0
ENDIF
CONST_INT I_EVENT_DEBUG_TABS_AFTER_ID 3
CONST_INT I_EVENT_DEBUG_TABS_AFTER_NAME 38
CONST_INT I_EVENT_DEBUG_TABS_AFTER_STATUS 4
CONST_INT I_EVENT_DEBUG_TABS_AFTER_STAGE 1
INT i
TEXT_LABEL_63 str_debug_info
str_debug_info = "ID"
REPEAT I_EVENT_DEBUG_TABS_AFTER_ID i
str_debug_info += " "
ENDREPEAT
str_debug_info += "Name"
REPEAT I_EVENT_DEBUG_TABS_AFTER_NAME i
str_debug_info += " "
ENDREPEAT
str_debug_info += "Status"
REPEAT I_EVENT_DEBUG_TABS_AFTER_STATUS i
str_debug_info += " "
ENDREPEAT
str_debug_info += "Stage"
REPEAT I_EVENT_DEBUG_TABS_AFTER_STAGE i
str_debug_info += " "
ENDREPEAT
DEBUG_DISPLAY_STRING_THIS_FRAME( sDebugData, str_debug_info, TL_MISSION_EVENTS_DEBUG_PAGE )
DEBUG_DISPLAY_SPACE_THIS_FRAME( sDebugData, TL_MISSION_EVENTS_DEBUG_PAGE )
REPEAT COUNT_OF( sEvents ) i
INT j, iStringLength
IF NOT IS_STRING_NULL_OR_EMPTY( sEvents[i].sData.strEventName )
// INT debug_draw_col_r, debug_draw_col_g, debug_draw_col_b
TEXT_LABEL_23 str_debug_status
TEXT_LABEL_63 str_temp
SWITCH sEvents[i].sData.eState
CASE EVENTSTATE_READY
str_debug_status = "Idle"
// debug_draw_col_r = 77
// debug_draw_col_g = 77
// debug_draw_col_b = 77
BREAK
CASE EVENTSTATE_RUNNING
str_debug_status = "Running"
// debug_draw_col_r = 255
// debug_draw_col_g = 191
// debug_draw_col_b = 0
BREAK
CASE EVENTSTATE_DELAYED
str_debug_status = "Delayed"
// debug_draw_col_r = 184
// debug_draw_col_g = 184
// debug_draw_col_b = 116
BREAK
CASE EVENTSTATE_PAUSED
str_debug_status = "Paused"
// debug_draw_col_r = 255
// debug_draw_col_g = 0
// debug_draw_col_b = 255
BREAK
CASE EVENTSTATE_COMPLETED
str_debug_status = "Complete"
// debug_draw_col_r = 68
// debug_draw_col_g = 255
// debug_draw_col_b = 40
BREAK
ENDSWITCH
// ID
str_debug_info = ""
str_temp = i
str_debug_info += str_temp
iStringLength = GET_LENGTH_OF_LITERAL_STRING( str_temp )
REPEAT ( ( I_EVENT_DEBUG_TABS_AFTER_ID + 2 ) - iStringLength ) j
str_debug_info += " "
ENDREPEAT
// Name
IF GET_LENGTH_OF_LITERAL_STRING( sEvents[i].sData.strEventName ) >= I_EVENT_DEBUG_TABS_AFTER_NAME + 4 - 2
str_temp = GET_STRING_FROM_STRING( sEvents[i].sData.strEventName, 0, I_EVENT_DEBUG_TABS_AFTER_NAME + 4 - 2 )
ELSE
str_temp = sEvents[i].sData.strEventName
ENDIF
str_debug_info += str_temp
//iStringLength = GET_LENGTH_OF_LITERAL_STRING( str_debug_info ) - ( I_EVENT_DEBUG_TABS_AFTER_ID + 2 )
iStringLength = GET_LENGTH_OF_LITERAL_STRING( str_temp )
REPEAT ( ( I_EVENT_DEBUG_TABS_AFTER_NAME + 4 ) - iStringLength ) j
str_debug_info += " "
ENDREPEAT
// Status
str_temp = str_debug_status
//iStringLength = GET_LENGTH_OF_LITERAL_STRING( str_debug_info ) - ( I_EVENT_DEBUG_TABS_AFTER_ID + 2 ) - ( I_EVENT_DEBUG_TABS_AFTER_NAME + 4 )
str_debug_info += str_temp
iStringLength = GET_LENGTH_OF_LITERAL_STRING( str_temp )
REPEAT ( ( I_EVENT_DEBUG_TABS_AFTER_STATUS + 6 ) - iStringLength ) j
str_debug_info += " "
ENDREPEAT
// Stage
str_temp = sEvents[i].sData.iStage
str_debug_info += str_temp
//iStringLength = GET_LENGTH_OF_LITERAL_STRING( str_debug_info ) - ( I_EVENT_DEBUG_TABS_AFTER_ID + 2 ) - ( I_EVENT_DEBUG_TABS_AFTER_NAME + 4 ) - ( I_EVENT_DEBUG_TABS_AFTER_STATUS + 6 )
iStringLength = GET_LENGTH_OF_LITERAL_STRING( str_temp )
REPEAT ( ( I_EVENT_DEBUG_TABS_AFTER_STAGE + 5 ) -iStringLength ) j
str_debug_info += " "
ENDREPEAT
DEBUG_DISPLAY_STRING_THIS_FRAME( sDebugData, str_debug_info, TL_MISSION_EVENTS_DEBUG_PAGE )
ENDIF
ENDREPEAT
ENDPROC
#ENDIF
#ENDIF
/// PURPOSE:
/// Adds a new mission event to the mission event system
/// PARAMS:
/// sEvent - Event struct to contain all the info for the event
/// strEventName - Debug name for the event, used for debug output
/// RETURNS:
/// Returns TRUE if the event has been added successfully, FALSE if not.
FUNC BOOL ADD_NEW_MISSION_EVENT(MISSION_EVENT_LINK_STRUCT &sEvent, UpdateMissionEvent event_proc, STRING strEventName)
IF sEvent.sData.eState != EVENTSTATE_EMPTY
SCRIPT_ASSERT("Specified event struct is already populated!")
RETURN FALSE
ELSE
sEvent.sData.eState = EVENTSTATE_READY
sEvent.sData.strEventName = strEventName
sEvent.EVENT_UPDATE_PROC = event_proc
RETURN TRUE
ENDIF
ENDFUNC
/// PURPOSE:
/// Resets the given event struct to the defaul variables
PROC REMOVE_MISSION_EVENT(MISSION_EVENT_LINK_STRUCT &sEvent)
MISSION_EVENT_LINK_STRUCT sNew
sEvent = sNew
ENDPROC
/// PURPOSE:
/// Removes all the mission events from the array
PROC REMOVE_ALL_MISSION_EVENTS(MISSION_EVENT_LINK_STRUCT &sEvents[])
INT i
REPEAT COUNT_OF(sEvents) i
REMOVE_MISSION_EVENT(sEvents[i])
ENDREPEAT
ENDPROC
///PURPOSE:
/// Indicates whether an event has been triggered or not
FUNC BOOL IS_MISSION_EVENT_TRIGGERED(MISSION_EVENT_DATA &sEvent)
IF sEvent.eState != EVENTSTATE_READY
AND (sEvent.eState != EVENTSTATE_DELAYED OR sEvent.iStage > 0)
#IF USE_CLF_DLC
AND sEvent.eState != EVENTSTATE_EMPTY
#ENDIF
RETURN TRUE
ELSE
RETURN FALSE
ENDIF
ENDFUNC
///PURPOSE:
/// Indicates whether an event has completed OR for USE_CLF_DLC = EVENTSTATE_CLEANUP
FUNC BOOL IS_MISSION_EVENT_ENDED(MISSION_EVENT_DATA &sEvent)
IF sEvent.eState = EVENTSTATE_COMPLETED
#IF USE_CLF_DLC
OR sEvent.eState = EVENTSTATE_CLEANUP
#ENDIF
RETURN TRUE
ELSE
RETURN FALSE
ENDIF
ENDFUNC
///PURPOSE:
/// Indicates if an event is ready to be used
FUNC BOOL IS_MISSION_EVENT_READY(MISSION_EVENT_DATA &sEvent)
IF sEvent.eState = EVENTSTATE_READY
RETURN TRUE
ELSE
RETURN FALSE
ENDIF
ENDFUNC
/// PURPOSE:
/// Indicates if an event is currently running
FUNC BOOL IS_MISSION_EVENT_RUNNING(MISSION_EVENT_DATA &sEvent)
IF IS_MISSION_EVENT_TRIGGERED(sEvent)
AND (NOT IS_MISSION_EVENT_ENDED(sEvent))
RETURN TRUE
ELSE
RETURN FALSE
ENDIF
ENDFUNC
///PURPOSE: Triggers an event
/// Trigger the specified event
FUNC BOOL TRIGGER_MISSION_EVENT(MISSION_EVENT_DATA &sEvent, INT iDelay = 0, BOOL bOverrideDelay = FALSE #IF USE_TU_CHANGES , INT iStartStage = MISSION_EVENT_STAGE_START #ENDIF )
IF sEvent.eState = EVENTSTATE_EMPTY
// event has not been added and is empty
SCRIPT_ASSERT("MISSION EVENT SYSTEM: Event does not exist!")
RETURN FALSE
ELIF sEvent.eState = EVENTSTATE_RUNNING
// already running
RETURN TRUE
ELIF sEvent.eState = EVENTSTATE_READY
OR (sEvent.eState = EVENTSTATE_DELAYED AND sEvent.iStage = MISSION_EVENT_STAGE_START AND bOverrideDelay) // a event with a start delay that has not yet kicked in
IF iDelay > 0
sEvent.eState = EVENTSTATE_DELAYED
sEvent.iStageDelay = iDelay
ELSE
sEvent.eState = EVENTSTATE_RUNNING
sEvent.iStageDelay = 0
ENDIF
sEvent.iTSStartEnd = GET_GAME_TIMER()
sEvent.iTSStage = GET_GAME_TIMER()
#IF USE_TU_CHANGES
sEvent.iStage = iStartStage
#ENDIF
#IF NOT USE_TU_CHANGES
sEvent.iStage = MISSION_EVENT_STAGE_START
#ENDIF
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE:
///
PROC END_MISSION_EVENT(MISSION_EVENT_DATA &sEvent)
IF sEvent.eState != EVENTSTATE_COMPLETED
#IF USE_CLF_DLC
AND sEvent.eState != EVENTSTATE_EMPTY
#ENDIF
#IF USE_CLF_DLC
sEvent.eState = EVENTSTATE_CLEANUP
#ENDIF
#IF NOT USE_CLF_DLC
sEvent.eState = EVENTSTATE_COMPLETED
#ENDIF
sEvent.iTSStartEnd = GET_GAME_TIMER()
sEvent.iStageDelay = 0
sEvent.iStage = MISSION_EVENT_STAGE_END
ENDIF
ENDPROC
/// PURPOSE:
///
PROC END_ALL_MISSION_EVENTS(MISSION_EVENT_LINK_STRUCT &sEvents[])
INT i
REPEAT COUNT_OF(sEvents) i
END_MISSION_EVENT(sEvents[i].sData)
ENDREPEAT
ENDPROC
/// PURPOSE:
///
PROC PAUSE_MISSION_EVENT(MISSION_EVENT_DATA &sEvent)
IF sEvent.eState != EVENTSTATE_COMPLETED
AND sEvent.eState != EVENTSTATE_READY
#IF USE_CLF_DLC
AND sEvent.eState != EVENTSTATE_EMPTY
#ENDIF
sEvent.eState = EVENTSTATE_PAUSED
ENDIF
ENDPROC
/// PURPOSE:
///
PROC RESUME_MISSION_EVENT(MISSION_EVENT_DATA &sEvent)
IF sEvent.eState = EVENTSTATE_PAUSED
sEvent.eState = EVENTSTATE_RUNNING
ENDIF
ENDPROC
/// PURPOSE:
///
PROC RESET_MISSION_EVENT(MISSION_EVENT_DATA &sEvent)
IF NOT IS_MISSION_EVENT_READY(sEvent)
#IF USE_CLF_DLC
AND sEvent.eState != EVENTSTATE_EMPTY
#ENDIF
sEvent.eState = EVENTSTATE_READY
ENDIF
ENDPROC
// Resets all the events in the mission
PROC RESET_ALL_MISSION_EVENTS(MISSION_EVENT_LINK_STRUCT &sEvents[])
INT i
REPEAT COUNT_OF(sEvents) i
RESET_MISSION_EVENT(sEvents[i].sData)
ENDREPEAT
ENDPROC
// Used to delay events internally insde their procs
PROC SET_MISSION_EVENT_STAGE(MISSION_EVENT_DATA &sEvent, INT iStage, INT iDelay = 0)
#IF USE_CLF_DLC
IF sEvent.eState != EVENTSTATE_EMPTY
#ENDIF
// Add delay if marked
IF iDelay > 0
sEvent.eState = EVENTSTATE_DELAYED
sEvent.iTSStage = GET_GAME_TIMER()
sEvent.iStageDelay = iDelay
ENDIF
sEvent.iStage = iStage
#IF USE_CLF_DLC
ENDIF
#ENDIF
ENDPROC
/// PURPOSE:
///
/// PARAMS:
/// sEvents -
PROC UPDATE_MISSION_EVENTS(MISSION_EVENT_LINK_STRUCT &sEvents[])
INT i
REPEAT COUNT_OF(sEvents) i
SWITCH sEvents[i].sData.eState
CASE EVENTSTATE_RUNNING
CALL sEvents[i].EVENT_UPDATE_PROC(sEvents[i].sData)
BREAK
CASE EVENTSTATE_DELAYED
IF (GET_GAME_TIMER() - sEvents[i].sData.iTSStage) > sEvents[i].sData.iStageDelay
sEvents[i].sData.eState = EVENTSTATE_RUNNING
sEvents[i].sData.iStageDelay = 0
ENDIF
BREAK
#IF USE_CLF_DLC
CASE EVENTSTATE_CLEANUP
CALL sEvents[i].EVENT_UPDATE_PROC(sEvents[i].sData)
sEvents[i].sData.eState = EVENTSTATE_COMPLETED
BREAK
#ENDIF
ENDSWITCH
ENDREPEAT
#IF NOT USE_TU_CHANGES
#IF IS_DEBUG_BUILD
IF IS_KEYBOARD_KEY_JUST_PRESSED(KEY_HOME) g_bDisplayMissionEventDebug = !g_bDisplayMissionEventDebug ENDIF
IF g_bDisplayMissionEventDebug
DRAW_MISSION_EVENT_DEBUG_INFO(sEvents)
ENDIF
#ENDIF
#ENDIF
ENDPROC