diff --git a/include/align.h b/include/align.h index 5375db4cdf..ae8b7c4cb3 100644 --- a/include/align.h +++ b/include/align.h @@ -10,6 +10,7 @@ typedef schar aligntyp; /* basic alignment type */ typedef struct align { /* alignment & record */ aligntyp type; int record; + unsigned abuse; } align; /* bounds for "record" -- respect initial alignments of 10 */ diff --git a/include/extern.h b/include/extern.h index 588a83be49..17efeecbea 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1759,6 +1759,7 @@ extern void copy_mextra(struct monst *, struct monst *); extern void dealloc_mextra(struct monst *); extern boolean usmellmon(struct permonst *); extern void mimic_hit_msg(struct monst *, short); +extern void adj_erinys(unsigned); /* ### mondata.c ### */ diff --git a/include/monsters.h b/include/monsters.h index a34c662c80..b1bb58edb4 100644 --- a/include/monsters.h +++ b/include/monsters.h @@ -2492,12 +2492,14 @@ and spelled this way */ MON("erinys", S_DEMON, LVL(7, 12, 2, 30, 10), (G_HELL | G_NOCORPSE | G_SGROUP | 2), + /* erinys attacks (among other things) are variable depending on your + alignment abuse, can be increased from here by adj_erinys(mon.c) */ A(ATTK(AT_WEAP, AD_DRST, 2, 4), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), SIZ(WT_HUMAN, 400, MS_SILENT, MZ_HUMAN), MR_FIRE | MR_POISON, 0, M1_HUMANOID | M1_POIS, - M2_NOPOLY | M2_DEMON | M2_STALK | M2_HOSTILE | M2_STRONG | M2_NASTY - | M2_FEMALE | M2_COLLECT, + M2_NOPOLY | M2_DEMON | M2_STALK | M2_STRONG | M2_NASTY | M2_FEMALE + | M2_COLLECT, M3_INFRAVISIBLE | M3_INFRAVISION, 10, CLR_RED, ERINYS), MON("barbed devil", S_DEMON, LVL(8, 12, 0, 35, 8), (G_HELL | G_NOCORPSE | G_SGROUP | 2), diff --git a/src/attrib.c b/src/attrib.c index 7b278f864c..2bcc6cade0 100644 --- a/src/attrib.c +++ b/src/attrib.c @@ -1219,8 +1219,14 @@ adjalign(int n) int newalign = u.ualign.record + n; if (n < 0) { + unsigned newabuse = u.ualign.abuse - n; + if (newalign < u.ualign.record) u.ualign.record = newalign; + if (newabuse > u.ualign.abuse) { + u.ualign.abuse = newabuse; + adj_erinys(newabuse); + } } else if (newalign > u.ualign.record) { u.ualign.record = newalign; if (u.ualign.record > ALIGNLIM) diff --git a/src/makemon.c b/src/makemon.c index 92e2282f4e..b28d03f8d5 100644 --- a/src/makemon.c +++ b/src/makemon.c @@ -2129,6 +2129,8 @@ peace_minded(register struct permonst *ptr) return TRUE; if (ptr->msound == MS_NEMESIS) return FALSE; + if (ptr == &mons[PM_ERINYS]) + return !u.ualign.abuse; if (race_peaceful(ptr)) return TRUE; diff --git a/src/mon.c b/src/mon.c index ef5c63519f..96c112e6fd 100644 --- a/src/mon.c +++ b/src/mon.c @@ -5462,4 +5462,53 @@ check_gear_next_turn(struct monst *mon) { mon->misc_worn_check |= I_SPECIAL; } + +/* make erinyes more dangerous based on your alignment abuse */ +void +adj_erinys(unsigned abuse) +{ + struct permonst *pm = &mons[PM_ERINYS]; + + if (abuse > 5L) { + pm->mflags1 |= M1_SEE_INVIS; + } + if (abuse > 10L) { + pm->mflags1 |= M1_AMPHIBIOUS; + } + if (abuse > 15L) { + pm->mflags1 |= M1_FLY; + } + if (abuse > 20L) { + /* more powerful attack */ + pm->mattk[0].damn = 3; + } + if (abuse > 25L) { + pm->mflags1 |= M1_REGEN; + } + if (abuse > 30L) { + pm->mflags1 |= M1_TPORT_CNTRL; + } + if (abuse > 35L) { + /* second attack */ + pm->mattk[1].aatyp = AT_WEAP; + pm->mattk[1].adtyp = AD_DRST; + pm->mattk[1].damn = 3; + pm->mattk[1].damd = 4; + } + if (abuse > 40L) { + pm->mflags1 |= M1_TPORT; + } + if (abuse > 50L) { + /* third (spellcasting) attack */ + pm->mattk[2].aatyp = AT_MAGC; + pm->mattk[2].adtyp = AD_SPEL; + pm->mattk[2].damn = 3; + pm->mattk[2].damd = 4; + } + + /* also adjust level and difficulty */ + pm->mlevel = min(7 + u.ualign.abuse, 50); + pm->difficulty = min(10 + (u.ualign.abuse / 3), 25); +} + /*mon.c*/ diff --git a/src/monmove.c b/src/monmove.c index 63a7ee7f59..48b3464011 100644 --- a/src/monmove.c +++ b/src/monmove.c @@ -639,6 +639,10 @@ dochug(register struct monst* mtmp) return 0; } + /* Erinyes will inform surrounding monsters of your crimes */ + if (mdat == &mons[PM_ERINYS] && !mtmp->mpeaceful && m_canseeu(mtmp)) + aggravate(); + /* Shriekers and Medusa have irregular abilities which must be checked every turn. These abilities do not cost a turn when used. */ diff --git a/src/restore.c b/src/restore.c index 2b5a8fccb2..b2a487c3c5 100644 --- a/src/restore.c +++ b/src/restore.c @@ -692,6 +692,7 @@ restgamestate(NHFILE *nhfp) /* must come after all mons & objs are restored */ relink_timers(FALSE); relink_light_sources(FALSE); + adj_erinys(u.ualign.abuse); /* inventory display is now viable */ iflags.perm_invent = defer_perm_invent; return TRUE;