Browse Source

Clean up PlaceMiniSet()

pull/4692/head
Anders Jenbo 4 years ago
parent
commit
6962fcd63e
  1. 118
      Source/drlg_l1.cpp
  2. 152
      Source/drlg_l2.cpp
  3. 102
      Source/drlg_l3.cpp
  4. 121
      Source/drlg_l4.cpp
  5. 2
      Source/gendung.cpp
  6. 2
      Source/gendung.h
  7. 60
      Source/quests.cpp
  8. 2
      Source/quests.h
  9. BIN
      test/fixtures/diablo/5-68685319.dun
  10. BIN
      test/fixtures/diablo/6-1824554527.dun
  11. BIN
      test/fixtures/diablo/7-1607627156.dun

118
Source/drlg_l1.cpp

@ -732,71 +732,68 @@ void ApplyShadowsPatterns()
} }
} }
bool PlaceMiniSet(const BYTE *miniset, int tmin, int tmax, int cx, int cy, bool setview) bool PlaceMiniSet(const BYTE *miniset, bool setview)
{ {
int sx;
int sy;
int sw = miniset[0]; int sw = miniset[0];
int sh = miniset[1]; int sh = miniset[1];
int sx = GenerateRnd(DMAXX - sw) - 1;
int sy = GenerateRnd(DMAXY - sh);
int numt = 1; for (int bailcnt = 0;; bailcnt++) {
if (tmax - tmin != 0) { if (bailcnt > 4000)
numt = GenerateRnd(tmax - tmin) + tmin; return false;
}
for (int i = 0; i < numt; i++) {
sx = GenerateRnd(DMAXX - sw);
sy = GenerateRnd(DMAXY - sh);
bool abort = false;
int found = 0;
while (!abort) { sx++;
abort = true; if (sx == DMAXX - sw) {
if (cx != -1 && sx >= cx - sw && sx <= cx + 12) { sx = 0;
sx++; sy++;
abort = false; if (sy == DMAXY - sh) {
} sy = 0;
if (cy != -1 && sy >= cy - sh && sy <= cy + 12) {
sy++;
abort = false;
} }
}
int ii = 2; if (SetPiecesRoom.Contains({ sx, sy })) {
continue;
}
for (int yy = 0; yy < sh && abort; yy++) { // Limit the position of SetPieces for compatibility with Diablo bug
for (int xx = 0; xx < sw && abort; xx++) { bool valid = true;
if (miniset[ii] != 0 && dungeon[xx + sx][sy + yy] != miniset[ii]) if (sx <= 12) {
abort = false; sx++;
if (Protected[xx + sx][sy + yy]) valid = false;
abort = false; }
ii++; if (sy <= 12) {
} sy++;
} valid = false;
}
if (!valid) {
continue;
}
if (!abort) { int ii = 2;
sx++;
if (sx == DMAXX - sw) { bool success = true;
sx = 0; for (int yy = 0; yy < sh && success; yy++) {
sy++; for (int xx = 0; xx < sw && success; xx++) {
if (sy == DMAXY - sh) { if (miniset[ii] != 0 && dungeon[xx + sx][sy + yy] != miniset[ii])
sy = 0; success = false;
} if (Protected[xx + sx][sy + yy])
} success = false;
if (++found > 4000) ii++;
return false;
} }
} }
if (success)
break;
}
int ii = sw * sh + 2; int ii = sw * sh + 2;
for (int yy = 0; yy < sh; yy++) { for (int yy = 0; yy < sh; yy++) {
for (int xx = 0; xx < sw; xx++) { for (int xx = 0; xx < sw; xx++) {
if (miniset[ii] != 0) { if (miniset[ii] != 0) {
dungeon[xx + sx][sy + yy] = miniset[ii]; dungeon[xx + sx][sy + yy] = miniset[ii];
}
ii++;
} }
ii++;
} }
} }
@ -2100,21 +2097,21 @@ bool PlaceCathedralStairs(lvl_entry entry)
// Place poison water entrance // Place poison water entrance
if (Quests[Q_PWATER].IsAvailable()) { if (Quests[Q_PWATER].IsAvailable()) {
if (!PlaceMiniSet(PWATERIN, 1, 1, 0, 0, entry == ENTRY_RTNLVL)) if (!PlaceMiniSet(PWATERIN, entry == ENTRY_RTNLVL))
success = false; success = false;
if (entry == ENTRY_RTNLVL) if (entry == ENTRY_RTNLVL)
ViewPosition += Displacement { 2, 3 }; ViewPosition += Displacement { 2, 3 };
} }
// Place stairs up // Place stairs up
if (!PlaceMiniSet(MyPlayer->pOriginalCathedral ? L5STAIRSUP : STAIRSUP, 1, 1, 0, 0, entry == ENTRY_MAIN)) { if (!PlaceMiniSet(MyPlayer->pOriginalCathedral ? L5STAIRSUP : STAIRSUP, entry == ENTRY_MAIN)) {
if (MyPlayer->pOriginalCathedral) if (MyPlayer->pOriginalCathedral)
return false; return false;
success = false; success = false;
} }
// Place stairs down // Place stairs down
if (!Quests[Q_LTBANNER].IsAvailable() && !PlaceMiniSet(STAIRSDOWN, 1, 1, 0, 0, entry == ENTRY_PREV)) if (!Quests[Q_LTBANNER].IsAvailable() && !PlaceMiniSet(STAIRSDOWN, entry == ENTRY_PREV))
success = false; success = false;
if (entry == ENTRY_PREV) { if (entry == ENTRY_PREV) {
if (Quests[Q_LTBANNER].IsAvailable()) if (Quests[Q_LTBANNER].IsAvailable())
@ -2132,14 +2129,14 @@ bool PlaceCryptStairs(lvl_entry entry)
// Place stairs up // Place stairs up
bool enteringFromAbove = entry == ENTRY_MAIN || entry == ENTRY_TWARPDN; bool enteringFromAbove = entry == ENTRY_MAIN || entry == ENTRY_TWARPDN;
if (!PlaceMiniSet(currlevel != 21 ? L5STAIRSUPHF : L5STAIRSTOWN, 1, 1, 0, 0, enteringFromAbove)) if (!PlaceMiniSet(currlevel != 21 ? L5STAIRSUPHF : L5STAIRSTOWN, enteringFromAbove))
success = false; success = false;
if (enteringFromAbove) if (enteringFromAbove)
ViewPosition.y++; ViewPosition.y++;
// Place stairs down // Place stairs down
if (currlevel != 24) { if (currlevel != 24) {
if (!PlaceMiniSet(L5STAIRSDOWN, 1, 1, 0, 0, entry == ENTRY_PREV)) if (!PlaceMiniSet(L5STAIRSDOWN, entry == ENTRY_PREV))
success = false; success = false;
if (entry == ENTRY_PREV) if (entry == ENTRY_PREV)
ViewPosition.y += 3; ViewPosition.y += 3;
@ -2257,7 +2254,12 @@ void GenerateLevel(lvl_entry entry)
} else { } else {
Substitution(); Substitution();
ApplyShadowsPatterns(); ApplyShadowsPatterns();
PlaceMiniSet(LAMPS, 5, 10, 0, 0, false);
int numt = GenerateRnd(5) + 5;
for (int i = 0; i < numt; i++) {
PlaceMiniSet(LAMPS, false);
}
FillFloor(); FillFloor();
} }
@ -2268,7 +2270,7 @@ void GenerateLevel(lvl_entry entry)
} }
DRLG_Init_Globals(); DRLG_Init_Globals();
DRLG_CheckQuests(setpc_x, setpc_y); DRLG_CheckQuests({ setpc_x, setpc_y });
} }
void Pass3() void Pass3()

152
Source/drlg_l2.cpp

@ -23,10 +23,6 @@ BYTE predungeon[DMAXX][DMAXY];
namespace { namespace {
int nSx1;
int nSy1;
int nSx2;
int nSy2;
int nRoomCnt; int nRoomCnt;
ROOMNODE RoomList[81]; ROOMNODE RoomList[81];
std::list<HALLNODE> HallList; std::list<HALLNODE> HallList;
@ -1645,61 +1641,36 @@ void ApplyShadowsPatterns()
} }
} }
bool PlaceMiniSet(const Miniset &miniset, int tmin, int tmax, int cx, int cy, bool setview) bool PlaceMiniSet(const Miniset &miniset, bool setview)
{ {
int sw = miniset.size.width; int sw = miniset.size.width;
int sh = miniset.size.height; int sh = miniset.size.height;
int sx = GenerateRnd(DMAXX - sw) - 1;
int sy = GenerateRnd(DMAXY - sh);
int numt = 1; for (int bailcnt = 0;; bailcnt++) {
if (tmax - tmin != 0) { if (bailcnt > 198)
numt = GenerateRnd(tmax - tmin) + tmin; return false;
}
sx++;
int sx = 0; if (sx == DMAXX - sw) {
int sy = 0; sx = 0;
for (int i = 0; i < numt; i++) { sy++;
sx = GenerateRnd(DMAXX - sw); if (sy == DMAXY - sh) {
sy = GenerateRnd(DMAXY - sh); sy = 0;
bool abort = false;
int bailcnt;
for (bailcnt = 0; !abort && bailcnt < 200; bailcnt++) {
abort = true;
if (sx >= nSx1 && sx <= nSx2 && sy >= nSy1 && sy <= nSy2) {
abort = false;
}
if (cx != -1 && sx >= cx - sw && sx <= cx + 12) {
sx = GenerateRnd(DMAXX - sw);
sy = GenerateRnd(DMAXY - sh);
abort = false;
}
if (cy != -1 && sy >= cy - sh && sy <= cy + 12) {
sx = GenerateRnd(DMAXX - sw);
sy = GenerateRnd(DMAXY - sh);
abort = false;
}
if (abort)
abort = miniset.matches({ sx, sy });
if (!abort) {
sx++;
if (sx == DMAXX - sw) {
sx = 0;
sy++;
if (sy == DMAXY - sh) {
sy = 0;
}
}
} }
} }
if (bailcnt >= 200) {
return false; if (SetPiecesRoom.Contains({ sx, sy })) {
continue;
} }
miniset.place({ sx, sy }); if (miniset.matches({ sx, sy }))
break;
} }
miniset.place({ sx, sy });
if (setview) { if (setview) {
ViewPosition = Point { 21, 22 } + Displacement { sx, sy } * 2; ViewPosition = Point { 21, 22 } + Displacement { sx, sy } * 2;
} }
@ -1714,7 +1685,7 @@ void PlaceMiniSetRandom(const Miniset &miniset, int rndper)
for (int sy = 0; sy < DMAXY - sh; sy++) { for (int sy = 0; sy < DMAXY - sh; sy++) {
for (int sx = 0; sx < DMAXX - sw; sx++) { for (int sx = 0; sx < DMAXX - sw; sx++) {
if (sx >= nSx1 && sx <= nSx2 && sy >= nSy1 && sy <= nSy2) if (SetPiecesRoom.Contains({ sx, sy }))
continue; continue;
if (!miniset.matches({ sx, sy })) if (!miniset.matches({ sx, sy }))
continue; continue;
@ -1958,10 +1929,7 @@ void CreateRoom(int nX1, int nY1, int nX2, int nY2, int nRDest, int nHDir, bool
DefineRoom(nRx1, nRy1, nRx2, nRy2, forceHW); DefineRoom(nRx1, nRy1, nRx2, nRy2, forceHW);
if (forceHW) { if (forceHW) {
nSx1 = nRx1 + 2; SetPiecesRoom = { { nRx1 + 2, nRy1 + 2 }, { nRx2 - nRx1 - 1, nRy2 - nRy1 - 1 } };
nSy1 = nRy1 + 2;
nSx2 = nRx2;
nSy2 = nRy2;
} }
int nRid = nRoomCnt; int nRid = nRoomCnt;
@ -2265,46 +2233,49 @@ void Substitution()
{ {
for (int y = 0; y < DMAXY; y++) { for (int y = 0; y < DMAXY; y++) {
for (int x = 0; x < DMAXX; x++) { for (int x = 0; x < DMAXX; x++) {
if ((x < nSx1 || x > nSx2) && (y < nSy1 || y > nSy2) && GenerateRnd(4) == 0) { if (SetPiecesRoom.Contains({ x, y }))
uint8_t c = BTYPESL2[dungeon[x][y]]; continue;
if (c != 0) { if (GenerateRnd(4) != 0)
int rv = GenerateRnd(16); continue;
int i = -1;
while (rv >= 0) { uint8_t c = BTYPESL2[dungeon[x][y]];
i++; if (c != 0) {
if (i == sizeof(BTYPESL2)) { int rv = GenerateRnd(16);
i = 0; int i = -1;
} while (rv >= 0) {
if (c == BTYPESL2[i]) { i++;
rv--; if (i == sizeof(BTYPESL2)) {
} i = 0;
} }
if (c == BTYPESL2[i]) {
rv--;
}
}
int j; int j;
for (j = y - 2; j < y + 2; j++) { for (j = y - 2; j < y + 2; j++) {
for (int k = x - 2; k < x + 2; k++) { for (int k = x - 2; k < x + 2; k++) {
if (dungeon[k][j] == i) { if (dungeon[k][j] == i) {
j = y + 3; j = y + 3;
k = x + 2; k = x + 2;
}
} }
} }
if (j < y + 3) { }
dungeon[x][y] = i; if (j < y + 3) {
} dungeon[x][y] = i;
} }
} }
} }
} }
} }
void SetRoom(int rx1, int ry1) void SetRoom(Point position)
{ {
int width = SDL_SwapLE16(pSetPiece[0]); int width = SDL_SwapLE16(pSetPiece[0]);
int height = SDL_SwapLE16(pSetPiece[1]); int height = SDL_SwapLE16(pSetPiece[1]);
setpc_x = rx1; setpc_x = position.x;
setpc_y = ry1; setpc_y = position.y;
setpc_w = width; setpc_w = width;
setpc_h = height; setpc_h = height;
@ -2314,10 +2285,10 @@ void SetRoom(int rx1, int ry1)
for (int i = 0; i < width; i++) { for (int i = 0; i < width; i++) {
auto tileId = static_cast<uint8_t>(SDL_SwapLE16(tileLayer[j * width + i])); auto tileId = static_cast<uint8_t>(SDL_SwapLE16(tileLayer[j * width + i]));
if (tileId != 0) { if (tileId != 0) {
dungeon[rx1 + i][ry1 + j] = tileId; dungeon[position.x + i][position.y + j] = tileId;
Protected[rx1 + i][ry1 + j] = true; Protected[position.x + i][position.y + j] = true;
} else { } else {
dungeon[rx1 + i][ry1 + j] = 3; dungeon[position.x + i][position.y + j] = 3;
} }
} }
} }
@ -2867,20 +2838,20 @@ void FixDoors()
bool PlaceStairs(lvl_entry entry) bool PlaceStairs(lvl_entry entry)
{ {
// Place stairs up // Place stairs up
if (!PlaceMiniSet(USTAIRS, 1, 1, -1, -1, entry == ENTRY_MAIN)) if (!PlaceMiniSet(USTAIRS, entry == ENTRY_MAIN))
return false; return false;
if (entry == ENTRY_MAIN) if (entry == ENTRY_MAIN)
ViewPosition.y -= 2; ViewPosition.y -= 2;
// Place stairs down // Place stairs down
if (!PlaceMiniSet(DSTAIRS, 1, 1, -1, -1, entry == ENTRY_PREV)) if (!PlaceMiniSet(DSTAIRS, entry == ENTRY_PREV))
return false; return false;
if (entry == ENTRY_PREV) if (entry == ENTRY_PREV)
ViewPosition.x--; ViewPosition.x--;
// Place town warp stairs // Place town warp stairs
if (currlevel == 5) { if (currlevel == 5) {
if (!PlaceMiniSet(WARPSTAIRS, 1, 1, -1, -1, entry == ENTRY_TWARPDN)) if (!PlaceMiniSet(WARPSTAIRS, entry == ENTRY_TWARPDN))
return false; return false;
if (entry == ENTRY_TWARPDN) if (entry == ENTRY_TWARPDN)
ViewPosition.y -= 2; ViewPosition.y -= 2;
@ -2900,7 +2871,7 @@ void GenerateLevel(lvl_entry entry)
} }
FixTilesPatterns(); FixTilesPatterns();
if (setloadflag) { if (setloadflag) {
SetRoom(nSx1, nSy1); SetRoom(SetPiecesRoom.position);
} }
FloodTransparencyValues(3); FloodTransparencyValues(3);
FixTransparency(); FixTransparency();
@ -3031,7 +3002,7 @@ void GenerateLevel(lvl_entry entry)
} }
DRLG_Init_Globals(); DRLG_Init_Globals();
DRLG_CheckQuests(nSx1, nSy1); DRLG_CheckQuests(SetPiecesRoom.position);
} }
void LoadDungeonData(const uint16_t *dunData) void LoadDungeonData(const uint16_t *dunData)
@ -3113,11 +3084,6 @@ void LoadPreL2Dungeon(const char *path)
void CreateL2Dungeon(uint32_t rseed, lvl_entry entry) void CreateL2Dungeon(uint32_t rseed, lvl_entry entry)
{ {
nSx1 = -1;
nSy1 = -1;
nSx2 = -1;
nSy2 = -1;
SetRndSeed(rseed); SetRndSeed(rseed);
dminPosition = { 16, 16 }; dminPosition = { 16, 16 };

102
Source/drlg_l3.cpp

@ -1674,73 +1674,55 @@ void PoolFix()
} }
} }
bool PlaceMiniSet(const BYTE *miniset, int tmin, int tmax, int cx, int cy, bool setview) bool PlaceMiniSet(const BYTE *miniset, bool setview)
{ {
int sw = miniset[0]; int sw = miniset[0];
int sh = miniset[1]; int sh = miniset[1];
int sx = GenerateRnd(DMAXX - sw) - 1;
int sy = GenerateRnd(DMAXY - sh);
int numt = 1; for (int bailcnt = 0;; bailcnt++) {
if (tmax - tmin != 0) { if (bailcnt > 198)
numt = GenerateRnd(tmax - tmin) + tmin; return false;
}
int sx = 0;
int sy = 0;
for (int i = 0; i < numt; i++) {
sx = GenerateRnd(DMAXX - sw);
sy = GenerateRnd(DMAXY - sh);
bool abort = false;
int bailcnt;
for (bailcnt = 0; !abort && bailcnt < 200;) {
bailcnt++;
abort = true;
if (cx != -1 && sx >= cx - sw && sx <= cx + 12) {
sx = GenerateRnd(DMAXX - sw);
sy = GenerateRnd(DMAXY - sh);
abort = false;
}
if (cy != -1 && sy >= cy - sh && sy <= cy + 12) {
sx = GenerateRnd(DMAXX - sw);
sy = GenerateRnd(DMAXY - sh);
abort = false;
}
int ii = 2;
for (int yy = 0; yy < sh && abort; yy++) {
for (int xx = 0; xx < sw && abort; xx++) {
if (miniset[ii] != 0 && dungeon[xx + sx][yy + sy] != miniset[ii])
abort = false;
if (Protected[xx + sx][yy + sy])
abort = false;
ii++;
}
}
if (!abort) { sx++;
sx++; if (sx == DMAXX - sw) {
if (sx == DMAXX - sw) { sx = 0;
sx = 0; sy++;
sy++; if (sy == DMAXY - sh) {
if (sy == DMAXY - sh) { sy = 0;
sy = 0;
}
}
} }
} }
if (bailcnt >= 200) {
return false; if (SetPiecesRoom.Contains({ sx, sy })) {
continue;
} }
int ii = sw * sh + 2;
for (int yy = 0; yy < sh; yy++) { int ii = 2;
for (int xx = 0; xx < sw; xx++) {
if (miniset[ii] != 0) { bool success = true;
dungeon[xx + sx][yy + sy] = miniset[ii]; for (int yy = 0; yy < sh && success; yy++) {
} for (int xx = 0; xx < sw && success; xx++) {
if (miniset[ii] != 0 && dungeon[xx + sx][sy + yy] != miniset[ii])
success = false;
if (Protected[xx + sx][sy + yy])
success = false;
ii++; ii++;
} }
} }
if (success)
break;
}
int ii = sw * sh + 2;
for (int yy = 0; yy < sh; yy++) {
for (int xx = 0; xx < sw; xx++) {
if (miniset[ii] != 0) {
dungeon[xx + sx][sy + yy] = miniset[ii];
}
ii++;
}
} }
if (setview) { if (setview) {
@ -2242,17 +2224,17 @@ bool Lockout()
bool PlaceCaveStairs(lvl_entry entry) bool PlaceCaveStairs(lvl_entry entry)
{ {
// Place stairs up // Place stairs up
if (!PlaceMiniSet(L3UP, 1, 1, -1, -1, entry == ENTRY_MAIN)) if (!PlaceMiniSet(L3UP, entry == ENTRY_MAIN))
return false; return false;
// Place stairs down // Place stairs down
if (!PlaceMiniSet(L3DOWN, 1, 1, -1, -1, entry == ENTRY_PREV)) if (!PlaceMiniSet(L3DOWN, entry == ENTRY_PREV))
return false; return false;
if (entry == ENTRY_PREV) if (entry == ENTRY_PREV)
ViewPosition += { 2, -2 }; ViewPosition += { 2, -2 };
// Place town warp stairs // Place town warp stairs
if (currlevel == 9 && !PlaceMiniSet(L3HOLDWARP, 1, 1, -1, -1, entry == ENTRY_TWARPDN)) if (currlevel == 9 && !PlaceMiniSet(L3HOLDWARP, entry == ENTRY_TWARPDN))
return false; return false;
return true; return true;
@ -2261,12 +2243,12 @@ bool PlaceCaveStairs(lvl_entry entry)
bool PlaceNestStairs(lvl_entry entry) bool PlaceNestStairs(lvl_entry entry)
{ {
// Place stairs up // Place stairs up
if (!PlaceMiniSet(currlevel != 17 ? L6UP : L6HOLDWARP, 1, 1, -1, -1, entry == ENTRY_MAIN || entry == ENTRY_TWARPDN)) if (!PlaceMiniSet(currlevel != 17 ? L6UP : L6HOLDWARP, entry == ENTRY_MAIN || entry == ENTRY_TWARPDN))
return false; return false;
// Place stairs down // Place stairs down
if (currlevel != 20) { if (currlevel != 20) {
if (!PlaceMiniSet(L6DOWN, 1, 1, -1, -1, entry == ENTRY_PREV)) if (!PlaceMiniSet(L6DOWN, entry == ENTRY_PREV))
return false; return false;
if (entry == ENTRY_PREV) if (entry == ENTRY_PREV)
ViewPosition += { 2, -2 }; ViewPosition += { 2, -2 };

121
Source/drlg_l4.cpp

@ -28,10 +28,6 @@ namespace {
bool hallok[20]; bool hallok[20];
int l4holdx; int l4holdx;
int l4holdy; int l4holdy;
int SP4x1;
int SP4y1;
int SP4x2;
int SP4y2;
BYTE L4dungeon[80][80]; BYTE L4dungeon[80][80];
BYTE dung[20][20]; BYTE dung[20][20];
// int dword_52A4DC; // int dword_52A4DC;
@ -168,61 +164,36 @@ void ApplyShadowsPatterns()
} }
} }
bool PlaceMiniSet(const Miniset &miniset, int tmin, int tmax, int cx, int cy, bool setview) bool PlaceMiniSet(const Miniset &miniset, bool setview)
{ {
int sx;
int sy;
int sw = miniset.size.width; int sw = miniset.size.width;
int sh = miniset.size.height; int sh = miniset.size.height;
int sx = GenerateRnd(DMAXX - sw) - 1;
int sy = GenerateRnd(DMAXY - sh);
int numt = 1; for (int bailcnt = 0;; bailcnt++) {
if (tmax - tmin != 0) { if (bailcnt > 198)
numt = GenerateRnd(tmax - tmin) + tmin; return false;
}
for (int i = 0; i < numt; i++) {
sx = GenerateRnd(DMAXX - sw);
sy = GenerateRnd(DMAXY - sh);
bool abort = false;
int bailcnt;
for (bailcnt = 0; !abort && bailcnt < 200; bailcnt++) {
abort = true;
if (sx >= SP4x1 && sx <= SP4x2 && sy >= SP4y1 && sy <= SP4y2) {
abort = false;
}
if (cx != -1 && sx >= cx - sw && sx <= cx + 12) {
sx = GenerateRnd(DMAXX - sw);
sy = GenerateRnd(DMAXY - sh);
abort = false;
}
if (cy != -1 && sy >= cy - sh && sy <= cy + 12) {
sx = GenerateRnd(DMAXX - sw);
sy = GenerateRnd(DMAXY - sh);
abort = false;
}
if (abort)
abort = miniset.matches({ sx, sy });
if (!abort) { sx++;
sx++; if (sx == DMAXX - sw) {
if (sx == DMAXX - sw) { sx = 0;
sx = 0; sy++;
sy++; if (sy == DMAXY - sh) {
if (sy == DMAXY - sh) { sy = 0;
sy = 0;
}
}
} }
} }
if (bailcnt >= 200) {
return false; if (SetPiecesRoom.Contains({ sx, sy })) {
continue;
} }
miniset.place({ sx, sy }, true); if (miniset.matches({ sx, sy }))
break;
} }
miniset.place({ sx, sy }, true);
if (currlevel == 15 && Quests[Q_BETRAYER]._qactive >= QUEST_ACTIVE) { /// Lazarus staff skip bug fixed if (currlevel == 15 && Quests[Q_BETRAYER]._qactive >= QUEST_ACTIVE) { /// Lazarus staff skip bug fixed
Quests[Q_BETRAYER].position = { sx + 1, sy + 1 }; Quests[Q_BETRAYER].position = { sx + 1, sy + 1 };
} }
@ -264,7 +235,7 @@ void InitDungeonFlags()
} }
} }
void SetRoom(const uint16_t *dunData, int rx1, int ry1) void SetRoom(const uint16_t *dunData, Point position)
{ {
int width = SDL_SwapLE16(dunData[0]); int width = SDL_SwapLE16(dunData[0]);
int height = SDL_SwapLE16(dunData[1]); int height = SDL_SwapLE16(dunData[1]);
@ -275,10 +246,10 @@ void SetRoom(const uint16_t *dunData, int rx1, int ry1)
for (int i = 0; i < width; i++) { for (int i = 0; i < width; i++) {
auto tileId = static_cast<uint8_t>(SDL_SwapLE16(tileLayer[j * width + i])); auto tileId = static_cast<uint8_t>(SDL_SwapLE16(tileLayer[j * width + i]));
if (tileId != 0) { if (tileId != 0) {
dungeon[i + rx1][j + ry1] = tileId; dungeon[position.x + i][position.y + j] = tileId;
Protected[i + rx1][j + ry1] = true; Protected[position.x + i][position.y + j] = true;
} else { } else {
dungeon[i + rx1][j + ry1] = 6; dungeon[position.x + i][position.y + j] = 6;
} }
} }
} }
@ -402,29 +373,23 @@ void FirstRoom()
l4holdy = y; l4holdy = y;
} }
if (Quests[Q_WARLORD].IsAvailable() || (currlevel == Quests[Q_BETRAYER]._qlevel && gbIsMultiplayer)) { if (Quests[Q_WARLORD].IsAvailable() || (currlevel == Quests[Q_BETRAYER]._qlevel && gbIsMultiplayer)) {
SP4x1 = x + 1; SetPiecesRoom = { { x + 1, y + 1 }, { w + 1, h + 1 } };
SP4y1 = y + 1;
SP4x2 = SP4x1 + w;
SP4y2 = SP4y1 + h;
} else { } else {
SP4x1 = 0; SetPiecesRoom = {};
SP4y1 = 0;
SP4x2 = 0;
SP4y2 = 0;
} }
MapRoom(x, y, w, h); MapRoom(x, y, w, h);
GenerateRoom(x, y, w, h, GenerateRnd(2)); GenerateRoom(x, y, w, h, GenerateRnd(2));
} }
void SetSetPiecesRoom(int rx1, int ry1) void SetSetPiecesRoom(Point position)
{ {
setpc_x = rx1; setpc_x = position.x;
setpc_y = ry1; setpc_y = position.y;
setpc_w = SDL_SwapLE16(pSetPiece[0]); setpc_w = SDL_SwapLE16(pSetPiece[0]);
setpc_h = SDL_SwapLE16(pSetPiece[1]); setpc_h = SDL_SwapLE16(pSetPiece[1]);
SetRoom(pSetPiece.get(), rx1, ry1); SetRoom(pSetPiece.get(), position);
} }
void MakeDungeon() void MakeDungeon()
@ -1145,25 +1110,25 @@ void LoadDiabQuads(bool preflag)
auto dunData = LoadFileInMem<uint16_t>("Levels\\L4Data\\diab1.DUN"); auto dunData = LoadFileInMem<uint16_t>("Levels\\L4Data\\diab1.DUN");
diabquad1x = 4 + l4holdx; diabquad1x = 4 + l4holdx;
diabquad1y = 4 + l4holdy; diabquad1y = 4 + l4holdy;
SetRoom(dunData.get(), diabquad1x, diabquad1y); SetRoom(dunData.get(), { diabquad1x, diabquad1y });
} }
{ {
auto dunData = LoadFileInMem<uint16_t>(preflag ? "Levels\\L4Data\\diab2b.DUN" : "Levels\\L4Data\\diab2a.DUN"); auto dunData = LoadFileInMem<uint16_t>(preflag ? "Levels\\L4Data\\diab2b.DUN" : "Levels\\L4Data\\diab2a.DUN");
diabquad2x = 27 - l4holdx; diabquad2x = 27 - l4holdx;
diabquad2y = 1 + l4holdy; diabquad2y = 1 + l4holdy;
SetRoom(dunData.get(), diabquad2x, diabquad2y); SetRoom(dunData.get(), { diabquad2x, diabquad2y });
} }
{ {
auto dunData = LoadFileInMem<uint16_t>(preflag ? "Levels\\L4Data\\diab3b.DUN" : "Levels\\L4Data\\diab3a.DUN"); auto dunData = LoadFileInMem<uint16_t>(preflag ? "Levels\\L4Data\\diab3b.DUN" : "Levels\\L4Data\\diab3a.DUN");
diabquad3x = 1 + l4holdx; diabquad3x = 1 + l4holdx;
diabquad3y = 27 - l4holdy; diabquad3y = 27 - l4holdy;
SetRoom(dunData.get(), diabquad3x, diabquad3y); SetRoom(dunData.get(), { diabquad3x, diabquad3y });
} }
{ {
auto dunData = LoadFileInMem<uint16_t>(preflag ? "Levels\\L4Data\\diab4b.DUN" : "Levels\\L4Data\\diab4a.DUN"); auto dunData = LoadFileInMem<uint16_t>(preflag ? "Levels\\L4Data\\diab4b.DUN" : "Levels\\L4Data\\diab4a.DUN");
diabquad4x = 28 - l4holdx; diabquad4x = 28 - l4holdx;
diabquad4y = 28 - l4holdy; diabquad4y = 28 - l4holdy;
SetRoom(dunData.get(), diabquad4x, diabquad4y); SetRoom(dunData.get(), { diabquad4x, diabquad4y });
} }
} }
@ -1286,7 +1251,7 @@ void GeneralFix()
bool PlaceStairs(lvl_entry entry) bool PlaceStairs(lvl_entry entry)
{ {
// Place stairs up // Place stairs up
if (!PlaceMiniSet(L4USTAIRS, 1, 1, -1, -1, entry == ENTRY_MAIN)) if (!PlaceMiniSet(L4USTAIRS, entry == ENTRY_MAIN))
return false; return false;
if (entry == ENTRY_MAIN) if (entry == ENTRY_MAIN)
ViewPosition.x++; ViewPosition.x++;
@ -1294,13 +1259,13 @@ bool PlaceStairs(lvl_entry entry)
if (currlevel != 15) { if (currlevel != 15) {
// Place stairs down // Place stairs down
if (currlevel != 16 && !Quests[Q_WARLORD].IsAvailable()) { if (currlevel != 16 && !Quests[Q_WARLORD].IsAvailable()) {
if (!PlaceMiniSet(L4DSTAIRS, 1, 1, -1, -1, entry == ENTRY_PREV)) if (!PlaceMiniSet(L4DSTAIRS, entry == ENTRY_PREV))
return false; return false;
} }
// Place town warp stairs // Place town warp stairs
if (currlevel == 13) { if (currlevel == 13) {
if (!PlaceMiniSet(L4TWARP, 1, 1, -1, -1, entry == ENTRY_TWARPDN)) if (!PlaceMiniSet(L4TWARP, entry == ENTRY_TWARPDN))
return false; return false;
if (entry == ENTRY_TWARPDN) if (entry == ENTRY_TWARPDN)
ViewPosition.x++; ViewPosition.x++;
@ -1308,7 +1273,7 @@ bool PlaceStairs(lvl_entry entry)
} else { } else {
// Place hell gate // Place hell gate
bool isGateOpen = gbIsMultiplayer || Quests[Q_DIABLO]._qactive == QUEST_ACTIVE; bool isGateOpen = gbIsMultiplayer || Quests[Q_DIABLO]._qactive == QUEST_ACTIVE;
if (!PlaceMiniSet(isGateOpen ? L4PENTA2 : L4PENTA, 1, 1, -1, -1, entry == ENTRY_PREV)) if (!PlaceMiniSet(isGateOpen ? L4PENTA2 : L4PENTA, entry == ENTRY_PREV))
return false; return false;
} }
@ -1346,8 +1311,8 @@ void GenerateLevel(lvl_entry entry)
SaveQuads(); SaveQuads();
} }
if (Quests[Q_WARLORD].IsAvailable() || (currlevel == Quests[Q_BETRAYER]._qlevel && gbIsMultiplayer)) { if (Quests[Q_WARLORD].IsAvailable() || (currlevel == Quests[Q_BETRAYER]._qlevel && gbIsMultiplayer)) {
for (int spi = SP4x1; spi < SP4x2; spi++) { for (int spi = SetPiecesRoom.position.x; spi < SetPiecesRoom.position.x + SetPiecesRoom.size.width - 1; spi++) {
for (int spj = SP4y1; spj < SP4y2; spj++) { for (int spj = SetPiecesRoom.position.y; spj < SetPiecesRoom.position.y + SetPiecesRoom.size.height - 1; spj++) {
Protected[spi][spj] = true; Protected[spi][spj] = true;
} }
} }
@ -1356,7 +1321,7 @@ void GenerateLevel(lvl_entry entry)
FloodTransparencyValues(6); FloodTransparencyValues(6);
FixTransparency(); FixTransparency();
if (setloadflag) { if (setloadflag) {
SetSetPiecesRoom(SP4x1, SP4y1); SetSetPiecesRoom(SetPiecesRoom.position);
} }
if (currlevel == 16) { if (currlevel == 16) {
LoadDiabQuads(true); LoadDiabQuads(true);
@ -1384,7 +1349,7 @@ void GenerateLevel(lvl_entry entry)
} }
} }
DRLG_CheckQuests(SP4x1, SP4y1); DRLG_CheckQuests(SetPiecesRoom.position);
if (currlevel == 15) { if (currlevel == 15) {
for (int j = 0; j < DMAXY; j++) { for (int j = 0; j < DMAXY; j++) {
@ -1442,7 +1407,7 @@ void LoadL4Dungeon(const char *path, int vx, int vy)
auto dunData = LoadFileInMem<uint16_t>(path); auto dunData = LoadFileInMem<uint16_t>(path);
SetRoom(dunData.get(), 0, 0); SetRoom(dunData.get(), { 0, 0 });
ViewPosition = { vx, vy }; ViewPosition = { vx, vy };
@ -1462,7 +1427,7 @@ void LoadPreL4Dungeon(const char *path)
auto dunData = LoadFileInMem<uint16_t>(path); auto dunData = LoadFileInMem<uint16_t>(path);
SetRoom(dunData.get(), 0, 0); SetRoom(dunData.get(), { 0, 0 });
} }
} // namespace devilution } // namespace devilution

2
Source/gendung.cpp

@ -23,6 +23,7 @@ namespace devilution {
uint8_t dungeon[DMAXX][DMAXY]; uint8_t dungeon[DMAXX][DMAXY];
uint8_t pdungeon[DMAXX][DMAXY]; uint8_t pdungeon[DMAXX][DMAXY];
bool Protected[DMAXX][DMAXY]; bool Protected[DMAXX][DMAXY];
Rectangle SetPiecesRoom;
int setpc_x; int setpc_x;
int setpc_y; int setpc_y;
int setpc_w; int setpc_w;
@ -527,6 +528,7 @@ void DRLG_AreaTrans(int num, BYTE *list)
void DRLG_InitSetPC() void DRLG_InitSetPC()
{ {
SetPiecesRoom = { { -1, -1 }, { -1, -1 } };
setpc_x = 0; setpc_x = 0;
setpc_y = 0; setpc_y = 0;
setpc_w = 0; setpc_w = 0;

2
Source/gendung.h

@ -11,6 +11,7 @@
#include "engine.h" #include "engine.h"
#include "engine/cel_sprite.hpp" #include "engine/cel_sprite.hpp"
#include "engine/point.hpp" #include "engine/point.hpp"
#include "engine/rectangle.hpp"
#include "scrollrt.h" #include "scrollrt.h"
#include "utils/attributes.h" #include "utils/attributes.h"
#include "utils/enum_traits.h" #include "utils/enum_traits.h"
@ -130,6 +131,7 @@ extern DVL_API_FOR_TEST uint8_t dungeon[DMAXX][DMAXY];
extern uint8_t pdungeon[DMAXX][DMAXY]; extern uint8_t pdungeon[DMAXX][DMAXY];
/** Tile that may not be overwritten by the level generator */ /** Tile that may not be overwritten by the level generator */
extern bool Protected[DMAXX][DMAXY]; extern bool Protected[DMAXX][DMAXY];
extern Rectangle SetPiecesRoom;
/** Specifies the active set level X-coordinate of the map. */ /** Specifies the active set level X-coordinate of the map. */
extern int setpc_x; extern int setpc_x;
/** Specifies the active set level Y-coordinate of the map. */ /** Specifies the active set level Y-coordinate of the map. */

60
Source/quests.cpp

@ -131,20 +131,20 @@ void DrawButcher()
DRLG_RectTrans(x + 3, y + 3, x + 10, y + 10); DRLG_RectTrans(x + 3, y + 3, x + 10, y + 10);
} }
void DrawSkelKing(quest_id q, int x, int y) void DrawSkelKing(quest_id q, Point position)
{ {
Quests[q].position = { 2 * x + 28, 2 * y + 23 }; Quests[q].position = { 2 * position.x + 28, 2 * position.y + 23 };
} }
void DrawWarLord(int x, int y) void DrawWarLord(Point position)
{ {
auto dunData = LoadFileInMem<uint16_t>("Levels\\L4Data\\Warlord2.DUN"); auto dunData = LoadFileInMem<uint16_t>("Levels\\L4Data\\Warlord2.DUN");
int width = SDL_SwapLE16(dunData[0]); int width = SDL_SwapLE16(dunData[0]);
int height = SDL_SwapLE16(dunData[1]); int height = SDL_SwapLE16(dunData[1]);
setpc_x = x; setpc_x = position.x;
setpc_y = y; setpc_y = position.y;
setpc_w = width; setpc_w = width;
setpc_h = height; setpc_h = height;
@ -153,20 +153,20 @@ void DrawWarLord(int x, int y)
for (int j = 0; j < height; j++) { for (int j = 0; j < height; j++) {
for (int i = 0; i < width; i++) { for (int i = 0; i < width; i++) {
auto tileId = static_cast<uint8_t>(SDL_SwapLE16(tileLayer[j * width + i])); auto tileId = static_cast<uint8_t>(SDL_SwapLE16(tileLayer[j * width + i]));
dungeon[x + i][y + j] = (tileId != 0) ? tileId : 6; dungeon[position.x + i][position.y + j] = (tileId != 0) ? tileId : 6;
} }
} }
} }
void DrawSChamber(quest_id q, int x, int y) void DrawSChamber(quest_id q, Point position)
{ {
auto dunData = LoadFileInMem<uint16_t>("Levels\\L2Data\\Bonestr1.DUN"); auto dunData = LoadFileInMem<uint16_t>("Levels\\L2Data\\Bonestr1.DUN");
int width = SDL_SwapLE16(dunData[0]); int width = SDL_SwapLE16(dunData[0]);
int height = SDL_SwapLE16(dunData[1]); int height = SDL_SwapLE16(dunData[1]);
setpc_x = x; setpc_x = position.x;
setpc_y = y; setpc_y = position.y;
setpc_w = width; setpc_w = width;
setpc_h = height; setpc_h = height;
@ -175,22 +175,22 @@ void DrawSChamber(quest_id q, int x, int y)
for (int j = 0; j < height; j++) { for (int j = 0; j < height; j++) {
for (int i = 0; i < width; i++) { for (int i = 0; i < width; i++) {
auto tileId = static_cast<uint8_t>(SDL_SwapLE16(tileLayer[j * width + i])); auto tileId = static_cast<uint8_t>(SDL_SwapLE16(tileLayer[j * width + i]));
dungeon[x + i][y + j] = (tileId != 0) ? tileId : 3; dungeon[position.x + i][position.y + j] = (tileId != 0) ? tileId : 3;
} }
} }
Quests[q].position = { 2 * x + 22, 2 * y + 23 }; Quests[q].position = { 2 * position.x + 22, 2 * position.y + 23 };
} }
void DrawLTBanner(int x, int y) void DrawLTBanner(Point position)
{ {
auto dunData = LoadFileInMem<uint16_t>("Levels\\L1Data\\Banner1.DUN"); auto dunData = LoadFileInMem<uint16_t>("Levels\\L1Data\\Banner1.DUN");
int width = SDL_SwapLE16(dunData[0]); int width = SDL_SwapLE16(dunData[0]);
int height = SDL_SwapLE16(dunData[1]); int height = SDL_SwapLE16(dunData[1]);
setpc_x = x; setpc_x = position.x;
setpc_y = y; setpc_y = position.y;
setpc_w = width; setpc_w = width;
setpc_h = height; setpc_h = height;
@ -200,21 +200,21 @@ void DrawLTBanner(int x, int y)
for (int i = 0; i < width; i++) { for (int i = 0; i < width; i++) {
auto tileId = static_cast<uint8_t>(SDL_SwapLE16(tileLayer[j * width + i])); auto tileId = static_cast<uint8_t>(SDL_SwapLE16(tileLayer[j * width + i]));
if (tileId != 0) { if (tileId != 0) {
pdungeon[x + i][y + j] = tileId; pdungeon[position.x + i][position.y + j] = tileId;
} }
} }
} }
} }
void DrawBlind(int x, int y) void DrawBlind(Point position)
{ {
auto dunData = LoadFileInMem<uint16_t>("Levels\\L2Data\\Blind1.DUN"); auto dunData = LoadFileInMem<uint16_t>("Levels\\L2Data\\Blind1.DUN");
int width = SDL_SwapLE16(dunData[0]); int width = SDL_SwapLE16(dunData[0]);
int height = SDL_SwapLE16(dunData[1]); int height = SDL_SwapLE16(dunData[1]);
setpc_x = x; setpc_x = position.x;
setpc_y = y; setpc_y = position.y;
setpc_w = width; setpc_w = width;
setpc_h = height; setpc_h = height;
@ -224,21 +224,21 @@ void DrawBlind(int x, int y)
for (int i = 0; i < width; i++) { for (int i = 0; i < width; i++) {
auto tileId = static_cast<uint8_t>(SDL_SwapLE16(tileLayer[j * width + i])); auto tileId = static_cast<uint8_t>(SDL_SwapLE16(tileLayer[j * width + i]));
if (tileId != 0) { if (tileId != 0) {
pdungeon[x + i][y + j] = tileId; pdungeon[position.x + i][position.y + j] = tileId;
} }
} }
} }
} }
void DrawBlood(int x, int y) void DrawBlood(Point position)
{ {
auto dunData = LoadFileInMem<uint16_t>("Levels\\L2Data\\Blood2.DUN"); auto dunData = LoadFileInMem<uint16_t>("Levels\\L2Data\\Blood2.DUN");
int width = SDL_SwapLE16(dunData[0]); int width = SDL_SwapLE16(dunData[0]);
int height = SDL_SwapLE16(dunData[1]); int height = SDL_SwapLE16(dunData[1]);
setpc_x = x; setpc_x = position.x;
setpc_y = y; setpc_y = position.y;
setpc_w = width; setpc_w = width;
setpc_h = height; setpc_h = height;
@ -248,7 +248,7 @@ void DrawBlood(int x, int y)
for (int i = 0; i < width; i++) { for (int i = 0; i < width; i++) {
auto tileId = static_cast<uint8_t>(SDL_SwapLE16(tileLayer[j * width + i])); auto tileId = static_cast<uint8_t>(SDL_SwapLE16(tileLayer[j * width + i]));
if (tileId != 0) { if (tileId != 0) {
dungeon[x + i][y + j] = tileId; dungeon[position.x + i][position.y + j] = tileId;
} }
} }
} }
@ -522,7 +522,7 @@ void CheckQuestKill(const Monster &monster, bool sendmsg)
} }
} }
void DRLG_CheckQuests(int x, int y) void DRLG_CheckQuests(Point position)
{ {
for (auto &quest : Quests) { for (auto &quest : Quests) {
if (quest.IsAvailable()) { if (quest.IsAvailable()) {
@ -531,22 +531,22 @@ void DRLG_CheckQuests(int x, int y)
DrawButcher(); DrawButcher();
break; break;
case Q_LTBANNER: case Q_LTBANNER:
DrawLTBanner(x, y); DrawLTBanner(position);
break; break;
case Q_BLIND: case Q_BLIND:
DrawBlind(x, y); DrawBlind(position);
break; break;
case Q_BLOOD: case Q_BLOOD:
DrawBlood(x, y); DrawBlood(position);
break; break;
case Q_WARLORD: case Q_WARLORD:
DrawWarLord(x, y); DrawWarLord(position);
break; break;
case Q_SKELKING: case Q_SKELKING:
DrawSkelKing(quest._qidx, x, y); DrawSkelKing(quest._qidx, position);
break; break;
case Q_SCHAMB: case Q_SCHAMB:
DrawSChamber(quest._qidx, x, y); DrawSChamber(quest._qidx, position);
break; break;
default: default:
break; break;

2
Source/quests.h

@ -91,7 +91,7 @@ void InitialiseQuestPools(uint32_t seed, Quest quests[]);
void CheckQuests(); void CheckQuests();
bool ForceQuests(); bool ForceQuests();
void CheckQuestKill(const Monster &monster, bool sendmsg); void CheckQuestKill(const Monster &monster, bool sendmsg);
void DRLG_CheckQuests(int x, int y); void DRLG_CheckQuests(Point position);
void SetReturnLvlPos(); void SetReturnLvlPos();
void GetReturnLvlPos(); void GetReturnLvlPos();
void LoadPWaterPalette(); void LoadPWaterPalette();

BIN
test/fixtures/diablo/5-68685319.dun vendored

Binary file not shown.

BIN
test/fixtures/diablo/6-1824554527.dun vendored

Binary file not shown.

BIN
test/fixtures/diablo/7-1607627156.dun vendored

Binary file not shown.
Loading…
Cancel
Save