follow-up related to #1320
This is additional groundwork related to https://github.com/NetHack/NetHack/issues/1320 This additional groundwork just puts some safeguards in place to make it rather tough to end up with an instant death from handling a cockatrice corpse in your inventory without appropriate protection. At this point, still no actual petrification will occur.
This commit is contained in:
22
src/do.c
22
src/do.c
@@ -20,8 +20,9 @@ staticfn NHFILE *currentlevel_rewrite(void);
|
||||
staticfn void familiar_level_msg(void);
|
||||
staticfn void final_level(void);
|
||||
staticfn void temperature_change_msg(schar);
|
||||
staticfn boolean better_not_try_to_drop_that(struct obj *);
|
||||
|
||||
/* static boolean badspot(coordxy,coordxy); */
|
||||
/* static boolean badspot(coordxy,coordxy); */
|
||||
|
||||
/* the #drop command: drop one inventory item */
|
||||
int
|
||||
@@ -709,6 +710,8 @@ drop(struct obj *obj)
|
||||
return ECMD_FAIL;
|
||||
if (!canletgo(obj, "drop"))
|
||||
return ECMD_FAIL;
|
||||
if (obj->otyp == CORPSE && better_not_try_to_drop_that(obj))
|
||||
return ECMD_FAIL;
|
||||
if (obj == uwep) {
|
||||
if (welded(uwep)) {
|
||||
weldmsg(obj);
|
||||
@@ -933,6 +936,23 @@ doddrop(void)
|
||||
return result;
|
||||
}
|
||||
|
||||
staticfn boolean
|
||||
better_not_try_to_drop_that(struct obj *otmp)
|
||||
{
|
||||
char buf[BUFSZ];
|
||||
|
||||
/* u_safe_from_fatal_corpse() with 0xF checks for gloves and stoning
|
||||
* resistance before bothering to prompt you.
|
||||
*/
|
||||
if (otmp->otyp == CORPSE && !u_safe_from_fatal_corpse(otmp, 0xF)) {
|
||||
Snprintf(
|
||||
buf, sizeof buf,
|
||||
"Drop the %s corpse without any protection while handling it?",
|
||||
obj_pmname(otmp));
|
||||
return (paranoid_ynq(TRUE, buf, FALSE) != 'y');
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
staticfn int /* check callers */
|
||||
menudrop_split(struct obj *otmp, long cnt)
|
||||
{
|
||||
|
||||
@@ -52,6 +52,7 @@ staticfn int takeoff_ok(struct obj *);
|
||||
/* maybe_destroy_armor() may return NULL */
|
||||
staticfn struct obj *maybe_destroy_armor(struct obj *, struct obj *,
|
||||
boolean *) NONNULLARG3;
|
||||
staticfn boolean better_not_take_that_off(struct obj *) NONNULLARG1;
|
||||
|
||||
/* plural "fingers" or optionally "gloves" */
|
||||
const char *
|
||||
@@ -2641,6 +2642,8 @@ select_off(struct obj *otmp)
|
||||
gloves_simple_name(uarmg));
|
||||
return 0;
|
||||
}
|
||||
if (better_not_take_that_off(otmp))
|
||||
return 0;
|
||||
}
|
||||
/* special boot checks */
|
||||
if (otmp == uarmf) {
|
||||
@@ -2886,6 +2889,26 @@ take_off(void)
|
||||
return 1; /* get busy */
|
||||
}
|
||||
|
||||
staticfn boolean
|
||||
better_not_take_that_off(struct obj *otmp)
|
||||
{
|
||||
struct obj *corpse = carrying_stoning_corpse();
|
||||
char buf[BUFSZ];
|
||||
|
||||
/* u_safe_from_fatal_corpse() with 0x4e instead of 0x6
|
||||
would also check for no stoning resistance before
|
||||
bothering to prompt, but losing stoning resistance
|
||||
later, without the gloves on could prove dangerous,
|
||||
so we won't factor that in */
|
||||
if (corpse && !u_safe_from_fatal_corpse(corpse, 0x6)) {
|
||||
Snprintf(buf, sizeof buf,
|
||||
"Take off your %s despite carrying a dead %s?",
|
||||
gloves_simple_name(otmp), obj_pmname(corpse));
|
||||
return (paranoid_ynq(TRUE, buf, FALSE) != 'y');
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* clear saved context to avoid inappropriate resumption of interrupted 'A' */
|
||||
void
|
||||
reset_remarm(void)
|
||||
|
||||
15
src/invent.c
15
src/invent.c
@@ -49,6 +49,7 @@ staticfn void ia_addmenu(winid, int, char, const char *);
|
||||
staticfn void itemactions_pushkeys(struct obj *, int);
|
||||
staticfn int itemactions(struct obj *);
|
||||
staticfn int dispinv_with_action(char *, boolean, const char *);
|
||||
staticfn struct obj *carrying_cockatrice_corpse(void);
|
||||
|
||||
/* enum and structs are defined in wintype.h */
|
||||
static win_request_info wri_info;
|
||||
@@ -1231,7 +1232,7 @@ hold_another_object(
|
||||
obj = addinv_core0(obj, (struct obj *) 0, FALSE);
|
||||
goto drop_it;
|
||||
} else if (obj->otyp == CORPSE
|
||||
&& !u_safe_from_fatal_corpse(obj)
|
||||
&& !u_safe_from_fatal_corpse(obj, 0xF)
|
||||
&& obj->wishedfor) {
|
||||
obj->wishedfor = 0;
|
||||
obj = addinv_core0(obj, (struct obj *) 0, FALSE);
|
||||
@@ -1480,6 +1481,18 @@ carrying(int type)
|
||||
return otmp;
|
||||
}
|
||||
|
||||
/* return inventory object of type that will petrify on touch */
|
||||
struct obj *
|
||||
carrying_stoning_corpse(void)
|
||||
{
|
||||
struct obj *otmp;
|
||||
|
||||
for (otmp = gi.invent; otmp; otmp = otmp->nobj)
|
||||
if (otmp->otyp == CORPSE && touch_petrifies(&mons[otmp->corpsenm]))
|
||||
break;
|
||||
return otmp;
|
||||
}
|
||||
|
||||
/* Fictional and not-so-fictional currencies.
|
||||
* http://concord.wikia.com/wiki/List_of_Fictional_Currencies
|
||||
*/
|
||||
|
||||
17
src/pickup.c
17
src/pickup.c
@@ -261,11 +261,20 @@ query_classes(
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* tests:
|
||||
* 1 = gloves
|
||||
* 2 = is_corpse
|
||||
* 4 = does corpse petrify
|
||||
* 8 = stone resistance
|
||||
*/
|
||||
boolean
|
||||
u_safe_from_fatal_corpse(struct obj *obj)
|
||||
u_safe_from_fatal_corpse(struct obj *obj, int tests)
|
||||
{
|
||||
if (uarmg || obj->otyp != CORPSE
|
||||
|| !touch_petrifies(&mons[obj->corpsenm]) || Stone_resistance)
|
||||
if (((tests & 1) && uarmg)
|
||||
|| ((tests & 2) && obj->otyp != CORPSE)
|
||||
|| ((tests & 4) && !touch_petrifies(&mons[obj->corpsenm]))
|
||||
|| ((tests & 8) && Stone_resistance))
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
@@ -274,7 +283,7 @@ u_safe_from_fatal_corpse(struct obj *obj)
|
||||
staticfn boolean
|
||||
fatal_corpse_mistake(struct obj *obj, boolean remotely)
|
||||
{
|
||||
if (u_safe_from_fatal_corpse(obj) || remotely)
|
||||
if (u_safe_from_fatal_corpse(obj, 0xF) || remotely)
|
||||
return FALSE;
|
||||
|
||||
if (poly_when_stoned(gy.youmonst.data) && polymon(PM_STONE_GOLEM)) {
|
||||
|
||||
@@ -6189,7 +6189,7 @@ makewish(void)
|
||||
/* TODO? maybe generate a second event describing what was received since
|
||||
these just echo player's request rather than show actual result */
|
||||
|
||||
if (otmp->otyp == CORPSE && !u_safe_from_fatal_corpse(otmp))
|
||||
if (otmp->otyp == CORPSE && !u_safe_from_fatal_corpse(otmp, 0xF))
|
||||
otmp->wishedfor = 1;
|
||||
|
||||
const char *verb = ((Is_airlevel(&u.uz) || u.uinwater)
|
||||
|
||||
Reference in New Issue
Block a user