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)
|
the first gift; artifacts you can't use well are less likely)
|
||||||
luck gains from sacrificing are limited by the value of the sacrifice
|
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
|
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
|
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
|
| eroded | int | Object erosion
|
||||||
| locked | boolean | Is the object locked?
|
| locked | boolean | Is the object locked?
|
||||||
| trapped | boolean | Is the object trapped?
|
| trapped | boolean | Is the object trapped?
|
||||||
|
| trap_known | boolean | If container is trapped, is it obvious?
|
||||||
| recharged | boolean | Is the object recharged?
|
| recharged | boolean | Is the object recharged?
|
||||||
| greased | boolean | Is the object greased?
|
| greased | boolean | Is the object greased?
|
||||||
| broken | boolean | Is the object broken?
|
| broken | boolean | Is the object broken?
|
||||||
|
|||||||
+1
-1
@@ -141,9 +141,9 @@ struct obj {
|
|||||||
* they have no locks */
|
* they have no locks */
|
||||||
Bitfield(pickup_prev, 1); /* was picked up previously */
|
Bitfield(pickup_prev, 1); /* was picked up previously */
|
||||||
Bitfield(ghostly, 1); /* it just got placed into a bones file */
|
Bitfield(ghostly, 1); /* it just got placed into a bones file */
|
||||||
|
Bitfield(tknown, 1); /* trap status known for chests */
|
||||||
#if 0
|
#if 0
|
||||||
/* not implemented */
|
/* not implemented */
|
||||||
Bitfield(tknown, 1); /* trap status known for chests */
|
|
||||||
Bitfield(eknown, 1); /* effect known for wands zapped or rings worn when
|
Bitfield(eknown, 1); /* effect known for wands zapped or rings worn when
|
||||||
* not seen yet after being picked up while blind
|
* not seen yet after being picked up while blind
|
||||||
* [maybe for remaining stack of used potion too] */
|
* [maybe for remaining stack of used potion too] */
|
||||||
|
|||||||
@@ -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 112
|
#define EDITLEVEL 113
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Development status possibilities.
|
* Development status possibilities.
|
||||||
|
|||||||
+1
-1
@@ -156,7 +156,7 @@ typedef struct {
|
|||||||
int quan;
|
int quan;
|
||||||
short buried;
|
short buried;
|
||||||
short lit;
|
short lit;
|
||||||
short eroded, locked, trapped, recharged, invis, greased, broken,
|
short eroded, locked, trapped, tknown, recharged, invis, greased, broken,
|
||||||
achievement;
|
achievement;
|
||||||
} object;
|
} object;
|
||||||
|
|
||||||
|
|||||||
@@ -930,6 +930,8 @@ detect_obj_traps(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (Is_box(otmp) && otmp->otrapped) {
|
if (Is_box(otmp) && otmp->otrapped) {
|
||||||
|
otmp->tknown = 1;
|
||||||
|
otmp->dknown = 1;
|
||||||
result |= u_at(x, y) ? OTRAP_HERE : OTRAP_THERE;
|
result |= u_at(x, y) ? OTRAP_HERE : OTRAP_THERE;
|
||||||
if (ft) {
|
if (ft) {
|
||||||
flash_glyph_at(x, y, trapglyph, FOUND_FLASH_COUNT);
|
flash_glyph_at(x, y, trapglyph, FOUND_FLASH_COUNT);
|
||||||
|
|||||||
+7
-5
@@ -105,11 +105,12 @@ picklock(void)
|
|||||||
: (gx.xlock.door->doormask & D_TRAPPED) != 0)
|
: (gx.xlock.door->doormask & D_TRAPPED) != 0)
|
||||||
&& gx.xlock.magic_key) {
|
&& gx.xlock.magic_key) {
|
||||||
gx.xlock.chance += 20; /* less effort needed next time */
|
gx.xlock.chance += 20; /* less effort needed next time */
|
||||||
/* unfortunately we don't have a 'tknown' flag to record
|
if (!gx.xlock.door) {
|
||||||
"known to be trapped" so declining to disarm and then
|
if (!gx.xlock.box->tknown)
|
||||||
retrying lock manipulation will find it all over again */
|
You("find a trap!");
|
||||||
if (y_n("You find a trap! Do you want to try to disarm it?")
|
gx.xlock.box->tknown = 1;
|
||||||
== 'y') {
|
}
|
||||||
|
if (y_n("Do you want to try to disarm it?") == 'y') {
|
||||||
const char *what;
|
const char *what;
|
||||||
boolean alreadyunlocked;
|
boolean alreadyunlocked;
|
||||||
|
|
||||||
@@ -120,6 +121,7 @@ picklock(void)
|
|||||||
alreadyunlocked = !(gx.xlock.door->doormask & D_LOCKED);
|
alreadyunlocked = !(gx.xlock.door->doormask & D_LOCKED);
|
||||||
} else {
|
} else {
|
||||||
gx.xlock.box->otrapped = 0;
|
gx.xlock.box->otrapped = 0;
|
||||||
|
gx.xlock.box->tknown = 0;
|
||||||
what = (gx.xlock.box->otyp == CHEST) ? "chest" : "box";
|
what = (gx.xlock.box->otyp == CHEST) ? "chest" : "box";
|
||||||
alreadyunlocked = !gx.xlock.box->olocked;
|
alreadyunlocked = !gx.xlock.box->olocked;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -852,6 +852,7 @@ unknow_object(struct obj *obj)
|
|||||||
|
|
||||||
obj->bknown = obj->rknown = 0;
|
obj->bknown = obj->rknown = 0;
|
||||||
obj->cknown = obj->lknown = 0;
|
obj->cknown = obj->lknown = 0;
|
||||||
|
obj->tknown = 0;
|
||||||
/* for an existing object, awareness of charges or enchantment has
|
/* for an existing object, awareness of charges or enchantment has
|
||||||
gone poof... [object types which don't use the known flag have
|
gone poof... [object types which don't use the known flag have
|
||||||
it set True for some reason] */
|
it set True for some reason] */
|
||||||
@@ -1000,6 +1001,7 @@ mksobj_init(struct obj *otmp, boolean artif)
|
|||||||
case LARGE_BOX:
|
case LARGE_BOX:
|
||||||
otmp->olocked = !!(rn2(5));
|
otmp->olocked = !!(rn2(5));
|
||||||
otmp->otrapped = !(rn2(10));
|
otmp->otrapped = !(rn2(10));
|
||||||
|
otmp->tknown = otmp->otrapped && !rn2(100); /* obvious trap */
|
||||||
FALLTHROUGH;
|
FALLTHROUGH;
|
||||||
/*FALLTHRU*/
|
/*FALLTHRU*/
|
||||||
case ICE_BOX:
|
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, "dknown", obj->dknown);
|
||||||
nhl_add_table_entry_int(L, "bknown", obj->bknown);
|
nhl_add_table_entry_int(L, "bknown", obj->bknown);
|
||||||
nhl_add_table_entry_int(L, "rknown", obj->rknown);
|
nhl_add_table_entry_int(L, "rknown", obj->rknown);
|
||||||
|
nhl_add_table_entry_int(L, "tknown", obj->tknown);
|
||||||
if (obj->oclass == POTION_CLASS)
|
if (obj->oclass == POTION_CLASS)
|
||||||
nhl_add_table_entry_int(L, "odiluted", obj->odiluted);
|
nhl_add_table_entry_int(L, "odiluted", obj->odiluted);
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -1334,6 +1334,9 @@ doname_base(
|
|||||||
Strcat(prefix, "uncursed ");
|
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 (lknown && Is_box(obj)) {
|
||||||
if (obj->obroken)
|
if (obj->obroken)
|
||||||
/* 3.6.0 used "unlockable" here but that could be misunderstood
|
/* 3.6.0 used "unlockable" here but that could be misunderstood
|
||||||
|
|||||||
+5
-1
@@ -2277,6 +2277,8 @@ create_object(object *o, struct mkroom *croom)
|
|||||||
}
|
}
|
||||||
if (o->trapped == 0 || o->trapped == 1)
|
if (o->trapped == 0 || o->trapped == 1)
|
||||||
otmp->otrapped = o->trapped;
|
otmp->otrapped = o->trapped;
|
||||||
|
if (o->trapped && (o->tknown == 0 || o->tknown == 1))
|
||||||
|
otmp->tknown = o->tknown;
|
||||||
otmp->greased = o->greased ? 1 : 0;
|
otmp->greased = o->greased ? 1 : 0;
|
||||||
|
|
||||||
if (o->quan > 0 && objects[otmp->otyp].oc_merge) {
|
if (o->quan > 0 && objects[otmp->otyp].oc_merge) {
|
||||||
@@ -3517,7 +3519,7 @@ lspo_object(lua_State *L)
|
|||||||
0, /* quan */
|
0, /* quan */
|
||||||
0, /* buried */
|
0, /* buried */
|
||||||
0, /* lit */
|
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 */
|
0, 0, 0, 0, /* invis, greased, broken, achievement */
|
||||||
};
|
};
|
||||||
#if 0
|
#if 0
|
||||||
@@ -3537,6 +3539,7 @@ lspo_object(lua_State *L)
|
|||||||
tmpobj.spe = -127;
|
tmpobj.spe = -127;
|
||||||
tmpobj.quan = -1;
|
tmpobj.quan = -1;
|
||||||
tmpobj.trapped = -1;
|
tmpobj.trapped = -1;
|
||||||
|
tmpobj.tknown = -1;
|
||||||
tmpobj.locked = -1;
|
tmpobj.locked = -1;
|
||||||
tmpobj.corpsenm = NON_PM;
|
tmpobj.corpsenm = NON_PM;
|
||||||
|
|
||||||
@@ -3590,6 +3593,7 @@ lspo_object(lua_State *L)
|
|||||||
tmpobj.eroded = get_table_int_opt(L, "eroded", 0);
|
tmpobj.eroded = get_table_int_opt(L, "eroded", 0);
|
||||||
tmpobj.locked = get_table_boolean_opt(L, "locked", -1);
|
tmpobj.locked = get_table_boolean_opt(L, "locked", -1);
|
||||||
tmpobj.trapped = get_table_boolean_opt(L, "trapped", -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.recharged = get_table_int_opt(L, "recharged", 0);
|
||||||
tmpobj.greased = get_table_boolean_opt(L, "greased", 0);
|
tmpobj.greased = get_table_boolean_opt(L, "greased", 0);
|
||||||
tmpobj.broken = get_table_boolean_opt(L, "broken", 0);
|
tmpobj.broken = get_table_boolean_opt(L, "broken", 0);
|
||||||
|
|||||||
+50
-27
@@ -65,6 +65,7 @@ staticfn void clear_conjoined_pits(struct trap *);
|
|||||||
staticfn boolean adj_nonconjoined_pit(struct trap *);
|
staticfn boolean adj_nonconjoined_pit(struct trap *);
|
||||||
staticfn int try_lift(struct monst *, struct trap *, int, boolean);
|
staticfn int try_lift(struct monst *, struct trap *, int, boolean);
|
||||||
staticfn int help_monster_out(struct monst *, struct trap *);
|
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);
|
staticfn void untrap_box(struct obj *, boolean, boolean);
|
||||||
#if 0
|
#if 0
|
||||||
staticfn void join_adjacent_pits(struct trap *);
|
staticfn void join_adjacent_pits(struct trap *);
|
||||||
@@ -5687,6 +5688,32 @@ help_monster_out(
|
|||||||
return 1;
|
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 */
|
/* check a particular container for a trap and optionally disarm it */
|
||||||
staticfn void
|
staticfn void
|
||||||
untrap_box(
|
untrap_box(
|
||||||
@@ -5696,32 +5723,19 @@ untrap_box(
|
|||||||
{
|
{
|
||||||
if ((box->otrapped
|
if ((box->otrapped
|
||||||
&& (force || (!confused && rn2(MAXULEV + 1 - u.ulevel) < 10)))
|
&& (force || (!confused && rn2(MAXULEV + 1 - u.ulevel) < 10)))
|
||||||
|
|| box->tknown
|
||||||
|| (!force && confused && !rn2(3))) {
|
|| (!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)
|
if (!confused)
|
||||||
exercise(A_WIS, TRUE);
|
exercise(A_WIS, TRUE);
|
||||||
|
|
||||||
if (ynq("Disarm it?") == 'y') {
|
if (ynq("Disarm it?") == 'y')
|
||||||
if (box->otrapped) {
|
disarm_box(box, force, confused);
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
You("find no traps on %s.", the(xname(box)));
|
You("find no traps on %s.", the(xname(box)));
|
||||||
}
|
}
|
||||||
@@ -5882,20 +5896,28 @@ untrap(
|
|||||||
whether any had been found but not attempted to untrap;
|
whether any had been found but not attempted to untrap;
|
||||||
now at most one per move may be checked and we only
|
now at most one per move may be checked and we only
|
||||||
continue on to door handling if they are all declined */
|
continue on to door handling if they are all declined */
|
||||||
for (otmp = svl.level.objects[x][y]; otmp; otmp = otmp->nexthere)
|
for (otmp = svl.level.objects[x][y]; otmp; otmp = otmp->nexthere) {
|
||||||
if (Is_box(otmp)) {
|
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 ",
|
(void) safe_qbuf(qbuf, "There is ",
|
||||||
" here. Check it for traps?", otmp,
|
" here. Check it for traps?", otmp,
|
||||||
doname, ansimpleoname, "a box");
|
doname, ansimpleoname, "a box");
|
||||||
switch (ynq(qbuf)) {
|
switch (ynq(qbuf)) {
|
||||||
case 'q':
|
case 'q':
|
||||||
return 0;
|
return 0;
|
||||||
case 'y':
|
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 */
|
return 1; /* even for 'no' at "Disarm it?" prompt */
|
||||||
}
|
}
|
||||||
/* 'n' => continue to next box */
|
/* 'n' => continue to next box */
|
||||||
}
|
}
|
||||||
There("are no other chests or boxes here.");
|
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 */
|
if (get_obj_location(obj, &cc.x, &cc.y, 0)) /* might be carried */
|
||||||
obj->ox = cc.x, obj->oy = cc.y;
|
obj->ox = cc.x, obj->oy = cc.y;
|
||||||
|
|
||||||
|
otmp->tknown = 0;
|
||||||
otmp->otrapped = 0; /* trap is one-shot; clear flag first in case
|
otmp->otrapped = 0; /* trap is one-shot; clear flag first in case
|
||||||
chest kills you and ends up in bones file */
|
chest kills you and ends up in bones file */
|
||||||
You(disarm ? "set it off!" : "trigger a trap!");
|
You(disarm ? "set it off!" : "trigger a trap!");
|
||||||
|
|||||||
Reference in New Issue
Block a user