diff --git a/CMake/Assets.cmake b/CMake/Assets.cmake index 4da83d212..7c6227ee1 100644 --- a/CMake/Assets.cmake +++ b/CMake/Assets.cmake @@ -159,6 +159,8 @@ set(devilutionx_assets gendata/cutstartw.clx levels/l1data/sklkngt.dun levels/l2data/bonechat.dun + levels/towndata/automap.dun + levels/towndata/automap.amp nlevels/l5data/cornerstone.dun nlevels/l5data/uberroom.dun ui_art/diablo.pal diff --git a/Packaging/resources/assets/levels/towndata/automap.amp b/Packaging/resources/assets/levels/towndata/automap.amp new file mode 100644 index 000000000..55a83f62d Binary files /dev/null and b/Packaging/resources/assets/levels/towndata/automap.amp differ diff --git a/Packaging/resources/assets/levels/towndata/automap.dun b/Packaging/resources/assets/levels/towndata/automap.dun new file mode 100644 index 000000000..831a1b365 Binary files /dev/null and b/Packaging/resources/assets/levels/towndata/automap.dun differ diff --git a/Source/automap.cpp b/Source/automap.cpp index 71f9badfc..2b222b16b 100644 --- a/Source/automap.cpp +++ b/Source/automap.cpp @@ -51,6 +51,18 @@ struct AutomapTile { CaveHorizontal, CaveVertical, CaveCross, + Bridg, + River, + RiverCornerEast, + RiverCornerNorth, + RiverCornerSouth, + RiverCornerWest, + RiverForkIn, + RiverForkOut, + RiverLeftIn, + RiverLeftOut, + RiverRightIn, + RiverRightOut, }; Types type; @@ -112,22 +124,206 @@ void DrawMapHorizontalDoor(const Surface &out, Point center, uint8_t colorBright void DrawDirt(const Surface &out, Point center, uint8_t color) { - out.SetPixel(center, color); + out.SetPixel({ 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); + 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); + + 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); + + 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); + + 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); +} + +void DrawBridg(const Surface &out, Point center, uint8_t color) +{ + out.SetPixel(center, 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(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); +} + +void DrawRiverRightIn(const Surface &out, Point center, uint8_t color) +{ + out.SetPixel({ 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); + + out.SetPixel(center, color); + out.SetPixel({ center.x, center.y + AmLine(8) }, color); + out.SetPixel({ 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); + + 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); +} + +void DrawRiverCornerSouth(const Surface &out, Point center, uint8_t color) +{ + out.SetPixel({ 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); +} + +void DrawRiverLeftOut(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); + out.SetPixel({ 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); + + out.SetPixel(center, color); + out.SetPixel({ 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); + 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); +} + +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); + + 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); + 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); + + 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); +} + +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); +} + +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); +} + +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); + + out.SetPixel(center, color); + out.SetPixel({ center.x, center.y + AmLine(8) }, color); + out.SetPixel({ 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); + + 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); +} + +void DrawRiver(const Surface &out, Point center, uint8_t color) +{ out.SetPixel({ 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); + + out.SetPixel(center, color); + out.SetPixel({ center.x, center.y + AmLine(8) }, color); + out.SetPixel({ 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); + + 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); +} + +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); + + 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); + + 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); + + 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); + + 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); +} + +void DrawRiverForkOut(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); + out.SetPixel({ center.x - AmLine(16), center.y + AmLine(8) }, color); + + out.SetPixel({ center.x - AmLine(8), center.y + AmLine(16) - AmLine(4) }, color); + out.SetPixel({ center.x, center.y + AmLine(16) }, color); + + out.SetPixel({ center.x + AmLine(8), center.y + AmLine(16) - AmLine(4) }, color); } void DrawStairs(const Surface &out, Point center, uint8_t color) @@ -340,6 +536,42 @@ void DrawAutomapTile(const Surface &out, Point center, Point map) case AutomapTile::Types::Corner: case AutomapTile::Types::None: break; + case AutomapTile::Types::Bridg: + DrawBridg(out, center, MapColorsItem); + break; + case AutomapTile::Types::River: + DrawRiver(out, center, MapColorsItem); + break; + case AutomapTile::Types::RiverCornerEast: + DrawRiverCornerEast(out, center, MapColorsItem); + break; + case AutomapTile::Types::RiverCornerNorth: + DrawRiverCornerNorth(out, center, MapColorsItem); + break; + case AutomapTile::Types::RiverCornerSouth: + DrawRiverCornerSouth(out, center, MapColorsItem); + break; + case AutomapTile::Types::RiverCornerWest: + DrawRiverCornerWest(out, center, MapColorsItem); + break; + case AutomapTile::Types::RiverForkIn: + DrawRiverForkIn(out, center, MapColorsItem); + break; + case AutomapTile::Types::RiverForkOut: + DrawRiverForkOut(out, center, MapColorsItem); + break; + case AutomapTile::Types::RiverLeftIn: + DrawRiverLeftIn(out, center, MapColorsItem); + break; + case AutomapTile::Types::RiverLeftOut: + DrawRiverLeftOut(out, center, MapColorsItem); + break; + case AutomapTile::Types::RiverRightIn: + DrawRiverRightIn(out, center, MapColorsItem); + break; + case AutomapTile::Types::RiverRightOut: + DrawRiverRightOut(out, center, MapColorsItem); + break; } } @@ -504,23 +736,24 @@ void DrawAutomapText(const Surface &out) return; } - if (leveltype != DTYPE_TOWN) { - std::string description; - switch (leveltype) { - case DTYPE_NEST: - description = fmt::format(fmt::runtime(_("Level: Nest {:d}")), currlevel - 16); - break; - case DTYPE_CRYPT: - description = fmt::format(fmt::runtime(_("Level: Crypt {:d}")), currlevel - 20); - break; - default: - description = fmt::format(fmt::runtime(_("Level: {:d}")), currlevel); - break; - } - - DrawString(out, description, linePosition); - linePosition.y += 15; + std::string description; + switch (leveltype) { + case DTYPE_NEST: + description = fmt::format(fmt::runtime(_("Level: Nest {:d}")), currlevel - 16); + break; + case DTYPE_CRYPT: + description = fmt::format(fmt::runtime(_("Level: Crypt {:d}")), currlevel - 20); + break; + case DTYPE_TOWN: + description = std::string(_("Town")); + break; + default: + description = fmt::format(fmt::runtime(_("Level: {:d}")), currlevel); + break; } + + DrawString(out, description, linePosition); + linePosition.y += 15; string_view difficulty; switch (sgGameInitInfo.nDifficulty) { case DIFF_NORMAL: @@ -534,13 +767,15 @@ void DrawAutomapText(const Surface &out) break; } - std::string description = fmt::format(fmt::runtime(_(/* TRANSLATORS: {:s} means: Game Difficulty. */ "Difficulty: {:s}")), difficulty); - DrawString(out, description, linePosition); + std::string difficultyString = fmt::format(fmt::runtime(_(/* TRANSLATORS: {:s} means: Game Difficulty. */ "Difficulty: {:s}")), difficulty); + DrawString(out, difficultyString, linePosition); } std::unique_ptr LoadAutomapData(size_t &tileCount) { switch (leveltype) { + case DTYPE_TOWN: + return LoadFileInMem("levels\\towndata\\automap.amp", &tileCount); case DTYPE_CATHEDRAL: return LoadFileInMem("levels\\l1data\\l1.amp", &tileCount); case DTYPE_CATACOMBS: @@ -634,12 +869,10 @@ void AutomapZoomOut() void DrawAutomap(const Surface &out) { - if (leveltype == DTYPE_TOWN) { - DrawAutomapText(out); - return; + Automap = { (ViewPosition.x - 8) / 2, (ViewPosition.y - 8) / 2 }; + if (leveltype != DTYPE_TOWN) { + Automap += { -4, -4 }; } - - Automap = { (ViewPosition.x - 16) / 2, (ViewPosition.y - 16) / 2 }; while (Automap.x + AutomapOffset.deltaX < 0) AutomapOffset.deltaX++; while (Automap.x + AutomapOffset.deltaX >= DMAXX) diff --git a/Source/control.cpp b/Source/control.cpp index 9d8576f42..a745bd3a7 100644 --- a/Source/control.cpp +++ b/Source/control.cpp @@ -713,14 +713,10 @@ void control_check_btn_press() void DoAutoMap() { - if (leveltype != DTYPE_TOWN || gbIsMultiplayer) { - if (!AutomapActive) - StartAutomap(); - else - AutomapActive = false; - } else { - InitDiabloMsg(EMSG_NO_AUTOMAP_IN_TOWN); - } + if (!AutomapActive) + StartAutomap(); + else + AutomapActive = false; } void CheckPanelInfo() diff --git a/Source/diablo.cpp b/Source/diablo.cpp index e3906616a..3fcb8df49 100644 --- a/Source/diablo.cpp +++ b/Source/diablo.cpp @@ -2202,6 +2202,9 @@ void LoadGameLevel(bool firstflag, lvl_entry lvldir) DeltaLoadLevel(); IncProgress(); + for (int x = 0; x < DMAXX; x++) + for (int y = 0; y < DMAXY; y++) + UpdateAutomapExplorer({ x, y }, MAP_EXP_SELF); } if (!gbIsMultiplayer) ResyncQuests(); diff --git a/Source/levels/town.cpp b/Source/levels/town.cpp index 8bd8f9fe7..c511d03b4 100644 --- a/Source/levels/town.cpp +++ b/Source/levels/town.cpp @@ -75,6 +75,9 @@ void FillTile(int xx, int yy, int t) */ void TownCloseHive() { + dungeon[35][27] = 18; + dungeon[36][27] = 63; + dPiece[78][60] = 0x489; dPiece[79][60] = 0x4ea; dPiece[78][61] = 0x4eb; @@ -198,14 +201,23 @@ void DrlgTPass3() FillSector("levels\\towndata\\sector3s.dun", 0, 46); FillSector("levels\\towndata\\sector4s.dun", 0, 0); + auto dunData = LoadFileInMem("levels\\towndata\\automap.dun"); + PlaceDunTiles(dunData.get(), { 0, 0 }); + if (!IsWarpOpen(DTYPE_CATACOMBS)) { + dungeon[20][7] = 10; + dungeon[20][6] = 8; FillTile(48, 20, 320); } if (!IsWarpOpen(DTYPE_CAVES)) { + dungeon[4][30] = 8; FillTile(16, 68, 332); FillTile(16, 70, 331); } if (!IsWarpOpen(DTYPE_HELL)) { + dungeon[15][35] = 7; + dungeon[16][35] = 7; + dungeon[17][35] = 7; for (int x = 36; x < 46; x++) { FillTile(x, 78, GenerateRnd(4) + 1); } @@ -249,6 +261,8 @@ bool OpensGrave(Point position) void TownOpenHive() { + dungeon[36][27] = 47; + dPiece[78][60] = 0x489; dPiece[79][60] = 0x48a; dPiece[78][61] = 0x48b; @@ -299,6 +313,9 @@ void TownOpenHive() void TownOpenGrave() { + dungeon[14][8] = 47; + dungeon[14][7] = 47; + dPiece[36][21] = 0x532; dPiece[37][21] = 0x533; dPiece[36][22] = 0x534;