📄 bind.cpp
字号:
//
// Online Game Cheats Client.dll hook
// Copyright (c) system 2001-2002
// Copyright (c) bunny771 2001-2002
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// NOTE:
// GNU license doesn't cover Engine directory.
// Content of Engine directory is copyrighted (c) 1999, 2000, by Valve LLC
// and it is licensed under Valve's proprietary license (see original HL SDK).
//
#pragma warning (disable:4786) // vc++ stl "truncated browser info"
#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <vector>
#include <string>
#include <fstream>
#include "cvar.h"
#include "bind.h"
#include "console.h"
using namespace std;
#include "interpreter.h"
extern bool bIsHooked;
//========================================================================================
KeyBindManager keyBindManager;
void Con_Echo(const char *fmt, ... );
string getOgcDirFile(const char* basename);
bool gMenuActive();
void func_menu_select();
void func_menu_back ();
void func_menu_up ();
void func_menu_down ();
//========================================================================================
static int getConsoleExtraCode( int scancode )
{
switch(scancode)
{
case 14: return -1; // backspace
case 28: return '\n'; // enter
case 57: return ' '; // space
case 172: return -2; // uparrow
case 180: return -3; // downarrow
case 175: return -4; // leftarrow
case 177: return -5; // rightarrow
default: return 0; // 0= not found
}
}
//========================================================================================
bool KeyBindManager::keyBlocked(int scancode,bool down)
{
if( (con_visible && con_visible()) || messageMode ) return false;
const char* name = keyNames[scancode].c_str();
if( !*name ){ return false; }
if( gConsole.active && down )
{
if( !name[1] && name[0]!='~' ) return true; // alpha-numeric keys
if( getConsoleExtraCode(scancode) ) return true; // extra keys
}
const char* keyname = keyNames[scancode].c_str();
return myBind.find(keyname) ;
}
//========================================================================================
bool KeyBindManager::keyBlocked(const char* name)
{
bool block = myBind.find(name);
return block||gMenuActive();
}
//========================================================================================
void KeyBindManager::remapKey(char* from, char* to)
{
int scancode_from = -1;
int scancode_to = -1;
for(int i=0;i<256;i++)
{
if( !strcmp(from,keyNames[i].c_str()) ){ scancode_from = i; }
if( !strcmp(to ,keyNames[i].c_str()) ){ scancode_to = i; }
}
keyRemapTable[scancode_from] = scancode_to;
}
//========================================================================================
void KeyBindManager::expandCommand(string& expand,bool down)
{
if(expand[0]=='+')
{
if(down){
CallBack_Execute(expand);
}else {
expand[0]='-';
CallBack_Execute(expand);
expand[0]='+';
}
}
else if( (expand[0]=='.'||expand[0]=='#') && expand[1]=='+' )
{
if(down){
CallBack_Execute(expand);
}else {
expand[1]='-';
CallBack_Execute(expand);
expand[1]='+';
}
}
else
{
if(down) { CallBack_Execute(expand); }
}
}
//========================================================================================
void KeyBindManager::notifyKeyEvent(int scancode,bool down,bool repeat)
{
const char* keyname = keyNames[scancode].c_str();
if(!*keyname )
return;
if( !keyname[1] && down && (messageMode || (con_visible && con_visible())) )
return;
if( gConsole.active && down && bIsHooked)
{
if( !keyname [1] && keyname [0]!='~' )
{
int code = keyname [0];
if( GetAsyncKeyState(VK_SHIFT) )
{
code = shiftRemap[code];
}
if(CallBack_ConType) CallBack_ConType(code);
return;
} else {
int extra = getConsoleExtraCode(scancode);
if (extra && CallBack_ConType) CallBack_ConType(extra);
}
}
if(myBind.find(keyname) && !repeat)
{
string& expand = myBindExpand[myBind.num];
expandCommand(expand,down);
}
}
//========================================================================================
void KeyBindManager::save()
{
ofstream ofs(getOgcDirFile("bind.cfg").c_str());
if(!ofs){ Con_Echo("&rcannot save bind.cfg"); return; }
ofs<<"// this file is generated automatically. do not edit!"<<endl;
for(myBind.it_start();myBind.it_running();myBind.it_next())
{
string& value = myBindExpand[myBind.num];
ofs << "bind " << myBind.str << " \"" << value << "\"\x0D\x0A";
}
}
//========================================================================================
void KeyBindManager::notifyMouseEvent(char* name,bool down)
{
if(!bIsHooked) return;
if(gMenuActive())
{
if(!strcmp(name,"mouse1" )) { if(down)func_menu_select(); return; } else
if(!strcmp(name,"mouse2" )) { if(down)func_menu_back (); return; } else
if(!strcmp(name,"mwheelup" )) { if(down)func_menu_up (); return; } else
if(!strcmp(name,"mwheeldown" )) { if(down)func_menu_down (); return; }
}
if(myBind.find(name))
{
string& expand = myBindExpand[myBind.num];
expandCommand(expand,down);
}
}
//========================================================================================
inline static void lowercase(char* str)
{
while(*str){ *str = tolower(*str); ++str; }
}
//========================================================================================
void KeyBindManager::addBind(char* key, char* value)
{
if(!*key)
{
Con_Echo("valid keys: ");
string line;
for(int i=0;i<256;i++)
{
string& name = keyNames[i];
if(!name.empty())
{
line += " [";
line += name;
line += "] ";
}
if(line.size()>50)
{
Con_Echo(line.c_str());
line.erase();
}
}
Con_Echo(" [mouse1] [mouse2] [mouse3]");
Con_Echo(" [mouse4] [mouse5] [mwheelup] [mwheeldown]");
return;
}
lowercase(key);
if(myBind.find(key))
{
string& expand = myBindExpand[myBind.num];
if(*value)
{
expand = value;
} else {
Con_Echo( "&w%s&a is bound to &w\"%s\"",key,expand.c_str() );
}
} else {
bool found = false;
for(int i=0;i<256;i++)if(keyNames[i]==key) {found=true;break;}
if( !strcmp(key,"mouse1") || !strcmp(key,"mouse2") || !strcmp(key,"mouse3")
|| !strcmp(key,"mouse4") || !strcmp(key,"mouse5")
|| !strcmp(key,"mwheelup") || !strcmp(key,"mwheeldown") )
{
found = true;
}
if(found)
{
if(*value)
{
int index = myBindExpand.size();
myBindExpand.push_back(value);
myBind.add(key,index);
} else {
Con_Echo("&w%s&a is not bound",key);
}
} else {
Con_Echo( "&w%s&a is not a valid key.\n",key);
}
}
}
//========================================================================================
void KeyBindManager::removeBind(char* key)
{
myBind.erase(key);
}
//========================================================================================
void KeyBindManager::init()
{
int i;
for(i=0;i<256;i++)keyRemapTable[i]=i;
keyNames[2] = "1";keyNames[3] = "2";keyNames[4] = "3";keyNames[5] = "4";keyNames[6] = "5";
keyNames[7] = "6";keyNames[8] = "7";keyNames[9] = "8";keyNames[10] = "9";keyNames[11] = "0";
keyNames[12] = "-";keyNames[13] = "=";keyNames[16] = "q";keyNames[17] = "w";keyNames[18] = "e";
keyNames[19] = "r";keyNames[20] = "t";keyNames[21] = "y";keyNames[22] = "u";keyNames[23] = "i";
keyNames[24] = "o";keyNames[25] = "p";keyNames[26] = "[";keyNames[27] = "]";keyNames[30] = "a";
keyNames[31] = "s";keyNames[32] = "d";keyNames[33] = "f";keyNames[34] = "g";keyNames[35] = "h";
keyNames[36] = "j";keyNames[37] = "k";keyNames[38] = "l";keyNames[39] = ";";keyNames[40] = "'";
keyNames[43] = "\\";keyNames[44]= "z";keyNames[45] = "x";keyNames[46] = "c";keyNames[47] = "v";
keyNames[48] = "b";keyNames[49] = "n";keyNames[50] = "m";keyNames[51] = ",";keyNames[52] = ".";
keyNames[53] = "/";keyNames[55] = "*";
keyNames[59] = "f1";keyNames[60] = "f2";keyNames[61] = "f3";keyNames[62] = "f4";keyNames[63] = "f5";
keyNames[64] = "f6";keyNames[65] = "f7";keyNames[66] = "f8";keyNames[67] = "f9";keyNames[68] = "f10";
keyNames[14] = "backspace"; keyNames[15] = "tab"; keyNames[28] = "enter";
keyNames[29] = "ctrl"; keyNames[42] = "shift"; keyNames[54] = "rshift";
keyNames[56] = "alt"; keyNames[57] = "space"; keyNames[58] = "capslock";
keyNames[69] = "pause"; keyNames[71] = "kp_home"; keyNames[72] = "kp_uparrow";
keyNames[73] = "kp_pgup"; keyNames[74] = "kp_minus"; keyNames[75] = "kp_leftarrow";
keyNames[76] = "kp_5"; keyNames[77] = "kp_rightarrow";keyNames[78] = "kp_plus";
keyNames[79] = "kp_end"; keyNames[80] = "kp_downarrow"; keyNames[81] = "kp_pgdn";
keyNames[82] = "kp_ins"; keyNames[83] = "kp_del"; keyNames[87] = "f11";
keyNames[88] = "f12"; keyNames[153] = "kp_slash"; keyNames[171] = "home";
keyNames[172] = "uparrow"; keyNames[173] = "pgup"; keyNames[174] = "minus";
keyNames[175] = "leftarrow"; keyNames[176] = "kp2_5"; keyNames[177] = "rightarrow";
keyNames[178] = "plus"; keyNames[179] = "end"; keyNames[180] = "downarrow";
keyNames[181] = "pgdn"; keyNames[182] = "ins"; keyNames[183] = "del";
for(i=0;i<=255;i++) shiftRemap[i] = toupper((char)i);
shiftRemap['1'] = '!';shiftRemap['2'] = '@';shiftRemap['3'] = '#';shiftRemap['4'] = '$';
shiftRemap['5'] = '%';shiftRemap['6'] = '^';shiftRemap['7'] = '&';shiftRemap['8'] = '*';
shiftRemap['9'] = '(';shiftRemap['0'] = ')';shiftRemap['/'] = '?';shiftRemap['-'] = '_';
shiftRemap['='] = '+';shiftRemap[';'] = ':';shiftRemap['\''] = '\"';
}
//========================================================================================
void remapScancodes(LPMSG lpMsg)
{
int scancode = (lpMsg->lParam>>16)&0xFF;
scancode = keyBindManager.remapScanCode(scancode);
lpMsg->lParam &= 0xFF00FFFF;
lpMsg->lParam += (scancode<<16);
}
//========================================================================================
int getScanCode_FixMessage(LPMSG lpMsg)
{
int scancode = (lpMsg->lParam>>16)&0xFF;
scancode = keyBindManager.remapScanCode(scancode);
lpMsg->lParam &= 0xFF00FFFF;
lpMsg->lParam += (scancode<<16);
if(lpMsg->lParam&(1<<24)) scancode += 100;
return scancode;
}
//========================================================================================
typedef BOOL (WINAPI *GetMessageFunc )(LPMSG,HWND,UINT,UINT);
BOOL WINAPI newGetMessage(
LPMSG lpMsg, // address of structure with message
HWND hWnd, // handle of window
UINT wMsgFilterMin, // first message
UINT wMsgFilterMax // last message
)
{
extern GetMessageFunc origGetMessage;
BOOL ret = origGetMessage(lpMsg,hWnd,wMsgFilterMin,wMsgFilterMax);
int msg = lpMsg->message;
if(msg>=WM_KEYFIRST && msg<=WM_KEYLAST)
{
if( msg==WM_KEYDOWN || msg==WM_SYSKEYDOWN)
{
int scancode = getScanCode_FixMessage(lpMsg);
if(keyBindManager.keyBlocked(scancode,true)) lpMsg->message=WM_CUT; // return a useless message
if( !(lpMsg->lParam&0x40000000) )
{
keyBindManager.notifyKeyEvent(scancode,true,false);
} else {
keyBindManager.notifyKeyEvent(scancode,true,true);
}
if(scancode==28){ keyBindManager.messageMode=false; }
}
else if(msg==WM_KEYUP || msg==WM_SYSKEYUP)
{
int scancode = getScanCode_FixMessage(lpMsg);
if(keyBindManager.keyBlocked(scancode,false)) lpMsg->message=WM_CUT; // return a useless message
keyBindManager.notifyKeyEvent(scancode,false);
}
}
else if(msg>=WM_MOUSEFIRST && msg<=WM_MOUSELAST)
{
char* name="";
bool down=true;
short zDelta = 0;
short butPress = 0;
switch(msg)
{
case WM_LBUTTONDBLCLK:
case WM_LBUTTONDOWN: name = "mouse1"; down=true ;break;
case WM_RBUTTONDBLCLK:
case WM_RBUTTONDOWN: name = "mouse2"; down=true ;break;
case WM_MBUTTONDBLCLK:
case WM_MBUTTONDOWN: name = "mouse3"; down=true ;break;
case WM_LBUTTONUP : name = "mouse1"; down=false;break;
case WM_RBUTTONUP : name = "mouse2"; down=false;break;
case WM_MBUTTONUP : name = "mouse3"; down=false;break;
// mouse4/mouse5 support from joolz-ogc 1.42
// don't know if it works. I only have a 3-button mouse...
case WM_XBUTTONDBLCLK:
case WM_XBUTTONDOWN:
butPress = GET_XBUTTON_WPARAM(lpMsg->wParam);
if (butPress == XBUTTON1) name = "mouse4";
else name = "mouse5";
down = true;
break;
case WM_XBUTTONUP:
butPress = GET_XBUTTON_WPARAM(lpMsg->wParam);
if (butPress == XBUTTON1) name = "mouse4";
else name = "mouse5";
down = false;
break;
case WM_MOUSEWHEEL :
zDelta = GET_WHEEL_DELTA_WPARAM(lpMsg->wParam);
down = true;
if(zDelta>0) name = "mwheelup";
else name = "mwheeldown";
if(keyBindManager.keyBlocked(name))lpMsg->message=WM_CUT;
break;
}
if( *name )
{
keyBindManager.notifyMouseEvent(name,down);
}
// note: this is needed, as the HL engine evaluates the bit changes
// in wParam for WM_MOUSEMOVE messages rather than WM_BUTTONUP.
// blocking bound keys is necessary so no hl binds get executed
// wbwg anticheat binds unbound keys to e.g. "useunbound mouse3"
// to notify the admin of unbound key usage. thus the need to block them.
if(keyBindManager.keyBlocked("mouse1")) { lpMsg->wParam &= (~MK_LBUTTON); }
if(keyBindManager.keyBlocked("mouse2")) { lpMsg->wParam &= (~MK_RBUTTON); }
if(keyBindManager.keyBlocked("mouse3")) { lpMsg->wParam &= (~MK_MBUTTON); }
if(keyBindManager.keyBlocked("mouse4")) { lpMsg->wParam &= (~MK_XBUTTON1); }
if(keyBindManager.keyBlocked("mouse5")) { lpMsg->wParam &= (~MK_XBUTTON2); }
}
return ret;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -