fix mention_walls reporting secret doors as solid walls
corpses and other flammable items not subject to direct burning or fire-based
erosion which were thrown or dropped into lava remained intact
+if a potion on the floor survived a land mine explosion and got propelled at
+ the hero, it didn't behave like a potion if it hit
Fixes to Post-3.6.0 Problems that Were Exposed Via git Repository
/* ### mthrowu.c ### */
-E int FDECL(thitu, (int, int, struct obj *, const char *));
+E int FDECL(thitu, (int, int, struct obj **, const char *));
E int FDECL(ohitmon, (struct monst *, struct obj *, int, BOOLEAN_P));
E void FDECL(thrwmu, (struct monst *));
E int FDECL(spitmu, (struct monst *, struct attack *));
E int FDECL(peffects, (struct obj *));
E void FDECL(healup, (int, int, BOOLEAN_P, BOOLEAN_P));
E void FDECL(strange_feeling, (struct obj *, const char *));
-E void FDECL(potionhit, (struct monst *, struct obj *, BOOLEAN_P));
+E void FDECL(potionhit, (struct monst *, struct obj *, int));
E void FDECL(potionbreathe, (struct obj *));
E int NDECL(dodip);
E void FDECL(mongrantswish, (struct monst **));
unsigned owt;
long quan; /* number of items */
- schar spe; /* quality of weapon, armor or ring (+ or -);
+ schar spe; /* quality of weapon, weptool, armor or ring (+ or -);
number of charges for wand or charged tool ( >= -1 );
marks your eggs, tin variety and spinach tins;
Schroedinger's Box (1) or royal coffers for a court (2);
#define ER_DAMAGED 2 /* object was damaged in some way */
#define ER_DESTROYED 3 /* object was destroyed */
+/* propeller method for potionhit() */
+#define POTHIT_HERO_BASH 0 /* wielded by hero */
+#define POTHIT_HERO_THROW 1 /* thrown by hero */
+#define POTHIT_MONST_THROW 2 /* thrown by a monster */
+#define POTHIT_OTHER_THROW 3 /* propelled by some other means [scatter()] */
+
/*
* Notes for adding new oextra structures:
*
int hitu, hitvalu;
hitvalu = 8 + otmp->spe;
- hitu = thitu(hitvalu,
- dmgval(otmp, &youmonst),
- otmp, (char *)0);
+ hitu = thitu(hitvalu, dmgval(otmp, &youmonst),
+ &otmp, (char *)0);
if (hitu) {
pline_The("%s hits you as you try to snatch it!",
the(onambuf));
/* object now hits you */
if (obj->oclass == POTION_CLASS) {
- potionhit(&youmonst, obj, TRUE);
+ potionhit(&youmonst, obj, POTHIT_HERO_THROW);
} else if (breaktest(obj)) {
int otyp = obj->otyp;
int blindinc;
&& rn2(6)) {
/* alternative to prayer or wand of opening/spell of knock
for dealing with cursed saddle: throw holy water > */
- potionhit(u.usteed, obj, TRUE);
+ potionhit(u.usteed, obj, POTHIT_HERO_THROW);
} else {
hitfloor(obj);
}
} else if (obj->oclass == POTION_CLASS
&& (guaranteed_hit || ACURR(A_DEX) > rnd(25))) {
- potionhit(mon, obj, TRUE);
+ potionhit(mon, obj, POTHIT_HERO_THROW);
return 1;
} else if (befriend_with_obj(mon->data, obj)
struct scatter_chain *schain = (struct scatter_chain *) 0;
long total = 0L;
- while ((otmp = individual_object ? obj : level.objects[sx][sy]) != 0) {
+ while ((otmp = (individual_object ? obj : level.objects[sx][sy])) != 0) {
if (otmp->quan > 1L) {
qtmp = otmp->quan - 1L;
if (qtmp > LARGEST_INT)
used_up = FALSE;
/* 9 in 10 chance of fracturing boulders or statues */
- if ((scflags & MAY_FRACTURE)
- && ((otmp->otyp == BOULDER) || (otmp->otyp == STATUE))
+ if ((scflags & MAY_FRACTURE) != 0
+ && (otmp->otyp == BOULDER || otmp->otyp == STATUE)
&& rn2(10)) {
if (otmp->otyp == BOULDER) {
if (cansee(sx, sy))
used_up = TRUE;
/* 1 in 10 chance of destruction of obj; glass, egg destruction */
- } else if ((scflags & MAY_DESTROY)
+ } else if ((scflags & MAY_DESTROY) != 0
&& (!rn2(10) || (objects[otmp->otyp].oc_material == GLASS
|| otmp->otyp == EGG))) {
if (breaks(otmp, (xchar) sx, (xchar) sy))
}
if (!used_up) {
- stmp = (struct scatter_chain *)
- alloc(sizeof (struct scatter_chain));
+ stmp = (struct scatter_chain *) alloc(sizeof *stmp);
stmp->next = (struct scatter_chain *) 0;
stmp->obj = otmp;
stmp->ox = sx;
if (bigmonst(youmonst.data))
hitvalu++;
hitu = thitu(hitvalu, dmgval(stmp->obj, &youmonst),
- stmp->obj, (char *) 0);
+ &stmp->obj, (char *) 0);
+ if (!stmp->obj)
+ stmp->stopped = TRUE;
if (hitu) {
stmp->range -= 3;
stop_occupation();
/* hero is hit by something other than a monster */
int
-thitu(tlev, dam, obj, name)
+thitu(tlev, dam, objp, name)
int tlev, dam;
-struct obj *obj;
-const char *name; /* if null, then format `obj' */
+struct obj **objp;
+const char *name; /* if null, then format `*objp' */
{
+ struct obj *obj = objp ? *objp : 0;
const char *onm, *knm;
boolean is_acid;
int kprefix = KILLED_BY_AN;
if (!name) {
if (!obj)
panic("thitu: name & obj both null?");
- name =
- strcpy(onmbuf, (obj->quan > 1L) ? doname(obj) : mshot_xname(obj));
+ name = strcpy(onmbuf,
+ (obj->quan > 1L) ? doname(obj) : mshot_xname(obj));
knm = strcpy(knmbuf, killer_xname(obj));
kprefix = KILLED_BY; /* killer_name supplies "an" if warranted */
} else {
else
You("are hit by %s%s", onm, exclam(dam));
- if (obj && objects[obj->otyp].oc_material == SILVER && Hate_silver) {
- /* extra damage already applied by dmgval() */
- pline_The("silver sears your flesh!");
- exercise(A_CON, FALSE);
- }
if (is_acid && Acid_resistance) {
pline("It doesn't seem to hurt you.");
+ } else if (obj && obj->oclass == POTION_CLASS) {
+ /* an explosion which scatters objects might hit hero with one
+ (potions deliberately thrown at hero are handled by m_throw) */
+ potionhit(&youmonst, obj, POTHIT_OTHER_THROW);
+ *objp = obj = 0; /* potionhit() uses up the potion */
} else {
+ if (obj && objects[obj->otyp].oc_material == SILVER
+ && Hate_silver) {
+ /* extra damage already applied by dmgval() */
+ pline_The("silver sears your flesh!");
+ exercise(A_CON, FALSE);
+ }
if (is_acid)
pline("It burns!");
losehp(dam, knm, kprefix); /* acid damage */
else
create = 1;
- if (create
- && !((mtmp = m_at(x, y)) && (mtmp->mtrapped) && (t = t_at(x, y))
- && ((t->ttyp == PIT) || (t->ttyp == SPIKED_PIT)))) {
+ if (create && !((mtmp = m_at(x, y)) != 0 && mtmp->mtrapped
+ && (t = t_at(x, y)) != 0
+ && (t->ttyp == PIT || t->ttyp == SPIKED_PIT))) {
int objgone = 0;
if (down_gate(x, y) != -1)
mtmp->msleeping = 0;
if (vis)
otmp->dknown = 1;
- potionhit(mtmp, otmp, FALSE);
+ /* probably thrown by a monster rather than 'other', but the
+ distinction only matters when hitting the hero */
+ potionhit(mtmp, otmp, POTHIT_OTHER_THROW);
return 1;
} else {
damage = dmgval(otmp, mtmp);
if (singleobj->oclass == POTION_CLASS) {
if (!Blind)
singleobj->dknown = 1;
- potionhit(&youmonst, singleobj, FALSE);
+ potionhit(&youmonst, singleobj, POTHIT_MONST_THROW);
break;
}
oldumort = u.umortality;
/* fall through */
case CREAM_PIE:
case BLINDING_VENOM:
- hitu = thitu(8, 0, singleobj, (char *) 0);
+ hitu = thitu(8, 0, &singleobj, (char *) 0);
break;
default:
dam = dmgval(singleobj, &youmonst);
hitv += 8 + singleobj->spe;
if (dam < 1)
dam = 1;
- hitu = thitu(hitv, dam, singleobj, (char *) 0);
+ hitu = thitu(hitv, dam, &singleobj, (char *) 0);
}
if (hitu && singleobj->opoisoned && is_poisonable(singleobj)) {
char onmbuf[BUFSZ], knmbuf[BUFSZ];
if (dam < 1)
dam = 1;
- (void) thitu(hitv, dam, otmp, (char *) 0);
+ (void) thitu(hitv, dam, &otmp, (char *) 0);
stop_occupation();
return;
}
return res;
}
+/* potion obj hits monster mon, which might be youmounst; obj always use up */
void
-potionhit(mon, obj, your_fault)
-register struct monst *mon;
-register struct obj *obj;
-boolean your_fault;
+potionhit(mon, obj, how)
+struct monst *mon;
+struct obj *obj;
+int how;
{
const char *botlnam = bottlename();
boolean isyou = (mon == &youmonst);
int distance, tx, ty;
struct obj *saddle = (struct obj *) 0;
- boolean hit_saddle = FALSE;
+ boolean hit_saddle = FALSE, your_fault = (how <= POTHIT_HERO_THROW);
if (isyou) {
tx = u.ux, ty = u.uy;
distance = 0;
pline_The("%s crashes on your %s and breaks into shards.", botlnam,
body_part(HEAD));
- losehp(Maybe_Half_Phys(rnd(2)), "thrown potion", KILLED_BY_AN);
+ losehp(Maybe_Half_Phys(rnd(2)),
+ (how == POTHIT_OTHER_THROW) ? "propelled potion" /* scatter */
+ : "thrown potion",
+ KILLED_BY_AN);
} else {
tx = mon->mx, ty = mon->my;
/* sometimes it hits the saddle */
case POT_ACID:
if (!Acid_resistance) {
int dmg;
+
pline("This burns%s!",
obj->blessed ? " a little"
: obj->cursed ? " a lot" : "");
unsigned trflags;
{
register int ttype = trap->ttyp;
- register struct obj *otmp;
+ struct obj *otmp;
boolean already_seen = trap->tseen,
forcetrap = (trflags & FORCETRAP) != 0,
webmsgok = (trflags & NOWEBMSG) == 0,
otmp->opoisoned = 0;
if (u.usteed && !rn2(2) && steedintrap(trap, otmp)) { /* nothing */
;
- } else if (thitu(8, dmgval(otmp, &youmonst), otmp, "arrow")) {
- obfree(otmp, (struct obj *) 0);
+ } else if (thitu(8, dmgval(otmp, &youmonst), &otmp, "arrow")) {
+ if (otmp)
+ obfree(otmp, (struct obj *) 0);
} else {
place_object(otmp, u.ux, u.uy);
if (!Blind)
oldumort = u.umortality;
if (u.usteed && !rn2(2) && steedintrap(trap, otmp)) { /* nothing */
;
- } else if (thitu(7, dmgval(otmp, &youmonst), otmp, "little dart")) {
- if (otmp->opoisoned)
- poisoned("dart", A_CON, "little dart",
- /* if damage triggered life-saving,
- poison is limited to attrib loss */
- (u.umortality > oldumort) ? 0 : 10, TRUE);
- obfree(otmp, (struct obj *) 0);
+ } else if (thitu(7, dmgval(otmp, &youmonst), &otmp, "little dart")) {
+ if (otmp) {
+ if (otmp->opoisoned)
+ poisoned("dart", A_CON, "little dart",
+ /* if damage triggered life-saving,
+ poison is limited to attrib loss */
+ (u.umortality > oldumort) ? 0 : 10, TRUE);
+ obfree(otmp, (struct obj *) 0);
+ }
} else {
place_object(otmp, u.ux, u.uy);
if (!Blind)
if (multi)
nomul(0);
if (thitu(9 + singleobj->spe, dmgval(singleobj, &youmonst),
- singleobj, (char *) 0))
+ &singleobj, (char *) 0))
stop_occupation();
}
if (style == ROLL) {
else
setuwep((struct obj *) 0);
freeinv(obj);
- potionhit(mon, obj, TRUE);
+ potionhit(mon, obj,
+ hand_to_hand ? POTHIT_HERO_BASH : POTHIT_HERO_THROW);
if (mon->mhp <= 0)
return FALSE; /* killed */
hittxt = TRUE;
if (bhitpos.x == u.ux && bhitpos.y == u.uy) { /* ct == 9 */
if (Fumbling || rn2(20) >= ACURR(A_DEX)) {
/* we hit ourselves */
- (void) thitu(10 + obj->spe, dmgval(obj, &youmonst), obj,
+ (void) thitu(10 + obj->spe, dmgval(obj, &youmonst), &obj,
"boomerang");
endmultishot(TRUE);
break;