Browse Source

♻️Clean up automap code

Use Point for x,y pairs. Make helpers for drawing door and squares
pull/1837/head
Anders Jenbo 5 years ago
parent
commit
654a2b8834
  1. 711
      Source/automap.cpp
  2. 9
      Source/automap.h
  3. 4
      Source/control.cpp
  4. 6
      Source/controls/plrctrls.cpp
  5. 2
      Source/debug.cpp
  6. 16
      Source/diablo.cpp
  7. 21
      Source/engine.cpp
  8. 17
      Source/engine.h
  9. 4
      Source/lighting.cpp
  10. 14
      Source/loadsave.cpp
  11. 4
      Source/msg.cpp
  12. 2
      Source/multi.cpp
  13. 2
      Source/objects.cpp
  14. 10
      Source/qol/xpbar.cpp
  15. 2
      Source/scrollrt.cpp
  16. 2
      Source/track.cpp
  17. 48
      test/automap_test.cpp

711
Source/automap.cpp

@ -22,266 +22,229 @@ namespace devilution {
namespace {
/**
* Maps from tile_id to automap type.
* BUGFIX: only the first 256 elements are ever read
*/
uint16_t AutomapTypes[512];
uint16_t AutomapTypes[256];
Point Automap;
enum MapColors : uint8_t {
/** color used to draw the player's arrow */
MapColorsPlayer = (PAL8_ORANGE + 1),
/** color for bright map lines (doors, stairs etc.) */
MapColorsBright = PAL8_YELLOW,
/** color for dim map lines/dots */
MapColorsDim = (PAL16_YELLOW + 8),
/** color for items on automap */
MapColorsItem = (PAL8_BLUE + 1),
};
constexpr uint16_t MapFlagsType = 0x000F;
/** these are in the second byte */
enum MapFlags : uint8_t {
// clang-format off
MapFlagsMapVerticalDoor = 1 << 0,
MapFlagsMapHorizontalDoor = 1 << 1,
MapFlagsVerticalArch = 1 << 2,
MapFlagsHorizontalArch = 1 << 3,
MapFlagsVerticalGrate = 1 << 4,
MapFlagsHorizontalGrate = 1 << 5,
MapFlagsDirt = 1 << 6,
MapFlagsStairs = 1 << 7,
// clang-format on
};
void DrawSquare(const CelOutputBuffer &out, Point center, uint8_t color)
{
Point left { center.x - AmLine16, center.y };
Point top { center.x, center.y - AmLine8 };
Point right { center.x + AmLine16, center.y };
Point bottom { center.x, center.y + AmLine8 };
DrawLineTo(out, top, left, color);
DrawLineTo(out, top, right, color);
DrawLineTo(out, bottom, left, color);
DrawLineTo(out, bottom, right, color);
}
int AutoMapX;
int AutoMapY;
void DrawMapVerticalDoor(const CelOutputBuffer &out, Point center)
{
Point offest { center.x - AmLine32, center.y - AmLine16 };
/** 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)
DrawLineTo(out, { center.x, offest.y }, { center.x - AmLine8, offest.y + AmLine4 }, MapColorsDim);
DrawLineTo(out, { offest.x, center.y }, { offest.x + AmLine8, center.y - AmLine4 }, MapColorsDim);
DrawSquare(out, { center.x - AmLine16, center.y - AmLine8 }, MapColorsBright);
}
#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
void DrawMapHorizontalDoor(const CelOutputBuffer &out, Point center)
{
Point offest { center.x + AmLine32, center.y - AmLine16 };
DrawLineTo(out, { center.x, offest.y }, { center.x + AmLine8, offest.y + AmLine4 }, MapColorsDim);
DrawLineTo(out, { offest.x, center.y }, { offest.x - AmLine8, center.y - AmLine4 }, MapColorsDim);
DrawSquare(out, { center.x + AmLine16, center.y - AmLine8 }, MapColorsBright);
}
/**
* @brief Renders the given automap shape at the specified screen coordinates.
*/
void DrawAutomapTile(const CelOutputBuffer &out, int sx, int sy, uint16_t automapType)
void DrawAutomapTile(const CelOutputBuffer &out, Point center, 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) {
if ((flags & MapFlagsDirt) != 0) {
SetPixel(out, center, MapColorsDim);
SetPixel(out, { center.x - AmLine8, center.y - AmLine4 }, MapColorsDim);
SetPixel(out, { center.x - AmLine8, center.y + AmLine4 }, MapColorsDim);
SetPixel(out, { center.x + AmLine8, center.y - AmLine4 }, MapColorsDim);
SetPixel(out, { center.x + AmLine8, center.y + AmLine4 }, MapColorsDim);
SetPixel(out, { center.x - AmLine16, center.y }, MapColorsDim);
SetPixel(out, { center.x + AmLine16, center.y }, MapColorsDim);
SetPixel(out, { center.x, center.y - AmLine8 }, MapColorsDim);
SetPixel(out, { center.x, center.y + AmLine8 }, MapColorsDim);
SetPixel(out, { center.x + AmLine8 - AmLine32, center.y + AmLine4 }, MapColorsDim);
SetPixel(out, { center.x - AmLine8 + AmLine32, center.y + AmLine4 }, MapColorsDim);
SetPixel(out, { center.x - AmLine16, center.y + AmLine8 }, MapColorsDim);
SetPixel(out, { center.x + AmLine16, center.y + AmLine8 }, MapColorsDim);
SetPixel(out, { center.x - AmLine8, center.y + AmLine16 - AmLine4 }, MapColorsDim);
SetPixel(out, { center.x + AmLine8, center.y + AmLine16 - AmLine4 }, MapColorsDim);
SetPixel(out, { center.x, center.y + AmLine16 }, MapColorsDim);
}
if ((flags & MapFlagsStairs) != 0) {
DrawLineTo(out, { center.x - AmLine8, center.y - AmLine8 - AmLine4 }, { center.x + AmLine8 + AmLine16, center.y + AmLine4 }, MapColorsBright);
DrawLineTo(out, { center.x - AmLine16, center.y - AmLine8 }, { center.x + AmLine16, center.y + AmLine8 }, MapColorsBright);
DrawLineTo(out, { center.x - AmLine16 - AmLine8, center.y - AmLine4 }, { center.x + AmLine8, center.y + AmLine8 + AmLine4 }, MapColorsBright);
DrawLineTo(out, { center.x - AmLine32, center.y }, { center.x, center.y + AmLine16 }, MapColorsBright);
}
bool drawVertical = false;
bool drawHorizontal = false;
bool drawCaveHorizontal = false;
bool drawCaveVertical = false;
switch (automapType & MapFlagsType) {
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);
DrawSquare(out, { center.x, center.y - AmLine8 }, MapColorsDim);
} break;
case 2:
case 5:
doVert = true;
drawVertical = true;
break;
case 3:
case 6:
doHorz = true;
drawHorizontal = true;
break;
case 4:
doVert = true;
doHorz = true;
drawVertical = true;
drawHorizontal = true;
break;
case 8:
doVert = true;
doCaveHorz = true;
drawVertical = true;
drawCaveHorizontal = true;
break;
case 9:
doHorz = true;
doCaveVert = true;
drawHorizontal = true;
drawCaveVertical = true;
break;
case 10:
doCaveHorz = true;
drawCaveHorizontal = true;
break;
case 11:
doCaveVert = true;
drawCaveVertical = true;
break;
case 12:
doCaveHorz = true;
doCaveVert = true;
drawCaveHorizontal = true;
drawCaveVertical = 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 (drawVertical) { // right-facing obstacle
if ((flags & MapFlagsMapVerticalDoor) != 0) { // two wall segments with a door in the middle
DrawMapVerticalDoor(out, center);
}
if ((flags & MapFlagsVerticalGrate) != 0) { // right-facing half-wall
DrawLineTo(out, { center.x - AmLine16, center.y - AmLine8 }, { center.x - AmLine32, center.y }, MapColorsDim);
flags |= MapFlagsVerticalArch;
}
if ((flags & MapFlagsVerticalArch) != 0) { // window or passable column
DrawSquare(out, { center.x, center.y - AmLine8 }, MapColorsDim);
}
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 & (MapFlagsMapVerticalDoor | MapFlagsVerticalGrate | MapFlagsVerticalArch)) == 0) {
DrawLineTo(out, { center.x, center.y - AmLine16 }, { center.x - AmLine32, center.y }, MapColorsDim);
}
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 (drawHorizontal) { // left-facing obstacle
if ((flags & MapFlagsMapVerticalDoor) != 0) {
DrawMapHorizontalDoor(out, center);
}
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 & MapFlagsHorizontalGrate) != 0) {
DrawLineTo(out, { center.x + AmLine16, center.y - AmLine8 }, { center.x + AmLine32, center.y }, MapColorsDim);
flags |= MapFlagsHorizontalArch;
}
if ((flags & MAPFLAG_HORZGRATE) != 0) {
DrawLineTo(out, sx + AmLine16, sy - AmLine8, sx + AmLine32, sy, COLOR_DIM);
flags |= MAPFLAG_HORZARCH;
if ((flags & MapFlagsHorizontalArch) != 0) {
DrawSquare(out, { center.x, center.y - AmLine8 }, MapColorsDim);
}
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 & (MapFlagsMapVerticalDoor | MapFlagsHorizontalGrate | MapFlagsHorizontalArch)) == 0) {
DrawLineTo(out, { center.x, center.y - AmLine16 }, { center.x + AmLine32, center.y }, MapColorsDim);
}
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);
}
// For caves the horizontal/vertical flags are swapped
if (drawCaveHorizontal) {
if ((flags & MapFlagsMapVerticalDoor) != 0) {
DrawMapHorizontalDoor(out, { center.x - AmLine32, center.y + AmLine16 });
} else {
DrawLineTo(out, sx, sy + AmLine16, sx + AmLine32, sy, COLOR_DIM);
DrawLineTo(out, { center.x, center.y + AmLine16 }, { center.x - AmLine32, center.y }, MapColorsDim);
}
}
}
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);
if (drawCaveVertical) {
if ((flags & MapFlagsMapVerticalDoor) != 0) {
DrawMapVerticalDoor(out, { center.x + AmLine32, center.y + AmLine16 });
} else {
DrawLineTo(out, { center.x, center.y + AmLine16 }, { center.x + AmLine32, center.y }, MapColorsDim);
}
}
}
void SearchAutomapItem(const CelOutputBuffer &out)
{
int x = plr[myplr].position.tile.x;
int y = plr[myplr].position.tile.y;
Point tile = plr[myplr].position.tile;
if (plr[myplr]._pmode == PM_WALK3) {
x = plr[myplr].position.future.x;
y = plr[myplr].position.future.y;
tile = plr[myplr].position.future;
if (plr[myplr]._pdir == DIR_W)
x++;
tile.x++;
else
y++;
tile.y++;
}
const int startX = clamp(x - 8, 0, MAXDUNX);
const int startY = clamp(y - 8, 0, MAXDUNY);
const int startX = clamp(tile.x - 8, 0, MAXDUNX);
const int startY = clamp(tile.y - 8, 0, MAXDUNY);
const int endX = clamp(x + 8, 0, MAXDUNX);
const int endY = clamp(y + 8, 0, MAXDUNY);
const int endX = clamp(tile.x + 8, 0, MAXDUNX);
const int endY = clamp(tile.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);
if (dItem[i][j] == 0)
continue;
int px = i - 2 * AutomapOffset.x - ViewX;
int py = j - 2 * AutomapOffset.y - ViewY;
Point screen = {
(ScrollInfo.offset.x * AutoMapScale / 100 / 2) + (px - py) * AmLine16 + gnScreenWidth / 2,
(ScrollInfo.offset.y * AutoMapScale / 100 / 2) + (px + py) * AmLine8 + (gnScreenHeight - PANEL_HEIGHT) / 2
};
if (PANELS_COVER) {
if (invflag || sbookflag)
screen.x -= 160;
if (chrflag || questlog)
screen.x += 160;
}
screen.y -= AmLine8;
DrawSquare(out, screen, MapColorsItem);
}
}
}
@ -289,116 +252,121 @@ void SearchAutomapItem(const CelOutputBuffer &out)
/**
* @brief Renders an arrow on the automap, centered on and facing the direction of the player.
*/
void DrawAutomapPlr(const CelOutputBuffer &out, int pnum)
void DrawAutomapPlr(const CelOutputBuffer &out, int playerId)
{
int x;
int y;
int playerColor = COLOR_PLAYER + (8 * pnum) % 128;
int playerColor = MapColorsPlayer + (8 * playerId) % 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++;
Point tile = plr[playerId].position.tile;
if (plr[playerId]._pmode == PM_WALK3) {
tile = plr[playerId].position.future;
if (plr[playerId]._pdir == DIR_W)
tile.x++;
else
y++;
} else {
x = plr[pnum].position.tile.x;
y = plr[pnum].position.tile.y;
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;
int px = tile.x - 2 * AutomapOffset.x - ViewX;
int py = tile.y - 2 * AutomapOffset.y - ViewY;
Point base = {
(plr[playerId].position.offset.x * AutoMapScale / 100 / 2) + (ScrollInfo.offset.x * AutoMapScale / 100 / 2) + (px - py) * AmLine16 + gnScreenWidth / 2,
(plr[playerId].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;
base.x -= gnScreenWidth / 4;
if (chrflag || questlog)
x += gnScreenWidth / 4;
base.x += gnScreenWidth / 4;
}
y -= AmLine8;
base.y -= AmLine8;
switch (plr[pnum]._pdir) {
Point point;
Point left;
Point right;
switch (plr[playerId]._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);
point = { base.x, base.y - AmLine16 };
left = { base.x - AmLine4, base.y - AmLine8 };
right = { base.x + AmLine4, base.y - AmLine8 };
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);
point = { base.x + AmLine16, base.y - AmLine8 };
left = { base.x + AmLine8, base.y - AmLine8 };
right = { base.x + AmLine8 + AmLine4, base.y };
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);
point = { base.x + AmLine16, base.y };
left = { base.x + AmLine8, base.y - AmLine4 };
right = { base.x + AmLine8, base.y + AmLine4 };
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);
point = { base.x + AmLine16, base.y + AmLine8 };
left = { base.x + AmLine8 + AmLine4, base.y };
right = { base.x + AmLine8, base.y + AmLine8 };
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);
point = { base.x, base.y + AmLine16 };
left = { base.x + AmLine4, base.y + AmLine8 };
right = { base.x - AmLine4, base.y + AmLine8 };
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);
point = { base.x - AmLine16, base.y + AmLine8 };
left = { base.x - AmLine4 - AmLine8, base.y };
right = { base.x - AmLine8, base.y + AmLine8 };
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);
point = { base.x - AmLine16, base.y };
left = { base.x - AmLine8, base.y - AmLine4 };
right = { base.x - AmLine8, base.y + AmLine4 };
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);
point = { base.x - AmLine16, base.y - AmLine8 };
left = { base.x - AmLine8, base.y - AmLine8 };
right = { base.x - AmLine4 - AmLine8, base.y };
break;
}
DrawLineTo(out, base, point, playerColor);
DrawLineTo(out, point, left, playerColor);
DrawLineTo(out, point, right, playerColor);
}
/**
* @brief Returns the automap shape at the given coordinate.
*/
uint16_t GetAutomapType(int x, int y, bool view)
uint16_t GetAutomapType(Point map, bool view)
{
if (view && x == -1 && y >= 0 && y < DMAXY && automapview[0][y]) {
if ((GetAutomapType(0, y, false) & (MAPFLAG_DIRT << 8)) != 0) {
if (view && map.x == -1 && map.y >= 0 && map.y < DMAXY && AutomapView[0][map.y]) {
if ((GetAutomapType({ 0, map.y }, false) & (MapFlagsDirt << 8)) != 0) {
return 0;
}
return MAPFLAG_DIRT << 8;
return MapFlagsDirt << 8;
}
if (view && y == -1 && x >= 0 && x < DMAXY && automapview[x][0]) {
if ((GetAutomapType(x, 0, false) & (MAPFLAG_DIRT << 8)) != 0) {
if (view && map.y == -1 && map.x >= 0 && map.x < DMAXY && AutomapView[map.x][0]) {
if ((GetAutomapType({ map.x, 0 }, false) & (MapFlagsDirt << 8)) != 0) {
return 0;
}
return MAPFLAG_DIRT << 8;
return MapFlagsDirt << 8;
}
if (x < 0 || x >= DMAXX) {
if (map.x < 0 || map.x >= DMAXX) {
return 0;
}
if (y < 0 || y >= DMAXX) {
if (map.y < 0 || map.y >= DMAXX) {
return 0;
}
if (!automapview[x][y] && view) {
if (!AutomapView[map.x][map.y] && view) {
return 0;
}
uint16_t rv = AutomapTypes[(BYTE)dungeon[x][y]];
uint16_t rv = AutomapTypes[dungeon[map.x][map.y]];
if (rv == 7) {
if (((GetAutomapType(x - 1, y, false) >> 8) & MAPFLAG_HORZARCH) != 0) {
if (((GetAutomapType(x, y - 1, false) >> 8) & MAPFLAG_VERTARCH) != 0) {
if (((GetAutomapType({ map.x - 1, map.y }, false) >> 8) & MapFlagsHorizontalArch) != 0) {
if (((GetAutomapType({ map.x, map.y - 1 }, false) >> 8) & MapFlagsVerticalArch) != 0) {
rv = 1;
}
}
@ -414,20 +382,20 @@ void DrawAutomapText(const CelOutputBuffer &out)
// TODO: Use the `out` buffer instead of the global one.
char desc[256];
int nextline = 20;
int nextLine = 20;
if (gbIsMultiplayer) {
strcat(strcpy(desc, _("game: ")), szPlayerName);
PrintGameStr(out, 8, 20, desc, COL_GOLD);
nextline = 35;
nextLine = 35;
if (szPlayerDescript[0] != 0) {
strcat(strcpy(desc, _("password: ")), szPlayerDescript);
PrintGameStr(out, 8, 35, desc, COL_GOLD);
nextline = 50;
nextLine = 50;
}
}
if (setlevel) {
PrintGameStr(out, 8, nextline, _(quest_level_names[(BYTE)setlvlnum]), COL_GOLD);
PrintGameStr(out, 8, nextLine, _(quest_level_names[setlvlnum]), COL_GOLD);
} else if (currlevel != 0) {
if (currlevel < 17 || currlevel > 20) {
if (currlevel < 21 || currlevel > 24)
@ -437,17 +405,16 @@ void DrawAutomapText(const CelOutputBuffer &out)
} else {
sprintf(desc, _("Level: Nest %i"), currlevel - 16);
}
PrintGameStr(out, 8, nextline, desc, COL_GOLD);
PrintGameStr(out, 8, nextLine, desc, COL_GOLD);
}
}
} // namespace
bool automapflag;
bool automapview[DMAXX][DMAXY];
bool AutomapActive;
bool AutomapView[DMAXX][DMAXY];
int AutoMapScale;
int AutoMapXOfs;
int AutoMapYOfs;
Point AutomapOffset;
int AmLine64;
int AmLine32;
int AmLine16;
@ -456,7 +423,7 @@ int AmLine4;
void InitAutomapOnce()
{
automapflag = false;
AutomapActive = false;
AutoMapScale = 50;
AmLine64 = 32;
AmLine32 = 16;
@ -467,7 +434,7 @@ void InitAutomapOnce()
void InitAutomap()
{
DWORD dwTiles;
uint32_t dwTiles;
std::unique_ptr<BYTE[]> pAFile;
memset(AutomapTypes, 0, sizeof(AutomapTypes));
@ -505,7 +472,7 @@ void InitAutomap()
}
pAFile = nullptr;
memset(automapview, 0, sizeof(automapview));
memset(AutomapView, 0, sizeof(AutomapView));
for (auto &column : dFlags)
for (auto &dFlag : column)
@ -514,33 +481,32 @@ void InitAutomap()
void StartAutomap()
{
AutoMapXOfs = 0;
AutoMapYOfs = 0;
automapflag = true;
AutomapOffset = { 0, 0 };
AutomapActive = true;
}
void AutomapUp()
{
AutoMapXOfs--;
AutoMapYOfs--;
AutomapOffset.x--;
AutomapOffset.y--;
}
void AutomapDown()
{
AutoMapXOfs++;
AutoMapYOfs++;
AutomapOffset.x++;
AutomapOffset.y++;
}
void AutomapLeft()
{
AutoMapXOfs--;
AutoMapYOfs++;
AutomapOffset.x--;
AutomapOffset.y++;
}
void AutomapRight()
{
AutoMapXOfs++;
AutoMapYOfs--;
AutomapOffset.x++;
AutomapOffset.y--;
}
void AutomapZoomIn()
@ -569,93 +535,90 @@ void AutomapZoomOut()
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;
Automap = { (ViewX - 16) / 2, (ViewY - 16) / 2 };
while (Automap.x + AutomapOffset.x < 0)
AutomapOffset.x++;
while (Automap.x + AutomapOffset.x >= DMAXX)
AutomapOffset.x--;
while (Automap.y + AutomapOffset.y < 0)
AutomapOffset.y++;
while (Automap.y + AutomapOffset.y >= DMAXY)
AutomapOffset.y--;
AutoMapY = (ViewY - 16) / 2;
while (AutoMapY + AutoMapYOfs < 0)
AutoMapYOfs++;
while (AutoMapY + AutoMapYOfs >= DMAXY)
AutoMapYOfs--;
AutoMapY += AutoMapYOfs;
Automap += AutomapOffset;
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)
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;
Point screen {
gnScreenWidth / 2,
(gnScreenHeight - PANEL_HEIGHT) / 2
};
if ((cells & 1) != 0) {
sx = gnScreenWidth / 2 - AmLine64 * ((cells - 1) / 2);
sy = (gnScreenHeight - PANEL_HEIGHT) / 2 - AmLine32 * ((cells + 1) / 2);
screen.x -= AmLine64 * ((cells - 1) / 2);
screen.y -= AmLine32 * ((cells + 1) / 2);
} else {
sx = gnScreenWidth / 2 - AmLine64 * (cells / 2) + AmLine32;
sy = (gnScreenHeight - PANEL_HEIGHT) / 2 - AmLine32 * (cells / 2) - AmLine16;
screen.x -= AmLine64 * (cells / 2) - AmLine32;
screen.y -= AmLine32 * (cells / 2) + AmLine16;
}
if ((ViewX & 1) != 0) {
sx -= AmLine16;
sy -= AmLine8;
screen.x -= AmLine16;
screen.y -= AmLine8;
}
if ((ViewY & 1) != 0) {
sx += AmLine16;
sy -= AmLine8;
screen.x += AmLine16;
screen.y -= AmLine8;
}
sx += AutoMapScale * ScrollInfo.offset.x / 100 / 2;
sy += AutoMapScale * ScrollInfo.offset.y / 100 / 2;
screen.x += AutoMapScale * ScrollInfo.offset.x / 100 / 2;
screen.y += AutoMapScale * ScrollInfo.offset.y / 100 / 2;
if (PANELS_COVER) {
if (invflag || sbookflag) {
sx -= gnScreenWidth / 4;
screen.x -= gnScreenWidth / 4;
}
if (chrflag || questlog) {
sx += gnScreenWidth / 4;
screen.x += gnScreenWidth / 4;
}
}
for (int i = 0; i <= cells + 1; i++) {
int x = sx;
int y;
Point map = { Automap.x - cells, Automap.y - 1 };
for (int i = 0; i <= cells + 1; i++) {
Point tile1 = screen;
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;
uint16_t mapType = GetAutomapType({ map.x + j, map.y - j }, true);
if (mapType != 0)
DrawAutomapTile(out, tile1, mapType);
tile1.x += AmLine64;
}
mapy++;
x = sx - AmLine32;
y = sy + AmLine16;
map.y++;
Point tile2 { screen.x - AmLine32, screen.y + 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;
uint16_t mapType = GetAutomapType({ map.x + j, map.y - j }, true);
if (mapType != 0)
DrawAutomapTile(out, tile2, mapType);
tile2.x += AmLine64;
}
mapx++;
sy += AmLine32;
map.x++;
screen.y += 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);
for (int playerId = 0; playerId < MAX_PLRS; playerId++) {
if (plr[playerId].plrlevel == plr[myplr].plrlevel && plr[playerId].plractive && !plr[playerId]._pLvlChanging) {
DrawAutomapPlr(out, playerId);
}
}
if (AutoMapShowItems)
@ -663,70 +626,69 @@ void DrawAutomap(const CelOutputBuffer &out)
DrawAutomapText(out);
}
void SetAutomapView(int x, int y)
void SetAutomapView(Point tile)
{
int xx = (x - 16) / 2;
int yy = (y - 16) / 2;
Point map { (tile.x - 16) / 2, (tile.y - 16) / 2 };
if (xx < 0 || xx >= DMAXX || yy < 0 || yy >= DMAXY) {
if (map.x < 0 || map.x >= DMAXX || map.y < 0 || map.y >= DMAXY) {
return;
}
automapview[xx][yy] = true;
AutomapView[map.x][map.y] = true;
uint16_t maptype = GetAutomapType(xx, yy, false);
uint16_t solid = maptype & 0x4000;
uint16_t mapType = GetAutomapType(map, false);
uint16_t solid = mapType & 0x4000;
switch (maptype & MAPFLAG_TYPE) {
switch (mapType & MapFlagsType) {
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;
if (GetAutomapType({ map.x, map.y + 1 }, false) == 0x4007)
AutomapView[map.x][map.y + 1] = true;
} else if ((GetAutomapType({ map.x - 1, map.y }, false) & 0x4000) != 0) {
AutomapView[map.x - 1][map.y] = 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;
if (GetAutomapType({ map.x + 1, map.y }, false) == 0x4007)
AutomapView[map.x + 1][map.y] = true;
} else if ((GetAutomapType({ map.x, map.y - 1 }, false) & 0x4000) != 0) {
AutomapView[map.x][map.y - 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;
if (GetAutomapType({ map.x, map.y + 1 }, false) == 0x4007)
AutomapView[map.x][map.y + 1] = true;
if (GetAutomapType({ map.x + 1, map.y }, false) == 0x4007)
AutomapView[map.x + 1][map.y] = 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;
if ((GetAutomapType({ map.x - 1, map.y }, false) & 0x4000) != 0)
AutomapView[map.x - 1][map.y] = true;
if ((GetAutomapType({ map.x, map.y - 1 }, false) & 0x4000) != 0)
AutomapView[map.x][map.y - 1] = true;
if ((GetAutomapType({ map.x - 1, map.y - 1 }, false) & 0x4000) != 0)
AutomapView[map.x - 1][map.y - 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;
if ((GetAutomapType({ map.x, map.y - 1 }, false) & 0x4000) != 0)
AutomapView[map.x][map.y - 1] = true;
if (GetAutomapType({ map.x, map.y + 1 }, false) == 0x4007)
AutomapView[map.x][map.y + 1] = true;
} else if ((GetAutomapType({ map.x - 1, map.y }, false) & 0x4000) != 0) {
AutomapView[map.x - 1][map.y] = 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;
if ((GetAutomapType({ map.x - 1, map.y }, false) & 0x4000) != 0)
AutomapView[map.x - 1][map.y] = true;
if (GetAutomapType({ map.x + 1, map.y }, false) == 0x4007)
AutomapView[map.x + 1][map.y] = true;
} else if ((GetAutomapType({ map.x, map.y - 1 }, false) & 0x4000) != 0) {
AutomapView[map.x][map.y - 1] = true;
}
break;
}
@ -734,8 +696,7 @@ void SetAutomapView(int x, int y)
void AutomapZoomReset()
{
AutoMapXOfs = 0;
AutoMapYOfs = 0;
AutomapOffset = { 0, 0 };
AmLine64 = (AutoMapScale * 64) / 100;
AmLine32 = AmLine64 / 2;
AmLine16 = AmLine32 / 2;

9
Source/automap.h

@ -13,13 +13,12 @@
namespace devilution {
/** Specifies whether the automap is enabled. */
extern bool automapflag;
extern bool AutomapActive;
/** Tracks the explored areas of the map. */
extern bool automapview[DMAXX][DMAXY];
extern bool AutomapView[DMAXX][DMAXY];
/** Specifies the scale of the automap. */
extern int AutoMapScale;
extern int AutoMapXOfs;
extern int AutoMapYOfs;
extern Point AutomapOffset;
extern int AmLine64;
extern int AmLine32;
extern int AmLine16;
@ -79,7 +78,7 @@ void DrawAutomap(const CelOutputBuffer &out);
/**
* @brief Marks the given coordinate as within view on the automap.
*/
void SetAutomapView(int x, int y);
void SetAutomapView(Point tile);
/**
* @brief Resets the zoom level of the automap.

4
Source/control.cpp

@ -972,10 +972,10 @@ void control_check_btn_press()
void DoAutoMap()
{
if (currlevel != 0 || gbIsMultiplayer) {
if (!automapflag)
if (!AutomapActive)
StartAutomap();
else
automapflag = false;
AutomapActive = false;
} else {
InitDiabloMsg(EMSG_NO_AUTOMAP_IN_TOWN);
}

6
Source/controls/plrctrls.cpp

@ -982,7 +982,7 @@ void StoreSpellCoords()
bool IsAutomapActive()
{
return automapflag && leveltype != DTYPE_TOWN;
return AutomapActive && leveltype != DTYPE_TOWN;
}
bool IsMovingMouseCursorWithController()
@ -1002,8 +1002,8 @@ void HandleRightStickMotion()
if (IsAutomapActive()) { // move map
int dx = 0, dy = 0;
acc.Pool(&dx, &dy, 32);
AutoMapXOfs += dy + dx;
AutoMapYOfs += dy - dx;
AutomapOffset.x += dy + dx;
AutomapOffset.y += dy - dx;
return;
}

2
Source/debug.cpp

@ -146,7 +146,7 @@ void PrintDebugPlayer(bool bNextPlayer)
NetSendCmdString(1 << myplr, dstr);
sprintf(dstr, " Lvl = %i : Change = %i", plr[dbgplr].plrlevel, plr[dbgplr]._pLvlChanging);
NetSendCmdString(1 << myplr, dstr);
const Point target = plr[dbgplr].GetTargetPosition();
Point target = plr[dbgplr].GetTargetPosition();
sprintf(dstr, " x = %i, y = %i : tx = %i, ty = %i", plr[dbgplr].position.tile.x, plr[dbgplr].position.tile.y, target.x, target.y);
NetSendCmdString(1 << myplr, dstr);
sprintf(dstr, " mode = %i : daction = %i : walk[0] = %i", plr[dbgplr]._pmode, plr[dbgplr].destAction, plr[dbgplr].walkpath[0]);

16
Source/diablo.cpp

@ -1184,7 +1184,7 @@ static void PressKey(int vkey)
stream_stop();
}
questlog = false;
automapflag = false;
AutomapActive = false;
msgdelay = 0;
gamemenu_off();
DisplayHelp();
@ -1258,7 +1258,7 @@ static void PressKey(int vkey)
QuestlogUp();
} else if (helpflag) {
HelpScrollUp();
} else if (automapflag) {
} else if (AutomapActive) {
AutomapUp();
}
} else if (vkey == DVL_VK_DOWN) {
@ -1268,7 +1268,7 @@ static void PressKey(int vkey)
QuestlogDown();
} else if (helpflag) {
HelpScrollDown();
} else if (automapflag) {
} else if (AutomapActive) {
AutomapDown();
}
} else if (vkey == DVL_VK_PRIOR) {
@ -1280,11 +1280,11 @@ static void PressKey(int vkey)
STextNext();
}
} else if (vkey == DVL_VK_LEFT) {
if (automapflag && !talkflag) {
if (AutomapActive && !talkflag) {
AutomapLeft();
}
} else if (vkey == DVL_VK_RIGHT) {
if (automapflag && !talkflag) {
if (AutomapActive && !talkflag) {
AutomapRight();
}
} else if (vkey == DVL_VK_TAB) {
@ -1297,7 +1297,7 @@ static void PressKey(int vkey)
qtextflag = false;
stream_stop();
}
automapflag = false;
AutomapActive = false;
msgdelay = 0;
gamemenu_off();
doom_close();
@ -1435,13 +1435,13 @@ static void PressChar(int32_t vkey)
return;
case '+':
case '=':
if (automapflag) {
if (AutomapActive) {
AutomapZoomIn();
}
return;
case '-':
case '_':
if (automapflag) {
if (AutomapActive) {
AutomapZoomOut();
}
return;

21
Source/engine.cpp

@ -75,7 +75,8 @@ constexpr std::uint8_t GetCelTransparentWidth(std::uint8_t control)
constexpr std::uint8_t MaxCl2Width = 65;
BYTE *GetLightTable(char light) {
BYTE *GetLightTable(char light)
{
int idx = light4flag ? 1024 : 4096;
if (light == 2)
idx += 256; // gray colors
@ -548,26 +549,26 @@ void CelBlitOutlineTo(const CelOutputBuffer &out, BYTE col, int sx, int sy, cons
}
}
void SetPixel(const CelOutputBuffer &out, int sx, int sy, BYTE col)
void SetPixel(const CelOutputBuffer &out, Point position, BYTE col)
{
if (!out.in_bounds(sx, sy))
if (!out.in_bounds(position))
return;
*out.at(sx, sy) = col;
*out.at(position.x, position.y) = col;
}
void DrawLineTo(const CelOutputBuffer &out, int x0, int y0, int x1, int y1, BYTE color_index)
void DrawLineTo(const CelOutputBuffer &out, Point a, Point b, BYTE color_index)
{
int dx = x1 - x0;
int dy = y1 - y0;
int dx = b.x - a.x;
int dy = b.y - a.y;
int steps = abs(dx) > abs(dy) ? abs(dx) : abs(dy);
float ix = dx / (float)steps;
float iy = dy / (float)steps;
float sx = x0;
float sy = y0;
float sx = a.x;
float sy = a.y;
for (int i = 0; i <= steps; i++, sx += ix, sy += iy) {
SetPixel(out, sx, sy, color_index);
SetPixel(out, { static_cast<int>(sx), static_cast<int>(sy) }, color_index);
}
}

17
Source/engine.h

@ -255,9 +255,9 @@ struct CelOutputBuffer {
return surface->pitch;
}
bool in_bounds(Sint16 x, Sint16 y) const
bool in_bounds(Point position) const
{
return x >= 0 && y >= 0 && x < region.w && y < region.h;
return position.x >= 0 && position.y >= 0 && position.x < region.w && position.y < region.h;
}
/**
@ -489,11 +489,10 @@ void CelBlitOutlineTo(const CelOutputBuffer &out, BYTE col, int sx, int sy, cons
/**
* @brief Set the value of a single pixel in the back buffer, checks bounds
* @param out Target buffer
* @param sx Target buffer coordinate
* @param sy Target buffer coordinate
* @param point Target buffer coordinate
* @param col Color index from current palette
*/
void SetPixel(const CelOutputBuffer &out, int sx, int sy, BYTE col);
void SetPixel(const CelOutputBuffer &out, Point position, BYTE col);
/**
* @brief Blit CL2 sprite, to the back buffer at the given coordianates
@ -540,13 +539,11 @@ void Cl2DrawLight(const CelOutputBuffer &out, int sx, int sy, const CelSprite &c
/**
* @brief Draw a line in the target buffer
* @param out Target buffer
* @param x0 Back buffer coordinate
* @param y0 Back buffer coordinate
* @param x1 Back buffer coordinate
* @param y1 Back buffer coordinate
* @param a Back buffer coordinate
* @param b Back buffer coordinate
* @param color_index Color index from current palette
*/
void DrawLineTo(const CelOutputBuffer &out, int x0, int y0, int x1, int y1, BYTE color_index);
void DrawLineTo(const CelOutputBuffer &out, Point a, Point b, BYTE color_index);
/**
* Draws a half-transparent rectangle by blacking out odd pixels on odd lines,

4
Source/lighting.cpp

@ -682,7 +682,7 @@ void DoVision(int nXPos, int nYPos, int nRadius, bool doautomap, bool visible)
if (nXPos >= 0 && nXPos <= MAXDUNX && nYPos >= 0 && nYPos <= MAXDUNY) {
if (doautomap) {
if (dFlags[nXPos][nYPos] >= 0) {
SetAutomapView(nXPos, nYPos);
SetAutomapView({ nXPos, nYPos });
}
dFlags[nXPos][nYPos] |= BFLAG_EXPLORED;
}
@ -743,7 +743,7 @@ void DoVision(int nXPos, int nYPos, int nRadius, bool doautomap, bool visible)
&& !nBlockTable[dPiece[x2adj + nCrawlX][y2adj + nCrawlY]])) {
if (doautomap) {
if (dFlags[nCrawlX][nCrawlY] >= 0) {
SetAutomapView(nCrawlX, nCrawlY);
SetAutomapView({ nCrawlX, nCrawlY });
}
dFlags[nCrawlX][nCrawlY] |= BFLAG_EXPLORED;
}

14
Source/loadsave.cpp

@ -1144,7 +1144,7 @@ void LoadGame(bool firstflag)
}
for (int j = 0; j < DMAXY; j++) {
for (int i = 0; i < DMAXX; i++)
automapview[i][j] = file.nextBool8();
AutomapView[i][j] = file.nextBool8();
}
for (int j = 0; j < MAXDUNY; j++) {
for (int i = 0; i < MAXDUNX; i++)
@ -1160,7 +1160,7 @@ void LoadGame(bool firstflag)
if (gbIsHellfire && !gbIsHellfireSaveGame)
SpawnPremium(myplr);
automapflag = file.nextBool8();
AutomapActive = file.nextBool8();
AutoMapScale = file.nextBE<int32_t>();
AutomapZoomReset();
ResyncQuests();
@ -1302,7 +1302,7 @@ static void SavePlayer(SaveHelper *file, int p)
file->writeLE<int32_t>(pPlayer->position.future.y);
// For backwards compatibility
const Point target = pPlayer->GetTargetPosition();
Point target = pPlayer->GetTargetPosition();
file->writeLE<int32_t>(target.x);
file->writeLE<int32_t>(target.y);
@ -1903,7 +1903,7 @@ void SaveGameData()
}
for (int j = 0; j < DMAXY; j++) {
for (int i = 0; i < DMAXX; i++)
file.writeLE<uint8_t>(automapview[i][j]);
file.writeLE<uint8_t>(AutomapView[i][j]);
}
for (int j = 0; j < MAXDUNY; j++) {
for (int i = 0; i < MAXDUNX; i++)
@ -1917,7 +1917,7 @@ void SaveGameData()
for (int i = 0; i < giNumberOfSmithPremiumItems; i++)
SavePremium(&file, i);
file.writeLE<uint8_t>(automapflag);
file.writeLE<uint8_t>(AutomapActive);
file.writeBE<int32_t>(AutoMapScale);
}
@ -2000,7 +2000,7 @@ void SaveLevel()
}
for (int j = 0; j < DMAXY; j++) {
for (int i = 0; i < DMAXX; i++)
file.writeLE<uint8_t>(automapview[i][j]);
file.writeLE<uint8_t>(AutomapView[i][j]);
}
for (int j = 0; j < MAXDUNY; j++) {
for (int i = 0; i < MAXDUNX; i++)
@ -2086,7 +2086,7 @@ void LoadLevel()
}
for (int j = 0; j < DMAXY; j++) {
for (int i = 0; i < DMAXX; i++)
automapview[i][j] = file.nextBool8();
AutomapView[i][j] = file.nextBool8();
}
for (int j = 0; j < MAXDUNY; j++) {
for (int i = 0; i < MAXDUNX; i++)

4
Source/msg.cpp

@ -519,7 +519,7 @@ void delta_leave_sync(BYTE bLevel)
pD->_mhitpoints = monster[ma]._mhitpoints;
pD->_mactive = monster[ma]._msquelch;
}
memcpy(&sgLocals[bLevel].automapsv, automapview, sizeof(automapview));
memcpy(&sgLocals[bLevel].automapsv, AutomapView, sizeof(AutomapView));
}
static void delta_sync_object(int oi, _cmd_id bCmd, BYTE bLevel)
@ -742,7 +742,7 @@ void DeltaLoadLevel()
}
}
}
memcpy(automapview, &sgLocals[currlevel], sizeof(automapview));
memcpy(AutomapView, &sgLocals[currlevel], sizeof(AutomapView));
}
for (i = 0; i < MAXITEMS; i++) {

2
Source/multi.cpp

@ -117,7 +117,7 @@ static BYTE *multi_recv_packet(TBuffer *pBuf, BYTE *body, DWORD *size)
static void NetRecvPlrData(TPkt *pkt)
{
const Point target = plr[myplr].GetTargetPosition();
Point target = plr[myplr].GetTargetPosition();
pkt->hdr.wCheck = LoadBE32("\0\0ip");
pkt->hdr.px = plr[myplr].position.tile.x;

2
Source/objects.cpp

@ -4030,7 +4030,7 @@ bool OperateShrineSecluded(int pnum)
if (pnum != myplr)
return true;
std::fill(&automapview[0][0], &automapview[DMAXX - 1][DMAXX - 1], true);
std::fill(&AutomapView[0][0], &AutomapView[DMAXX - 1][DMAXX - 1], true);
InitDiabloMsg(EMSG_SHRINE_SECLUDED);

10
Source/qol/xpbar.cpp

@ -34,11 +34,11 @@ void DrawBar(const CelOutputBuffer &out, int x, int y, int width, const ColorGra
FastDrawHorizLine(out, x, y + 3, width, gradient[gradient.size() / 2 - 1]);
}
void DrawEndCap(const CelOutputBuffer &out, int x, int y, int idx, const ColorGradient &gradient)
void DrawEndCap(const CelOutputBuffer &out, Point point, int idx, const ColorGradient &gradient)
{
SetPixel(out, x, y + 1, gradient[idx * 3 / 4]);
SetPixel(out, x, y + 2, gradient[idx]);
SetPixel(out, x, y + 3, gradient[idx / 2]);
SetPixel(out, { point.x, point.y + 1 }, gradient[idx * 3 / 4]);
SetPixel(out, { point.x, point.y + 2 }, gradient[idx]);
SetPixel(out, { point.x, point.y + 3 }, gradient[idx / 2]);
}
} // namespace
@ -101,7 +101,7 @@ void DrawXPBar(const CelOutputBuffer &out)
DrawBar(out, xPos, yPos, fullBar, SILVER_GRADIENT);
// End pixels appear gradually
DrawEndCap(out, xPos + fullBar, yPos, fade, SILVER_GRADIENT);
DrawEndCap(out, { xPos + static_cast<int>(fullBar), yPos }, fade, SILVER_GRADIENT);
}
bool CheckXPBarInfo()

2
Source/scrollrt.cpp

@ -1244,7 +1244,7 @@ extern void DrawControllerModifierHints(const CelOutputBuffer &out);
void DrawView(const CelOutputBuffer &out, int StartX, int StartY)
{
DrawGame(out, StartX, StartY);
if (automapflag) {
if (AutomapActive) {
DrawAutomap(out.subregionY(0, gnViewportHeight));
}
DrawMonsterHealthBar(out);

2
Source/track.cpp

@ -29,7 +29,7 @@ void track_process()
if (plr[myplr].actionFrame <= 6 && plr[myplr]._pmode != PM_STAND)
return;
const Point target = plr[myplr].GetTargetPosition();
Point target = plr[myplr].GetTargetPosition();
if (cursmx != target.x || cursmy != target.y) {
Uint32 tick = SDL_GetTicks();
if ((int)(tick - sgdwLastWalk) >= gnTickDelay * 6) {

48
test/automap_test.cpp

@ -7,7 +7,7 @@ using namespace devilution;
TEST(Automap, InitAutomap)
{
InitAutomapOnce();
EXPECT_EQ(automapflag, false);
EXPECT_EQ(AutomapActive, false);
EXPECT_EQ(AutoMapScale, 50);
EXPECT_EQ(AmLine64, 32);
EXPECT_EQ(AmLine32, 16);
@ -19,45 +19,45 @@ TEST(Automap, InitAutomap)
TEST(Automap, StartAutomap)
{
StartAutomap();
EXPECT_EQ(AutoMapXOfs, 0);
EXPECT_EQ(AutoMapYOfs, 0);
EXPECT_EQ(automapflag, true);
EXPECT_EQ(AutomapOffset.x, 0);
EXPECT_EQ(AutomapOffset.y, 0);
EXPECT_EQ(AutomapActive, true);
}
TEST(Automap, AutomapUp)
{
AutoMapXOfs = 1;
AutoMapYOfs = 1;
AutomapOffset.x = 1;
AutomapOffset.y = 1;
AutomapUp();
EXPECT_EQ(AutoMapXOfs, 0);
EXPECT_EQ(AutoMapYOfs, 0);
EXPECT_EQ(AutomapOffset.x, 0);
EXPECT_EQ(AutomapOffset.y, 0);
}
TEST(Automap, AutomapDown)
{
AutoMapXOfs = 1;
AutoMapYOfs = 1;
AutomapOffset.x = 1;
AutomapOffset.y = 1;
AutomapDown();
EXPECT_EQ(AutoMapXOfs, 2);
EXPECT_EQ(AutoMapYOfs, 2);
EXPECT_EQ(AutomapOffset.x, 2);
EXPECT_EQ(AutomapOffset.y, 2);
}
TEST(Automap, AutomapLeft)
{
AutoMapXOfs = 1;
AutoMapYOfs = 1;
AutomapOffset.x = 1;
AutomapOffset.y = 1;
AutomapLeft();
EXPECT_EQ(AutoMapXOfs, 0);
EXPECT_EQ(AutoMapYOfs, 2);
EXPECT_EQ(AutomapOffset.x, 0);
EXPECT_EQ(AutomapOffset.y, 2);
}
TEST(Automap, AutomapRight)
{
AutoMapXOfs = 1;
AutoMapYOfs = 1;
AutomapOffset.x = 1;
AutomapOffset.y = 1;
AutomapRight();
EXPECT_EQ(AutoMapXOfs, 2);
EXPECT_EQ(AutoMapYOfs, 0);
EXPECT_EQ(AutomapOffset.x, 2);
EXPECT_EQ(AutomapOffset.y, 0);
}
TEST(Automap, AutomapZoomIn)
@ -113,11 +113,11 @@ TEST(Automap, AutomapZoomOut_Min)
TEST(Automap, AutomapZoomReset)
{
AutoMapScale = 50;
AutoMapXOfs = 1;
AutoMapYOfs = 1;
AutomapOffset.x = 1;
AutomapOffset.y = 1;
AutomapZoomReset();
EXPECT_EQ(AutoMapXOfs, 0);
EXPECT_EQ(AutoMapYOfs, 0);
EXPECT_EQ(AutomapOffset.x, 0);
EXPECT_EQ(AutomapOffset.y, 0);
EXPECT_EQ(AutoMapScale, 50);
EXPECT_EQ(AmLine64, 32);
EXPECT_EQ(AmLine32, 16);

Loading…
Cancel
Save