fix github issue #1011 - monster imagination
Issue reported by AndrioCelos: if hero was killed by a wand zapped by a monster, the cause of death was "killed by <wand damage> imagined by <the monster>" instead of intended "killed by <wand damage> zapped by <the monster>". Report mentioned that the monster was unseen but that wasn't relevant. This worked when monster wand zaps were briefly changed to use -9..-0 but got broken when that was reverted to using -39..-30 (due to -0 being the same as 0 so making zapper of wands of magic missile ambiguous). Fixes #1011
This commit is contained in:
@@ -1531,6 +1531,8 @@ change 'm' prefix for #tip from 'use menu to pick among floor containers'
|
|||||||
context-sensitive item-action Tip directly operates on the item
|
context-sensitive item-action Tip directly operates on the item
|
||||||
anti-magic field's reduction of hero's maximum energy could result in current
|
anti-magic field's reduction of hero's maximum energy could result in current
|
||||||
energy being one point higher than maximum
|
energy being one point higher than maximum
|
||||||
|
if hero was killed by a wand zapped by a monster, cause of death was reported
|
||||||
|
as "killed by a bolt of <damage type> imagined by <monster>"
|
||||||
|
|
||||||
|
|
||||||
Fixes to 3.7.0-x Platform and/or Interface Problems Exposed Via git Repository
|
Fixes to 3.7.0-x Platform and/or Interface Problems Exposed Via git Repository
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
*/
|
*/
|
||||||
#define MAGIC_COOKIE 1000
|
#define MAGIC_COOKIE 1000
|
||||||
|
|
||||||
|
static int zaptype(int);
|
||||||
static void probe_objchain(struct obj *);
|
static void probe_objchain(struct obj *);
|
||||||
static boolean zombie_can_dig(coordxy x, coordxy y);
|
static boolean zombie_can_dig(coordxy x, coordxy y);
|
||||||
static void polyuse(struct obj *, int, int);
|
static void polyuse(struct obj *, int, int);
|
||||||
@@ -76,6 +77,17 @@ static const char *const flash_types[] = {
|
|||||||
"blast of poison gas", "blast of acid", "", ""
|
"blast of poison gas", "blast of acid", "", ""
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* convert monster zap/spell/breath value to hero zap/spell/breath value */
|
||||||
|
static int
|
||||||
|
zaptype(int type)
|
||||||
|
{
|
||||||
|
if (type <= -30 && -39 <= type) /* monster wand zap */
|
||||||
|
type += 30; /* first convert -39..-30 to -9..0 so that abs()
|
||||||
|
* will yield 0..9 (hero wand zap) for it */
|
||||||
|
type = abs(type);
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Recognizing unseen wands by zapping: in 3.4.3 and earlier, zapping
|
* Recognizing unseen wands by zapping: in 3.4.3 and earlier, zapping
|
||||||
* most wand types while blind would add that type to the discoveries
|
* most wand types while blind would add that type to the discoveries
|
||||||
@@ -3492,12 +3504,13 @@ maybe_explode_trap(struct trap *ttmp, struct obj *otmp)
|
|||||||
* If fhitm returns non-zero value, stops the beam and returns the monster
|
* If fhitm returns non-zero value, stops the beam and returns the monster
|
||||||
*/
|
*/
|
||||||
struct monst *
|
struct monst *
|
||||||
bhit(coordxy ddx, coordxy ddy, int range, /* direction and range */
|
bhit(
|
||||||
enum bhit_call_types weapon, /* defined in hack.h */
|
coordxy ddx, coordxy ddy, int range, /* direction and range */
|
||||||
int (*fhitm)(MONST_P, OBJ_P), /* fns called when mon/obj hit */
|
enum bhit_call_types weapon, /* defined in hack.h */
|
||||||
int (*fhito)(OBJ_P, OBJ_P),
|
int (*fhitm)(MONST_P, OBJ_P), /* fns called when mon/obj hit */
|
||||||
struct obj **pobj) /* object tossed/used, set to NULL
|
int (*fhito)(OBJ_P, OBJ_P),
|
||||||
if object is destroyed */
|
struct obj **pobj) /* object tossed/used, set to NULL
|
||||||
|
* if object is destroyed */
|
||||||
{
|
{
|
||||||
struct monst *mtmp, *result = (struct monst *) 0;
|
struct monst *mtmp, *result = (struct monst *) 0;
|
||||||
struct obj *obj = *pobj;
|
struct obj *obj = *pobj;
|
||||||
@@ -3912,12 +3925,12 @@ zhitm(
|
|||||||
struct obj **ootmp) /* to return worn armor for caller to disintegrate */
|
struct obj **ootmp) /* to return worn armor for caller to disintegrate */
|
||||||
{
|
{
|
||||||
int tmp = 0; /* damage amount */
|
int tmp = 0; /* damage amount */
|
||||||
int abstype = abs(type) % 10;
|
int damgtype = zaptype(type) % 10;
|
||||||
boolean sho_shieldeff = FALSE;
|
boolean sho_shieldeff = FALSE;
|
||||||
boolean spellcaster = is_hero_spell(type); /* maybe get a bonus! */
|
boolean spellcaster = is_hero_spell(type); /* maybe get a bonus! */
|
||||||
|
|
||||||
*ootmp = (struct obj *) 0;
|
*ootmp = (struct obj *) 0;
|
||||||
switch (abstype) {
|
switch (damgtype) {
|
||||||
case ZT_MAGIC_MISSILE:
|
case ZT_MAGIC_MISSILE:
|
||||||
if (resists_magm(mon) || defended(mon, AD_MAGM)) {
|
if (resists_magm(mon) || defended(mon, AD_MAGM)) {
|
||||||
sho_shieldeff = TRUE;
|
sho_shieldeff = TRUE;
|
||||||
@@ -4076,7 +4089,7 @@ zhitu(
|
|||||||
const char *fltxt,
|
const char *fltxt,
|
||||||
coordxy sx, coordxy sy)
|
coordxy sx, coordxy sy)
|
||||||
{
|
{
|
||||||
int dam = 0, abstyp = abs(type);
|
int dam = 0, abstyp = zaptype(type);
|
||||||
|
|
||||||
switch (abstyp % 10) {
|
switch (abstyp % 10) {
|
||||||
case ZT_MAGIC_MISSILE:
|
case ZT_MAGIC_MISSILE:
|
||||||
@@ -4388,34 +4401,33 @@ buzz(int type, int nd, coordxy sx, coordxy sy, int dx, int dy)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* type == 0 to 9 : you shooting a wand
|
* type == 0 to 9 : you zapping a wand
|
||||||
* type == 10 to 19 : you casting a spell
|
* type == 10 to 19 : you casting a spell
|
||||||
* type == 20 to 29 : you breathing as a monster
|
* type == 20 to 29 : you breathing as a monster
|
||||||
* type == -10 to -19 : monster casting spell
|
* type == -10 to -19 : monster casting spell
|
||||||
* type == -20 to -29 : monster breathing at you
|
* type == -20 to -29 : monster breathing at you
|
||||||
* type == -30 to -39 : monster shooting a wand
|
* type == -30 to -39 : monster zapping a wand
|
||||||
* called with dx = dy = 0 with vertical bolts
|
* called with dx = dy = 0 for vertical bolts
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
dobuzz(
|
dobuzz(
|
||||||
int type,
|
int type, /* 0..29 (by hero) or -39..-10 (by monster) */
|
||||||
int nd,
|
int nd, /* damage strength ('number of dice') */
|
||||||
coordxy sx, coordxy sy,
|
coordxy sx, coordxy sy, /* starting point */
|
||||||
int dx, int dy,
|
int dx, int dy, /* direction delta */
|
||||||
boolean say) /* announce out of sight hit/miss events if true */
|
boolean say) /* announce out of sight hit/miss events if true */
|
||||||
{
|
{
|
||||||
int range, abstype = abs(type) % 10;
|
int range, fltyp = zaptype(type), damgtype = fltyp % 10;
|
||||||
register coordxy lsx, lsy;
|
register coordxy lsx, lsy;
|
||||||
struct monst *mon;
|
struct monst *mon;
|
||||||
coord save_bhitpos;
|
coord save_bhitpos;
|
||||||
boolean shopdamage = FALSE;
|
boolean shopdamage = FALSE;
|
||||||
struct obj *otmp;
|
struct obj *otmp;
|
||||||
int spell_type;
|
int spell_type;
|
||||||
int fltyp = (type <= -30) ? abstype : abs(type);
|
int hdmgtype = Hallucination ? rn2(6) : damgtype;
|
||||||
int habstype = Hallucination ? rn2(6) : abstype;
|
|
||||||
|
|
||||||
/* if its a Hero Spell then get its SPE_TYPE */
|
/* if its a Hero Spell then get its SPE_TYPE */
|
||||||
spell_type = is_hero_spell(type) ? SPE_MAGIC_MISSILE + abstype : 0;
|
spell_type = is_hero_spell(type) ? SPE_MAGIC_MISSILE + damgtype : 0;
|
||||||
|
|
||||||
if (u.uswallow) {
|
if (u.uswallow) {
|
||||||
register int tmp;
|
register int tmp;
|
||||||
@@ -4443,7 +4455,7 @@ dobuzz(
|
|||||||
range = 1;
|
range = 1;
|
||||||
save_bhitpos = gb.bhitpos;
|
save_bhitpos = gb.bhitpos;
|
||||||
|
|
||||||
tmp_at(DISP_BEAM, zapdir_to_glyph(dx, dy, habstype));
|
tmp_at(DISP_BEAM, zapdir_to_glyph(dx, dy, hdmgtype));
|
||||||
while (range-- > 0) {
|
while (range-- > 0) {
|
||||||
lsx = sx;
|
lsx = sx;
|
||||||
sx += dx;
|
sx += dx;
|
||||||
@@ -4512,7 +4524,7 @@ dobuzz(
|
|||||||
mon->mhp = mon->mhpmax;
|
mon->mhp = mon->mhpmax;
|
||||||
break; /* Out of while loop */
|
break; /* Out of while loop */
|
||||||
}
|
}
|
||||||
if (mon->data == &mons[PM_DEATH] && abstype == ZT_DEATH) {
|
if (mon->data == &mons[PM_DEATH] && damgtype == ZT_DEATH) {
|
||||||
if (canseemon(mon)) {
|
if (canseemon(mon)) {
|
||||||
hit(flash_str(fltyp, FALSE), mon, ".");
|
hit(flash_str(fltyp, FALSE), mon, ".");
|
||||||
pline("%s absorbs the deadly %s!", Monnam(mon),
|
pline("%s absorbs the deadly %s!", Monnam(mon),
|
||||||
@@ -4557,7 +4569,7 @@ 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)
|
if (damgtype != ZT_SLEEP)
|
||||||
wakeup(mon, (type >= 0) ? TRUE : FALSE);
|
wakeup(mon, (type >= 0) ? TRUE : FALSE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4591,10 +4603,10 @@ dobuzz(
|
|||||||
}
|
}
|
||||||
} else if (!Blind) {
|
} else if (!Blind) {
|
||||||
pline("%s whizzes by you!", The(flash_str(fltyp, FALSE)));
|
pline("%s whizzes by you!", The(flash_str(fltyp, FALSE)));
|
||||||
} else if (abstype == ZT_LIGHTNING) {
|
} else if (damgtype == ZT_LIGHTNING) {
|
||||||
Your("%s tingles.", body_part(ARM));
|
Your("%s tingles.", body_part(ARM));
|
||||||
}
|
}
|
||||||
if (abstype == ZT_LIGHTNING)
|
if (damgtype == ZT_LIGHTNING)
|
||||||
(void) flashburn((long) d(nd, 50));
|
(void) flashburn((long) d(nd, 50));
|
||||||
stop_occupation();
|
stop_occupation();
|
||||||
nomul(0);
|
nomul(0);
|
||||||
@@ -4654,7 +4666,7 @@ dobuzz(
|
|||||||
dx = -dx;
|
dx = -dx;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
tmp_at(DISP_CHANGE, zapdir_to_glyph(dx, dy, habstype));
|
tmp_at(DISP_CHANGE, zapdir_to_glyph(dx, dy, hdmgtype));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4662,11 +4674,11 @@ dobuzz(
|
|||||||
if (type == ZT_SPELL(ZT_FIRE))
|
if (type == ZT_SPELL(ZT_FIRE))
|
||||||
explode(sx, sy, type, d(12, 6), 0, EXPL_FIERY);
|
explode(sx, sy, type, d(12, 6), 0, EXPL_FIERY);
|
||||||
if (shopdamage)
|
if (shopdamage)
|
||||||
pay_for_damage(abstype == ZT_FIRE ? "burn away"
|
pay_for_damage(damgtype == ZT_FIRE ? "burn away"
|
||||||
: abstype == ZT_COLD ? "shatter"
|
: damgtype == ZT_COLD ? "shatter"
|
||||||
/* "damage" indicates wall rather than door */
|
/* "damage" indicates wall rather than door */
|
||||||
: abstype == ZT_ACID ? "damage"
|
: damgtype == ZT_ACID ? "damage"
|
||||||
: abstype == ZT_DEATH ? "disintegrate"
|
: damgtype == ZT_DEATH ? "disintegrate"
|
||||||
: "destroy",
|
: "destroy",
|
||||||
FALSE);
|
FALSE);
|
||||||
gb.bhitpos = save_bhitpos;
|
gb.bhitpos = save_bhitpos;
|
||||||
@@ -4786,7 +4798,7 @@ zap_over_floor(
|
|||||||
struct trap *t;
|
struct trap *t;
|
||||||
struct rm *lev = &levl[x][y];
|
struct rm *lev = &levl[x][y];
|
||||||
boolean see_it = cansee(x, y), yourzap;
|
boolean see_it = cansee(x, y), yourzap;
|
||||||
int rangemod = 0, abstype = abs(type) % 10;
|
int rangemod = 0, damgtype = zaptype(type) % 10;
|
||||||
boolean lavawall = (lev->typ == LAVAWALL);
|
boolean lavawall = (lev->typ == LAVAWALL);
|
||||||
|
|
||||||
if (type == PHYS_EXPL_TYPE) {
|
if (type == PHYS_EXPL_TYPE) {
|
||||||
@@ -4794,7 +4806,7 @@ zap_over_floor(
|
|||||||
return -1000; /* not a zap anyway, shouldn't matter */
|
return -1000; /* not a zap anyway, shouldn't matter */
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (abstype) {
|
switch (damgtype) {
|
||||||
case ZT_FIRE:
|
case ZT_FIRE:
|
||||||
t = t_at(x, y);
|
t = t_at(x, y);
|
||||||
if (t && t->ttyp == WEB) {
|
if (t && t->ttyp == WEB) {
|
||||||
@@ -4995,9 +5007,11 @@ zap_over_floor(
|
|||||||
yourzap = (type >= 0 && !exploding_wand_typ);
|
yourzap = (type >= 0 && !exploding_wand_typ);
|
||||||
zapverb = "blast"; /* breath attack or wand explosion */
|
zapverb = "blast"; /* breath attack or wand explosion */
|
||||||
if (!exploding_wand_typ) {
|
if (!exploding_wand_typ) {
|
||||||
if (abs(type) < ZT_SPELL(0))
|
int ztype = zaptype(type); /* 0..29 for both hero and monsters */
|
||||||
|
|
||||||
|
if (ztype < ZT_SPELL(0))
|
||||||
zapverb = "bolt"; /* wand zap */
|
zapverb = "bolt"; /* wand zap */
|
||||||
else if (abs(type) < ZT_BREATH(0))
|
else if (ztype < ZT_BREATH(0))
|
||||||
zapverb = "spell";
|
zapverb = "spell";
|
||||||
} else if (exploding_wand_typ == POT_OIL
|
} else if (exploding_wand_typ == POT_OIL
|
||||||
|| exploding_wand_typ == SCR_FIRE) {
|
|| exploding_wand_typ == SCR_FIRE) {
|
||||||
@@ -5028,7 +5042,7 @@ zap_over_floor(
|
|||||||
const char *see_txt = 0, *sense_txt = 0, *hear_txt = 0;
|
const char *see_txt = 0, *sense_txt = 0, *hear_txt = 0;
|
||||||
|
|
||||||
rangemod = -1000;
|
rangemod = -1000;
|
||||||
switch (abstype) {
|
switch (damgtype) {
|
||||||
case ZT_FIRE:
|
case ZT_FIRE:
|
||||||
new_doormask = D_NODOOR;
|
new_doormask = D_NODOOR;
|
||||||
see_txt = "The door is consumed in flames!";
|
see_txt = "The door is consumed in flames!";
|
||||||
@@ -5100,7 +5114,7 @@ zap_over_floor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (OBJ_AT(x, y) && abstype == ZT_FIRE)
|
if (OBJ_AT(x, y) && damgtype == ZT_FIRE)
|
||||||
if (burn_floor_objects(x, y, FALSE, type > 0) && couldsee(x, y)) {
|
if (burn_floor_objects(x, y, FALSE, type > 0) && couldsee(x, y)) {
|
||||||
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");
|
||||||
@@ -5857,14 +5871,17 @@ makewish(void)
|
|||||||
* Assumes that the caller will specify typ in the appropriate range for
|
* Assumes that the caller will specify typ in the appropriate range for
|
||||||
* wand/spell/breath weapon. */
|
* wand/spell/breath weapon. */
|
||||||
const char*
|
const char*
|
||||||
flash_str(int typ,
|
flash_str(
|
||||||
boolean nohallu) /* suppress hallucination (for death reasons) */
|
int typ,
|
||||||
|
boolean nohallu) /* suppress hallucination (for death reasons) */
|
||||||
{
|
{
|
||||||
static char fltxt[BUFSZ];
|
static char fltxt[BUFSZ];
|
||||||
|
|
||||||
|
typ = zaptype(typ);
|
||||||
if (Hallucination && !nohallu) {
|
if (Hallucination && !nohallu) {
|
||||||
/* always return "blast of foo" for simplicity.
|
/* always return "blast of foo" for simplicity.
|
||||||
* This could be extended with hallucinatory rays, but probably not worth
|
* This could be extended with hallucinatory rays, but probably
|
||||||
* it at this time. */
|
* not worth it at this time. */
|
||||||
Sprintf(fltxt, "blast of %s", rnd_hallublast());
|
Sprintf(fltxt, "blast of %s", rnd_hallublast());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
Reference in New Issue
Block a user