The MOST detailed UI modding tutorial · hotkey aspect

[Guide for UI modders]
This is a tutorial for those who want to add their own hotkeys into game.
I don't know how the original game binds keys to various actions , but the following is a way available for modders
Firstly , we need to pay attention to this directory , for Windows , it is
-- C:\Users\User\AppData\Local\Gas Powered Games\Supreme Commander Forged Alliance --
And you will find a file named game.prefs here . Yes , 'prefs' is the suffix , thus you must tell your Windows which application you want to open it with. Mine is notepad ++
This is where SUPCOM storages its user datas .
How to access it in game ? It's a function embedded in Engine , and you can find it in
-- SupCom\mohodata\lua\user\prefs.lua --
You will see something named 'GetPreference' here.
It can be found on supcom wiki , however , only such a perfunctory statement.
'INFO: obj GetPreference(string, [default])'
What 'GetPreference' actually does is extracting datas from game.prefs . That's why you can pass 'profile' , or 'profile.profiles' to it , as the game.prefs itself contains these tables.


Secondly , we should notice that there is a thing called profile.current .
It is a number , recording how many profiles you have in game.
Emmm.....
Is it really that simple ? Of course not.
Another role it plays is pointing to the current profile , which is used by Player now. New profile would be added to the end of profile table , and its index is just equal to the total sum.
So you would see these codes .

if profile.profiles[profile.current] then

As profile.current pointing to the current profile , the current profile must storaged with a index having a value of profile.current , which indicates that all the profiles are storaged in profile.profiles . You would understand the abovementioned code better if you take a look of game.prefs.


Thirdly , take a look of this line of codes.

profile.profiles[profile.current][fieldName] = data

If you do have took a look of game.prefs , you would notice the variable called 'fieldName' .
You can put whatever you want into this variable , even give it a value of 'asdjoiadjgrjsiofgjsdoigr' , though which won't be discerned by game.
I'm not talking about something magical , but if you want your custom fieldName can be recognized , you need to assume that there're really a ton of lines of fixed codes somewhere you can't reach , saying 'local x = profile.userkeyaction' , or something like that , fixed , unchangeable .
Thus if you want your codes be recognized by game , especially to put your custom hotkey into use , you must follow the specification .


The specification I found is following:
If you want to add your own hotkeys into game , there're two things you need to pay attention to.
One is action, the another is category.
Game says : There will be v.category . Then there popped out a rule for modders that if you don't have a element indexed with string 'category' in table , even if this table contains actual command , game won't recognize it.
Category is necessary , but what value it actually holds is not important. You can say:

local t = { action = 'rtertghfgh' , category = 'bbhhnjnjfg' }

Just keep category ~= nil , and if there's no such a bbhhnjnjfg category , game will create a new one. You can press F1 to see this category printed out .


For action , if you don't give it a string path value like
"UI_Lua import('/mods/apimod/lib/main.lua')._print()"
The game would remind you that unknown console command not found.
e.g. The game won't find what is called rtertghfgh.
But anyway , it runs successfully .
Keep it in mind that if you don't have a action stuff while still having category , the game will crash at the beginning , because he cannot comprehend a nil value as actual path .
And if you have both two , you can put them together into one table .
Usually , we have another element called order , but this is not a thing decisive
Finally , your codes look like

local t = {	
	action = "dxxxx", 
	category = 'dxddx', 
	order = 35
	}

You can add whatever you like into variable t , though they will not be discerned.
It's also legal.

local t = {	
	12,34,45,67,89,90,
	action = "dxxxx", 
	category = 'dxddx', 
	order = 350
	}



We are not finished yet.
After completing table t , we need to put t into a larger table .

local s = {t}

Somewhere we can't see , game loops table s , and for each k,v in s , it loops v to know what category this v has, and what action this v refers to , and prints k as a description of the action in v .
If you directly pass t as the result , like that

Prefs.SetToCurrentProfile("UserKeyActions", t)

Things you made won't be shown in game , as the game is attempting to loop a string value. The game would get stuck .


Once everything set well , you should worry about the description shown out.
The game shows index of table t in the table s as the description for the t , which is number 1 in this case.
You can set the index as a string , but that's not convenient.
Mine solution is :

local keydes = import('/lua/keymap/keydescriptions.lua').keyDescriptions
keydes[1] = 'dsdsds'

Note that I said keydes[1] , not keydes['1'] , as the index is number not a string.
Lua passes table from = rightside to = leftside as referrence , so you can call keydes[1] to modify original table , which is the one game reads datas from.
Thus one gamemain.lua file does all the thing , no need for modders to put keydescriptions.lua into hook.


Eventually , the hotkeys bound to custom actions are shown in currentprofile.UserKeyMap .
Thus , even though you clear UserKeyActions , there's still referrence to the hotkey bound to the cleared one.
Theoretically , you can make use of \lua\keymap in similar way , to achieve similar function without using UserKeyActions , you can make a try. I suggest you to do these in gamemain.lua , do not put too many files into hook to mess up your mod.

You should read this old forum post (and thread including use of smartselect) :
https://forums.faforever.com/viewtopic.php?f=40&t=8230

@reckless_charger I know this . Mine is modifying lua , not game.prefs

Yeah but link may still be useful for others and the first line of your post does say 'This is a tutorial for those who want to add their own hotkeys into game.'

@illumination This was a fantastic read, and I almost have my head around it. Can the integrated hotkey mod be changed in this way? For example, one of the default combinations is 'Upgrade - T3 mobile AA - T3 transport - T3 torpedo bomber'. Could I swap Transport with ASF in that combination? Or would I need to write a new mod for that new hotkey combo?