Jump to content

[LE] Transferring hot key registration between scripts


Recommended Posts

I had a secondary quest script that resided on my MCM quest which used the OnKeyDown event while the key registration was handled on the MCM script within an OnUpdate event which is registered for during the OnConfigClose event. While tweaking some features, I realized that if the OnKeyDown event were on a player alias that I could handle some additional things (i.e. toggling a bool variable with the key press that would allow certain code to run during the OnItemRemoved event that would ordinarily be blocked). Anyway, since the alias script doesn't get the key registration from the MCM I came up with this solution.

 

 

MCM script

Int OldMAK
;variable is set to -1.0 inside the OnConfigInit event -- same value as initial hot key dxscancode

Event OnKeyDown(Int KeyCode)
    If  KeyCode == abim_IMS_ModActKeyGV.GetValue()
        If OldMAK != KeyCode
            OldMAK = KeyCode
            SendModEvent("abim_HotKeyInitiateEvent")
            Debug.Notification("Initiating secondary script hot key registration")
        EndIf
    UnRegisterForAllKeys()
    EndIf
EndEvent

Alias script

Event OnPlayerLoadGame()
	RegisterForModEvent("abim_HotKeyInitiateEvent","OnHotKeyInitiate")
EndEvent
;mod event is also registered in the OnInit event

Event OnHotKeyInitiate(string eventName, string strArg, float numArg, Form sender)
	UnregisterForAllKeys()
    Int MAK = abim_IMS_ModActKeyGV.GetValue() as Int
    If  MAK != -1.0
        RegisterForKey(MAK)
        Debug.Notification("Hot key registration complete")
        OnKeyDown(MAK)
    EndIf
EndEvent

Result: Player picks a hotkey in the MCM. On first use, the event is sent and the alias script processes it and registers for the designated key and then calls the OnKeyDown event so that the user doesn't have to perform a double press to achieve the function they wanted to perform with the hotkey. From then on the key press triggers the OnKeyDown event on the alias.

 

 

Thought this was rather ingenious myself as I'd never used the mod event feature from SKSE before. However, if there is a better way, I'd like to know.

Link to comment
Share on other sites

Very creative.

 

You could also create and fill a property to that alias in the MCM script and trigger the registration directly. I would put this in the alias script.

Event RegisterHotkey(int keyCode)
	UnregisterForAllKeys()
	if keyCode != -1
		RegisterForKey(keyCode)
	endif
EndEvent

Technically you could do all of those checks and calls from the MCM script, but at a minimum it would mean calling both Unregister and Register remotely which is slower than calling a function which can then call them on its own object. And you don't actually need that global variable with this scheme since you would be passing the new keycode directly through the function.

Link to comment
Share on other sites

 

You could also create and fill a property to that alias in the MCM script and trigger the registration directly. I would put this in the alias script.

Technically you could do all of those checks and calls from the MCM script, but at a minimum it would mean calling both Unregister and Register remotely which is slower than calling a function which can then call them on its own object. And you don't actually need that global variable with this scheme since you would be passing the new keycode directly through the function.

 

@ cdcooley For my own personal reference, is this what you mean?

 

MCM

ReferenceAlias Property PlayerAlias Auto
Int Property nKeyInt = -1 Auto
    
State BindKey

    Event OnKeyMapChangeST(int aiNewkeyCode, string asConflictControl, string asConflictName)
        If KeyConflict(aiNewKeyCode, asConflictControl, asConflictName)
            nKeyInt = aiNewKeyCode
            (PlayerAlias as AliasPlayerScript).UnregisterForKey(aiNewKeyCode)
            self.SetKeyMapOptionValueST(nKeyInt)
            (PlayerAlias as AliasPlayerScript).RegisterForKey(aiNewKeyCode)
        EndIf
    EndEvent
    Event OnDefaultST()
        (PlayerAlias as AliasPlayerScript).UnregisterForKey(nKeyInt)
        nKeyInt = -1
        self.SetKeyMapOptionValueST(nKeyInt)
    EndEvent
    Event OnHighlightST()
        SetInfoText("Assign a Hot Key to ....\nDefault will unbind Hot Key")
    EndEvent
EndState

Alias

ModConfigMenuScript Property Config Auto
    
Event OnKeyDown(Int KeyCode)
    If(KeyCode == Config.nKeyInt)
        ; ....
    EndIf
Event

So the MCM Key is neat & tidy, with the Keycode Int changed from private variable to a property? So the Alias can use it. The code is untested for function or compilation, be kind, I'm self taught.

Link to comment
Share on other sites

@ cdcooley

I should have thought of that since I have called functions on other scripts like that before. At least I got to learn how to use something that was new to me. Is there any harm in leaving it the way it is (at least until I need to make more than just a minor edit)?

Link to comment
Share on other sites

@ cdcooley

I should have thought of that since I have called functions on other scripts like that before. At least I got to learn how to use something that was new to me. Is there any harm in leaving it the way it is (at least until I need to make more than just a minor edit)?

No problem I can see.

Link to comment
Share on other sites

@ cdcooley For my own personal reference, is this what you mean?

No, because now the alias script has to access the MCM quest script which is a lot slower than accessing a global variable.

 

Ideally you should never store your actual mod state information in the MCM script itself. The MCM script should always be using values form other scripts or global variables. I personally love using custom properties in the other scripts to keep things simple for the MCM (and to ensure they always have sane values).

 

MCM

AliasPlayerScript Property PlayerAlias Auto
    
; when setting up the menu in OnPageReset
; AddKeyMapOptionST("BindKey", "Hot Key", PlayerAlias.hotkeyCode, OPTION_FLAG_WITH_UNMAP)

State BindKey

	Event OnKeyMapChangeST(int newKeyCode, string conflictControl, string conflictName)
		; whatever conflict resolution checks you feel are needed here
		PlayerAlias.hotkeyCode = newKeyCode
		SetKeyMapOptionValueST(newKeyCode)
	endEvent

	Event OnDefaultST()
		PlayerAlias.hotkeyCode = -1  ; unmap it
	EndEvent

	Event OnHighlightST()
		SetInfoText("Assign a Hot Key to ....\nDefault will unbind Hot Key")
	EndEvent

EndState

Alias

ScriptName AliasPlayerScript extends ReferenceAlias

int hotkeyCode_var = -1 ; initially unmapped

int Property hotkeyCode Hidden

	int Function get()
		return hotkeyCode_var
	EndFunction

	Function set(int newCode)  ; unregister old key and register the new one
		if hotkeyCode_var > -1
			UnregisterForKey(hotkeyCode_var)
		endif
		hotkeyCode_var = newCode
		if hotkeyCode_var > -1
			RegisterForKey(hotkeyCode_var)
		elseif hotkeyCode_var < -1
			hotkeyCode_var = -1 ; so it displays correctly in the MCM
		endif
	EndFunction

EndProperty


Event OnKeyDown(int keyCode)
	if keycode == hotkeyCode_var
		; do something interesting
	endif
EndEvent

That property may look complicated but if you wanted multiple hotkeys you can duplicate it and replace the hotkeyCode and hotkeyCode_var names to make as many different hotkeys as you wanted and they would all handle their own registrations independently.

 

And yes, you can safely change the hotkey registrations while the MCM is open. They don't require game mode or block the MCM script processing in any way.

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...