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

@@ -1637,6 +1637,9 @@ Lua selection operations 'subtract' and 'xor' didn't always work as intended
accept 'true' or 'false' as value for des.object field 'trapped'
special level loader didn't check for bad coordinates supplied by <level>.lua
file thorougnly enough
hero might not be credited with "entered Mine Town" achievement for the town
variations which treat the whole level as the town if that level gets
entered via falling or level teleport
Fixes to 3.7.0-x Platform and/or Interface Problems Exposed Via git Repository

View File

@@ -17,7 +17,7 @@
* Incrementing EDITLEVEL can be used to force invalidation of old bones
* and save files.
*/
#define EDITLEVEL 87
#define EDITLEVEL 88
/*
* Development status possibilities.

View File

@@ -410,13 +410,15 @@ struct levelflags {
Bitfield(is_maze_lev, 1);
Bitfield(is_cavernous_lev, 1);
Bitfield(arboreal, 1); /* Trees replace rock */
Bitfield(has_town, 1); /* level contains a town */
Bitfield(wizard_bones, 1); /* set if level came from a bones file
which was created in wizard mode (or
normal mode descendant of such) */
* which was created in wizard mode (or
* normal mode descendant of such) */
Bitfield(corrmaze, 1); /* Whether corridors are used for the maze
rather than ROOM */
* rather than ROOM */
Bitfield(rndmongen, 1); /* random monster generation allowed? */
Bitfield(deathdrops, 1); /* monsters may drop corpses/death drops */
Bitfield(noautosearch, 1); /* automatic searching disabled */
Bitfield(fumaroles, 1); /* lava emits poison gas at random */
Bitfield(stormy, 1); /* clouds create lightning bolts at random */

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)) {