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
+3
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' accept 'true' or 'false' as value for des.object field 'trapped'
special level loader didn't check for bad coordinates supplied by <level>.lua special level loader didn't check for bad coordinates supplied by <level>.lua
file thorougnly enough 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 Fixes to 3.7.0-x Platform and/or Interface Problems Exposed Via git Repository
+1 -1
View File
@@ -17,7 +17,7 @@
* Incrementing EDITLEVEL can be used to force invalidation of old bones * Incrementing EDITLEVEL can be used to force invalidation of old bones
* and save files. * and save files.
*/ */
#define EDITLEVEL 87 #define EDITLEVEL 88
/* /*
* Development status possibilities. * Development status possibilities.
+5 -3
View File
@@ -410,13 +410,15 @@ struct levelflags {
Bitfield(is_maze_lev, 1); Bitfield(is_maze_lev, 1);
Bitfield(is_cavernous_lev, 1); Bitfield(is_cavernous_lev, 1);
Bitfield(arboreal, 1); /* Trees replace rock */ 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 Bitfield(wizard_bones, 1); /* set if level came from a bones file
which was created in wizard mode (or * which was created in wizard mode (or
normal mode descendant of such) */ * normal mode descendant of such) */
Bitfield(corrmaze, 1); /* Whether corridors are used for the maze Bitfield(corrmaze, 1); /* Whether corridors are used for the maze
rather than ROOM */ * rather than ROOM */
Bitfield(rndmongen, 1); /* random monster generation allowed? */ Bitfield(rndmongen, 1); /* random monster generation allowed? */
Bitfield(deathdrops, 1); /* monsters may drop corpses/death drops */ Bitfield(deathdrops, 1); /* monsters may drop corpses/death drops */
Bitfield(noautosearch, 1); /* automatic searching disabled */ Bitfield(noautosearch, 1); /* automatic searching disabled */
Bitfield(fumaroles, 1); /* lava emits poison gas at random */ Bitfield(fumaroles, 1); /* lava emits poison gas at random */
Bitfield(stormy, 1); /* clouds create lightning bolts at random */ Bitfield(stormy, 1); /* clouds create lightning bolts at random */
+17 -6
View File
@@ -3069,11 +3069,10 @@ in_rooms(register coordxy x, register coordxy y, register int typewanted)
boolean boolean
in_town(coordxy x, coordxy y) in_town(coordxy x, coordxy y)
{ {
s_level *slev = Is_special(&u.uz);
register struct mkroom *sroom; register struct mkroom *sroom;
boolean has_subrooms = FALSE; boolean has_subrooms = FALSE;
if (!slev || !slev->flags.town) if (!gl.level.flags.has_town)
return FALSE; return FALSE;
/* /*
@@ -3140,15 +3139,27 @@ check_special_room(boolean newlev)
if (*u.ushops0) if (*u.ushops0)
u_left_shop(u.ushops_left, newlev); u_left_shop(u.ushops_left, newlev);
if (!*u.uentered && !*u.ushops_entered) /* implied by newlev */ /*
return; /* no entrance messages necessary */ * Check for attaining 'entered Mine Town' achievement.
* Most of the Mine Town variations have the town in one large room
if (!gc.context.achieveo.minetn_reached * 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)) { && In_mines(&u.uz) && in_town(u.ux, u.uy)) {
record_achievement(ACH_TOWN); record_achievement(ACH_TOWN);
gc.context.achieveo.minetn_reached = TRUE; 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? */ /* Did we just enter a shop? */
if (*u.ushops_entered) if (*u.ushops_entered)
u_entered_shop(u.ushops_entered); u_entered_shop(u.ushops_entered);
+6
View File
@@ -793,8 +793,14 @@ clear_level_structures(void)
gl.level.flags.is_maze_lev = 0; gl.level.flags.is_maze_lev = 0;
gl.level.flags.is_cavernous_lev = 0; gl.level.flags.is_cavernous_lev = 0;
gl.level.flags.arboreal = 0; gl.level.flags.arboreal = 0;
gl.level.flags.has_town = 0;
gl.level.flags.wizard_bones = 0; gl.level.flags.wizard_bones = 0;
gl.level.flags.corrmaze = 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; gn.nroom = 0;
gr.rooms[0].hx = -1; gr.rooms[0].hx = -1;
+8 -3
View File
@@ -524,6 +524,7 @@ void
fixup_special(void) fixup_special(void)
{ {
lev_region *r = gl.lregions; lev_region *r = gl.lregions;
s_level *sp;
struct d_level lev; struct d_level lev;
int x, y; int x, y;
struct mkroom *croom; struct mkroom *croom;
@@ -547,8 +548,7 @@ fixup_special(void)
lev = u.uz; lev = u.uz;
lev.dlevel = atoi(r->rname.str); lev.dlevel = atoi(r->rname.str);
} else { } else {
s_level *sp = find_level(r->rname.str); sp = find_level(r->rname.str);
lev = sp->dlevel; lev = sp->dlevel;
} }
/*FALLTHRU*/ /*FALLTHRU*/
@@ -648,6 +648,9 @@ fixup_special(void)
stolen_booty(); stolen_booty();
} }
if ((sp = Is_special(&u.uz)) != 0 && sp->flags.town) /* Mine Town */
gl.level.flags.has_town = 1;
if (gl.lregions) if (gl.lregions)
free((genericptr_t) gl.lregions), gl.lregions = 0; free((genericptr_t) gl.lregions), gl.lregions = 0;
gn.num_lregions = 0; gn.num_lregions = 0;
@@ -1076,6 +1079,7 @@ makemaz(const char *s)
/* SPLEVTYPE format is "level-choice,level-choice"... */ /* SPLEVTYPE format is "level-choice,level-choice"... */
if (wizard && *protofile && sp && sp->rndlevs) { if (wizard && *protofile && sp && sp->rndlevs) {
char *ep = getenv("SPLEVTYPE"); /* not nh_getenv */ char *ep = getenv("SPLEVTYPE"); /* not nh_getenv */
if (ep) { if (ep) {
/* strrchr always succeeds due to code in prior block */ /* strrchr always succeeds due to code in prior block */
int len = (int) ((strrchr(protofile, '-') - protofile) + 1); int len = (int) ((strrchr(protofile, '-') - protofile) + 1);
@@ -1083,6 +1087,7 @@ makemaz(const char *s)
while (ep && *ep) { while (ep && *ep) {
if (!strncmp(ep, protofile, len)) { if (!strncmp(ep, protofile, len)) {
int pick = atoi(ep + len); int pick = atoi(ep + len);
/* use choice only if valid */ /* use choice only if valid */
if (pick > 0 && pick <= (int) sp->rndlevs) if (pick > 0 && pick <= (int) sp->rndlevs)
Sprintf(protofile + len, "%d", pick); Sprintf(protofile + len, "%d", pick);
@@ -1109,7 +1114,7 @@ makemaz(const char *s)
impossible("Couldn't load \"%s\" - making a maze.", protofile); 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); gl.level.flags.corrmaze = !rn2(3);
if (!Invocation_lev(&u.uz) && rn2(2)) { if (!Invocation_lev(&u.uz) && rn2(2)) {