monster spells
This fixes the problem with my monster spell changes which let monsters summon monsters around you when they don't even know you're around. The summoned monsters should appear where the monster thinks you are, if you're invisible or displaced. I have not prevented them from summoning monsters when you are in a temple, nor have I prevented them from aggravating monsters several times when you're out of sight. Messages should be a little smarter, taking into account number of monsters and invisibility/displacement. --Ken A
This commit is contained in:
@@ -2201,7 +2201,7 @@ E int FDECL(tactics, (struct monst *));
|
|||||||
E void NDECL(aggravate);
|
E void NDECL(aggravate);
|
||||||
E void NDECL(clonewiz);
|
E void NDECL(clonewiz);
|
||||||
E int NDECL(pick_nasty);
|
E int NDECL(pick_nasty);
|
||||||
E void FDECL(nasty, (struct monst*));
|
E int FDECL(nasty, (struct monst*));
|
||||||
E void NDECL(resurrect);
|
E void NDECL(resurrect);
|
||||||
E void NDECL(intervene);
|
E void NDECL(intervene);
|
||||||
E void NDECL(wizdead);
|
E void NDECL(wizdead);
|
||||||
|
|||||||
102
src/mcastu.c
102
src/mcastu.c
@@ -226,7 +226,13 @@ castmu(mtmp, mattk, thinks_it_foundyou, foundyou)
|
|||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
pline("%s casts a spell%s!", Monnam(mtmp),
|
pline("%s casts a spell%s!", Monnam(mtmp),
|
||||||
is_undirected_spell(mattk->adtyp, spellnum) ? "" : " at you");
|
is_undirected_spell(mattk->adtyp, spellnum) ? "" :
|
||||||
|
(Invisible && !perceives(mtmp->data) &&
|
||||||
|
(mtmp->mux != u.ux || mtmp->muy != u.uy)) ?
|
||||||
|
" at a spot near you" :
|
||||||
|
(Displaced && (mtmp->mux != u.ux || mtmp->muy != u.uy)) ?
|
||||||
|
" at your displaced image" :
|
||||||
|
" at you");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* As these are spells, the damage is related to the level
|
* As these are spells, the damage is related to the level
|
||||||
@@ -337,12 +343,29 @@ int spellnum;
|
|||||||
}
|
}
|
||||||
/* else FALLTHRU */
|
/* else FALLTHRU */
|
||||||
case MGC_SUMMON_MONS: /* also aggravates */
|
case MGC_SUMMON_MONS: /* also aggravates */
|
||||||
|
{
|
||||||
|
int count;
|
||||||
|
|
||||||
|
count = nasty(mtmp); /* summon something nasty */
|
||||||
if (mtmp->iswiz)
|
if (mtmp->iswiz)
|
||||||
verbalize("Destroy the thief, my pets!");
|
verbalize("Destroy the thief, my pet%s!", plur(count));
|
||||||
else
|
else {
|
||||||
pline("A monster appears!");
|
const char *mappear =
|
||||||
nasty(mtmp); /* summon something nasty */
|
(count == 1) ? "A monster appears" : "Monsters appear";
|
||||||
/* FALLTHRU */
|
|
||||||
|
/* messages not quite right if plural monsters created but
|
||||||
|
only a single monster is seen */
|
||||||
|
if (Invisible && !perceives(mtmp->data) &&
|
||||||
|
(mtmp->mux != u.ux || mtmp->muy != u.uy))
|
||||||
|
pline("%s around a spot near you!", mappear);
|
||||||
|
else if (Displaced && (mtmp->mux != u.ux || mtmp->muy != u.uy))
|
||||||
|
pline("%s around your displaced image!", mappear);
|
||||||
|
else
|
||||||
|
pline("%s from nowhere!", mappear);
|
||||||
|
}
|
||||||
|
dmg = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case MGC_AGGRAVATION:
|
case MGC_AGGRAVATION:
|
||||||
You_feel("that monsters are aware of your presence.");
|
You_feel("that monsters are aware of your presence.");
|
||||||
aggravate();
|
aggravate();
|
||||||
@@ -502,31 +525,45 @@ int spellnum;
|
|||||||
/* Try for insects, and if there are none
|
/* Try for insects, and if there are none
|
||||||
left, go for (sticks to) snakes. -3. */
|
left, go for (sticks to) snakes. -3. */
|
||||||
struct permonst *pm = mkclass(S_ANT,0);
|
struct permonst *pm = mkclass(S_ANT,0);
|
||||||
struct monst *mtmp2;
|
struct monst *mtmp2 = (struct monst *)0;
|
||||||
char let = (pm ? S_ANT : S_SNAKE);
|
char let = (pm ? S_ANT : S_SNAKE);
|
||||||
boolean success;
|
boolean success;
|
||||||
int i;
|
int i;
|
||||||
|
coord bypos;
|
||||||
|
|
||||||
success = pm ? TRUE : FALSE;
|
success = pm ? TRUE : FALSE;
|
||||||
for (i = 0; i <= (int) mtmp->m_lev; i++) {
|
for (i = 0; i <= (int) mtmp->m_lev; i++) {
|
||||||
if ((pm = mkclass(let,0)) != 0 &&
|
if (!enexto(&bypos, mtmp->mux, mtmp->muy, mtmp->data))
|
||||||
(mtmp2 = makemon(pm, u.ux, u.uy, NO_MM_FLAGS)) != 0) {
|
break;
|
||||||
|
if ((pm = mkclass(let,0)) != 0 &&
|
||||||
|
(mtmp2 = makemon(pm, bypos.x, bypos.y, NO_MM_FLAGS)) != 0) {
|
||||||
success = TRUE;
|
success = TRUE;
|
||||||
mtmp2->msleeping = mtmp2->mpeaceful = mtmp2->mtame = 0;
|
mtmp2->msleeping = mtmp2->mpeaceful = mtmp2->mtame = 0;
|
||||||
set_malign(mtmp2);
|
set_malign(mtmp2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (canseemon(mtmp)) {
|
/* Not quite right:
|
||||||
/* wrong--should check if you can see the insects/snakes */
|
* -- message doesn't always make sense for unseen caster (particularly
|
||||||
if (!success)
|
* the first message)
|
||||||
pline("%s casts at a clump of sticks, but nothing happens.",
|
* -- message assumes plural monsters summoned (non-plural should be
|
||||||
Monnam(mtmp));
|
* very rare, unlike in nasty())
|
||||||
else if (let == S_SNAKE)
|
* -- message assumes plural monsters seen
|
||||||
pline("%s transforms a clump of sticks into snakes!",
|
*/
|
||||||
Monnam(mtmp));
|
if (!success)
|
||||||
else
|
pline("%s casts at a clump of sticks, but nothing happens.",
|
||||||
pline("%s summons insects!", Monnam(mtmp));
|
Monnam(mtmp));
|
||||||
}
|
else if (let == S_SNAKE)
|
||||||
|
pline("%s transforms a clump of sticks into snakes!",
|
||||||
|
Monnam(mtmp));
|
||||||
|
else if (Invisible && !perceives(mtmp->data) &&
|
||||||
|
(mtmp->mux != u.ux || mtmp->muy != u.uy))
|
||||||
|
pline("%s summons insects around a spot near you!",
|
||||||
|
Monnam(mtmp));
|
||||||
|
else if (Displaced && (mtmp->mux != u.ux || mtmp->muy != u.uy))
|
||||||
|
pline("%s summons insects around your displaced image!",
|
||||||
|
Monnam(mtmp));
|
||||||
|
else
|
||||||
|
pline("%s summons insects!", Monnam(mtmp));
|
||||||
dmg = 0;
|
dmg = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -563,9 +600,15 @@ int spellnum;
|
|||||||
shieldeff(u.ux, u.uy);
|
shieldeff(u.ux, u.uy);
|
||||||
You_feel("momentarily dizzy.");
|
You_feel("momentarily dizzy.");
|
||||||
} else {
|
} else {
|
||||||
|
boolean oldprop = Confusion;
|
||||||
|
|
||||||
dmg = (int)mtmp->m_lev;
|
dmg = (int)mtmp->m_lev;
|
||||||
if (Half_spell_damage) dmg = (dmg + 1) / 2;
|
if (Half_spell_damage) dmg = (dmg + 1) / 2;
|
||||||
make_confused(HConfusion + dmg, TRUE);
|
make_confused(HConfusion + dmg, TRUE);
|
||||||
|
if (Hallucination)
|
||||||
|
You_feel("%s!", oldprop ? "trippier" : "trippy");
|
||||||
|
else
|
||||||
|
You_feel("%sconfused!", oldprop ? "more " : "");
|
||||||
}
|
}
|
||||||
dmg = 0;
|
dmg = 0;
|
||||||
break;
|
break;
|
||||||
@@ -633,7 +676,9 @@ int spellnum;
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Some undirected spells are useless under some circumstances */
|
/* Some undirected spells are useless under some circumstances. */
|
||||||
|
/* This isn't called when the monster is deliberately casting at you; we
|
||||||
|
handle that using fallthroughs. */
|
||||||
STATIC_DCL
|
STATIC_DCL
|
||||||
boolean
|
boolean
|
||||||
spell_would_be_useless(mtmp, adtyp, spellnum)
|
spell_would_be_useless(mtmp, adtyp, spellnum)
|
||||||
@@ -641,6 +686,14 @@ struct monst *mtmp;
|
|||||||
int spellnum;
|
int spellnum;
|
||||||
int adtyp;
|
int adtyp;
|
||||||
{
|
{
|
||||||
|
/* Some spells don't require the player to really be there and can be cast
|
||||||
|
* by the monster when you're invisible, yet still shouldn't be cast when
|
||||||
|
* the monster doesn't even think you're there.
|
||||||
|
* This check isn't quite right because it always uses your real position.
|
||||||
|
* We really want something like "if the monster could see mux, muy".
|
||||||
|
*/
|
||||||
|
boolean couldsee = couldsee(mtmp->mx, mtmp->my);
|
||||||
|
|
||||||
if (adtyp == AD_SPEL) {
|
if (adtyp == AD_SPEL) {
|
||||||
/* aggravate monsters, etc. won't be cast by peaceful monsters */
|
/* aggravate monsters, etc. won't be cast by peaceful monsters */
|
||||||
if (mtmp->mpeaceful && (spellnum == MGC_AGGRAVATION ||
|
if (mtmp->mpeaceful && (spellnum == MGC_AGGRAVATION ||
|
||||||
@@ -661,6 +714,10 @@ int adtyp;
|
|||||||
/* healing when already healed */
|
/* healing when already healed */
|
||||||
if (mtmp->mhp == mtmp->mhpmax && spellnum == MGC_CURE_SELF)
|
if (mtmp->mhp == mtmp->mhpmax && spellnum == MGC_CURE_SELF)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
/* don't summon monsters if it doesn't think you're around */
|
||||||
|
if (!couldsee && (spellnum == MGC_SUMMON_MONS ||
|
||||||
|
(!mtmp->iswiz && spellnum == MGC_CLONE_WIZ)))
|
||||||
|
return TRUE;
|
||||||
} else if (adtyp == AD_CLRC) {
|
} else if (adtyp == AD_CLRC) {
|
||||||
/* summon insects/sticks to snakes won't be cast by peaceful monsters */
|
/* summon insects/sticks to snakes won't be cast by peaceful monsters */
|
||||||
if (mtmp->mpeaceful && spellnum == CLC_INSECTS)
|
if (mtmp->mpeaceful && spellnum == CLC_INSECTS)
|
||||||
@@ -668,6 +725,9 @@ int adtyp;
|
|||||||
/* healing when already healed */
|
/* healing when already healed */
|
||||||
if (mtmp->mhp == mtmp->mhpmax && spellnum == CLC_CURE_SELF)
|
if (mtmp->mhp == mtmp->mhpmax && spellnum == CLC_CURE_SELF)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
/* don't summon insects if it doesn't think you're around */
|
||||||
|
if (!couldsee && spellnum == CLC_INSECTS)
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|||||||
29
src/wizard.c
29
src/wizard.c
@@ -410,33 +410,44 @@ pick_nasty()
|
|||||||
|
|
||||||
/* create some nasty monsters, aligned or neutral with the caster */
|
/* create some nasty monsters, aligned or neutral with the caster */
|
||||||
/* a null caster defaults to a chaotic caster (e.g. the wizard) */
|
/* a null caster defaults to a chaotic caster (e.g. the wizard) */
|
||||||
void
|
int
|
||||||
nasty(mcast)
|
nasty(mcast)
|
||||||
struct monst *mcast;
|
struct monst *mcast;
|
||||||
{
|
{
|
||||||
register struct monst *mtmp;
|
register struct monst *mtmp;
|
||||||
register int i, j, tmp;
|
register int i, j, tmp;
|
||||||
int castalign = (mcast ? mcast->data->maligntyp : -1);
|
int castalign = (mcast ? mcast->data->maligntyp : -1);
|
||||||
|
coord bypos;
|
||||||
|
int count=0;
|
||||||
|
|
||||||
if(!rn2(10) && Inhell) msummon(&mons[PM_WIZARD_OF_YENDOR]);
|
if(!rn2(10) && Inhell) {
|
||||||
else {
|
msummon(&mons[PM_WIZARD_OF_YENDOR]);
|
||||||
|
count++;
|
||||||
|
} else {
|
||||||
tmp = (u.ulevel > 3) ? u.ulevel/3 : 1; /* just in case -- rph */
|
tmp = (u.ulevel > 3) ? u.ulevel/3 : 1; /* just in case -- rph */
|
||||||
|
/* if we don't have a casting monster, the nasties appear around you */
|
||||||
|
bypos.x = u.ux;
|
||||||
|
bypos.y = u.uy;
|
||||||
for(i = rnd(tmp); i > 0; --i)
|
for(i = rnd(tmp); i > 0; --i)
|
||||||
for(j=0; j<20; j++) {
|
for(j=0; j<20; j++) {
|
||||||
|
if (mcast &&
|
||||||
|
!enexto(&bypos, mcast->mux, mcast->muy, mcast->data))
|
||||||
|
continue;
|
||||||
if ((mtmp = makemon(&mons[pick_nasty()],
|
if ((mtmp = makemon(&mons[pick_nasty()],
|
||||||
u.ux, u.uy, NO_MM_FLAGS)) != 0) {
|
bypos.x, bypos.y, NO_MM_FLAGS)) != 0) {
|
||||||
mtmp->msleeping = mtmp->mpeaceful = mtmp->mtame = 0;
|
mtmp->msleeping = mtmp->mpeaceful = mtmp->mtame = 0;
|
||||||
set_malign(mtmp);
|
set_malign(mtmp);
|
||||||
} else /* GENOD? */
|
} else /* GENOD? */
|
||||||
mtmp = makemon((struct permonst *)0,
|
mtmp = makemon((struct permonst *)0,
|
||||||
u.ux, u.uy, NO_MM_FLAGS);
|
bypos.x, bypos.y, NO_MM_FLAGS);
|
||||||
if(mtmp && (mtmp->data->maligntyp == 0 ||
|
if(mtmp && (mtmp->data->maligntyp == 0 ||
|
||||||
sgn(mtmp->data->maligntyp) == sgn(castalign)) )
|
sgn(mtmp->data->maligntyp) == sgn(castalign)) ) {
|
||||||
|
count++;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Let's resurrect the wizard, for some unexpected fun. */
|
/* Let's resurrect the wizard, for some unexpected fun. */
|
||||||
@@ -506,7 +517,7 @@ intervene()
|
|||||||
break;
|
break;
|
||||||
case 3: aggravate();
|
case 3: aggravate();
|
||||||
break;
|
break;
|
||||||
case 4: nasty((struct monst *)0);
|
case 4: (void)nasty((struct monst *)0);
|
||||||
break;
|
break;
|
||||||
case 5: resurrect();
|
case 5: resurrect();
|
||||||
break;
|
break;
|
||||||
|
|||||||
Reference in New Issue
Block a user