Tes3Mod:ToggleMenus and HUD workarounds
The ToggleMenus function can be useful to force the game engine out of Menu Mode, but some scripters (myself included) have had real issues with using it.
Remember that a second ToggleMenus call is always necessary. Without this, menus do not "have permission" to display at all. Attempting to force menus to open by script, while the general Menus state is toggled "off", will often cause freezing/CTD.
As others have found, however, using a double ToggleMenus call has the nasty side effect of completely disabling the HUD. Once disabled, the HUD will not reappear until it is reinitialized.
There are only two events, that I know of, that will force the game engine to reinitialize the HUD without the player's intervention. There may be others, but these are the ones I have tested and which I know work:-
Any new cell load (interior or exterior) forces the game engine to reinitialize the game interface completely, including the HUD.
Begin nigedo_hidemove If ( OnActivate ) ToggleMenus Player->COE 0 0 ToggleMenus Endif End
This means that it is entirely safe to use ToggleMenus to hide the cell load progress bar in the case of scripts that teleport the player by means of multiple cell loads. Delaying the second ToggleMenus call until the same frame that the player arrives in their destination cell will hide the transportation and still reinitialize the HUD.
This is the other, and more useful, means of reinitializing the HUD.
a) If you use ToggleMenus to immediately exit dialogue, you should add follow on code to initiate a ForceGreeting from the same NPC and then call ToggleMenus twice, to restart the HUD and safely leave Menu Mode respectively.
e.g. Call this script from a StartScript in the required dialogue Results field:-
Begin nigedo_exit_dialogue Short step If ( step == 0 ) ToggleMenus ToggleMenus Set step to 1 Elseif ( step == 1 ) ForceGreeting ToggleMenus Set step to 2 Elseif ( step == 2 ) ToggleMenus MenuTest StopScript nigedo_exit_dialogue Endif End
- The functions must be called in separate frames in this order to work successfully.
- Calling ForceGreeting in the same frame as the first of the second set of ToggleMenus calls (step 1), allows the HUD to remain active despite menus state being toggled "off". I believe this is because the ForceGreeting is already in the process of reinitializing the HUD as the ToggleMenus call processes. The ToggleMenus call catches the dialogue window, but not the HUD.
- The MenuTest call (step 2) eliminates an inventory view Menu Mode state that appears to underlie dialogue Menu Mode states.
b) If you want to use this method to safely exit Menu Mode states other than dialogue, you will need to create a custom NPC that you can use to initiate a ForceGreeting call, as required.
To do this:
- Create a new race with default attributes - call it "race_invisible"
- Create a new NPC using the race "race_invisible" and call him "npc_HUD_reset"
- Create a new dialogue entry towards the start of the "Greetings 0" section. Filter it by ID = "npc_HUD_reset" and enter the text "." (this isn't strictly necessary, but it's cleaner)
Then add this script to "npc_HUD_reset":-
Begin nigedo_reset_HUD Short step If ( GetDisabled ) SetDelete 1 Return Endif If ( step == 0 ) ForceGreeting ToggleMenus Set step to 1 Elseif ( step == 1 ) ToggleMenus MenuTest Disable Set step to 0 Endif End
Now, whenever you create a script that uses ToggleMenus calls to exit Menu Mode, add a follow on section that places an instance of "npc_HUD_reset" at the player.
e.g. This example exits the inventory share Menu Mode state, when activating a container:-
Begin nigedo_container_shutDown Short step If ( step == 0 ) If ( OnActivate ) Activate Set step to 1 Endif Elseif ( step == 1 ) MenuTest ToggleMenus ToggleMenus Set step to 2 Elseif ( step == 2 ) If ( MenuMode ) Return Endif PlaceAtPC npc_HUD_reset 1 0 0 Set step to 0 Endif End
Note that, in this case, a MenuTest call is necessary at step 1, in order to exit an underlying inventory view Menu Mode state. This is not always necessary and MenuTest can cause problems if called unnecessarily. Experiment with your specific needs and determine whether you may need additional MenuTest calls to assist the process.