ddnet/src/game/client/components/binds.cpp

413 lines
10 KiB
C++
Raw Normal View History

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. */
2010-05-29 07:25:38 +00:00
#include <engine/config.h>
#include <engine/shared/config.h>
#include "binds.h"
2010-05-29 07:25:38 +00:00
bool CBinds::CBindsSpecial::OnInput(IInput::CEvent Event)
{
// don't handle invalid events and keys that arn't set to anything
2017-04-11 23:36:48 +00:00
if(((Event.m_Key >= KEY_F1 && Event.m_Key <= KEY_F12) || (Event.m_Key >= KEY_F13 && Event.m_Key <= KEY_F24)) && m_pBinds->m_apKeyBindings[Event.m_Key])
{
2010-05-29 07:25:38 +00:00
int Stroke = 0;
if(Event.m_Flags&IInput::FLAG_PRESS)
Stroke = 1;
2017-04-11 23:36:48 +00:00
m_pBinds->GetConsole()->ExecuteLineStroked(Stroke, m_pBinds->m_apKeyBindings[Event.m_Key]);
return true;
}
return false;
}
2010-05-29 07:25:38 +00:00
CBinds::CBinds()
{
2017-04-11 23:36:48 +00:00
mem_zero(m_apKeyBindings, sizeof(m_apKeyBindings));
2010-05-29 07:25:38 +00:00
m_SpecialBinds.m_pBinds = this;
}
2017-04-11 23:36:48 +00:00
CBinds::~CBinds()
{
for(int i = 0; i < KEY_LAST; i++)
if(m_apKeyBindings[i])
mem_free(m_apKeyBindings[i]);
}
void CBinds::Bind(int KeyID, const char *pStr)
{
if(KeyID < 0 || KeyID >= KEY_LAST)
return;
2017-04-11 23:36:48 +00:00
if(m_apKeyBindings[KeyID])
mem_free(m_apKeyBindings[KeyID]);
char aBuf[256];
2017-04-11 23:36:48 +00:00
if(!pStr[0])
{
str_format(aBuf, sizeof(aBuf), "unbound %s (%d)", Input()->KeyName(KeyID), KeyID);
2017-04-11 23:36:48 +00:00
}
else
2017-04-11 23:36:48 +00:00
{
int size = str_length(pStr) + 1;
m_apKeyBindings[KeyID] = (char *)mem_alloc(size, 1);
str_copy(m_apKeyBindings[KeyID], pStr, size);
str_format(aBuf, sizeof(aBuf), "bound %s (%d) = %s", Input()->KeyName(KeyID), KeyID, m_apKeyBindings[KeyID]);
}
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "binds", aBuf);
}
2010-05-29 07:25:38 +00:00
bool CBinds::OnInput(IInput::CEvent e)
{
// don't handle invalid events and keys that arn't set to anything
2017-04-11 23:36:48 +00:00
if(e.m_Key <= 0 || e.m_Key >= KEY_LAST || !m_apKeyBindings[e.m_Key])
return false;
2010-05-29 07:25:38 +00:00
if(e.m_Flags&IInput::FLAG_PRESS)
2017-04-11 23:36:48 +00:00
Console()->ExecuteLineStroked(1, m_apKeyBindings[e.m_Key]);
if(e.m_Flags&IInput::FLAG_RELEASE)
2017-04-11 23:36:48 +00:00
Console()->ExecuteLineStroked(0, m_apKeyBindings[e.m_Key]);
return true;
}
2010-05-29 07:25:38 +00:00
void CBinds::UnbindAll()
{
for(int i = 0; i < KEY_LAST; i++)
2017-04-11 23:36:48 +00:00
{
if(m_apKeyBindings)
mem_free(m_apKeyBindings[i]);
m_apKeyBindings[i] = 0;
}
}
const char *CBinds::Get(int KeyID)
{
if(KeyID > 0 && KeyID < KEY_LAST)
2017-04-11 23:36:48 +00:00
return m_apKeyBindings[KeyID];
return "";
}
2010-05-29 07:25:38 +00:00
const char *CBinds::GetKey(const char *pBindStr)
{
2010-05-29 07:25:38 +00:00
for(int KeyId = 0; KeyId < KEY_LAST; KeyId++)
{
2010-05-29 07:25:38 +00:00
const char *pBind = Get(KeyId);
if(!pBind[0])
continue;
2010-05-29 07:25:38 +00:00
if(str_comp(pBind, pBindStr) == 0)
return Input()->KeyName(KeyId);
}
return "";
}
2010-05-29 07:25:38 +00:00
void CBinds::SetDefaults()
{
// 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");
2016-04-30 21:39:42 +00:00
Bind(KEY_BACKQUOTE, "+statboard");
2010-05-29 07:25:38 +00:00
Bind(KEY_F10, "screenshot");
Bind('a', "+left");
Bind('d', "+right");
Bind(KEY_SPACE, "+jump");
Bind(KEY_MOUSE_1, "+fire");
Bind(KEY_MOUSE_2, "+hook");
Bind(KEY_LSHIFT, "+emote");
2014-06-16 11:29:18 +00:00
#if defined(__ANDROID__)
Bind(KEY_RCTRL, "+fire");
Bind(KEY_RETURN, "+hook");
Bind(KEY_RIGHT, "+right");
Bind(KEY_LEFT, "+left");
Bind(KEY_UP, "+jump");
Bind(KEY_DOWN, "+hook");
Bind(KEY_PAGEUP, "+prevweapon");
Bind(KEY_PAGEDOWN, "+nextweapon");
2014-06-16 12:44:00 +00:00
Bind(KEY_F5, "spectate_previous");
Bind(KEY_F6, "spectate_next");
2014-06-16 11:29:18 +00:00
#else
Bind(KEY_RETURN, "+show_chat; chat all");
Bind(KEY_RIGHT, "spectate_next");
Bind(KEY_LEFT, "spectate_previous");
2014-06-16 12:44:00 +00:00
Bind(KEY_RSHIFT, "+spectate");
2014-06-16 11:29:18 +00:00
#endif
2010-05-29 07:25:38 +00:00
Bind('1', "+weapon1");
Bind('2', "+weapon2");
Bind('3', "+weapon3");
Bind('4', "+weapon4");
Bind('5', "+weapon5");
2010-05-29 07:25:38 +00:00
Bind(KEY_MOUSE_WHEEL_UP, "+prevweapon");
Bind(KEY_MOUSE_WHEEL_DOWN, "+nextweapon");
2015-07-07 10:40:22 +00:00
Bind('t', "+show_chat; chat all");
Bind('y', "+show_chat; chat team");
Bind('z', "+show_chat; chat team"); // For German keyboards
Bind('u', "+show_chat");
Bind('i', "+show_chat; chat all /c ");
2010-05-29 07:25:38 +00:00
Bind(KEY_F3, "vote yes");
Bind(KEY_F4, "vote no");
2013-08-18 01:33:55 +00:00
Bind('k', "kill");
2015-07-07 10:40:22 +00:00
Bind('q', "say /pause");
2013-08-18 01:33:55 +00:00
Bind('p', "say /pause");
// DDRace
2011-04-17 17:14:49 +00:00
if(g_Config.m_ClDDRaceBinds)
SetDDRaceBinds(false);
}
2010-05-29 07:25:38 +00:00
void CBinds::OnConsoleInit()
{
// bindings
2010-05-29 07:25:38 +00:00
IConfig *pConfig = Kernel()->RequestInterface<IConfig>();
if(pConfig)
pConfig->RegisterCallback(ConfigSaveCallback, this);
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");
Console()->Register("unbind", "s[key]", CFGFLAG_CLIENT, ConUnbind, this, "Unbind key");
Console()->Register("unbindall", "", CFGFLAG_CLIENT, ConUnbindAll, this, "Unbind all keys");
// default bindings
2010-05-29 07:25:38 +00:00
SetDefaults();
}
void CBinds::ConBind(IConsole::IResult *pResult, void *pUserData)
{
2010-05-29 07:25:38 +00:00
CBinds *pBinds = (CBinds *)pUserData;
const char *pKeyName = pResult->GetString(0);
int id = pBinds->GetKeyID(pKeyName);
if(!id)
{
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "key %s not found", pKeyName);
pBinds->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "binds", aBuf);
return;
}
2010-05-29 07:25:38 +00:00
pBinds->Bind(id, pResult->GetString(1));
}
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;
if(pResult->NumArguments() == 1)
2017-01-28 17:34:24 +00:00
{
2017-01-28 15:29:03 +00:00
char aBuf[256];
const char *pKeyName = pResult->GetString(0);
2017-01-28 16:02:39 +00:00
int id = pBinds->GetKeyID(pKeyName);
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);
pBinds->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "binds", aBuf);
2017-01-28 16:02:39 +00:00
}
else
2017-01-28 17:34:24 +00:00
{
2017-04-11 23:36:48 +00:00
if (!pBinds->m_apKeyBindings[id])
str_format(aBuf, sizeof(aBuf), "%s (%d) is not bound", pKeyName, id);
else
2017-04-11 23:36:48 +00:00
str_format(aBuf, sizeof(aBuf), "%s (%d) = %s", pKeyName, id, pBinds->m_apKeyBindings[id]);
pBinds->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "binds", aBuf);
}
}
else if(pResult->NumArguments() == 0)
{
char aBuf[1024];
for(int i = 0; i < KEY_LAST; i++)
{
2017-04-11 23:36:48 +00:00
if(!pBinds->m_apKeyBindings[i])
continue;
2017-04-11 23:36:48 +00:00
str_format(aBuf, sizeof(aBuf), "%s (%d) = %s", pBinds->Input()->KeyName(i), i, pBinds->m_apKeyBindings[i]);
pBinds->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "binds", aBuf);
2017-01-28 16:02:39 +00:00
}
2017-01-28 15:29:03 +00:00
}
}
void CBinds::ConUnbind(IConsole::IResult *pResult, void *pUserData)
{
2010-05-29 07:25:38 +00:00
CBinds *pBinds = (CBinds *)pUserData;
const char *pKeyName = pResult->GetString(0);
int id = pBinds->GetKeyID(pKeyName);
if(!id)
{
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "key %s not found", pKeyName);
pBinds->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "binds", aBuf);
return;
}
2010-05-29 07:25:38 +00:00
pBinds->Bind(id, "");
}
void CBinds::ConUnbindAll(IConsole::IResult *pResult, void *pUserData)
{
2010-05-29 07:25:38 +00:00
CBinds *pBinds = (CBinds *)pUserData;
pBinds->UnbindAll();
}
int CBinds::GetKeyID(const char *pKeyName)
{
// check for numeric
2010-05-29 07:25:38 +00:00
if(pKeyName[0] == '&')
{
2010-05-29 07:25:38 +00:00
int i = str_toint(pKeyName+1);
if(i > 0 && i < KEY_LAST)
return i; // numeric
}
// 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)
return i;
}
return 0;
}
2010-05-29 07:25:38 +00:00
void CBinds::ConfigSaveCallback(IConfig *pConfig, void *pUserData)
{
2010-05-29 07:25:38 +00:00
CBinds *pSelf = (CBinds *)pUserData;
2010-05-29 07:25:38 +00:00
char aBuffer[256];
char *pEnd = aBuffer+sizeof(aBuffer)-8;
pConfig->WriteLine("unbindall");
for(int i = 0; i < KEY_LAST; i++)
{
2017-04-11 23:36:48 +00:00
if(!pSelf->m_apKeyBindings[i])
continue;
2010-05-29 07:25:38 +00:00
str_format(aBuffer, sizeof(aBuffer), "bind %s ", pSelf->Input()->KeyName(i));
// process the string. we need to escape some characters
2017-04-11 23:36:48 +00:00
const char *pSrc = pSelf->m_apKeyBindings[i];
2010-05-29 07:25:38 +00:00
char *pDst = aBuffer + str_length(aBuffer);
*pDst++ = '"';
while(*pSrc && pDst < pEnd)
{
2010-05-29 07:25:38 +00:00
if(*pSrc == '"' || *pSrc == '\\') // escape \ and "
*pDst++ = '\\';
*pDst++ = *pSrc++;
}
2010-05-29 07:25:38 +00:00
*pDst++ = '"';
*pDst++ = 0;
2010-05-29 07:25:38 +00:00
pConfig->WriteLine(aBuffer);
}
}
2011-04-17 17:14:49 +00:00
// DDRace
void CBinds::SetDDRaceBinds(bool FreeOnly)
{
if(!FreeOnly)
{
Bind(KEY_KP_PLUS, "zoom+");
Bind(KEY_KP_MINUS, "zoom-");
Bind(KEY_KP_MULTIPLY, "zoom");
Bind(KEY_HOME, "kill");
Bind(KEY_PAUSE, "say /pause");
Bind(KEY_UP, "+jump");
Bind(KEY_LEFT, "+left");
Bind(KEY_RIGHT, "+right");
Bind('[', "+prevweapon");
Bind(']', "+nextweapon");
Bind('c', "say /rank");
Bind('v', "say /info");
Bind('b', "say /top5");
Bind('x', "emote 14");
Bind('h', "emote 2");
Bind('m', "emote 5");
2014-01-14 20:47:54 +00:00
Bind('s', "+showhookcoll");
Bind('x', "toggle cl_dummy 0 1");
2014-06-16 11:29:18 +00:00
#if !defined(__ANDROID__)
2014-07-25 23:12:32 +00:00
Bind(KEY_PAGEDOWN, "toggle cl_show_quads 0 1");
Bind(KEY_PAGEUP, "toggle cl_overlay_entities 0 100");
2014-06-16 11:29:18 +00:00
#endif
2015-08-24 20:46:28 +00:00
Bind(KEY_KP_0, "say /emote normal 999999");
Bind(KEY_KP_1, "say /emote happy 999999");
Bind(KEY_KP_2, "say /emote angry 999999");
Bind(KEY_KP_3, "say /emote pain 999999");
Bind(KEY_KP_4, "say /emote surprise 999999");
Bind(KEY_KP_5, "say /emote blink 999999");
2011-04-17 17:14:49 +00:00
Bind(KEY_MOUSE_3, "+spectate");
2016-03-26 00:09:34 +00:00
Bind(KEY_MINUS, "spectate_previous");
Bind(KEY_EQUALS, "spectate_next");
2011-04-17 17:14:49 +00:00
}
else
{
if(!Get(KEY_KP_PLUS)[0])
Bind(KEY_KP_PLUS, "zoom+");
if(!Get(KEY_KP_MINUS)[0])
Bind(KEY_KP_MINUS, "zoom-");
if(!Get(KEY_KP_MULTIPLY)[0])
Bind(KEY_KP_MULTIPLY, "zoom");
if(!Get(KEY_HOME)[0])
Bind(KEY_HOME, "kill");
if(!Get(KEY_PAUSE)[0])
Bind(KEY_PAUSE, "say /pause");
if(!Get(KEY_UP)[0])
Bind(KEY_UP, "+jump");
if(!Get(KEY_LEFT)[0])
Bind(KEY_LEFT, "+left");
if(!Get(KEY_RIGHT)[0])
Bind(KEY_RIGHT, "+right");
if(!Get('[')[0])
Bind('[', "+prevweapon");
if(!Get(']')[0])
Bind(']', "+nextweapon");
if(!Get('c')[0])
Bind('c', "say /rank");
if(!Get('v')[0])
Bind('v', "say /info");
if(!Get('b')[0])
Bind('b', "say /top5");
if(!Get('x')[0])
Bind('x', "emote 14");
if(!Get(KEY_KP_PLUS)[0])
Bind('h', "emote 2");
if(!Get('m')[0])
Bind('m', "emote 5");
if(!Get('s')[0])
Bind('s', "+showhookcoll");
if(!Get('x')[0])
Bind('x', "toggle cl_dummy 0 1");
2011-04-17 17:14:49 +00:00
if(!Get(KEY_PAGEDOWN)[0])
2016-03-26 00:09:34 +00:00
Bind(KEY_PAGEDOWN, "toggle cl_show_quads 0 1");
2011-04-17 17:14:49 +00:00
if(!Get(KEY_PAGEUP)[0])
2016-03-26 00:09:34 +00:00
Bind(KEY_PAGEUP, "toggle cl_overlay_entities 0 100");
2015-08-24 20:46:28 +00:00
if(!Get(KEY_KP_0)[0])
Bind(KEY_KP_0, "say /emote normal 999999");
if(!Get(KEY_KP_1)[0])
Bind(KEY_KP_1, "say /emote happy 999999");
if(!Get(KEY_KP_2)[0])
Bind(KEY_KP_2, "say /emote angry 999999");
if(!Get(KEY_KP_3)[0])
Bind(KEY_KP_3, "say /emote pain 999999");
if(!Get(KEY_KP_4)[0])
Bind(KEY_KP_4, "say /emote surprise 999999");
if(!Get(KEY_KP_5)[0])
Bind(KEY_KP_5, "say /emote blink 999999");
2011-04-17 17:14:49 +00:00
if(!Get(KEY_MOUSE_3)[0])
Bind(KEY_MOUSE_3, "+spectate");
if(!Get(KEY_MINUS)[0])
Bind(KEY_MINUS, "spectate_previous");
if(!Get(KEY_EQUALS)[0])
Bind(KEY_EQUALS, "spectate_next");
}
2014-01-14 20:47:54 +00:00
g_Config.m_ClDDRaceBindsSet = 1;
2013-08-18 01:33:55 +00:00
}