Skip to content

Commit

Permalink
Make erinyes scale with alignment abuse
Browse files Browse the repository at this point in the history
Consistent with their mythological role of punishing those who had
violated societal taboos -- oathbreakers, hosts who attacked their
guests, etc -- erinyes scale with the cumulative amount of alignment
abuse the hero has committed over the course of the game.  This is
tracked separately from the alignment record, and cannot be cleared by
the hero improving her favor with her god via "good deeds" as the normal
alignment record can.  Erinyes will gain abilities, levels, and attacks
as the hero's alignment abuse worsens.  They will also aggravate
monsters when near the hero.
  • Loading branch information
entrez authored and PatR committed Jan 11, 2024
1 parent 32f3f7c commit f930a12
Show file tree
Hide file tree
Showing 8 changed files with 68 additions and 2 deletions.
1 change: 1 addition & 0 deletions include/align.h
Expand Up @@ -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 */
Expand Down
1 change: 1 addition & 0 deletions include/extern.h
Expand Up @@ -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 ### */

Expand Down
6 changes: 4 additions & 2 deletions include/monsters.h
Expand Up @@ -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),
Expand Down
6 changes: 6 additions & 0 deletions src/attrib.c
Expand Up @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions src/makemon.c
Expand Up @@ -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;
Expand Down
49 changes: 49 additions & 0 deletions src/mon.c
Expand Up @@ -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*/
4 changes: 4 additions & 0 deletions src/monmove.c
Expand Up @@ -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. */
Expand Down
1 change: 1 addition & 0 deletions src/restore.c
Expand Up @@ -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;
Expand Down

0 comments on commit f930a12

Please sign in to comment.