1
0
Fork 0
mirror of https://codeberg.org/noisytoot/notnotdnethack.git synced 2025-07-26 23:32:25 +01:00

mon.c 3.8

tabbing fixes

Temporary monsters shouldn't leave corpses

Increase nudziarth mirror frequency

Add mercurial dragons to dragon list

Straw Golems leave sheafs of hay

Shieres attack in elf form and flee in light form

Disturbed Uvuudaums return to their meditation if they have full hp

Watcher tentacle movement restrictions

Tame monsters don't attack peaceful monsters and vice versa

Handle drow vs drow aggression.
	Even pets won't attack drow of matching house.
	On some quests, drow of your faction will attack quest enemies
	Drow attack drow of other houses
	Drow attack elves
	Drow attack edderkops

NOTE: Eladrin do not return to any form in particular after death.

Drow general quest leader has to create the bell as they die

Illurien returns

Initial nemesis always leaves a corpse

Aklys valid for small monsters

Attacking the quest entorage angers the old quest leader

noisy waking function confuses, stuns, and counts as injuring monsters with sensitive ears (so just grimlocks, at least for now)

Hunting horrors have long tails
This commit is contained in:
Chris-plus-alphanumericgibberish 2015-01-24 02:43:14 -05:00
parent a47d8c1ab3
commit b2b3c942d1

168
src/mon.c
View file

@ -222,13 +222,18 @@ register struct monst *mtmp;
int mndx = monsndx(mdat);
struct obj *otmp;
if(u.specialSealsActive&SEAL_NUDZIARTH && !rn2(100)){
if(mtmp->mvanishes > -1){
return (struct obj *)0;
}
if(u.specialSealsActive&SEAL_NUDZIARTH && !rn2(4)){
(void) mksobj_at(MIRROR, x, y, TRUE, FALSE);
}
switch(mndx) {
case PM_GRAY_DRAGON:
case PM_SILVER_DRAGON:
case PM_MERCURIAL_DRAGON:
case PM_SHIMMERING_DRAGON:
case PM_DEEP_DRAGON:
case PM_RED_DRAGON:
@ -517,6 +522,12 @@ register struct monst *mtmp;
obj = mksobj_at(SCR_BLANK_PAPER, x, y, TRUE, FALSE);
mtmp->mnamelth = 0;
break;
case PM_STRAW_GOLEM:
obj = mksobj_at(SHEAF_OF_HAY, x, y, FALSE, FALSE);
obj->quan = (long)(d(2,4));
obj->owt = weight(obj);
mtmp->mnamelth = 0;
break;
case PM_SPELL_GOLEM:{
int scrnum = 0;
int scrrng = SCR_STINKING_CLOUD-SCR_ENCHANT_ARMOR;
@ -806,6 +817,9 @@ mcalcdistress()
/* regenerate hit points */
mon_regen(mtmp, FALSE);
if(mtmp->data == &mons[PM_BALL_OF_LIGHT]) mtmp->mflee = 1;
else if(mtmp->data == &mons[PM_SHIERE]) mtmp->mflee = 0;
/* possibly polymorph shapechangers and lycanthropes */
if (mtmp->cham && !rn2(6))
(void) newcham(mtmp, (struct permonst *)0, FALSE, FALSE);
@ -997,14 +1011,19 @@ movemon()
if(canseemon(mtmp)) pline("%s gets angry...", mon_nam(mtmp));
mtmp->mpeaceful = 0;
}
if(u.uevent.udemigod &&
mtmp->data == &mons[PM_UVUUDAUM] &&
mtmp->mpeaceful
){
pline("%s shakes off it's torpor...", Amonnam(mtmp));
if(mtmp->data == &mons[PM_UVUUDAUM]){
if(u.uevent.udemigod){
if(mtmp->mpeaceful){
pline("%s ceases its meditation...", Amonnam(mtmp));
mtmp->mpeaceful = 0;
set_malign(mtmp);
}
} else if(!mtmp->mpeaceful && mtmp->mhp == mtmp->mhpmax && mtmp->m_lev >= 15){
pline("%s resumes its meditation...", Amonnam(mtmp));
mtmp->mpeaceful = 1;
set_malign(mtmp);
}
}
if (vision_full_recalc) vision_recalc(0); /* vision! */
@ -1419,6 +1438,7 @@ mfndpos(mon, poss, info, flag)
long flag;
{
struct permonst *mdat = mon->data;
struct monst *witw = 0;
register xchar x,y,nx,ny;
register int cnt = 0;
register uchar ntyp;
@ -1427,6 +1447,10 @@ mfndpos(mon, poss, info, flag)
boolean rockok = FALSE, treeok = FALSE, thrudoor;
int maxx, maxy;
if(mdat == &mons[PM_SWARM_OF_SNAKING_TENTACLES] || mdat == &mons[PM_LONG_SINUOUS_TENTACLE]){
for(witw = fmon; witw; witw = witw->nmon) if(witw->data == &mons[PM_WATCHER_IN_THE_WATER]) break;
} else witw = 0;
x = mon->mx;
y = mon->my;
nowtyp = levl[x][y].typ;
@ -1504,6 +1528,11 @@ nexttry: /* eels prefer the water, but if there is no water nearby,
) if(x + xdir[(int)mon->mextra[0]] != nx ||
y + ydir[(int)mon->mextra[0]] != ny
) continue;
if(mdat == &mons[PM_WATCHER_IN_THE_WATER] &&
distmin(nx, ny, mon->mux, mon->muy) <= 3 &&
dist2(nx, ny, mon->mux, mon->muy) <= dist2(mon->mx, mon->my, mon->mux, mon->muy)) continue;
if(witw && dist2(nx, ny, witw->mx, witw->my) > 32 &&
dist2(nx, ny, witw->mx, witw->my) >= dist2(mon->mx, mon->my, witw->mx, witw->my)) continue;
if(mdat == &mons[PM_HOOLOOVOO] &&
IS_WALL(levl[mon->mx][mon->my].typ) &&
!IS_WALL(levl[nx][ny].typ)
@ -1656,6 +1685,10 @@ struct monst *magr, /* monster that is currently deciding where to move */
ma = magr->data;
md = mdef->data;
if(magr->mpeaceful && mdef->mpeaceful && (magr->mtame || mdef->mtame)) return 0L;
if(is_drow(ma) && is_drow(md) && (magr->mfaction == mdef->mfaction)) return 0L;
if (u.sowdisc && !mdef->mtame)
return ALLOW_M|ALLOW_TM;
/* supposedly purple worms are attracted to shrieking because they
@ -1686,7 +1719,9 @@ struct monst *magr, /* monster that is currently deciding where to move */
if( (ma->msound==MS_GUARDIAN
|| (Role_if(PM_NOBLEMAN) && (ma == &mons[PM_KNIGHT] || ma == &mons[PM_MAID] || ma == &mons[PM_PEASANT]) && magr->mpeaceful)
|| (Role_if(PM_KNIGHT) && ma == &mons[PM_KNIGHT] && magr->mpeaceful)
|| (Race_if(PM_DROW) && is_drow(ma) && magr->mfaction == u.uhouse)
)
&& !((Race_if(PM_DROW) && !flags.stag && !Role_if(PM_NOBLEMAN)) || !is_drow(md))
&& magr->mpeaceful==TRUE
&& mdef->mpeaceful==FALSE
) return ALLOW_M|ALLOW_TM;
@ -1694,7 +1729,9 @@ struct monst *magr, /* monster that is currently deciding where to move */
if( (md->msound == MS_GUARDIAN
|| (Role_if(PM_NOBLEMAN) && (md == &mons[PM_KNIGHT] || md == &mons[PM_MAID] || md == &mons[PM_PEASANT]) && mdef->mpeaceful)
|| (Role_if(PM_KNIGHT) && md == &mons[PM_KNIGHT] && mdef->mpeaceful)
|| (Race_if(PM_DROW) && is_drow(md) && mdef->mfaction == u.uhouse)
)
&& !((Race_if(PM_DROW) && !flags.stag && !Role_if(PM_NOBLEMAN)) || !is_drow(ma))
&& mdef->mpeaceful==TRUE
&& magr->mpeaceful==FALSE
&& rn2(2)
@ -1708,14 +1745,43 @@ struct monst *magr, /* monster that is currently deciding where to move */
return ALLOW_M|ALLOW_TM;
/* elves vs. drow */
if( is_elf(ma) && is_elf(md) && is_drow(ma) != is_drow(md))
if( (is_elf(ma) || is_elf(md)) && (is_drow(ma) || is_drow(md)) && magr->mfaction != EILISTRAEE_SYMBOL && mdef->mfaction != EILISTRAEE_SYMBOL)
return ALLOW_M|ALLOW_TM;
/* drow vs. other drow */
/* Note that factions may be different than the displayed house name,
as faction is set during generation and displayed house name goes by equipment! */
if( is_drow(ma) && is_drow(md) && magr->mfaction != mdef->mfaction)
if( is_drow(ma) && is_drow(md) &&
magr->mfaction != mdef->mfaction
){
int f1 = magr->mfaction, f2 = mdef->mfaction;
boolean truce1 = FALSE, truce2 = FALSE;
if((f1 >= FIRST_GODDESS && f1 <= LAST_GODDESS) ||
(f1 >= FIRST_TOWER && f1 <= LAST_TOWER)
) truce1 = TRUE;
if((f2 >= FIRST_GODDESS && f2 <= LAST_GODDESS) ||
(f2 >= FIRST_TOWER && f2 <= LAST_TOWER)
) truce2 = TRUE;
if((f1 == XAXOX || f1 == EDDER_SYMBOL) && (f2 == XAXOX || f2 == EDDER_SYMBOL));
else if(!truce1 && !truce2) return ALLOW_M|ALLOW_TM;
else if(truce1 && truce2);
else if(truce1 && !(f2 <= LAST_HOUSE && f2 >= FIRST_HOUSE))
return ALLOW_M|ALLOW_TM;
else if(truce2 && !(f1 <= LAST_HOUSE && f1 >= FIRST_HOUSE))
return ALLOW_M|ALLOW_TM;
}
/* drow vs. edderkops */
if(is_drow(ma) && magr->mfaction != XAXOX && magr->mfaction != EDDER_SYMBOL && md == &mons[PM_EDDERKOP]){
return ALLOW_M|ALLOW_TM;
}
/* and vice versa */
if(is_drow(md) && mdef->mfaction != XAXOX && mdef->mfaction != EDDER_SYMBOL && ma == &mons[PM_EDDERKOP]){
return ALLOW_M|ALLOW_TM;
}
/* Nazgul vs. hobbits */
if(ma == &mons[PM_NAZGUL] && md == &mons[PM_HOBBIT])
@ -2106,7 +2172,15 @@ boolean was_swallowed; /* digestion */
{
struct permonst *mdat = mon->data;
int i, tmp;
if(Race_if(PM_DROW) && !Role_if(PM_NOBLEMAN) && mdat == &mons[urole.neminum] && !flags.made_bell){
(void) mksobj_at(BELL_OF_OPENING, mon->mx, mon->my, TRUE, FALSE);
flags.made_bell = TRUE;
if(mdat == &mons[PM_ECLAVDRA]) return FALSE;
}
if(mdat == &mons[PM_ILLURIEN_OF_THE_MYRIAD_GLIMPSES] && !(u.uevent.ukilled_illurien)){
u.uevent.ukilled_illurien = 1;
u.ill_cnt = rn1(1000, 250);
}
if (mdat == &mons[PM_VLAD_THE_IMPALER]) {
livelog_write_string("destroyed Vlad the Impaler");
if (cansee(mon->mx, mon->my) && !was_swallowed)
@ -2236,17 +2310,28 @@ boolean was_swallowed; /* digestion */
explode(mon->mx+x, mon->my+y, 8, tmp, -1, rn2(7)); //-1 is unspecified source. 8 is physical
}
tmp=0;
}
else if(mdat->mattk[i].adtyp == AD_SPNL){
} else if(mdat->mattk[i].adtyp == AD_SPNL){
explode(mon->mx, mon->my, 2, tmp, MON_EXPLODE, EXPL_WET);
makemon(&mons[PM_LEVIATHAN], mon->mx, mon->my, MM_ADJACENTOK);
}
else if(mdat == &mons[PM_ANCIENT_OF_DEATH]){
} else if(mdat == &mons[PM_ANCIENT_OF_DEATH]){
if(!(u.sealsActive&SEAL_OSE)) explode(mon->mx, mon->my, 0, tmp, MON_EXPLODE, EXPL_DARK);
}
else if(mdat->mattk[i].adtyp == AD_MAND){
} else if(mdat->mattk[i].adtyp == AD_WTCH){
struct monst *mtmp, *mtmp2;
pline("%s lets out a terrible shriek!", Monnam(mon));
for (mtmp = fmon; mtmp; mtmp = mtmp2){
mtmp2 = mtmp->nmon;
if(mtmp->data == &mons[PM_SWARM_OF_SNAKING_TENTACLES] || mtmp->data == &mons[PM_LONG_SINUOUS_TENTACLE]){
if (DEADMONSTER(mtmp)) continue;
mtmp->mhp = -10;
monkilled(mtmp,"",AD_DRLI);
}
}
} else if(mdat->mattk[i].adtyp == AD_MAND){
struct monst *mtmp, *mtmp2;
if(mon->mcan){
pline("%s croaks out a horse shriek. It seems %s has a sore throat!", Monnam(mon), mon_nam(mon));
return FALSE;
}
else pline("%s lets out a terrible shriek!", Monnam(mon));
for (mtmp = fmon; mtmp; mtmp = mtmp2){
mtmp2 = mtmp->nmon;
if(mtmp->data->geno & G_GENO && !nonliving(mon->data) && !is_demon(mon->data) && !is_keter(mon->data)){
@ -2496,6 +2581,8 @@ boolean was_swallowed; /* digestion */
|| is_golem(mdat)
|| is_mplayer(mdat)
|| is_rider(mdat)
|| mdat == &mons[PM_SEYLL_AUZKOVYN]
|| mdat == &mons[PM_DARUTH_XAXOX]
// || mdat == &mons[PM_UNICORN_OF_AMBER]
|| mdat == &mons[PM_NIGHTMARE]
// || mdat == &mons[PM_PINK_UNICORN]
@ -2869,7 +2956,7 @@ xkilled(mtmp, dest)
&& typ != FIGURINE
&& (otmp->owt > 3 ||
objects[typ].oc_big /*oc_bimanual/oc_bulky*/ ||
is_spear(otmp) || is_pole(otmp) ||
is_spear(otmp) || (is_pole(otmp) && otmp->otyp != AKLYS) ||
typ == MORNING_STAR)
&& !is_divider(mdat)) {
delobj(otmp);
@ -2912,10 +2999,16 @@ cleanup:
newexplevel(); /* will decide if you go up */
/* adjust alignment points */
if (mtmp->m_id == quest_status.leader_m_id) { /* REAL BAD! */
if (mtmp->m_id == quest_status.leader_m_id) {
if(flags.leader_backstab){ /* They attacked you! */
adjalign((int)(ALIGNLIM/4));
pline("That was %sa bad idea...",
u.uevent.qcompleted ? "probably " : "");
} else {/* REAL BAD! */
adjalign(-(u.ualign.record+(int)ALIGNLIM/2));
pline("That was %sa bad idea...",
u.uevent.qcompleted ? "probably " : "");
}
} else if (mdat->msound == MS_NEMESIS) /* Real good! */
adjalign((int)(ALIGNLIM/4));
else if (mdat->msound == MS_GUARDIAN && mdat != &mons[PM_THUG]) { /* Bad *//*nobody cares if you kill thugs*/
@ -3248,6 +3341,20 @@ register struct monst *mtmp;
if (humanoid(mtmp->data) || mtmp->isshk || mtmp->isgd)
pline("%s gets angry!", Monnam(mtmp));
else if (flags.verbose && flags.soundok) growl(mtmp);
if(flags.stag && (mtmp->data == &mons[PM_DROW_MATRON_MOTHER] || mtmp->data == &mons[PM_ECLAVDRA])){
struct monst *tm;
for(tm = fmon; tm; tm = tm->nmon){
if(tm->mfaction != EILISTRAEE_SYMBOL &&
tm->mfaction != XAXOX && tm->mfaction != EDDER_SYMBOL &&
is_drow(tm->data) && !tm->mtame
){
tm->housealert = 1;
tm->mpeaceful = 0;
tm->mstrategy &= ~STRAT_WAITMASK;
set_malign(tm);
}
}
}
}
/* attacking your own quest leader will anger his or her guardians */
@ -3314,6 +3421,24 @@ register int x, y, distance;
}
}
/* Wake up monsters near some particular location. */
void
wake_nearto_noisy(x, y, distance)
register int x, y, distance;
{
register struct monst *mtmp;
wake_nearto(x,y,distance);
distance /= 3;
for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
if (!DEADMONSTER(mtmp) && sensitive_ears(mtmp->data) &&
dist2(mtmp->mx, mtmp->my, x, y) < distance){
mtmp->mstun = 1;
mtmp->mconf = 1;
mtmp->uhurtm = 1;
}
}
}
/* NOTE: we must check for mimicry before calling this routine */
void
seemimic(mtmp)
@ -3651,16 +3776,17 @@ boolean msg; /* "The oldmon turns into a newmon!" */
}
#ifndef DCC30_BUG
if (mdat == &mons[PM_LONG_WORM] && (mtmp->wormno = get_wormno()) != 0) {
if ((mdat == &mons[PM_LONG_WORM] || mndx == PM_HUNTING_HORROR) &&
(mtmp->wormno = get_wormno()) != 0) {
#else
/* DICE 3.0 doesn't like assigning and comparing mtmp->wormno in the
* same expression.
*/
if (mdat == &mons[PM_LONG_WORM] &&
if ((mdat == &mons[PM_LONG_WORM] || mndx == PM_HUNTING_HORROR) &&
(mtmp->wormno = get_wormno(), mtmp->wormno != 0)) {
#endif
/* we can now create worms with tails - 11/91 */
initworm(mtmp, rn2(5));
initworm(mtmp, mndx == PM_HUNTING_HORROR ? 2 : rn2(5));
if (count_wsegs(mtmp))
place_worm_tail_randomly(mtmp, mtmp->mx, mtmp->my);
}