more Master Key of Thievery: lock/unlock vs traps
Always find traps when using the rogue's quest Key to lock or unlock a trapped door or chest provided that the Key is not cursed (for rogues) or is blessed (for non-rogues). When a trap is found, the player is given the opportunity to disarm it, and doing so will always succeed. (It isn't disarmed automatically; the player may prefer to leave traps in place, presumably hoping to set up a dangerous bones file. Or he or she may be unaware of the guaranteed success and be too timid to risk trying to disarm the trap.) TODO: make #untrap of a door or chest while carrying that Key always find traps (with same bless/curse requirements as above). And maybe change its #invoke property from untrap to detect unseen/secret door detection since current invoke power would become redundant. Also, move a bunch of new artifact abilities from the fixes section to the new features section in fixes36.1.
This commit is contained in:
@@ -350,14 +350,6 @@ pets start with apport equal to your charisma
|
||||
sometimes generate the random mazes with wide corridors, thick walls,
|
||||
or with dead ends changed to loops
|
||||
put throne room gold in the chest
|
||||
wielding Trollsbane prevents trolls from reviving
|
||||
wielding Demonbane prevents demons summoning friends
|
||||
wielding Dragonbane confers reflection
|
||||
wielding Ogresmasher grants 25 constitution
|
||||
Cleaver can hit three monsters with one swing
|
||||
Master Key of Thievery warns about undetected traps if wielded
|
||||
Elbereth must now be on a square by itself to function
|
||||
Elbereth now erodes based on attacks by the player, not monsters scared
|
||||
novels are made of paper, not gold
|
||||
movement speeds are made less predictable by using random rounding, rather
|
||||
than via adding a random offset
|
||||
@@ -681,6 +673,17 @@ new paranoid_confirm settings: wand-break to require "yes" rather than 'y'
|
||||
option force_invmenu to make commands asking for inventory items always
|
||||
use a menu instead of a text line query
|
||||
option hitpointbar to show a bar graph of hit points behind title field
|
||||
wielding Trollsbane prevents troll corpses from reviving
|
||||
wielding Demonbane prevents demons summoning friends
|
||||
wielding Dragonbane confers reflection
|
||||
wielding Ogresmasher grants 25 constitution
|
||||
Cleaver can hit three adjacent monsters with one swing
|
||||
Master Key of Thievery warns about undetected traps if wielded without gloves
|
||||
Master Key of Thievery always finds door and chest traps if used to lock or
|
||||
unlock a trapped door or chest while non-cursed (for rogues) or
|
||||
blessed (for non-rogues); player is offered the opportunity to disarm
|
||||
"Elbereth" must now be the only engraved text on a square to function
|
||||
"Elbereth" now erodes based on attacks by the player, not monsters scared
|
||||
|
||||
|
||||
Platform- and/or Interface-Specific New Features
|
||||
|
||||
71
src/lock.c
71
src/lock.c
@@ -4,18 +4,21 @@
|
||||
|
||||
#include "hack.h"
|
||||
|
||||
STATIC_PTR int NDECL(picklock);
|
||||
STATIC_PTR int NDECL(forcelock);
|
||||
|
||||
/* at most one of `door' and `box' should be non-null at any given time */
|
||||
STATIC_VAR NEARDATA struct xlock_s {
|
||||
struct rm *door;
|
||||
struct obj *box;
|
||||
int picktyp, /* key|pick|card for unlock, sharp vs blunt for #force */
|
||||
chance, usedtime;
|
||||
boolean magic_key;
|
||||
} xlock;
|
||||
|
||||
/* occupation callbacks */
|
||||
STATIC_PTR int NDECL(picklock);
|
||||
STATIC_PTR int NDECL(forcelock);
|
||||
|
||||
STATIC_DCL const char *NDECL(lock_action);
|
||||
STATIC_DCL boolean FDECL(is_magic_key, (struct monst *, struct obj *));
|
||||
STATIC_DCL boolean FDECL(obstructed, (int, int, BOOLEAN_P));
|
||||
STATIC_DCL void FDECL(chest_shatter_msg, (struct obj *));
|
||||
|
||||
@@ -105,6 +108,40 @@ picklock(VOID_ARGS)
|
||||
if (rn2(100) >= xlock.chance)
|
||||
return 1; /* still busy */
|
||||
|
||||
/* using the Master Key of Thievery finds traps if its bless/curse
|
||||
state is adequate (non-cursed for rogues, blessed for others;
|
||||
checked when setting up 'xlock') */
|
||||
if ((!xlock.door ? (int) xlock.box->otrapped
|
||||
: (xlock.door->doormask & D_TRAPPED) != 0)
|
||||
&& xlock.magic_key) {
|
||||
xlock.chance += 20; /* less effort needed next time */
|
||||
/* unfortunately we don't have a 'tknown' flag to record
|
||||
"known to be trapped" so declining to disarm and then
|
||||
retrying lock manipulation will find it all over again */
|
||||
if (yn("You find a trap! Do you want to try to disarm it?") == 'y') {
|
||||
const char *what;
|
||||
boolean alreadyunlocked;
|
||||
|
||||
/* disarming while using magic key always succeeds */
|
||||
if (xlock.door) {
|
||||
xlock.door->doormask &= ~D_TRAPPED;
|
||||
what = "door";
|
||||
alreadyunlocked = !(xlock.door->doormask & D_LOCKED);
|
||||
} else {
|
||||
xlock.box->otrapped = 0;
|
||||
what = (xlock.box->otyp == CHEST) ? "chest" : "box";
|
||||
alreadyunlocked = !xlock.box->olocked;
|
||||
}
|
||||
You("succeed in disarming the trap. The %s is still %slocked.",
|
||||
what, alreadyunlocked ? "un" : "");
|
||||
exercise(A_WIS, TRUE);
|
||||
} else {
|
||||
You("stop %s.", lock_action());
|
||||
exercise(A_WIS, FALSE);
|
||||
}
|
||||
return ((xlock.usedtime = 0));
|
||||
}
|
||||
|
||||
You("succeed in %s.", lock_action());
|
||||
if (xlock.door) {
|
||||
if (xlock.door->doormask & D_TRAPPED) {
|
||||
@@ -225,6 +262,7 @@ void
|
||||
reset_pick()
|
||||
{
|
||||
xlock.usedtime = xlock.chance = xlock.picktyp = 0;
|
||||
xlock.magic_key = FALSE;
|
||||
xlock.door = 0;
|
||||
xlock.box = 0;
|
||||
}
|
||||
@@ -237,6 +275,21 @@ maybe_reset_pick()
|
||||
reset_pick();
|
||||
}
|
||||
|
||||
/* Master Key is magic key if its bless/curse state meets our criteria:
|
||||
not cursed for rogues or blessed for non-rogues */
|
||||
STATIC_OVL boolean
|
||||
is_magic_key(mon, obj)
|
||||
struct monst *mon; /* if null, non-rogue is assumed */
|
||||
struct obj *obj;
|
||||
{
|
||||
if (((obj && obj->oartifact == ART_MASTER_KEY_OF_THIEVERY)
|
||||
&& ((mon == &youmonst) ? Role_if(PM_ROGUE)
|
||||
: (mon && mon->data == &mons[PM_ROGUE])))
|
||||
? !obj->cursed : obj->blessed)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* for doapply(); if player gives a direction or resumes an interrupted
|
||||
previous attempt then it costs hero a move even if nothing ultimately
|
||||
happens; when told "can't do that" before being asked for direction
|
||||
@@ -264,6 +317,7 @@ struct obj *pick;
|
||||
|
||||
if (nohands(youmonst.data)) {
|
||||
const char *what = (picktyp == LOCK_PICK) ? "pick" : "key";
|
||||
|
||||
if (picktyp == CREDIT_CARD)
|
||||
what = "card";
|
||||
pline(no_longer, "hold the", what);
|
||||
@@ -277,6 +331,7 @@ struct obj *pick;
|
||||
const char *action = lock_action();
|
||||
|
||||
You("resume your attempt at %s.", action);
|
||||
xlock.magic_key = is_magic_key(&youmonst, pick);
|
||||
set_occupation(picklock, action, 0);
|
||||
return PICKLOCK_DID_SOMETHING;
|
||||
}
|
||||
@@ -291,8 +346,9 @@ struct obj *pick;
|
||||
return PICKLOCK_DID_NOTHING;
|
||||
}
|
||||
|
||||
if ((picktyp != LOCK_PICK && picktyp != CREDIT_CARD
|
||||
&& picktyp != SKELETON_KEY)) {
|
||||
if (picktyp != LOCK_PICK
|
||||
&& picktyp != CREDIT_CARD
|
||||
&& picktyp != SKELETON_KEY) {
|
||||
impossible("picking lock with object %d?", picktyp);
|
||||
return PICKLOCK_DID_NOTHING;
|
||||
}
|
||||
@@ -375,7 +431,6 @@ struct obj *pick;
|
||||
if (otmp->cursed)
|
||||
ch /= 2;
|
||||
|
||||
xlock.picktyp = picktyp;
|
||||
xlock.box = otmp;
|
||||
xlock.door = 0;
|
||||
break;
|
||||
@@ -407,7 +462,7 @@ struct obj *pick;
|
||||
} else if (mtmp && is_door_mappear(mtmp)) {
|
||||
/* "The door actually was a <mimic>!" */
|
||||
stumble_onto_mimic(mtmp);
|
||||
/* mimic might keep the key (50% chance, 10% for PYEC) */
|
||||
/* mimic might keep the key (50% chance, 10% for PYEC or MKoT) */
|
||||
maybe_absorb_item(mtmp, pick, 50, 10);
|
||||
return PICKLOCK_LEARNED_SOMETHING;
|
||||
}
|
||||
@@ -462,6 +517,7 @@ struct obj *pick;
|
||||
context.move = 0;
|
||||
xlock.chance = ch;
|
||||
xlock.picktyp = picktyp;
|
||||
xlock.magic_key = is_magic_key(&youmonst, pick);
|
||||
xlock.usedtime = 0;
|
||||
set_occupation(picklock, lock_action(), 0);
|
||||
return PICKLOCK_DID_SOMETHING;
|
||||
@@ -531,6 +587,7 @@ doforce()
|
||||
xlock.box = otmp;
|
||||
xlock.chance = objects[uwep->otyp].oc_wldam * 2;
|
||||
xlock.picktyp = picktyp;
|
||||
xlock.magic_key = FALSE;
|
||||
xlock.usedtime = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user