1
0
Fork 0
mirror of https://codeberg.org/noisytoot/notnotdnethack.git synced 2025-05-12 10:25:08 +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

440
src/mon.c
View file

@ -221,14 +221,19 @@ register struct monst *mtmp;
int x = mtmp->mx, y = mtmp->my;
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:
@ -305,7 +310,7 @@ register struct monst *mtmp;
}
goto default_1;
case PM_LONG_WORM:
(void) mksobj_at(WORM_TOOTH, x, y, TRUE, FALSE);
(void) mksobj_at(WORM_TOOTH, x, y, TRUE, FALSE);
goto default_1;
case PM_VAMPIRE:
case PM_VAMPIRE_LORD:
@ -452,10 +457,10 @@ register struct monst *mtmp;
}
break;
case PM_IRON_GOLEM:
num = d(2,6);
num = d(2,6);
while (num--){
obj = mksobj_at(IRON_CHAIN, x, y, TRUE, FALSE);
obj = mksobj_at(IRON_CHAIN, x, y, TRUE, FALSE);
obj = mksobj_at(IRON_CHAIN, x, y, TRUE, FALSE);
obj = mksobj_at(IRON_BAR, x, y, TRUE, FALSE);
}
mtmp->mnamelth = 0;
@ -466,42 +471,42 @@ register struct monst *mtmp;
obj = mksobj_at(DWARVISH_MITHRIL_COAT, x, y, TRUE, FALSE); //balance of law
obj = mksobj_at(ELVEN_MITHRIL_COAT, x, y, TRUE, FALSE); //and chaos
}
mtmp->mnamelth = 0;
mtmp->mnamelth = 0;
break;
case PM_GLASS_GOLEM:
num = d(2,4); /* very low chance of creating all glass gems */
while (num--)
obj = mksobj_at((LAST_GEM + rnd(9)), x, y, TRUE, FALSE);
mtmp->mnamelth = 0;
num = d(2,4); /* very low chance of creating all glass gems */
while (num--)
obj = mksobj_at((LAST_GEM + rnd(9)), x, y, TRUE, FALSE);
mtmp->mnamelth = 0;
break;
case PM_CLAY_GOLEM:
obj = mksobj_at(ROCK, x, y, FALSE, FALSE);
obj->quan = (long)(rn2(20) + 50);
obj->owt = weight(obj);
mtmp->mnamelth = 0;
obj = mksobj_at(ROCK, x, y, FALSE, FALSE);
obj->quan = (long)(rn2(20) + 50);
obj->owt = weight(obj);
mtmp->mnamelth = 0;
break;
case PM_STONE_GOLEM:
obj = mkcorpstat(STATUE, (struct monst *)0,
mdat, x, y, FALSE);
obj = mkcorpstat(STATUE, (struct monst *)0,
mdat, x, y, FALSE);
break;
case PM_WOOD_GOLEM:
num = d(2,4);
while(num--) {
obj = mksobj_at(QUARTERSTAFF, x, y, TRUE, FALSE);
}
mtmp->mnamelth = 0;
num = d(2,4);
while(num--) {
obj = mksobj_at(QUARTERSTAFF, x, y, TRUE, FALSE);
}
mtmp->mnamelth = 0;
break;
case PM_LEATHER_GOLEM:
num = d(2,4);
while(num--)
obj = mksobj_at(LEATHER_ARMOR, x, y, TRUE, FALSE);
mtmp->mnamelth = 0;
num = d(2,4);
while(num--)
obj = mksobj_at(LEATHER_ARMOR, x, y, TRUE, FALSE);
mtmp->mnamelth = 0;
break;
case PM_GOLD_GOLEM:
/* Good luck gives more coins */
obj = mkgold((long)(200 - rnl(101)), x, y);
mtmp->mnamelth = 0;
break;
/* Good luck gives more coins */
obj = mkgold((long)(200 - rnl(101)), x, y);
mtmp->mnamelth = 0;
break;
case PM_TREASURY_GOLEM:
num = d(2,4);
while (num--)
@ -511,10 +516,16 @@ register struct monst *mtmp;
obj = mkgold((long)(400 - rnl(101)), x, y);
mtmp->mnamelth = 0;
break;
case PM_PAPER_GOLEM:
num = rnd(4);
while (num--)
obj = mksobj_at(SCR_BLANK_PAPER, x, y, TRUE, FALSE);
case PM_PAPER_GOLEM:
num = rnd(4);
while (num--)
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:{
@ -805,6 +816,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))
@ -864,7 +878,7 @@ movemon()
Uh oh, weeping angels have a levelport attack. Doesn't seem to
cause problems, though....
*/
/////////////////////////////////////////////////////
//Weeping angel handling////////////////////////////
///////////////////////////////////////////////////
@ -878,7 +892,7 @@ movemon()
* the angel's AC based on the value from 2, slower speed equals higher AC (Quantum Lock).
*/
for(mtmp = fmon; mtmp; mtmp = mtmp->nmon){
//Weeping angel step 1
//Weeping angel step 1
if(is_weeping(mtmp->data)){
if(mtmp->mextra[2] && u.uevent.udemigod){
mtmp->mextra[2] = 0; //Quantum Lock status will be reset below.
@ -932,7 +946,7 @@ movemon()
mtmp->movement -= NORMAL_SPEED;
if (mtmp->movement >= NORMAL_SPEED)
somebody_can_move = TRUE;
mtmp->mstdy /= 2; //monster is moving, reduce studied level
//Weeping angel step 3
@ -997,13 +1011,18 @@ 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));
mtmp->mpeaceful = 0;
set_malign(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;
@ -1426,7 +1446,11 @@ mfndpos(mon, poss, info, flag)
boolean wantpool,poolok,lavaok,nodiag,quantumlock;
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;
@ -1483,9 +1507,9 @@ nexttry: /* eels prefer the water, but if there is no water nearby,
levl[nx][ny].doormask & D_CLOSED && !(flag & OPENDOOR)
|| levl[nx][ny].doormask & D_LOCKED :
!amorphous(mdat) &&
((levl[nx][ny].doormask & D_CLOSED && !(flag & OPENDOOR)) ||
(levl[nx][ny].doormask & D_LOCKED && !(flag & UNLOCKDOOR))) &&
!thrudoor) continue;
((levl[nx][ny].doormask & D_CLOSED && !(flag & OPENDOOR)) ||
(levl[nx][ny].doormask & D_LOCKED && !(flag & UNLOCKDOOR))) &&
!thrudoor) continue;
if(nx != x && ny != y && (nodiag ||
#ifdef REINCARNATION
((IS_DOOR(nowtyp) &&
@ -1497,13 +1521,18 @@ nexttry: /* eels prefer the water, but if there is no water nearby,
(IS_DOOR(ntyp) && (levl[nx][ny].doormask & ~D_BROKEN)))
#endif
))
continue;
continue;
if(mdat == &mons[PM_CLOCKWORK_SOLDIER] || mdat == &mons[PM_CLOCKWORK_DWARF] ||
mdat == &mons[PM_FABERGE_SPHERE] || mdat == &mons[PM_FIREWORK_CART] ||
mdat == &mons[PM_JUGGERNAUT] || mdat == &mons[PM_ID_JUGGERNAUT]
) 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)
@ -1511,12 +1540,12 @@ nexttry: /* eels prefer the water, but if there is no water nearby,
//Weeping angels should avoid stepping into corredors, where they can be forced into a standoff.
if(quantumlock && IS_ROOM(levl[mon->mx][mon->my].typ) && !IS_ROOM(ntyp) ) continue;
if((is_pool(nx,ny) == wantpool || poolok) &&
(lavaok || !is_lava(nx,ny))) {
if((is_pool(nx,ny) == wantpool || poolok) &&
(lavaok || !is_lava(nx,ny))) {
int dispx, dispy;
boolean monseeu = (mon->mcansee && (!Invis || perceives(mdat)));
boolean checkobj = OBJ_AT(nx,ny);
/* Displacement also displaces the Elbereth/scare monster,
* as long as you are visible.
*/
@ -1655,7 +1684,11 @@ 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,15 +1745,44 @@ 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])
return ALLOW_M|ALLOW_TM;
@ -2031,15 +2097,15 @@ register struct monst *mtmp;
mptr = mtmp->data; /* save this for m_detach() */
/* restore chameleon, lycanthropes to true form at death */
if (mtmp->cham)
set_mon_data(mtmp, &mons[cham_to_pm[mtmp->cham]], -1);
set_mon_data(mtmp, &mons[cham_to_pm[mtmp->cham]], -1);
else if (mtmp->data == &mons[PM_WEREJACKAL])
set_mon_data(mtmp, &mons[PM_HUMAN_WEREJACKAL], -1);
set_mon_data(mtmp, &mons[PM_HUMAN_WEREJACKAL], -1);
else if (mtmp->data == &mons[PM_WEREWOLF])
set_mon_data(mtmp, &mons[PM_HUMAN_WEREWOLF], -1);
set_mon_data(mtmp, &mons[PM_HUMAN_WEREWOLF], -1);
else if (mtmp->data == &mons[PM_WERERAT])
set_mon_data(mtmp, &mons[PM_HUMAN_WERERAT], -1);
set_mon_data(mtmp, &mons[PM_HUMAN_WERERAT], -1);
else if (mtmp->data == &mons[PM_ANUBAN_JACKAL])
set_mon_data(mtmp, &mons[PM_ANUBITE], -1);
set_mon_data(mtmp, &mons[PM_ANUBITE], -1);
/* if MAXMONNO monsters of a given type have died, and it
* can be done, extinguish that monster.
@ -2058,15 +2124,15 @@ register struct monst *mtmp;
/* if it's a (possibly polymorphed) quest leader, mark him as dead */
if (mtmp->m_id == quest_status.leader_m_id)
quest_status.leader_is_dead = TRUE;
quest_status.leader_is_dead = TRUE;
#ifdef MAIL
/* if the mail daemon dies, no more mail delivery. -3. */
if (tmp == PM_MAIL_DAEMON) mvitals[tmp].mvflags |= G_GENOD;
#endif
if (mtmp->data->mlet == S_KETER) {
/* Dead Keter may come back. */
switch(rnd(5)) {
/* Dead Keter may come back. */
switch(rnd(5)) {
case 1: /* returns near the stairs */
(void) makemon(mtmp->data,xdnstair,ydnstair,NO_MM_FLAGS);
break;
@ -2075,10 +2141,10 @@ register struct monst *mtmp;
break;
default:
break;
}
}
}
if(mtmp->iswiz) wizdead();
if(mtmp->data->msound == MS_NEMESIS) nemdead();
if(mtmp->data->msound == MS_NEMESIS) nemdead();
#ifdef RECORD_ACHIEVE
if(mtmp->data == &mons[PM_LUCIFER]){
achieve.killed_lucifer = 1;
@ -2090,10 +2156,10 @@ register struct monst *mtmp;
achieve.killed_demogorgon = 1;
}
else if(mtmp->data == &mons[PM_MEDUSA])
achieve.killed_medusa = 1;
achieve.killed_medusa = 1;
#endif
if(glyph_is_invisible(levl[mtmp->mx][mtmp->my].glyph))
unmap_object(mtmp->mx, mtmp->my);
unmap_object(mtmp->mx, mtmp->my);
m_detach(mtmp, mptr);
}
@ -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)
@ -2152,36 +2226,36 @@ boolean was_swallowed; /* digestion */
mdat->mattk[i].aatyp = AT_BOOM;
mdat->mattk[i].adtyp = u.oonaenergy;
}
if (mdat->mattk[i].aatyp == AT_BOOM && mdat->mattk[i].adtyp != AD_HLBD && mdat->mattk[i].adtyp != AD_POSN) {
if (mdat->mattk[i].damn)
tmp = d((int)mdat->mattk[i].damn,
(int)mdat->mattk[i].damd);
if (mdat->mattk[i].aatyp == AT_BOOM && mdat->mattk[i].adtyp != AD_HLBD && mdat->mattk[i].adtyp != AD_POSN) {
if (mdat->mattk[i].damn)
tmp = d((int)mdat->mattk[i].damn,
(int)mdat->mattk[i].damd);
else if(mdat->mattk[i].damd)
tmp = d((int)mdat->mlevel+1, (int)mdat->mattk[i].damd);
else tmp = 0;
if (was_swallowed && magr) {
if (magr == &youmonst) {
There("is an explosion in your %s!",
body_part(STOMACH));
Sprintf(killer_buf, "%s explosion",
s_suffix(mdat->mname));
if (Half_physical_damage) tmp = (tmp+1) / 2;
losehp(tmp, killer_buf, KILLED_BY_AN);
if (was_swallowed && magr) {
if (magr == &youmonst) {
There("is an explosion in your %s!",
body_part(STOMACH));
Sprintf(killer_buf, "%s explosion",
s_suffix(mdat->mname));
if (Half_physical_damage) tmp = (tmp+1) / 2;
losehp(tmp, killer_buf, KILLED_BY_AN);
}
else {
if (flags.soundok) You_hear("an explosion.");
magr->mhp -= tmp;
if (magr->mhp < 1) mondied(magr);
if (magr->mhp < 1) { /* maybe lifesaved */
if (canspotmon(magr))
pline("%s rips open!", Monnam(magr));
if (flags.soundok) You_hear("an explosion.");
magr->mhp -= tmp;
if (magr->mhp < 1) mondied(magr);
if (magr->mhp < 1) { /* maybe lifesaved */
if (canspotmon(magr))
pline("%s rips open!", Monnam(magr));
}
else if (canseemon(magr)) pline("%s seems to have indigestion.", Monnam(magr));
}
return FALSE;
}
}
return FALSE;
}
Sprintf(killer_buf, "%s explosion", s_suffix(mdat->mname));
killer = killer_buf;
killer_format = KILLED_BY_AN;
@ -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]){
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 == &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_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)){
@ -2293,8 +2378,8 @@ boolean was_swallowed; /* digestion */
}
else if(mdat->mattk[i].adtyp == AD_KAOS){
makemon(&mons[PM_CHAOS], mon->mx, mon->my, MM_ADJACENTOK);
return (FALSE);
}
return (FALSE);
}
else if( ( (mdat->mattk[i].aatyp == AT_NONE && mdat==&mons[PM_GREAT_CTHULHU])
|| mdat->mattk[i].aatyp == AT_BOOM)
&& mdat->mattk[i].adtyp == AD_POSN){
@ -2472,7 +2557,7 @@ boolean was_swallowed; /* digestion */
lvlgain = rn2(2);
} else if((mdat==&mons[PM_DEEPEST_ONE])){
lvlgain = 1;
}
}
for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
mdat1 = mtmp->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]
@ -2578,7 +2665,7 @@ register struct monst *mdef;
/* cease occupation if the monster was associated */
if(mdef->moccupation) stop_occupation();
/* drop special items like the Amulet so that a dismissed Keter or nurse
can't remove them from the game */
mdrop_special_objs(mdef);
@ -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);
@ -2905,17 +2992,23 @@ cleanup:
u.hod += 10;
You_feel("guilty...");
}
/* give experience points */
tmp = experience(mtmp, (int)mvitals[mndx].died + 1);
more_experienced(tmp, 0);
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*/
@ -2935,7 +3028,7 @@ cleanup:
else You_hear("the studio audience applaud!");
} else if (mtmp->mpeaceful)
adjalign(-5);
if(((mtmp->mferal || mtmp->mtame)) && u.sealsActive&SEAL_BERITH) unbind(SEAL_BERITH,TRUE);
/* malign was already adjusted for u.ualign.type and randomization */
@ -3065,43 +3158,43 @@ int typ, fatal, opoistype;
pline("%s%s %s poisoned!", isupper(*string) ? "" : "The ",
string, plural ? "were" : "was");
}
if(!opoistype || (opoistype & OPOISON_BASIC)){
if(Poison_resistance) {
if(!strcmp(string, "blast")) shieldeff(u.ux, u.uy);
pline_The("poison doesn't seem to affect you.");
return;
}
/* suppress killer prefix if it already has one */
if ((i = name_to_mon(pname)) >= LOW_PM && mons[i].geno & G_UNIQ) {
kprefix = KILLED_BY;
if (!type_is_pname(&mons[i])) pname = the(pname);
} else if (!strncmpi(pname, "the ", 4) ||
!strncmpi(pname, "an ", 3) ||
!strncmpi(pname, "a ", 2)) {
/*[ does this need a plural check too? ]*/
kprefix = KILLED_BY;
}
i = rn2(fatal + 20*thrown_weapon);
if(i == 0 && typ != A_CHA) {
u.uhp = -1;
pline_The("poison was deadly...");
} else if(i <= 5) {
/* Check that a stat change was made */
if (adjattrib(typ, thrown_weapon ? -1 : -rn1(3,3), 1))
pline("You%s!", poiseff[typ]);
} else {
i = thrown_weapon ? rnd(6) : rn1(10,6);
if(Half_physical_damage) i = (i+1) / 2;
losehp(i, pname, kprefix);
}
if(u.uhp < 1) {
killer_format = kprefix;
killer = pname;
/* "Poisoned by a poisoned ___" is redundant */
done(strstri(pname, "poison") ? DIED : POISONING);
}
(void) encumber_msg();
if(Poison_resistance) {
if(!strcmp(string, "blast")) shieldeff(u.ux, u.uy);
pline_The("poison doesn't seem to affect you.");
return;
}
/* suppress killer prefix if it already has one */
if ((i = name_to_mon(pname)) >= LOW_PM && mons[i].geno & G_UNIQ) {
kprefix = KILLED_BY;
if (!type_is_pname(&mons[i])) pname = the(pname);
} else if (!strncmpi(pname, "the ", 4) ||
!strncmpi(pname, "an ", 3) ||
!strncmpi(pname, "a ", 2)) {
/*[ does this need a plural check too? ]*/
kprefix = KILLED_BY;
}
i = rn2(fatal + 20*thrown_weapon);
if(i == 0 && typ != A_CHA) {
u.uhp = -1;
pline_The("poison was deadly...");
} else if(i <= 5) {
/* Check that a stat change was made */
if (adjattrib(typ, thrown_weapon ? -1 : -rn1(3,3), 1))
pline("You%s!", poiseff[typ]);
} else {
i = thrown_weapon ? rnd(6) : rn1(10,6);
if(Half_physical_damage) i = (i+1) / 2;
losehp(i, pname, kprefix);
}
if(u.uhp < 1) {
killer_format = kprefix;
killer = pname;
/* "Poisoned by a poisoned ___" is redundant */
done(strstri(pname, "poison") ? DIED : POISONING);
}
(void) encumber_msg();
}
else if(opoistype & OPOISON_FILTH){
if(Sick_resistance) {
@ -3161,10 +3254,10 @@ int typ, fatal, opoistype;
if(u.sealsActive&SEAL_HUGINN_MUNINN){
unbind(SEAL_HUGINN_MUNINN,TRUE);
} else {
forget_levels(1); /* lose memory of 1% of levels*/
forget_objects(1); /* lose memory of 1% of objects*/
forget_traps(); /* lose memory of all traps*/
}
forget_levels(1); /* lose memory of 1% of levels*/
forget_objects(1); /* lose memory of 1% of objects*/
forget_traps(); /* lose memory of all traps*/
}
}
}
@ -3205,12 +3298,12 @@ register struct monst *mtmp;
make_stunned(HStun + mtmp->mhp/10, TRUE);
}
if(mtmp->data == &mons[PM_MEDUSA]) {
register int i;
for(i = 0; i < NATTK; i++)
if(mtmp->data->mattk[i].aatyp == AT_GAZE) {
register int i;
for(i = 0; i < NATTK; i++)
if(mtmp->data->mattk[i].aatyp == AT_GAZE) {
if(!mtmp->mtame) (void) gazemu(mtmp, &mtmp->data->mattk[i]);
break;
}
break;
}
} else if(mtmp->data == &mons[PM_GREAT_CTHULHU]) {
register int i;
for(i = 0; i < NATTK; i++)
@ -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)
@ -3524,7 +3649,7 @@ boolean msg; /* "The oldmon turns into a newmon!" */
int mndx, tryct;
struct permonst *olddata = mtmp->data;
char oldname[BUFSZ];
if (msg) {
/* like Monnam() but never mention saddle */
Strcpy(oldname, x_monnam(mtmp, ARTICLE_THE, (char *)0,
@ -3579,7 +3704,7 @@ boolean msg; /* "The oldmon turns into a newmon!" */
wormgone(mtmp);
place_monster(mtmp, mtmp->mx, mtmp->my);
}
/* Possibly Unblock */
if(!opaque(mdat) && opaque(mtmp->data)) unblock_point(mtmp->mx, mtmp->my);
/* Possibly Block */
@ -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);
}