fix pull request #485 - genetic engineer attacks

Pull request fixed two genetic engineer problems:
1) lack of "you hit <foo>" message when you were poly'd into one;
2) lack of shield effect animation ('sparkle') when a genetic
   engineer hit magic resistant hero.

That opened a can o' worms.
3) hero lacking see invisible, poly'd into genetic engineer, and
   turning target into an invisible stalker got no feedback about
   the target vanishing.

A genetic engineer attacking a monster would polymorph it turn
after turn.
4) put back the teleport capability I removed when bringing it over
   from slash'em;
5) have genetic engineer teleport away after polymorphing someone.

The various mhitm_ad_XXXX() routines used g.vis to have caller
decide visibility, but hmonas() for poly'd hero didn't set that so
some messages--not just attack induced polymorph--were based on
visibility of earlier monster vs monster activity.
6) have hmonas() set up g.vis even though it doesn't use that.

There may have been one or two other minor fixes before I managed
to force the lid back onto the can.

Fixes #485
This commit is contained in:
PatR
2021-04-04 20:06:45 -07:00
parent 7d77267f93
commit 28f112fb17
4 changed files with 41 additions and 18 deletions

View File

@@ -584,6 +584,9 @@ avoid "Not carrying anything. Never mind." for 'force_invmenu'
'altmeta' option could be toggled On but once On could not be toggled back Off
wearing a ring of protection and any amulet behaved as if wearing an amulet of
guarding when determining MC value
messaging for genetic engineer attacks had several problems
give genetic engineers teleport capability (as they had in slash'em); 'port
away after polymorphing someone so that they don't just repeat that
curses: 'msg_window' option wasn't functional for curses unless the binary
also included tty support

View File

@@ -946,9 +946,11 @@ mdamagem(struct monst *magr, struct monst *mdef,
int
mon_poly(struct monst *magr, struct monst *mdef, int dmg)
{
static const char freaky[] = " undergoes a freakish metamorphosis";
if (mdef == &g.youmonst) {
if (Antimagic) {
shieldeff(mdef->mx, mdef->my);
shieldeff(u.ux, u.uy);
} else if (Unchanging) {
; /* just take a little damage */
} else {
@@ -994,14 +996,27 @@ mon_poly(struct monst *magr, struct monst *mdef, int dmg)
monkilled(mdef, "", AD_RBRE);
}
} else if (newcham(mdef, (struct permonst *) 0, FALSE, FALSE)) {
if (g.vis && canspotmon(mdef))
pline("%s%s turns into %s.", Before,
!flags.verbose ? ""
: " undergoes a freakish metamorphosis and",
x_monnam(mdef, ARTICLE_A, (char *) 0,
(SUPPRESS_NAME | SUPPRESS_IT
| SUPPRESS_INVISIBLE), FALSE));
if (g.vis) { /* either seen or adjacent */
boolean was_seen = !!strcmpi("It", Before),
verbosely = flags.verbose || !was_seen;
if (canspotmon(mdef))
pline("%s%s%s turns into %s.", Before,
verbosely ? freaky : "", verbosely ? " and" : "",
x_monnam(mdef, ARTICLE_A, (char *) 0,
(SUPPRESS_NAME | SUPPRESS_IT
| SUPPRESS_INVISIBLE), FALSE));
else if (was_seen || magr == &g.youmonst)
pline("%s%s%s.", Before, freaky,
!was_seen ? "" : " and disappears");
}
dmg = 0;
if (can_teleport(magr->data)) {
if (magr == &g.youmonst)
tele();
else if (!tele_restrict(magr))
(void) rloc(magr, TRUE);
}
} else {
if (g.vis && flags.verbose)
pline1(nothing_happens);

View File

@@ -1760,7 +1760,7 @@ struct permonst _mons2[] = {
A(ATTK(AT_CLAW, AD_POLY, 1, 4),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(WT_HUMAN, 20, MS_HUMANOID, MZ_HUMAN), MR_POISON, 0,
M1_HUMANOID | M1_OMNIVORE | M1_POIS, M2_HOSTILE | M2_NASTY,
M1_HUMANOID | M1_OMNIVORE | M1_POIS | M1_TPORT, M2_HOSTILE | M2_NASTY,
M3_INFRAVISIBLE, 14, CLR_GREEN),
/*
* Rust monster or disenchanter

View File

@@ -3087,27 +3087,27 @@ mhitm_ad_conf(struct monst *magr, struct attack *mattk, struct monst *mdef,
}
void
mhitm_ad_poly(struct monst *magr,
struct attack *mattk UNUSED, /* implied */
struct monst *mdef,
struct mhitm_data *mhm)
mhitm_ad_poly(struct monst *magr, struct attack *mattk,
struct monst *mdef, struct mhitm_data *mhm)
{
if (magr == &g.youmonst) {
/* uhitm */
int armpro = magic_negation(mdef);
/* since hero can't be cancelled, only defender's armor applies */
boolean negated = !(rn2(10) >= 3 * armpro);
/* require weaponless attack in order to honor AD_POLY;
since hero can't be cancelled, only defender's armor applies */
boolean negated = uwep || !(rn2(10) >= 3 * armpro);
if (!negated && mhm->damage < mdef->mhp)
mhm->damage = mon_poly(magr, mdef, mhm->damage);
mhm->damage = mon_poly(&g.youmonst, mdef, mhm->damage);
} else if (mdef == &g.youmonst) {
/* mhitu */
int armpro = magic_negation(mdef);
int armpro = magic_negation(&g.youmonst);
boolean uncancelled = !magr->mcan && (rn2(10) >= 3 * armpro);
hitmsg(magr, mattk);
if (uncancelled
&& Maybe_Half_Phys(mhm->damage) < (Upolyd ? u.mh : u.uhp))
mhm->damage = mon_poly(magr, mdef, mhm->damage);
mhm->damage = mon_poly(magr, &g.youmonst, mhm->damage);
} else {
/* mhitm */
if (!magr->mcan && mhm->damage < mdef->mhp)
@@ -4414,6 +4414,9 @@ hmonas(struct monst *mon)
dhit = 0, attknum = 0;
int dieroll, multi_claw = 0;
/* not used here but umpteen mhitm_ad_xxxx() need this */
g.vis = (canseemon(mon) || distu(mon->mx, mon->my) <= 2);
/* with just one touch/claw/weapon attack, both rings matter;
with more than one, alternate right and left when checking
whether silver ring causes successful hit */
@@ -4793,6 +4796,8 @@ hmonas(struct monst *mon)
if (g.multi < 0)
break; /* If paralyzed while attacking, i.e. floating eye */
}
g.vis = FALSE; /* reset */
/* return value isn't used, but make it match hitum()'s */
return !DEADMONSTER(mon);
}