Summary:
This short tutorial fixes a couple of really annoying problems in Quake that have to do with all sorts of aliases and keybinds being triggered inappropriately in situations in-game, in the console and when using ALT-TAB or changing video mode (if you are using an engine that supports that).
Walkthrough:
This part fixes the ALT-TAB and video mode changing issues. Later on, the console and messagemode fixes are addressed.
For starters, some of the code is not really in the right place in Quake.
I moved Key_ClearAllStates from gl_vidnt.c/vid_win.c into keys.c. There is no Windows-only code in Key_ClearAllStates, so it is just a more sensible location.
Here is the ClearAllStates from GLQuake:
And the Key_ClearStates from GLQuake:/*
================
ClearAllStates
================
*/
void ClearAllStates (void)
{
int i;
// send an up event for each key, to make sure the server clears them all
for (i=0 ; i<256 ; i++)
{
Key_Event (i, false);
}
Key_ClearStates ();
IN_ClearStates ();
}
/*
===================
Key_ClearStates
===================
*/
void Key_ClearStates (void)
{
int i;
for (i=0 ; i<256 ; i++)
{
keydown = false;
key_repeats = 0;
}
}
Note that the above is setting the down state to false.
And here is the IN_ClearStates from GLQuake in in_win.c:
/*
===================
IN_ClearStates
===================
*/
void IN_ClearStates (void)
{
if (mouseactive)
{
mx_accum = 0;
my_accum = 0;
mouse_oldbuttonstate = 0;
}
}
This is reseting the mouse coordinates.
What is wrong with the way GLQuake does it
First, it is triggering -aliases FOR all keys. It doesn't matter if the key was depressed or not. This can have undesirable effects when ALT-TAB is done or if the client supports video mode changing.
Second, only ClearAllStates in gl_vidnt.c/vid_win.c calls Key_ClearStates. Why have 2 procedures separate and 1 of them in clearly the wrong source file.
What I did to fix this ...
Only ClearAllStates calls Key_ClearStates and it's in the wrong place. I deleted ClearAllStates from gl_vidnt.c and vid_win.c. Then renamed Key_ClearStates to Key_ClearAllStates.
And instead of triggering every key with a release event, it only triggers key events for keys that were actually down.
Code: Select all
/*
==================
Key_ClearAllStates
==================
*/
void Key_ClearAllStates (void)
{
int i;
for (i=0 ; i<256 ; i++)
{
// If the key is down, trigger the up action if, say, +showscores or another +bind is activated
if (keydown[i])
Key_Event (i, false);
}
IN_ClearStates ();
}
Extra Credit
The above doesn't address another issue. Minus -aliases are triggered in the console or even in messagemode! This is annoying.
My console, for instance, gets spammed with "-hook isn't a valid alias" and weird impulses gets trigger when I'm in message mode because I have a weapon changing binds with both +aliases and -aliases. I've had other oddball things happen while typing, I even ruined a tournament game once when logged in as admin from this because all sorts of things can get triggered by -aliases being executed while chatting.
The Fix For That
First, we are going to mark whether a key was depressed while in-game.
Second, in Key_Event we need a temp variable to store this value. This is because Key_Event will need to set the down state to false if exiting.//At the top of keys.c
qboolean keygamedown[256];
And we need to set this variable immediately after "keydown[key] = down;"//keys.c in Key_Event
qboolean wasgamekey = false;
Code: Select all
//keys.c in Key_Event
wasgamekey = keygamedown[key]; // Baker: to prevent -aliases being triggered in-console needlessly
if (!down) {
keygamedown[key] = false;
}
And finally, we need to have it set the keygamedown ONLY when the +alias is executed:if (!down)
{
// Baker: we only want to trigger -alias if appropriate
// but we ALWAYS want to exit if key is up
if (wasgamekey) {
kb = keybindings[key];
if (kb && kb[0] == '+')
{
Q_snprintfz (cmd, sizeof(cmd), "-%s %i\n", kb+1, key);
Cbuf_AddText (cmd);
}
if (keyshift[key] != key)
{
kb = keybindings[keyshift[key]];
if (kb && kb[0] == '+')
{
Q_snprintfz (cmd, sizeof(cmd), "-%s %i\n", kb+1, key);
Cbuf_AddText (cmd);
}
}
}
return;
}
if ((kb = keybindings[key]))
{
// Baker: if we are here, the key is down
// and if it is retrigger a bind
// it must be allowed to trigger the -bind
//
keygamedown[key]=true; // Let it be untriggered anytime
if (kb[0] == '+')
{ // button commands add keynum as a parm
Q_snprintfz (cmd, sizeof(cmd), "%s %i\n", kb, key);
Cbuf_AddText (cmd);
}
else
{
Cbuf_AddText (kb);
Cbuf_AddText ("\n");
}
}
return;