Browse Source

Sharing automap exploration in multiplayer

pull/3247/head
qndel 5 years ago committed by Anders Jenbo
parent
commit
e567953bc9
  1. 318
      Source/automap.cpp
  2. 22
      Source/automap.h
  3. 19
      Source/debug.cpp
  4. 13
      Source/lighting.cpp
  5. 3
      Source/lighting.h
  6. 12
      Source/loadsave.cpp
  7. 4
      Source/monster.cpp
  8. 4
      Source/objects.cpp

318
Source/automap.cpp

@ -96,47 +96,47 @@ void DrawDiamond(const Surface &out, Point center, uint8_t color)
DrawMapLineNE(out, bottom, AmLine8, color); DrawMapLineNE(out, bottom, AmLine8, color);
} }
void DrawMapVerticalDoor(const Surface &out, Point center) void DrawMapVerticalDoor(const Surface &out, Point center, uint8_t colorBright, uint8_t colorDim)
{ {
DrawMapLineNE(out, { center.x + AmLine8, center.y - AmLine4 }, AmLine4, MapColorsDim); DrawMapLineNE(out, { center.x + AmLine8, center.y - AmLine4 }, AmLine4, colorDim);
DrawMapLineNE(out, { center.x - AmLine16, center.y + AmLine8 }, AmLine4, MapColorsDim); DrawMapLineNE(out, { center.x - AmLine16, center.y + AmLine8 }, AmLine4, colorDim);
DrawDiamond(out, center, MapColorsBright); DrawDiamond(out, center, colorBright);
} }
void DrawMapHorizontalDoor(const Surface &out, Point center) void DrawMapHorizontalDoor(const Surface &out, Point center, uint8_t colorBright, uint8_t colorDim)
{ {
DrawMapLineSE(out, { center.x - AmLine16, center.y - AmLine8 }, AmLine4, MapColorsDim); DrawMapLineSE(out, { center.x - AmLine16, center.y - AmLine8 }, AmLine4, colorDim);
DrawMapLineSE(out, { center.x + AmLine8, center.y + AmLine4 }, AmLine4, MapColorsDim); DrawMapLineSE(out, { center.x + AmLine8, center.y + AmLine4 }, AmLine4, colorDim);
DrawDiamond(out, center, MapColorsBright); DrawDiamond(out, center, colorBright);
} }
void DrawDirt(const Surface &out, Point center) void DrawDirt(const Surface &out, Point center, uint8_t color)
{ {
out.SetPixel(center, MapColorsDim); out.SetPixel(center, color);
out.SetPixel({ center.x - AmLine8, center.y - AmLine4 }, MapColorsDim); out.SetPixel({ center.x - AmLine8, center.y - AmLine4 }, color);
out.SetPixel({ center.x - AmLine8, center.y + AmLine4 }, MapColorsDim); out.SetPixel({ center.x - AmLine8, center.y + AmLine4 }, color);
out.SetPixel({ center.x + AmLine8, center.y - AmLine4 }, MapColorsDim); out.SetPixel({ center.x + AmLine8, center.y - AmLine4 }, color);
out.SetPixel({ center.x + AmLine8, center.y + AmLine4 }, MapColorsDim); out.SetPixel({ center.x + AmLine8, center.y + AmLine4 }, color);
out.SetPixel({ center.x - AmLine16, center.y }, MapColorsDim); out.SetPixel({ center.x - AmLine16, center.y }, color);
out.SetPixel({ center.x + AmLine16, center.y }, MapColorsDim); out.SetPixel({ center.x + AmLine16, center.y }, color);
out.SetPixel({ center.x, center.y - AmLine8 }, MapColorsDim); out.SetPixel({ center.x, center.y - AmLine8 }, color);
out.SetPixel({ center.x, center.y + AmLine8 }, MapColorsDim); out.SetPixel({ center.x, center.y + AmLine8 }, color);
out.SetPixel({ center.x + AmLine8 - AmLine32, center.y + AmLine4 }, MapColorsDim); out.SetPixel({ center.x + AmLine8 - AmLine32, center.y + AmLine4 }, color);
out.SetPixel({ center.x - AmLine8 + AmLine32, center.y + AmLine4 }, MapColorsDim); out.SetPixel({ center.x - AmLine8 + AmLine32, center.y + AmLine4 }, color);
out.SetPixel({ center.x - AmLine16, center.y + AmLine8 }, MapColorsDim); out.SetPixel({ center.x - AmLine16, center.y + AmLine8 }, color);
out.SetPixel({ center.x + AmLine16, center.y + AmLine8 }, MapColorsDim); out.SetPixel({ center.x + AmLine16, center.y + AmLine8 }, color);
out.SetPixel({ center.x - AmLine8, center.y + AmLine16 - AmLine4 }, MapColorsDim); out.SetPixel({ center.x - AmLine8, center.y + AmLine16 - AmLine4 }, color);
out.SetPixel({ center.x + AmLine8, center.y + AmLine16 - AmLine4 }, MapColorsDim); out.SetPixel({ center.x + AmLine8, center.y + AmLine16 - AmLine4 }, color);
out.SetPixel({ center.x, center.y + AmLine16 }, MapColorsDim); out.SetPixel({ center.x, center.y + AmLine16 }, color);
} }
void DrawStairs(const Surface &out, Point center) void DrawStairs(const Surface &out, Point center, uint8_t color)
{ {
constexpr int NumStairSteps = 4; constexpr int NumStairSteps = 4;
const Displacement offset = { -AmLine8, AmLine4 }; const Displacement offset = { -AmLine8, AmLine4 };
Point p = { center.x - AmLine8, center.y - AmLine8 - AmLine4 }; Point p = { center.x - AmLine8, center.y - AmLine8 - AmLine4 };
for (int i = 0; i < NumStairSteps; ++i) { for (int i = 0; i < NumStairSteps; ++i) {
DrawMapLineSE(out, p, AmLine16, MapColorsBright); DrawMapLineSE(out, p, AmLine16, color);
p += offset; p += offset;
} }
} }
@ -144,113 +144,198 @@ void DrawStairs(const Surface &out, Point center)
/** /**
* Left-facing obstacle * Left-facing obstacle
*/ */
void DrawHorizontal(const Surface &out, Point center, AutomapTile tile) void DrawHorizontal(const Surface &out, Point center, AutomapTile tile, uint8_t colorBright, uint8_t colorDim)
{ {
if (!tile.HasFlag(AutomapTile::Flags::HorizontalPassage)) { if (!tile.HasFlag(AutomapTile::Flags::HorizontalPassage)) {
DrawMapLineSE(out, { center.x, center.y - AmLine16 }, AmLine16, MapColorsDim); DrawMapLineSE(out, { center.x, center.y - AmLine16 }, AmLine16, colorDim);
return; return;
} }
if (tile.HasFlag(AutomapTile::Flags::HorizontalDoor)) { if (tile.HasFlag(AutomapTile::Flags::HorizontalDoor)) {
DrawMapHorizontalDoor(out, { center.x + AmLine16, center.y - AmLine8 }); DrawMapHorizontalDoor(out, { center.x + AmLine16, center.y - AmLine8 }, colorBright, colorDim);
} }
if (tile.HasFlag(AutomapTile::Flags::HorizontalGrate)) { if (tile.HasFlag(AutomapTile::Flags::HorizontalGrate)) {
DrawMapLineSE(out, { center.x + AmLine16, center.y - AmLine8 }, AmLine8, MapColorsDim); DrawMapLineSE(out, { center.x + AmLine16, center.y - AmLine8 }, AmLine8, colorDim);
DrawDiamond(out, { center.x, center.y - AmLine8 }, MapColorsDim); DrawDiamond(out, { center.x, center.y - AmLine8 }, colorDim);
} else if (tile.HasFlag(AutomapTile::Flags::HorizontalArch)) { } else if (tile.HasFlag(AutomapTile::Flags::HorizontalArch)) {
DrawDiamond(out, { center.x, center.y - AmLine8 }, MapColorsDim); DrawDiamond(out, { center.x, center.y - AmLine8 }, colorDim);
} }
} }
/** /**
* Right-facing obstacle * Right-facing obstacle
*/ */
void DrawVertical(const Surface &out, Point center, AutomapTile tile) void DrawVertical(const Surface &out, Point center, AutomapTile tile, uint8_t colorBright, uint8_t colorDim)
{ {
if (!tile.HasFlag(AutomapTile::Flags::VerticalPassage)) { if (!tile.HasFlag(AutomapTile::Flags::VerticalPassage)) {
DrawMapLineNE(out, { center.x - AmLine32, center.y }, AmLine16, MapColorsDim); DrawMapLineNE(out, { center.x - AmLine32, center.y }, AmLine16, colorDim);
return; return;
} }
if (tile.HasFlag(AutomapTile::Flags::VerticalDoor)) { // two wall segments with a door in the middle if (tile.HasFlag(AutomapTile::Flags::VerticalDoor)) { // two wall segments with a door in the middle
DrawMapVerticalDoor(out, { center.x - AmLine16, center.y - AmLine8 }); DrawMapVerticalDoor(out, { center.x - AmLine16, center.y - AmLine8 }, colorBright, colorDim);
} }
if (tile.HasFlag(AutomapTile::Flags::VerticalGrate)) { // right-facing half-wall if (tile.HasFlag(AutomapTile::Flags::VerticalGrate)) { // right-facing half-wall
DrawMapLineNE(out, { center.x - AmLine32, center.y }, AmLine8, MapColorsDim); DrawMapLineNE(out, { center.x - AmLine32, center.y }, AmLine8, colorDim);
DrawDiamond(out, { center.x, center.y - AmLine8 }, MapColorsDim); DrawDiamond(out, { center.x, center.y - AmLine8 }, colorDim);
} else if (tile.HasFlag(AutomapTile::Flags::VerticalArch)) { // window or passable column } else if (tile.HasFlag(AutomapTile::Flags::VerticalArch)) { // window or passable column
DrawDiamond(out, { center.x, center.y - AmLine8 }, MapColorsDim); DrawDiamond(out, { center.x, center.y - AmLine8 }, colorDim);
} }
} }
/** /**
* For caves the horizontal/vertical flags are swapped * For caves the horizontal/vertical flags are swapped
*/ */
void DrawCaveHorizontal(const Surface &out, Point center, AutomapTile tile) void DrawCaveHorizontal(const Surface &out, Point center, AutomapTile tile, uint8_t colorBright, uint8_t colorDim)
{ {
if (tile.HasFlag(AutomapTile::Flags::VerticalDoor)) { if (tile.HasFlag(AutomapTile::Flags::VerticalDoor)) {
DrawMapHorizontalDoor(out, { center.x - AmLine16, center.y + AmLine8 }); DrawMapHorizontalDoor(out, { center.x - AmLine16, center.y + AmLine8 }, colorBright, colorDim);
} else { } else {
DrawMapLineSE(out, { center.x - AmLine32, center.y }, AmLine16, MapColorsDim); DrawMapLineSE(out, { center.x - AmLine32, center.y }, AmLine16, colorDim);
} }
} }
/** /**
* For caves the horizontal/vertical flags are swapped * For caves the horizontal/vertical flags are swapped
*/ */
void DrawCaveVertical(const Surface &out, Point center, AutomapTile tile) void DrawCaveVertical(const Surface &out, Point center, AutomapTile tile, uint8_t colorBright, uint8_t colorDim)
{ {
if (tile.HasFlag(AutomapTile::Flags::HorizontalDoor)) { if (tile.HasFlag(AutomapTile::Flags::HorizontalDoor)) {
DrawMapVerticalDoor(out, { center.x + AmLine16, center.y + AmLine8 }); DrawMapVerticalDoor(out, { center.x + AmLine16, center.y + AmLine8 }, colorBright, colorDim);
} else { } else {
DrawMapLineNE(out, { center.x, center.y + AmLine16 }, AmLine16, MapColorsDim); DrawMapLineNE(out, { center.x, center.y + AmLine16 }, AmLine16, colorDim);
} }
} }
/**
* @brief Check if a given tile has the provided AutomapTile flag
*/
bool HasAutomapFlag(Point position, AutomapTile::Flags type)
{
if (position.x < 0 || position.x >= DMAXX || position.y < 0 || position.y >= DMAXX) {
return false;
}
return AutomapTypeTiles[dungeon[position.x][position.y]].HasFlag(type);
}
/**
* @brief Returns the automap shape at the given coordinate.
*/
AutomapTile GetAutomapType(Point position)
{
if (position.x < 0 || position.x >= DMAXX || position.y < 0 || position.y >= DMAXX) {
return {};
}
AutomapTile tile = AutomapTypeTiles[dungeon[position.x][position.y]];
if (tile.type == AutomapTile::Types::Corner) {
if (HasAutomapFlag({ position.x - 1, position.y }, AutomapTile::Flags::HorizontalArch)) {
if (HasAutomapFlag({ position.x, position.y - 1 }, AutomapTile::Flags::VerticalArch)) {
tile.type = AutomapTile::Types::Diamond;
}
}
}
return tile;
}
/**
* @brief Returns the automap shape at the given coordinate.
*/
AutomapTile GetAutomapTypeView(Point map)
{
if (map.x == -1 && map.y >= 0 && map.y < DMAXY && AutomapView[0][map.y] != MAP_EXP_NONE) {
if (HasAutomapFlag({ 0, map.y + 1 }, AutomapTile::Flags::Dirt) && HasAutomapFlag({ 0, map.y }, AutomapTile::Flags::Dirt) && HasAutomapFlag({ 0, map.y - 1 }, AutomapTile::Flags::Dirt)) {
return {};
}
return { AutomapTile::Types::None, AutomapTile::Flags::Dirt };
}
if (map.y == -1 && map.x >= 0 && map.x < DMAXY && AutomapView[map.x][0] != MAP_EXP_NONE) {
if (HasAutomapFlag({ map.x + 1, 0 }, AutomapTile::Flags::Dirt) && HasAutomapFlag({ map.x, 0 }, AutomapTile::Flags::Dirt) && HasAutomapFlag({ map.x - 1, 0 }, AutomapTile::Flags::Dirt)) {
return {};
}
return { AutomapTile::Types::None, AutomapTile::Flags::Dirt };
}
if (map.x < 0 || map.x >= DMAXX) {
return {};
}
if (map.y < 0 || map.y >= DMAXX) {
return {};
}
if (AutomapView[map.x][map.y] == MAP_EXP_NONE) {
return {};
}
return GetAutomapType(map);
}
/** /**
* @brief Renders the given automap shape at the specified screen coordinates. * @brief Renders the given automap shape at the specified screen coordinates.
*/ */
void DrawAutomapTile(const Surface &out, Point center, AutomapTile tile) void DrawAutomapTile(const Surface &out, Point center, Point map)
{ {
AutomapTile tile = GetAutomapTypeView(map);
uint8_t colorBright = MapColorsBright;
uint8_t colorDim = MapColorsDim;
MapExplorationType explorationType = static_cast<MapExplorationType>(AutomapView[map.x][map.y]);
switch (explorationType) {
case MAP_EXP_SHRINE:
colorDim = PAL16_GRAY + 11;
colorBright = PAL16_GRAY + 9;
break;
case MAP_EXP_OTHERS:
colorDim = PAL16_YELLOW + 11;
colorBright = PAL16_YELLOW + 9;
break;
case MAP_EXP_SELF:
case MAP_EXP_NONE:
case MAP_EXP_OLD:
break;
}
if (tile.HasFlag(AutomapTile::Flags::Dirt)) { if (tile.HasFlag(AutomapTile::Flags::Dirt)) {
DrawDirt(out, center); DrawDirt(out, center, colorDim);
} }
if (tile.HasFlag(AutomapTile::Flags::Stairs)) { if (tile.HasFlag(AutomapTile::Flags::Stairs)) {
DrawStairs(out, center); DrawStairs(out, center, colorBright);
} }
switch (tile.type) { switch (tile.type) {
case AutomapTile::Types::Diamond: // stand-alone column or other unpassable object case AutomapTile::Types::Diamond: // stand-alone column or other unpassable object
DrawDiamond(out, { center.x, center.y - AmLine8 }, MapColorsDim); DrawDiamond(out, { center.x, center.y - AmLine8 }, colorDim);
break; break;
case AutomapTile::Types::Vertical: case AutomapTile::Types::Vertical:
case AutomapTile::Types::FenceVertical: case AutomapTile::Types::FenceVertical:
DrawVertical(out, center, tile); DrawVertical(out, center, tile, colorBright, colorDim);
break; break;
case AutomapTile::Types::Horizontal: case AutomapTile::Types::Horizontal:
case AutomapTile::Types::FenceHorizontal: case AutomapTile::Types::FenceHorizontal:
DrawHorizontal(out, center, tile); DrawHorizontal(out, center, tile, colorBright, colorDim);
break; break;
case AutomapTile::Types::Cross: case AutomapTile::Types::Cross:
DrawVertical(out, center, tile); DrawVertical(out, center, tile, colorBright, colorDim);
DrawHorizontal(out, center, tile); DrawHorizontal(out, center, tile, colorBright, colorDim);
break; break;
case AutomapTile::Types::CaveHorizontalCross: case AutomapTile::Types::CaveHorizontalCross:
DrawVertical(out, center, tile); DrawVertical(out, center, tile, colorBright, colorDim);
DrawCaveHorizontal(out, center, tile); DrawCaveHorizontal(out, center, tile, colorBright, colorDim);
break; break;
case AutomapTile::Types::CaveVerticalCross: case AutomapTile::Types::CaveVerticalCross:
DrawHorizontal(out, center, tile); DrawHorizontal(out, center, tile, colorBright, colorDim);
DrawCaveVertical(out, center, tile); DrawCaveVertical(out, center, tile, colorBright, colorDim);
break; break;
case AutomapTile::Types::CaveHorizontal: case AutomapTile::Types::CaveHorizontal:
DrawCaveHorizontal(out, center, tile); DrawCaveHorizontal(out, center, tile, colorBright, colorDim);
break; break;
case AutomapTile::Types::CaveVertical: case AutomapTile::Types::CaveVertical:
DrawCaveVertical(out, center, tile); DrawCaveVertical(out, center, tile, colorBright, colorDim);
break; break;
case AutomapTile::Types::CaveCross: case AutomapTile::Types::CaveCross:
DrawCaveHorizontal(out, center, tile); DrawCaveHorizontal(out, center, tile, colorBright, colorDim);
DrawCaveVertical(out, center, tile); DrawCaveVertical(out, center, tile, colorBright, colorDim);
break; break;
case AutomapTile::Types::Corner: case AutomapTile::Types::Corner:
case AutomapTile::Types::None: case AutomapTile::Types::None:
@ -386,71 +471,6 @@ void DrawAutomapPlr(const Surface &out, const Displacement &myPlayerOffset, int
} }
} }
/**
* @brief Check if a given tile has the provided AutomapTile flag
*/
bool HasAutomapFlag(Point position, AutomapTile::Flags type)
{
if (position.x < 0 || position.x >= DMAXX || position.y < 0 || position.y >= DMAXX) {
return false;
}
return AutomapTypeTiles[dungeon[position.x][position.y]].HasFlag(type);
}
/**
* @brief Returns the automap shape at the given coordinate.
*/
AutomapTile GetAutomapType(Point position)
{
if (position.x < 0 || position.x >= DMAXX || position.y < 0 || position.y >= DMAXX) {
return {};
}
AutomapTile tile = AutomapTypeTiles[dungeon[position.x][position.y]];
if (tile.type == AutomapTile::Types::Corner) {
if (HasAutomapFlag({ position.x - 1, position.y }, AutomapTile::Flags::HorizontalArch)) {
if (HasAutomapFlag({ position.x, position.y - 1 }, AutomapTile::Flags::VerticalArch)) {
tile.type = AutomapTile::Types::Diamond;
}
}
}
return tile;
}
/**
* @brief Returns the automap shape at the given coordinate.
*/
AutomapTile GetAutomapTypeView(Point map)
{
if (map.x == -1 && map.y >= 0 && map.y < DMAXY && AutomapView[0][map.y]) {
if (HasAutomapFlag({ 0, map.y + 1 }, AutomapTile::Flags::Dirt) && HasAutomapFlag({ 0, map.y }, AutomapTile::Flags::Dirt) && HasAutomapFlag({ 0, map.y - 1 }, AutomapTile::Flags::Dirt)) {
return {};
}
return { AutomapTile::Types::None, AutomapTile::Flags::Dirt };
}
if (map.y == -1 && map.x >= 0 && map.x < DMAXY && AutomapView[map.x][0]) {
if (HasAutomapFlag({ map.x + 1, 0 }, AutomapTile::Flags::Dirt) && HasAutomapFlag({ map.x, 0 }, AutomapTile::Flags::Dirt) && HasAutomapFlag({ map.x - 1, 0 }, AutomapTile::Flags::Dirt)) {
return {};
}
return { AutomapTile::Types::None, AutomapTile::Flags::Dirt };
}
if (map.x < 0 || map.x >= DMAXX) {
return {};
}
if (map.y < 0 || map.y >= DMAXX) {
return {};
}
if (!AutomapView[map.x][map.y]) {
return {};
}
return GetAutomapType(map);
}
/** /**
* @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. * @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.
*/ */
@ -515,7 +535,7 @@ std::unique_ptr<AutomapTile[]> LoadAutomapData(size_t &tileCount)
} // namespace } // namespace
bool AutomapActive; bool AutomapActive;
bool AutomapView[DMAXX][DMAXY]; uint8_t AutomapView[DMAXX][DMAXY];
int AutoMapScale; int AutoMapScale;
Displacement AutomapOffset; Displacement AutomapOffset;
int AmLine64; int AmLine64;
@ -677,14 +697,14 @@ void DrawAutomap(const Surface &out)
for (int i = 0; i <= cells + 1; i++) { for (int i = 0; i <= cells + 1; i++) {
Point tile1 = screen; Point tile1 = screen;
for (int j = 0; j < cells; j++) { for (int j = 0; j < cells; j++) {
DrawAutomapTile(out, tile1, GetAutomapTypeView({ map.x + j, map.y - j })); DrawAutomapTile(out, tile1, { map.x + j, map.y - j });
tile1.x += AmLine64; tile1.x += AmLine64;
} }
map.y++; map.y++;
Point tile2 { screen.x - AmLine32, screen.y + AmLine16 }; Point tile2 { screen.x - AmLine32, screen.y + AmLine16 };
for (int j = 0; j <= cells; j++) { for (int j = 0; j <= cells; j++) {
DrawAutomapTile(out, tile2, GetAutomapTypeView({ map.x + j, map.y - j })); DrawAutomapTile(out, tile2, { map.x + j, map.y - j });
tile2.x += AmLine64; tile2.x += AmLine64;
} }
map.x++; map.x++;
@ -704,7 +724,13 @@ void DrawAutomap(const Surface &out)
DrawAutomapText(out); DrawAutomapText(out);
} }
void SetAutomapView(Point position) void UpdateAutomapExplorer(Point map, MapExplorationType explorer)
{
if (AutomapView[map.x][map.y] < explorer)
AutomapView[map.x][map.y] = explorer;
}
void SetAutomapView(Point position, MapExplorationType explorer)
{ {
const Point map { (position.x - 16) / 2, (position.y - 16) / 2 }; const Point map { (position.x - 16) / 2, (position.y - 16) / 2 };
@ -712,7 +738,7 @@ void SetAutomapView(Point position)
return; return;
} }
AutomapView[map.x][map.y] = true; UpdateAutomapExplorer(map, explorer);
AutomapTile tile = GetAutomapType(map); AutomapTile tile = GetAutomapType(map);
bool solid = tile.HasFlag(AutomapTile::Flags::Dirt); bool solid = tile.HasFlag(AutomapTile::Flags::Dirt);
@ -722,57 +748,57 @@ void SetAutomapView(Point position)
if (solid) { if (solid) {
auto tileSW = GetAutomapType({ map.x, map.y + 1 }); auto tileSW = GetAutomapType({ map.x, map.y + 1 });
if (tileSW.type == AutomapTile::Types::Corner && tileSW.HasFlag(AutomapTile::Flags::Dirt)) if (tileSW.type == AutomapTile::Types::Corner && tileSW.HasFlag(AutomapTile::Flags::Dirt))
AutomapView[map.x][map.y + 1] = true; UpdateAutomapExplorer({ map.x, map.y + 1 }, explorer);
} else if (HasAutomapFlag({ map.x - 1, map.y }, AutomapTile::Flags::Dirt)) { } else if (HasAutomapFlag({ map.x - 1, map.y }, AutomapTile::Flags::Dirt)) {
AutomapView[map.x - 1][map.y] = true; UpdateAutomapExplorer({ map.x - 1, map.y }, explorer);
} }
break; break;
case AutomapTile::Types::Horizontal: case AutomapTile::Types::Horizontal:
if (solid) { if (solid) {
auto tileSE = GetAutomapType({ map.x + 1, map.y }); auto tileSE = GetAutomapType({ map.x + 1, map.y });
if (tileSE.type == AutomapTile::Types::Corner && tileSE.HasFlag(AutomapTile::Flags::Dirt)) if (tileSE.type == AutomapTile::Types::Corner && tileSE.HasFlag(AutomapTile::Flags::Dirt))
AutomapView[map.x + 1][map.y] = true; UpdateAutomapExplorer({ map.x + 1, map.y }, explorer);
} else if (HasAutomapFlag({ map.x, map.y - 1 }, AutomapTile::Flags::Dirt)) { } else if (HasAutomapFlag({ map.x, map.y - 1 }, AutomapTile::Flags::Dirt)) {
AutomapView[map.x][map.y - 1] = true; UpdateAutomapExplorer({ map.x, map.y - 1 }, explorer);
} }
break; break;
case AutomapTile::Types::Cross: case AutomapTile::Types::Cross:
if (solid) { if (solid) {
auto tileSW = GetAutomapType({ map.x, map.y + 1 }); auto tileSW = GetAutomapType({ map.x, map.y + 1 });
if (tileSW.type == AutomapTile::Types::Corner && tileSW.HasFlag(AutomapTile::Flags::Dirt)) if (tileSW.type == AutomapTile::Types::Corner && tileSW.HasFlag(AutomapTile::Flags::Dirt))
AutomapView[map.x][map.y + 1] = true; UpdateAutomapExplorer({ map.x, map.y + 1 }, explorer);
auto tileSE = GetAutomapType({ map.x + 1, map.y }); auto tileSE = GetAutomapType({ map.x + 1, map.y });
if (tileSE.type == AutomapTile::Types::Corner && tileSE.HasFlag(AutomapTile::Flags::Dirt)) if (tileSE.type == AutomapTile::Types::Corner && tileSE.HasFlag(AutomapTile::Flags::Dirt))
AutomapView[map.x + 1][map.y] = true; UpdateAutomapExplorer({ map.x + 1, map.y }, explorer);
} else { } else {
if (HasAutomapFlag({ map.x - 1, map.y }, AutomapTile::Flags::Dirt)) if (HasAutomapFlag({ map.x - 1, map.y }, AutomapTile::Flags::Dirt))
AutomapView[map.x - 1][map.y] = true; UpdateAutomapExplorer({ map.x - 1, map.y }, explorer);
if (HasAutomapFlag({ map.x, map.y - 1 }, AutomapTile::Flags::Dirt)) if (HasAutomapFlag({ map.x, map.y - 1 }, AutomapTile::Flags::Dirt))
AutomapView[map.x][map.y - 1] = true; UpdateAutomapExplorer({ map.x, map.y - 1 }, explorer);
if (HasAutomapFlag({ map.x - 1, map.y - 1 }, AutomapTile::Flags::Dirt)) if (HasAutomapFlag({ map.x - 1, map.y - 1 }, AutomapTile::Flags::Dirt))
AutomapView[map.x - 1][map.y - 1] = true; UpdateAutomapExplorer({ map.x - 1, map.y - 1 }, explorer);
} }
break; break;
case AutomapTile::Types::FenceVertical: case AutomapTile::Types::FenceVertical:
if (solid) { if (solid) {
if (HasAutomapFlag({ map.x, map.y - 1 }, AutomapTile::Flags::Dirt)) if (HasAutomapFlag({ map.x, map.y - 1 }, AutomapTile::Flags::Dirt))
AutomapView[map.x][map.y - 1] = true; UpdateAutomapExplorer({ map.x, map.y - 1 }, explorer);
auto tileSW = GetAutomapType({ map.x, map.y + 1 }); auto tileSW = GetAutomapType({ map.x, map.y + 1 });
if (tileSW.type == AutomapTile::Types::Corner && tileSW.HasFlag(AutomapTile::Flags::Dirt)) if (tileSW.type == AutomapTile::Types::Corner && tileSW.HasFlag(AutomapTile::Flags::Dirt))
AutomapView[map.x][map.y + 1] = true; UpdateAutomapExplorer({ map.x, map.y + 1 }, explorer);
} else if (HasAutomapFlag({ map.x - 1, map.y }, AutomapTile::Flags::Dirt)) { } else if (HasAutomapFlag({ map.x - 1, map.y }, AutomapTile::Flags::Dirt)) {
AutomapView[map.x - 1][map.y] = true; UpdateAutomapExplorer({ map.x - 1, map.y }, explorer);
} }
break; break;
case AutomapTile::Types::FenceHorizontal: case AutomapTile::Types::FenceHorizontal:
if (solid) { if (solid) {
if (HasAutomapFlag({ map.x - 1, map.y }, AutomapTile::Flags::Dirt)) if (HasAutomapFlag({ map.x - 1, map.y }, AutomapTile::Flags::Dirt))
AutomapView[map.x - 1][map.y] = true; UpdateAutomapExplorer({ map.x - 1, map.y }, explorer);
auto tileSE = GetAutomapType({ map.x + 1, map.y }); auto tileSE = GetAutomapType({ map.x + 1, map.y });
if (tileSE.type == AutomapTile::Types::Corner && tileSE.HasFlag(AutomapTile::Flags::Dirt)) if (tileSE.type == AutomapTile::Types::Corner && tileSE.HasFlag(AutomapTile::Flags::Dirt))
AutomapView[map.x + 1][map.y] = true; UpdateAutomapExplorer({ map.x + 1, map.y }, explorer);
} else if (HasAutomapFlag({ map.x, map.y - 1 }, AutomapTile::Flags::Dirt)) { } else if (HasAutomapFlag({ map.x, map.y - 1 }, AutomapTile::Flags::Dirt)) {
AutomapView[map.x][map.y - 1] = true; UpdateAutomapExplorer({ map.x, map.y - 1 }, explorer);
} }
break; break;
default: default:

22
Source/automap.h

@ -14,10 +14,23 @@
namespace devilution { namespace devilution {
enum MapExplorationType : uint8_t {
/** unexplored map tile */
MAP_EXP_NONE,
/** map tile explored in vanilla - compatibility reasons */
MAP_EXP_OLD,
/** map explored by a shrine */
MAP_EXP_SHRINE,
/** map tile explored by someone else in multiplayer */
MAP_EXP_OTHERS,
/** map tile explored by current player */
MAP_EXP_SELF,
};
/** Specifies whether the automap is enabled. */ /** Specifies whether the automap is enabled. */
extern bool AutomapActive; extern bool AutomapActive;
/** Tracks the explored areas of the map. */ /** Tracks the explored areas of the map. */
extern bool AutomapView[DMAXX][DMAXY]; extern uint8_t AutomapView[DMAXX][DMAXY];
/** Specifies the scale of the automap. */ /** Specifies the scale of the automap. */
extern int AutoMapScale; extern int AutoMapScale;
extern Displacement AutomapOffset; extern Displacement AutomapOffset;
@ -77,10 +90,15 @@ void AutomapZoomOut();
*/ */
void DrawAutomap(const Surface &out); void DrawAutomap(const Surface &out);
/**
* @brief Updates automap explorer at point if value is higher than existing.
*/
void UpdateAutomapExplorer(Point map, MapExplorationType explorer);
/** /**
* @brief Marks the given coordinate as within view on the automap. * @brief Marks the given coordinate as within view on the automap.
*/ */
void SetAutomapView(Point tile); void SetAutomapView(Point tile, MapExplorationType explorer);
/** /**
* @brief Resets the zoom level of the automap. * @brief Resets the zoom level of the automap.

19
Source/debug.cpp

@ -333,13 +333,25 @@ std::string DebugCmdLighting(const string_view parameter)
return "All raindrops are the same."; return "All raindrops are the same.";
} }
std::string DebugCmdMap(const string_view parameter) std::string DebugCmdMapReveal(const string_view parameter)
{ {
std::fill(&AutomapView[0][0], &AutomapView[DMAXX - 1][DMAXX - 1], true); for (int x = 0; x < DMAXX; x++)
for (int y = 0; y < DMAXY; y++)
UpdateAutomapExplorer({ x, y }, MAP_EXP_SHRINE);
return "The way is made clear when viewed from above"; return "The way is made clear when viewed from above";
} }
std::string DebugCmdMapHide(const string_view parameter)
{
for (int x = 0; x < DMAXX; x++)
for (int y = 0; y < DMAXY; y++)
if (AutomapView[x][y] == MAP_EXP_SHRINE)
AutomapView[x][y] = MAP_EXP_NONE;
return "The way is made unclear when viewed from below";
}
std::string DebugCmdVision(const string_view parameter) std::string DebugCmdVision(const string_view parameter)
{ {
DebugVision = !DebugVision; DebugVision = !DebugVision;
@ -708,7 +720,8 @@ std::vector<DebugCmdItem> DebugCmdList = {
{ "setspells", "Set spell level to {level} for all spells.", "{level}", &DebugCmdSetSpellsLevel }, { "setspells", "Set spell level to {level} for all spells.", "{level}", &DebugCmdSetSpellsLevel },
{ "take gold", "Removes all gold from inventory.", "", &DebugCmdTakeGoldCheat }, { "take gold", "Removes all gold from inventory.", "", &DebugCmdTakeGoldCheat },
{ "give quest", "Enable a given quest.", "({id})", &DebugCmdQuest }, { "give quest", "Enable a given quest.", "({id})", &DebugCmdQuest },
{ "give map", "Reveal the map.", "", &DebugCmdMap }, { "give map", "Reveal the map.", "", &DebugCmdMapReveal },
{ "take map", "Hide the map.", "", &DebugCmdMapHide },
{ "changelevel", "Moves to specifided {level} (use 0 for town).", "{level}", &DebugCmdWarpToLevel }, { "changelevel", "Moves to specifided {level} (use 0 for town).", "{level}", &DebugCmdWarpToLevel },
{ "map", "Load a quest level {level}.", "{level}", &DebugCmdLoadMap }, { "map", "Load a quest level {level}.", "{level}", &DebugCmdLoadMap },
{ "visit", "Visit a towner.", "{towner}", &DebugCmdVisitTowner }, { "visit", "Visit a towner.", "{towner}", &DebugCmdVisitTowner },

13
Source/lighting.cpp

@ -645,13 +645,12 @@ void DoUnVision(Point position, int nRadius)
} }
} }
void DoVision(Point position, int nRadius, bool doautomap, bool visible) void DoVision(Point position, int nRadius, MapExplorationType doautomap, bool visible)
{ {
if (InDungeonBounds(position)) { if (InDungeonBounds(position)) {
if (doautomap) { if (doautomap != MAP_EXP_NONE) {
if (dFlags[position.x][position.y] != 0) { if (dFlags[position.x][position.y] != 0) {
SetAutomapView(position); SetAutomapView(position, doautomap);
} }
dFlags[position.x][position.y] |= BFLAG_EXPLORED; dFlags[position.x][position.y] |= BFLAG_EXPLORED;
} }
@ -712,9 +711,9 @@ void DoVision(Point position, int nRadius, bool doautomap, bool visible)
&& !nBlockTable[dPiece[x1adj + nCrawlX][y1adj + nCrawlY]]) && !nBlockTable[dPiece[x1adj + nCrawlX][y1adj + nCrawlY]])
|| (InDungeonBounds({ x2adj + nCrawlX, y2adj + nCrawlY }) || (InDungeonBounds({ x2adj + nCrawlX, y2adj + nCrawlY })
&& !nBlockTable[dPiece[x2adj + nCrawlX][y2adj + nCrawlY]])) { && !nBlockTable[dPiece[x2adj + nCrawlX][y2adj + nCrawlY]])) {
if (doautomap) { if (doautomap != MAP_EXP_NONE) {
if (dFlags[nCrawlX][nCrawlY] != 0) { if (dFlags[nCrawlX][nCrawlY] != 0) {
SetAutomapView({ nCrawlX, nCrawlY }); SetAutomapView({ nCrawlX, nCrawlY }, doautomap);
} }
dFlags[nCrawlX][nCrawlY] |= BFLAG_EXPLORED; dFlags[nCrawlX][nCrawlY] |= BFLAG_EXPLORED;
} }
@ -1172,7 +1171,7 @@ void ProcessVisionList()
DoVision( DoVision(
vision.position.tile, vision.position.tile,
vision._lradius, vision._lradius,
vision._lflags, vision._lflags ? MAP_EXP_SELF : MAP_EXP_OTHERS,
vision._lflags); vision._lflags);
} }
bool delflag; bool delflag;

3
Source/lighting.h

@ -7,6 +7,7 @@
#include <array> #include <array>
#include "automap.h"
#include "engine.h" #include "engine.h"
#include "engine/point.hpp" #include "engine/point.hpp"
#include "miniwin/miniwin.h" #include "miniwin/miniwin.h"
@ -49,7 +50,7 @@ extern bool UpdateLighting;
void DoLighting(Point position, int nRadius, int Lnum); void DoLighting(Point position, int nRadius, int Lnum);
void DoUnVision(Point position, int nRadius); void DoUnVision(Point position, int nRadius);
void DoVision(Point position, int nRadius, bool doautomap, bool visible); void DoVision(Point position, int nRadius, MapExplorationType doautomap, bool visible);
void MakeLightTable(); void MakeLightTable();
#ifdef _DEBUG #ifdef _DEBUG
void ToggleLighting(); void ToggleLighting();

12
Source/loadsave.cpp

@ -1832,7 +1832,7 @@ void LoadGame(bool firstflag)
} }
for (int j = 0; j < DMAXY; j++) { for (int j = 0; j < DMAXY; j++) {
for (int i = 0; i < DMAXX; i++) // NOLINT(modernize-loop-convert) for (int i = 0; i < DMAXX; i++) // NOLINT(modernize-loop-convert)
AutomapView[i][j] = file.NextBool8(); AutomapView[i][j] = file.NextLE<uint8_t>();
} }
file.Skip(MAXDUNX * MAXDUNY); // dMissile file.Skip(MAXDUNX * MAXDUNY); // dMissile
} }
@ -2026,7 +2026,7 @@ void SaveGameData()
} }
for (int j = 0; j < DMAXY; j++) { for (int j = 0; j < DMAXY; j++) {
for (int i = 0; i < DMAXX; i++) // NOLINT(modernize-loop-convert) for (int i = 0; i < DMAXX; i++) // NOLINT(modernize-loop-convert)
file.WriteLE<uint8_t>(AutomapView[i][j] ? 1 : 0); file.WriteLE<uint8_t>(AutomapView[i][j]);
} }
for (int j = 0; j < MAXDUNY; j++) { for (int j = 0; j < MAXDUNY; j++) {
for (int i = 0; i < MAXDUNX; i++) // NOLINT(modernize-loop-convert) for (int i = 0; i < MAXDUNX; i++) // NOLINT(modernize-loop-convert)
@ -2125,7 +2125,7 @@ void SaveLevel()
} }
for (int j = 0; j < DMAXY; j++) { for (int j = 0; j < DMAXY; j++) {
for (int i = 0; i < DMAXX; i++) // NOLINT(modernize-loop-convert) for (int i = 0; i < DMAXX; i++) // NOLINT(modernize-loop-convert)
file.WriteLE<uint8_t>(AutomapView[i][j] ? 1 : 0); file.WriteLE<uint8_t>(AutomapView[i][j]);
} }
} }
@ -2206,8 +2206,10 @@ void LoadLevel()
dPreLight[i][j] = file.NextLE<int8_t>(); dPreLight[i][j] = file.NextLE<int8_t>();
} }
for (int j = 0; j < DMAXY; j++) { for (int j = 0; j < DMAXY; j++) {
for (int i = 0; i < DMAXX; i++) // NOLINT(modernize-loop-convert) for (int i = 0; i < DMAXX; i++) { // NOLINT(modernize-loop-convert)
AutomapView[i][j] = file.NextBool8(); uint8_t automapView = file.NextLE<uint8_t>();
AutomapView[i][j] = automapView == MAP_EXP_OLD ? MAP_EXP_SELF : automapView;
}
} }
} }

4
Source/monster.cpp

@ -1073,7 +1073,7 @@ void DiabloDeath(Monster &diablo, bool sendmsg)
dMonster[monster.position.tile.x][monster.position.tile.y] = k + 1; dMonster[monster.position.tile.x][monster.position.tile.y] = k + 1;
} }
AddLight(diablo.position.tile, 8); AddLight(diablo.position.tile, 8);
DoVision(diablo.position.tile, 8, false, true); DoVision(diablo.position.tile, 8, MAP_EXP_NONE, true);
int dist = diablo.position.tile.WalkingDistance(ViewPosition); int dist = diablo.position.tile.WalkingDistance(ViewPosition);
if (dist > 20) if (dist > 20)
dist = 20; dist = 20;
@ -3809,7 +3809,7 @@ void InitMonsters()
for (int i = 0; i < nt; i++) { for (int i = 0; i < nt; i++) {
for (int s = -2; s < 2; s++) { for (int s = -2; s < 2; s++) {
for (int t = -2; t < 2; t++) for (int t = -2; t < 2; t++)
DoVision(trigs[i].position + Displacement { s, t }, 15, false, false); DoVision(trigs[i].position + Displacement { s, t }, 15, MAP_EXP_NONE, false);
} }
} }
if (!gbIsSpawn) if (!gbIsSpawn)

4
Source/objects.cpp

@ -3212,7 +3212,9 @@ bool OperateShrineSecluded(int pnum)
if (pnum != MyPlayerId) if (pnum != MyPlayerId)
return true; return true;
std::fill(&AutomapView[0][0], &AutomapView[DMAXX - 1][DMAXX - 1], true); for (int x = 0; x < DMAXX; x++)
for (int y = 0; y < DMAXY; y++)
UpdateAutomapExplorer({ x, y }, MAP_EXP_SHRINE);
InitDiabloMsg(EMSG_SHRINE_SECLUDED); InitDiabloMsg(EMSG_SHRINE_SECLUDED);

Loading…
Cancel
Save