You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

745 lines
20 KiB

/**
* @file automap.cpp
*
* Implementation of the in-game map overlay.
*/
#include "automap.h"
#include <algorithm>
#include "control.h"
#include "inv.h"
#include "miniwin/miniwin.h"
#include "monster.h"
#include "palette.h"
#include "player.h"
#include "setmaps.h"
#include "utils/ui_fwd.h"
namespace devilution {
namespace {
/**
* Maps from tile_id to automap type.
* BUGFIX: only the first 256 elements are ever read
*/
uint16_t AutomapTypes[512];
int AutoMapX;
int AutoMapY;
/** color used to draw the player's arrow */
#define COLOR_PLAYER (PAL8_ORANGE + 1)
/** color for bright map lines (doors, stairs etc.) */
#define COLOR_BRIGHT PAL8_YELLOW
/** color for dim map lines/dots */
#define COLOR_DIM (PAL16_YELLOW + 8)
// color for items on automap
#define COLOR_ITEM (PAL8_BLUE + 1)
#define MAPFLAG_TYPE 0x000F
/** these are in the second byte */
#define MAPFLAG_VERTDOOR 0x01
#define MAPFLAG_HORZDOOR 0x02
#define MAPFLAG_VERTARCH 0x04
#define MAPFLAG_HORZARCH 0x08
#define MAPFLAG_VERTGRATE 0x10
#define MAPFLAG_HORZGRATE 0x20
#define MAPFLAG_DIRT 0x40
#define MAPFLAG_STAIRS 0x80
/**
* @brief Renders the given automap shape at the specified screen coordinates.
*/
void DrawAutomapTile(const CelOutputBuffer &out, int sx, int sy, uint16_t automapType)
{
uint8_t flags = automapType >> 8;
if ((flags & MAPFLAG_DIRT) != 0) {
SetPixel(out, sx, sy, COLOR_DIM);
SetPixel(out, sx - AmLine8, sy - AmLine4, COLOR_DIM);
SetPixel(out, sx - AmLine8, sy + AmLine4, COLOR_DIM);
SetPixel(out, sx + AmLine8, sy - AmLine4, COLOR_DIM);
SetPixel(out, sx + AmLine8, sy + AmLine4, COLOR_DIM);
SetPixel(out, sx - AmLine16, sy, COLOR_DIM);
SetPixel(out, sx + AmLine16, sy, COLOR_DIM);
SetPixel(out, sx, sy - AmLine8, COLOR_DIM);
SetPixel(out, sx, sy + AmLine8, COLOR_DIM);
SetPixel(out, sx + AmLine8 - AmLine32, sy + AmLine4, COLOR_DIM);
SetPixel(out, sx - AmLine8 + AmLine32, sy + AmLine4, COLOR_DIM);
SetPixel(out, sx - AmLine16, sy + AmLine8, COLOR_DIM);
SetPixel(out, sx + AmLine16, sy + AmLine8, COLOR_DIM);
SetPixel(out, sx - AmLine8, sy + AmLine16 - AmLine4, COLOR_DIM);
SetPixel(out, sx + AmLine8, sy + AmLine16 - AmLine4, COLOR_DIM);
SetPixel(out, sx, sy + AmLine16, COLOR_DIM);
}
if ((flags & MAPFLAG_STAIRS) != 0) {
DrawLineTo(out, sx - AmLine8, sy - AmLine8 - AmLine4, sx + AmLine8 + AmLine16, sy + AmLine4, COLOR_BRIGHT);
DrawLineTo(out, sx - AmLine16, sy - AmLine8, sx + AmLine16, sy + AmLine8, COLOR_BRIGHT);
DrawLineTo(out, sx - AmLine16 - AmLine8, sy - AmLine4, sx + AmLine8, sy + AmLine8 + AmLine4, COLOR_BRIGHT);
DrawLineTo(out, sx - AmLine32, sy, sx, sy + AmLine16, COLOR_BRIGHT);
}
bool doVert = false;
bool doHorz = false;
bool doCaveHorz = false;
bool doCaveVert = false;
switch (automapType & MAPFLAG_TYPE) {
case 1: { // stand-alone column or other unpassable object
int x1 = sx - AmLine16;
int y1 = sy - AmLine16;
int x2 = x1 + AmLine32;
int y2 = sy - AmLine8;
DrawLineTo(out, sx, y1, x1, y2, COLOR_DIM);
DrawLineTo(out, sx, y1, x2, y2, COLOR_DIM);
DrawLineTo(out, sx, sy, x1, y2, COLOR_DIM);
DrawLineTo(out, sx, sy, x2, y2, COLOR_DIM);
} break;
case 2:
case 5:
doVert = true;
break;
case 3:
case 6:
doHorz = true;
break;
case 4:
doVert = true;
doHorz = true;
break;
case 8:
doVert = true;
doCaveHorz = true;
break;
case 9:
doHorz = true;
doCaveVert = true;
break;
case 10:
doCaveHorz = true;
break;
case 11:
doCaveVert = true;
break;
case 12:
doCaveHorz = true;
doCaveVert = true;
break;
}
if (doVert) { // right-facing obstacle
if ((flags & MAPFLAG_VERTDOOR) != 0) { // two wall segments with a door in the middle
int x1 = sx - AmLine32;
int x2 = sx - AmLine16;
int y1 = sy - AmLine16;
int y2 = sy - AmLine8;
DrawLineTo(out, sx, y1, sx - AmLine8, y1 + AmLine4, COLOR_DIM);
DrawLineTo(out, x1, sy, x1 + AmLine8, sy - AmLine4, COLOR_DIM);
DrawLineTo(out, x2, y1, x1, y2, COLOR_BRIGHT);
DrawLineTo(out, x2, y1, sx, y2, COLOR_BRIGHT);
DrawLineTo(out, x2, sy, x1, y2, COLOR_BRIGHT);
DrawLineTo(out, x2, sy, sx, y2, COLOR_BRIGHT);
}
if ((flags & MAPFLAG_VERTGRATE) != 0) { // right-facing half-wall
DrawLineTo(out, sx - AmLine16, sy - AmLine8, sx - AmLine32, sy, COLOR_DIM);
flags |= MAPFLAG_VERTARCH;
}
if ((flags & MAPFLAG_VERTARCH) != 0) { // window or passable column
int x1 = sx - AmLine16;
int y1 = sy - AmLine16;
int x2 = x1 + AmLine32;
int y2 = sy - AmLine8;
DrawLineTo(out, sx, y1, x1, y2, COLOR_DIM);
DrawLineTo(out, sx, y1, x2, y2, COLOR_DIM);
DrawLineTo(out, sx, sy, x1, y2, COLOR_DIM);
DrawLineTo(out, sx, sy, x2, y2, COLOR_DIM);
}
if ((flags & (MAPFLAG_VERTDOOR | MAPFLAG_VERTGRATE | MAPFLAG_VERTARCH)) == 0)
DrawLineTo(out, sx, sy - AmLine16, sx - AmLine32, sy, COLOR_DIM);
}
if (doHorz) { // left-facing obstacle
if ((flags & MAPFLAG_HORZDOOR) != 0) {
int x1 = sx + AmLine16;
int x2 = sx + AmLine32;
int y1 = sy - AmLine16;
int y2 = sy - AmLine8;
DrawLineTo(out, sx, y1, sx + AmLine8, y1 + AmLine4, COLOR_DIM);
DrawLineTo(out, x2, sy, x2 - AmLine8, sy - AmLine4, COLOR_DIM);
DrawLineTo(out, x1, y1, sx, y2, COLOR_BRIGHT);
DrawLineTo(out, x1, y1, x2, y2, COLOR_BRIGHT);
DrawLineTo(out, x1, sy, sx, y2, COLOR_BRIGHT);
DrawLineTo(out, x1, sy, x2, y2, COLOR_BRIGHT);
}
if ((flags & MAPFLAG_HORZGRATE) != 0) {
DrawLineTo(out, sx + AmLine16, sy - AmLine8, sx + AmLine32, sy, COLOR_DIM);
flags |= MAPFLAG_HORZARCH;
}
if ((flags & MAPFLAG_HORZARCH) != 0) {
int x1 = sx - AmLine16;
int y1 = sy - AmLine16;
int x2 = x1 + AmLine32;
int y2 = sy - AmLine8;
DrawLineTo(out, sx, y1, x1, y2, COLOR_DIM);
DrawLineTo(out, sx, y1, x2, y2, COLOR_DIM);
DrawLineTo(out, sx, sy, x1, y2, COLOR_DIM);
DrawLineTo(out, sx, sy, x2, y2, COLOR_DIM);
}
if ((flags & (MAPFLAG_HORZDOOR | MAPFLAG_HORZGRATE | MAPFLAG_HORZARCH)) == 0)
DrawLineTo(out, sx, sy - AmLine16, sx + AmLine32, sy, COLOR_DIM);
}
// for caves the horz/vert flags are switched
if (doCaveHorz) {
if ((flags & MAPFLAG_VERTDOOR) != 0) {
int x1 = sx - AmLine32;
int x2 = sx - AmLine16;
int y1 = sy + AmLine16;
int y2 = sy + AmLine8;
DrawLineTo(out, sx, y1, sx - AmLine8, y1 - AmLine4, COLOR_DIM);
DrawLineTo(out, x1, sy, x1 + AmLine8, sy + AmLine4, COLOR_DIM);
DrawLineTo(out, x2, y1, x1, y2, COLOR_BRIGHT);
DrawLineTo(out, x2, y1, sx, y2, COLOR_BRIGHT);
DrawLineTo(out, x2, sy, x1, y2, COLOR_BRIGHT);
DrawLineTo(out, x2, sy, sx, y2, COLOR_BRIGHT);
} else
DrawLineTo(out, sx, sy + AmLine16, sx - AmLine32, sy, COLOR_DIM);
}
if (doCaveVert) {
if ((flags & MAPFLAG_HORZDOOR) != 0) {
int x1 = sx + AmLine16;
int x2 = sx + AmLine32;
int y1 = sy + AmLine16;
int y2 = sy + AmLine8;
DrawLineTo(out, sx, y1, sx + AmLine8, y1 - AmLine4, COLOR_DIM);
DrawLineTo(out, x2, sy, x2 - AmLine8, sy + AmLine4, COLOR_DIM);
DrawLineTo(out, x1, y1, sx, y2, COLOR_BRIGHT);
DrawLineTo(out, x1, y1, x2, y2, COLOR_BRIGHT);
DrawLineTo(out, x1, sy, sx, y2, COLOR_BRIGHT);
DrawLineTo(out, x1, sy, x2, y2, COLOR_BRIGHT);
} else {
DrawLineTo(out, sx, sy + AmLine16, sx + AmLine32, sy, COLOR_DIM);
}
}
}
void DrawAutomapItem(const CelOutputBuffer &out, int x, int y, uint8_t color)
{
int x1 = x - AmLine32 / 2;
int y1 = y - AmLine16 / 2;
int x2 = x1 + AmLine64 / 2;
int y2 = y1 + AmLine32 / 2;
DrawLineTo(out, x, y1, x1, y, color);
DrawLineTo(out, x, y1, x2, y, color);
DrawLineTo(out, x, y2, x1, y, color);
DrawLineTo(out, x, y2, x2, y, color);
}
void SearchAutomapItem(const CelOutputBuffer &out)
{
int x = plr[myplr].position.tile.x;
int y = plr[myplr].position.tile.y;
if (plr[myplr]._pmode == PM_WALK3) {
x = plr[myplr].position.future.x;
y = plr[myplr].position.future.y;
if (plr[myplr]._pdir == DIR_W)
x++;
else
y++;
}
const int startX = clamp(x - 8, 0, MAXDUNX);
const int startY = clamp(y - 8, 0, MAXDUNY);
const int endX = clamp(x + 8, 0, MAXDUNX);
const int endY = clamp(y + 8, 0, MAXDUNY);
for (int i = startX; i < endX; i++) {
for (int j = startY; j < endY; j++) {
if (dItem[i][j] != 0) {
int px = i - 2 * AutoMapXOfs - ViewX;
int py = j - 2 * AutoMapYOfs - ViewY;
x = (ScrollInfo.offset.x * AutoMapScale / 100 / 2) + (px - py) * AmLine16 + gnScreenWidth / 2;
y = (ScrollInfo.offset.y * AutoMapScale / 100 / 2) + (px + py) * AmLine8 + (gnScreenHeight - PANEL_HEIGHT) / 2;
if (PANELS_COVER) {
if (invflag || sbookflag)
x -= 160;
if (chrflag || questlog)
x += 160;
}
y -= AmLine8;
DrawAutomapItem(out, x, y, COLOR_ITEM);
}
}
}
}
/**
* @brief Renders an arrow on the automap, centered on and facing the direction of the player.
*/
void DrawAutomapPlr(const CelOutputBuffer &out, int pnum)
{
int x;
int y;
int playerColor = COLOR_PLAYER + (8 * pnum) % 128;
if (plr[pnum]._pmode == PM_WALK3) {
x = plr[pnum].position.future.x;
y = plr[pnum].position.future.y;
if (plr[pnum]._pdir == DIR_W)
x++;
else
y++;
} else {
x = plr[pnum].position.tile.x;
y = plr[pnum].position.tile.y;
}
int px = x - 2 * AutoMapXOfs - ViewX;
int py = y - 2 * AutoMapYOfs - ViewY;
x = (plr[pnum].position.offset.x * AutoMapScale / 100 / 2) + (ScrollInfo.offset.x * AutoMapScale / 100 / 2) + (px - py) * AmLine16 + gnScreenWidth / 2;
y = (plr[pnum].position.offset.y * AutoMapScale / 100 / 2) + (ScrollInfo.offset.y * AutoMapScale / 100 / 2) + (px + py) * AmLine8 + (gnScreenHeight - PANEL_HEIGHT) / 2;
if (PANELS_COVER) {
if (invflag || sbookflag)
x -= gnScreenWidth / 4;
if (chrflag || questlog)
x += gnScreenWidth / 4;
}
y -= AmLine8;
switch (plr[pnum]._pdir) {
case DIR_N:
DrawLineTo(out, x, y, x, y - AmLine16, playerColor);
DrawLineTo(out, x, y - AmLine16, x - AmLine4, y - AmLine8, playerColor);
DrawLineTo(out, x, y - AmLine16, x + AmLine4, y - AmLine8, playerColor);
break;
case DIR_NE:
DrawLineTo(out, x, y, x + AmLine16, y - AmLine8, playerColor);
DrawLineTo(out, x + AmLine16, y - AmLine8, x + AmLine8, y - AmLine8, playerColor);
DrawLineTo(out, x + AmLine16, y - AmLine8, x + AmLine8 + AmLine4, y, playerColor);
break;
case DIR_E:
DrawLineTo(out, x, y, x + AmLine16, y, playerColor);
DrawLineTo(out, x + AmLine16, y, x + AmLine8, y - AmLine4, playerColor);
DrawLineTo(out, x + AmLine16, y, x + AmLine8, y + AmLine4, playerColor);
break;
case DIR_SE:
DrawLineTo(out, x, y, x + AmLine16, y + AmLine8, playerColor);
DrawLineTo(out, x + AmLine16, y + AmLine8, x + AmLine8 + AmLine4, y, playerColor);
DrawLineTo(out, x + AmLine16, y + AmLine8, x + AmLine8, y + AmLine8, playerColor);
break;
case DIR_S:
case DIR_OMNI:
DrawLineTo(out, x, y, x, y + AmLine16, playerColor);
DrawLineTo(out, x, y + AmLine16, x + AmLine4, y + AmLine8, playerColor);
DrawLineTo(out, x, y + AmLine16, x - AmLine4, y + AmLine8, playerColor);
break;
case DIR_SW:
DrawLineTo(out, x, y, x - AmLine16, y + AmLine8, playerColor);
DrawLineTo(out, x - AmLine16, y + AmLine8, x - AmLine4 - AmLine8, y, playerColor);
DrawLineTo(out, x - AmLine16, y + AmLine8, x - AmLine8, y + AmLine8, playerColor);
break;
case DIR_W:
DrawLineTo(out, x, y, x - AmLine16, y, playerColor);
DrawLineTo(out, x - AmLine16, y, x - AmLine8, y - AmLine4, playerColor);
DrawLineTo(out, x - AmLine16, y, x - AmLine8, y + AmLine4, playerColor);
break;
case DIR_NW:
DrawLineTo(out, x, y, x - AmLine16, y - AmLine8, playerColor);
DrawLineTo(out, x - AmLine16, y - AmLine8, x - AmLine8, y - AmLine8, playerColor);
DrawLineTo(out, x - AmLine16, y - AmLine8, x - AmLine4 - AmLine8, y, playerColor);
break;
}
}
/**
* @brief Returns the automap shape at the given coordinate.
*/
uint16_t GetAutomapType(int x, int y, bool view)
{
if (view && x == -1 && y >= 0 && y < DMAXY && automapview[0][y]) {
if ((GetAutomapType(0, y, false) & (MAPFLAG_DIRT << 8)) != 0) {
return 0;
}
return MAPFLAG_DIRT << 8;
}
if (view && y == -1 && x >= 0 && x < DMAXY && automapview[x][0]) {
if ((GetAutomapType(x, 0, false) & (MAPFLAG_DIRT << 8)) != 0) {
return 0;
}
return MAPFLAG_DIRT << 8;
}
if (x < 0 || x >= DMAXX) {
return 0;
}
if (y < 0 || y >= DMAXX) {
return 0;
}
if (!automapview[x][y] && view) {
return 0;
}
uint16_t rv = AutomapTypes[(BYTE)dungeon[x][y]];
if (rv == 7) {
if (((GetAutomapType(x - 1, y, false) >> 8) & MAPFLAG_HORZARCH) != 0) {
if (((GetAutomapType(x, y - 1, false) >> 8) & MAPFLAG_VERTARCH) != 0) {
rv = 1;
}
}
}
return rv;
}
/**
* @brief Renders game info, such as the name of the current level, and in multi player the name of the game and the game password.
*/
void DrawAutomapText(const CelOutputBuffer &out)
{
// TODO: Use the `out` buffer instead of the global one.
char desc[256];
int nextline = 20;
if (gbIsMultiplayer) {
strcat(strcpy(desc, "game: "), szPlayerName);
PrintGameStr(out, 8, 20, desc, COL_GOLD);
nextline = 35;
if (szPlayerDescript[0] != 0) {
strcat(strcpy(desc, "password: "), szPlayerDescript);
PrintGameStr(out, 8, 35, desc, COL_GOLD);
nextline = 50;
}
}
if (setlevel) {
PrintGameStr(out, 8, nextline, quest_level_names[(BYTE)setlvlnum], COL_GOLD);
} else if (currlevel != 0) {
if (currlevel < 17 || currlevel > 20) {
if (currlevel < 21 || currlevel > 24)
sprintf(desc, "Level: %i", currlevel);
else
sprintf(desc, "Level: Crypt %i", currlevel - 20);
} else {
sprintf(desc, "Level: Nest %i", currlevel - 16);
}
PrintGameStr(out, 8, nextline, desc, COL_GOLD);
}
}
} // namespace
bool automapflag;
bool automapview[DMAXX][DMAXY];
int AutoMapScale;
int AutoMapXOfs;
int AutoMapYOfs;
int AmLine64;
int AmLine32;
int AmLine16;
int AmLine8;
int AmLine4;
void InitAutomapOnce()
{
automapflag = false;
AutoMapScale = 50;
AmLine64 = 32;
AmLine32 = 16;
AmLine16 = 8;
AmLine8 = 4;
AmLine4 = 2;
}
void InitAutomap()
{
DWORD dwTiles;
BYTE *pAFile;
memset(AutomapTypes, 0, sizeof(AutomapTypes));
switch (leveltype) {
case DTYPE_CATHEDRAL:
if (currlevel < 21)
pAFile = LoadFileInMem("Levels\\L1Data\\L1.AMP", &dwTiles);
else
pAFile = LoadFileInMem("NLevels\\L5Data\\L5.AMP", &dwTiles);
break;
case DTYPE_CATACOMBS:
pAFile = LoadFileInMem("Levels\\L2Data\\L2.AMP", &dwTiles);
break;
case DTYPE_CAVES:
if (currlevel < 17)
pAFile = LoadFileInMem("Levels\\L3Data\\L3.AMP", &dwTiles);
else
pAFile = LoadFileInMem("NLevels\\L6Data\\L6.AMP", &dwTiles);
break;
case DTYPE_HELL:
pAFile = LoadFileInMem("Levels\\L4Data\\L4.AMP", &dwTiles);
break;
default:
return;
}
dwTiles /= 2;
BYTE *pTmp = pAFile;
for (unsigned i = 1; i <= dwTiles; i++) {
uint8_t b1 = *pTmp++;
uint8_t b2 = *pTmp++;
AutomapTypes[i] = b1 + (b2 << 8);
}
mem_free_dbg(pAFile);
memset(automapview, 0, sizeof(automapview));
for (auto &column : dFlags)
for (auto &dFlag : column)
dFlag &= ~BFLAG_EXPLORED;
}
void StartAutomap()
{
AutoMapXOfs = 0;
AutoMapYOfs = 0;
automapflag = true;
}
void AutomapUp()
{
AutoMapXOfs--;
AutoMapYOfs--;
}
void AutomapDown()
{
AutoMapXOfs++;
AutoMapYOfs++;
}
void AutomapLeft()
{
AutoMapXOfs--;
AutoMapYOfs++;
}
void AutomapRight()
{
AutoMapXOfs++;
AutoMapYOfs--;
}
void AutomapZoomIn()
{
if (AutoMapScale < 200) {
AutoMapScale += 5;
AmLine64 = (AutoMapScale * 64) / 100;
AmLine32 = AmLine64 / 2;
AmLine16 = AmLine32 / 2;
AmLine8 = AmLine16 / 2;
AmLine4 = AmLine8 / 2;
}
}
void AutomapZoomOut()
{
if (AutoMapScale > 50) {
AutoMapScale -= 5;
AmLine64 = (AutoMapScale * 64) / 100;
AmLine32 = AmLine64 / 2;
AmLine16 = AmLine32 / 2;
AmLine8 = AmLine16 / 2;
AmLine4 = AmLine8 / 2;
}
}
void DrawAutomap(const CelOutputBuffer &out)
{
int sx;
int sy;
if (leveltype == DTYPE_TOWN) {
DrawAutomapText(out);
return;
}
AutoMapX = (ViewX - 16) / 2;
while (AutoMapX + AutoMapXOfs < 0)
AutoMapXOfs++;
while (AutoMapX + AutoMapXOfs >= DMAXX)
AutoMapXOfs--;
AutoMapX += AutoMapXOfs;
AutoMapY = (ViewY - 16) / 2;
while (AutoMapY + AutoMapYOfs < 0)
AutoMapYOfs++;
while (AutoMapY + AutoMapYOfs >= DMAXY)
AutoMapYOfs--;
AutoMapY += AutoMapYOfs;
int d = (AutoMapScale * 64) / 100;
int cells = 2 * (gnScreenWidth / 2 / d) + 1;
if (((gnScreenWidth / 2) % d) != 0)
cells++;
if ((gnScreenWidth / 2) % d >= (AutoMapScale * 32) / 100)
cells++;
if ((ScrollInfo.offset.x + ScrollInfo.offset.y) != 0)
cells++;
int mapx = AutoMapX - cells;
int mapy = AutoMapY - 1;
if ((cells & 1) != 0) {
sx = gnScreenWidth / 2 - AmLine64 * ((cells - 1) / 2);
sy = (gnScreenHeight - PANEL_HEIGHT) / 2 - AmLine32 * ((cells + 1) / 2);
} else {
sx = gnScreenWidth / 2 - AmLine64 * (cells / 2) + AmLine32;
sy = (gnScreenHeight - PANEL_HEIGHT) / 2 - AmLine32 * (cells / 2) - AmLine16;
}
if ((ViewX & 1) != 0) {
sx -= AmLine16;
sy -= AmLine8;
}
if ((ViewY & 1) != 0) {
sx += AmLine16;
sy -= AmLine8;
}
sx += AutoMapScale * ScrollInfo.offset.x / 100 / 2;
sy += AutoMapScale * ScrollInfo.offset.y / 100 / 2;
if (PANELS_COVER) {
if (invflag || sbookflag) {
sx -= gnScreenWidth / 4;
}
if (chrflag || questlog) {
sx += gnScreenWidth / 4;
}
}
for (int i = 0; i <= cells + 1; i++) {
int x = sx;
int y;
for (int j = 0; j < cells; j++) {
uint16_t maptype = GetAutomapType(mapx + j, mapy - j, true);
if (maptype != 0)
DrawAutomapTile(out, x, sy, maptype);
x += AmLine64;
}
mapy++;
x = sx - AmLine32;
y = sy + AmLine16;
for (int j = 0; j <= cells; j++) {
uint16_t maptype = GetAutomapType(mapx + j, mapy - j, true);
if (maptype != 0)
DrawAutomapTile(out, x, y, maptype);
x += AmLine64;
}
mapx++;
sy += AmLine32;
}
for (int pnum = 0; pnum < MAX_PLRS; pnum++) {
if (plr[pnum].plrlevel == plr[myplr].plrlevel && plr[pnum].plractive && !plr[pnum]._pLvlChanging) {
DrawAutomapPlr(out, pnum);
}
}
if (AutoMapShowItems)
SearchAutomapItem(out);
DrawAutomapText(out);
}
void SetAutomapView(int x, int y)
{
int xx = (x - 16) / 2;
int yy = (y - 16) / 2;
if (xx < 0 || xx >= DMAXX || yy < 0 || yy >= DMAXY) {
return;
}
automapview[xx][yy] = true;
uint16_t maptype = GetAutomapType(xx, yy, false);
uint16_t solid = maptype & 0x4000;
switch (maptype & MAPFLAG_TYPE) {
case 2:
if (solid != 0) {
if (GetAutomapType(xx, yy + 1, false) == 0x4007)
automapview[xx][yy + 1] = true;
} else if ((GetAutomapType(xx - 1, yy, false) & 0x4000) != 0) {
automapview[xx - 1][yy] = true;
}
break;
case 3:
if (solid != 0) {
if (GetAutomapType(xx + 1, yy, false) == 0x4007)
automapview[xx + 1][yy] = true;
} else if ((GetAutomapType(xx, yy - 1, false) & 0x4000) != 0) {
automapview[xx][yy - 1] = true;
}
break;
case 4:
if (solid != 0) {
if (GetAutomapType(xx, yy + 1, false) == 0x4007)
automapview[xx][yy + 1] = true;
if (GetAutomapType(xx + 1, yy, false) == 0x4007)
automapview[xx + 1][yy] = true;
} else {
if ((GetAutomapType(xx - 1, yy, false) & 0x4000) != 0)
automapview[xx - 1][yy] = true;
if ((GetAutomapType(xx, yy - 1, false) & 0x4000) != 0)
automapview[xx][yy - 1] = true;
if ((GetAutomapType(xx - 1, yy - 1, false) & 0x4000) != 0)
automapview[xx - 1][yy - 1] = true;
}
break;
case 5:
if (solid != 0) {
if ((GetAutomapType(xx, yy - 1, false) & 0x4000) != 0)
automapview[xx][yy - 1] = true;
if (GetAutomapType(xx, yy + 1, false) == 0x4007)
automapview[xx][yy + 1] = true;
} else if ((GetAutomapType(xx - 1, yy, false) & 0x4000) != 0) {
automapview[xx - 1][yy] = true;
}
break;
case 6:
if (solid != 0) {
if ((GetAutomapType(xx - 1, yy, false) & 0x4000) != 0)
automapview[xx - 1][yy] = true;
if (GetAutomapType(xx + 1, yy, false) == 0x4007)
automapview[xx + 1][yy] = true;
} else if ((GetAutomapType(xx, yy - 1, false) & 0x4000) != 0) {
automapview[xx][yy - 1] = true;
}
break;
}
}
void AutomapZoomReset()
{
AutoMapXOfs = 0;
AutoMapYOfs = 0;
AmLine64 = (AutoMapScale * 64) / 100;
AmLine32 = AmLine64 / 2;
AmLine16 = AmLine32 / 2;
AmLine8 = AmLine16 / 2;
AmLine4 = AmLine8 / 2;
}
} // namespace devilution