fix github issue #1070 - Minetown achievement

Issue reported by vultur-cadens:  arriving on the Mine Town level
via falling or level teleport won't register the "entered Minetown"
achievement if hero doesn't arrive inside a room.

Reorder some code in check_special_room() so that town entry will be
tested before the early return if no room entry has occurred.  This
adds 'level.flags.has_town' to make the town test be cheaper when
the hero hasn't attained the achievement yet and is wandering around
the mines.

Fixes #1070
This commit is contained in:
PatR
2023-07-06 13:18:19 -07:00
parent 2bba306348
commit 60a3263a85
6 changed files with 40 additions and 13 deletions

View File

@@ -3069,11 +3069,10 @@ in_rooms(register coordxy x, register coordxy y, register int typewanted)
boolean
in_town(coordxy x, coordxy y)
{
s_level *slev = Is_special(&u.uz);
register struct mkroom *sroom;
boolean has_subrooms = FALSE;
if (!slev || !slev->flags.town)
if (!gl.level.flags.has_town)
return FALSE;
/*
@@ -3140,15 +3139,27 @@ check_special_room(boolean newlev)
if (*u.ushops0)
u_left_shop(u.ushops_left, newlev);
if (!*u.uentered && !*u.ushops_entered) /* implied by newlev */
return; /* no entrance messages necessary */
if (!gc.context.achieveo.minetn_reached
/*
* Check for attaining 'entered Mine Town' achievement.
* Most of the Mine Town variations have the town in one large room
* containing a bunch of subrooms; we check for entering that large
* room. However, two of the variations cover the whole level rather
* than include a room with subrooms. We need to check for town entry
* before the possible early return for not having entered a room in
* case we have arrived in the town but have not entered any room.
*
* TODO: change the minetn variants which don't include any town
* boundary to have such.
*/
if (gl.level.flags.has_town && !gc.context.achieveo.minetn_reached
&& In_mines(&u.uz) && in_town(u.ux, u.uy)) {
record_achievement(ACH_TOWN);
gc.context.achieveo.minetn_reached = TRUE;
}
if (!*u.uentered && !*u.ushops_entered) /* implied by newlev */
return; /* no entrance messages necessary */
/* Did we just enter a shop? */
if (*u.ushops_entered)
u_entered_shop(u.ushops_entered);

View File

@@ -793,8 +793,14 @@ clear_level_structures(void)
gl.level.flags.is_maze_lev = 0;
gl.level.flags.is_cavernous_lev = 0;
gl.level.flags.arboreal = 0;
gl.level.flags.has_town = 0;
gl.level.flags.wizard_bones = 0;
gl.level.flags.corrmaze = 0;
gl.level.flags.rndmongen = 0;
gl.level.flags.deathdrops = 0;
gl.level.flags.noautosearch = 0;
gl.level.flags.fumaroles = 0;
gl.level.flags.stormy = 0;
gn.nroom = 0;
gr.rooms[0].hx = -1;

View File

@@ -524,6 +524,7 @@ void
fixup_special(void)
{
lev_region *r = gl.lregions;
s_level *sp;
struct d_level lev;
int x, y;
struct mkroom *croom;
@@ -547,8 +548,7 @@ fixup_special(void)
lev = u.uz;
lev.dlevel = atoi(r->rname.str);
} else {
s_level *sp = find_level(r->rname.str);
sp = find_level(r->rname.str);
lev = sp->dlevel;
}
/*FALLTHRU*/
@@ -648,6 +648,9 @@ fixup_special(void)
stolen_booty();
}
if ((sp = Is_special(&u.uz)) != 0 && sp->flags.town) /* Mine Town */
gl.level.flags.has_town = 1;
if (gl.lregions)
free((genericptr_t) gl.lregions), gl.lregions = 0;
gn.num_lregions = 0;
@@ -1076,6 +1079,7 @@ makemaz(const char *s)
/* SPLEVTYPE format is "level-choice,level-choice"... */
if (wizard && *protofile && sp && sp->rndlevs) {
char *ep = getenv("SPLEVTYPE"); /* not nh_getenv */
if (ep) {
/* strrchr always succeeds due to code in prior block */
int len = (int) ((strrchr(protofile, '-') - protofile) + 1);
@@ -1083,6 +1087,7 @@ makemaz(const char *s)
while (ep && *ep) {
if (!strncmp(ep, protofile, len)) {
int pick = atoi(ep + len);
/* use choice only if valid */
if (pick > 0 && pick <= (int) sp->rndlevs)
Sprintf(protofile + len, "%d", pick);
@@ -1109,7 +1114,7 @@ makemaz(const char *s)
impossible("Couldn't load \"%s\" - making a maze.", protofile);
}
gl.level.flags.is_maze_lev = TRUE;
gl.level.flags.is_maze_lev = 1;
gl.level.flags.corrmaze = !rn2(3);
if (!Invocation_lev(&u.uz) && rn2(2)) {