Sunsword #invoke, directed at self

Give a resistance animation if you #invoke Sunsword while it's
wielded and direct its blinding ray at yourself.  Flashing a camera
at a monster who is wielding it will also produce the animation.
This commit is contained in:
PatR
2024-04-19 10:50:46 -07:00
parent aaea81c6ac
commit 9d71c8e1f4
6 changed files with 60 additions and 33 deletions

View File

@@ -1773,6 +1773,7 @@ extern boolean defended(struct monst *, int) NONNULLARG1;
extern boolean resists_drli(struct monst *) NONNULLARG1;
extern boolean resists_magm(struct monst *) NONNULLARG1;
extern boolean resists_blnd(struct monst *) NONNULLARG1;
extern boolean resists_blnd_by_arti(struct monst *) NONNULLARG1;
extern boolean can_blnd(struct monst *, struct monst *,
uchar, struct obj *) NONNULLARG2;
extern boolean ranged_attk(struct permonst *) NONNULLARG1;
@@ -3829,7 +3830,7 @@ extern int dozap(void);
extern int zapyourself(struct obj *, boolean) NONNULLARG1;
extern void ubreatheu(struct attack *) NONNULLARG1;
extern int lightdamage(struct obj *, boolean, int) NONNULLARG1;
extern boolean flashburn(long);
extern boolean flashburn(long, boolean);
extern boolean cancel_monst(struct monst *, struct obj *, boolean, boolean,
boolean) NONNULLARG12;
extern void zapsetup(void);

View File

@@ -1942,7 +1942,8 @@ arti_invoke(struct obj *obj)
if (vulnerable) /* could be fatal if Unchanging */
(void) lightdamage(obj, TRUE, 2 * damg);
if (!flashburn((long) (damg + rnd(damg))) && !vulnerable)
if (!flashburn((long) (damg + rnd(damg)), FALSE)
&& !vulnerable)
pline("%s", nothing_seems_to_happen);
}
} else {

View File

@@ -688,7 +688,7 @@ cast_cleric_spell(struct monst *mtmp, int dmg, int spellnum)
do this before maybe blinding the hero via flashburn() */
mon_spell_hits_spot(mtmp, AD_ELEC, u.ux, u.uy);
/* blind hero; no effect if already blind */
(void) flashburn((long) rnd(100));
(void) flashburn((long) rnd(100), TRUE);
break;
}
case CLC_CURSE_ITEMS:

View File

@@ -170,14 +170,13 @@ resists_magm(struct monst *mon)
return FALSE;
}
/* True iff monster is resistant to light-induced blindness */
/* True iff monster is resistant to light-induced blindness due to some
mundane reason (already blinded) */
boolean
resists_blnd(struct monst *mon)
{
struct permonst *ptr = mon->data;
boolean is_you = (mon == &gy.youmonst);
long slotmask;
struct obj *o;
if (is_you ? (Blind || Unaware)
: (mon->mblinded || !mon->mcansee || !haseyes(ptr)
@@ -189,21 +188,32 @@ resists_blnd(struct monst *mon)
if (dmgtype_fromattack(ptr, AD_BLND, AT_EXPL)
|| dmgtype_fromattack(ptr, AD_BLND, AT_GAZE))
return TRUE;
return resists_blnd_by_arti(mon);
}
/* True iff monster is resistant to light-induced blindness due to worn
or wielded magical equipment (used to decide whether to show sparkle
animation when resisting) */
boolean
resists_blnd_by_arti(struct monst *mon)
{
struct obj *o;
boolean is_you = (mon == &gy.youmonst);
o = is_you ? uwep : MON_WEP(mon);
if (o && o->oartifact && defends(AD_BLND, o))
return TRUE;
o = is_you ? gi.invent : mon->minvent;
slotmask = W_ARMOR | W_ACCESSORY;
if (!is_you /* assumes monsters don't wield non-weapons */
|| (uwep && (uwep->oclass == WEAPON_CLASS || is_weptool(uwep))))
slotmask |= W_WEP;
if (is_you && u.twoweap)
slotmask |= W_SWAPWEP;
for (; o; o = o->nobj)
if (((o->owornmask & slotmask) != 0L
&& objects[o->otyp].oc_oprop == BLINDED)
|| (o->oartifact && defends_when_carried(AD_BLND, o)))
if (defends_when_carried(AD_BLND, o))
return TRUE;
#if 0 /* omit this; the Eyes of the Overworld have no carry property and
* their worn property is magic resistance rather than blindness
* resistance; wearing them blocks blindness without actually
* preventing it, so don't classify them as providing resistance */
if (is_you && is_art(uamul, ART_EYES_OF_THE_OVERWORLD))
return TRUE;
#endif /* 0 */
return FALSE;
}

View File

@@ -6097,17 +6097,17 @@ flash_hits_mon(
struct obj *otmp) /* source of flash */
{
struct rm *lev;
coordxy mx = mtmp->mx, my = mtmp->my;
int tmp, amt, useeit, res = 0;
if (gn.notonhead)
return 0;
lev = &levl[mtmp->mx][mtmp->my];
lev = &levl[mx][my];
useeit = canseemon(mtmp);
if (M_AP_TYPE(mtmp) != M_AP_NOTHING) {
char whatbuf[BUFSZ];
coordxy x = mtmp->mx, y = mtmp->my;
int oldglyph = glyph_at(x, y);
int oldglyph = glyph_at(mx, my);
/* 'altmon' probably doesn't matter here because 'whatbuf' will
only be shown if the glyph changes and wakeup() doesn't call
@@ -6118,13 +6118,14 @@ flash_hits_mon(
* finish_meating() to end quickmimic */
/* if glyph has changed then hero saw something happen */
if (glyph_at(x, y) != oldglyph)
if (glyph_at(mx, my) != oldglyph) {
pline("That %s is really %s%c", whatbuf,
/* y_monnam()+a_monnam() */
x_monnam(mtmp, mtmp->mtame ? ARTICLE_YOUR : ARTICLE_A,
(char *) 0, 0, FALSE),
mtmp->mtame ? '.' : '!');
res = 1; /* mtmp is affected whether hero sees it or not */
res = 1;
}
}
if (mtmp->msleeping && haseyes(mtmp->data)) {
@@ -6135,15 +6136,15 @@ flash_hits_mon(
}
} else if (mtmp->data->mlet != S_LIGHT) {
if (!resists_blnd(mtmp)) {
tmp = dist2(otmp->ox, otmp->oy, mtmp->mx, mtmp->my);
tmp = dist2(otmp->ox, otmp->oy, mx, my);
if (useeit) {
pline("%s is blinded by the flash!", Monnam(mtmp));
res = 1;
}
if (mtmp->data == &mons[PM_GREMLIN]) {
/* Rule #1: Keep them out of the light. */
amt = otmp->otyp == WAN_LIGHT ? d(1 + otmp->spe, 4)
: rn2(min(mtmp->mhp, 4));
amt = (otmp->otyp == WAN_LIGHT) ? d(1 + otmp->spe, 4)
: rnd(min(mtmp->mhp, 4));
light_hits_gremlin(mtmp, amt);
}
if (!DEADMONSTER(mtmp)) {
@@ -6154,12 +6155,16 @@ flash_hits_mon(
mtmp->mcansee = 0;
mtmp->mblinded = (tmp < 3) ? 0 : rnd(1 + 50 / tmp);
}
} else if (flags.verbose && useeit) {
if (lev->lit)
pline("The flash of light shines on %s.", mon_nam(mtmp));
else
pline("%s is illuminated.", Monnam(mtmp));
res = 2; /* 'message has been given' temporary value */
} else if (useeit) {
if (resists_blnd_by_arti(mtmp))
shieldeff(mx, my);
if (flags.verbose) {
if (lev->lit)
pline("The flash of light shines on %s.", mon_nam(mtmp));
else
pline("%s is illuminated.", Monnam(mtmp));
res = 2; /* 'message has been given' temporary value */
}
}
}
if (res) {

View File

@@ -2657,7 +2657,7 @@ zapyourself(struct obj *obj, boolean ordinary)
ugolemeffects(AD_ELEC, orig_dmg);
}
(void) destroy_items(&gy.youmonst, AD_ELEC, orig_dmg);
(void) flashburn((long) rnd(100));
(void) flashburn((long) rnd(100), TRUE);
break;
case SPE_FIREBALL:
@@ -2836,7 +2836,7 @@ zapyourself(struct obj *obj, boolean ordinary)
damage = 5;
damage = lightdamage(obj, ordinary, damage);
damage += rnd(25);
if (flashburn((long) damage))
if (flashburn((long) damage, FALSE))
learn_it = TRUE;
damage = 0; /* reset */
break;
@@ -2971,7 +2971,7 @@ lightdamage(
/* light[ning] causes blindness */
boolean
flashburn(long duration)
flashburn(long duration, boolean via_lightning)
{
if (!resists_blnd(&gy.youmonst)) {
You(are_blinded_by_the_flash);
@@ -2980,6 +2980,16 @@ flashburn(long duration)
Your1(vision_clears);
return TRUE;
}
/* if blinding is resisted due to magical equipment (Sunsword), give
a sparkle animation (even if also resisted due to being blind)
_unless_ this is lightning-induced; we don't want a double sparkle
if hero is both lightning resistant and blindness resistant, or
worse, have a single sparkle where the player confuses blindness
resistance for lightning resistance */
if (!via_lightning && resists_blnd_by_arti(&gy.youmonst)) {
shieldeff(u.ux, u.uy);
return TRUE;
}
return FALSE;
}
@@ -4817,7 +4827,7 @@ dobuzz(
Your("%s tingles.", body_part(ARM));
}
if (damgtype == ZT_LIGHTNING)
(void) flashburn((long) d(nd, 50));
(void) flashburn((long) d(nd, 50), TRUE);
stop_occupation();
nomul(0);
}