2010-11-20 10:37:14 +00:00
|
|
|
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
|
|
|
|
/* If you are missing that file, acquire a complete release at teeworlds.com. */
|
2020-09-26 19:41:58 +00:00
|
|
|
#include "binds.h"
|
2010-05-29 07:25:38 +00:00
|
|
|
#include <engine/config.h>
|
|
|
|
#include <engine/shared/config.h>
|
2008-08-27 15:48:50 +00:00
|
|
|
|
2022-02-07 23:37:08 +00:00
|
|
|
#include <game/client/gameclient.h>
|
|
|
|
|
2021-03-08 03:41:27 +00:00
|
|
|
static const ColorRGBA gs_BindPrintColor{1.0f, 1.0f, 0.8f, 1.0f};
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
bool CBinds::CBindsSpecial::OnInput(IInput::CEvent Event)
|
2008-08-30 09:34:55 +00:00
|
|
|
{
|
2019-04-28 13:32:14 +00:00
|
|
|
// only handle F and composed F binds
|
2022-02-07 23:37:08 +00:00
|
|
|
if(((Event.m_Key >= KEY_F1 && Event.m_Key <= KEY_F12) || (Event.m_Key >= KEY_F13 && Event.m_Key <= KEY_F24)) && (Event.m_Key != KEY_F5 || !m_pClient->m_Menus.IsActive()))
|
2008-08-30 09:34:55 +00:00
|
|
|
{
|
2022-01-22 16:34:23 +00:00
|
|
|
int Mask = CBinds::GetModifierMask(Input());
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2021-04-17 15:37:39 +00:00
|
|
|
// Look for a composed bind
|
2019-04-28 13:32:14 +00:00
|
|
|
bool ret = false;
|
2022-04-28 06:45:25 +00:00
|
|
|
if(m_pBinds->m_aapKeyBindings[Mask][Event.m_Key])
|
2019-04-28 13:32:14 +00:00
|
|
|
{
|
2022-04-28 06:45:25 +00:00
|
|
|
m_pBinds->GetConsole()->ExecuteLineStroked(Event.m_Flags & IInput::FLAG_PRESS, m_pBinds->m_aapKeyBindings[Mask][Event.m_Key]);
|
|
|
|
ret = true;
|
2021-04-17 15:37:39 +00:00
|
|
|
}
|
|
|
|
// Look for a non composed bind
|
|
|
|
if(!ret && m_pBinds->m_aapKeyBindings[0][Event.m_Key])
|
|
|
|
{
|
|
|
|
m_pBinds->GetConsole()->ExecuteLineStroked(Event.m_Flags & IInput::FLAG_PRESS, m_pBinds->m_aapKeyBindings[0][Event.m_Key]);
|
2019-04-28 13:32:14 +00:00
|
|
|
ret = true;
|
|
|
|
}
|
2021-04-17 15:37:39 +00:00
|
|
|
|
2019-04-28 13:32:14 +00:00
|
|
|
return ret;
|
2008-08-30 09:34:55 +00:00
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2008-08-30 09:34:55 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
CBinds::CBinds()
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2019-04-28 13:32:14 +00:00
|
|
|
mem_zero(m_aapKeyBindings, sizeof(m_aapKeyBindings));
|
2010-05-29 07:25:38 +00:00
|
|
|
m_SpecialBinds.m_pBinds = this;
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
|
2017-04-11 23:36:48 +00:00
|
|
|
CBinds::~CBinds()
|
|
|
|
{
|
|
|
|
for(int i = 0; i < KEY_LAST; i++)
|
2020-10-26 14:14:07 +00:00
|
|
|
for(auto &apKeyBinding : m_aapKeyBindings)
|
2022-03-01 22:19:49 +00:00
|
|
|
free(apKeyBinding[i]);
|
2017-04-11 23:36:48 +00:00
|
|
|
}
|
|
|
|
|
2022-02-06 21:57:04 +00:00
|
|
|
void CBinds::Bind(int KeyID, const char *pStr, bool FreeOnly, int ModifierCombination)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2011-02-12 10:40:36 +00:00
|
|
|
if(KeyID < 0 || KeyID >= KEY_LAST)
|
2008-08-27 15:48:50 +00:00
|
|
|
return;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2022-02-06 21:57:04 +00:00
|
|
|
if(FreeOnly && Get(KeyID, ModifierCombination)[0])
|
2017-07-21 17:32:32 +00:00
|
|
|
return;
|
|
|
|
|
2022-03-01 22:19:49 +00:00
|
|
|
free(m_aapKeyBindings[ModifierCombination][KeyID]);
|
|
|
|
m_aapKeyBindings[ModifierCombination][KeyID] = 0;
|
2017-04-11 23:36:48 +00:00
|
|
|
|
2019-04-28 13:41:32 +00:00
|
|
|
// skip modifiers for +xxx binds
|
|
|
|
if(pStr[0] == '+')
|
2022-02-06 21:57:04 +00:00
|
|
|
ModifierCombination = 0;
|
2019-04-28 13:41:32 +00:00
|
|
|
|
2010-08-17 22:06:00 +00:00
|
|
|
char aBuf[256];
|
2017-04-11 23:36:48 +00:00
|
|
|
if(!pStr[0])
|
|
|
|
{
|
2022-02-06 21:57:04 +00:00
|
|
|
str_format(aBuf, sizeof(aBuf), "unbound %s%s (%d)", GetKeyBindModifiersName(ModifierCombination), Input()->KeyName(KeyID), KeyID);
|
2017-04-11 23:36:48 +00:00
|
|
|
}
|
2008-08-27 15:48:50 +00:00
|
|
|
else
|
2017-04-11 23:36:48 +00:00
|
|
|
{
|
2018-04-09 09:56:39 +00:00
|
|
|
int Size = str_length(pStr) + 1;
|
2022-02-06 21:57:04 +00:00
|
|
|
m_aapKeyBindings[ModifierCombination][KeyID] = (char *)malloc(Size);
|
|
|
|
str_copy(m_aapKeyBindings[ModifierCombination][KeyID], pStr, Size);
|
|
|
|
str_format(aBuf, sizeof(aBuf), "bound %s%s (%d) = %s", GetKeyBindModifiersName(ModifierCombination), Input()->KeyName(KeyID), KeyID, m_aapKeyBindings[ModifierCombination][KeyID]);
|
2017-04-11 23:36:48 +00:00
|
|
|
}
|
2022-03-06 11:22:29 +00:00
|
|
|
Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "binds", aBuf, gs_BindPrintColor);
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
int CBinds::GetModifierMask(IInput *pInput)
|
2019-04-28 13:32:14 +00:00
|
|
|
{
|
|
|
|
int Mask = 0;
|
2022-06-30 22:36:32 +00:00
|
|
|
static const auto s_aModifierKeys = {
|
2022-02-06 22:30:19 +00:00
|
|
|
KEY_LSHIFT,
|
|
|
|
KEY_RSHIFT,
|
|
|
|
KEY_LCTRL,
|
|
|
|
KEY_RCTRL,
|
|
|
|
KEY_LALT,
|
|
|
|
KEY_RALT,
|
|
|
|
KEY_LGUI,
|
|
|
|
KEY_RGUI,
|
|
|
|
};
|
2022-06-30 22:36:32 +00:00
|
|
|
for(const auto Key : s_aModifierKeys)
|
2022-02-06 22:30:19 +00:00
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
if(pInput->KeyIsPressed(Key))
|
2022-02-06 22:30:19 +00:00
|
|
|
{
|
|
|
|
Mask |= GetModifierMaskOfKey(Key);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-28 13:32:14 +00:00
|
|
|
return Mask;
|
|
|
|
}
|
|
|
|
|
|
|
|
int CBinds::GetModifierMaskOfKey(int Key)
|
|
|
|
{
|
|
|
|
switch(Key)
|
|
|
|
{
|
|
|
|
case KEY_LSHIFT:
|
|
|
|
case KEY_RSHIFT:
|
|
|
|
return 1 << CBinds::MODIFIER_SHIFT;
|
|
|
|
case KEY_LCTRL:
|
|
|
|
case KEY_RCTRL:
|
|
|
|
return 1 << CBinds::MODIFIER_CTRL;
|
|
|
|
case KEY_LALT:
|
2021-12-18 11:23:20 +00:00
|
|
|
case KEY_RALT:
|
2019-04-28 13:32:14 +00:00
|
|
|
return 1 << CBinds::MODIFIER_ALT;
|
2021-12-18 11:23:20 +00:00
|
|
|
case KEY_LGUI:
|
|
|
|
case KEY_RGUI:
|
|
|
|
return 1 << CBinds::MODIFIER_GUI;
|
2019-04-28 13:32:14 +00:00
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
bool CBinds::OnInput(IInput::CEvent e)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2019-04-28 13:32:14 +00:00
|
|
|
// don't handle invalid events
|
|
|
|
if(e.m_Key <= 0 || e.m_Key >= KEY_LAST)
|
2008-08-27 15:48:50 +00:00
|
|
|
return false;
|
|
|
|
|
2019-04-28 13:32:14 +00:00
|
|
|
int Mask = GetModifierMask(Input());
|
|
|
|
int KeyModifierMask = GetModifierMaskOfKey(e.m_Key);
|
|
|
|
Mask &= ~KeyModifierMask;
|
|
|
|
|
2020-10-03 07:57:20 +00:00
|
|
|
bool ret = false;
|
2022-04-28 06:45:25 +00:00
|
|
|
if(m_aapKeyBindings[Mask][e.m_Key])
|
2019-04-28 13:32:14 +00:00
|
|
|
{
|
2022-04-28 06:45:25 +00:00
|
|
|
if(e.m_Flags & IInput::FLAG_PRESS)
|
|
|
|
Console()->ExecuteLineStroked(1, m_aapKeyBindings[Mask][e.m_Key]);
|
|
|
|
if(e.m_Flags & IInput::FLAG_RELEASE)
|
|
|
|
Console()->ExecuteLineStroked(0, m_aapKeyBindings[Mask][e.m_Key]);
|
|
|
|
ret = true;
|
2019-04-28 13:32:14 +00:00
|
|
|
}
|
2019-05-10 23:38:15 +00:00
|
|
|
|
2020-10-30 22:23:07 +00:00
|
|
|
if(m_aapKeyBindings[0][e.m_Key] && !ret)
|
2020-10-03 07:57:20 +00:00
|
|
|
{
|
2020-10-04 10:14:16 +00:00
|
|
|
// When ctrl+shift are pressed (ctrl+shift binds and also the hard-coded ctrl+shift+d, ctrl+shift+g, ctrl+shift+e), ignore other +xxx binds
|
2021-12-19 22:42:19 +00:00
|
|
|
if(e.m_Flags & IInput::FLAG_PRESS && Mask != ((1 << MODIFIER_CTRL) | (1 << MODIFIER_SHIFT)) && Mask != ((1 << MODIFIER_GUI) | (1 << MODIFIER_SHIFT)))
|
2021-12-18 11:23:20 +00:00
|
|
|
Console()->ExecuteLineStroked(1, m_aapKeyBindings[0][e.m_Key]);
|
2020-10-03 07:57:20 +00:00
|
|
|
if(e.m_Flags & IInput::FLAG_RELEASE)
|
|
|
|
Console()->ExecuteLineStroked(0, m_aapKeyBindings[0][e.m_Key]);
|
|
|
|
ret = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CBinds::UnbindAll()
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2020-10-26 14:14:07 +00:00
|
|
|
for(auto &apKeyBinding : m_aapKeyBindings)
|
2017-04-11 23:36:48 +00:00
|
|
|
{
|
2020-10-26 14:14:07 +00:00
|
|
|
for(auto &pKeyBinding : apKeyBinding)
|
2019-04-28 13:32:14 +00:00
|
|
|
{
|
2022-03-01 22:19:49 +00:00
|
|
|
free(pKeyBinding);
|
2020-10-26 14:14:07 +00:00
|
|
|
pKeyBinding = 0;
|
2019-04-28 13:32:14 +00:00
|
|
|
}
|
2017-04-11 23:36:48 +00:00
|
|
|
}
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
|
2022-02-06 21:57:04 +00:00
|
|
|
const char *CBinds::Get(int KeyID, int ModifierCombination)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2022-02-06 21:57:04 +00:00
|
|
|
if(KeyID > 0 && KeyID < KEY_LAST && m_aapKeyBindings[ModifierCombination][KeyID])
|
|
|
|
return m_aapKeyBindings[ModifierCombination][KeyID];
|
2008-08-27 15:48:50 +00:00
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
2019-04-28 13:32:14 +00:00
|
|
|
void CBinds::GetKey(const char *pBindStr, char *aBuf, unsigned BufSize)
|
2008-09-25 14:04:02 +00:00
|
|
|
{
|
2019-04-28 13:32:14 +00:00
|
|
|
aBuf[0] = 0;
|
2020-09-04 20:48:39 +00:00
|
|
|
for(int Mod = 0; Mod < MODIFIER_COMBINATION_COUNT; Mod++)
|
2008-09-25 14:04:02 +00:00
|
|
|
{
|
2019-04-28 13:32:14 +00:00
|
|
|
for(int KeyId = 0; KeyId < KEY_LAST; KeyId++)
|
|
|
|
{
|
|
|
|
const char *pBind = Get(KeyId, Mod);
|
|
|
|
if(!pBind[0])
|
|
|
|
continue;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2020-09-04 20:48:39 +00:00
|
|
|
if(str_comp(pBind, pBindStr) == 0)
|
|
|
|
{
|
2019-04-28 13:32:14 +00:00
|
|
|
if(Mod)
|
|
|
|
str_format(aBuf, BufSize, "%s+%s", GetModifierName(Mod), Input()->KeyName(KeyId));
|
|
|
|
else
|
|
|
|
str_format(aBuf, BufSize, "%s", Input()->KeyName(KeyId));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2008-09-25 14:04:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CBinds::SetDefaults()
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
|
|
|
// set default key bindings
|
2010-05-29 07:25:38 +00:00
|
|
|
UnbindAll();
|
|
|
|
Bind(KEY_F1, "toggle_local_console");
|
|
|
|
Bind(KEY_F2, "toggle_remote_console");
|
|
|
|
Bind(KEY_TAB, "+scoreboard");
|
2017-07-21 17:53:49 +00:00
|
|
|
Bind(KEY_EQUALS, "+statboard");
|
2010-05-29 07:25:38 +00:00
|
|
|
Bind(KEY_F10, "screenshot");
|
|
|
|
|
2017-07-21 17:32:32 +00:00
|
|
|
Bind(KEY_A, "+left");
|
|
|
|
Bind(KEY_D, "+right");
|
2010-05-29 07:25:38 +00:00
|
|
|
|
|
|
|
Bind(KEY_SPACE, "+jump");
|
|
|
|
Bind(KEY_MOUSE_1, "+fire");
|
|
|
|
Bind(KEY_MOUSE_2, "+hook");
|
|
|
|
Bind(KEY_LSHIFT, "+emote");
|
2015-08-05 13:34:08 +00:00
|
|
|
Bind(KEY_RETURN, "+show_chat; chat all");
|
2011-04-13 15:39:26 +00:00
|
|
|
Bind(KEY_RIGHT, "spectate_next");
|
|
|
|
Bind(KEY_LEFT, "spectate_previous");
|
2014-06-16 12:44:00 +00:00
|
|
|
Bind(KEY_RSHIFT, "+spectate");
|
2010-05-29 07:25:38 +00:00
|
|
|
|
2017-07-21 17:32:32 +00:00
|
|
|
Bind(KEY_1, "+weapon1");
|
|
|
|
Bind(KEY_2, "+weapon2");
|
|
|
|
Bind(KEY_3, "+weapon3");
|
|
|
|
Bind(KEY_4, "+weapon4");
|
|
|
|
Bind(KEY_5, "+weapon5");
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
Bind(KEY_MOUSE_WHEEL_UP, "+prevweapon");
|
|
|
|
Bind(KEY_MOUSE_WHEEL_DOWN, "+nextweapon");
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2017-07-21 17:32:32 +00:00
|
|
|
Bind(KEY_T, "+show_chat; chat all");
|
|
|
|
Bind(KEY_Y, "+show_chat; chat team");
|
|
|
|
Bind(KEY_U, "+show_chat");
|
|
|
|
Bind(KEY_I, "+show_chat; chat all /c ");
|
2008-09-25 14:04:02 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
Bind(KEY_F3, "vote yes");
|
2011-04-13 18:37:12 +00:00
|
|
|
Bind(KEY_F4, "vote no");
|
2011-02-16 09:20:27 +00:00
|
|
|
|
2017-07-21 17:32:32 +00:00
|
|
|
Bind(KEY_K, "kill");
|
|
|
|
Bind(KEY_Q, "say /pause");
|
|
|
|
Bind(KEY_P, "say /pause");
|
2013-08-18 01:33:55 +00:00
|
|
|
|
2011-04-09 06:41:31 +00:00
|
|
|
// DDRace
|
2020-09-05 21:15:14 +00:00
|
|
|
g_Config.m_ClDDRaceBindsSet = 0;
|
|
|
|
SetDDRaceBinds(false);
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CBinds::OnConsoleInit()
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2008-08-30 21:01:57 +00:00
|
|
|
// bindings
|
2021-01-10 12:47:07 +00:00
|
|
|
IConfigManager *pConfigManager = Kernel()->RequestInterface<IConfigManager>();
|
|
|
|
if(pConfigManager)
|
|
|
|
pConfigManager->RegisterCallback(ConfigSaveCallback, this);
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2015-12-28 15:14:52 +00:00
|
|
|
Console()->Register("bind", "s[key] r[command]", CFGFLAG_CLIENT, ConBind, this, "Bind key to execute the command");
|
2017-03-06 17:06:55 +00:00
|
|
|
Console()->Register("dump_binds", "?s[key]", CFGFLAG_CLIENT, ConDumpBinds, this, "Print command executed by this keybindind or all binds");
|
2015-12-28 15:14:52 +00:00
|
|
|
Console()->Register("unbind", "s[key]", CFGFLAG_CLIENT, ConUnbind, this, "Unbind key");
|
2011-08-13 00:11:06 +00:00
|
|
|
Console()->Register("unbindall", "", CFGFLAG_CLIENT, ConUnbindAll, this, "Unbind all keys");
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2008-08-30 21:01:57 +00:00
|
|
|
// default bindings
|
2010-05-29 07:25:38 +00:00
|
|
|
SetDefaults();
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
|
2011-08-13 00:11:06 +00:00
|
|
|
void CBinds::ConBind(IConsole::IResult *pResult, void *pUserData)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
CBinds *pBinds = (CBinds *)pUserData;
|
2019-04-28 13:32:14 +00:00
|
|
|
const char *pBindStr = pResult->GetString(0);
|
|
|
|
int Modifier;
|
|
|
|
int KeyID = pBinds->GetBindSlot(pBindStr, &Modifier);
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2019-04-28 13:32:14 +00:00
|
|
|
if(!KeyID)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2010-08-17 22:06:00 +00:00
|
|
|
char aBuf[256];
|
2019-04-28 13:32:14 +00:00
|
|
|
str_format(aBuf, sizeof(aBuf), "key %s not found", pBindStr);
|
2021-03-08 03:41:27 +00:00
|
|
|
pBinds->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "binds", aBuf, gs_BindPrintColor);
|
2008-08-27 15:48:50 +00:00
|
|
|
return;
|
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2019-04-28 13:32:14 +00:00
|
|
|
pBinds->Bind(KeyID, pResult->GetString(1), false, Modifier);
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
|
2017-03-06 17:06:55 +00:00
|
|
|
void CBinds::ConDumpBinds(IConsole::IResult *pResult, void *pUserData)
|
2017-01-28 15:29:03 +00:00
|
|
|
{
|
|
|
|
CBinds *pBinds = (CBinds *)pUserData;
|
2017-03-06 14:31:19 +00:00
|
|
|
if(pResult->NumArguments() == 1)
|
2017-01-28 17:34:24 +00:00
|
|
|
{
|
2017-01-28 15:29:03 +00:00
|
|
|
char aBuf[256];
|
2017-03-06 14:31:19 +00:00
|
|
|
const char *pKeyName = pResult->GetString(0);
|
2017-01-28 16:02:39 +00:00
|
|
|
|
2019-04-28 13:32:14 +00:00
|
|
|
int Modifier;
|
|
|
|
int id = pBinds->GetBindSlot(pKeyName, &Modifier);
|
2020-09-26 19:41:58 +00:00
|
|
|
if(!id)
|
2017-01-28 16:02:39 +00:00
|
|
|
{
|
2017-03-06 17:06:55 +00:00
|
|
|
str_format(aBuf, sizeof(aBuf), "key '%s' not found", pKeyName);
|
2021-03-08 03:41:27 +00:00
|
|
|
pBinds->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "binds", aBuf, gs_BindPrintColor);
|
2017-01-28 16:02:39 +00:00
|
|
|
}
|
2017-03-06 14:31:19 +00:00
|
|
|
else
|
2017-01-28 17:34:24 +00:00
|
|
|
{
|
2020-09-26 19:41:58 +00:00
|
|
|
if(!pBinds->m_aapKeyBindings[Modifier][id])
|
2017-03-06 14:31:19 +00:00
|
|
|
str_format(aBuf, sizeof(aBuf), "%s (%d) is not bound", pKeyName, id);
|
|
|
|
else
|
2019-04-28 13:32:14 +00:00
|
|
|
str_format(aBuf, sizeof(aBuf), "%s (%d) = %s", pKeyName, id, pBinds->m_aapKeyBindings[Modifier][id]);
|
2017-03-06 14:31:19 +00:00
|
|
|
|
2021-03-08 03:41:27 +00:00
|
|
|
pBinds->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "binds", aBuf, gs_BindPrintColor);
|
2017-03-06 14:31:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(pResult->NumArguments() == 0)
|
|
|
|
{
|
|
|
|
char aBuf[1024];
|
2020-09-04 20:48:39 +00:00
|
|
|
for(int i = 0; i < MODIFIER_COMBINATION_COUNT; i++)
|
2017-03-06 14:31:19 +00:00
|
|
|
{
|
2019-04-28 13:32:14 +00:00
|
|
|
for(int j = 0; j < KEY_LAST; j++)
|
|
|
|
{
|
|
|
|
if(!pBinds->m_aapKeyBindings[i][j])
|
|
|
|
continue;
|
2020-08-30 00:01:56 +00:00
|
|
|
|
2020-09-04 20:48:39 +00:00
|
|
|
str_format(aBuf, sizeof(aBuf), "%s%s (%d) = %s", GetKeyBindModifiersName(i), pBinds->Input()->KeyName(j), j, pBinds->m_aapKeyBindings[i][j]);
|
2021-03-08 03:41:27 +00:00
|
|
|
pBinds->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "binds", aBuf, gs_BindPrintColor);
|
2019-04-28 13:32:14 +00:00
|
|
|
}
|
2017-01-28 16:02:39 +00:00
|
|
|
}
|
2017-01-28 15:29:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-08-13 00:11:06 +00:00
|
|
|
void CBinds::ConUnbind(IConsole::IResult *pResult, void *pUserData)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
CBinds *pBinds = (CBinds *)pUserData;
|
|
|
|
const char *pKeyName = pResult->GetString(0);
|
2019-04-28 13:32:14 +00:00
|
|
|
int Modifier;
|
|
|
|
int id = pBinds->GetBindSlot(pKeyName, &Modifier);
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2008-08-27 15:48:50 +00:00
|
|
|
if(!id)
|
|
|
|
{
|
2010-08-17 22:06:00 +00:00
|
|
|
char aBuf[256];
|
|
|
|
str_format(aBuf, sizeof(aBuf), "key %s not found", pKeyName);
|
2021-03-08 03:41:27 +00:00
|
|
|
pBinds->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "binds", aBuf, gs_BindPrintColor);
|
2008-08-27 15:48:50 +00:00
|
|
|
return;
|
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2019-04-28 13:32:14 +00:00
|
|
|
pBinds->Bind(id, "", false, Modifier);
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
|
2011-08-13 00:11:06 +00:00
|
|
|
void CBinds::ConUnbindAll(IConsole::IResult *pResult, void *pUserData)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
CBinds *pBinds = (CBinds *)pUserData;
|
|
|
|
pBinds->UnbindAll();
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
|
2011-02-12 10:40:36 +00:00
|
|
|
int CBinds::GetKeyID(const char *pKeyName)
|
2008-08-30 21:01:57 +00:00
|
|
|
{
|
|
|
|
// check for numeric
|
2010-05-29 07:25:38 +00:00
|
|
|
if(pKeyName[0] == '&')
|
2008-08-30 21:01:57 +00:00
|
|
|
{
|
2020-09-26 19:41:58 +00:00
|
|
|
int i = str_toint(pKeyName + 1);
|
2008-08-30 21:01:57 +00:00
|
|
|
if(i > 0 && i < KEY_LAST)
|
|
|
|
return i; // numeric
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2008-08-30 21:01:57 +00:00
|
|
|
// search for key
|
|
|
|
for(int i = 0; i < KEY_LAST; i++)
|
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(str_comp(pKeyName, Input()->KeyName(i)) == 0)
|
2008-08-30 21:01:57 +00:00
|
|
|
return i;
|
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2008-08-30 21:01:57 +00:00
|
|
|
return 0;
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
|
2022-02-06 21:57:04 +00:00
|
|
|
int CBinds::GetBindSlot(const char *pBindString, int *pModifierCombination)
|
2019-04-28 13:32:14 +00:00
|
|
|
{
|
2022-02-06 21:57:04 +00:00
|
|
|
*pModifierCombination = MODIFIER_NONE;
|
2020-09-04 20:48:39 +00:00
|
|
|
char aMod[32];
|
|
|
|
aMod[0] = '\0';
|
2019-04-28 13:32:14 +00:00
|
|
|
const char *pKey = str_next_token(pBindString, "+", aMod, sizeof(aMod));
|
2020-08-30 00:01:56 +00:00
|
|
|
while(aMod[0] && *(pKey))
|
2019-04-28 13:32:14 +00:00
|
|
|
{
|
2020-09-26 19:41:58 +00:00
|
|
|
if(!str_comp(aMod, "shift"))
|
2022-02-06 21:57:04 +00:00
|
|
|
*pModifierCombination |= (1 << MODIFIER_SHIFT);
|
2020-09-26 19:41:58 +00:00
|
|
|
else if(!str_comp(aMod, "ctrl"))
|
2022-02-06 21:57:04 +00:00
|
|
|
*pModifierCombination |= (1 << MODIFIER_CTRL);
|
2020-09-26 19:41:58 +00:00
|
|
|
else if(!str_comp(aMod, "alt"))
|
2022-02-06 21:57:04 +00:00
|
|
|
*pModifierCombination |= (1 << MODIFIER_ALT);
|
2021-12-18 11:23:20 +00:00
|
|
|
else if(!str_comp(aMod, "gui"))
|
2022-02-06 21:57:04 +00:00
|
|
|
*pModifierCombination |= (1 << MODIFIER_GUI);
|
2019-04-28 13:32:14 +00:00
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
|
2020-09-26 19:41:58 +00:00
|
|
|
if(str_find(pKey + 1, "+"))
|
2020-08-30 00:01:56 +00:00
|
|
|
pKey = str_next_token(pKey + 1, "+", aMod, sizeof(aMod));
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
2022-02-06 21:57:04 +00:00
|
|
|
return GetKeyID(*pModifierCombination == MODIFIER_NONE ? aMod : pKey + 1);
|
2019-04-28 13:32:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const char *CBinds::GetModifierName(int Modifier)
|
|
|
|
{
|
|
|
|
switch(Modifier)
|
|
|
|
{
|
|
|
|
case MODIFIER_SHIFT:
|
|
|
|
return "shift";
|
|
|
|
case MODIFIER_CTRL:
|
|
|
|
return "ctrl";
|
|
|
|
case MODIFIER_ALT:
|
|
|
|
return "alt";
|
2021-12-18 11:23:20 +00:00
|
|
|
case MODIFIER_GUI:
|
|
|
|
return "gui";
|
2019-04-28 13:32:14 +00:00
|
|
|
case MODIFIER_NONE:
|
|
|
|
default:
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-06 21:57:04 +00:00
|
|
|
const char *CBinds::GetKeyBindModifiersName(int ModifierCombination)
|
2020-09-04 20:48:39 +00:00
|
|
|
{
|
|
|
|
static char aModifier[256];
|
|
|
|
aModifier[0] = '\0';
|
2020-09-26 19:41:58 +00:00
|
|
|
for(int k = 1; k < MODIFIER_COUNT; k++)
|
2020-09-04 20:48:39 +00:00
|
|
|
{
|
2022-02-06 21:57:04 +00:00
|
|
|
if(ModifierCombination & (1 << k))
|
2020-09-04 20:48:39 +00:00
|
|
|
{
|
|
|
|
str_append(aModifier, GetModifierName(k), sizeof(aModifier));
|
|
|
|
str_append(aModifier, "+", sizeof(aModifier));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return aModifier;
|
|
|
|
}
|
|
|
|
|
2021-01-10 12:47:07 +00:00
|
|
|
void CBinds::ConfigSaveCallback(IConfigManager *pConfigManager, void *pUserData)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
CBinds *pSelf = (CBinds *)pUserData;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2021-01-10 12:47:07 +00:00
|
|
|
pConfigManager->WriteLine("unbindall");
|
2020-09-04 20:48:39 +00:00
|
|
|
for(int i = 0; i < MODIFIER_COMBINATION_COUNT; i++)
|
2008-08-27 15:48:50 +00:00
|
|
|
{
|
2019-04-28 13:32:14 +00:00
|
|
|
for(int j = 0; j < KEY_LAST; j++)
|
|
|
|
{
|
|
|
|
if(!pSelf->m_aapKeyBindings[i][j])
|
|
|
|
continue;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2022-02-06 10:57:40 +00:00
|
|
|
// worst case the str_escape can double the string length
|
|
|
|
int Size = str_length(pSelf->m_aapKeyBindings[i][j]) * 2 + 30;
|
|
|
|
char *pBuffer = (char *)malloc(Size);
|
|
|
|
char *pEnd = pBuffer + Size;
|
|
|
|
|
|
|
|
str_format(pBuffer, Size, "bind %s%s \"", GetKeyBindModifiersName(i), pSelf->Input()->KeyName(j));
|
2019-04-28 13:32:14 +00:00
|
|
|
// process the string. we need to escape some characters
|
2022-02-06 10:57:40 +00:00
|
|
|
char *pDst = pBuffer + str_length(pBuffer);
|
2019-04-28 13:32:14 +00:00
|
|
|
str_escape(&pDst, pSelf->m_aapKeyBindings[i][j], pEnd);
|
2022-02-06 10:57:40 +00:00
|
|
|
str_append(pBuffer, "\"", Size);
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2022-02-06 10:57:40 +00:00
|
|
|
pConfigManager->WriteLine(pBuffer);
|
|
|
|
free(pBuffer);
|
2019-04-28 13:32:14 +00:00
|
|
|
}
|
2008-08-27 15:48:50 +00:00
|
|
|
}
|
|
|
|
}
|
2011-04-17 17:14:49 +00:00
|
|
|
|
|
|
|
// DDRace
|
|
|
|
|
|
|
|
void CBinds::SetDDRaceBinds(bool FreeOnly)
|
|
|
|
{
|
2020-09-05 21:15:14 +00:00
|
|
|
if(g_Config.m_ClDDRaceBindsSet < 1)
|
|
|
|
{
|
|
|
|
Bind(KEY_KP_PLUS, "zoom+", FreeOnly);
|
|
|
|
Bind(KEY_KP_MINUS, "zoom-", FreeOnly);
|
|
|
|
Bind(KEY_KP_MULTIPLY, "zoom", FreeOnly);
|
|
|
|
Bind(KEY_PAUSE, "say /pause", FreeOnly);
|
|
|
|
Bind(KEY_UP, "+jump", FreeOnly);
|
|
|
|
Bind(KEY_LEFT, "+left", FreeOnly);
|
|
|
|
Bind(KEY_RIGHT, "+right", FreeOnly);
|
|
|
|
Bind(KEY_LEFTBRACKET, "+prevweapon", FreeOnly);
|
|
|
|
Bind(KEY_RIGHTBRACKET, "+nextweapon", FreeOnly);
|
|
|
|
Bind(KEY_C, "say /rank", FreeOnly);
|
|
|
|
Bind(KEY_V, "say /info", FreeOnly);
|
|
|
|
Bind(KEY_B, "say /top5", FreeOnly);
|
|
|
|
Bind(KEY_S, "+showhookcoll", FreeOnly);
|
|
|
|
Bind(KEY_X, "toggle cl_dummy 0 1", FreeOnly);
|
2020-12-18 18:13:07 +00:00
|
|
|
Bind(KEY_H, "toggle cl_dummy_hammer 0 1", FreeOnly);
|
|
|
|
Bind(KEY_SLASH, "+show_chat; chat all /", FreeOnly);
|
2020-09-05 21:15:14 +00:00
|
|
|
Bind(KEY_PAGEUP, "toggle cl_overlay_entities 0 100", FreeOnly);
|
|
|
|
Bind(KEY_KP_0, "say /emote normal 999999", FreeOnly);
|
|
|
|
Bind(KEY_KP_1, "say /emote happy 999999", FreeOnly);
|
|
|
|
Bind(KEY_KP_2, "say /emote angry 999999", FreeOnly);
|
|
|
|
Bind(KEY_KP_3, "say /emote pain 999999", FreeOnly);
|
|
|
|
Bind(KEY_KP_4, "say /emote surprise 999999", FreeOnly);
|
|
|
|
Bind(KEY_KP_5, "say /emote blink 999999", FreeOnly);
|
|
|
|
Bind(KEY_MOUSE_3, "+spectate", FreeOnly);
|
|
|
|
Bind(KEY_MINUS, "spectate_previous", FreeOnly);
|
|
|
|
Bind(KEY_EQUALS, "spectate_next", FreeOnly);
|
|
|
|
}
|
|
|
|
|
2020-09-07 13:40:20 +00:00
|
|
|
g_Config.m_ClDDRaceBindsSet = 1;
|
2013-08-18 01:33:55 +00:00
|
|
|
}
|