Name | Author | Game Mode | Rating | |||||
---|---|---|---|---|---|---|---|---|
ChatBinds | juanpablo123 | Mutator | 9.5 |
#pragma name "ChatBinds"
/*
ChatBinds mutator by Headshot / juanpablo123
A simple, yet powerful mutator that allows players to essentially "bind"
chat commands to their keys for fast access.
Features three different binding modes: !bind, !bindtoggle, and !bindtoggle2.
!bind: This binds a command to a specified key. Simplest option.
ex. !bind k !k
!bindtoggle: Allows binding a chat command that requires an on/off
parameter.
ex. !bindtoggle p /spectate
!bindtoggle2: Allows binding two off/on chat commands (in that order) that
toggle one option.
ex. !bindtoggle2 o /stop /start
You are also able to bind, but not limited to, keys from F1 to F24
(does anyone even have such function keys that high?) or even the numpad keys.
Your binds are saved, so they will work on any server that uses this mutator.
*/
/*
source for key names from below:
https://docs.microsoft.com/es-es/windows/win32/inputdev/virtual-key-codes
*/
dictionary keyNames = {
{"backspace", 0x08},
{"tab", 0x09},
{"clear", 0x0c},
{"enter", 0x0d},
{"return", 0x0d},
{"shift", 0x10},
{"ctrl", 0x11},
{"control", 0x11},
{"alt", 0x12},
{"menu", 0x12},
{"pause", 0x13},
{"capslock", 0x14},
{"esc", 0x1b},
{"escape", 0x1b},
{"space", 0x20},
{"pgup", 0x21},
{"pageup", 0x21},
{"pgdn", 0x22},
{"pgdown", 0x22},
{"pagedown", 0x22},
{"end", 0x23},
{"home", 0x24},
{"left", 0x25},
{"up", 0x26},
{"right", 0x27},
{"down", 0x28},
{"select", 0x29},
{"printscreen", 0x2c},
{"prntscrn", 0x2c},
{"printscrn", 0x2c},
{"snapshot", 0x2c},
{"ins", 0x2d},
{"insert", 0x2d},
{"del", 0x2e},
{"delete", 0x2e},
{"1", 0x31},
{"2", 0x32},
{"3", 0x33},
{"4", 0x34},
{"5", 0x35},
{"6", 0x36},
{"7", 0x37},
{"8", 0x38},
{"9", 0x39},
{"0", 0x30},
{"a", 0x41},
{"b", 0x42},
{"c", 0x43},
{"d", 0x44},
{"e", 0x45},
{"f", 0x46},
{"g", 0x47},
{"h", 0x48},
{"i", 0x49},
{"j", 0x4a},
{"k", 0x4b},
{"l", 0x4c},
{"m", 0x4d},
{"n", 0x4e},
{"o", 0x4f},
{"p", 0x50},
{"q", 0x51},
{"r", 0x52},
{"s", 0x53},
{"t", 0x54},
{"u", 0x55},
{"v", 0x56},
{"w", 0x57},
{"x", 0x58},
{"y", 0x59},
{"z", 0x5a},
{"lmeta", 0x5b},
{"lwin", 0x5b},
{"rmeta", 0x5c},
{"rwin", 0x5c},
{"apps", 0x5d},
{"numpad0", 0x60},
{"numpad_0", 0x60},
{"numpad_ins", 0x60},
{"numpad_insert", 0x60},
{"numpad1", 0x61},
{"numpad_1", 0x61},
{"numpad_end", 0x61},
{"numpad2", 0x62},
{"numpad_2", 0x62},
{"numpad_dn", 0x62},
{"numpad_down", 0x62},
{"numpad3", 0x63},
{"numpad_3", 0x63},
{"numpad_pgdn", 0x63},
{"numpad_pagedn", 0x63},
{"numpad_pagedown", 0x63},
{"numpad4", 0x64},
{"numpad_4", 0x64},
{"numpad_left", 0x64},
{"numpad5", 0x65},
{"numpad_5", 0x65},
{"numpad6", 0x66},
{"numpad_6", 0x66},
{"numpad_right", 0x66},
{"numpad7", 0x67},
{"numpad_7", 0x67},
{"numpad_home", 0x67},
{"numpad8", 0x68},
{"numpad_8", 0x68},
{"numpad_up", 0x68},
{"numpad9", 0x69},
{"numpad_9", 0x69},
{"numpad_pgup", 0x69},
{"numpad_pageup", 0x69},
{"numpad_multiply", 0x6a},
{"numpad_asterisk", 0x6a},
{"numpad_add", 0x6b},
{"numpad_plus", 0x6b},
{"numpad_sub", 0x6d},
{"numpad_substract", 0x6d},
{"numpad_minus", 0x6d},
{"numpad_dot", 0x6e},
{"numpad_period", 0x6e},
{"numpad_decimal", 0x6e},
{"numpad_del", 0x6e},
{"numpad_delete", 0x6e},
{"numpad_divide", 0x6f},
{"numpad_div", 0x6f},
{"numpad_slash", 0x6f},
{"f1", 0x70},
{"f2", 0x71},
{"f3", 0x72},
{"f4", 0x73},
{"f5", 0x74},
{"f6", 0x75},
{"f7", 0x76},
{"f8", 0x77},
{"f9", 0x78},
{"f10", 0x79},
{"f11", 0x7a},
{"f12", 0x7b},
{"f13", 0x7c},
{"f14", 0x7d},
{"f15", 0x7e},
{"f16", 0x7f},
{"f17", 0x80},
{"f18", 0x81},
{"f19", 0x82},
{"f20", 0x83},
{"f21", 0x84},
{"f22", 0x85},
{"f23", 0x86},
{"f24", 0x87},
{"numlock", 0x90},
{"scroll", 0x91},
{"scrollock", 0x91},
{"scrolllock", 0x91},
{"scroll_lock", 0x91},
{"scrll", 0x91},
{"lshift", 0xa0},
{"rshift", 0xa1},
{"lctrl", 0xa2},
{"lcontrol", 0xa2},
{"rctrl", 0xa3},
{"rcontrol", 0xa3},
{"lmenu", 0xa4},
{"lalt", 0xa4},
{"rmenu", 0xa5},
{"ralt", 0xa5},
{"back", 0xa6},
{"browser_back", 0xa6},
{"forward", 0xa7},
{"browser_forward", 0xa7},
{"next", 0xa7},
{"browser_next", 0xa7},
{"refresh", 0xa8},
{"browser_refresh", 0xa8},
{"browser_stop", 0xa9},
{"search", 0xaa},
{"browser_search", 0xaa},
{"favorites", 0xab},
{"browser_favorites", 0xab},
{"browser_home", 0xac},
{"vol_mute", 0xad},
{"volume_mute", 0xad},
{"mute", 0xad},
{"vol_dn", 0xae},
{"volume_dn", 0xae},
{"vol_down", 0xae},
{"volume_down", 0xae},
{"vol_up", 0xaf},
{"volume_up", 0xaf},
{"media_next", 0xb0},
{"media_prev", 0xb1},
{"media_back", 0xb1},
{"media_stop", 0xb2},
{"media_playpause", 0xb3},
{"media_play_pause", 0xb3},
{"media_play", 0xb3},
{"media_pause", 0xb3},
{"launch_mail", 0xb4},
{"launch_media_select", 0xb5},
{"launch_app1", 0xb6},
{"launch_app2", 0xb7},
{"semicolon", 0xba},
{";", 0xba},
{":", 0xba},
{"plus", 0xbb},
{"+", 0xbb},
{"comma", 0xbc},
{",", 0xbc},
{"minus", 0xbd},
{"-", 0xbd},
{"period", 0xbe},
{"dot", 0xbe},
{".", 0xbe},
{"question", 0xbf},
{"?", 0xbf},
{"slash", 0xbf},
{"/", 0xbf},
{"tilde", 0xc0},
{"~", 0xc0},
{"grave_accent", 0xc0},
{"graveaccent", 0xc0},
{"grave", 0xc0},
{"`", 0xc0},
{"[", 0xdb},
{"{", 0xdb},
{"\\", 0xdc},
{"|", 0xdc},
{"}", 0xdd},
{"]", 0xdd},
{"\"", 0xde},
{"'", 0xde},
{"quote", 0xde}
};
enum TOGGLETYPES
{
TOGGLE_NONE,
TOGGLE_ON_OFF,
TOGGLE_TWO_CMDS,
BIND_LENGTH=0xde+1
};
array<string> binds(BIND_LENGTH, "");
array<bool> pressed(BIND_LENGTH, false);
array<array<int>> isToggle(BIND_LENGTH, array<int> = {TOGGLE_NONE, 0}); // {toggle type, on/off toggle itself}
array<array<string>> toggleCmds(BIND_LENGTH, array<string> = {"", ""}); // for TOGGLE_TWO_CMDS, the two commands used for toggling something (ex. {"/stop", "/start"})
void onLevelBegin()
{
jjSTREAM tutorial("chatbinds_tut.asdat");
jjSTREAM binds_file("my_chatbinds.asdat");
if (tutorial.isEmpty())
{
jjAlert("Welcome to ChatBinds!");
jjAlert("To get started, use the !bind, !bindtoggle, !bindtoggle2 and !unbind commands.");
tutorial.push(0);
tutorial.save("chatbinds_tut.asdat");
}
if (binds_file.isEmpty()) return; // file doesn't exist or has nothing
for (uint i=0x00; i<BIND_LENGTH; i++)
{
string bind, togglecmd_1, togglecmd_2;
bool has_togglecmds;
int toggle;
binds_file.pop(bind);
binds_file.pop(toggle);
binds_file.pop(has_togglecmds);
if (has_togglecmds)
{
binds_file.pop(togglecmd_1);
binds_file.pop(togglecmd_2);
}
binds[i] = bind;
isToggle[i][0] = toggle;
toggleCmds[i] = array<string> = {togglecmd_1, togglecmd_2};
}
}
void saveBinds()
{
jjSTREAM binds_file;
for (uint i=0x00; i<BIND_LENGTH; i++)
{
binds_file.push(binds[i]);
binds_file.push(isToggle[i][0]);
if (not toggleCmds[i][0].isEmpty())
{
binds_file.push(true);
binds_file.push(toggleCmds[i][0]);
binds_file.push(toggleCmds[i][1]);
}
else
binds_file.push(false);
}
binds_file.save("my_chatbinds.asdat");
}
bool onLocalChat(string &in chatmsg, CHAT::Type chatType)
{
array<string> cmdargs = chatmsg.split(" ");
string cmd = cmdargs[0];
cmdargs.removeAt(0);
if (cmd == "!bind")
{
if (cmdargs.isEmpty())
{
jjAlert("Usage: !bind <key> [chat message or command]");
jjAlert("Leave out the second argument to display what command the key is bound to.");
jjAlert("Example: ||!bind k !k ||||||or ||!bind k");
}
else
{
string key = cmdargs[0];
if (keyNames.exists(key))
{
uint keyInd = uint(keyNames[key]);
if (cmdargs.length() >= 2)
{
cmdargs.removeAt(0);
string cmd_bind = join(cmdargs, " ");
binds[keyInd] = cmd_bind;
isToggle[keyInd] = array<int> = {TOGGLE_NONE, 0};
toggleCmds[keyInd] = array<string> = {"", ""};
jjAlert("Bound key ||"+key+" ||||||to ||"+cmd_bind);
saveBinds();
}
else
{
if (not binds[keyInd].isEmpty() and isToggle[keyInd][0] == TOGGLE_ON_OFF)
jjAlert("||"+key+" ||||||is bound to a toggle: ||"+binds[keyInd]+" on/off");
else if (not binds[keyInd].isEmpty())
jjAlert("||"+key+" ||||||is bound to ||"+binds[keyInd]);
else if (not toggleCmds[keyInd][0].isEmpty())
jjAlert("||"+key+" ||||||is bound to a toggle: ||"+toggleCmds[keyInd][0]+" ||||||and ||"+toggleCmds[keyInd][1]);
else
jjAlert("||"+key+" ||||||is not bound");
}
}
else
jjAlert("|Invalid key '"+key+" '");
}
return true;
}
else if (cmd == "!bindtoggle")
{
if (cmdargs.isEmpty())
{
jjAlert("Usage: !bindtoggle <key> [chat message or command]");
jjAlert("A special command to bind on/off commands to keys.");
jjAlert("Example: !bind p /spectate");
}
else
{
string key = cmdargs[0];
if (keyNames.exists(key))
{
uint keyInd = uint(keyNames[key]);
if (cmdargs.length() >= 2)
{
cmdargs.removeAt(0);
string cmd_bind = join(cmdargs, " ");
binds[keyInd] = cmd_bind;
isToggle[keyInd] = array<int> = {TOGGLE_ON_OFF, 0};
toggleCmds[keyInd] = array<string> = {"", ""};
jjAlert("(Toggle) bound key ||"+key+" ||||||to ||"+cmd_bind+" on/off");
saveBinds();
}
else
{
if (not binds[keyInd].isEmpty() and isToggle[keyInd][0] == TOGGLE_ON_OFF)
jjAlert("||"+key+" ||||||is bound to a toggle: ||"+binds[keyInd]+" on/off");
else if (not binds[keyInd].isEmpty())
jjAlert("||"+key+" ||||||is bound to ||"+binds[keyInd]);
else if (not toggleCmds[keyInd][0].isEmpty())
jjAlert("||"+key+" ||||||is bound to a toggle: ||"+toggleCmds[keyInd][0]+" ||||||and ||"+toggleCmds[keyInd][1]);
else
jjAlert("||"+key+" ||||||is not bound");
}
}
else
jjAlert("|Invalid key '"+key+" '");
}
return true;
}
else if (cmd == "!bindtoggle2")
{
if (cmdargs.isEmpty())
{
jjAlert("Usage: !bindtoggle2 <key> <OFF command> <ON command>");
jjAlert("Like !bindtoggle, but uses two commands to toggle something.");
jjAlert("Example: !bind p /stop /start");
}
else
{
string key = cmdargs[0];
if (keyNames.exists(key))
{
uint keyInd = uint(keyNames[key]);
if (cmdargs.length() >= 3)
{
string on_cmd = cmdargs[1];
string off_cmd = cmdargs[2];
isToggle[keyInd] = array<int> = {TOGGLE_TWO_CMDS, 0};
toggleCmds[keyInd] = array<string> = {on_cmd, off_cmd};
jjAlert("(Toggle) bound key ||"+key+" ||||||to ||"+on_cmd+" - "+off_cmd);
saveBinds();
}
else if (cmdargs.length() == 2)
jjAlert("|Missing ON command argument");
else
{
if (not binds[keyInd].isEmpty() and isToggle[keyInd][0] == TOGGLE_ON_OFF)
jjAlert("||"+key+" ||||||is bound to a toggle: ||"+binds[keyInd]+" on/off");
else if (not binds[keyInd].isEmpty())
jjAlert("||"+key+" ||||||is bound to ||"+binds[keyInd]);
else if (not toggleCmds[keyInd][0].isEmpty())
jjAlert("||"+key+" ||||||is bound to a toggle: ||"+toggleCmds[keyInd][0]+" ||||||and ||"+toggleCmds[keyInd][1]);
else
jjAlert("||"+key+" ||||||is not bound");
}
}
else
jjAlert("|Invalid key '"+key+" '");
}
return true;
}
else if (cmd == "!unbind")
{
if (cmdargs.isEmpty())
{
jjAlert("Usage: !unbind <key>");
jjAlert("Removes a chat bind from a key.");
jjAlert("Example: !unbind p");
}
else
{
string key = cmdargs[0];
if (keyNames.exists(key))
{
uint keyInd = uint(keyNames[key]);
if (binds[keyInd].isEmpty() and toggleCmds[keyInd][0].isEmpty())
jjAlert("||"+key+" ||||||is not bound");
else
{
jjAlert("Unbound ||"+key);
binds[keyInd] = "";
isToggle[keyInd] = array<int> = {0, 0};
toggleCmds[keyInd] = array<string> = {"", ""};
saveBinds();
}
}
else
jjAlert("|Invalid key '"+key+" '");
}
return true;
}
return false;
}
void onPlayerInput(jjPLAYER@ player)
{
for (uint i=0x00; i<BIND_LENGTH; i++)
{
if (jjKey[i] and (not binds[i].isEmpty() or not toggleCmds[i][0].isEmpty()) and not pressed[i])
{
switch(isToggle[i][0])
{
case TOGGLE_NONE:
jjChat(binds[i]);
break;
case TOGGLE_ON_OFF:
jjChat(binds[i]+" "+ ((isToggle[i][1] > 0) ? "off" : "on"));
break;
case TOGGLE_TWO_CMDS:
jjChat(toggleCmds[i][isToggle[i][1]]);
break;
}
isToggle[i][1] = -isToggle[i][1]+1;
pressed[i] = true;
}
else if (not jjKey[i] and pressed[i])
pressed[i] = false;
}
}
Jazz2Online © 1999-INFINITY (Site Credits). We have a Privacy Policy. Jazz Jackrabbit, Jazz Jackrabbit 2, Jazz Jackrabbit Advance and all related trademarks and media are ™ and © Epic Games. Lori Jackrabbit is © Dean Dodrill. J2O development powered by Loops of Fury and Chemical Beats.
Eat your lima beans, Johnny.