From: Pasi Kallinen Date: Sat, 21 Jan 2023 14:52:17 +0000 (+0200) Subject: Hit and wake sleeping monster makes it growl X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=677b32c2a7;p=nethack Hit and wake sleeping monster makes it growl Unless you kill the monster with one hit, it'll wake up cranky and make noise - waking up other sleeping monsters. This was a bit tricky with all the message sequencing; I tested all the hit/throw/fire/zap combos I could think of, and it took a while to get things looking right. --- diff --git a/doc/fixes3-7-0.txt b/doc/fixes3-7-0.txt index 6e8864a0f..73479ac16 100644 --- a/doc/fixes3-7-0.txt +++ b/doc/fixes3-7-0.txt @@ -1089,6 +1089,7 @@ allow setting per-level "temperature": hot, cold, or temperate, currently only affects some messages digging is noisy polymorphing into fire elemental allows you eat flammable items +hitting sleeping monsters will cause them to wake up noisily Fixes to 3.7.0-x Problems that Were Exposed Via git Repository diff --git a/include/extern.h b/include/extern.h index c6370f6a8..baae09151 100644 --- a/include/extern.h +++ b/include/extern.h @@ -2914,7 +2914,7 @@ extern void dynamic_multi_reason(struct monst *, const char *, boolean); extern void erode_armor(struct monst *, int); extern boolean attack_checks(struct monst *, struct obj *); extern void check_caitiff(struct monst *); -extern void mon_maybe_wakeup_on_hit(struct monst *); +extern void mon_maybe_unparalyze(struct monst *); extern int find_roll_to_hit(struct monst *, uchar, struct obj *, int *, int *); extern boolean force_attack(struct monst *, boolean); extern boolean do_attack(struct monst *); @@ -3477,7 +3477,7 @@ extern void dobuzz(int, int, coordxy, coordxy, int, int, boolean); extern void melt_ice(coordxy, coordxy, const char *); extern void start_melt_ice_timeout(coordxy, coordxy, long); extern void melt_ice_away(union any *, long); -extern int zap_over_floor(coordxy, coordxy, int, boolean *, short); +extern int zap_over_floor(coordxy, coordxy, int, boolean *, boolean, short); extern void fracture_rock(struct obj *); extern boolean break_statue(struct obj *); extern boolean u_adtyp_resistance_obj(int); diff --git a/src/dokick.c b/src/dokick.c index 2b08f7525..676764114 100644 --- a/src/dokick.c +++ b/src/dokick.c @@ -183,7 +183,7 @@ kick_monster(struct monst *mon, coordxy x, coordxy y) attknum = 0, tmp = find_roll_to_hit(mon, AT_KICK, (struct obj *) 0, &attknum, &armorpenalty); - mon_maybe_wakeup_on_hit(mon); + mon_maybe_unparalyze(mon); for (i = 0; i < NATTK; i++) { /* first of two kicks might have provoked counterattack diff --git a/src/dothrow.c b/src/dothrow.c index 217f65a24..84b16e099 100644 --- a/src/dothrow.c +++ b/src/dothrow.c @@ -1830,8 +1830,6 @@ omon_adj(struct monst *mon, struct obj *obj, boolean mon_notices) /* sleeping target is more likely to be hit */ if (mon->msleeping) { tmp += 2; - if (mon_notices) - mon->msleeping = 0; } /* ditto for immobilized target */ if (!mon->mcanmove || !mon->data->mmove) { diff --git a/src/explode.c b/src/explode.c index 32a146542..204899987 100644 --- a/src/explode.c +++ b/src/explode.c @@ -411,7 +411,8 @@ explode( * from inside their engulfer. */ if (!(u.uswallow && !gc.context.mon_moving)) (void) zap_over_floor(xx, yy, type, - &shopdamage, exploding_wand_typ); + &shopdamage, FALSE, + exploding_wand_typ); mtmp = m_at(xx, yy); if (!mtmp && u_at(xx, yy)) diff --git a/src/mon.c b/src/mon.c index 8736edbe3..279e3dbcb 100644 --- a/src/mon.c +++ b/src/mon.c @@ -3789,6 +3789,8 @@ wake_msg(struct monst *mtmp, boolean interesting) void wakeup(struct monst* mtmp, boolean via_attack) { + boolean was_sleeping = mtmp->msleeping; + wake_msg(mtmp, via_attack); mtmp->msleeping = 0; if (M_AP_TYPE(mtmp) != M_AP_NOTHING) { @@ -3802,8 +3804,15 @@ wakeup(struct monst* mtmp, boolean via_attack) newsym(mtmp->mx, mtmp->my); } finish_meating(mtmp); - if (via_attack) + if (via_attack) { + if (was_sleeping) + growl(mtmp); setmangry(mtmp, TRUE); + if (mtmp->ispriest && *in_rooms(mtmp->mx, mtmp->my, TEMPLE)) + ghod_hitsu(mtmp); + if (mtmp->isshk && !*u.ushops) + hot_pursuit(mtmp); + } } /* Wake up nearby monsters without angering them. */ diff --git a/src/uhitm.c b/src/uhitm.c index f90a56a7b..06a20e0ca 100644 --- a/src/uhitm.c +++ b/src/uhitm.c @@ -293,13 +293,10 @@ check_caitiff(struct monst *mtmp) } } -/* wake up monster, maybe unparalyze it */ +/* maybe unparalyze monster */ void -mon_maybe_wakeup_on_hit(struct monst *mtmp) +mon_maybe_unparalyze(struct monst *mtmp) { - if (mtmp->msleeping) - mtmp->msleeping = 0; - if (!mtmp->mcanmove) { if (!rn2(10)) { mtmp->mcanmove = 1; @@ -647,7 +644,7 @@ hitum_cleave( tmp = find_roll_to_hit(mtmp, uattk->aatyp, uwep, &attknum, &armorpenalty); - mon_maybe_wakeup_on_hit(mtmp); + mon_maybe_unparalyze(mtmp); dieroll = rnd(20); mhit = (tmp > dieroll); gb.bhitpos.x = tx, gb.bhitpos.y = ty; /* normally set up by @@ -685,7 +682,7 @@ hitum(struct monst *mon, struct attack *uattk) dieroll = rnd(20), mhit = (tmp > dieroll || u.uswallow); - mon_maybe_wakeup_on_hit(mon); + mon_maybe_unparalyze(mon); /* Cleaver attacks three spots, 'mon' and one on either side of 'mon'; it can't be part of dual-wielding but we guard against that anyway; @@ -712,7 +709,7 @@ hitum(struct monst *mon, struct attack *uattk) || !malive || m_at(x, y) != mon)) { tmp = find_roll_to_hit(mon, uattk->aatyp, uswapwep, &attknum, &armorpenalty); - mon_maybe_wakeup_on_hit(mon); + mon_maybe_unparalyze(mon); dieroll = rnd(20); mhit = (tmp > dieroll || u.uswallow); malive = known_hitum(mon, uswapwep, &mhit, tmp, armorpenalty, uattk, @@ -786,7 +783,6 @@ hmon_hitmon( saved_oname[0] = '\0'; - wakeup(mon, TRUE); if (!obj) { /* attack with bare hands */ long silverhit = 0L; /* armor mask */ @@ -816,6 +812,7 @@ hmon_hitmon( if ((thrown == HMON_THROWN || thrown == HMON_KICKED) /* not Applied */ && stone_missile(obj) && passes_rocks(mdat)) { hit(mshot_xname(obj), mon, " but does no harm."); + wakeup(mon, TRUE); return TRUE; } /* remember obj's name since it might end up being destroyed and @@ -1510,6 +1507,9 @@ hmon_hitmon( Your("%s %s no longer poisoned.", saved_oname, vtense(saved_oname, "are")); + if (!destroyed) + wakeup(mon, TRUE); + return destroyed ? FALSE : TRUE; } @@ -4854,7 +4854,7 @@ hmonas(struct monst *mon) tmp = find_roll_to_hit(mon, AT_WEAP, weapon, &attknum, &armorpenalty); - mon_maybe_wakeup_on_hit(mon); + mon_maybe_unparalyze(mon); dieroll = rnd(20); dhit = (tmp > dieroll || u.uswallow); /* caller must set gb.bhitpos */ @@ -4896,7 +4896,7 @@ hmonas(struct monst *mon) /*weaponless:*/ tmp = find_roll_to_hit(mon, mattk->aatyp, (struct obj *) 0, &attknum, &armorpenalty); - mon_maybe_wakeup_on_hit(mon); + mon_maybe_unparalyze(mon); dieroll = rnd(20); dhit = (tmp > dieroll || u.uswallow); if (dhit) { @@ -5089,7 +5089,7 @@ hmonas(struct monst *mon) case AT_ENGL: tmp = find_roll_to_hit(mon, mattk->aatyp, (struct obj *) 0, &attknum, &armorpenalty); - mon_maybe_wakeup_on_hit(mon); + mon_maybe_unparalyze(mon); if ((dhit = (tmp > rnd(20 + i)))) { wakeup(mon, TRUE); if (mon->data == &mons[PM_SHADE]) { diff --git a/src/zap.c b/src/zap.c index 0104280c3..17353df2d 100644 --- a/src/zap.c +++ b/src/zap.c @@ -4393,7 +4393,7 @@ dobuzz( gb.bhitpos.x = sx, gb.bhitpos.y = sy; /* Fireballs only damage when they explode */ if (type != ZT_SPELL(ZT_FIRE)) { - range += zap_over_floor(sx, sy, type, &shopdamage, 0); + range += zap_over_floor(sx, sy, type, &shopdamage, 0, TRUE); /* zap with fire -> melt ice -> drown monster, so monster found and cached above might not be here any more */ mon = m_at(sx, sy); @@ -4480,6 +4480,8 @@ dobuzz( } if (mon_could_move && !mon->mcanmove) /* ZT_SLEEP */ slept_monst(mon); + if (abstype != ZT_SLEEP) + wakeup(mon, TRUE); } } range -= 2; @@ -4698,6 +4700,7 @@ zap_over_floor( coordxy x, coordxy y, /* location */ int type, /* damage type plus {wand|spell|breath} info */ boolean *shopdamage, /* extra output if shop door is destroyed */ + boolean ignoremon, /* ignore any monster here */ short exploding_wand_typ) /* supplied when breaking a wand; or POT_OIL * when a lit potion of oil explodes */ { @@ -5012,16 +5015,8 @@ zap_over_floor( newsym(x, y); You("%s of smoke.", !Blind ? "see a puff" : "smell a whiff"); } - if ((mon = m_at(x, y)) != 0) { - wakeup(mon, FALSE); - if (type >= 0) { - setmangry(mon, TRUE); - if (mon->ispriest && *in_rooms(mon->mx, mon->my, TEMPLE)) - ghod_hitsu(mon); - if (mon->isshk && !*u.ushops) - hot_pursuit(mon); - } - } + if (!ignoremon && (mon = m_at(x, y)) != 0) + wakeup(mon, (type >= 0) ? TRUE : FALSE); return rangemod; }