Advanced hotkeys

I have started to plan a complete rework of hotkeys. I have a previous thread where I demonstrate this, titled "Completely customizable hotkeys mod", and it works fine but its implementation is not exactly user friendly for customizing as it's all code based, for my personal use.

So the main idea: (These are all already working in my version)

  • Allow different key bindings based on the context. Primarily this is based on the category of selected units (but could be other things as well). For example, having engineers selected will have its own keymapping, like an automatic build mode.

  • Allow for combinations. Modifier keys are great for re-using keys, but this would also make it possible to assign key combinations like Space-A if clicked in succession. It opens up a lot of possibilities to group your keys for different purposes. For example I use Space+other keys to set target priority. This keeps everything in reach at all times.

  • Allow chaining actions to run sequentially. If you want one button to do many things, like idk, selecting the closest engineer and build a pd - then you have to find a mod that has put these together for you. So I suggest that to be possible for users directly by selecting multiple actions from the list.

The new ideas:

  • Make a UI for all this that is easy to use. I imagine an "Advanced" button that goes into the Key Bindings dialog, that activate advanced mode and expands the dialog. Exact design is a work in progress, many things to consider.

  • Exporting of your keys and share it with others, making a list of presets for people to try out.

Questions

  • Do you have any ideas? How would you use it?

  • Are you interested in helping out? It could be fun you know.

  • If there is a desire for this to be integrated in the future, the team might want to get involved early and give me some advice on that process and any requirements. @Jip

My personal code-only version assigns all the hotkeys that I have specified in customKeyMap like you can see below, but its not super clean perhaps. I havent found a way to hijack the keypress in any other way, so suggestions are welcome.

function RunCustom(key)
	ForkThread(customKeyMap[key])
end

function Init()
	from(customKeyMap).foreach(function(k, v)
		local name = string.gsub(k, "-", "_")

		userKeyActions['AHK '..name] = {
			action = 'UI_Lua import("/mods/AdvancedHotkeys/modules/main.lua").RunCustom("'..k..'")',
			category = 'AHK'
		}

		userKeyMap[k] = 'AHK '..name
	end)

	Prefs.SetToCurrentProfile('UserKeyActions', userKeyActions)
	Prefs.SetToCurrentProfile('UserKeyMap', userKeyMap)
end
local customKeyMap = {

	['Esc'] = function() Hotkey('Esc', function(hotkey)
		print("Soft stop")
		ConExecute 'UI_Lua import("/lua/ui/game/orders.lua").SoftStop()'
                
                -- Key combo for double clicking
		SubHotkeys({
			['Esc'] = function() SubHotkey('Esc', function(hotkey)
				print("Stop")
				ConExecute 'UI_Lua import("/lua/ui/game/orders.lua").Stop()'
			end) end,
		})
	end) end, 
        -- ...
local function Hotkey(hotkey, func)
	subHotkey = subHotkeys[hotkey]
	local currentTime = GetSystemTimeSeconds()
	local diffTime = currentTime - lastClickTime
	local decay = 0.002 * Prefs.GetFromCurrentProfile('options.selection_sets_double_tap_decay')
	local inTime = diffTime < decay
	lastClickTime = currentTime

	if subHotkey ~= nil and inTime then
		ForkThread(subHotkey)
	else
		subHotkeys = nil
		func(hotkey)
	end
end

local function SubHotkeys(obj)
	subHotkeys = obj
end

local function SubHotkey(hotkey, func)
        local currentTime = GetSystemTimeSeconds()
	local diffTime = currentTime - lastClickTime
	local decay = 0.001 * Prefs.GetFromCurrentProfile('options.selection_sets_double_tap_decay')

	if storedUniqueIdentifier == hotkey and diffTime < decay then
		subHotkey = subHotkeys[hotkey]
	end

	storedUniqueIdentifier = hotkey

	func(hotkey)
end

Personally contextual keybinds would be great, you could rebind most of your order keys to build units when only factories are selected.

To make future integration easier you can look at the repository code at https://github.com/FAForever/fa and check out the code style of the recently changed files (some things like UI are very old and unchanged).

Update:

Instead of assigning keys to actions, you will assign actions to keys. As well as the context conditionals.

Obviously there are many things missing here, but I think something like this is how it must be.

Let me know if you see a better solution, before I get too far down the line 🙏

You select the key to edit, and scroll the list to the left and to find and add actions from there.

About the IF, ELSE IF, ELSE - its not super clean, and might be a bit unfamiliar for non-programmers. At first I wanted to have tabs or something to seperate the contexts, but I realize that the order matters, as a unit can be part of two contexts. So I see no other way than to specify this in each key, then perhaps add a filter to show only those with a certain conditional. This list will be very long, so the main issue I see is how to find what you're looking for, and to understand what it does (especially when importing someone elses preset).

Actions can be modified (or even added from scratch as ConExecutable code). For example you might want to add "+inview" to a select, which would give you only units currently on screen. This gives a high degree of freedom for those who understands coding without having to make a mod just for adding simple commands. This is of course optional.

I will aim to make it simple and clean, and those more advanced parts will be accessable from a drop down menu or something. The goal is to make it accessible to everyone.

Advanced Hotkeys.jpg

PS:

@Nomander Thanks for the feedback, I'm in there time to time trying to get familiar. Will try to stay in line. Still wonder though about how to do this so that the team is happy about the functionality as well, not just code.