fix #H4353 - monster gets angry after being killed

...by thrown potion.  The reported case was a shopkeeper killed by
system shock from thrown potion of polymorph, but any death (acid,
burning oil explosion, water against iron golem, holy water against
undead, demon, or werecritter) to any peaceful monster could cause
similar result.
This commit is contained in:
PatR
2016-05-31 04:44:21 -07:00
parent 71113a6971
commit 30855febad
2 changed files with 32 additions and 21 deletions

View File

@@ -276,6 +276,8 @@ when getpos was picking a location, typing '^' to move to the next known trap
skipped some detected traps if their location was unseen
describe detected door traps and chest traps as trapped door and trapped chest
instead of bear trap; bear trap tile is still used on map though
thrown potion that killed peaceful monster would cause "the <mon> gets argry"
after the message about it being killed
Fixes to Post-3.6.0 Problems that Were Exposed Via git Repository

View File

@@ -1241,16 +1241,18 @@ boolean your_fault;
{
const char *botlnam = bottlename();
boolean isyou = (mon == &youmonst);
int distance;
int distance, tx, ty;
struct obj *saddle = (struct obj *) 0;
boolean hit_saddle = FALSE;
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);
} else {
tx = mon->mx, ty = mon->my;
/* sometimes it hits the saddle */
if (((mon->misc_worn_check & W_SADDLE)
&& (saddle = which_armor(mon, W_SADDLE)))
@@ -1259,10 +1261,10 @@ boolean your_fault;
&& ((rnl(10) > 7 && obj->cursed)
|| (rnl(10) < 4 && obj->blessed) || !rn2(3)))))
hit_saddle = TRUE;
distance = distu(mon->mx, mon->my);
if (!cansee(mon->mx, mon->my))
distance = distu(tx, ty);
if (!cansee(tx, ty)) {
pline("Crash!");
else {
} else {
char *mnam = mon_nam(mon);
char buf[BUFSZ];
@@ -1285,7 +1287,7 @@ boolean your_fault;
}
/* oil doesn't instantly evaporate; Neither does a saddle hit */
if (obj->otyp != POT_OIL && !hit_saddle && cansee(mon->mx, mon->my))
if (obj->otyp != POT_OIL && !hit_saddle && cansee(tx, ty))
pline("%s.", Tobjnam(obj, "evaporate"));
if (isyou) {
@@ -1313,7 +1315,7 @@ boolean your_fault;
} else if (hit_saddle && saddle) {
char *mnam, buf[BUFSZ], saddle_glows[BUFSZ];
boolean affected = FALSE;
boolean useeit = !Blind && canseemon(mon) && cansee(mon->mx, mon->my);
boolean useeit = !Blind && canseemon(mon) && cansee(tx, ty);
mnam = x_monnam(mon, ARTICLE_THE, (char *) 0,
(SUPPRESS_IT | SUPPRESS_SADDLE), FALSE);
@@ -1331,10 +1333,8 @@ boolean your_fault;
if (useeit && !affected)
pline("%s %s wet.", buf, aobjnam(saddle, "get"));
} else {
boolean angermon = TRUE;
boolean angermon = your_fault;
if (!your_fault)
angermon = FALSE;
switch (obj->otyp) {
case POT_HEALING:
case POT_EXTRA_HEALING:
@@ -1419,7 +1419,7 @@ boolean your_fault;
pline("%s %s in pain!", Monnam(mon),
is_silent(mon->data) ? "writhes" : "shrieks");
if (!is_silent(mon->data))
wake_nearto(mon->mx, mon->my, mon->data->mlevel * 10);
wake_nearto(tx, ty, mon->data->mlevel * 10);
mon->mhp -= d(2, 6);
/* should only be by you */
if (mon->mhp < 1)
@@ -1451,14 +1451,14 @@ boolean your_fault;
break;
case POT_OIL:
if (obj->lamplit)
explode_oil(obj, mon->mx, mon->my);
explode_oil(obj, tx, ty);
break;
case POT_ACID:
if (!resists_acid(mon) && !resist(mon, POTION_CLASS, 0, NOTELL)) {
pline("%s %s in pain!", Monnam(mon),
is_silent(mon->data) ? "writhes" : "shrieks");
if (!is_silent(mon->data))
wake_nearto(mon->mx, mon->my, mon->data->mlevel * 10);
wake_nearto(tx, ty, mon->data->mlevel * 10);
mon->mhp -= d(obj->cursed ? 2 : 1, obj->blessed ? 4 : 8);
if (mon->mhp < 1) {
if (your_fault)
@@ -1480,27 +1480,36 @@ boolean your_fault;
break;
*/
}
if (angermon)
wakeup(mon);
else
mon->msleeping = 0;
/* target might have been killed */
if (mon->mhp > 0) {
if (angermon)
wakeup(mon);
else
mon->msleeping = 0;
}
}
/* Note: potionbreathe() does its own docall() */
if ((distance == 0 || ((distance < 3) && rn2(5)))
if ((distance == 0 || (distance < 3 && rn2(5)))
&& (!breathless(youmonst.data) || haseyes(youmonst.data)))
potionbreathe(obj);
else if (obj->dknown && !objects[obj->otyp].oc_name_known
&& !objects[obj->otyp].oc_uname && cansee(mon->mx, mon->my))
&& !objects[obj->otyp].oc_uname && cansee(tx, ty))
docall(obj);
if (*u.ushops && obj->unpaid) {
struct monst *shkp = shop_keeper(*in_rooms(u.ux, u.uy, SHOPBASE));
if (shkp)
/* neither of the first two cases should be able to happen;
only the hero should ever have an unpaid item, and only
when inside a tended shop */
if (!shkp) /* if shkp was killed, unpaid ought to cleared already */
obj->unpaid = 0;
else if (context.mon_moving) /* obj thrown by monster */
subfrombill(obj, shkp);
else /* obj thrown by hero */
(void) stolen_value(obj, u.ux, u.uy, (boolean) shkp->mpeaceful,
FALSE);
else
obj->unpaid = 0;
}
obfree(obj, (struct obj *) 0);
}