Difference between revisions of "Measuring Time to Display Menus"

From the Oblivion ConstructionSet Wiki
Jump to navigation Jump to search
imported>Khalim19
m (grammar correction)
imported>Khalim19
(→‎Notes: clarification)
Line 14: Line 14:
*The script requires [[OBSE]] to run.
*The script requires [[OBSE]] to run.
*The script uses [[GetUserTime]] function from OBSE to get the user's current date and time. The [[GetSecondsPassed]] function cannot be used for the purposes of the script.
*The script uses [[GetUserTime]] function from OBSE to get the user's current date and time. The [[GetSecondsPassed]] function cannot be used for the purposes of the script.
*The time measured is displayed in seconds with precision up to three decimal places. The number of decimal places is restricted by the [[GetUserTime]] function - the "Millisecond" array element returned by the function can have values ranging from 0 to 999 only.
*The time measured is displayed in seconds with precision up to three decimal places. The number of decimal places is restricted by the [[GetUserTime]] function - the "Millisecond" array element returned by the function can only be an integer ranging from 0 to 999.
*The script runs every frame in order to get the most precise results.
*The script runs every frame in order to get the most precise results.



Revision as of 15:58, 28 August 2013

Introduction

While opening a menu or switching to another menu, the game is frozen. If it's desired to measure how long this time period lasts, you can use the quest script in this page for this purpose.

This can be useful e.g. to test performance when adding new/modifying existing menu components in Oblivion XML files, especially the inventory, magic or container menu, which can open really slow if there are hundreds of items in these menus.

The quest script:

  • measures the time it takes to open a menu from GameMode,
  • measures the time it takes to switch to another menu when in MenuMode.

As a side effect, the script can also measure the time it takes to load an interior or exterior when opening doors, using fast travel, etc. if loading screens are displayed, but not if loading saved games or starting a new game.

Notes

  • The script prints the currently active menu and the measured time to the console.
  • The script requires OBSE to run.
  • The script uses GetUserTime function from OBSE to get the user's current date and time. The GetSecondsPassed function cannot be used for the purposes of the script.
  • The time measured is displayed in seconds with precision up to three decimal places. The number of decimal places is restricted by the GetUserTime function - the "Millisecond" array element returned by the function can only be an integer ranging from 0 to 999.
  • The script runs every frame in order to get the most precise results.

The Script

scn OpenMenuTimeMeasureScript

float fQuestDelayTime

array_var previousUserTime
int previousDay
int previousHours
int previousMinutes
int previousSeconds
int previousMilliseconds
float previousTime

array_var currentUserTime
int currentDay
int currentHours
int currentMinutes
int currentSeconds
int currentMilliseconds
float currentTime

float timePassed

int previousMenuMode
int currentMenuMode
short isNewMenu
short isMenuMode		; 0 = GameMode, 1 = MenuMode

short runOpenMenuOnce
short initPreviousUserTimeOnce

Begin GameMode
	set fQuestDelayTime to 0.01
	
	if (initPreviousUserTimeOnce == 0)
		; The previousUserTime array is initialized and assigned values below.
		set initPreviousUserTimeOnce to 1
	endif

	if isMenuMode
		set isMenuMode to 0
	endif
	
	let previousUserTime := GetUserTime
	if (runOpenMenuOnce == 1)
		set runOpenMenuOnce to 0
	endif
End

Begin MenuMode
	set fQuestDelayTime to 0.01
	
	let currentMenuMode := GetActiveMenuMode
	
	if (isNewMenu == 0)   ; The first time the current (= active) menu is displayed
		let previousMenuMode := currentMenuMode
		set isNewMenu to 1
	elseif (previousMenuMode != currentMenuMode)
		; User switched to another menu
		set runOpenMenuOnce to 0
		set isNewMenu to 0
	elseif (previousMenuMode == currentMenuMode)
		if isMenuMode
			; In case user switches to another menu from the current menu
			let previousUserTime := GetUserTime
		endif
	endif

	; In case user leaves to GameMode and then reopens the last active menu again
	set isMenuMode to 1


	if runOpenMenuOnce
		return
	endif
	
	set runOpenMenuOnce to 1
	
	; Initialize the previousUserTime array in case the GameMode portion of the
	; script hasn't kicked in yet (where this array is initialized and assigned values).
	if (initPreviousUserTimeOnce == 0)
		set initPreviousUserTimeOnce to 1
		let previousUserTime := GetUserTime
	endif
	
	let currentUserTime := GetUserTime
	
	let previousDay := previousUserTime["Day"]
	let previousHours := previousUserTime["Hour"]
	let previousMinutes := previousUserTime["Minute"]
	let previousSeconds := previousUserTime["Second"]
	let previousMilliseconds := previousUserTime["Millisecond"]
	
	let currentDay := currentUserTime["Day"]
	let currentHours := previousUserTime["Hour"]
	let currentMinutes := currentUserTime["Minute"]
	let currentSeconds := currentUserTime["Second"]
	let currentMilliseconds := currentUserTime["Millisecond"]

	; Milliseconds are added later (because of precision errors I encountered)
	let previousTime := (previousHours * 3600) + (previousMinutes * 60) + previousSeconds
	let currentTime := (currentHours * 3600) + (currentMinutes * 60) + currentSeconds
	
	if (previousDay != currentDay)
		; Previous timestamp was captured before midnight
		; and the current timestamp after midnight.
		; 86400 seconds = 24 * 60 * 60 seconds = 1 day
		let currentTime := currentTime + 86400
	endif
	
	let timePassed := currentTime - previousTime + ((currentMilliseconds - previousMilliseconds) / 1000)
	
	printc "Menu %g", currentMenuMode
	printc "Time passed: %.3f", timePassed
End

Issues

  • The script will not yield correct values if the time measured is longer than one day (= 86400 seconds), which is extremely unlikely to happen.
  • The script will not measure time if a menu is reloaded via the "reload" command from the console.

As already mentioned, the script also measures time it takes to switch to another menu. There is an issue with this behavior, however. For example, in player's inventory menu, there are multiple menus on the screen that can be active (one at a time) - inventory menu, magic popup menu and HUD main menu. Moving your mouse outside the inventory menu causes the game to switch to the HUD main menu, which triggers the time measure. Moving your mouse back to the inventory menu triggers it again.

Ignoring the HUD main menu is not a solution, because if player opens the inventory menu and the mouse cursor points outside the inventory menu, the HUD main menu will be active first. The entire time the mouse is positioned over the HUD main menu would add to the time measured, causing it to be incorrect.

If you didn't understand from the description what the issue is, it should be clearer once you use the script in game and watch the console output. You may want to toggle debug text on by typing "tdt" in the console so that the output is displayed even if the console is not active.

This issue occurs in any menu.