mirror fixes (trunk only)
From some notes I made prior to release of 3.4.3, about applying a carried mirror in the direction of a monster: invisible player applying mirror toward monster which can't see invisible should have no effect (monster can't see hero's equipment); similarly when inside engulfer regardless of whether it can see invisible; applying mirror at worm tail shouldn't work but does; applying mirror toward unseen monster that can see invisible (so should be able to see its own image) doesn't work because bhit() won't target it; mirror shouldn't work when target is only visible via infravision. The fourth one is iffy since it assumes that invisible monsters produce invisible reflections rather than no reflections. The reverse of that is probably more reasonable but isn't as interesting. The fifth one may be contradictory; it fails to extend that logic to "infravisible monsters produce infravisible reflections."
This commit is contained in:
@@ -228,6 +228,7 @@ eliminate case-sensitivity when converting words from singular to plural and
|
||||
vice versa, so some failing wishes like "Gauntlets of Power" now work
|
||||
breath attack directed at self by poly'd hero always hits
|
||||
override non-silver vs shades for artifacts which deal extra damage to undead
|
||||
assorted mirror fixes--mainly visibility issues
|
||||
|
||||
|
||||
Platform- and/or Interface-Specific Fixes
|
||||
|
||||
85
src/apply.c
85
src/apply.c
@@ -4,6 +4,8 @@
|
||||
|
||||
#include "hack.h"
|
||||
|
||||
extern boolean notonhead; /* for long worms */
|
||||
|
||||
static const char tools[] = { TOOL_CLASS, WEAPON_CLASS, WAND_CLASS, 0 };
|
||||
static const char tools_too[] = { ALL_CLASSES, TOOL_CLASS, POTION_CLASS,
|
||||
WEAPON_CLASS, WAND_CLASS, GEM_CLASS, 0 };
|
||||
@@ -717,12 +719,20 @@ STATIC_OVL int
|
||||
use_mirror(obj)
|
||||
struct obj *obj;
|
||||
{
|
||||
const char *mirror;
|
||||
const char *mirror, *uvisage;
|
||||
struct monst *mtmp;
|
||||
unsigned how_seen;
|
||||
char mlet;
|
||||
boolean vis;
|
||||
boolean vis, invis_mirror, useeit, monable;
|
||||
|
||||
if(!getdir((char *)0)) return 0;
|
||||
invis_mirror = Invis;
|
||||
#ifdef INVISIBLE_OBJECTS
|
||||
if (obj->oinvis) invis_mirror = TRUE;
|
||||
#endif
|
||||
useeit = !Blind && (!invis_mirror || See_invisible);
|
||||
uvisage = (ACURR(A_CHA) > 14) ?
|
||||
(poly_gender() == 1 ? "beautiful" : "handsome") : "ugly";
|
||||
mirror = simpleonames(obj); /* "mirror" or "looking glass" */
|
||||
if(obj->cursed && !rn2(2)) {
|
||||
if (!Blind)
|
||||
@@ -730,7 +740,9 @@ struct obj *obj;
|
||||
return 1;
|
||||
}
|
||||
if(!u.dx && !u.dy && !u.dz) {
|
||||
if(!Blind && !Invisible) {
|
||||
if (!useeit) {
|
||||
You_cant("see your %s %s.", uvisage, body_part(FACE));
|
||||
} else {
|
||||
if (u.umonnum == PM_FLOATING_EYE) {
|
||||
if (Free_action) {
|
||||
You("stiffen momentarily under your gaze.");
|
||||
@@ -753,32 +765,26 @@ struct obj *obj;
|
||||
You(look_str, "peaked");
|
||||
else if (u.uhs >= WEAK)
|
||||
You(look_str, "undernourished");
|
||||
else You("look as %s as ever.",
|
||||
ACURR(A_CHA) > 14 ?
|
||||
(poly_gender()==1 ? "beautiful" : "handsome") :
|
||||
"ugly");
|
||||
} else {
|
||||
You_cant("see your %s %s.",
|
||||
ACURR(A_CHA) > 14 ?
|
||||
(poly_gender()==1 ? "beautiful" : "handsome") :
|
||||
"ugly",
|
||||
body_part(FACE));
|
||||
else
|
||||
You("look as %s as ever.", uvisage);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
if(u.uswallow) {
|
||||
if (!Blind) You("reflect %s %s.", s_suffix(mon_nam(u.ustuck)),
|
||||
mbodypart(u.ustuck, STOMACH));
|
||||
if (useeit)
|
||||
You("reflect %s %s.", s_suffix(mon_nam(u.ustuck)),
|
||||
mbodypart(u.ustuck, STOMACH));
|
||||
return 1;
|
||||
}
|
||||
if(Underwater) {
|
||||
You(Hallucination ?
|
||||
"give the fish a chance to fix their makeup." :
|
||||
"reflect the murky water.");
|
||||
if (useeit)
|
||||
You(Hallucination ?
|
||||
"give the fish a chance to fix their makeup." :
|
||||
"reflect the murky water.");
|
||||
return 1;
|
||||
}
|
||||
if(u.dz) {
|
||||
if (!Blind)
|
||||
if (useeit)
|
||||
You("reflect the %s.",
|
||||
(u.dz > 0) ? surface(u.ux,u.uy) : ceiling(u.ux,u.uy));
|
||||
return 1;
|
||||
@@ -787,10 +793,18 @@ struct obj *obj;
|
||||
(int FDECL((*),(MONST_P,OBJ_P)))0,
|
||||
(int FDECL((*),(OBJ_P,OBJ_P)))0,
|
||||
&obj);
|
||||
if (!mtmp || !haseyes(mtmp->data))
|
||||
if (!mtmp || !haseyes(mtmp->data) || notonhead)
|
||||
return 1;
|
||||
|
||||
/* couldsee(mtmp->mx, mtmp->my) is implied by the fact that bhit()
|
||||
targetted it, so we can ignore possibility of X-ray vision */
|
||||
vis = canseemon(mtmp);
|
||||
/* ways to directly see monster (excludes X-ray vision, telepathy,
|
||||
extended detection, type-specific warning) */
|
||||
#define SEENMON (MONSEEN_NORMAL | MONSEEN_SEEINVIS | MONSEEN_INFRAVIS)
|
||||
how_seen = vis ? howmonseen(mtmp) : 0;
|
||||
/* whether monster is able to use its vision-based capabilities */
|
||||
monable = !mtmp->mcan && (!mtmp->minvis || perceives(mtmp->data));
|
||||
mlet = mtmp->data->mlet;
|
||||
if (mtmp->msleeping) {
|
||||
if (vis)
|
||||
@@ -799,20 +813,27 @@ struct obj *obj;
|
||||
} else if (!mtmp->mcansee) {
|
||||
if (vis)
|
||||
pline("%s can't see anything right now.", Monnam(mtmp));
|
||||
} else if (invis_mirror && !perceives(mtmp->data)) {
|
||||
if (vis)
|
||||
pline("%s fails to notice your %s.", Monnam(mtmp), mirror);
|
||||
/* infravision doesn't produce an image in the mirror */
|
||||
} else if ((how_seen & SEENMON) == MONSEEN_INFRAVIS) {
|
||||
if (vis) /* (redundant) */
|
||||
pline("%s is too far away to see %sself in the dark.",
|
||||
Monnam(mtmp), mhim(mtmp));
|
||||
/* some monsters do special things */
|
||||
} else if (mlet == S_VAMPIRE || mlet == S_GHOST || is_vampshifter(mtmp)) {
|
||||
} else if (mlet == S_VAMPIRE || mlet == S_GHOST ||
|
||||
is_vampshifter(mtmp)) {
|
||||
if (vis)
|
||||
pline("%s doesn't have a reflection.", Monnam(mtmp));
|
||||
} else if(!mtmp->mcan && !mtmp->minvis &&
|
||||
mtmp->data == &mons[PM_MEDUSA]) {
|
||||
} else if (monable && mtmp->data == &mons[PM_MEDUSA]) {
|
||||
if (mon_reflects(mtmp, "The gaze is reflected away by %s %s!"))
|
||||
return 1;
|
||||
if (vis)
|
||||
pline("%s is turned to stone!", Monnam(mtmp));
|
||||
stoned = TRUE;
|
||||
killed(mtmp);
|
||||
} else if(!mtmp->mcan && !mtmp->minvis &&
|
||||
mtmp->data == &mons[PM_FLOATING_EYE]) {
|
||||
} else if (monable && mtmp->data == &mons[PM_FLOATING_EYE]) {
|
||||
int tmp = d((int)mtmp->m_lev, (int)mtmp->data->mattk[0].damd);
|
||||
if (!rn2(4)) tmp = 120;
|
||||
if (vis)
|
||||
@@ -820,12 +841,11 @@ struct obj *obj;
|
||||
else
|
||||
You_hear("%s stop moving.", something);
|
||||
paralyze_monst(mtmp, (int)mtmp->mfrozen + tmp);
|
||||
} else if(!mtmp->mcan && !mtmp->minvis &&
|
||||
mtmp->data == &mons[PM_UMBER_HULK]) {
|
||||
} else if (monable && mtmp->data == &mons[PM_UMBER_HULK]) {
|
||||
if (vis)
|
||||
pline("%s confuses itself!", Monnam(mtmp));
|
||||
mtmp->mconf = 1;
|
||||
} else if (!mtmp->mcan && !mtmp->minvis &&
|
||||
} else if (monable &&
|
||||
(mlet == S_NYMPH ||
|
||||
mtmp->data == &mons[PM_SUCCUBUS] ||
|
||||
mtmp->data == &mons[PM_INCUBUS])) {
|
||||
@@ -849,10 +869,11 @@ struct obj *obj;
|
||||
} else if (!Blind) {
|
||||
if (mtmp->minvis && !See_invisible)
|
||||
;
|
||||
else if ((mtmp->minvis && !perceives(mtmp->data))
|
||||
|| !haseyes(mtmp->data))
|
||||
pline("%s doesn't seem to notice its reflection.",
|
||||
Monnam(mtmp));
|
||||
else if ((mtmp->minvis && !perceives(mtmp->data)) ||
|
||||
/* redundant: can't get here if these are true */
|
||||
!haseyes(mtmp->data) || notonhead || !mtmp->mcansee)
|
||||
pline("%s doesn't seem to notice %s reflection.",
|
||||
Monnam(mtmp), mhis(mtmp));
|
||||
else
|
||||
pline("%s ignores %s reflection.",
|
||||
Monnam(mtmp), mhis(mtmp));
|
||||
|
||||
52
src/zap.c
52
src/zap.c
@@ -2994,37 +2994,39 @@ struct obj **pobj; /* object tossed/used, set to NULL
|
||||
if (mtmp && !(in_skip && M_IN_WATER(mtmp->data))) {
|
||||
notonhead = (bhitpos.x != mtmp->mx ||
|
||||
bhitpos.y != mtmp->my);
|
||||
if (weapon != FLASHED_LIGHT) {
|
||||
if(weapon != ZAPPED_WAND) {
|
||||
if(weapon != INVIS_BEAM) tmp_at(DISP_END, 0);
|
||||
if (cansee(bhitpos.x,bhitpos.y) && !canspotmon(mtmp)) {
|
||||
if (weapon != INVIS_BEAM) {
|
||||
map_invisible(bhitpos.x, bhitpos.y);
|
||||
return(mtmp);
|
||||
}
|
||||
} else
|
||||
return(mtmp);
|
||||
}
|
||||
if (weapon != INVIS_BEAM) {
|
||||
(*fhitm)(mtmp, obj);
|
||||
range -= 3;
|
||||
}
|
||||
} else {
|
||||
/* FLASHED_LIGHT hitting invisible monster
|
||||
should pass through instead of stop so
|
||||
we call flash_hits_mon() directly rather
|
||||
than returning mtmp back to caller. That
|
||||
allows the flash to keep on going. Note
|
||||
that we use mtmp->minvis not canspotmon()
|
||||
because it makes no difference whether
|
||||
the hero can see the monster or not.*/
|
||||
if (weapon == FLASHED_LIGHT) {
|
||||
/* FLASHED_LIGHT hitting invisible monster should
|
||||
pass through instead of stop so we call
|
||||
flash_hits_mon() directly rather than returning
|
||||
mtmp back to caller. That allows the flash to
|
||||
keep on going. Note that we use mtmp->minvis
|
||||
not canspotmon() because it makes no difference
|
||||
whether the hero can see the monster or not. */
|
||||
if (mtmp->minvis) {
|
||||
obj->ox = u.ux, obj->oy = u.uy;
|
||||
(void) flash_hits_mon(mtmp, obj);
|
||||
} else {
|
||||
tmp_at(DISP_END, 0);
|
||||
return(mtmp); /* caller will call flash_hits_mon */
|
||||
return mtmp; /* caller will call flash_hits_mon */
|
||||
}
|
||||
} else if (weapon == INVIS_BEAM) {
|
||||
/* Like FLASHED_LIGHT, INVIS_BEAM should continue
|
||||
through invisible targets; unlike it, we aren't
|
||||
prepared for multiple hits so just get first one
|
||||
that's either visible or could see its invisible
|
||||
self. [No tmp_at() cleanup is needed here.] */
|
||||
if (!mtmp->minvis || perceives(mtmp->data))
|
||||
return mtmp;
|
||||
} else if (weapon != ZAPPED_WAND) {
|
||||
/* THROWN_WEAPON, KICKED_WEAPON */
|
||||
tmp_at(DISP_END, 0);
|
||||
if (cansee(bhitpos.x, bhitpos.y) && !canspotmon(mtmp))
|
||||
map_invisible(bhitpos.x, bhitpos.y);
|
||||
return mtmp;
|
||||
} else {
|
||||
/* ZAPPED_WAND */
|
||||
(*fhitm)(mtmp, obj);
|
||||
range -= 3;
|
||||
}
|
||||
} else {
|
||||
if (weapon == ZAPPED_WAND && obj->otyp == WAN_PROBING &&
|
||||
|
||||
Reference in New Issue
Block a user