/* (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. */ #include #include #include "binds.h" bool CBinds::CBindsSpecial::OnInput(IInput::CEvent Event) { // don't handle invalid events and keys that arn't set to anything if(Event.m_Key >= KEY_F1 && Event.m_Key <= KEY_F15 && m_pBinds->m_aaKeyBindings[Event.m_Key][0] != 0) { int Stroke = 0; if(Event.m_Flags&IInput::FLAG_PRESS) Stroke = 1; m_pBinds->GetConsole()->ExecuteLineStroked(Stroke, m_pBinds->m_aaKeyBindings[Event.m_Key], IConsole::CONSOLELEVEL_CONFIG, -1); return true; } return false; } CBinds::CBinds() { mem_zero(m_aaKeyBindings, sizeof(m_aaKeyBindings)); m_SpecialBinds.m_pBinds = this; } void CBinds::Bind(int KeyID, const char *pStr) { if(KeyID < 0 || KeyID >= KEY_LAST) return; str_copy(m_aaKeyBindings[KeyID], pStr, sizeof(m_aaKeyBindings[KeyID])); char aBuf[256]; if(!m_aaKeyBindings[KeyID][0]) str_format(aBuf, sizeof(aBuf), "unbound %s (%d)", Input()->KeyName(KeyID), KeyID); else str_format(aBuf, sizeof(aBuf), "bound %s (%d) = %s", Input()->KeyName(KeyID), KeyID, m_aaKeyBindings[KeyID]); Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "binds", aBuf); } bool CBinds::OnInput(IInput::CEvent e) { // don't handle invalid events and keys that arn't set to anything if(e.m_Key <= 0 || e.m_Key >= KEY_LAST || m_aaKeyBindings[e.m_Key][0] == 0) return false; int Stroke = 0; if(e.m_Flags&IInput::FLAG_PRESS) Stroke = 1; Console()->ExecuteLineStroked(Stroke, m_aaKeyBindings[e.m_Key], IConsole::CONSOLELEVEL_CONFIG, -1); return true; } void CBinds::UnbindAll() { for(int i = 0; i < KEY_LAST; i++) m_aaKeyBindings[i][0] = 0; } const char *CBinds::Get(int KeyID) { if(KeyID > 0 && KeyID < KEY_LAST) return m_aaKeyBindings[KeyID]; return ""; } const char *CBinds::GetKey(const char *pBindStr) { for(int KeyId = 0; KeyId < KEY_LAST; KeyId++) { const char *pBind = Get(KeyId); if(!pBind[0]) continue; if(str_comp(pBind, pBindStr) == 0) return Input()->KeyName(KeyId); } return ""; } void CBinds::SetDefaults() { // set default key bindings UnbindAll(); Bind(KEY_F1, "toggle_local_console"); Bind(KEY_F2, "toggle_remote_console"); Bind(KEY_TAB, "+scoreboard"); Bind('u', "+show_chat"); 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"); Bind(KEY_RSHIFT, "+spectate"); Bind('1', "+weapon1"); Bind('2', "+weapon2"); Bind('3', "+weapon3"); Bind('4', "+weapon4"); Bind('5', "+weapon5"); Bind(KEY_MOUSE_WHEEL_UP, "+prevweapon"); Bind(KEY_MOUSE_WHEEL_DOWN, "+nextweapon"); Bind('t', "chat all"); Bind('y', "chat team"); Bind(KEY_F3, "vote yes"); Bind(KEY_F4, "vote no"); // DDRace if(!g_Config.m_ClDDRaceBinds) return; 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('z', "emote 12"); Bind('x', "emote 14"); Bind('h', "emote 2"); Bind('m', "emote 5"); Bind(KEY_PAGEDOWN, "cl_show_entities 0"); Bind(KEY_PAGEUP, "cl_show_entities 1"); Bind(KEY_KP0, "say /emote normal 999999"); Bind(KEY_KP1, "say /emote happy 999999"); Bind(KEY_KP2, "say /emote angry 999999"); Bind(KEY_KP3, "say /emote pain 999999"); Bind(KEY_KP4, "say /emote surprise 999999"); Bind(KEY_KP5, "say /emote blink 999999"); } void CBinds::OnConsoleInit() { // bindings IConfig *pConfig = Kernel()->RequestInterface(); if(pConfig) pConfig->RegisterCallback(ConfigSaveCallback, this); Console()->Register("bind", "sr", CFGFLAG_CLIENT, ConBind, this, "Bind key to execute the command", IConsole::CONSOLELEVEL_USER); Console()->Register("unbind", "s", CFGFLAG_CLIENT, ConUnbind, this, "Unbind key", IConsole::CONSOLELEVEL_USER); Console()->Register("unbindall", "", CFGFLAG_CLIENT, ConUnbindAll, this, "Unbind all keys", IConsole::CONSOLELEVEL_USER); Console()->Register("dump_binds", "", CFGFLAG_CLIENT, ConDumpBinds, this, "Dump binds", IConsole::CONSOLELEVEL_USER); // default bindings SetDefaults(); } void CBinds::ConBind(IConsole::IResult *pResult, void *pUserData, int ClientID) { 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()->PrintResponse(IConsole::OUTPUT_LEVEL_STANDARD, "binds", aBuf); return; } pBinds->Bind(id, pResult->GetString(1)); } void CBinds::ConUnbind(IConsole::IResult *pResult, void *pUserData, int ClientID) { 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()->PrintResponse(IConsole::OUTPUT_LEVEL_STANDARD, "binds", aBuf); return; } pBinds->Bind(id, ""); } void CBinds::ConUnbindAll(IConsole::IResult *pResult, void *pUserData, int ClientID) { CBinds *pBinds = (CBinds *)pUserData; pBinds->UnbindAll(); } void CBinds::ConDumpBinds(IConsole::IResult *pResult, void *pUserData, int ClientID) { CBinds *pBinds = (CBinds *)pUserData; char aBuf[1024]; for(int i = 0; i < KEY_LAST; i++) { if(pBinds->m_aaKeyBindings[i][0] == 0) continue; str_format(aBuf, sizeof(aBuf), "%s (%d) = %s", pBinds->Input()->KeyName(i), i, pBinds->m_aaKeyBindings[i]); pBinds->Console()->PrintResponse(IConsole::OUTPUT_LEVEL_STANDARD, "binds", aBuf); } } int CBinds::GetKeyID(const char *pKeyName) { // check for numeric if(pKeyName[0] == '&') { 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++) { if(str_comp(pKeyName, Input()->KeyName(i)) == 0) return i; } return 0; } void CBinds::ConfigSaveCallback(IConfig *pConfig, void *pUserData) { CBinds *pSelf = (CBinds *)pUserData; char aBuffer[256]; char *pEnd = aBuffer+sizeof(aBuffer)-8; pConfig->WriteLine("unbindall"); for(int i = 0; i < KEY_LAST; i++) { if(pSelf->m_aaKeyBindings[i][0] == 0) continue; str_format(aBuffer, sizeof(aBuffer), "bind %s ", pSelf->Input()->KeyName(i)); // process the string. we need to escape some characters const char *pSrc = pSelf->m_aaKeyBindings[i]; char *pDst = aBuffer + str_length(aBuffer); *pDst++ = '"'; while(*pSrc && pDst < pEnd) { if(*pSrc == '"' || *pSrc == '\\') // escape \ and " *pDst++ = '\\'; *pDst++ = *pSrc++; } *pDst++ = '"'; *pDst++ = 0; pConfig->WriteLine(aBuffer); } }