Rudimentary key rebinding in game options
Currently shown only in the full options list, as it's not quite complete. (For example, it doesn't handle movement commands, or the getpos keys)
This commit is contained in:
@@ -1764,6 +1764,7 @@ some quest nemeses release a cloud of poisonous gas when they die
|
||||
taming magic acting on an already tame creature might make it become tamer
|
||||
eliminate scimitar skill and have scimitars use saber skill
|
||||
simplified configuration options menu
|
||||
rudimentary key rebinding in game options
|
||||
|
||||
|
||||
Platform- and/or Interface-Specific New Features
|
||||
|
||||
@@ -264,6 +264,8 @@ extern void savech_extcmd(const char *, boolean);
|
||||
extern char extcmd_initiator(void);
|
||||
extern int doextcmd(void);
|
||||
extern struct ext_func_tab *extcmds_getentry(int);
|
||||
extern int count_bind_keys(void);
|
||||
extern void handler_rebind_keys(void);
|
||||
extern int extcmds_match(const char *, int, int **);
|
||||
extern const char *key2extcmddesc(uchar);
|
||||
extern boolean bind_specialkey(uchar, const char *);
|
||||
|
||||
@@ -132,6 +132,8 @@ opt_##a,
|
||||
+ sizeof "kick" + sizeof "force" + 20),
|
||||
opt_out, set_in_game, Yes, Yes, No, Yes, NoAlias,
|
||||
"action to take when encountering locked door or chest")
|
||||
NHOPTO("bind keys", Advanced, o_bind_keys, BUFSZ, opt_in,
|
||||
set_in_game, No, Yes, No, NoAlias, "edit key binds")
|
||||
#if defined(MICRO) && !defined(AMIGA)
|
||||
NHOPTB(BIOS, Advanced, 0, opt_in, set_in_config, Off, Yes, No, No, NoAlias,
|
||||
&iflags.BIOS)
|
||||
|
||||
182
src/cmd.c
182
src/cmd.c
@@ -161,6 +161,7 @@ static char *parse(void);
|
||||
static void show_direction_keys(winid, char, boolean);
|
||||
static boolean help_dir(char, uchar, const char *);
|
||||
|
||||
static void handler_rebind_keys_add(boolean);
|
||||
static boolean bind_key_fn(uchar, int (*)(void));
|
||||
static void commands_init(void);
|
||||
static boolean keylist_func_has_key(const struct ext_func_tab *, boolean *);
|
||||
@@ -2826,6 +2827,187 @@ extcmds_getentry(int i)
|
||||
return &extcmdlist[i];
|
||||
}
|
||||
|
||||
/* return number of extended commands bound to a non-default key */
|
||||
int
|
||||
count_bind_keys(void)
|
||||
{
|
||||
int nbinds = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < extcmdlist_length; i++)
|
||||
if (extcmdlist[i].key && g.Cmd.commands[extcmdlist[i].key] != &extcmdlist[i])
|
||||
nbinds++;
|
||||
return nbinds;
|
||||
}
|
||||
|
||||
static void
|
||||
display_changed_key_binds(void)
|
||||
{
|
||||
winid win;
|
||||
int i;
|
||||
char buf[BUFSZ];
|
||||
char buf2[QBUFSZ];
|
||||
|
||||
win = create_nhwindow(NHW_TEXT);
|
||||
for (i = 0; i < extcmdlist_length; i++) {
|
||||
struct ext_func_tab *ec = &extcmdlist[i];
|
||||
|
||||
if (ec->key && g.Cmd.commands[ec->key]
|
||||
&& g.Cmd.commands[ec->key] != ec) {
|
||||
Sprintf(buf, "BIND=%s:%s", key2txt(ec->key, buf2),
|
||||
g.Cmd.commands[ec->key]->ef_txt);
|
||||
putstr(win, 0, buf);
|
||||
}
|
||||
}
|
||||
display_nhwindow(win, TRUE);
|
||||
destroy_nhwindow(win);
|
||||
}
|
||||
|
||||
/* interactive key binding */
|
||||
static void
|
||||
handler_rebind_keys_add(boolean keyfirst)
|
||||
{
|
||||
struct ext_func_tab *ec;
|
||||
winid win;
|
||||
anything any;
|
||||
int i, npick;
|
||||
menu_item *picks = (menu_item *) 0;
|
||||
char buf[BUFSZ];
|
||||
char buf2[QBUFSZ];
|
||||
uchar key = '\0';
|
||||
|
||||
if (keyfirst) {
|
||||
pline("Bind which key? ");
|
||||
key = pgetchar();
|
||||
|
||||
if (!key || key == '\027')
|
||||
return;
|
||||
}
|
||||
|
||||
win = create_nhwindow(NHW_MENU);
|
||||
start_menu(win, MENU_BEHAVE_STANDARD);
|
||||
any = cg.zeroany;
|
||||
|
||||
if (key) {
|
||||
if (g.Cmd.commands[key]) {
|
||||
Sprintf(buf, "Key '%s' is currently bound to \"%s\".",
|
||||
key2txt(key, buf2), g.Cmd.commands[key]->ef_txt);
|
||||
} else {
|
||||
Sprintf(buf, "Key '%s' is not bound to anything.",
|
||||
key2txt(key, buf2));
|
||||
}
|
||||
add_menu(win, &nul_glyphinfo, &any, '\0', 0, ATR_NONE, 0, buf,
|
||||
MENU_ITEMFLAGS_NONE);
|
||||
add_menu(win, &nul_glyphinfo, &any, '\0', 0, ATR_NONE, 0, "",
|
||||
MENU_ITEMFLAGS_NONE);
|
||||
}
|
||||
|
||||
any.a_int = -1;
|
||||
add_menu(win, &nul_glyphinfo, &any, '\0', 0, ATR_NONE, 0, "nothing: unbind the key",
|
||||
MENU_ITEMFLAGS_NONE);
|
||||
|
||||
any.a_int = 0;
|
||||
add_menu(win, &nul_glyphinfo, &any, '\0', 0, ATR_NONE, 0, "",
|
||||
MENU_ITEMFLAGS_NONE);
|
||||
|
||||
for (i = 0; i < extcmdlist_length; i++) {
|
||||
ec = &extcmdlist[i];
|
||||
|
||||
if ((ec->flags & (MOVEMENTCMD|INTERNALCMD|CMD_NOT_AVAILABLE)) != 0)
|
||||
continue;
|
||||
|
||||
any.a_int = (i + 1);
|
||||
Sprintf(buf, "%s: %s", ec->ef_txt, ec->ef_desc);
|
||||
add_menu(win, &nul_glyphinfo, &any, '\0', 0, ATR_NONE, 0, buf,
|
||||
MENU_ITEMFLAGS_NONE);
|
||||
}
|
||||
if (key)
|
||||
Sprintf(buf, "Bind '%s' to what command?", key2txt(key, buf2));
|
||||
else
|
||||
Sprintf(buf, "Bind what command?");
|
||||
end_menu(win, buf);
|
||||
npick = select_menu(win, PICK_ONE, &picks);
|
||||
destroy_nhwindow(win);
|
||||
if (npick > 0) {
|
||||
const struct ext_func_tab *prevec;
|
||||
const char *cmdstr;
|
||||
|
||||
i = picks->item.a_int;
|
||||
free((genericptr_t) picks);
|
||||
|
||||
if (i == -1) {
|
||||
ec = NULL;
|
||||
cmdstr = "nothing";
|
||||
goto bindit;
|
||||
} else {
|
||||
ec = &extcmdlist[i-1];
|
||||
cmdstr = ec->ef_txt;
|
||||
}
|
||||
bindit:
|
||||
if (!key) {
|
||||
pline("Bind which key? ");
|
||||
key = pgetchar();
|
||||
|
||||
if (!key || key == '\027')
|
||||
return;
|
||||
}
|
||||
|
||||
prevec = g.Cmd.commands[key];
|
||||
|
||||
if (bind_key(key, cmdstr)) {
|
||||
if (prevec && prevec != ec) {
|
||||
pline("Changed key '%s' from \"%s\" to \"%s\".",
|
||||
key2txt(key, buf2), prevec->ef_txt, cmdstr);
|
||||
} else if (!prevec) {
|
||||
pline("Bound key '%s' to \"%s\".", key2txt(key, buf2), cmdstr);
|
||||
}
|
||||
} else {
|
||||
pline("Key binding failed?!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
handler_rebind_keys(void)
|
||||
{
|
||||
winid win;
|
||||
anything any;
|
||||
int i, npick;
|
||||
menu_item *picks = (menu_item *) 0;
|
||||
|
||||
redo_rebind:
|
||||
|
||||
win = create_nhwindow(NHW_MENU);
|
||||
start_menu(win, MENU_BEHAVE_STANDARD);
|
||||
any = cg.zeroany;
|
||||
|
||||
any.a_int = 1;
|
||||
add_menu(win, &nul_glyphinfo, &any, '\0', 0, ATR_NONE, 0, "bind key to a command",
|
||||
MENU_ITEMFLAGS_NONE);
|
||||
any.a_int = 2;
|
||||
add_menu(win, &nul_glyphinfo, &any, '\0', 0, ATR_NONE, 0, "bind command to a key",
|
||||
MENU_ITEMFLAGS_NONE);
|
||||
if (count_bind_keys()) {
|
||||
any.a_int = 3;
|
||||
add_menu(win, &nul_glyphinfo, &any, '\0', 0, ATR_NONE, 0, "view changed key binds",
|
||||
MENU_ITEMFLAGS_NONE);
|
||||
}
|
||||
end_menu(win, "Do what?");
|
||||
npick = select_menu(win, PICK_ONE, &picks);
|
||||
destroy_nhwindow(win);
|
||||
if (npick > 0) {
|
||||
i = picks->item.a_int;
|
||||
free((genericptr_t) picks);
|
||||
|
||||
if (i == 1 || i == 2) {
|
||||
handler_rebind_keys_add((i == 1));
|
||||
} else if (i == 3) {
|
||||
display_changed_key_binds();
|
||||
}
|
||||
goto redo_rebind;
|
||||
}
|
||||
}
|
||||
|
||||
/* find extended command entries matching findstr.
|
||||
if findstr is NULL, returns all available entries.
|
||||
returns: number of matching extended commands,
|
||||
|
||||
@@ -7567,6 +7567,28 @@ optfn_o_autopickup_exceptions(
|
||||
return optn_ok;
|
||||
}
|
||||
|
||||
static int
|
||||
optfn_o_bind_keys(
|
||||
int optidx UNUSED, int req, boolean negated UNUSED,
|
||||
char *opts, char *op UNUSED)
|
||||
{
|
||||
if (req == do_init) {
|
||||
return optn_ok;
|
||||
}
|
||||
if (req == do_set) {
|
||||
}
|
||||
if (req == get_val) {
|
||||
if (!opts)
|
||||
return optn_err;
|
||||
Sprintf(opts, n_currently_set, count_bind_keys());
|
||||
return optn_ok;
|
||||
}
|
||||
if (req == do_handler) {
|
||||
handler_rebind_keys();
|
||||
}
|
||||
return optn_ok;
|
||||
}
|
||||
|
||||
static int
|
||||
optfn_o_menu_colors(int optidx UNUSED, int req, boolean negated UNUSED,
|
||||
char *opts, char *op UNUSED)
|
||||
|
||||
Reference in New Issue
Block a user