autounlock overhaul
This gives the player more control over what autounlock does. It is
now a compound option rather than a boolean, and takes values of
autounlock:none
!autounlock or noautounlock (shortcuts for none)
autounlock:untrap + apply-key + kick + force (spaces are optional
or can be used instead of plus-signs, but can't mix "foo bar+quux")
autounlock (without a value, shortcut for autounlock:apply-key).
Default is autounlock:apply-key.
Untrap isn't implemented (feel free to jump in) so is suppressed from
the 'O' command's new sub-menu for autounlock. It's parsed and
accepted from .nethackrc but won't accomplish anything.
[Just musing: it should be feasible to kick in direction '.' to break
open a container or #force to an adjacent spot to break open a door.
If that was done, autounlock:kick+force (or more likely autounlock:
apply-key+kick+force when lacking a key) would resort to force if hero
couldn't kick due to wounded legs or riding.
This changes struct flags so increments EDITLEVEL again.
This includes pull requests #750 from entrez and #751 from FIQ but was
entered from scratch rather than using use their commits.
Closes #750
Closes #751
This commit is contained in:
+6
-2
@@ -9,8 +9,6 @@ autoopen walking into a door attempts to open it [True]
|
|||||||
autopickup automatically pick up objects you move over [True]
|
autopickup automatically pick up objects you move over [True]
|
||||||
autoquiver when firing with an empty quiver, select some [False]
|
autoquiver when firing with an empty quiver, select some [False]
|
||||||
suitable inventory weapon to fill the quiver
|
suitable inventory weapon to fill the quiver
|
||||||
autounlock when opening a locked door or looting a locked [True]
|
|
||||||
container while carrying a key, offer to use it
|
|
||||||
BIOS allow the use of IBM ROM BIOS calls [False]
|
BIOS allow the use of IBM ROM BIOS calls [False]
|
||||||
blind your character is permanently blind [False]
|
blind your character is permanently blind [False]
|
||||||
bones allow loading bones files [True]
|
bones allow loading bones files [True]
|
||||||
@@ -150,6 +148,12 @@ Compound options are written as option_name:option_value.
|
|||||||
|
|
||||||
Compound options which can be set during the game are:
|
Compound options which can be set during the game are:
|
||||||
|
|
||||||
|
autounlock when attempting to open a door or loot a [Apply-Key]
|
||||||
|
container that is locked, specifies an action to take:
|
||||||
|
can be None, or one or more of Apply-Key + Kick + Force;
|
||||||
|
Kick is only useful for doors and Force is only useful for
|
||||||
|
containers; either will only be attempted if Apply-Key is
|
||||||
|
omitted or you aren't carrying any unlocking tool
|
||||||
boulder override the default boulder symbol [`]
|
boulder override the default boulder symbol [`]
|
||||||
disclose the types of information you want [ni na nv ng nc no]
|
disclose the types of information you want [ni na nv ng nc no]
|
||||||
offered at the end of the game
|
offered at the end of the game
|
||||||
|
|||||||
+22
-3
@@ -3659,9 +3659,28 @@ If no weapon is found or the option is
|
|||||||
false, the \(oqt\(cq (throw) command is executed instead.
|
false, the \(oqt\(cq (throw) command is executed instead.
|
||||||
Persistent.
|
Persistent.
|
||||||
.lp autounlock
|
.lp autounlock
|
||||||
Walking into a locked door or looting a locked container while carrying
|
Controls what action to take when attempting to walk into a locked door
|
||||||
an unlocking tool (such as a key) will ask whether to use that tool to
|
or to loot a locked container.
|
||||||
unlock the door or container (default true).
|
Takes a plus-sign separated list of values:
|
||||||
|
\fIapply-key\fP which will attempt to use a key or other unlocking tool
|
||||||
|
if you have one;
|
||||||
|
\fIkick\fP which will kick the door (if you lack a key or omit apply-key;
|
||||||
|
has no effect on containers);
|
||||||
|
\fIforce\fP which will try to force a container's lid with your currently
|
||||||
|
wielded weapon (if you lack a key or omit apply-key; has no effect on
|
||||||
|
doors); or
|
||||||
|
\fInone\fP which can't be combined with the other choices.
|
||||||
|
.lp ""
|
||||||
|
Omitting the value is treated as if \f(CRautounlock:apply-key\fP.
|
||||||
|
Preceding \f(CRautounlock\fP with \(oq!\(cq or \(lqno\(rq is treated as
|
||||||
|
\f(CRautounlock:none\fP.
|
||||||
|
.lp ""
|
||||||
|
Applying a key might set off a trap if the door or container is trapped.
|
||||||
|
Successfully kicking a door will break it and wake up nearby monsters.
|
||||||
|
Successfully forcing a container open will break its lock and might also
|
||||||
|
destroy some of its contents or damage your weapon or both.
|
||||||
|
.lp ""
|
||||||
|
The default is \fIapply-key\fP.
|
||||||
Persistent.
|
Persistent.
|
||||||
.lp blind
|
.lp blind
|
||||||
Start the character permanently blind (default false).
|
Start the character permanently blind (default false).
|
||||||
|
|||||||
+25
-3
@@ -3970,9 +3970,31 @@ If no weapon is found or the option is
|
|||||||
false, the `t' (throw) command is executed instead. Persistent.
|
false, the `t' (throw) command is executed instead. Persistent.
|
||||||
%.lp
|
%.lp
|
||||||
\item[\ib{autounlock}]
|
\item[\ib{autounlock}]
|
||||||
Walking into a locked door or looting a locked container while carrying
|
Controls what action to take when attempting to walk into a locked door
|
||||||
an unlocking tool (such as a key) will ask whether to use that tool to
|
or to loot a locked container.
|
||||||
unlock the door or container (default true).
|
Takes a plus-sign separated list of values:
|
||||||
|
{\it apply-key\/} which will attempt to use a key or other unlocking tool
|
||||||
|
if you have one;
|
||||||
|
{\it kick\/} which will kick the door (if you lack a key or omit apply-key;
|
||||||
|
has no effect on containers);
|
||||||
|
{\it force\/} which will try to force a container's lid with your currently
|
||||||
|
wielded weapon (if you lack a key or omit apply-key; has no effect on
|
||||||
|
doors); or
|
||||||
|
{\it none\/} which can't be combined with the other choices.
|
||||||
|
\\
|
||||||
|
%.lp ""
|
||||||
|
Omitting the value is treated as if {\tt autounlock:apply-key}.
|
||||||
|
Preceding {\tt autounlock} with `{\tt !}' or ``{\tt no}'' is treated as
|
||||||
|
{\tt autounlock:none}.
|
||||||
|
\\
|
||||||
|
%.lp ""
|
||||||
|
Applying a key might set off a trap if the door or container is trapped.
|
||||||
|
Successfully kicking a door will break it and wake up nearby monsters.
|
||||||
|
Successfully forcing a container open will break its lock and might also
|
||||||
|
destroy some of its contents or damage your weapon or both.
|
||||||
|
\\
|
||||||
|
%.lp ""
|
||||||
|
The default is {\it apply-key\/}.
|
||||||
Persistent.
|
Persistent.
|
||||||
%.lp
|
%.lp
|
||||||
\item[\ib{blind}]
|
\item[\ib{blind}]
|
||||||
|
|||||||
+5
-1
@@ -20,7 +20,6 @@ struct flag {
|
|||||||
boolean autodig; /* MRKR: Automatically dig */
|
boolean autodig; /* MRKR: Automatically dig */
|
||||||
boolean autoquiver; /* Automatically fill quiver */
|
boolean autoquiver; /* Automatically fill quiver */
|
||||||
boolean autoopen; /* open doors by walking into them */
|
boolean autoopen; /* open doors by walking into them */
|
||||||
boolean autounlock; /* automatically apply unlocking tools */
|
|
||||||
boolean beginner; /* True early in each game; affects feedback */
|
boolean beginner; /* True early in each game; affects feedback */
|
||||||
boolean biff; /* enable checking for mail */
|
boolean biff; /* enable checking for mail */
|
||||||
boolean bones; /* allow saving/loading bones */
|
boolean bones; /* allow saving/loading bones */
|
||||||
@@ -63,6 +62,11 @@ struct flag {
|
|||||||
boolean tombstone; /* print tombstone */
|
boolean tombstone; /* print tombstone */
|
||||||
boolean verbose; /* max battle info */
|
boolean verbose; /* max battle info */
|
||||||
int end_top, end_around; /* describe desired score list */
|
int end_top, end_around; /* describe desired score list */
|
||||||
|
unsigned autounlock; /* locked door/chest action */
|
||||||
|
#define AUTOUNLOCK_UNTRAP 1
|
||||||
|
#define AUTOUNLOCK_APPLY_KEY 2
|
||||||
|
#define AUTOUNLOCK_KICK 4
|
||||||
|
#define AUTOUNLOCK_FORCE 8
|
||||||
unsigned moonphase;
|
unsigned moonphase;
|
||||||
unsigned long suppress_alert;
|
unsigned long suppress_alert;
|
||||||
#define NEW_MOON 0
|
#define NEW_MOON 0
|
||||||
|
|||||||
+5
-2
@@ -124,8 +124,11 @@ opt_##a,
|
|||||||
set_in_game, No, Yes, No, NoAlias, "edit autopickup exceptions")
|
set_in_game, No, Yes, No, NoAlias, "edit autopickup exceptions")
|
||||||
NHOPTB(autoquiver, 0, opt_in, set_in_game, Off, Yes, No, No, NoAlias,
|
NHOPTB(autoquiver, 0, opt_in, set_in_game, Off, Yes, No, No, NoAlias,
|
||||||
&flags.autoquiver)
|
&flags.autoquiver)
|
||||||
NHOPTB(autounlock, 0, opt_out, set_in_game, On, Yes, No, No, NoAlias,
|
NHOPTC(autounlock,
|
||||||
&flags.autounlock)
|
(sizeof "none" + sizeof "untrap" + sizeof "apply-key"
|
||||||
|
+ sizeof "kick" + sizeof "force" + 20),
|
||||||
|
opt_out, set_in_game, Yes, Yes, No, Yes, NoAlias,
|
||||||
|
"action to take when encountering locked door or chest")
|
||||||
#if defined(MICRO) && !defined(AMIGA)
|
#if defined(MICRO) && !defined(AMIGA)
|
||||||
NHOPTB(BIOS, 0, opt_in, set_in_config, Off, Yes, No, No, NoAlias,
|
NHOPTB(BIOS, 0, opt_in, set_in_config, Off, Yes, No, No, NoAlias,
|
||||||
&iflags.BIOS)
|
&iflags.BIOS)
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
* Incrementing EDITLEVEL can be used to force invalidation of old bones
|
* Incrementing EDITLEVEL can be used to force invalidation of old bones
|
||||||
* and save files.
|
* and save files.
|
||||||
*/
|
*/
|
||||||
#define EDITLEVEL 57
|
#define EDITLEVEL 58
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Development status possibilities.
|
* Development status possibilities.
|
||||||
|
|||||||
+29
-15
@@ -350,18 +350,19 @@ DISABLE_WARNING_FORMAT_NONLITERAL
|
|||||||
|
|
||||||
/* player is applying a key, lock pick, or credit card */
|
/* player is applying a key, lock pick, or credit card */
|
||||||
int
|
int
|
||||||
pick_lock(struct obj *pick,
|
pick_lock(
|
||||||
xchar rx, xchar ry, /* coordinates of doors/container,
|
struct obj *pick,
|
||||||
for autounlock: does not prompt
|
xchar rx, xchar ry, /* coordinates of door/container, for autounlock:
|
||||||
for direction if these are set */
|
* does not prompt for direction if these are set */
|
||||||
struct obj *container) /* container, for autounlock */
|
struct obj *container) /* container, for autounlock */
|
||||||
{
|
{
|
||||||
int picktyp, c, ch;
|
int picktyp, c, ch;
|
||||||
coord cc;
|
coord cc;
|
||||||
struct rm *door;
|
struct rm *door;
|
||||||
struct obj *otmp;
|
struct obj *otmp;
|
||||||
char qbuf[QBUFSZ];
|
char qbuf[QBUFSZ];
|
||||||
boolean autounlock = (rx != 0 && ry != 0) || (container != NULL);
|
boolean autounlock = (((rx != 0 && ry != 0) || container != NULL)
|
||||||
|
&& (flags.autounlock & AUTOUNLOCK_APPLY_KEY) != 0);
|
||||||
|
|
||||||
picktyp = pick->otyp;
|
picktyp = pick->otyp;
|
||||||
|
|
||||||
@@ -422,7 +423,7 @@ pick_lock(struct obj *pick,
|
|||||||
boolean it;
|
boolean it;
|
||||||
int count;
|
int count;
|
||||||
|
|
||||||
if (u.dz < 0) {
|
if (u.dz < 0 && !autounlock) { /* beware stale u.dz value */
|
||||||
There("isn't any sort of lock up %s.",
|
There("isn't any sort of lock up %s.",
|
||||||
Levitation ? "here" : "there");
|
Levitation ? "here" : "there");
|
||||||
return PICKLOCK_LEARNED_SOMETHING;
|
return PICKLOCK_LEARNED_SOMETHING;
|
||||||
@@ -436,10 +437,12 @@ pick_lock(struct obj *pick,
|
|||||||
|
|
||||||
count = 0;
|
count = 0;
|
||||||
c = 'n'; /* in case there are no boxes here */
|
c = 'n'; /* in case there are no boxes here */
|
||||||
for (otmp = g.level.objects[cc.x][cc.y]; otmp; otmp = otmp->nexthere)
|
for (otmp = g.level.objects[cc.x][cc.y]; otmp; otmp = otmp->nexthere) {
|
||||||
/* autounlock on boxes: only the one that just informed you it was
|
/* autounlock on boxes: only the one that was just discovered to
|
||||||
* locked. Don't include any other boxes which might be here. */
|
be locked; don't include any other boxes which might be here */
|
||||||
if ((!autounlock && Is_box(otmp)) || (otmp == container)) {
|
if (autounlock && otmp != container)
|
||||||
|
continue;
|
||||||
|
if (Is_box(otmp)) {
|
||||||
++count;
|
++count;
|
||||||
if (!can_reach_floor(TRUE)) {
|
if (!can_reach_floor(TRUE)) {
|
||||||
You_cant("reach %s from up here.", the(xname(otmp)));
|
You_cant("reach %s from up here.", the(xname(otmp)));
|
||||||
@@ -508,6 +511,7 @@ pick_lock(struct obj *pick,
|
|||||||
g.xlock.door = 0;
|
g.xlock.door = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (c != 'y') {
|
if (c != 'y') {
|
||||||
if (!count)
|
if (!count)
|
||||||
There("doesn't seem to be any sort of lock here.");
|
There("doesn't seem to be any sort of lock here.");
|
||||||
@@ -626,6 +630,11 @@ doforce(void)
|
|||||||
register int c, picktyp;
|
register int c, picktyp;
|
||||||
char qbuf[QBUFSZ];
|
char qbuf[QBUFSZ];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO?
|
||||||
|
* allow force with edged weapon to be performed on doors.
|
||||||
|
*/
|
||||||
|
|
||||||
if (u.uswallow) {
|
if (u.uswallow) {
|
||||||
You_cant("force anything from inside here.");
|
You_cant("force anything from inside here.");
|
||||||
return ECMD_OK;
|
return ECMD_OK;
|
||||||
@@ -780,7 +789,6 @@ doopen_indir(int x, int y)
|
|||||||
if (!(door->doormask & D_CLOSED)) {
|
if (!(door->doormask & D_CLOSED)) {
|
||||||
const char *mesg;
|
const char *mesg;
|
||||||
boolean locked = FALSE;
|
boolean locked = FALSE;
|
||||||
struct obj* unlocktool;
|
|
||||||
|
|
||||||
switch (door->doormask) {
|
switch (door->doormask) {
|
||||||
case D_BROKEN:
|
case D_BROKEN:
|
||||||
@@ -798,11 +806,17 @@ doopen_indir(int x, int y)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
pline("This door%s.", mesg);
|
pline("This door%s.", mesg);
|
||||||
if (locked) {
|
if (locked && flags.autounlock) {
|
||||||
if (flags.autounlock && (unlocktool = autokey(TRUE)) != 0) {
|
struct obj *unlocktool;
|
||||||
|
|
||||||
|
u.dz = 0; /* should already be 0 since hero moved toward door */
|
||||||
|
if ((flags.autounlock & AUTOUNLOCK_APPLY_KEY) != 0
|
||||||
|
&& (unlocktool = autokey(TRUE)) != 0) {
|
||||||
res = pick_lock(unlocktool, cc.x, cc.y,
|
res = pick_lock(unlocktool, cc.x, cc.y,
|
||||||
(struct obj *) 0) ? ECMD_TIME : ECMD_OK;
|
(struct obj *) 0) ? ECMD_TIME : ECMD_OK;
|
||||||
} else if (!u.usteed && ynq("Kick it?") == 'y') {
|
} else if (!u.usteed
|
||||||
|
&& (flags.autounlock & AUTOUNLOCK_KICK) != 0
|
||||||
|
&& ynq("Kick it?") == 'y') {
|
||||||
cmdq_add_ec(dokick);
|
cmdq_add_ec(dokick);
|
||||||
cmdq_add_dir(sgn(cc.x - u.ux), sgn(cc.y - u.uy), 0);
|
cmdq_add_dir(sgn(cc.x - u.ux), sgn(cc.y - u.uy), 0);
|
||||||
res = ECMD_TIME;
|
res = ECMD_TIME;
|
||||||
|
|||||||
+179
@@ -190,6 +190,14 @@ static NEARDATA const char *msgwind[][3] = { /* 'msg_window' settings */
|
|||||||
" most recent first]" }
|
" most recent first]" }
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
/* autounlock settings */
|
||||||
|
static NEARDATA const char *unlocktypes[][2] = {
|
||||||
|
{ "none", "" },
|
||||||
|
{ "untrap", "(might fail)" },
|
||||||
|
{ "apply-key", "" },
|
||||||
|
{ "kick", "(doors only)" },
|
||||||
|
{ "force", "(chests/boxes only)" },
|
||||||
|
};
|
||||||
static NEARDATA const char *burdentype[] = {
|
static NEARDATA const char *burdentype[] = {
|
||||||
"unencumbered", "burdened", "stressed",
|
"unencumbered", "burdened", "stressed",
|
||||||
"strained", "overtaxed", "overloaded"
|
"strained", "overtaxed", "overloaded"
|
||||||
@@ -297,6 +305,7 @@ static int count_apes(void);
|
|||||||
static int count_cond(void);
|
static int count_cond(void);
|
||||||
|
|
||||||
static int handler_align_misc(int);
|
static int handler_align_misc(int);
|
||||||
|
static int handler_autounlock(int);
|
||||||
static int handler_disclose(void);
|
static int handler_disclose(void);
|
||||||
static int handler_menu_headings(void);
|
static int handler_menu_headings(void);
|
||||||
static int handler_menustyle(void);
|
static int handler_menustyle(void);
|
||||||
@@ -712,6 +721,107 @@ optfn_altkeyhandling(
|
|||||||
return optn_ok;
|
return optn_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
optfn_autounlock(
|
||||||
|
int optidx,
|
||||||
|
int req,
|
||||||
|
boolean negated,
|
||||||
|
char *opts,
|
||||||
|
char *op)
|
||||||
|
{
|
||||||
|
if (req == do_init) {
|
||||||
|
flags.autounlock = AUTOUNLOCK_APPLY_KEY;
|
||||||
|
return optn_ok;
|
||||||
|
}
|
||||||
|
if (req == do_set) {
|
||||||
|
/* autounlock:none or autounlock:untrap+apply-key+kick+force;
|
||||||
|
autounlock without a value is same as autounlock:apply-key and
|
||||||
|
!autounlock is same as autounlock:none; multiple values can be
|
||||||
|
space separated or plus-sign separated but the same separation
|
||||||
|
must be used for each element, not mix&match */
|
||||||
|
char sep, *nxt;
|
||||||
|
unsigned newflags;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if ((op = string_for_opt(opts, TRUE)) == empty_optstr) {
|
||||||
|
flags.autounlock = negated ? 0 : AUTOUNLOCK_APPLY_KEY;
|
||||||
|
return optn_ok;
|
||||||
|
}
|
||||||
|
newflags = 0;
|
||||||
|
sep = index(op, '+') ? '+' : ' ';
|
||||||
|
while (op) {
|
||||||
|
op = trimspaces(op); /* might have leading space */
|
||||||
|
if ((nxt = index(op, sep)) != '\0') {
|
||||||
|
*nxt++ = '\0';
|
||||||
|
op = trimspaces(op); /* might have trailing space after
|
||||||
|
* plus sign removal */
|
||||||
|
}
|
||||||
|
for (i = 0; i < SIZE(unlocktypes); ++i)
|
||||||
|
if (!strncmpi(op, unlocktypes[i][0], Strlen(op))
|
||||||
|
/* fuzzymatch() doesn't match leading substrings but
|
||||||
|
this allows "apply_key" and "applykey" to match
|
||||||
|
"apply-key"; "apply key" too if part of foo+bar */
|
||||||
|
|| fuzzymatch(op, unlocktypes[i][0], " -_", TRUE)) {
|
||||||
|
switch (*op) {
|
||||||
|
case 'n':
|
||||||
|
negated = TRUE;
|
||||||
|
break;
|
||||||
|
case 'u':
|
||||||
|
newflags |= AUTOUNLOCK_UNTRAP;
|
||||||
|
break;
|
||||||
|
case 'a':
|
||||||
|
newflags |= AUTOUNLOCK_APPLY_KEY;
|
||||||
|
break;
|
||||||
|
case 'k':
|
||||||
|
newflags |= AUTOUNLOCK_KICK;
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
newflags |= AUTOUNLOCK_FORCE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
config_error_add("Invalid value for \"%s\": \"%s\"",
|
||||||
|
allopt[optidx].name, op);
|
||||||
|
return optn_silenterr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
op = nxt;
|
||||||
|
}
|
||||||
|
if (negated && newflags != 0) {
|
||||||
|
config_error_add(
|
||||||
|
"Invalid value combination for \"%s\": 'none' with some",
|
||||||
|
allopt[optidx].name);
|
||||||
|
return optn_silenterr;
|
||||||
|
}
|
||||||
|
flags.autounlock = newflags;
|
||||||
|
return optn_ok;
|
||||||
|
}
|
||||||
|
if (req == get_val) {
|
||||||
|
if (!opts)
|
||||||
|
return optn_err;
|
||||||
|
if (!flags.autounlock) {
|
||||||
|
Strcpy(opts, "none");
|
||||||
|
} else {
|
||||||
|
static const char plus[] = " + ";
|
||||||
|
const char *p = "";
|
||||||
|
|
||||||
|
*opts = '\0';
|
||||||
|
if (flags.autounlock & AUTOUNLOCK_UNTRAP)
|
||||||
|
Sprintf(eos(opts), "%s%s", p, unlocktypes[1][0]), p = plus;
|
||||||
|
if (flags.autounlock & AUTOUNLOCK_APPLY_KEY)
|
||||||
|
Sprintf(eos(opts), "%s%s", p, unlocktypes[2][0]), p = plus;
|
||||||
|
if (flags.autounlock & AUTOUNLOCK_KICK)
|
||||||
|
Sprintf(eos(opts), "%s%s", p, unlocktypes[3][0]), p = plus;
|
||||||
|
if (flags.autounlock & AUTOUNLOCK_FORCE)
|
||||||
|
Sprintf(eos(opts), "%s%s", p, unlocktypes[4][0]); /*no more p*/
|
||||||
|
}
|
||||||
|
return optn_ok;
|
||||||
|
}
|
||||||
|
if (req == do_handler) {
|
||||||
|
return handler_autounlock(optidx);
|
||||||
|
}
|
||||||
|
return optn_ok;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
optfn_boulder(int optidx UNUSED, int req, boolean negated UNUSED,
|
optfn_boulder(int optidx UNUSED, int req, boolean negated UNUSED,
|
||||||
char *opts, char *op UNUSED)
|
char *opts, char *op UNUSED)
|
||||||
@@ -4408,6 +4518,75 @@ handler_align_misc(int optidx)
|
|||||||
return optn_ok;
|
return optn_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
handler_autounlock(int optidx)
|
||||||
|
{
|
||||||
|
winid tmpwin;
|
||||||
|
anything any;
|
||||||
|
boolean chngd;
|
||||||
|
unsigned oldflags = flags.autounlock;
|
||||||
|
const char *optname = allopt[optidx].name;
|
||||||
|
char buf[BUFSZ], sep = iflags.menu_tab_sep ? '\t' : ' ';
|
||||||
|
menu_item *window_pick = (menu_item *) 0;
|
||||||
|
int i, n, presel, res = optn_ok;
|
||||||
|
|
||||||
|
tmpwin = create_nhwindow(NHW_MENU);
|
||||||
|
start_menu(tmpwin, MENU_BEHAVE_STANDARD);
|
||||||
|
any = cg.zeroany;
|
||||||
|
for (i = 0; i < SIZE(unlocktypes); ++i) {
|
||||||
|
if (i == 1) /*** suppress 'untrap' from the menu... ***/
|
||||||
|
continue; /*** until it actually gets implemented ***/
|
||||||
|
Sprintf(buf, "%-10.10s%c%.40s",
|
||||||
|
unlocktypes[i][0], sep, unlocktypes[i][1]);
|
||||||
|
presel = !i ? !flags.autounlock : (flags.autounlock & (1 << (i - 1)));
|
||||||
|
any.a_int = i + 1;
|
||||||
|
add_menu(tmpwin, &nul_glyphinfo, &any, *unlocktypes[i][0], 0,
|
||||||
|
ATR_NONE, buf,
|
||||||
|
((presel ? MENU_ITEMFLAGS_SELECTED : MENU_ITEMFLAGS_NONE)
|
||||||
|
| (!i ? MENU_ITEMFLAGS_SKIPINVERT : 0)));
|
||||||
|
}
|
||||||
|
Sprintf(buf, "Select '%.20s' actions:", optname);
|
||||||
|
end_menu(tmpwin, buf);
|
||||||
|
n = select_menu(tmpwin, PICK_ANY, &window_pick);
|
||||||
|
if (n > 0) {
|
||||||
|
int k;
|
||||||
|
boolean wasnone = !flags.autounlock;
|
||||||
|
unsigned newflags = 0, noflags = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < n; ++i) {
|
||||||
|
k = window_pick[i].item.a_int - 1;
|
||||||
|
if (k)
|
||||||
|
newflags |= (1 << (k - 1));
|
||||||
|
else
|
||||||
|
noflags = 1;
|
||||||
|
}
|
||||||
|
/* wasnone: 'none' is preselected;
|
||||||
|
!wasnone: don't force it to be unselected */
|
||||||
|
if (newflags && noflags && !wasnone) {
|
||||||
|
config_error_add(
|
||||||
|
"Invalid value combination for \"%s\": 'none' with some",
|
||||||
|
optname);
|
||||||
|
res = optn_silenterr;
|
||||||
|
} else {
|
||||||
|
flags.autounlock = newflags;
|
||||||
|
}
|
||||||
|
free((genericptr_t) window_pick);
|
||||||
|
} else if (n == 0) { /* nothing was picked but menu wasn't cancelled */
|
||||||
|
/* something that was preselected got unselected, leaving nothing;
|
||||||
|
treat that as picking 'none' (even though 'none' might be what
|
||||||
|
got unselected) */
|
||||||
|
flags.autounlock = 0;
|
||||||
|
}
|
||||||
|
destroy_nhwindow(tmpwin);
|
||||||
|
chngd = (flags.autounlock != oldflags);
|
||||||
|
if (chngd || flags.verbose) {
|
||||||
|
optfn_autounlock(optidx, get_val, FALSE, buf, (char *) NULL);
|
||||||
|
pline("'%s' %s '%s'.", optname,
|
||||||
|
chngd ? "changed to" : "is still", buf);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
handler_disclose(void)
|
handler_disclose(void)
|
||||||
{
|
{
|
||||||
|
|||||||
+10
-4
@@ -1872,8 +1872,6 @@ do_loot_cont(struct obj **cobjp,
|
|||||||
if (!cobj)
|
if (!cobj)
|
||||||
return ECMD_OK;
|
return ECMD_OK;
|
||||||
if (cobj->olocked) {
|
if (cobj->olocked) {
|
||||||
struct obj *unlocktool;
|
|
||||||
|
|
||||||
if (ccount < 2 && (g.level.objects[cobj->ox][cobj->oy] == cobj))
|
if (ccount < 2 && (g.level.objects[cobj->ox][cobj->oy] == cobj))
|
||||||
pline("%s locked.",
|
pline("%s locked.",
|
||||||
cobj->lknown ? "It is" : "Hmmm, it turns out to be");
|
cobj->lknown ? "It is" : "Hmmm, it turns out to be");
|
||||||
@@ -1884,10 +1882,18 @@ do_loot_cont(struct obj **cobjp,
|
|||||||
cobj->lknown = 1;
|
cobj->lknown = 1;
|
||||||
|
|
||||||
if (flags.autounlock) {
|
if (flags.autounlock) {
|
||||||
if ((unlocktool = autokey(TRUE)) != 0) {
|
struct obj *unlocktool;
|
||||||
|
|
||||||
|
/* TODO: handle AUTOUNLOCK_UNTRAP and maybe add kicking at
|
||||||
|
self when chest present to handle AUTOUNLOCK_KICK */
|
||||||
|
u.dz = 0; /* might be non-zero from previous command since
|
||||||
|
* #loot isn't a move command; pick_lock() cares */
|
||||||
|
if ((flags.autounlock & AUTOUNLOCK_APPLY_KEY) != 0
|
||||||
|
&& (unlocktool = autokey(TRUE)) != 0) {
|
||||||
/* pass ox and oy to avoid direction prompt */
|
/* pass ox and oy to avoid direction prompt */
|
||||||
return (pick_lock(unlocktool, cobj->ox, cobj->oy, cobj) != 0);
|
return (pick_lock(unlocktool, cobj->ox, cobj->oy, cobj) != 0);
|
||||||
} else if (ccount == 1 && u_have_forceable_weapon()) {
|
} else if ((flags.autounlock & AUTOUNLOCK_FORCE) != 0
|
||||||
|
&& ccount == 1 && u_have_forceable_weapon()) {
|
||||||
/* single container, and we could #force it open... */
|
/* single container, and we could #force it open... */
|
||||||
cmdq_add_ec(doforce); /* doforce asks for confirmation */
|
cmdq_add_ec(doforce); /* doforce asks for confirmation */
|
||||||
g.abort_looting = TRUE;
|
g.abort_looting = TRUE;
|
||||||
|
|||||||
Reference in New Issue
Block a user