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.
This commit is contained in:
Pasi Kallinen
2023-01-21 16:52:17 +02:00
parent 9dca76bb50
commit 677b32c2a7
8 changed files with 34 additions and 30 deletions

View File

@@ -1089,6 +1089,7 @@ allow setting per-level "temperature": hot, cold, or temperate, currently
only affects some messages only affects some messages
digging is noisy digging is noisy
polymorphing into fire elemental allows you eat flammable items 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 Fixes to 3.7.0-x Problems that Were Exposed Via git Repository

View File

@@ -2914,7 +2914,7 @@ extern void dynamic_multi_reason(struct monst *, const char *, boolean);
extern void erode_armor(struct monst *, int); extern void erode_armor(struct monst *, int);
extern boolean attack_checks(struct monst *, struct obj *); extern boolean attack_checks(struct monst *, struct obj *);
extern void check_caitiff(struct monst *); 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 int find_roll_to_hit(struct monst *, uchar, struct obj *, int *, int *);
extern boolean force_attack(struct monst *, boolean); extern boolean force_attack(struct monst *, boolean);
extern boolean do_attack(struct monst *); 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 melt_ice(coordxy, coordxy, const char *);
extern void start_melt_ice_timeout(coordxy, coordxy, long); extern void start_melt_ice_timeout(coordxy, coordxy, long);
extern void melt_ice_away(union any *, 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 void fracture_rock(struct obj *);
extern boolean break_statue(struct obj *); extern boolean break_statue(struct obj *);
extern boolean u_adtyp_resistance_obj(int); extern boolean u_adtyp_resistance_obj(int);

View File

@@ -183,7 +183,7 @@ kick_monster(struct monst *mon, coordxy x, coordxy y)
attknum = 0, attknum = 0,
tmp = find_roll_to_hit(mon, AT_KICK, (struct obj *) 0, &attknum, tmp = find_roll_to_hit(mon, AT_KICK, (struct obj *) 0, &attknum,
&armorpenalty); &armorpenalty);
mon_maybe_wakeup_on_hit(mon); mon_maybe_unparalyze(mon);
for (i = 0; i < NATTK; i++) { for (i = 0; i < NATTK; i++) {
/* first of two kicks might have provoked counterattack /* first of two kicks might have provoked counterattack

View File

@@ -1830,8 +1830,6 @@ omon_adj(struct monst *mon, struct obj *obj, boolean mon_notices)
/* sleeping target is more likely to be hit */ /* sleeping target is more likely to be hit */
if (mon->msleeping) { if (mon->msleeping) {
tmp += 2; tmp += 2;
if (mon_notices)
mon->msleeping = 0;
} }
/* ditto for immobilized target */ /* ditto for immobilized target */
if (!mon->mcanmove || !mon->data->mmove) { if (!mon->mcanmove || !mon->data->mmove) {

View File

@@ -411,7 +411,8 @@ explode(
* from inside their engulfer. */ * from inside their engulfer. */
if (!(u.uswallow && !gc.context.mon_moving)) if (!(u.uswallow && !gc.context.mon_moving))
(void) zap_over_floor(xx, yy, type, (void) zap_over_floor(xx, yy, type,
&shopdamage, exploding_wand_typ); &shopdamage, FALSE,
exploding_wand_typ);
mtmp = m_at(xx, yy); mtmp = m_at(xx, yy);
if (!mtmp && u_at(xx, yy)) if (!mtmp && u_at(xx, yy))

View File

@@ -3789,6 +3789,8 @@ wake_msg(struct monst *mtmp, boolean interesting)
void void
wakeup(struct monst* mtmp, boolean via_attack) wakeup(struct monst* mtmp, boolean via_attack)
{ {
boolean was_sleeping = mtmp->msleeping;
wake_msg(mtmp, via_attack); wake_msg(mtmp, via_attack);
mtmp->msleeping = 0; mtmp->msleeping = 0;
if (M_AP_TYPE(mtmp) != M_AP_NOTHING) { if (M_AP_TYPE(mtmp) != M_AP_NOTHING) {
@@ -3802,8 +3804,15 @@ wakeup(struct monst* mtmp, boolean via_attack)
newsym(mtmp->mx, mtmp->my); newsym(mtmp->mx, mtmp->my);
} }
finish_meating(mtmp); finish_meating(mtmp);
if (via_attack) if (via_attack) {
if (was_sleeping)
growl(mtmp);
setmangry(mtmp, TRUE); 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. */ /* Wake up nearby monsters without angering them. */

View File

@@ -293,13 +293,10 @@ check_caitiff(struct monst *mtmp)
} }
} }
/* wake up monster, maybe unparalyze it */ /* maybe unparalyze monster */
void 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 (!mtmp->mcanmove) {
if (!rn2(10)) { if (!rn2(10)) {
mtmp->mcanmove = 1; mtmp->mcanmove = 1;
@@ -647,7 +644,7 @@ hitum_cleave(
tmp = find_roll_to_hit(mtmp, uattk->aatyp, uwep, tmp = find_roll_to_hit(mtmp, uattk->aatyp, uwep,
&attknum, &armorpenalty); &attknum, &armorpenalty);
mon_maybe_wakeup_on_hit(mtmp); mon_maybe_unparalyze(mtmp);
dieroll = rnd(20); dieroll = rnd(20);
mhit = (tmp > dieroll); mhit = (tmp > dieroll);
gb.bhitpos.x = tx, gb.bhitpos.y = ty; /* normally set up by 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), dieroll = rnd(20),
mhit = (tmp > dieroll || u.uswallow); 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'; /* 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; 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)) { || !malive || m_at(x, y) != mon)) {
tmp = find_roll_to_hit(mon, uattk->aatyp, uswapwep, &attknum, tmp = find_roll_to_hit(mon, uattk->aatyp, uswapwep, &attknum,
&armorpenalty); &armorpenalty);
mon_maybe_wakeup_on_hit(mon); mon_maybe_unparalyze(mon);
dieroll = rnd(20); dieroll = rnd(20);
mhit = (tmp > dieroll || u.uswallow); mhit = (tmp > dieroll || u.uswallow);
malive = known_hitum(mon, uswapwep, &mhit, tmp, armorpenalty, uattk, malive = known_hitum(mon, uswapwep, &mhit, tmp, armorpenalty, uattk,
@@ -786,7 +783,6 @@ hmon_hitmon(
saved_oname[0] = '\0'; saved_oname[0] = '\0';
wakeup(mon, TRUE);
if (!obj) { /* attack with bare hands */ if (!obj) { /* attack with bare hands */
long silverhit = 0L; /* armor mask */ long silverhit = 0L; /* armor mask */
@@ -816,6 +812,7 @@ hmon_hitmon(
if ((thrown == HMON_THROWN || thrown == HMON_KICKED) /* not Applied */ if ((thrown == HMON_THROWN || thrown == HMON_KICKED) /* not Applied */
&& stone_missile(obj) && passes_rocks(mdat)) { && stone_missile(obj) && passes_rocks(mdat)) {
hit(mshot_xname(obj), mon, " but does no harm."); hit(mshot_xname(obj), mon, " but does no harm.");
wakeup(mon, TRUE);
return TRUE; return TRUE;
} }
/* remember obj's name since it might end up being destroyed and /* 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, Your("%s %s no longer poisoned.", saved_oname,
vtense(saved_oname, "are")); vtense(saved_oname, "are"));
if (!destroyed)
wakeup(mon, TRUE);
return destroyed ? FALSE : TRUE; return destroyed ? FALSE : TRUE;
} }
@@ -4854,7 +4854,7 @@ hmonas(struct monst *mon)
tmp = find_roll_to_hit(mon, AT_WEAP, weapon, &attknum, tmp = find_roll_to_hit(mon, AT_WEAP, weapon, &attknum,
&armorpenalty); &armorpenalty);
mon_maybe_wakeup_on_hit(mon); mon_maybe_unparalyze(mon);
dieroll = rnd(20); dieroll = rnd(20);
dhit = (tmp > dieroll || u.uswallow); dhit = (tmp > dieroll || u.uswallow);
/* caller must set gb.bhitpos */ /* caller must set gb.bhitpos */
@@ -4896,7 +4896,7 @@ hmonas(struct monst *mon)
/*weaponless:*/ /*weaponless:*/
tmp = find_roll_to_hit(mon, mattk->aatyp, (struct obj *) 0, tmp = find_roll_to_hit(mon, mattk->aatyp, (struct obj *) 0,
&attknum, &armorpenalty); &attknum, &armorpenalty);
mon_maybe_wakeup_on_hit(mon); mon_maybe_unparalyze(mon);
dieroll = rnd(20); dieroll = rnd(20);
dhit = (tmp > dieroll || u.uswallow); dhit = (tmp > dieroll || u.uswallow);
if (dhit) { if (dhit) {
@@ -5089,7 +5089,7 @@ hmonas(struct monst *mon)
case AT_ENGL: case AT_ENGL:
tmp = find_roll_to_hit(mon, mattk->aatyp, (struct obj *) 0, tmp = find_roll_to_hit(mon, mattk->aatyp, (struct obj *) 0,
&attknum, &armorpenalty); &attknum, &armorpenalty);
mon_maybe_wakeup_on_hit(mon); mon_maybe_unparalyze(mon);
if ((dhit = (tmp > rnd(20 + i)))) { if ((dhit = (tmp > rnd(20 + i)))) {
wakeup(mon, TRUE); wakeup(mon, TRUE);
if (mon->data == &mons[PM_SHADE]) { if (mon->data == &mons[PM_SHADE]) {

View File

@@ -4393,7 +4393,7 @@ dobuzz(
gb.bhitpos.x = sx, gb.bhitpos.y = sy; gb.bhitpos.x = sx, gb.bhitpos.y = sy;
/* Fireballs only damage when they explode */ /* Fireballs only damage when they explode */
if (type != ZT_SPELL(ZT_FIRE)) { 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 /* zap with fire -> melt ice -> drown monster, so monster
found and cached above might not be here any more */ found and cached above might not be here any more */
mon = m_at(sx, sy); mon = m_at(sx, sy);
@@ -4480,6 +4480,8 @@ dobuzz(
} }
if (mon_could_move && !mon->mcanmove) /* ZT_SLEEP */ if (mon_could_move && !mon->mcanmove) /* ZT_SLEEP */
slept_monst(mon); slept_monst(mon);
if (abstype != ZT_SLEEP)
wakeup(mon, TRUE);
} }
} }
range -= 2; range -= 2;
@@ -4698,6 +4700,7 @@ zap_over_floor(
coordxy x, coordxy y, /* location */ coordxy x, coordxy y, /* location */
int type, /* damage type plus {wand|spell|breath} info */ int type, /* damage type plus {wand|spell|breath} info */
boolean *shopdamage, /* extra output if shop door is destroyed */ 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 short exploding_wand_typ) /* supplied when breaking a wand; or POT_OIL
* when a lit potion of oil explodes */ * when a lit potion of oil explodes */
{ {
@@ -5012,16 +5015,8 @@ zap_over_floor(
newsym(x, y); newsym(x, y);
You("%s of smoke.", !Blind ? "see a puff" : "smell a whiff"); You("%s of smoke.", !Blind ? "see a puff" : "smell a whiff");
} }
if ((mon = m_at(x, y)) != 0) { if (!ignoremon && (mon = m_at(x, y)) != 0)
wakeup(mon, FALSE); wakeup(mon, (type >= 0) ? TRUE : 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);
}
}
return rangemod; return rangemod;
} }