Port the autounlock feature, hallucinatory trap names from UnNetHack
This adds a boolean option, autounlock, defaulting to true. When this is set to TRUE, messages stating that some door or container is locked are automatically followed by a prompt asking if you would like to unlock it, if you are carrying an unlocking tool (key, lock pick, or credit card). Architecturally, this extends the pick_lock function to take three additional arguments (door coordinates or a box on the ground you are autounlocking). The code that selects an unlocking tool will always look first for a skeleton key, then a lock pick, then a credit card. Since curses, rust, and other attributes don't really have an effect on the viability of the unlocking device, it didn't seem to warrant making a more complex function for that. Add hallucinatory trap names This adds many funny, realistic, and nonsensical traps to the game, to be shown when the player is hallucinating. Architecturally, the biggest change is merging the what_trap macro and the "defsyms[trap_to_defsym(ttyp)].explanation" pattern into a single function "trapname", which returns the name of the trap, handling the hallucination case. There is also a second parameter used for overriding hallucination in the occasional cases where the actual trap name should always be returned. In addition, the what_trap and random_trap macros are now obsolete and not used anywhere, so they are removed. reinstate anti-rng abuse bit on hallucination updates to hallucinatory trap names and fixes37.0 entry
This commit is contained in:
59
src/lock.c
59
src/lock.c
@@ -294,14 +294,18 @@ struct obj *container; /* passed from obfree() */
|
||||
|
||||
/* player is applying a key, lock pick, or credit card */
|
||||
int
|
||||
pick_lock(pick)
|
||||
pick_lock(pick, rx, ry, container)
|
||||
struct obj *pick;
|
||||
xchar rx, ry; /* coordinates of doors/container, for autounlock: does not
|
||||
prompt for direction if these are set */
|
||||
struct obj *container; /* container, for autounlock */
|
||||
{
|
||||
int picktyp, c, ch;
|
||||
coord cc;
|
||||
struct rm *door;
|
||||
struct obj *otmp;
|
||||
char qbuf[QBUFSZ];
|
||||
boolean autounlock = (rx != 0 && ry != 0) || (container != NULL);
|
||||
|
||||
picktyp = pick->otyp;
|
||||
|
||||
@@ -348,8 +352,13 @@ struct obj *pick;
|
||||
}
|
||||
ch = 0; /* lint suppression */
|
||||
|
||||
if (!get_adjacent_loc((char *) 0, "Invalid location!", u.ux, u.uy, &cc))
|
||||
if (rx != 0 && ry != 0) { /* autounlock; caller has provided coordinates */
|
||||
cc.x = rx;
|
||||
cc.y = ry;
|
||||
}
|
||||
else if (!get_adjacent_loc((char *) 0, "Invalid location!", u.ux, u.uy, &cc)) {
|
||||
return PICKLOCK_DID_NOTHING;
|
||||
}
|
||||
|
||||
if (cc.x == u.ux && cc.y == u.uy) { /* pick lock on a container */
|
||||
const char *verb;
|
||||
@@ -372,7 +381,9 @@ struct obj *pick;
|
||||
count = 0;
|
||||
c = 'n'; /* in case there are no boxes here */
|
||||
for (otmp = g.level.objects[cc.x][cc.y]; otmp; otmp = otmp->nexthere)
|
||||
if (Is_box(otmp)) {
|
||||
/* autounlock on boxes: only the one that just informed you it was
|
||||
* locked. Don't include any other boxes which might be here. */
|
||||
if ((!autounlock && Is_box(otmp)) || (otmp == container)) {
|
||||
++count;
|
||||
if (!can_reach_floor(TRUE)) {
|
||||
You_cant("reach %s from up here.", the(xname(otmp)));
|
||||
@@ -388,17 +399,24 @@ struct obj *pick;
|
||||
else
|
||||
verb = "pick";
|
||||
|
||||
/* "There is <a box> here; <verb> <it|its lock>?" */
|
||||
Sprintf(qsfx, " here; %s %s?", verb, it ? "it" : "its lock");
|
||||
(void) safe_qbuf(qbuf, "There is ", qsfx, otmp, doname,
|
||||
ansimpleoname, "a box");
|
||||
otmp->lknown = 1;
|
||||
if (autounlock) {
|
||||
Sprintf(qbuf, "Unlock it with %s?", yname(pick));
|
||||
c = yn(qbuf);
|
||||
if (c == 'n')
|
||||
return 0;
|
||||
} else {
|
||||
/* "There is <a box> here; <verb> <it|its lock>?" */
|
||||
Sprintf(qsfx, " here; %s %s?", verb, it ? "it" : "its lock");
|
||||
(void) safe_qbuf(qbuf, "There is ", qsfx, otmp, doname,
|
||||
ansimpleoname, "a box");
|
||||
otmp->lknown = 1;
|
||||
|
||||
c = ynq(qbuf);
|
||||
if (c == 'q')
|
||||
return 0;
|
||||
if (c == 'n')
|
||||
continue;
|
||||
c = ynq(qbuf);
|
||||
if (c == 'q')
|
||||
return 0;
|
||||
if (c == 'n')
|
||||
continue;
|
||||
}
|
||||
|
||||
if (otmp->obroken) {
|
||||
You_cant("fix its broken lock with %s.", doname(pick));
|
||||
@@ -484,8 +502,10 @@ struct obj *pick;
|
||||
return PICKLOCK_LEARNED_SOMETHING;
|
||||
}
|
||||
|
||||
Sprintf(qbuf, "%s it?",
|
||||
(door->doormask & D_LOCKED) ? "Unlock" : "Lock");
|
||||
Sprintf(qbuf, "%s it%s%s?",
|
||||
(door->doormask & D_LOCKED) ? "Unlock" : "Lock",
|
||||
autounlock ? " with " : "",
|
||||
autounlock ? yname(pick) : "");
|
||||
|
||||
c = yn(qbuf);
|
||||
if (c == 'n')
|
||||
@@ -685,6 +705,8 @@ int x, y;
|
||||
|
||||
if (!(door->doormask & D_CLOSED)) {
|
||||
const char *mesg;
|
||||
boolean locked = FALSE;
|
||||
struct obj* unlocktool;
|
||||
|
||||
switch (door->doormask) {
|
||||
case D_BROKEN:
|
||||
@@ -698,9 +720,16 @@ int x, y;
|
||||
break;
|
||||
default:
|
||||
mesg = " is locked";
|
||||
locked = TRUE;
|
||||
break;
|
||||
}
|
||||
pline("This door%s.", mesg);
|
||||
if (locked && flags.autounlock &&
|
||||
((unlocktool = carrying(SKELETON_KEY)) ||
|
||||
(unlocktool = carrying(LOCK_PICK)) ||
|
||||
(unlocktool = carrying(CREDIT_CARD)))) {
|
||||
pick_lock(unlocktool, cc.x, cc.y, (struct obj *) 0);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user