From 45bb29bac2059e9a3ced3525891a97f0d24a79f8 Mon Sep 17 00:00:00 2001 From: KPhoenix Date: Sat, 26 Aug 2023 19:37:40 -0400 Subject: [PATCH 1/5] Detailed Automap Change Towner color Adjust colors Fix river color and change towners to white Crosses for towners Add golem Update automap.cpp Draw Beserked Draw X for dead players Clean up code Change rivers back to Item color Readability More cleanup More cleanup Pentragram Fix pentagram shadow Transparent Automap Pentagram with no floats Update automap.cpp SetMapPixel and cleanup Differentiate stairs --- Source/automap.cpp | 480 +++++++++++++++++++----- Source/automap.h | 6 +- Source/control.cpp | 8 +- Source/diablo.cpp | 2 + Source/engine.cpp | 9 + Source/engine.h | 1 + Source/engine/render/automap_render.cpp | 132 ++++++- Source/engine/render/automap_render.hpp | 2 + 8 files changed, 538 insertions(+), 102 deletions(-) diff --git a/Source/automap.cpp b/Source/automap.cpp index eabf18b717b..28a014d69d8 100644 --- a/Source/automap.cpp +++ b/Source/automap.cpp @@ -15,7 +15,9 @@ #include "engine/render/automap_render.hpp" #include "levels/gendung.h" #include "levels/setmaps.h" +#include "missiles.h" #include "player.h" +#include "towners.h" #include "utils/language.h" #include "utils/stdcompat/algorithm.hpp" #include "utils/ui_fwd.h" @@ -39,6 +41,20 @@ enum MapColors : uint8_t { MapColorsDim = (PAL16_YELLOW + 8), /** color for items on automap */ MapColorsItem = (PAL8_BLUE + 1), + /** color for objects on automap */ + MapColorsObject = (PAL8_ORANGE + 1), + /** color for Town Portal on automap */ + MapColorsPortal = (PAL8_BLUE + 1), + /** color for Red Portal on automap */ + MapColorsRedPortal = (PAL8_RED + 1), + /** color for towners on automap */ + MapColorsTowner = (PAL16_GRAY + 15), + /** color for golems on automap */ + MapColorsGolem = (PAL16_GRAY + 4), + /** color for berserked monster on automap */ + MapColorsBerserk = (PAL8_YELLOW + 4), + /** color for berserked monster on automap */ + MapColorsDead = (PAL8_RED + 2), }; struct AutomapTile { @@ -114,6 +130,22 @@ void DrawDiamond(const Surface &out, Point center, uint8_t color) DrawMapLineNE(out, bottom, AmLine(8), color); } +void DrawCross(const Surface &out, Point center, uint8_t color) +{ + DrawMapLineNE(out, { center.x, center.y - AmLine(8) }, AmLine(8), color); + DrawMapLineNE(out, { center.x - AmLine(32), center.y + AmLine(8) }, AmLine(8), color); + DrawMapLineNE(out, { center.x - AmLine(32), center.y - AmLine(8) }, AmLine(8), color); + DrawMapLineSE(out, { center.x + AmLine(16), center.y - AmLine(16) }, AmLine(8), color); + DrawMapLineSE(out, { center.x - AmLine(32), center.y + AmLine(8) }, AmLine(8), color); + DrawMapLineSE(out, { center.x - AmLine(32), center.y - AmLine(8) }, AmLine(8), color); + DrawMapLineSE(out, { center.x - AmLine(16), center.y - AmLine(16) }, AmLine(8), color); + DrawMapLineSE(out, { center.x, center.y + AmLine(8) }, AmLine(8), color); + DrawMapLineSE(out, { center.x + AmLine(16), center.y }, AmLine(8), color); + DrawMapLineNE(out, { center.x - AmLine(16), center.y + AmLine(16) }, AmLine(8), color); + DrawMapLineNE(out, { center.x + AmLine(16), center.y }, AmLine(8), color); + DrawMapLineNE(out, { center.x + AmLine(16), center.y + AmLine(16) }, AmLine(8), color); +} + void DrawMapVerticalDoor(const Surface &out, Point center, uint8_t colorBright, uint8_t colorDim) { if (leveltype != DTYPE_CATACOMBS) { @@ -344,14 +376,114 @@ void DrawRiverForkOut(const Surface &out, Point center, uint8_t color) out.SetPixel({ center.x + AmLine(8), center.y + AmLine(16) - AmLine(4) }, color); } -void DrawStairs(const Surface &out, Point center, uint8_t color) +enum class StairsType : uint8_t { + Invalid, + DownRight, + DownLeft, + UpRight, + UpLeft, +}; + +StairsType GetStairsType(uint8_t tileId, uint8_t dlvl) +{ + if (dlvl == 0) + return StairsType::DownRight; + // clang-format off + switch (tileId) { + // Church + case 57: + return StairsType::DownRight; + case 66: + return StairsType::UpRight; + // Catacombs + case 78: + return StairsType::DownRight; + case 77: + case 160: + return StairsType::UpRight; // Shortcut + // Caves + case 47: + return StairsType::DownLeft; + case 48: + return StairsType::DownRight; + case 51: + case 153: + return StairsType::UpRight; // Shortcut + // Hell + case 43: + return StairsType::DownLeft; + case 33: + case 131: + return StairsType::UpRight; // Shortcut + // Hive + case 16: + return StairsType::DownLeft; + case 17: + case 21: + return StairsType::UpRight; + // Crypt + case 46: + return StairsType::DownRight; + case 56: + case 64: + return StairsType::UpRight; + default: + return StairsType::Invalid; + } + // clang-format on +} + +void DrawStairs(const Surface &out, Point center, uint8_t color, StairsType type) { constexpr int NumStairSteps = 4; - const Displacement offset = { -AmLine(8), AmLine(4) }; - Point p = { center.x - AmLine(8), center.y - AmLine(8) - AmLine(4) }; + + Displacement stairsOffset = { 0, 0 }; + + if (type == StairsType::DownRight) { + stairsOffset = Displacement { AmLine(24), AmLine(12) }; + } else if (type == StairsType::DownLeft) { + stairsOffset = Displacement { -AmLine(24), AmLine(12) }; + } + + int lineLength = 16; + + if (IsAnyOf(type, StairsType::DownRight, StairsType::DownLeft)) + lineLength = 4; + + Displacement offset = { 0, 0 }; + Point p; + + if (IsAnyOf(type, StairsType::DownRight, StairsType::UpRight)) { + offset = { -AmLine(8), AmLine(4) }; + p = { center.x - AmLine(8) + stairsOffset.deltaX, center.y - AmLine(8) - AmLine(4) + stairsOffset.deltaY }; + } else if (IsAnyOf(type, StairsType::DownLeft, StairsType::UpLeft)) { + offset = { AmLine(8), AmLine(4) }; + p = { center.x + AmLine(8) + stairsOffset.deltaX, center.y - AmLine(8) - AmLine(4) + stairsOffset.deltaY }; + } + for (int i = 0; i < NumStairSteps; ++i) { - DrawMapLineSE(out, p, AmLine(16), color); + if (IsAnyOf(type, StairsType::DownRight, StairsType::UpRight)) + DrawMapLineSE(out, p, AmLine(lineLength), color); + else if (IsAnyOf(type, StairsType::DownLeft, StairsType::UpLeft)) + DrawMapLineSW(out, p, AmLine(lineLength), color); + + if (i != NumStairSteps - 1) { + if (type == StairsType::DownRight) + DrawMapLineSW(out, p + Displacement { 1, 0 }, AmLine(4), color); + else if (type == StairsType::DownLeft) + DrawMapLineSE(out, p + Displacement { -1, 0 }, AmLine(4), color); + } + p += offset; + + if (type == StairsType::DownRight) { + p -= Displacement { AmLine(8), AmLine(4) }; + } else if (type == StairsType::DownLeft) { + p -= Displacement { -AmLine(8), AmLine(4) }; + } + + if (IsAnyOf(type, StairsType::DownRight, StairsType::DownLeft)) + lineLength += 4; } } @@ -514,7 +646,15 @@ void DrawAutomapTile(const Surface &out, Point center, Point map) } if (tile.HasFlag(AutomapTile::Flags::Stairs)) { - DrawStairs(out, center, colorBright); + DrawStairs(out, center, colorBright, GetStairsType(dungeon[map.x][map.y], currlevel)); + } + + if (currlevel == Quests[Q_BETRAYER]._qlevel && map == Quests[Q_BETRAYER].position.worldToMega() + Displacement { 1, 1 }) { + int pentaColor = (Quests[Q_BETRAYER]._qactive == QUEST_DONE) ? PAL8_RED + 2 : PAL16_YELLOW + 8; + DrawMapEllipse(out, center + Displacement { 0, 1 }, AmLine(64), 0); // shadow + DrawMapStar(out, center + Displacement { 0, 1 }, AmLine(64), 0); // shadow + DrawMapEllipse(out, center, AmLine(64), pentaColor); + DrawMapStar(out, center, AmLine(64), pentaColor); } switch (tile.type) { @@ -593,10 +733,32 @@ void DrawAutomapTile(const Surface &out, Point center, Point map) } } +Point GetAutomapScreen(const int i, const int j, const Displacement &myPlayerOffset) +{ + int px = i - 2 * AutomapOffset.deltaX - ViewPosition.x; + int py = j - 2 * AutomapOffset.deltaY - ViewPosition.y; + + Point screen = { + (myPlayerOffset.deltaX * AutoMapScale / 100 / 2) + (px - py) * AmLine(16) + gnScreenWidth / 2, + (myPlayerOffset.deltaY * AutoMapScale / 100 / 2) + (px + py) * AmLine(8) + (gnScreenHeight - GetMainPanel().size.height) / 2 + }; + + if (CanPanelsCoverView()) { + if (IsRightPanelOpen()) + screen.x -= 160; + if (IsLeftPanelOpen()) + screen.x += 160; + } + screen.y -= AmLine(8); + + return screen; +} + void SearchAutomapItem(const Surface &out, const Displacement &myPlayerOffset, int searchRadius, tl::function_ref highlightTile) { const Player &player = *MyPlayer; Point tile = player.position.tile; + if (player._pmode == PM_WALK_SIDEWAYS) { tile = player.position.future; if (player._pdir == Direction::West) @@ -616,49 +778,79 @@ void SearchAutomapItem(const Surface &out, const Displacement &myPlayerOffset, i if (!highlightTile({ i, j })) continue; - int px = i - 2 * AutomapOffset.deltaX - ViewPosition.x; - int py = j - 2 * AutomapOffset.deltaY - ViewPosition.y; + DrawDiamond(out, GetAutomapScreen(i, j, myPlayerOffset), MapColorsItem); + } + } +} - Point screen = { - (myPlayerOffset.deltaX * AutoMapScale / 100 / 2) + (px - py) * AmLine(16) + gnScreenWidth / 2, - (myPlayerOffset.deltaY * AutoMapScale / 100 / 2) + (px + py) * AmLine(8) + (gnScreenHeight - GetMainPanel().size.height) / 2 - }; +void DrawAutomapObject(const Surface &out, const Displacement &myPlayerOffset, tl::function_ref highlightTile) +{ + for (int i = 0; i < MAXDUNX; i++) { + for (int j = 0; j < MAXDUNY; j++) { + MapExplorationType explorationType = static_cast(AutomapView[clamp(((i - 16) / 2), 0, DMAXX - 1)][clamp(((j - 16) / 2), 0, DMAXY - 1)]); - if (CanPanelsCoverView()) { - if (IsRightPanelOpen()) - screen.x -= 160; - if (IsLeftPanelOpen()) - screen.x += 160; - } - screen.y -= AmLine(8); - DrawDiamond(out, screen, MapColorsItem); + if (!highlightTile({ i, j }) || explorationType == MAP_EXP_NONE || !IsAnyOf(ObjectAtPosition({ i, j })._otype, OBJ_BLINDBOOK, OBJ_BLOODBOOK, OBJ_BOOK2R, OBJ_CRUX1, OBJ_CRUX2, OBJ_CRUX3, OBJ_L5BOOKS, OBJ_L5LEVER, OBJ_LAZSTAND, OBJ_LEVER, OBJ_MCIRCLE1, OBJ_MCIRCLE2, OBJ_MUSHPATCH, OBJ_PEDESTAL, OBJ_SIGNCHEST, OBJ_SLAINHERO, OBJ_STAND, OBJ_STORYBOOK, OBJ_SWITCHSKL, OBJ_WARARMOR, OBJ_WARWEAP)) + continue; + + DrawDiamond(out, GetAutomapScreen(i, j, myPlayerOffset), MapColorsObject); } } } -/** - * @brief Renders an arrow on the automap, centered on and facing the direction of the player. - */ -void DrawAutomapPlr(const Surface &out, const Displacement &myPlayerOffset, int playerId) +void DrawAutomapMissile(const Surface &out, const Displacement &myPlayerOffset) { - int playerColor = MapColorsPlayer + (8 * playerId) % 128; + for (int i = 0; i < MAXDUNX; i++) { + for (int j = 0; j < MAXDUNY; j++) { + MapExplorationType explorationType = static_cast(AutomapView[clamp(((i - 16) / 2), 0, DMAXX - 1)][clamp(((j - 16) / 2), 0, DMAXY - 1)]); + Missile *portal = nullptr; + + for (auto &m : Missiles) { + if (IsAnyOf(m._mitype, MissileID::TownPortal, MissileID::RedPortal) && m.position.tile == Point { i, j }) { + portal = &m; + } + } + if (portal == nullptr || (explorationType == MAP_EXP_NONE && portal->_mitype == MissileID::RedPortal)) + continue; - Player &player = Players[playerId]; - Point tile = player.position.tile; - if (player._pmode == PM_WALK_SIDEWAYS) { - tile = player.position.future; + DrawCross(out, GetAutomapScreen(i, j, myPlayerOffset), portal->_mitype == MissileID::TownPortal ? MapColorsPortal : MapColorsRedPortal); + } } +} + +Displacement GetAutomapWalkingOffset(const Player &player) +{ + Displacement offset = {}; + if (player.isWalking()) + offset = GetOffsetForWalking(player.AnimInfo, player._pdir); + return offset; +} + +Displacement GetAutomapWalkingOffset(const Monster *monster) +{ + Displacement offset = {}; + + if (monster->isWalking()) + offset = GetOffsetForWalking(monster->animInfo, monster->direction); + return offset; +} + +Displacement GetAutomapWalkingOffset(const Towner &towner) +{ + return {}; +} + +template +void DrawAutomapArrow(const Surface &out, const EntityType &entity, const Displacement &myPlayerOffset, const Point &tile, const Direction &dir, const int col, const int deadCol, const bool entityIsAlive) +{ int px = tile.x - 2 * AutomapOffset.deltaX - ViewPosition.x; int py = tile.y - 2 * AutomapOffset.deltaY - ViewPosition.y; - Displacement playerOffset = {}; - if (player.isWalking()) - playerOffset = GetOffsetForWalking(player.AnimInfo, player._pdir); + Displacement offset = GetAutomapWalkingOffset(entity); Point base = { - ((playerOffset.deltaX + myPlayerOffset.deltaX) * AutoMapScale / 100 / 2) + (px - py) * AmLine(16) + gnScreenWidth / 2, - ((playerOffset.deltaY + myPlayerOffset.deltaY) * AutoMapScale / 100 / 2) + (px + py) * AmLine(8) + (gnScreenHeight - GetMainPanel().size.height) / 2 + ((offset.deltaX + myPlayerOffset.deltaX) * AutoMapScale / 100 / 2) + (px - py) * AmLine(16) + gnScreenWidth / 2, + ((offset.deltaY + myPlayerOffset.deltaY) * AutoMapScale / 100 / 2) + (px + py) * AmLine(8) + (gnScreenHeight - GetMainPanel().size.height) / 2 }; if (CanPanelsCoverView()) { @@ -669,58 +861,157 @@ void DrawAutomapPlr(const Surface &out, const Displacement &myPlayerOffset, int } base.y -= AmLine(16); - switch (player._pdir) { - case Direction::North: { - const Point point { base.x, base.y - AmLine(16) }; - DrawVerticalLine(out, point, AmLine(16), playerColor); - DrawMapLineSteepNE(out, { point.x - AmLine(4), point.y + 2 * AmLine(4) }, AmLine(4), playerColor); - DrawMapLineSteepNW(out, { point.x + AmLine(4), point.y + 2 * AmLine(4) }, AmLine(4), playerColor); - } break; - case Direction::NorthEast: { - const Point point { base.x + AmLine(16), base.y - AmLine(8) }; - DrawHorizontalLine(out, { point.x - AmLine(8), point.y }, AmLine(8), playerColor); - DrawMapLineNE(out, { point.x - 2 * AmLine(8), point.y + AmLine(8) }, AmLine(8), playerColor); - DrawMapLineSteepSW(out, point, AmLine(4), playerColor); - } break; - case Direction::East: { - const Point point { base.x + AmLine(16), base.y }; - DrawMapLineNW(out, point, AmLine(4), playerColor); - DrawHorizontalLine(out, { point.x - AmLine(16), point.y }, AmLine(16), playerColor); - DrawMapLineSW(out, point, AmLine(4), playerColor); - } break; - case Direction::SouthEast: { - const Point point { base.x + AmLine(16), base.y + AmLine(8) }; - DrawMapLineSteepNW(out, point, AmLine(4), playerColor); - DrawMapLineSE(out, { point.x - 2 * AmLine(8), point.y - AmLine(8) }, AmLine(8), playerColor); - DrawHorizontalLine(out, { point.x - (AmLine(8) + 1), point.y }, AmLine(8) + 1, playerColor); - } break; - case Direction::South: { - const Point point { base.x, base.y + AmLine(16) }; - DrawVerticalLine(out, { point.x, point.y - AmLine(16) }, AmLine(16), playerColor); - DrawMapLineSteepSW(out, { point.x + AmLine(4), point.y - 2 * AmLine(4) }, AmLine(4), playerColor); - DrawMapLineSteepSE(out, { point.x - AmLine(4), point.y - 2 * AmLine(4) }, AmLine(4), playerColor); - } break; - case Direction::SouthWest: { - const Point point { base.x - AmLine(16), base.y + AmLine(8) }; - DrawMapLineSteepNE(out, point, AmLine(4), playerColor); - DrawMapLineSW(out, { point.x + 2 * AmLine(8), point.y - AmLine(8) }, AmLine(8), playerColor); - DrawHorizontalLine(out, point, AmLine(8) + 1, playerColor); - } break; - case Direction::West: { - const Point point { base.x - AmLine(16), base.y }; - DrawMapLineNE(out, point, AmLine(4), playerColor); - DrawHorizontalLine(out, point, AmLine(16) + 1, playerColor); - DrawMapLineSE(out, point, AmLine(4), playerColor); - } break; - case Direction::NorthWest: { - const Point point { base.x - AmLine(16), base.y - AmLine(8) }; - DrawMapLineNW(out, { point.x + 2 * AmLine(8), point.y + AmLine(8) }, AmLine(8), playerColor); - DrawHorizontalLine(out, point, AmLine(8) + 1, playerColor); - DrawMapLineSteepSE(out, point, AmLine(4), playerColor); - } break; - case Direction::NoDirection: - break; + if (entityIsAlive) { + switch (dir) { + case Direction::North: { + const Point point { base.x, base.y - AmLine(16) }; + DrawVerticalLine(out, point, AmLine(16), col); + DrawMapLineSteepNE(out, { point.x - AmLine(4), point.y + 2 * AmLine(4) }, AmLine(4), col); + DrawMapLineSteepNW(out, { point.x + AmLine(4), point.y + 2 * AmLine(4) }, AmLine(4), col); + } break; + case Direction::NorthEast: { + const Point point { base.x + AmLine(16), base.y - AmLine(8) }; + DrawHorizontalLine(out, { point.x - AmLine(8), point.y }, AmLine(8), col); + DrawMapLineNE(out, { point.x - 2 * AmLine(8), point.y + AmLine(8) }, AmLine(8), col); + DrawMapLineSteepSW(out, point, AmLine(4), col); + } break; + case Direction::East: { + const Point point { base.x + AmLine(16), base.y }; + DrawMapLineNW(out, point, AmLine(4), col); + DrawHorizontalLine(out, { point.x - AmLine(16), point.y }, AmLine(16), col); + DrawMapLineSW(out, point, AmLine(4), col); + } break; + case Direction::SouthEast: { + const Point point { base.x + AmLine(16), base.y + AmLine(8) }; + DrawMapLineSteepNW(out, point, AmLine(4), col); + DrawMapLineSE(out, { point.x - 2 * AmLine(8), point.y - AmLine(8) }, AmLine(8), col); + DrawHorizontalLine(out, { point.x - (AmLine(8) + 1), point.y }, AmLine(8) + 1, col); + } break; + case Direction::South: { + const Point point { base.x, base.y + AmLine(16) }; + DrawVerticalLine(out, { point.x, point.y - AmLine(16) }, AmLine(16), col); + DrawMapLineSteepSW(out, { point.x + AmLine(4), point.y - 2 * AmLine(4) }, AmLine(4), col); + DrawMapLineSteepSE(out, { point.x - AmLine(4), point.y - 2 * AmLine(4) }, AmLine(4), col); + } break; + case Direction::SouthWest: { + const Point point { base.x - AmLine(16), base.y + AmLine(8) }; + DrawMapLineSteepNE(out, point, AmLine(4), col); + DrawMapLineSW(out, { point.x + 2 * AmLine(8), point.y - AmLine(8) }, AmLine(8), col); + DrawHorizontalLine(out, point, AmLine(8) + 1, col); + } break; + case Direction::West: { + const Point point { base.x - AmLine(16), base.y }; + DrawMapLineNE(out, point, AmLine(4), col); + DrawHorizontalLine(out, point, AmLine(16) + 1, col); + DrawMapLineSE(out, point, AmLine(4), col); + } break; + case Direction::NorthWest: { + const Point point { base.x - AmLine(16), base.y - AmLine(8) }; + DrawMapLineNW(out, { point.x + 2 * AmLine(8), point.y + AmLine(8) }, AmLine(8), col); + DrawHorizontalLine(out, point, AmLine(8) + 1, col); + DrawMapLineSteepSE(out, point, AmLine(4), col); + } break; + case Direction::NoDirection: + break; + } + } else { + const Point point { base.x, base.y }; + DrawMapLineNE(out, { point.x - AmLine(8), point.y }, AmLine(8), deadCol); + DrawMapLineNW(out, { point.x + AmLine(8), point.y }, AmLine(8), deadCol); + } +} + +/* void DrawAutomapTowner(const Surface &out, const Displacement &myPlayerOffset) +{ + for (auto &towner : Towners) { + bool townerAlive = towner._tAnimLen != 1; + Point tile = towner.position; + DrawCross(out, GetAutomapScreen(towner.position.x, towner.position.y, myPlayerOffset), (townerAlive) ? MapColorsTowner : MapColorsDead); + } +}*/ + +/** + * @brief Renders an arrow on the automap, centered on and facing the direction of the towner. + */ +void DrawAutomapTowner(const Surface &out, const Displacement &myPlayerOffset) +{ + for (auto &towner : Towners) { + bool townerAlive = towner._tAnimLen != 1; + Point tile = towner.position; + + Direction townerDir; + switch (towner._ttype) { + case TOWN_BMAID: + case TOWN_DEADGUY: + case TOWN_DRUNK: + case TOWN_HEALER: + townerDir = Direction::SouthEast; + break; + case TOWN_PEGBOY: + case TOWN_STORY: + case TOWN_WITCH: + townerDir = Direction::South; + break; + case TOWN_FARMER: + case TOWN_GIRL: + case TOWN_SMITH: + case TOWN_TAVERN: + townerDir = Direction::SouthWest; + break; + default: + townerDir = Direction::NoDirection; + break; + } + + DrawAutomapArrow(out, towner, myPlayerOffset, tile, townerDir, MapColorsTowner, MapColorsDead, townerAlive); + } +} + +/** + * @brief Renders an arrow on the automap, centered on and facing the direction of the minion. + */ +void DrawAutomapMinion(const Surface &out, const Displacement &myPlayerOffset) +{ + for (int i = 0; i < MAXDUNX; i++) { + for (int j = 0; j < MAXDUNY; j++) { + MapExplorationType explorationType = static_cast(AutomapView[clamp(((i - 16) / 2), 0, DMAXX - 1)][clamp(((j - 16) / 2), 0, DMAXY - 1)]); + auto *monster = FindMonsterAtPosition({ i, j }); + if (monster == nullptr) + continue; + if ((monster->flags & (MFLAG_BERSERK | MFLAG_GOLEM)) == 0) + continue; + + int monsterColor = (monster->type().type == MT_GOLEM) ? MapColorsGolem : MapColorsBerserk; + bool monsterAlive = monster->hitPoints > 0; + Point tile = monster->position.tile; + + if (monster->position.tile == GolemHoldingCell) + return; + + if (monster->mode == MonsterMode::MoveSideways) { + tile = monster->position.future; + } + + DrawAutomapArrow(out, monster, myPlayerOffset, tile, monster->direction, monsterColor, monsterColor, monsterAlive); + } + } +} + +/** + * @brief Renders an arrow on the automap, centered on and facing the direction of the player. + */ +void DrawAutomapPlr(const Surface &out, const Displacement &myPlayerOffset, int playerId) +{ + Player &player = Players[playerId]; + bool plrAlive = player._pHitPoints > 0; + int playerColor = MapColorsPlayer + (8 * playerId) % 128; + Point tile = player.position.tile; + + if (player._pmode == PM_WALK_SIDEWAYS) { + tile = player.position.future; } + + DrawAutomapArrow(out, player, myPlayerOffset, tile, player._pdir, playerColor, MapColorsDead, plrAlive); } /** @@ -816,6 +1107,7 @@ std::unique_ptr LoadAutomapData(size_t &tileCount) } // namespace bool AutomapActive; +bool AutomapTransparent; uint8_t AutomapView[DMAXX][DMAXY]; int AutoMapScale; Displacement AutomapOffset; @@ -823,6 +1115,7 @@ Displacement AutomapOffset; void InitAutomapOnce() { AutomapActive = false; + AutomapTransparent = false; AutoMapScale = 50; } @@ -876,7 +1169,7 @@ void AutomapZoomIn() if (AutoMapScale >= 200) return; - AutoMapScale += 5; + AutoMapScale += 25; } void AutomapZoomOut() @@ -884,7 +1177,7 @@ void AutomapZoomOut() if (AutoMapScale <= 50) return; - AutoMapScale -= 5; + AutoMapScale -= 25; } void DrawAutomap(const Surface &out) @@ -973,6 +1266,21 @@ void DrawAutomap(const Surface &out) if (leveltype == DTYPE_CAVES) myPlayerOffset.deltaY += TILE_HEIGHT; + // Draw Objects + DrawAutomapObject(out, myPlayerOffset, [](Point position) { return dObject[position.x][position.y] != 0; }); + + // Draw Missiles + DrawAutomapMissile(out, myPlayerOffset); + + if (leveltype == DTYPE_TOWN) { + // Draw Towners + DrawAutomapTowner(out, myPlayerOffset); + } else { + // Draw Minions + DrawAutomapMinion(out, myPlayerOffset); + } + + // Draw Players for (size_t playerId = 0; playerId < Players.size(); playerId++) { Player &player = Players[playerId]; if (player.isOnActiveLevel() && player.plractive && !player._pLvlChanging && (&player == MyPlayer || player.friendlyMode)) { diff --git a/Source/automap.h b/Source/automap.h index b2b1cb23d37..5cf16b4c46b 100644 --- a/Source/automap.h +++ b/Source/automap.h @@ -30,6 +30,8 @@ enum MapExplorationType : uint8_t { /** Specifies whether the automap is enabled. */ extern DVL_API_FOR_TEST bool AutomapActive; +/** Specifies whether the automap is transparent. */ +extern DVL_API_FOR_TEST bool AutomapTransparent; /** Tracks the explored areas of the map. */ extern uint8_t AutomapView[DMAXX][DMAXY]; /** Specifies the scale of the automap. */ @@ -38,8 +40,8 @@ extern DVL_API_FOR_TEST Displacement AutomapOffset; inline int AmLine(int x) { - assert(x >= 4 && x <= 64); - assert((x & (x - 1)) == 0); + assert(x >= 2 && x <= 64); + //assert((x & (x - 1)) == 0); return AutoMapScale * x / 100; } diff --git a/Source/control.cpp b/Source/control.cpp index 9a40e7f3a61..e8a6a399351 100644 --- a/Source/control.cpp +++ b/Source/control.cpp @@ -991,10 +991,14 @@ void control_check_btn_press() void DoAutoMap() { - if (!AutomapActive) + if (!AutomapActive) { StartAutomap(); - else + } else if (!AutomapTransparent) { + AutomapTransparent = true; + } else { AutomapActive = false; + AutomapTransparent = false; + } } void CheckPanelInfo() diff --git a/Source/diablo.cpp b/Source/diablo.cpp index 51c3bcdad87..318e1c6e356 100644 --- a/Source/diablo.cpp +++ b/Source/diablo.cpp @@ -1760,6 +1760,7 @@ void InitKeymapActions() stream_stop(); } AutomapActive = false; + AutomapTransparent = false; CancelCurrentDiabloMsg(); gamemenu_off(); doom_close(); @@ -2228,6 +2229,7 @@ void InitPadmapActions() stream_stop(); } AutomapActive = false; + AutomapTransparent = false; CancelCurrentDiabloMsg(); gamemenu_off(); doom_close(); diff --git a/Source/engine.cpp b/Source/engine.cpp index 909733cd80e..7d4b504c250 100644 --- a/Source/engine.cpp +++ b/Source/engine.cpp @@ -163,6 +163,15 @@ void DrawHalfTransparentRectTo(const Surface &out, int sx, int sy, int width, in DrawHalfTransparentBlendedRectTo(out, sx, sy, width, height); } +void SetHalfTransparentPixel(const Surface &out, Point position, std::uint8_t col) +{ + if (out.InBounds(position)) { + uint8_t *pix = out.at(position.x, position.y); + const std::array &lookupTable = paletteTransparencyLookup[col]; + *pix = lookupTable[*pix]; + } +} + void UnsafeDrawBorder2px(const Surface &out, Rectangle rect, uint8_t color) { const size_t width = rect.size.width; diff --git a/Source/engine.h b/Source/engine.h index 6750e6c62ca..08ff4bd200c 100644 --- a/Source/engine.h +++ b/Source/engine.h @@ -117,6 +117,7 @@ void UnsafeDrawVerticalLine(const Surface &out, Point from, int height, std::uin * @param height Rectangle height */ void DrawHalfTransparentRectTo(const Surface &out, int sx, int sy, int width, int height); +void SetHalfTransparentPixel(const Surface &out, Point position, std::uint8_t col); /** * Draws a 2px inset border. diff --git a/Source/engine/render/automap_render.cpp b/Source/engine/render/automap_render.cpp index 9dc5de0484a..534caf842e8 100644 --- a/Source/engine/render/automap_render.cpp +++ b/Source/engine/render/automap_render.cpp @@ -4,6 +4,8 @@ * Line drawing routines for the automap. */ #include "engine/render/automap_render.hpp" +#include "automap.h" +#include "engine.h" #include @@ -20,36 +22,72 @@ enum class DirectionY : int8_t { NORTH = -1, }; +void SetMapPixel(const Surface &out, Point point, uint8_t color) +{ + if (!AutomapTransparent) { + out.SetPixel(point, color); + } else { + SetHalfTransparentPixel(out, point, color); + } +} + template void DrawMapLine(const Surface &out, Point from, int height, std::uint8_t colorIndex) { while (height-- > 0) { - out.SetPixel({ from.x, from.y + 1 }, 0); - out.SetPixel(from, colorIndex); + SetMapPixel(out, { from.x, from.y + 1 }, 0); + SetMapPixel(out, from, colorIndex); from.x += static_cast(DirX); - out.SetPixel({ from.x, from.y + 1 }, 0); - out.SetPixel(from, colorIndex); + SetMapPixel(out, { from.x, from.y + 1 }, 0); + SetMapPixel(out, from, colorIndex); from.x += static_cast(DirX); from.y += static_cast(DirY); } - out.SetPixel({ from.x, from.y + 1 }, 0); - out.SetPixel(from, colorIndex); + SetMapPixel(out, { from.x, from.y + 1 }, 0); + SetMapPixel(out, from, colorIndex); } template void DrawMapLineSteep(const Surface &out, Point from, int width, std::uint8_t colorIndex) { while (width-- > 0) { - out.SetPixel({ from.x, from.y + 1 }, 0); - out.SetPixel(from, colorIndex); + SetMapPixel(out, { from.x, from.y + 1 }, 0); + SetMapPixel(out, from, colorIndex); from.y += static_cast(DirY); - out.SetPixel({ from.x, from.y + 1 }, 0); - out.SetPixel(from, colorIndex); + SetMapPixel(out, { from.x, from.y + 1 }, 0); + SetMapPixel(out, from, colorIndex); from.y += static_cast(DirY); from.x += static_cast(DirX); } - out.SetPixel({ from.x, from.y + 1 }, 0); - out.SetPixel(from, colorIndex); + SetMapPixel(out, { from.x, from.y + 1 }, 0); + SetMapPixel(out, from, colorIndex); +} + +void DrawMapFreeLine(const Surface &out, Point from, Point to, uint8_t colorIndex) +{ + int dx = std::abs(to.x - from.x); + int dy = std::abs(to.y - from.y); + int sx = from.x < to.x ? 1 : -1; + int sy = from.y < to.y ? 1 : -1; + int err = dx - dy; + + while (true) { + SetMapPixel(out, from, colorIndex); + + if (from.x == to.x && from.y == to.y) { + break; + } + + int e2 = 2 * err; + if (e2 > -dy) { + err -= dy; + from.x += sx; + } + if (e2 < dx) { + err += dx; + from.y += sy; + } + } } } // namespace @@ -94,4 +132,74 @@ void DrawMapLineSteepSW(const Surface &out, Point from, int width, std::uint8_t DrawMapLineSteep(out, from, width, colorIndex); } +void DrawMapEllipse(const Surface &out, Point from, int radius, uint8_t colorIndex) +{ + const int a = radius; + const int b = radius / 2; + + int x = 0; + int y = b; + + // Initial point + SetMapPixel(out, { from.x, from.y + b }, colorIndex); + SetMapPixel(out, { from.x, from.y - b }, colorIndex); + + // Initialize the parameters + int p1 = (b * b) - (a * a * b) + (a * a) / 4; + + // Region 1 + while ((b * b * x) < (a * a * y)) { + x++; + if (p1 < 0) { + p1 += (2 * b * b * x) + (b * b); + } else { + y--; + p1 += (2 * b * b * x) - (2 * a * a * y) + (b * b); + } + + SetMapPixel(out, { from.x + x, from.y + y }, colorIndex); + SetMapPixel(out, { from.x - x, from.y + y }, colorIndex); + SetMapPixel(out, { from.x + x, from.y - y }, colorIndex); + SetMapPixel(out, { from.x - x, from.y - y }, colorIndex); + } + + // Initialize the second parameter for Region 2 + int p2 = (b * b * ((x + 1) * (x + 1))) + (a * a * ((y - 1) * (y - 1))) - (a * a * b * b); + + // Region 2 + while (y > 0) { + y--; + if (p2 > 0) { + p2 += (-2 * a * a * y) + (a * a); + } else { + x++; + p2 += (2 * b * b * x) - (2 * a * a * y) + (a * a); + } + + SetMapPixel(out, { from.x + x, from.y + y }, colorIndex); + SetMapPixel(out, { from.x - x, from.y + y }, colorIndex); + SetMapPixel(out, { from.x + x, from.y - y }, colorIndex); + SetMapPixel(out, { from.x - x, from.y - y }, colorIndex); + } +} + +void DrawMapStar(const Surface &out, Point center, int radius, uint8_t color) +{ + const int scaleFactor = 128; + Point anchors[5]; + + anchors[0] = { center.x - (121 * radius / scaleFactor), center.y + (19 * radius / scaleFactor) }; // Left Point + anchors[1] = { center.x + (121 * radius / scaleFactor), center.y + (19 * radius / scaleFactor) }; // Right Point + anchors[2] = { center.x, center.y + (64 * radius / scaleFactor) }; // Bottom Point + anchors[3] = { center.x - (75 * radius / scaleFactor), center.y - (51 * radius / scaleFactor) }; // Top Left Point + anchors[4] = { center.x + (75 * radius / scaleFactor), center.y - (51 * radius / scaleFactor) }; // Top Right Point + + // Draw lines between the anchors to form a star + DrawMapFreeLine(out, anchors[3], anchors[1], color); // Connect Top Left -> Right + DrawMapFreeLine(out, anchors[1], anchors[0], color); // Connect Right -> Left + DrawMapFreeLine(out, anchors[0], anchors[4], color); // Connect Left -> Top Right + DrawMapFreeLine(out, anchors[4], anchors[2], color); // Connect Top Right -> Bottom + DrawMapFreeLine(out, anchors[2], anchors[3], color); // Connect Bottom -> Top Left +} + } // namespace devilution diff --git a/Source/engine/render/automap_render.hpp b/Source/engine/render/automap_render.hpp index df342eac78e..b45ee6ed4c1 100644 --- a/Source/engine/render/automap_render.hpp +++ b/Source/engine/render/automap_render.hpp @@ -88,5 +88,7 @@ void DrawMapLineSteepNW(const Surface &out, Point from, int width, std::uint8_t * The end point is at `{ from.x - (width + 1), from.y + 2 * width }`. */ void DrawMapLineSteepSW(const Surface &out, Point from, int width, std::uint8_t colorIndex); +void DrawMapEllipse(const Surface &out, Point from, int radius, uint8_t colorIndex); +void DrawMapStar(const Surface &out, Point from, int radius, uint8_t colorIndex); } // namespace devilution From ad19f3bd34610cb35b3e009ce3ba83bfed05f01c Mon Sep 17 00:00:00 2001 From: KPhoenix Date: Tue, 29 Aug 2023 23:47:16 -0400 Subject: [PATCH 2/5] Fix Pentagram offset --- Source/automap.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Source/automap.cpp b/Source/automap.cpp index 28a014d69d8..795160b0ead 100644 --- a/Source/automap.cpp +++ b/Source/automap.cpp @@ -651,10 +651,11 @@ void DrawAutomapTile(const Surface &out, Point center, Point map) if (currlevel == Quests[Q_BETRAYER]._qlevel && map == Quests[Q_BETRAYER].position.worldToMega() + Displacement { 1, 1 }) { int pentaColor = (Quests[Q_BETRAYER]._qactive == QUEST_DONE) ? PAL8_RED + 2 : PAL16_YELLOW + 8; - DrawMapEllipse(out, center + Displacement { 0, 1 }, AmLine(64), 0); // shadow - DrawMapStar(out, center + Displacement { 0, 1 }, AmLine(64), 0); // shadow - DrawMapEllipse(out, center, AmLine(64), pentaColor); - DrawMapStar(out, center, AmLine(64), pentaColor); + Displacement pentaOffset = { 0, -(TILE_HEIGHT / 2) }; + DrawMapEllipse(out, center + Displacement { 0, 1 } + pentaOffset, AmLine(64), 0); // shadow + DrawMapStar(out, center + Displacement { 0, 1 } + pentaOffset, AmLine(64), 0); // shadow + DrawMapEllipse(out, center + pentaOffset, AmLine(64), pentaColor); + DrawMapStar(out, center + pentaOffset, AmLine(64), pentaColor); } switch (tile.type) { From 91b5e399033a71a413174b0f47c55abc1e32bd54 Mon Sep 17 00:00:00 2001 From: KPhoenix Date: Wed, 30 Aug 2023 23:19:07 -0400 Subject: [PATCH 3/5] Fix Transparency and Add Minimap --- Source/automap.cpp | 342 ++++++++++++++---------- Source/automap.h | 8 + Source/control.cpp | 6 +- Source/diablo.cpp | 2 - Source/engine/render/automap_render.cpp | 36 +-- Source/engine/render/automap_render.hpp | 1 + 6 files changed, 229 insertions(+), 166 deletions(-) diff --git a/Source/automap.cpp b/Source/automap.cpp index 795160b0ead..5239efe180c 100644 --- a/Source/automap.cpp +++ b/Source/automap.cpp @@ -118,7 +118,7 @@ struct AutomapTile { */ std::array AutomapTypeTiles; -void DrawDiamond(const Surface &out, Point center, uint8_t color) +void DrawMapDiamond(const Surface &out, Point center, uint8_t color) { const Point left { center.x - AmLine(16), center.y }; const Point top { center.x, center.y - AmLine(8) }; @@ -130,7 +130,7 @@ void DrawDiamond(const Surface &out, Point center, uint8_t color) DrawMapLineNE(out, bottom, AmLine(8), color); } -void DrawCross(const Surface &out, Point center, uint8_t color) +void DrawMapCross(const Surface &out, Point center, uint8_t color) { DrawMapLineNE(out, { center.x, center.y - AmLine(8) }, AmLine(8), color); DrawMapLineNE(out, { center.x - AmLine(32), center.y + AmLine(8) }, AmLine(8), color); @@ -151,11 +151,11 @@ void DrawMapVerticalDoor(const Surface &out, Point center, uint8_t colorBright, if (leveltype != DTYPE_CATACOMBS) { DrawMapLineNE(out, { center.x + AmLine(8), center.y - AmLine(4) }, AmLine(4), colorDim); DrawMapLineNE(out, { center.x - AmLine(16), center.y + AmLine(8) }, AmLine(4), colorDim); - DrawDiamond(out, center, colorBright); + DrawMapDiamond(out, center, colorBright); } else { DrawMapLineNE(out, { center.x - AmLine(8), center.y + AmLine(4) }, AmLine(8), colorDim); DrawMapLineNE(out, { center.x - AmLine(16), center.y + AmLine(8) }, AmLine(4), colorDim); - DrawDiamond(out, { center.x + AmLine(16), center.y - AmLine(8) }, colorBright); + DrawMapDiamond(out, { center.x + AmLine(16), center.y - AmLine(8) }, colorBright); } } @@ -164,216 +164,216 @@ void DrawMapHorizontalDoor(const Surface &out, Point center, uint8_t colorBright if (leveltype != DTYPE_CATACOMBS) { DrawMapLineSE(out, { center.x - AmLine(16), center.y - AmLine(8) }, AmLine(4), colorDim); DrawMapLineSE(out, { center.x + AmLine(8), center.y + AmLine(4) }, AmLine(4), colorDim); - DrawDiamond(out, center, colorBright); + DrawMapDiamond(out, center, colorBright); } else { DrawMapLineSE(out, { center.x - AmLine(8), center.y - AmLine(4) }, AmLine(8), colorDim); DrawMapLineSE(out, { center.x + AmLine(8), center.y + AmLine(4) }, AmLine(4), colorDim); - DrawDiamond(out, { center.x - AmLine(16), center.y - AmLine(8) }, colorBright); + DrawMapDiamond(out, { center.x - AmLine(16), center.y - AmLine(8) }, colorBright); } } void DrawDirt(const Surface &out, Point center, uint8_t color) { - out.SetPixel({ center.x + AmLine(8) - AmLine(32), center.y + AmLine(4) }, color); + SetMapPixel(out, { center.x + AmLine(8) - AmLine(32), center.y + AmLine(4) }, color); - out.SetPixel({ center.x - AmLine(16), center.y }, color); - out.SetPixel({ center.x - AmLine(16), center.y + AmLine(8) }, color); + SetMapPixel(out, { center.x - AmLine(16), center.y }, color); + SetMapPixel(out, { center.x - AmLine(16), center.y + AmLine(8) }, color); - out.SetPixel({ center.x - AmLine(8), center.y - AmLine(4) }, color); - out.SetPixel({ center.x - AmLine(8), center.y + AmLine(4) }, color); - out.SetPixel({ center.x - AmLine(8), center.y + AmLine(16) - AmLine(4) }, color); + SetMapPixel(out, { center.x - AmLine(8), center.y - AmLine(4) }, color); + SetMapPixel(out, { center.x - AmLine(8), center.y + AmLine(4) }, color); + SetMapPixel(out, { center.x - AmLine(8), center.y + AmLine(16) - AmLine(4) }, color); - out.SetPixel({ center.x, center.y - AmLine(8) }, color); - out.SetPixel(center, color); - out.SetPixel({ center.x, center.y + AmLine(8) }, color); - out.SetPixel({ center.x, center.y + AmLine(16) }, color); + SetMapPixel(out, { center.x, center.y - AmLine(8) }, color); + SetMapPixel(out, center, color); + SetMapPixel(out, { center.x, center.y + AmLine(8) }, color); + SetMapPixel(out, { center.x, center.y + AmLine(16) }, color); - out.SetPixel({ center.x + AmLine(8), center.y - AmLine(4) }, color); - out.SetPixel({ center.x + AmLine(8), center.y + AmLine(4) }, color); - out.SetPixel({ center.x + AmLine(8), center.y + AmLine(16) - AmLine(4) }, color); + SetMapPixel(out, { center.x + AmLine(8), center.y - AmLine(4) }, color); + SetMapPixel(out, { center.x + AmLine(8), center.y + AmLine(4) }, color); + SetMapPixel(out, { center.x + AmLine(8), center.y + AmLine(16) - AmLine(4) }, color); - out.SetPixel({ center.x + AmLine(16), center.y }, color); - out.SetPixel({ center.x + AmLine(16), center.y + AmLine(8) }, color); + SetMapPixel(out, { center.x + AmLine(16), center.y }, color); + SetMapPixel(out, { center.x + AmLine(16), center.y + AmLine(8) }, color); - out.SetPixel({ center.x - AmLine(8) + AmLine(32), center.y + AmLine(4) }, color); + SetMapPixel(out, { center.x - AmLine(8) + AmLine(32), center.y + AmLine(4) }, color); } void DrawBridge(const Surface &out, Point center, uint8_t color) { - out.SetPixel(center, color); + SetMapPixel(out, center, color); - out.SetPixel({ center.x + AmLine(8), center.y - AmLine(4) }, color); - out.SetPixel({ center.x + AmLine(8), center.y + AmLine(4) }, color); + SetMapPixel(out, { center.x + AmLine(8), center.y - AmLine(4) }, color); + SetMapPixel(out, { center.x + AmLine(8), center.y + AmLine(4) }, color); - out.SetPixel({ center.x + AmLine(16), center.y }, color); - out.SetPixel({ center.x + AmLine(16), center.y + AmLine(8) }, color); + SetMapPixel(out, { center.x + AmLine(16), center.y }, color); + SetMapPixel(out, { center.x + AmLine(16), center.y + AmLine(8) }, color); - out.SetPixel({ center.x - AmLine(8) + AmLine(32), center.y + AmLine(4) }, color); + SetMapPixel(out, { center.x - AmLine(8) + AmLine(32), center.y + AmLine(4) }, color); } void DrawRiverRightIn(const Surface &out, Point center, uint8_t color) { - out.SetPixel({ center.x - AmLine(16), center.y + AmLine(8) }, color); + SetMapPixel(out, { center.x - AmLine(16), center.y + AmLine(8) }, color); - out.SetPixel({ center.x - AmLine(8), center.y + AmLine(4) }, color); - out.SetPixel({ center.x - AmLine(8), center.y + AmLine(16) - AmLine(4) }, color); + SetMapPixel(out, { center.x - AmLine(8), center.y + AmLine(4) }, color); + SetMapPixel(out, { center.x - AmLine(8), center.y + AmLine(16) - AmLine(4) }, color); - out.SetPixel(center, color); - out.SetPixel({ center.x, center.y + AmLine(8) }, color); - out.SetPixel({ center.x, center.y + AmLine(16) }, color); + SetMapPixel(out, center, color); + SetMapPixel(out, { center.x, center.y + AmLine(8) }, color); + SetMapPixel(out, { center.x, center.y + AmLine(16) }, color); - out.SetPixel({ center.x + AmLine(8), center.y + AmLine(4) }, color); - out.SetPixel({ center.x + AmLine(8), center.y + AmLine(16) - AmLine(4) }, color); + SetMapPixel(out, { center.x + AmLine(8), center.y + AmLine(4) }, color); + SetMapPixel(out, { center.x + AmLine(8), center.y + AmLine(16) - AmLine(4) }, color); - out.SetPixel({ center.x + AmLine(16), center.y }, color); - out.SetPixel({ center.x + AmLine(16), center.y + AmLine(8) }, color); + SetMapPixel(out, { center.x + AmLine(16), center.y }, color); + SetMapPixel(out, { center.x + AmLine(16), center.y + AmLine(8) }, color); - out.SetPixel({ center.x - AmLine(8) + AmLine(32), center.y + AmLine(4) }, color); + SetMapPixel(out, { center.x - AmLine(8) + AmLine(32), center.y + AmLine(4) }, color); } void DrawRiverCornerSouth(const Surface &out, Point center, uint8_t color) { - out.SetPixel({ center.x, center.y + AmLine(16) }, color); + SetMapPixel(out, { center.x, center.y + AmLine(16) }, color); } void DrawRiverCornerNorth(const Surface &out, Point center, uint8_t color) { - out.SetPixel({ center.x - AmLine(8), center.y - AmLine(4) }, color); - out.SetPixel({ center.x, center.y - AmLine(8) }, color); - out.SetPixel({ center.x + AmLine(8), center.y - AmLine(4) }, color); + SetMapPixel(out, { center.x - AmLine(8), center.y - AmLine(4) }, color); + SetMapPixel(out, { center.x, center.y - AmLine(8) }, color); + SetMapPixel(out, { center.x + AmLine(8), center.y - AmLine(4) }, color); } void DrawRiverLeftOut(const Surface &out, Point center, uint8_t color) { - out.SetPixel({ center.x + AmLine(8) - AmLine(32), center.y + AmLine(4) }, color); + SetMapPixel(out, { center.x + AmLine(8) - AmLine(32), center.y + AmLine(4) }, color); - out.SetPixel({ center.x - AmLine(16), center.y }, color); - out.SetPixel({ center.x - AmLine(16), center.y + AmLine(8) }, color); + SetMapPixel(out, { center.x - AmLine(16), center.y }, color); + SetMapPixel(out, { center.x - AmLine(16), center.y + AmLine(8) }, color); - out.SetPixel({ center.x - AmLine(8), center.y + AmLine(4) }, color); - out.SetPixel({ center.x - AmLine(8), center.y + AmLine(16) - AmLine(4) }, color); + SetMapPixel(out, { center.x - AmLine(8), center.y + AmLine(4) }, color); + SetMapPixel(out, { center.x - AmLine(8), center.y + AmLine(16) - AmLine(4) }, color); - out.SetPixel(center, color); - out.SetPixel({ center.x, center.y + AmLine(8) }, color); + SetMapPixel(out, center, color); + SetMapPixel(out, { center.x, center.y + AmLine(8) }, color); - out.SetPixel({ center.x + AmLine(8), center.y - AmLine(4) }, color); - out.SetPixel({ center.x + AmLine(8), center.y + AmLine(4) }, color); - out.SetPixel({ center.x + AmLine(8), center.y + AmLine(16) - AmLine(4) }, color); + SetMapPixel(out, { center.x + AmLine(8), center.y - AmLine(4) }, color); + SetMapPixel(out, { center.x + AmLine(8), center.y + AmLine(4) }, color); + SetMapPixel(out, { center.x + AmLine(8), center.y + AmLine(16) - AmLine(4) }, color); - out.SetPixel({ center.x + AmLine(16), center.y }, color); - out.SetPixel({ center.x + AmLine(16), center.y + AmLine(8) }, color); + SetMapPixel(out, { center.x + AmLine(16), center.y }, color); + SetMapPixel(out, { center.x + AmLine(16), center.y + AmLine(8) }, color); - out.SetPixel({ center.x - AmLine(8) + AmLine(32), center.y + AmLine(4) }, color); + SetMapPixel(out, { center.x - AmLine(8) + AmLine(32), center.y + AmLine(4) }, color); } void DrawRiverLeftIn(const Surface &out, Point center, uint8_t color) { - out.SetPixel({ center.x - AmLine(16), center.y }, color); - out.SetPixel({ center.x - AmLine(16), center.y + AmLine(8) }, color); + SetMapPixel(out, { center.x - AmLine(16), center.y }, color); + SetMapPixel(out, { center.x - AmLine(16), center.y + AmLine(8) }, color); - out.SetPixel({ center.x - AmLine(8), center.y - AmLine(4) }, color); - out.SetPixel({ center.x - AmLine(8), center.y + AmLine(4) }, color); - out.SetPixel({ center.x - AmLine(8), center.y + AmLine(16) - AmLine(4) }, color); + SetMapPixel(out, { center.x - AmLine(8), center.y - AmLine(4) }, color); + SetMapPixel(out, { center.x - AmLine(8), center.y + AmLine(4) }, color); + SetMapPixel(out, { center.x - AmLine(8), center.y + AmLine(16) - AmLine(4) }, color); - out.SetPixel({ center.x, center.y - AmLine(8) }, color); - out.SetPixel(center, color); - out.SetPixel({ center.x, center.y + AmLine(8) }, color); - out.SetPixel({ center.x, center.y + AmLine(16) }, color); + SetMapPixel(out, { center.x, center.y - AmLine(8) }, color); + SetMapPixel(out, center, color); + SetMapPixel(out, { center.x, center.y + AmLine(8) }, color); + SetMapPixel(out, { center.x, center.y + AmLine(16) }, color); - out.SetPixel({ center.x + AmLine(8), center.y - AmLine(4) }, color); - out.SetPixel({ center.x + AmLine(8), center.y + AmLine(4) }, color); - out.SetPixel({ center.x + AmLine(8), center.y + AmLine(16) - AmLine(4) }, color); + SetMapPixel(out, { center.x + AmLine(8), center.y - AmLine(4) }, color); + SetMapPixel(out, { center.x + AmLine(8), center.y + AmLine(4) }, color); + SetMapPixel(out, { center.x + AmLine(8), center.y + AmLine(16) - AmLine(4) }, color); } void DrawRiverCornerWest(const Surface &out, Point center, uint8_t color) { - out.SetPixel({ center.x + AmLine(8) - AmLine(32), center.y + AmLine(4) }, color); - out.SetPixel({ center.x - AmLine(16), center.y }, color); + SetMapPixel(out, { center.x + AmLine(8) - AmLine(32), center.y + AmLine(4) }, color); + SetMapPixel(out, { center.x - AmLine(16), center.y }, color); } void DrawRiverCornerEast(const Surface &out, Point center, uint8_t color) { - out.SetPixel({ center.x + AmLine(16), center.y }, color); - out.SetPixel({ center.x + AmLine(16), center.y + AmLine(8) }, color); - out.SetPixel({ center.x - AmLine(8) + AmLine(32), center.y + AmLine(4) }, color); + SetMapPixel(out, { center.x + AmLine(16), center.y }, color); + SetMapPixel(out, { center.x + AmLine(16), center.y + AmLine(8) }, color); + SetMapPixel(out, { center.x - AmLine(8) + AmLine(32), center.y + AmLine(4) }, color); } void DrawRiverRightOut(const Surface &out, Point center, uint8_t color) { - out.SetPixel({ center.x - AmLine(8), center.y + AmLine(4) }, color); - out.SetPixel({ center.x - AmLine(8), center.y + AmLine(16) - AmLine(4) }, color); + SetMapPixel(out, { center.x - AmLine(8), center.y + AmLine(4) }, color); + SetMapPixel(out, { center.x - AmLine(8), center.y + AmLine(16) - AmLine(4) }, color); - out.SetPixel(center, color); - out.SetPixel({ center.x, center.y + AmLine(8) }, color); - out.SetPixel({ center.x, center.y + AmLine(16) }, color); + SetMapPixel(out, center, color); + SetMapPixel(out, { center.x, center.y + AmLine(8) }, color); + SetMapPixel(out, { center.x, center.y + AmLine(16) }, color); - out.SetPixel({ center.x + AmLine(8), center.y - AmLine(4) }, color); - out.SetPixel({ center.x + AmLine(8), center.y + AmLine(4) }, color); - out.SetPixel({ center.x + AmLine(8), center.y + AmLine(16) - AmLine(4) }, color); + SetMapPixel(out, { center.x + AmLine(8), center.y - AmLine(4) }, color); + SetMapPixel(out, { center.x + AmLine(8), center.y + AmLine(4) }, color); + SetMapPixel(out, { center.x + AmLine(8), center.y + AmLine(16) - AmLine(4) }, color); - out.SetPixel({ center.x + AmLine(16), center.y }, color); - out.SetPixel({ center.x + AmLine(16), center.y + AmLine(8) }, color); + SetMapPixel(out, { center.x + AmLine(16), center.y }, color); + SetMapPixel(out, { center.x + AmLine(16), center.y + AmLine(8) }, color); - out.SetPixel({ center.x - AmLine(8) + AmLine(32), center.y + AmLine(4) }, color); + SetMapPixel(out, { center.x - AmLine(8) + AmLine(32), center.y + AmLine(4) }, color); } void DrawRiver(const Surface &out, Point center, uint8_t color) { - out.SetPixel({ center.x - AmLine(16), center.y + AmLine(8) }, color); + SetMapPixel(out, { center.x - AmLine(16), center.y + AmLine(8) }, color); - out.SetPixel({ center.x - AmLine(8), center.y + AmLine(4) }, color); - out.SetPixel({ center.x - AmLine(8), center.y + AmLine(16) - AmLine(4) }, color); + SetMapPixel(out, { center.x - AmLine(8), center.y + AmLine(4) }, color); + SetMapPixel(out, { center.x - AmLine(8), center.y + AmLine(16) - AmLine(4) }, color); - out.SetPixel(center, color); - out.SetPixel({ center.x, center.y + AmLine(8) }, color); - out.SetPixel({ center.x, center.y + AmLine(16) }, color); + SetMapPixel(out, center, color); + SetMapPixel(out, { center.x, center.y + AmLine(8) }, color); + SetMapPixel(out, { center.x, center.y + AmLine(16) }, color); - out.SetPixel({ center.x + AmLine(8), center.y - AmLine(4) }, color); - out.SetPixel({ center.x + AmLine(8), center.y + AmLine(4) }, color); - out.SetPixel({ center.x + AmLine(8), center.y + AmLine(16) - AmLine(4) }, color); + SetMapPixel(out, { center.x + AmLine(8), center.y - AmLine(4) }, color); + SetMapPixel(out, { center.x + AmLine(8), center.y + AmLine(4) }, color); + SetMapPixel(out, { center.x + AmLine(8), center.y + AmLine(16) - AmLine(4) }, color); - out.SetPixel({ center.x + AmLine(16), center.y }, color); - out.SetPixel({ center.x + AmLine(16), center.y + AmLine(8) }, color); + SetMapPixel(out, { center.x + AmLine(16), center.y }, color); + SetMapPixel(out, { center.x + AmLine(16), center.y + AmLine(8) }, color); - out.SetPixel({ center.x - AmLine(8) + AmLine(32), center.y + AmLine(4) }, color); + SetMapPixel(out, { center.x - AmLine(8) + AmLine(32), center.y + AmLine(4) }, color); } void DrawRiverForkIn(const Surface &out, Point center, uint8_t color) { - out.SetPixel({ center.x - AmLine(16), center.y }, color); - out.SetPixel({ center.x - AmLine(16), center.y + AmLine(8) }, color); + SetMapPixel(out, { center.x - AmLine(16), center.y }, color); + SetMapPixel(out, { center.x - AmLine(16), center.y + AmLine(8) }, color); - out.SetPixel({ center.x - AmLine(8), center.y - AmLine(4) }, color); - out.SetPixel({ center.x - AmLine(8), center.y + AmLine(4) }, color); - out.SetPixel({ center.x - AmLine(8), center.y + AmLine(16) - AmLine(4) }, color); + SetMapPixel(out, { center.x - AmLine(8), center.y - AmLine(4) }, color); + SetMapPixel(out, { center.x - AmLine(8), center.y + AmLine(4) }, color); + SetMapPixel(out, { center.x - AmLine(8), center.y + AmLine(16) - AmLine(4) }, color); - out.SetPixel({ center.x, center.y - AmLine(8) }, color); - out.SetPixel(center, color); - out.SetPixel({ center.x, center.y + AmLine(8) }, color); - out.SetPixel({ center.x, center.y + AmLine(16) }, color); + SetMapPixel(out, { center.x, center.y - AmLine(8) }, color); + SetMapPixel(out, center, color); + SetMapPixel(out, { center.x, center.y + AmLine(8) }, color); + SetMapPixel(out, { center.x, center.y + AmLine(16) }, color); - out.SetPixel({ center.x + AmLine(8), center.y - AmLine(4) }, color); - out.SetPixel({ center.x + AmLine(8), center.y + AmLine(4) }, color); - out.SetPixel({ center.x + AmLine(8), center.y + AmLine(16) - AmLine(4) }, color); + SetMapPixel(out, { center.x + AmLine(8), center.y - AmLine(4) }, color); + SetMapPixel(out, { center.x + AmLine(8), center.y + AmLine(4) }, color); + SetMapPixel(out, { center.x + AmLine(8), center.y + AmLine(16) - AmLine(4) }, color); - out.SetPixel({ center.x + AmLine(16), center.y }, color); - out.SetPixel({ center.x + AmLine(16), center.y + AmLine(8) }, color); + SetMapPixel(out, { center.x + AmLine(16), center.y }, color); + SetMapPixel(out, { center.x + AmLine(16), center.y + AmLine(8) }, color); - out.SetPixel({ center.x - AmLine(8) + AmLine(32), center.y + AmLine(4) }, color); + SetMapPixel(out, { center.x - AmLine(8) + AmLine(32), center.y + AmLine(4) }, color); } void DrawRiverForkOut(const Surface &out, Point center, uint8_t color) { - out.SetPixel({ center.x + AmLine(8) - AmLine(32), center.y + AmLine(4) }, color); + SetMapPixel(out, { center.x + AmLine(8) - AmLine(32), center.y + AmLine(4) }, color); - out.SetPixel({ center.x - AmLine(16), center.y }, color); - out.SetPixel({ center.x - AmLine(16), center.y + AmLine(8) }, color); + SetMapPixel(out, { center.x - AmLine(16), center.y }, color); + SetMapPixel(out, { center.x - AmLine(16), center.y + AmLine(8) }, color); - out.SetPixel({ center.x - AmLine(8), center.y + AmLine(16) - AmLine(4) }, color); + SetMapPixel(out, { center.x - AmLine(8), center.y + AmLine(16) - AmLine(4) }, color); - out.SetPixel({ center.x, center.y + AmLine(16) }, color); + SetMapPixel(out, { center.x, center.y + AmLine(16) }, color); - out.SetPixel({ center.x + AmLine(8), center.y + AmLine(16) - AmLine(4) }, color); + SetMapPixel(out, { center.x + AmLine(8), center.y + AmLine(16) - AmLine(4) }, color); } enum class StairsType : uint8_t { @@ -501,9 +501,9 @@ void DrawHorizontal(const Surface &out, Point center, AutomapTile tile, uint8_t } if (tile.HasFlag(AutomapTile::Flags::HorizontalGrate)) { DrawMapLineSE(out, { center.x + AmLine(16), center.y - AmLine(8) }, AmLine(8), colorDim); - DrawDiamond(out, { center.x, center.y - AmLine(8) }, colorDim); + DrawMapDiamond(out, { center.x, center.y - AmLine(8) }, colorDim); } else if (tile.HasFlag(AutomapTile::Flags::HorizontalArch)) { - DrawDiamond(out, { center.x, center.y - AmLine(8) }, colorDim); + DrawMapDiamond(out, { center.x, center.y - AmLine(8) }, colorDim); } } @@ -521,9 +521,9 @@ void DrawVertical(const Surface &out, Point center, AutomapTile tile, uint8_t co } if (tile.HasFlag(AutomapTile::Flags::VerticalGrate)) { // right-facing half-wall DrawMapLineNE(out, { center.x - AmLine(32), center.y }, AmLine(8), colorDim); - DrawDiamond(out, { center.x, center.y - AmLine(8) }, colorDim); + DrawMapDiamond(out, { center.x, center.y - AmLine(8) }, colorDim); } else if (tile.HasFlag(AutomapTile::Flags::VerticalArch)) { // window or passable column - DrawDiamond(out, { center.x, center.y - AmLine(8) }, colorDim); + DrawMapDiamond(out, { center.x, center.y - AmLine(8) }, colorDim); } } @@ -651,16 +651,15 @@ void DrawAutomapTile(const Surface &out, Point center, Point map) if (currlevel == Quests[Q_BETRAYER]._qlevel && map == Quests[Q_BETRAYER].position.worldToMega() + Displacement { 1, 1 }) { int pentaColor = (Quests[Q_BETRAYER]._qactive == QUEST_DONE) ? PAL8_RED + 2 : PAL16_YELLOW + 8; - Displacement pentaOffset = { 0, -(TILE_HEIGHT / 2) }; - DrawMapEllipse(out, center + Displacement { 0, 1 } + pentaOffset, AmLine(64), 0); // shadow - DrawMapStar(out, center + Displacement { 0, 1 } + pentaOffset, AmLine(64), 0); // shadow - DrawMapEllipse(out, center + pentaOffset, AmLine(64), pentaColor); - DrawMapStar(out, center + pentaOffset, AmLine(64), pentaColor); + DrawMapEllipse(out, center + Displacement { 0, 1 }, AmLine(64), 0); // shadow + DrawMapStar(out, center + Displacement { 0, 1 }, AmLine(64), 0); // shadow + DrawMapEllipse(out, center, AmLine(64), pentaColor); + DrawMapStar(out, center, AmLine(64), pentaColor); } switch (tile.type) { case AutomapTile::Types::Diamond: // stand-alone column or other unpassable object - DrawDiamond(out, { center.x, center.y - AmLine(8) }, colorDim); + DrawMapDiamond(out, { center.x, center.y - AmLine(8) }, colorDim); break; case AutomapTile::Types::Vertical: case AutomapTile::Types::FenceVertical: @@ -739,9 +738,21 @@ Point GetAutomapScreen(const int i, const int j, const Displacement &myPlayerOff int px = i - 2 * AutomapOffset.deltaX - ViewPosition.x; int py = j - 2 * AutomapOffset.deltaY - ViewPosition.y; + Point screenOffset { + gnScreenWidth / 2, + (gnScreenHeight - GetMainPanel().size.height) / 2 + }; + + if (AutomapMini) { + screenOffset = { + AutomapMiniRect.position.x + AutomapMiniRect.size.width / 2, + AutomapMiniRect.position.y + AutomapMiniRect.size.height / 2 + }; + } + Point screen = { - (myPlayerOffset.deltaX * AutoMapScale / 100 / 2) + (px - py) * AmLine(16) + gnScreenWidth / 2, - (myPlayerOffset.deltaY * AutoMapScale / 100 / 2) + (px + py) * AmLine(8) + (gnScreenHeight - GetMainPanel().size.height) / 2 + (myPlayerOffset.deltaX * AutoMapScale / 100 / 2) + (px - py) * AmLine(16) + screenOffset.x, + (myPlayerOffset.deltaY * AutoMapScale / 100 / 2) + (px + py) * AmLine(8) + screenOffset.y }; if (CanPanelsCoverView()) { @@ -779,7 +790,7 @@ void SearchAutomapItem(const Surface &out, const Displacement &myPlayerOffset, i if (!highlightTile({ i, j })) continue; - DrawDiamond(out, GetAutomapScreen(i, j, myPlayerOffset), MapColorsItem); + DrawMapDiamond(out, GetAutomapScreen(i, j, myPlayerOffset), MapColorsItem); } } } @@ -793,7 +804,7 @@ void DrawAutomapObject(const Surface &out, const Displacement &myPlayerOffset, t if (!highlightTile({ i, j }) || explorationType == MAP_EXP_NONE || !IsAnyOf(ObjectAtPosition({ i, j })._otype, OBJ_BLINDBOOK, OBJ_BLOODBOOK, OBJ_BOOK2R, OBJ_CRUX1, OBJ_CRUX2, OBJ_CRUX3, OBJ_L5BOOKS, OBJ_L5LEVER, OBJ_LAZSTAND, OBJ_LEVER, OBJ_MCIRCLE1, OBJ_MCIRCLE2, OBJ_MUSHPATCH, OBJ_PEDESTAL, OBJ_SIGNCHEST, OBJ_SLAINHERO, OBJ_STAND, OBJ_STORYBOOK, OBJ_SWITCHSKL, OBJ_WARARMOR, OBJ_WARWEAP)) continue; - DrawDiamond(out, GetAutomapScreen(i, j, myPlayerOffset), MapColorsObject); + DrawMapDiamond(out, GetAutomapScreen(i, j, myPlayerOffset), MapColorsObject); } } } @@ -813,7 +824,7 @@ void DrawAutomapMissile(const Surface &out, const Displacement &myPlayerOffset) if (portal == nullptr || (explorationType == MAP_EXP_NONE && portal->_mitype == MissileID::RedPortal)) continue; - DrawCross(out, GetAutomapScreen(i, j, myPlayerOffset), portal->_mitype == MissileID::TownPortal ? MapColorsPortal : MapColorsRedPortal); + DrawMapEllipse(out, GetAutomapScreen(i, j, myPlayerOffset), AmLine(16), portal->_mitype == MissileID::TownPortal ? MapColorsPortal : MapColorsRedPortal); } } } @@ -849,9 +860,21 @@ void DrawAutomapArrow(const Surface &out, const EntityType &entity, const Displa Displacement offset = GetAutomapWalkingOffset(entity); + Point screen { + gnScreenWidth / 2, + (gnScreenHeight - GetMainPanel().size.height) / 2 + }; + + if (AutomapMini) { + screen = { + AutomapMiniRect.position.x + AutomapMiniRect.size.width / 2, + AutomapMiniRect.position.y + AutomapMiniRect.size.height / 2 + }; + } + Point base = { - ((offset.deltaX + myPlayerOffset.deltaX) * AutoMapScale / 100 / 2) + (px - py) * AmLine(16) + gnScreenWidth / 2, - ((offset.deltaY + myPlayerOffset.deltaY) * AutoMapScale / 100 / 2) + (px + py) * AmLine(8) + (gnScreenHeight - GetMainPanel().size.height) / 2 + ((offset.deltaX + myPlayerOffset.deltaX) * AutoMapScale / 100 / 2) + (px - py) * AmLine(16) + screen.x, + ((offset.deltaY + myPlayerOffset.deltaY) * AutoMapScale / 100 / 2) + (px + py) * AmLine(8) + screen.y }; if (CanPanelsCoverView()) { @@ -922,15 +945,6 @@ void DrawAutomapArrow(const Surface &out, const EntityType &entity, const Displa } } -/* void DrawAutomapTowner(const Surface &out, const Displacement &myPlayerOffset) -{ - for (auto &towner : Towners) { - bool townerAlive = towner._tAnimLen != 1; - Point tile = towner.position; - DrawCross(out, GetAutomapScreen(towner.position.x, towner.position.y, myPlayerOffset), (townerAlive) ? MapColorsTowner : MapColorsDead); - } -}*/ - /** * @brief Renders an arrow on the automap, centered on and facing the direction of the towner. */ @@ -1108,16 +1122,23 @@ std::unique_ptr LoadAutomapData(size_t &tileCount) } // namespace bool AutomapActive; +bool AutomapMini; bool AutomapTransparent; uint8_t AutomapView[DMAXX][DMAXY]; int AutoMapScale; Displacement AutomapOffset; +Rectangle AutomapMiniRect {}; void InitAutomapOnce() { AutomapActive = false; - AutomapTransparent = false; + AutomapMini = false; + AutomapTransparent = true; AutoMapScale = 50; + int minimapWidth = gnScreenWidth / 4; + Size minimapSize { minimapWidth, minimapWidth / 2 }; + int minimapPadding = 16; + AutomapMiniRect = Rectangle { { gnScreenWidth - minimapPadding - minimapSize.width, minimapPadding }, minimapSize }; } void InitAutomap() @@ -1139,6 +1160,22 @@ void StartAutomap() { AutomapOffset = { 0, 0 }; AutomapActive = true; + AutoMapScale = 50; +} + +void StartMinimap() +{ + AutomapOffset = { 0, 0 }; + AutomapMini = true; + if (gnScreenHeight >= 0 && gnScreenHeight < 960) + AutoMapScale = 25; + else if (gnScreenHeight >= 960 && gnScreenHeight < 1440) + AutoMapScale = 50; + else if (gnScreenHeight >= 1440 && gnScreenHeight < 1920) + AutoMapScale = 75; + else + AutoMapScale = 100; + } void AutomapUp() @@ -1167,7 +1204,7 @@ void AutomapRight() void AutomapZoomIn() { - if (AutoMapScale >= 200) + if (AutoMapScale >= 400) return; AutoMapScale += 25; @@ -1175,7 +1212,7 @@ void AutomapZoomIn() void AutomapZoomOut() { - if (AutoMapScale <= 50) + if (AutoMapScale <= 25) return; AutoMapScale -= 25; @@ -1184,6 +1221,7 @@ void AutomapZoomOut() void DrawAutomap(const Surface &out) { Automap = { (ViewPosition.x - 8) / 2, (ViewPosition.y - 8) / 2 }; + if (leveltype != DTYPE_TOWN) { Automap += { -4, -4 }; } @@ -1218,6 +1256,18 @@ void DrawAutomap(const Surface &out) gnScreenWidth / 2, (gnScreenHeight - GetMainPanel().size.height) / 2 }; + + if (AutomapMini) { + screen = { + AutomapMiniRect.position.x + AutomapMiniRect.size.width / 2, + AutomapMiniRect.position.y + AutomapMiniRect.size.height / 2 + }; + DrawHorizontalLine(out, AutomapMiniRect.position + Displacement { -1, -1 }, AutomapMiniRect.size.width + 2, MapColorsDim); + DrawHorizontalLine(out, AutomapMiniRect.position + Displacement { -1, AutomapMiniRect.size.height }, AutomapMiniRect.size.width + 2, MapColorsDim); + DrawVerticalLine(out, AutomapMiniRect.position + Displacement { -1, 0 }, AutomapMiniRect.size.height, MapColorsDim); + DrawVerticalLine(out, AutomapMiniRect.position + Displacement { AutomapMiniRect.size.width, 0 }, AutomapMiniRect.size.height, MapColorsDim); + } + if ((cells & 1) != 0) { screen.x -= AmLine(64) * ((cells - 1) / 2); screen.y -= AmLine(32) * ((cells + 1) / 2); diff --git a/Source/automap.h b/Source/automap.h index 5cf16b4c46b..f8f171c1af9 100644 --- a/Source/automap.h +++ b/Source/automap.h @@ -30,6 +30,8 @@ enum MapExplorationType : uint8_t { /** Specifies whether the automap is enabled. */ extern DVL_API_FOR_TEST bool AutomapActive; +/** Specifies whether the automap is in minimap mode. */ +extern DVL_API_FOR_TEST bool AutomapMini; /** Specifies whether the automap is transparent. */ extern DVL_API_FOR_TEST bool AutomapTransparent; /** Tracks the explored areas of the map. */ @@ -37,6 +39,7 @@ extern uint8_t AutomapView[DMAXX][DMAXY]; /** Specifies the scale of the automap. */ extern DVL_API_FOR_TEST int AutoMapScale; extern DVL_API_FOR_TEST Displacement AutomapOffset; +extern Rectangle AutomapMiniRect; inline int AmLine(int x) { @@ -60,6 +63,11 @@ void InitAutomap(); */ void StartAutomap(); +/** + * @brief Displays the minimap. + */ +void StartMinimap(); + /** * @brief Scrolls the automap upwards. */ diff --git a/Source/control.cpp b/Source/control.cpp index e8a6a399351..542a0978565 100644 --- a/Source/control.cpp +++ b/Source/control.cpp @@ -993,11 +993,11 @@ void DoAutoMap() { if (!AutomapActive) { StartAutomap(); - } else if (!AutomapTransparent) { - AutomapTransparent = true; + } else if (!AutomapMini) { + StartMinimap(); } else { AutomapActive = false; - AutomapTransparent = false; + AutomapMini = false; } } diff --git a/Source/diablo.cpp b/Source/diablo.cpp index 318e1c6e356..51c3bcdad87 100644 --- a/Source/diablo.cpp +++ b/Source/diablo.cpp @@ -1760,7 +1760,6 @@ void InitKeymapActions() stream_stop(); } AutomapActive = false; - AutomapTransparent = false; CancelCurrentDiabloMsg(); gamemenu_off(); doom_close(); @@ -2229,7 +2228,6 @@ void InitPadmapActions() stream_stop(); } AutomapActive = false; - AutomapTransparent = false; CancelCurrentDiabloMsg(); gamemenu_off(); doom_close(); diff --git a/Source/engine/render/automap_render.cpp b/Source/engine/render/automap_render.cpp index 534caf842e8..4c176033ab9 100644 --- a/Source/engine/render/automap_render.cpp +++ b/Source/engine/render/automap_render.cpp @@ -22,15 +22,6 @@ enum class DirectionY : int8_t { NORTH = -1, }; -void SetMapPixel(const Surface &out, Point point, uint8_t color) -{ - if (!AutomapTransparent) { - out.SetPixel(point, color); - } else { - SetHalfTransparentPixel(out, point, color); - } -} - template void DrawMapLine(const Surface &out, Point from, int height, std::uint8_t colorIndex) { @@ -92,6 +83,17 @@ void DrawMapFreeLine(const Surface &out, Point from, Point to, uint8_t colorInde } // namespace +void SetMapPixel(const Surface &out, Point point, uint8_t color) +{ + if (AutomapMini && !AutomapMiniRect.contains(point)) + return; + if (!AutomapTransparent) { + out.SetPixel(point, color); + } else { + SetHalfTransparentPixel(out, point, color); + } +} + void DrawMapLineNE(const Surface &out, Point from, int height, std::uint8_t colorIndex) { DrawMapLine(out, from, height, colorIndex); @@ -134,6 +136,8 @@ void DrawMapLineSteepSW(const Surface &out, Point from, int width, std::uint8_t void DrawMapEllipse(const Surface &out, Point from, int radius, uint8_t colorIndex) { + from.y -= AmLine(8); + const int a = radius; const int b = radius / 2; @@ -183,16 +187,18 @@ void DrawMapEllipse(const Surface &out, Point from, int radius, uint8_t colorInd } } -void DrawMapStar(const Surface &out, Point center, int radius, uint8_t color) +void DrawMapStar(const Surface &out, Point from, int radius, uint8_t color) { + from.y -= AmLine(8); + const int scaleFactor = 128; Point anchors[5]; - anchors[0] = { center.x - (121 * radius / scaleFactor), center.y + (19 * radius / scaleFactor) }; // Left Point - anchors[1] = { center.x + (121 * radius / scaleFactor), center.y + (19 * radius / scaleFactor) }; // Right Point - anchors[2] = { center.x, center.y + (64 * radius / scaleFactor) }; // Bottom Point - anchors[3] = { center.x - (75 * radius / scaleFactor), center.y - (51 * radius / scaleFactor) }; // Top Left Point - anchors[4] = { center.x + (75 * radius / scaleFactor), center.y - (51 * radius / scaleFactor) }; // Top Right Point + anchors[0] = { from.x - (121 * radius / scaleFactor), from.y + (19 * radius / scaleFactor) }; // Left Point + anchors[1] = { from.x + (121 * radius / scaleFactor), from.y + (19 * radius / scaleFactor) }; // Right Point + anchors[2] = { from.x, from.y + (64 * radius / scaleFactor) }; // Bottom Point + anchors[3] = { from.x - (75 * radius / scaleFactor), from.y - (51 * radius / scaleFactor) }; // Top Left Point + anchors[4] = { from.x + (75 * radius / scaleFactor), from.y - (51 * radius / scaleFactor) }; // Top Right Point // Draw lines between the anchors to form a star DrawMapFreeLine(out, anchors[3], anchors[1], color); // Connect Top Left -> Right diff --git a/Source/engine/render/automap_render.hpp b/Source/engine/render/automap_render.hpp index b45ee6ed4c1..1b295a233d0 100644 --- a/Source/engine/render/automap_render.hpp +++ b/Source/engine/render/automap_render.hpp @@ -17,6 +17,7 @@ namespace devilution { +void SetMapPixel(const Surface &out, Point point, uint8_t color); /** * @brief Draw a line in the target buffer from the given point towards north east at an `atan(1/2)` angle. * From 42844fbad29071e2fa3cb96499c1527dc7fdfa5c Mon Sep 17 00:00:00 2001 From: KPhoenix Date: Wed, 30 Aug 2023 23:39:46 -0400 Subject: [PATCH 4/5] Adjust padding and improve minimap --- Source/automap.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Source/automap.cpp b/Source/automap.cpp index 5239efe180c..17ce4ef24c4 100644 --- a/Source/automap.cpp +++ b/Source/automap.cpp @@ -1137,7 +1137,7 @@ void InitAutomapOnce() AutoMapScale = 50; int minimapWidth = gnScreenWidth / 4; Size minimapSize { minimapWidth, minimapWidth / 2 }; - int minimapPadding = 16; + int minimapPadding = 8; AutomapMiniRect = Rectangle { { gnScreenWidth - minimapPadding - minimapSize.width, minimapPadding }, minimapSize }; } @@ -1160,6 +1160,7 @@ void StartAutomap() { AutomapOffset = { 0, 0 }; AutomapActive = true; + AutomapTransparent = true; AutoMapScale = 50; } @@ -1167,6 +1168,7 @@ void StartMinimap() { AutomapOffset = { 0, 0 }; AutomapMini = true; + AutomapTransparent = false; if (gnScreenHeight >= 0 && gnScreenHeight < 960) AutoMapScale = 25; else if (gnScreenHeight >= 960 && gnScreenHeight < 1440) @@ -1262,6 +1264,7 @@ void DrawAutomap(const Surface &out) AutomapMiniRect.position.x + AutomapMiniRect.size.width / 2, AutomapMiniRect.position.y + AutomapMiniRect.size.height / 2 }; + DrawHalfTransparentRectTo(out, AutomapMiniRect.position.x, AutomapMiniRect.position.y, AutomapMiniRect.size.width, AutomapMiniRect.size.height); DrawHorizontalLine(out, AutomapMiniRect.position + Displacement { -1, -1 }, AutomapMiniRect.size.width + 2, MapColorsDim); DrawHorizontalLine(out, AutomapMiniRect.position + Displacement { -1, AutomapMiniRect.size.height }, AutomapMiniRect.size.width + 2, MapColorsDim); DrawVerticalLine(out, AutomapMiniRect.position + Displacement { -1, 0 }, AutomapMiniRect.size.height, MapColorsDim); From 5a8186902ceab23311ceb2c0e6c85ae6c767df7a Mon Sep 17 00:00:00 2001 From: KPhoenix Date: Wed, 30 Aug 2023 23:47:47 -0400 Subject: [PATCH 5/5] clang --- Source/automap.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Source/automap.cpp b/Source/automap.cpp index 17ce4ef24c4..0ee349f02e7 100644 --- a/Source/automap.cpp +++ b/Source/automap.cpp @@ -1177,7 +1177,6 @@ void StartMinimap() AutoMapScale = 75; else AutoMapScale = 100; - } void AutomapUp()