Hero remembers trapped boxes
After finding a trap on a chest or a large box, remember it as trapped: "You see here a trapped large box." Randomly generated chests and boxes can be obviously trapped. Allow defining obviously trapped containers via lua. Invalidates saves and bones.
This commit is contained in:
@@ -1492,6 +1492,7 @@ artifact gifts are rebalanced (easier to obtain; higher-value sacrifices are
|
||||
the first gift; artifacts you can't use well are less likely)
|
||||
luck gains from sacrificing are limited by the value of the sacrifice
|
||||
failed #untrap could move hero diagonally into or out of an open doorway
|
||||
remember box is trapped after finding the trap
|
||||
|
||||
|
||||
Fixes to 3.7.0-x General Problems Exposed Via git Repository
|
||||
|
||||
@@ -849,6 +849,7 @@ The table parameter accepts the following:
|
||||
| eroded | int | Object erosion
|
||||
| locked | boolean | Is the object locked?
|
||||
| trapped | boolean | Is the object trapped?
|
||||
| trap_known | boolean | If container is trapped, is it obvious?
|
||||
| recharged | boolean | Is the object recharged?
|
||||
| greased | boolean | Is the object greased?
|
||||
| broken | boolean | Is the object broken?
|
||||
|
||||
@@ -141,9 +141,9 @@ struct obj {
|
||||
* they have no locks */
|
||||
Bitfield(pickup_prev, 1); /* was picked up previously */
|
||||
Bitfield(ghostly, 1); /* it just got placed into a bones file */
|
||||
Bitfield(tknown, 1); /* trap status known for chests */
|
||||
#if 0
|
||||
/* not implemented */
|
||||
Bitfield(tknown, 1); /* trap status known for chests */
|
||||
Bitfield(eknown, 1); /* effect known for wands zapped or rings worn when
|
||||
* not seen yet after being picked up while blind
|
||||
* [maybe for remaining stack of used potion too] */
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* Incrementing EDITLEVEL can be used to force invalidation of old bones
|
||||
* and save files.
|
||||
*/
|
||||
#define EDITLEVEL 112
|
||||
#define EDITLEVEL 113
|
||||
|
||||
/*
|
||||
* Development status possibilities.
|
||||
|
||||
@@ -156,7 +156,7 @@ typedef struct {
|
||||
int quan;
|
||||
short buried;
|
||||
short lit;
|
||||
short eroded, locked, trapped, recharged, invis, greased, broken,
|
||||
short eroded, locked, trapped, tknown, recharged, invis, greased, broken,
|
||||
achievement;
|
||||
} object;
|
||||
|
||||
|
||||
@@ -930,6 +930,8 @@ detect_obj_traps(
|
||||
continue;
|
||||
}
|
||||
if (Is_box(otmp) && otmp->otrapped) {
|
||||
otmp->tknown = 1;
|
||||
otmp->dknown = 1;
|
||||
result |= u_at(x, y) ? OTRAP_HERE : OTRAP_THERE;
|
||||
if (ft) {
|
||||
flash_glyph_at(x, y, trapglyph, FOUND_FLASH_COUNT);
|
||||
|
||||
12
src/lock.c
12
src/lock.c
@@ -105,11 +105,12 @@ picklock(void)
|
||||
: (gx.xlock.door->doormask & D_TRAPPED) != 0)
|
||||
&& gx.xlock.magic_key) {
|
||||
gx.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 (y_n("You find a trap! Do you want to try to disarm it?")
|
||||
== 'y') {
|
||||
if (!gx.xlock.door) {
|
||||
if (!gx.xlock.box->tknown)
|
||||
You("find a trap!");
|
||||
gx.xlock.box->tknown = 1;
|
||||
}
|
||||
if (y_n("Do you want to try to disarm it?") == 'y') {
|
||||
const char *what;
|
||||
boolean alreadyunlocked;
|
||||
|
||||
@@ -120,6 +121,7 @@ picklock(void)
|
||||
alreadyunlocked = !(gx.xlock.door->doormask & D_LOCKED);
|
||||
} else {
|
||||
gx.xlock.box->otrapped = 0;
|
||||
gx.xlock.box->tknown = 0;
|
||||
what = (gx.xlock.box->otyp == CHEST) ? "chest" : "box";
|
||||
alreadyunlocked = !gx.xlock.box->olocked;
|
||||
}
|
||||
|
||||
@@ -852,6 +852,7 @@ unknow_object(struct obj *obj)
|
||||
|
||||
obj->bknown = obj->rknown = 0;
|
||||
obj->cknown = obj->lknown = 0;
|
||||
obj->tknown = 0;
|
||||
/* for an existing object, awareness of charges or enchantment has
|
||||
gone poof... [object types which don't use the known flag have
|
||||
it set True for some reason] */
|
||||
@@ -1000,6 +1001,7 @@ mksobj_init(struct obj *otmp, boolean artif)
|
||||
case LARGE_BOX:
|
||||
otmp->olocked = !!(rn2(5));
|
||||
otmp->otrapped = !(rn2(10));
|
||||
otmp->tknown = otmp->otrapped && !rn2(100); /* obvious trap */
|
||||
FALLTHROUGH;
|
||||
/*FALLTHRU*/
|
||||
case ICE_BOX:
|
||||
|
||||
@@ -295,6 +295,7 @@ l_obj_to_table(lua_State *L)
|
||||
nhl_add_table_entry_int(L, "dknown", obj->dknown);
|
||||
nhl_add_table_entry_int(L, "bknown", obj->bknown);
|
||||
nhl_add_table_entry_int(L, "rknown", obj->rknown);
|
||||
nhl_add_table_entry_int(L, "tknown", obj->tknown);
|
||||
if (obj->oclass == POTION_CLASS)
|
||||
nhl_add_table_entry_int(L, "odiluted", obj->odiluted);
|
||||
else
|
||||
|
||||
@@ -1334,6 +1334,9 @@ doname_base(
|
||||
Strcat(prefix, "uncursed ");
|
||||
}
|
||||
|
||||
/* "a large trapped box" would perhaps be more correct */
|
||||
if (Is_box(obj) && obj->otrapped && obj->tknown && obj->dknown)
|
||||
Strcat(prefix,"trapped ");
|
||||
if (lknown && Is_box(obj)) {
|
||||
if (obj->obroken)
|
||||
/* 3.6.0 used "unlockable" here but that could be misunderstood
|
||||
|
||||
@@ -2277,6 +2277,8 @@ create_object(object *o, struct mkroom *croom)
|
||||
}
|
||||
if (o->trapped == 0 || o->trapped == 1)
|
||||
otmp->otrapped = o->trapped;
|
||||
if (o->trapped && (o->tknown == 0 || o->tknown == 1))
|
||||
otmp->tknown = o->tknown;
|
||||
otmp->greased = o->greased ? 1 : 0;
|
||||
|
||||
if (o->quan > 0 && objects[otmp->otyp].oc_merge) {
|
||||
@@ -3517,7 +3519,7 @@ lspo_object(lua_State *L)
|
||||
0, /* quan */
|
||||
0, /* buried */
|
||||
0, /* lit */
|
||||
0, 0, 0, 0, /* eroded, locked, trapped, recharged */
|
||||
0, 0, 0, 0, 0, /* eroded, locked, trapped, tknown, recharged */
|
||||
0, 0, 0, 0, /* invis, greased, broken, achievement */
|
||||
};
|
||||
#if 0
|
||||
@@ -3537,6 +3539,7 @@ lspo_object(lua_State *L)
|
||||
tmpobj.spe = -127;
|
||||
tmpobj.quan = -1;
|
||||
tmpobj.trapped = -1;
|
||||
tmpobj.tknown = -1;
|
||||
tmpobj.locked = -1;
|
||||
tmpobj.corpsenm = NON_PM;
|
||||
|
||||
@@ -3590,6 +3593,7 @@ lspo_object(lua_State *L)
|
||||
tmpobj.eroded = get_table_int_opt(L, "eroded", 0);
|
||||
tmpobj.locked = get_table_boolean_opt(L, "locked", -1);
|
||||
tmpobj.trapped = get_table_boolean_opt(L, "trapped", -1);
|
||||
tmpobj.tknown = get_table_boolean_opt(L, "trap_known", -1);
|
||||
tmpobj.recharged = get_table_int_opt(L, "recharged", 0);
|
||||
tmpobj.greased = get_table_boolean_opt(L, "greased", 0);
|
||||
tmpobj.broken = get_table_boolean_opt(L, "broken", 0);
|
||||
|
||||
77
src/trap.c
77
src/trap.c
@@ -65,6 +65,7 @@ staticfn void clear_conjoined_pits(struct trap *);
|
||||
staticfn boolean adj_nonconjoined_pit(struct trap *);
|
||||
staticfn int try_lift(struct monst *, struct trap *, int, boolean);
|
||||
staticfn int help_monster_out(struct monst *, struct trap *);
|
||||
staticfn void disarm_box(struct obj *, boolean, boolean);
|
||||
staticfn void untrap_box(struct obj *, boolean, boolean);
|
||||
#if 0
|
||||
staticfn void join_adjacent_pits(struct trap *);
|
||||
@@ -5687,6 +5688,32 @@ help_monster_out(
|
||||
return 1;
|
||||
}
|
||||
|
||||
staticfn void
|
||||
disarm_box(struct obj *box, boolean force, boolean confused)
|
||||
{
|
||||
if (box->otrapped) {
|
||||
int ch = ACURR(A_DEX) + u.ulevel;
|
||||
|
||||
if (Role_if(PM_ROGUE))
|
||||
ch *= 2;
|
||||
if (!force && (confused || Fumbling
|
||||
|| rnd(75 + level_difficulty() / 2) > ch)) {
|
||||
(void) chest_trap(box, FINGER, TRUE);
|
||||
/* 'box' might be gone now */
|
||||
} else {
|
||||
You("disarm it!");
|
||||
box->otrapped = 0;
|
||||
box->tknown = 0;
|
||||
more_experienced(8, 0);
|
||||
newexplevel();
|
||||
}
|
||||
exercise(A_DEX, TRUE);
|
||||
} else {
|
||||
pline("That %s was not trapped.", xname(box));
|
||||
box->tknown = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* check a particular container for a trap and optionally disarm it */
|
||||
staticfn void
|
||||
untrap_box(
|
||||
@@ -5696,32 +5723,19 @@ untrap_box(
|
||||
{
|
||||
if ((box->otrapped
|
||||
&& (force || (!confused && rn2(MAXULEV + 1 - u.ulevel) < 10)))
|
||||
|| box->tknown
|
||||
|| (!force && confused && !rn2(3))) {
|
||||
You("find a trap on %s!", the(xname(box)));
|
||||
if (!(box->tknown && box->dknown))
|
||||
You("find a trap on %s!", the(xname(box)));
|
||||
else
|
||||
pline("There's a trap on %s.", the(xname(box)));
|
||||
box->tknown = 1;
|
||||
box->dknown = 1;
|
||||
if (!confused)
|
||||
exercise(A_WIS, TRUE);
|
||||
|
||||
if (ynq("Disarm it?") == 'y') {
|
||||
if (box->otrapped) {
|
||||
int ch = ACURR(A_DEX) + u.ulevel;
|
||||
|
||||
if (Role_if(PM_ROGUE))
|
||||
ch *= 2;
|
||||
if (!force && (confused || Fumbling
|
||||
|| rnd(75 + level_difficulty() / 2) > ch)) {
|
||||
(void) chest_trap(box, FINGER, TRUE);
|
||||
/* 'box' might be gone now */
|
||||
} else {
|
||||
You("disarm it!");
|
||||
box->otrapped = 0;
|
||||
more_experienced(8, 0);
|
||||
newexplevel();
|
||||
}
|
||||
exercise(A_DEX, TRUE);
|
||||
} else {
|
||||
pline("That %s was not trapped.", xname(box));
|
||||
}
|
||||
}
|
||||
if (ynq("Disarm it?") == 'y')
|
||||
disarm_box(box, force, confused);
|
||||
} else {
|
||||
You("find no traps on %s.", the(xname(box)));
|
||||
}
|
||||
@@ -5882,20 +5896,28 @@ untrap(
|
||||
whether any had been found but not attempted to untrap;
|
||||
now at most one per move may be checked and we only
|
||||
continue on to door handling if they are all declined */
|
||||
for (otmp = svl.level.objects[x][y]; otmp; otmp = otmp->nexthere)
|
||||
if (Is_box(otmp)) {
|
||||
for (otmp = svl.level.objects[x][y]; otmp; otmp = otmp->nexthere) {
|
||||
if (!Is_box(otmp))
|
||||
continue;
|
||||
if (otmp->tknown && otmp->dknown)
|
||||
(void) safe_qbuf(qbuf, "Disarm this ", NULL,
|
||||
otmp, xname, ansimpleoname, "a box");
|
||||
else
|
||||
(void) safe_qbuf(qbuf, "There is ",
|
||||
" here. Check it for traps?", otmp,
|
||||
doname, ansimpleoname, "a box");
|
||||
switch (ynq(qbuf)) {
|
||||
switch (ynq(qbuf)) {
|
||||
case 'q':
|
||||
return 0;
|
||||
case 'y':
|
||||
untrap_box(otmp, force, confused);
|
||||
if (otmp->tknown && otmp->dknown)
|
||||
disarm_box(otmp, force, confused);
|
||||
else
|
||||
untrap_box(otmp, force, confused);
|
||||
return 1; /* even for 'no' at "Disarm it?" prompt */
|
||||
}
|
||||
/* 'n' => continue to next box */
|
||||
}
|
||||
}
|
||||
There("are no other chests or boxes here.");
|
||||
}
|
||||
|
||||
@@ -6170,6 +6192,7 @@ chest_trap(
|
||||
if (get_obj_location(obj, &cc.x, &cc.y, 0)) /* might be carried */
|
||||
obj->ox = cc.x, obj->oy = cc.y;
|
||||
|
||||
otmp->tknown = 0;
|
||||
otmp->otrapped = 0; /* trap is one-shot; clear flag first in case
|
||||
chest kills you and ends up in bones file */
|
||||
You(disarm ? "set it off!" : "trigger a trap!");
|
||||
|
||||
Reference in New Issue
Block a user