From 62a95101094b0fdbd8fe66414a5c5464de5fd1e3 Mon Sep 17 00:00:00 2001 From: PatR Date: Thu, 14 Jul 2022 13:38:09 -0700 Subject: [PATCH] \#wizfliplevel fixes Fix wizard mode issues pointed out by the #wizmakemap fix. If a shopkeeper or temple priest is on a different level and its home level gets flipped, monst eshk or epri data became invalid and would cause trouble if the shk or priest ever made it back to home level. If a vault guard is maintaining a temporary corridor and the level gets flipped, the data became invalid. If you used #wizfliplevel while the guard was leading you out, the corridor spots would be flipped along with the rest of the map but the guards's temporary corridor data didn't match. Breaches in the vault walls would be sealed, then the guard would just mill around, never finishing leading the hero out. --- doc/fixes3-7-0.txt | 3 +++ src/sp_lev.c | 65 +++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 65 insertions(+), 3 deletions(-) diff --git a/doc/fixes3-7-0.txt b/doc/fixes3-7-0.txt index 8f465807e..204ba151d 100644 --- a/doc/fixes3-7-0.txt +++ b/doc/fixes3-7-0.txt @@ -957,6 +957,9 @@ if #wizmakemap was used to generate a replacement level while any shopkeeper, temple priest, or vault guard from the level was off of it at the time, the monster's eshk, epri, or egd data became invalid and would cause trouble if the monster returned to its 'home' level +similarly, if #wizfliplevel was used to transpose an active level while a + vauld guard was maintaining a temporary corridor or while a monster + with eshk, epri, or egd data was off level, that data became invalid blessed potion of polymorph will prompt user for monster to poly into diff --git a/src/sp_lev.c b/src/sp_lev.c index b4aa4d8d8..da68519d6 100644 --- a/src/sp_lev.c +++ b/src/sp_lev.c @@ -27,6 +27,8 @@ static void flip_drawbridge_horizontal(struct rm *); static void flip_drawbridge_vertical(struct rm *); static void flip_visuals(int, int, int, int, int); static int flip_encoded_direction_bits(int, int); +static void flip_vault_guard(int, struct monst *, + coordxy, coordxy, coordxy, coordxy); static void sel_set_wall_property(coordxy, coordxy, genericptr_t); static void set_wall_property(coordxy, coordxy, coordxy, coordxy, int); static void count_features(void); @@ -484,7 +486,10 @@ flip_encoded_direction_bits(int flp, int val) /* transpose top with bottom or left with right or both; sometimes called for new special levels, or for any level via the #wizfliplevel command */ void -flip_level(int flp, boolean extras) +flip_level( + int flp, /* mask for orientation(s) to transpose */ + boolean extras) /* False: level creation; True: #wizfliplevel is + * altering an active level so more needs to be done */ { int x, y, i, itmp; coordxy minx, miny, maxx, maxy; @@ -589,8 +594,12 @@ flip_level(int flp, boolean extras) /* monsters */ for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) { - if (mtmp->isgd && mtmp->mx == 0) - continue; + if (mtmp->isgd) { + if (extras) /* flip mtmp->mextra->egd */ + flip_vault_guard(flp, mtmp, minx, miny, maxx, maxy); + if (mtmp->mx == 0) /* not on map so don't flip guard->mx,my */ + continue; + } /* skip the occasional earth elemental outside the flip area */ if (!inFlipArea(mtmp->mx, mtmp->my)) continue; @@ -617,6 +626,20 @@ flip_level(int flp, boolean extras) } #endif } + if (extras) { /* #wizfliplevel rather than level creation */ + for (mtmp = g.migrating_mons; mtmp; mtmp = mtmp->nmon) { + if (mtmp->isgd && on_level(&u.uz, &EGD(mtmp)->gdlevel)) { + flip_vault_guard(flp, mtmp, minx, miny, maxx, maxy); /* egd */ + } else if (mtmp->ispriest + && on_level(&u.uz, &EPRI(mtmp)->shrlevel)) { + Flip_coord(EPRI(mtmp)->shrpos); /* priest's altar */ + } else if (mtmp->isshk + && on_level(&u.uz, &ESHK(mtmp)->shoplevel)) { + Flip_coord(ESHK(mtmp)->shk); /* shk's preferred spot */ + Flip_coord(ESHK(mtmp)->shd); /* shop door */ + } + } + } /* engravings */ for (etmp = head_engr; etmp; etmp = etmp->nxt_engr) { @@ -831,6 +854,42 @@ flip_level(int flp, boolean extras) vision_reset(); } +/* for #wizfliplevel, flip guard's egd data; not needed for level creation */ +static void +flip_vault_guard( + int flp, /* 1: transpose vertically, 2: transpose horizontally, 3: both */ + struct monst *gd, /* the vault guard, has monst->mextra->egd data */ + coordxy minx, coordxy miny, /* needed by FlipX(), FlipY(), */ + coordxy maxx, coordxy maxy) /* and inFlipArea() macros */ +{ + int i; + struct egd *egd = EGD(gd); + + if (inFlipArea(egd->gdx, egd->gdy)) { + if (flp & 1) + egd->gdy = FlipY(egd->gdy); + if (flp & 2) + egd->gdx = FlipX(egd->gdx); + } + if (inFlipArea(egd->ogx, egd->ogy)) { + if (flp & 1) + egd->ogy = FlipY(egd->ogy); + if (flp & 2) + egd->ogx = FlipX(egd->ogx); + } + for (i = egd->fcbeg; i < egd->fcend; ++i) { + coordxy fx = egd->fakecorr[i].fx, fy = egd->fakecorr[i].fy; + + if (inFlipArea(fx, fy)) { + if (flp & 1) + egd->fakecorr[i].fy = FlipY(fy); + if (flp & 2) + egd->fakecorr[i].fx = FlipX(fx); + } + } + return; +} + #undef FlipX #undef FlipY #undef inFlipArea