Hallucination vs gaze attacks (trunk only)
Suggested by <Someone> in March, 2005 based on newsgroup discussion
at the time: hallucination protects against touch of death attack by
disrupting how the hero's brain reacts, so why not against gaze attacks
too? This gives hallucinating hero 75% chance of being unaffected by
gazes. If unaffected or if the gazer has been cancelled, the gaze will
fail with some feedback. Previously, all cancelled gazes failed but only
Medusa's gave feedback.
This will give players another way to defeat Medusa, but since it
isn't foolproof and there are several sure fire ways already, I don't
think it'll hurt play balance there. It may be useful to avoid getting
repeatedly stunned by Archons though.
This commit is contained in:
@@ -344,6 +344,7 @@ pile_limit option to control when to switch to "there are objects here"
|
||||
some monsters will use fire to prevent selves being turned into green slime
|
||||
add `#vanquished' debug mode command
|
||||
C and #name commands are now same and use menu to choose monster vs object
|
||||
hallucination provides partial protection against gaze attacks
|
||||
|
||||
|
||||
Platform- and/or Interface-Specific New Features
|
||||
|
||||
@@ -751,7 +751,8 @@ struct obj *obj;
|
||||
pline("Yow! The %s stares back!", mirror);
|
||||
else
|
||||
pline("Yikes! You've frozen yourself!");
|
||||
nomul(-rnd((MAXULEV+6) - u.ulevel));
|
||||
if (!Hallucination || !rn2(4))
|
||||
nomul(-rnd(MAXULEV + 6 - u.ulevel));
|
||||
nomovemsg = 0; /* default, "you can move again" */
|
||||
}
|
||||
} else if (youmonst.data->mlet == S_VAMPIRE)
|
||||
|
||||
148
src/mhitu.c
148
src/mhitu.c
@@ -1921,17 +1921,38 @@ gazemu(mtmp, mattk) /* monster gazes at you */
|
||||
register struct monst *mtmp;
|
||||
register struct attack *mattk;
|
||||
{
|
||||
static const char * const reactions[] = {
|
||||
"confused", /* [0] */
|
||||
"stunned", /* [1] */
|
||||
"puzzled", "dazzled", /* [2,3] */
|
||||
"irritated", "inflamed", /* [4,5] */
|
||||
"tired", /* [6] */
|
||||
"dulled", /* [7] */
|
||||
};
|
||||
int react = -1;
|
||||
boolean cancelled = (mtmp->mcan != 0), already = FALSE;
|
||||
|
||||
/* assumes that hero has to see monster's gaze in order to be
|
||||
affected, rather than monster just having to look at hero;
|
||||
when hallucinating, hero's brain doesn't register what
|
||||
it's seeing correctly so the gaze is usually ineffective
|
||||
[this could be taken a lot farther and select a gaze effect
|
||||
appropriate to what's currently being displayed, giving
|
||||
ordinary monsters a gaze attack when hero thinks he or she
|
||||
is facing a gazing creature, but let's not go that far...] */
|
||||
if (Hallucination && rn2(4)) cancelled = TRUE;
|
||||
|
||||
switch(mattk->adtyp) {
|
||||
case AD_STON:
|
||||
if (mtmp->mcan || !mtmp->mcansee) {
|
||||
case AD_STON:
|
||||
if (cancelled || !mtmp->mcansee) {
|
||||
if (!canseemon(mtmp)) break; /* silently */
|
||||
pline("%s %s.", Monnam(mtmp),
|
||||
(mtmp->data == &mons[PM_MEDUSA] && mtmp->mcan) ?
|
||||
"doesn't look all that ugly" :
|
||||
"gazes ineffectually");
|
||||
break;
|
||||
}
|
||||
if (Reflecting && couldsee(mtmp->mx, mtmp->my) &&
|
||||
}
|
||||
if (Reflecting && couldsee(mtmp->mx, mtmp->my) &&
|
||||
mtmp->data == &mons[PM_MEDUSA]) {
|
||||
/* hero has line of sight to Medusa and she's not blind */
|
||||
boolean useeit = canseemon(mtmp);
|
||||
@@ -1956,8 +1977,8 @@ gazemu(mtmp, mattk) /* monster gazes at you */
|
||||
|
||||
if (mtmp->mhp > 0) break;
|
||||
return 2;
|
||||
}
|
||||
if (canseemon(mtmp) && couldsee(mtmp->mx, mtmp->my) &&
|
||||
}
|
||||
if (canseemon(mtmp) && couldsee(mtmp->mx, mtmp->my) &&
|
||||
!Stone_resistance) {
|
||||
You("meet %s gaze.", s_suffix(mon_nam(mtmp)));
|
||||
stop_occupation();
|
||||
@@ -1967,12 +1988,15 @@ gazemu(mtmp, mattk) /* monster gazes at you */
|
||||
killer.format = KILLED_BY;
|
||||
Strcpy(killer.name, mtmp->data->mname);
|
||||
done(STONING);
|
||||
}
|
||||
break;
|
||||
case AD_CONF:
|
||||
if(!mtmp->mcan && canseemon(mtmp) &&
|
||||
couldsee(mtmp->mx, mtmp->my) &&
|
||||
}
|
||||
break;
|
||||
case AD_CONF:
|
||||
if (canseemon(mtmp) && couldsee(mtmp->mx, mtmp->my) &&
|
||||
mtmp->mcansee && !mtmp->mspec_used && rn2(5)) {
|
||||
if (cancelled) {
|
||||
react = 0; /* "confused" */
|
||||
already = (mtmp->mconf != 0);
|
||||
} else {
|
||||
int conf = d(3,4);
|
||||
|
||||
mtmp->mspec_used = mtmp->mspec_used + (conf + rn2(6));
|
||||
@@ -1984,11 +2008,15 @@ gazemu(mtmp, mattk) /* monster gazes at you */
|
||||
make_confused(HConfusion + conf, FALSE);
|
||||
stop_occupation();
|
||||
}
|
||||
break;
|
||||
case AD_STUN:
|
||||
if(!mtmp->mcan && canseemon(mtmp) &&
|
||||
couldsee(mtmp->mx, mtmp->my) &&
|
||||
}
|
||||
break;
|
||||
case AD_STUN:
|
||||
if (canseemon(mtmp) && couldsee(mtmp->mx, mtmp->my) &&
|
||||
mtmp->mcansee && !mtmp->mspec_used && rn2(5)) {
|
||||
if (cancelled) {
|
||||
react = 1; /* "stunned" */
|
||||
already = (mtmp->mstun != 0);
|
||||
} else {
|
||||
int stun = d(2,6);
|
||||
|
||||
mtmp->mspec_used = mtmp->mspec_used + (stun + rn2(6));
|
||||
@@ -1996,10 +2024,19 @@ gazemu(mtmp, mattk) /* monster gazes at you */
|
||||
make_stunned(HStun + stun, TRUE);
|
||||
stop_occupation();
|
||||
}
|
||||
break;
|
||||
case AD_BLND:
|
||||
if (!mtmp->mcan && canseemon(mtmp) && !resists_blnd(&youmonst)
|
||||
&& distu(mtmp->mx,mtmp->my) <= BOLT_LIM*BOLT_LIM) {
|
||||
}
|
||||
break;
|
||||
case AD_BLND:
|
||||
if (canseemon(mtmp) && !resists_blnd(&youmonst) &&
|
||||
distu(mtmp->mx,mtmp->my) <= BOLT_LIM*BOLT_LIM) {
|
||||
if (cancelled) {
|
||||
react = rn1(2,2); /* "puzzled" || "dazzled" */
|
||||
already = (mtmp->mcansee == 0);
|
||||
/* Archons gaze every round; we don't want cancelled ones
|
||||
giving the "seems puzzled/dazzled" message that often */
|
||||
if (mtmp->mcan && mtmp->data == &mons[PM_ARCHON] && rn2(5))
|
||||
react = -1;
|
||||
} else {
|
||||
int blnd = d((int)mattk->damn, (int)mattk->damd);
|
||||
|
||||
You("are blinded by %s radiance!",
|
||||
@@ -2012,12 +2049,15 @@ gazemu(mtmp, mattk) /* monster gazes at you */
|
||||
if (!Blind) Your(vision_clears);
|
||||
else make_stunned((long)d(1,3),TRUE);
|
||||
}
|
||||
break;
|
||||
case AD_FIRE:
|
||||
if (!mtmp->mcan && canseemon(mtmp) &&
|
||||
couldsee(mtmp->mx, mtmp->my) &&
|
||||
}
|
||||
break;
|
||||
case AD_FIRE:
|
||||
if (canseemon(mtmp) && couldsee(mtmp->mx, mtmp->my) &&
|
||||
mtmp->mcansee && !mtmp->mspec_used && rn2(5)) {
|
||||
int dmg = d(2,6);
|
||||
if (cancelled) {
|
||||
react = rn1(2,4); /* "irritated" || "inflamed" */
|
||||
} else {
|
||||
int dmg = d(2,6), lev = (int)mtmp->m_lev;
|
||||
|
||||
pline("%s attacks you with a fiery gaze!", Monnam(mtmp));
|
||||
stop_occupation();
|
||||
@@ -2026,37 +2066,53 @@ gazemu(mtmp, mattk) /* monster gazes at you */
|
||||
dmg = 0;
|
||||
}
|
||||
burn_away_slime();
|
||||
if ((int) mtmp->m_lev > rn2(20))
|
||||
destroy_item(SCROLL_CLASS, AD_FIRE);
|
||||
if ((int) mtmp->m_lev > rn2(20))
|
||||
destroy_item(POTION_CLASS, AD_FIRE);
|
||||
if ((int) mtmp->m_lev > rn2(25))
|
||||
destroy_item(SPBOOK_CLASS, AD_FIRE);
|
||||
if (lev > rn2(20)) destroy_item(SCROLL_CLASS, AD_FIRE);
|
||||
if (lev > rn2(20)) destroy_item(POTION_CLASS, AD_FIRE);
|
||||
if (lev > rn2(25)) destroy_item(SPBOOK_CLASS, AD_FIRE);
|
||||
if (dmg) mdamageu(mtmp, dmg);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
#ifdef PM_BEHOLDER /* work in progress */
|
||||
case AD_SLEE:
|
||||
if(!mtmp->mcan && canseemon(mtmp) &&
|
||||
couldsee(mtmp->mx, mtmp->my) && mtmp->mcansee &&
|
||||
multi >= 0 && !rn2(5) && !Sleep_resistance) {
|
||||
|
||||
case AD_SLEE:
|
||||
if (canseemon(mtmp) && couldsee(mtmp->mx, mtmp->my) &&
|
||||
mtmp->mcansee && multi >= 0 && !rn2(5) && !Sleep_resistance) {
|
||||
if (cancelled) {
|
||||
react = 6; /* "tired" */
|
||||
already = (mtmp->mfrozen != 0); /* can't happen... */
|
||||
} else {
|
||||
fall_asleep(-rnd(10), TRUE);
|
||||
pline("%s gaze makes you very sleepy...",
|
||||
s_suffix(Monnam(mtmp)));
|
||||
}
|
||||
break;
|
||||
case AD_SLOW:
|
||||
if(!mtmp->mcan && canseemon(mtmp) && mtmp->mcansee &&
|
||||
(HFast & (INTRINSIC|TIMEOUT)) &&
|
||||
!defends(AD_SLOW, uwep) && !rn2(4))
|
||||
|
||||
}
|
||||
break;
|
||||
case AD_SLOW:
|
||||
if (canseemon(mtmp) && couldsee(mtmp->mx, mtmp->my) &&
|
||||
mtmp->mcansee && (HFast & (INTRINSIC|TIMEOUT)) &&
|
||||
!defends(AD_SLOW, uwep) && !rn2(4)) {
|
||||
if (cancelled) {
|
||||
react = 7; /* "dulled" */
|
||||
already = (mtmp->mspeed == MSLOW);
|
||||
} else {
|
||||
u_slow_down();
|
||||
stop_occupation();
|
||||
break;
|
||||
#endif
|
||||
default: impossible("Gaze attack %d?", mattk->adtyp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif /* BEHOLDER */
|
||||
default:
|
||||
impossible("Gaze attack %d?", mattk->adtyp);
|
||||
break;
|
||||
}
|
||||
if (react >= 0) {
|
||||
if (Hallucination && rn2(3)) react = rn2(SIZE(reactions));
|
||||
/* cancelled/hallucinatory feedback; monster might look "confused",
|
||||
"stunned",&c but we don't actually set corresponding attribute */
|
||||
pline("%s looks %s%s.", Monnam(mtmp),
|
||||
!rn2(3) ? "" : already ? "quite " :
|
||||
(!rn2(2) ? "a bit " : "somewhat "),
|
||||
reactions[react]);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -1085,10 +1085,12 @@ dogaze()
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if (Blind) {
|
||||
You_cant("see anything to gaze at.");
|
||||
return 0;
|
||||
} else if (Hallucination) {
|
||||
You_cant("gaze at anything you can see.");
|
||||
return 0;
|
||||
}
|
||||
if (u.uen < 15) {
|
||||
You("lack the energy to use your special gaze!");
|
||||
@@ -1109,12 +1111,10 @@ dogaze()
|
||||
|| mtmp->m_ap_type == M_AP_OBJECT) {
|
||||
looked--;
|
||||
continue;
|
||||
} else if (flags.safe_dog && !Confusion && !Hallucination
|
||||
&& mtmp->mtame) {
|
||||
} else if (flags.safe_dog && mtmp->mtame && !Confusion) {
|
||||
You("avoid gazing at %s.", y_monnam(mtmp));
|
||||
} else {
|
||||
if (flags.confirm && mtmp->mpeaceful && !Confusion
|
||||
&& !Hallucination) {
|
||||
if (flags.confirm && mtmp->mpeaceful && !Confusion) {
|
||||
Sprintf(qbuf, "Really %s %s?",
|
||||
(adtyp == AD_CONF) ? "confuse" : "attack",
|
||||
mon_nam(mtmp));
|
||||
@@ -1137,26 +1137,28 @@ dogaze()
|
||||
Monnam(mtmp));
|
||||
mtmp->mconf = 1;
|
||||
} else if (adtyp == AD_FIRE) {
|
||||
int dmg = d(2,6);
|
||||
int dmg = d(2,6), lev = (int)u.ulevel;
|
||||
|
||||
You("attack %s with a fiery gaze!", mon_nam(mtmp));
|
||||
if (resists_fire(mtmp)) {
|
||||
pline_The("fire doesn't burn %s!", mon_nam(mtmp));
|
||||
dmg = 0;
|
||||
}
|
||||
if((int) u.ulevel > rn2(20))
|
||||
if (lev > rn2(20))
|
||||
(void) destroy_mitem(mtmp, SCROLL_CLASS, AD_FIRE);
|
||||
if((int) u.ulevel > rn2(20))
|
||||
if (lev > rn2(20))
|
||||
(void) destroy_mitem(mtmp, POTION_CLASS, AD_FIRE);
|
||||
if((int) u.ulevel > rn2(25))
|
||||
if (lev > rn2(25))
|
||||
(void) destroy_mitem(mtmp, SPBOOK_CLASS, AD_FIRE);
|
||||
if (dmg && !DEADMONSTER(mtmp)) mtmp->mhp -= dmg;
|
||||
if (dmg) mtmp->mhp -= dmg;
|
||||
if (mtmp->mhp <= 0) killed(mtmp);
|
||||
}
|
||||
/* For consistency with passive() in uhitm.c, this only
|
||||
* affects you if the monster is still alive.
|
||||
*/
|
||||
if (!DEADMONSTER(mtmp) &&
|
||||
(mtmp->data==&mons[PM_FLOATING_EYE]) && !mtmp->mcan) {
|
||||
if (DEADMONSTER(mtmp)) continue;
|
||||
|
||||
if (mtmp->data == &mons[PM_FLOATING_EYE] && !mtmp->mcan) {
|
||||
if (!Free_action) {
|
||||
You("are frozen by %s gaze!",
|
||||
s_suffix(mon_nam(mtmp)));
|
||||
@@ -1175,8 +1177,7 @@ dogaze()
|
||||
* works on the monster's turn, but for it to *not* have an
|
||||
* effect would be too weird.
|
||||
*/
|
||||
if (!DEADMONSTER(mtmp) &&
|
||||
(mtmp->data == &mons[PM_MEDUSA]) && !mtmp->mcan) {
|
||||
if (mtmp->data == &mons[PM_MEDUSA] && !mtmp->mcan) {
|
||||
pline(
|
||||
"Gazing at the awake %s is not a very good idea.",
|
||||
l_monnam(mtmp));
|
||||
|
||||
@@ -2352,6 +2352,10 @@ boolean wep_was_destroyed;
|
||||
else if (Free_action)
|
||||
You("momentarily stiffen under %s gaze!",
|
||||
s_suffix(mon_nam(mon)));
|
||||
else if (Hallucination && rn2(4))
|
||||
pline("%s looks %s%s.", Monnam(mon),
|
||||
!rn2(2) ? "" : "rather ",
|
||||
!rn2(2) ? "numb" : "stupified");
|
||||
else {
|
||||
You("are frozen by %s gaze!",
|
||||
s_suffix(mon_nam(mon)));
|
||||
|
||||
Reference in New Issue
Block a user