extern void set_uasmon(void);
extern void float_vs_flight(void);
extern void change_sex(void);
+extern void livelog_newform(boolean, int, int);
extern void polyself(int);
extern int polymon(int);
extern void rehumanize(void);
* Incrementing EDITLEVEL can be used to force invalidation of old bones
* and save files.
*/
-#define EDITLEVEL 48
+#define EDITLEVEL 49
/*
* Development status possibilities.
boolean umoved; /* changed map location (post-move) */
int last_str_turn; /* 0: none, 1: half turn, 2: full turn
+: turn right, -: turn left */
- int ulevel; /* 1 to MAXULEV */
- int ulevelmax;
+ int ulevel; /* 1 to MAXULEV (30) */
+ int ulevelmax; /* highest level, but might go down (to throttle
+ * lost level recovery via blessed full healing) */
+ int ulevelpeak; /* really highest level reached; never does down */
unsigned utrap; /* trap timeout */
unsigned utraptype; /* defined if utrap nonzero. one of utraptypes */
char urooms[5]; /* rooms (roomno + 3) occupied now */
make_slimed(0L, (char *) 0);
break;
case AMULET_OF_CHANGE: {
- int orig_sex = poly_gender();
+ int new_sex, orig_sex = poly_gender();
if (Unchanging)
break;
change_sex();
+ new_sex = poly_gender();
/* Don't use same message as polymorph */
- if (orig_sex != poly_gender()) {
+ if (new_sex != orig_sex) {
makeknown(AMULET_OF_CHANGE);
You("are suddenly very %s!",
flags.female ? "feminine" : "masculine");
g.context.botl = 1;
newsym(u.ux, u.uy); /* glyphmon flag and tile may have gone
- from male to female or vice versa */
- } else
+ * from male to female or vice versa */
+ } else {
/* already polymorphed into single-gender monster; only
changed the character's base sex */
You("don't feel like yourself.");
+ }
+ livelog_newform(FALSE, orig_sex, new_sex);
pline_The("amulet disintegrates!");
if (orig_sex == poly_gender() && uamul->dknown
&& !objects[AMULET_OF_CHANGE].oc_name_known
u.ulevel -= 1;
/* remove intrinsic abilities */
adjabil(u.ulevel + 1, u.ulevel);
- livelog_printf(LL_MINORAC, "lost experience level %d", u.ulevel);
+ livelog_printf(LL_MINORAC, "lost experience level %d", u.ulevel + 1);
} else {
if (drainer) {
g.killer.format = KILLED_BY;
}
void
-pluslvl(boolean incr) /* true iff via incremental experience growth */
-{ /* (false for potion of gain level) */
+pluslvl(
+ boolean incr) /* True: incremental experience growth;
+ * False: potion of gain level or wraith corpse */
+{
int hpinc, eninc;
if (!incr)
/* increase level (unless already maxxed) */
if (u.ulevel < MAXULEV) {
- int newrank, oldrank = xlev_to_rank(u.ulevel);
+ int old_ach_cnt, newrank, oldrank = xlev_to_rank(u.ulevel);
/* increase experience points to reflect new level */
if (incr) {
if (u.ulevelmax < u.ulevel)
u.ulevelmax = u.ulevel;
adjabil(u.ulevel - 1, u.ulevel); /* give new intrinsics */
+
+ old_ach_cnt = count_achievements();
newrank = xlev_to_rank(u.ulevel);
if (newrank > oldrank)
record_achievement(achieve_rank(newrank));
- else
- livelog_printf(LL_MINORAC, "gained experience level %d",
- u.ulevel);
+ /* a new rank achievement will log its own message; log a simpler
+ message here if we didn't just get an achievement (so when rank
+ hasn't changed or hero just regained a lost level and the rank
+ achievement doesn't get repeated) */
+ if (count_achievements() == old_ach_cnt)
+ livelog_printf(LL_MINORAC, "%sgained experience level %d",
+ (u.ulevel <= u.ulevelpeak) ? "re" : "", u.ulevel);
+ if (u.ulevel > u.ulevelpeak)
+ u.ulevelpeak = u.ulevel;
}
g.context.botl = TRUE;
}
*/
static void
-show_achievements(int final) /* used "behind the curtain" by enl_foo() macros */
+show_achievements(
+ int final) /* 'final' is used "behind the curtain" by enl_foo() macros */
{
int i, achidx, absidx, acnt;
char title[QBUFSZ], buf[QBUFSZ];
#if 0
/* change monster type to match new sex; disabled with
PM_AMOROUS_DEMON */
-
u.umonnum = (u.umonnum == PM_SUCCUBUS) ? PM_INCUBUS : PM_SUCCUBUS;
#endif
set_uasmon();
}
}
+/* log a message if non-poly'd hero's gender has changed */
+void
+livelog_newform(boolean viapoly, int oldgend, int newgend)
+{
+ char buf[BUFSZ];
+ const char *oldrole, *oldrank, *newrole, *newrank;
+
+ /*
+ * TODO?
+ * Give other logging feedback here instead of in newman().
+ */
+
+ if (!Upolyd) {
+ if (newgend != oldgend) {
+ oldrole = (oldgend && g.urole.name.f) ? g.urole.name.f
+ : g.urole.name.m;
+ newrole = (newgend && g.urole.name.f) ? g.urole.name.f
+ : g.urole.name.m;
+ oldrank = rank_of(u.ulevel, Role_switch, oldgend);
+ newrank = rank_of(u.ulevel, Role_switch, newgend);
+ Sprintf(buf, "%.10s %.30s", genders[flags.female].adj, newrank);
+ livelog_printf(LL_MINORAC, "%s into %s",
+ viapoly ? "polymorphed" : "transformed",
+ an(strcmp(newrole, oldrole) ? newrole
+ : strcmp(newrank, oldrank) ? newrank
+ : buf));
+ }
+ }
+}
+
static void
newman(void)
{
- int i, oldlvl, newlvl, hpmax, enmax;
+ const char *newform;
+ int i, oldlvl, newlvl, oldgend, newgend, hpmax, enmax;
oldlvl = u.ulevel;
newlvl = oldlvl + rn1(5, -2); /* new = old + {-2,-1,0,+1,+2} */
u.ulevelmax = newlvl;
u.ulevel = newlvl;
+ oldgend = poly_gender();
if (g.sex_change_ok && !rn2(10))
change_sex();
}
}
newuhs(FALSE);
- polyman("You feel like a new %s!",
- /* use saved gender we're about to revert to, not current */
- ((Upolyd ? u.mfemale : flags.female) && g.urace.individual.f)
+ /* use saved gender we're about to revert to, not current */
+ newform = ((Upolyd ? u.mfemale : flags.female) && g.urace.individual.f)
? g.urace.individual.f
: (g.urace.individual.m)
? g.urace.individual.m
- : g.urace.noun);
+ : g.urace.noun;
+ polyman("You feel like a new %s!", newform);
+
+ newgend = poly_gender();
+ /* note: newman() bypasses achievemnts for new ranks attained and
+ doesn't log "new <form>" when that isn't accompanied by level change */
+ if (newlvl != oldlvl)
+ livelog_printf(LL_MINORAC, "became experience level %d as a new %s",
+ newlvl, newform);
+ else
+ livelog_newform(TRUE, oldgend, newgend);
+
if (Slimed) {
Your("body transforms, but there is still slime on you.");
make_slimed(10L, (const char *) 0);