0xC0FFEE's Rotating Keybind Tutorial

What the heck are 'rotating keybinds'?

'Rotating keybinds' is something I came up with for remapping large numbers of keybinds quickly and easily, without ever having to type 'bind' or 'exec' commands in the console.

This technique allows you to have an infinite (yes, infinite!) number of keybind sets that you can cycle through. You can have different keybinds for assault/defense, or a keybind set for each map. You can have two sets of 'Great Job Team!', etc. keybinds; one that does the squad commo of 'GJT', and another that does 'GJT' as a teamsay. (No more "West!" when you meant to say "Good Job Soldier!") And you can probably do some cool stuff that I haven't even thought of yet!

The 0XC0FFEE Keybind Philosophy

Generally, binding multiple (non-commo) actions to a key will get you into trouble (some multiple action keybinds are considered cheating by many people, including me). Don't bind multiple actions to keys unless they are all commo actions.

Also, please don't bind extra comms to common actions like reloading. It's a waste of a line on people's consoles to have someone say 'Cover me while I reload' when they are on the other side of the map. Remember that there are only a limited number of lines in each person's message console, and everyone needs to see reports and deaths. Don't clog people's message consoles up with useless blabbering.

My keybinds (and there are a LOT of them) are for communicating with my team only. They are not for saying 'W+f 0\/\/|\|3D!' every time I get a kill. They are not for belittling or harassing other players. They are for reporting enemies and issuing instructions or warnings: "Coming up the ladder, HOLD YOUR FIRE!", "E MAIN ENTRANCE!", "Please keep the main pump room doors closed!" etc.

To summarize: don't be a chat-spamming idiot. Use commo keybinds judiciously and when appropriate. With good commo keybinds, you can help your team win by providing timely and accurate information on enemy movements, and by the superior teamwork enabled by good communication.

Rotating Keybind Tutorial

This is an advanced technique. If you are unfamiliar with changing keybinds, creating and executing text files, and editing the command aliases in your USER.INI file, you should probably acquaint yourself with those subjects first.

I will attempt to explain this as best I can, using some very simple examples. This will take a while, bear with me...

The first step in creating your own rotating keybinds is to create text files that contain your keybinds. I'm a Pipeline whore, so my example will use Pipeline specific keybinds for reporting enemies. (NOTE: teamsay commands do not work in single-player mode, you will need to connect to a server to try out the examples.)

Create a text file in your AA/system directory named DEFENSE.TXT with the following contents:

code:
;DEFENSE.TXT

bind numpad1 teamsay E PRIMARY VALVE!
bind numpad2 teamsay E SECONDARY VALVE!
bind numpad3 teamsay E EXTERIOR VALVE!

You can load these keybinds by typing 'exec defense.txt' in the AA console.

Now, let's make one for assault. Instead of reporting enemies at the objectives (which is practically a given), our assault keybinds will be for reporting enemies exiting the buildings.

Create a text file in your AA/system directory named ASSAULT.TXT with the following contents:
code:
;ASSAULT.TXT

bind numpad1 teamsay E MAIN ENTRANCE!
bind numpad2 teamsay E NORTHSIDE (SECONDARY) ENTRANCE!
bind numpad3 teamsay E OUTSIDE EXT VALVE!

You can load these keybinds by typing 'exec assault.txt' in the AA console.

We can bind the execution of these two text files to the PageUp and PageDn keys by doing these commands in the AA console:
code:
bind pageup exec defense.txt
bind pagedn exec assault.txt

Now, pressing PageUp will load the defense keybinds, and pressing PageDn will load the assault keybinds.

But what would be even better is if we could have just one button switch between assault and defense keybinds, an assault/defense toggle, if you will. This is easily possible. The trick is that the toggle key has its mapping changed by the very text file it is invoking.

So let's add a line at the bottom of the DEFENSE.TXT:
code:
;DEFENSE.TXT

bind numpad1 teamsay E PRIMARY VALVE!
bind numpad2 teamsay E SECONDARY VALVE!
bind numpad3 teamsay E EXTERIOR VALVE!
bind pageup exec assault.txt

And let's add a similar line at the bottom of ASSAULT.TXT:
code:
;ASSAULT.TXT

bind numpad1 teamsay E MAIN ENTRANCE!
bind numpad2 teamsay E NORTHSIDE (SECONDARY) ENTRANCE!
bind numpad3 teamsay E OUTSIDE EXT VALVE!
bind pageup exec defense.txt

Now we can switch between assault and defense keybind sets by pressing only the PageUp key! Each keybind set remaps PageUp to load the other set.

This could be carried on infinitely, with each press of the PageUp key loading a different set of keybinds and remapping PageUp to load the next set. You could even remap PageUp and PageDn to 'page' through the list, by remapping them to act as 'next' and 'previous' buttons. (This is what I have done. Although I only have three sets of keybinds to cycle through, I had to do it just as 'proof of concept'.)

But now we have another problem: how to know which keybind set is the active one. And AA does not provide any means (that I know of) for displaying messages on the console, other than teamsay or global messages. The 'type' command in the Unreal engine doesn't seem to work. And we don't want to bother our teammates by announcing what keybind set we just loaded, because we might be switching them a lot.

Fortunately, there's a way around this. We can use the PunkBuster client to display a console message, like this:
code:
pb_*   YOUR MESSAGE HERE   *

If you put a line like that in a text file that you exec, the Punkbuster client will display an error message on the console, like this:
code:
PunkBuster Client: Unknown Command/Setting: pb_*   YOUR MESSAGE HERE   *

Crude, but effective. There may be a better way to put a message on the console, but I don't know it. If anyone knows of one, I'd love to hear about it. For now, this will have to do. (If anybody is worried that PB is logging your PB client error messages, I've been doing this for months and have never had a problem. So either they aren't, or they don't care.)

To have our text files display a message on the console, let's add another line to DEFENSE.TXT:
code:
;DEFENSE.TXT

bind numpad1 teamsay E PRIMARY VALVE!
bind numpad2 teamsay E SECONDARY VALVE!
bind numpad3 teamsay E EXTERIOR VALVE!
bind pageup exec assault.txt
pb_*   DEFENSE keybinds loaded   *

And ASSAULT.TXT:
code:
;ASSAULT.TXT

bind numpad1 teamsay E MAIN ENTRANCE!
bind numpad2 teamsay E NORTHSIDE (SECONDARY) ENTRANCE!
bind numpad3 teamsay E OUTSIDE EXT VALVE!
bind pageup exec defense.txt
pb_*   ASSAULT keybinds loaded   *

Now when we press the PageUp key, not only is a different set of keybinds loaded, but we also get a nifty message on the console saying WHICH keybinds have just been loaded.

You could also take this one step further, and make a text file with nothing but pb_** messages. Make one called DEFENSELIST.TXT like this:
code:
;DEFENSELIST.TXT

pb_*   1 - E PRI   *
pb_*   2 - E SEC   *
pb_*   3 - E EXT   *

If you exec DEFENSELIST.TXT, you will see this on your console:
code:
PunkBuster Client: Unknown Command/Setting: pb_*   1 - E PRI   *
PunkBuster Client: Unknown Command/Setting: pb_*   2 - E SEC   *
PunkBuster Client: Unknown Command/Setting: pb_*   3 - E EXT   *

And, of course, you could bind execution of DEFENSELIST.TXT to, for example, the K key, by doing 'bind K exec defenselist.txt'. You could also add a line to DEFENSE.TXT and ASSAULT.TXT that would remap K to exec DEFENSELIST.TXT and ASSAULTLIST.TXT respectively. (I use the F12 key for this function.)

Unfortunately, there are limitations to what you can accomplish with keybinds by using text files. You cannot bind multiple actions to a key, like you can in the USER.INI file. For example:
code:
I=reportin|commoradio|commosendmessage 25

This binds the following actions to the I key: report in, switch to radio commo (in case commo was set to something else, like hand), and send the message "I'm hit!".

You can't do the same thing with a 'bind' command in a text file. What happens is that the text file executes the commands after each pipe, so having:
code:
bind I reportin|commoradio|commosendmessage 25

in a text file results in the following actions:
  1. 'I' gets mapped to the 'reportin' action, and nothing else
     
  2. your commo gets switched to radio
     
  3. the message 'I'm hit' is sent over the radio

To get around this limitation, you can use command aliases. At the top of the [Engine.Input] section of your USER.INI file are several lines like this:
code:
Aliases[0]=(Command="Button bFire | Fire",Alias="Fire")
Aliases[1]=(Command="Button bAltFire | AltFire",Alias="AltFire")
...on down to Aliases[40]

Most of these you can re-appropriate for your own use. For example:
code:
Aliases[17]=(Command="Button SnapLevel",Alias="CenterView")
is practically useless. Who uses 'CenterView' anyways? But you can remap it to do a multiple command commo, like this:
code:
Aliases[17]=(Command="commosquad|commosendmessage 17|commoradio|commosendmessage 99",Alias="Squad_GJS")

The 'commoradio|commosendmessage 99' is to put your commo back to regular radio, rather than leaving it on the squad radio. The 'commosendmessage 99' part is required because 'commoradio' switches to radio commo and leaves the radio commo menu open, and you have to press a key to close it. '99' is just an invalid message number that closes the menu. '666' would probably work just as well.

To map F7 to our squad radio 'Good Job Soldier', we can put this line in a text file, then 'exec' it:
code:
bind F7 Squad_GJS

And then, of course, you could have in another text file:
code:
bind F7 teamsay "Good Job Soldier!"

In my own configuration, I have F5 switch between squad leader messages and teamsays by executing the text files SQUAD.TXT and NO_SQUAD.TXT.

First, you need to have the following lines in the aliases section of your USER.INI file:
code:
Aliases[XX]=(Command="commosquad|commosendmessage 17|commoradio|commosendmessage 99",Alias="Squad_GJS")
Aliases[XX]=(Command="commosquad|commosendmessage 18|commoradio|commosendmessage 99",Alias="Squad_GJT")
Aliases[XX]=(Command="commosquad|commosendmessage 6|commoradio|commosendmessage 99",Alias="Squad_HoldPos")
Aliases[XX]=(Command="commosquad|commosendmessage 12|commoradio|commosendmessage 99",Alias="Squad_What")
Aliases[XX]=(Command="commosquad|commosendmessage 2|commoradio|commosendmessage 99",Alias="Squad_SpreadOut")
Aliases[XX]=(Command="commosquad|commosendmessage 7|commoradio|commosendmessage 99",Alias="Squad_Report")
I have removed the alias numbers because they will vary depending on what aliases you decide to re-appropriate.

I *think* that only the following aliases are 'must-haves', but things may have changed in 2.4:
code:
Aliases[0]=(Command="Button bFire | Fire",Alias="Fire")
Aliases[1]=(Command="Button bAltFire | AltFire",Alias="AltFire")
Aliases[2]=(Command="Axis aBaseY Speed=+300.0",Alias="MoveForward")
Aliases[3]=(Command="Axis aBaseY Speed=-300.0",Alias="MoveBackward")
Aliases[4]=(Command="Axis aStrafe Speed=-300.0",Alias="StrafeLeft")
Aliases[5]=(Command="Axis aStrafe Speed=+300.0",Alias="StrafeRight")
Aliases[6]=(Command="Jump | Axis aUp Speed=+300.0",Alias="Jump")
Aliases[7]=(Command="Button bAction | Action",Alias="Action")
Aliases[8]=(Command="Button bLeanRight | LeanRight",Alias="LeanRight")
Aliases[9]=(Command="Button bLeanLeft | LeanLeft",Alias="LeanLeft")
Aliases[10]=(Command="Button bSprint | Sprint",Alias="Sprint")
This would give you aliases 11-40 to use for your own stuff.

And now the text files:
code:
;SQUAD.TXT

bind F5 exec nosquad.txt
bind F7 Squad_GJS
bind F8 Squad_GJT
bind F9 Squad_HoldPos
bind F10 Squad_What
bind F11 Squad_SpreadOut
bind Enter Squad_Report
pb_*     SQUAD     keybinds loaded     *
As you can see, when squad keybinds are loaded, F5 switches to the no_squad keybinds.

The other text file looks like this:
code:
;NO_SQUAD.TXT

bind F5 exec squad.txt
bind F7 teamsay "Good job soldier!"
bind F8 teamsay "Great job team!"
bind F9 teamsay "Hold this position!"
bind F10 teamsay "What are you doing, soldier?!"
bind F11 teamsay "Spread out!"
bind Enter teamsay ">> REPORT IN! <<"
pb_*     NOSQUAD     keybinds loaded     *
With the no_squad keybinds loaded, F5 switches back to the squad keybinds.

Now I can use the same key (Enter) for "Report In!" regardless of whether I am squad leader or not. If I am squad leader, I press F5 until I see 'SQUAD keybinds loaded', and Enter sends "Report in!" over the squad radio. If I am not squad leader, I load the no_squad keybinds, again, simply by pressing F5 until I see 'NOSQUAD keybinds loaded', and Enter teamsays ">> REPORT IN! <<". Same thing for GJS, GJT, etc.
 

Rotating Keybinds: A Critical Analysis

In my rotating keybinds tutorial, I explained how it was possible to make a single key cycle through multiple sets of keybinds by execing text files. This is very useful for map-specific enemy reporting or gameplan keybinds, which I map to my number pad.

The trick was that the key that exec'd a text file would be re-bound during the execution of that text file. So, you would press a key, PageUp, for example, which would exec text file A. Inside text file A was a bind command to re-bind PageUp to exec text file B. When text file B was exec'd, PageUp could be re-bound back to exec text file A, completing the loop, or you could continue on with text files C,D,E, and F. The last text file must remap PageUp to load the first text file in order to maintain a looping structure.

This is all well and good. Except for a number of shortcomings:

1) Execution of each text file would remap 11 (0-9, plus period) keys on the numberpad. This would cause the game to lag a bit, because each bind requires that the USER.INI file be changed. Bind a key, write to USER.INI. Bind a key, write to USER.INI. And then nine more times. For each press of the 'cycle keybind' button.

Given that this keybind loading lag is unavoidable, it only makes sense to minimize the number of times new keybinds are loaded. The ‘rotating keybinds’ technique does not do this. In fact, if you have more than two keybind sets in the rotation, you _will_ have to load a set you aren’t going to use (possibly several), on your way to the one you want.

2) Although the number of keybind sets that you could cycle through is theoretically limitless, it quickly becomes impractical as you add keybind sets.

If you are on set #1 for example, and want to load set #9, you would have to press your 'cycle keybind' button eight times. 11 writes to USER.INI times 8 keypresses means that USER.INI is updated 88 times! And if you don't have two 'cycle' buttons (forward and backward), you could easily skip past the set you wanted, and have to go all the way through the list again! This is highly inefficient and annoying.

3) The 'rotating' enabled by the looping structure requires that multiple text files be edited to add or remove text files from the rotation. This is not a big deal if you just need to add one more set to the rotation, but if you want to move a set from the middle of the list to the end, or if you want to insert a set into the middle of the list, you will have your work cut out for you. And it can get tough to keep it all straight.

4) There are 32 AA maps. And two teams per map. That’s 64(!) keybind sets, if you wanted to do them all. How the hell do you manage that many keybind sets?! Not by loading each one in sequence until you find the one you want, that’s for sure!

With all these points in mind, I set about developing my next keybind loading technique. I wanted the following:

-random access to a full set (11 keys) of number pad keybinds for every single AA map (currently 64 sets)
-the capability to (easily) add maps in the future, when they are included with new releases of AA
-easy changing of keybinds for individual maps (by editing as few files as possible, with no knowledge or understanding of the keybind loading mechanisms required)
-the ability to display a list of the currently active keybinds
-keybinds must be toggle-able between assault & defense

Over the past few weeks, I have come up with another way to load map-specific number pad keybinds, that meets all of the requirements above. It relies on two of the techniques employed with 'rotating' keybinds: 1) using the Punkbuster client to display 'error' messages with the menu contents, and 2) re-binding the 'exec' key in exec'd text files

I am providing the system I came up with for AA community use HERE. Installation instructions and full keybind and map lists are included.

AA Binds v2

Since I created the rotating keybinds tutorial, I have discovered that Unreal color codes work in the PB client error messages. This is fortunate, as it allows menus with much greater readability.

So what I did was to have PageUp exec a text file that remaps the number pad to act as menu selections. So, you press PageUp, and you see this in your console window:


At this point, the only number keys on the numpad that are active are 0, 1, and 2. All other numeric numpad binds have been erased, so pressing 4 or 5 won't do anything.

Pressing 0 will present a list of the regular map groupings, like this:


Then, pressing 0 to select 172nd Infantry Brigade shows a list of the 172nd maps:


Pressing 1 will load the Pipeline keybinds and display the message:


Notice that you do not have to select assault or defense. The Pipeline map defaults to 'defense', but this is easily changed by editing the appropriate text file. To switch between assault and defense, I have utilized the PageDn key to act as an assault/defense toggle. Repeated pressing of PageDn does this:


I have also employed the F12 key to display a list of the key assignments for the active bind set. Pressing F12 with the pipeline defense binds loaded displays:


So, you can press in rapid succession: PageUp 0 0 1 and you will load the Pipeline keybinds. PageUp 1 0 1 will load SF Hospital binds, etc. Each map has a three digit code assigned to it, making random access to all 32 maps a piece of cake!

Another bonus is the single player keybind set. Press PageUp, then 2 to load the single player keybind list. Here it is:


Notice items 0 and 1. While the single player menu is active, you can type the three digit map code and instead of loading keybinds for that map, it loads that map. No more checking a map list to see what the actual filename is if you want to check out a map in single player mode. They’re all right here!

I have also incorporated the SSG/not SSG toggle (on F6) used in the rotating keybinds method:


While in a keybind or map loading menu, the numpad period key acts as a ‘cancel’ button and will unbind all of the number keys on the numpad.


It also remains active as ‘cancel’ in the single player bindset.

All the keybinds reside in the directory C:\aabinds2, with each map having its own subdirectory. Inside each map subdirectory are four files: the defense keybinds, the defense keybind list, and the assault keybinds and keybind list. This makes it very easy to edit the keybinds and their associated listing.

You can edit keybinds for only the maps you use, without having to bother with any of the others. In my own case, I only have pipeline binds configured, so that’s all that is configured in the aabinds2 system. I have only provided a framework that others can build on.

Have fun!
 

DOWNLOAD AA Binds v2

 

 

Back Home

Visitors currently browsing this website.

© 2006 {PoT} Pipeline Operations Team
Last Page Update: