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

152
Source/drlg_l2.cpp

@ -23,10 +23,6 @@ BYTE predungeon[DMAXX][DMAXY];
namespace {
int nSx1;
int nSy1;
int nSx2;
int nSy2;
int nRoomCnt;
ROOMNODE RoomList[81];
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 sh = miniset.size.height;
int sx = GenerateRnd(DMAXX - sw) - 1;
int sy = GenerateRnd(DMAXY - sh);
int numt = 1;
if (tmax - tmin != 0) {
numt = GenerateRnd(tmax - tmin) + tmin;
}
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 (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;
}
}
for (int bailcnt = 0;; bailcnt++) {
if (bailcnt > 198)
return false;
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) {
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 sx = 0; sx < DMAXX - sw; sx++) {
if (sx >= nSx1 && sx <= nSx2 && sy >= nSy1 && sy <= nSy2)
if (SetPiecesRoom.Contains({ sx, sy }))
continue;
if (!miniset.matches({ sx, sy }))
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);
if (forceHW) {
nSx1 = nRx1 + 2;
nSy1 = nRy1 + 2;
nSx2 = nRx2;
nSy2 = nRy2;
SetPiecesRoom = { { nRx1 + 2, nRy1 + 2 }, { nRx2 - nRx1 - 1, nRy2 - nRy1 - 1 } };
}
int nRid = nRoomCnt;
@ -2265,46 +2233,49 @@ void Substitution()
{
for (int y = 0; y < DMAXY; y++) {
for (int x = 0; x < DMAXX; x++) {
if ((x < nSx1 || x > nSx2) && (y < nSy1 || y > nSy2) && GenerateRnd(4) == 0) {
uint8_t c = BTYPESL2[dungeon[x][y]];
if (c != 0) {
int rv = GenerateRnd(16);
int i = -1;
while (rv >= 0) {
i++;
if (i == sizeof(BTYPESL2)) {
i = 0;
}
if (c == BTYPESL2[i]) {
rv--;
}
if (SetPiecesRoom.Contains({ x, y }))
continue;
if (GenerateRnd(4) != 0)
continue;
uint8_t c = BTYPESL2[dungeon[x][y]];
if (c != 0) {
int rv = GenerateRnd(16);
int i = -1;
while (rv >= 0) {
i++;
if (i == sizeof(BTYPESL2)) {
i = 0;
}
if (c == BTYPESL2[i]) {
rv--;
}
}
int j;
for (j = y - 2; j < y + 2; j++) {
for (int k = x - 2; k < x + 2; k++) {
if (dungeon[k][j] == i) {
j = y + 3;
k = x + 2;
}
int j;
for (j = y - 2; j < y + 2; j++) {
for (int k = x - 2; k < x + 2; k++) {
if (dungeon[k][j] == i) {
j = y + 3;
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 height = SDL_SwapLE16(pSetPiece[1]);
setpc_x = rx1;
setpc_y = ry1;
setpc_x = position.x;
setpc_y = position.y;
setpc_w = width;
setpc_h = height;
@ -2314,10 +2285,10 @@ void SetRoom(int rx1, int ry1)
for (int i = 0; i < width; i++) {
auto tileId = static_cast<uint8_t>(SDL_SwapLE16(tileLayer[j * width + i]));
if (tileId != 0) {
dungeon[rx1 + i][ry1 + j] = tileId;
Protected[rx1 + i][ry1 + j] = true;
dungeon[position.x + i][position.y + j] = tileId;
Protected[position.x + i][position.y + j] = true;
} 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)
{
// Place stairs up
if (!PlaceMiniSet(USTAIRS, 1, 1, -1, -1, entry == ENTRY_MAIN))
if (!PlaceMiniSet(USTAIRS, entry == ENTRY_MAIN))
return false;
if (entry == ENTRY_MAIN)
ViewPosition.y -= 2;
// Place stairs down
if (!PlaceMiniSet(DSTAIRS, 1, 1, -1, -1, entry == ENTRY_PREV))
if (!PlaceMiniSet(DSTAIRS, entry == ENTRY_PREV))
return false;
if (entry == ENTRY_PREV)
ViewPosition.x--;
// Place town warp stairs
if (currlevel == 5) {
if (!PlaceMiniSet(WARPSTAIRS, 1, 1, -1, -1, entry == ENTRY_TWARPDN))
if (!PlaceMiniSet(WARPSTAIRS, entry == ENTRY_TWARPDN))
return false;
if (entry == ENTRY_TWARPDN)
ViewPosition.y -= 2;
@ -2900,7 +2871,7 @@ void GenerateLevel(lvl_entry entry)
}
FixTilesPatterns();
if (setloadflag) {
SetRoom(nSx1, nSy1);
SetRoom(SetPiecesRoom.position);
}
FloodTransparencyValues(3);
FixTransparency();
@ -3031,7 +3002,7 @@ void GenerateLevel(lvl_entry entry)
}
DRLG_Init_Globals();
DRLG_CheckQuests(nSx1, nSy1);
DRLG_CheckQuests(SetPiecesRoom.position);
}
void LoadDungeonData(const uint16_t *dunData)
@ -3113,11 +3084,6 @@ void LoadPreL2Dungeon(const char *path)
void CreateL2Dungeon(uint32_t rseed, lvl_entry entry)
{
nSx1 = -1;
nSy1 = -1;
nSx2 = -1;
nSy2 = -1;
SetRndSeed(rseed);
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 sh = miniset[1];
int sx = GenerateRnd(DMAXX - sw) - 1;
int sy = GenerateRnd(DMAXY - sh);
int numt = 1;
if (tmax - tmin != 0) {
numt = GenerateRnd(tmax - tmin) + tmin;
}
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++;
}
}
for (int bailcnt = 0;; bailcnt++) {
if (bailcnt > 198)
return false;
if (!abort) {
sx++;
if (sx == DMAXX - sw) {
sx = 0;
sy++;
if (sy == DMAXY - sh) {
sy = 0;
}
}
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;
}
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][yy + sy] = miniset[ii];
}
int ii = 2;
bool success = true;
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++;
}
}
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) {
@ -2242,17 +2224,17 @@ bool Lockout()
bool PlaceCaveStairs(lvl_entry entry)
{
// Place stairs up
if (!PlaceMiniSet(L3UP, 1, 1, -1, -1, entry == ENTRY_MAIN))
if (!PlaceMiniSet(L3UP, entry == ENTRY_MAIN))
return false;
// Place stairs down
if (!PlaceMiniSet(L3DOWN, 1, 1, -1, -1, entry == ENTRY_PREV))
if (!PlaceMiniSet(L3DOWN, entry == ENTRY_PREV))
return false;
if (entry == ENTRY_PREV)
ViewPosition += { 2, -2 };
// 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 true;
@ -2261,12 +2243,12 @@ bool PlaceCaveStairs(lvl_entry entry)
bool PlaceNestStairs(lvl_entry entry)
{
// 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;
// Place stairs down
if (currlevel != 20) {
if (!PlaceMiniSet(L6DOWN, 1, 1, -1, -1, entry == ENTRY_PREV))
if (!PlaceMiniSet(L6DOWN, entry == ENTRY_PREV))
return false;
if (entry == ENTRY_PREV)
ViewPosition += { 2, -2 };

121
Source/drlg_l4.cpp

@ -28,10 +28,6 @@ namespace {
bool hallok[20];
int l4holdx;
int l4holdy;
int SP4x1;
int SP4y1;
int SP4x2;
int SP4y2;
BYTE L4dungeon[80][80];
BYTE dung[20][20];
// 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 sh = miniset.size.height;
int sx = GenerateRnd(DMAXX - sw) - 1;
int sy = GenerateRnd(DMAXY - sh);
int numt = 1;
if (tmax - tmin != 0) {
numt = GenerateRnd(tmax - tmin) + tmin;
}
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 });
for (int bailcnt = 0;; bailcnt++) {
if (bailcnt > 198)
return false;
if (!abort) {
sx++;
if (sx == DMAXX - sw) {
sx = 0;
sy++;
if (sy == DMAXY - sh) {
sy = 0;
}
}
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 }, 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
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 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++) {
auto tileId = static_cast<uint8_t>(SDL_SwapLE16(tileLayer[j * width + i]));
if (tileId != 0) {
dungeon[i + rx1][j + ry1] = tileId;
Protected[i + rx1][j + ry1] = true;
dungeon[position.x + i][position.y + j] = tileId;
Protected[position.x + i][position.y + j] = true;
} else {
dungeon[i + rx1][j + ry1] = 6;
dungeon[position.x + i][position.y + j] = 6;
}
}
}
@ -402,29 +373,23 @@ void FirstRoom()
l4holdy = y;
}
if (Quests[Q_WARLORD].IsAvailable() || (currlevel == Quests[Q_BETRAYER]._qlevel && gbIsMultiplayer)) {
SP4x1 = x + 1;
SP4y1 = y + 1;
SP4x2 = SP4x1 + w;
SP4y2 = SP4y1 + h;
SetPiecesRoom = { { x + 1, y + 1 }, { w + 1, h + 1 } };
} else {
SP4x1 = 0;
SP4y1 = 0;
SP4x2 = 0;
SP4y2 = 0;
SetPiecesRoom = {};
}
MapRoom(x, y, w, h);
GenerateRoom(x, y, w, h, GenerateRnd(2));
}
void SetSetPiecesRoom(int rx1, int ry1)
void SetSetPiecesRoom(Point position)
{
setpc_x = rx1;
setpc_y = ry1;
setpc_x = position.x;
setpc_y = position.y;
setpc_w = SDL_SwapLE16(pSetPiece[0]);
setpc_h = SDL_SwapLE16(pSetPiece[1]);
SetRoom(pSetPiece.get(), rx1, ry1);
SetRoom(pSetPiece.get(), position);
}
void MakeDungeon()
@ -1145,25 +1110,25 @@ void LoadDiabQuads(bool preflag)
auto dunData = LoadFileInMem<uint16_t>("Levels\\L4Data\\diab1.DUN");
diabquad1x = 4 + l4holdx;
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");
diabquad2x = 27 - l4holdx;
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");
diabquad3x = 1 + l4holdx;
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");
diabquad4x = 28 - l4holdx;
diabquad4y = 28 - l4holdy;
SetRoom(dunData.get(), diabquad4x, diabquad4y);
SetRoom(dunData.get(), { diabquad4x, diabquad4y });
}
}
@ -1286,7 +1251,7 @@ void GeneralFix()
bool PlaceStairs(lvl_entry entry)
{
// Place stairs up
if (!PlaceMiniSet(L4USTAIRS, 1, 1, -1, -1, entry == ENTRY_MAIN))
if (!PlaceMiniSet(L4USTAIRS, entry == ENTRY_MAIN))
return false;
if (entry == ENTRY_MAIN)
ViewPosition.x++;
@ -1294,13 +1259,13 @@ bool PlaceStairs(lvl_entry entry)
if (currlevel != 15) {
// Place stairs down
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;
}
// Place town warp stairs
if (currlevel == 13) {
if (!PlaceMiniSet(L4TWARP, 1, 1, -1, -1, entry == ENTRY_TWARPDN))
if (!PlaceMiniSet(L4TWARP, entry == ENTRY_TWARPDN))
return false;
if (entry == ENTRY_TWARPDN)
ViewPosition.x++;
@ -1308,7 +1273,7 @@ bool PlaceStairs(lvl_entry entry)
} else {
// Place hell gate
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;
}
@ -1346,8 +1311,8 @@ void GenerateLevel(lvl_entry entry)
SaveQuads();
}
if (Quests[Q_WARLORD].IsAvailable() || (currlevel == Quests[Q_BETRAYER]._qlevel && gbIsMultiplayer)) {
for (int spi = SP4x1; spi < SP4x2; spi++) {
for (int spj = SP4y1; spj < SP4y2; spj++) {
for (int spi = SetPiecesRoom.position.x; spi < SetPiecesRoom.position.x + SetPiecesRoom.size.width - 1; spi++) {
for (int spj = SetPiecesRoom.position.y; spj < SetPiecesRoom.position.y + SetPiecesRoom.size.height - 1; spj++) {
Protected[spi][spj] = true;
}
}
@ -1356,7 +1321,7 @@ void GenerateLevel(lvl_entry entry)
FloodTransparencyValues(6);
FixTransparency();
if (setloadflag) {
SetSetPiecesRoom(SP4x1, SP4y1);
SetSetPiecesRoom(SetPiecesRoom.position);
}
if (currlevel == 16) {
LoadDiabQuads(true);
@ -1384,7 +1349,7 @@ void GenerateLevel(lvl_entry entry)
}
}
DRLG_CheckQuests(SP4x1, SP4y1);
DRLG_CheckQuests(SetPiecesRoom.position);
if (currlevel == 15) {
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);
SetRoom(dunData.get(), 0, 0);
SetRoom(dunData.get(), { 0, 0 });
ViewPosition = { vx, vy };
@ -1462,7 +1427,7 @@ void LoadPreL4Dungeon(const char *path)
auto dunData = LoadFileInMem<uint16_t>(path);
SetRoom(dunData.get(), 0, 0);
SetRoom(dunData.get(), { 0, 0 });
}
} // namespace devilution

2
Source/gendung.cpp

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

2
Source/gendung.h

@ -11,6 +11,7 @@
#include "engine.h"
#include "engine/cel_sprite.hpp"
#include "engine/point.hpp"
#include "engine/rectangle.hpp"
#include "scrollrt.h"
#include "utils/attributes.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];
/** Tile that may not be overwritten by the level generator */
extern bool Protected[DMAXX][DMAXY];
extern Rectangle SetPiecesRoom;
/** Specifies the active set level X-coordinate of the map. */
extern int setpc_x;
/** 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);
}
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");
int width = SDL_SwapLE16(dunData[0]);
int height = SDL_SwapLE16(dunData[1]);
setpc_x = x;
setpc_y = y;
setpc_x = position.x;
setpc_y = position.y;
setpc_w = width;
setpc_h = height;
@ -153,20 +153,20 @@ void DrawWarLord(int x, int y)
for (int j = 0; j < height; j++) {
for (int i = 0; i < 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");
int width = SDL_SwapLE16(dunData[0]);
int height = SDL_SwapLE16(dunData[1]);
setpc_x = x;
setpc_y = y;
setpc_x = position.x;
setpc_y = position.y;
setpc_w = width;
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 i = 0; i < 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");
int width = SDL_SwapLE16(dunData[0]);
int height = SDL_SwapLE16(dunData[1]);
setpc_x = x;
setpc_y = y;
setpc_x = position.x;
setpc_y = position.y;
setpc_w = width;
setpc_h = height;
@ -200,21 +200,21 @@ void DrawLTBanner(int x, int y)
for (int i = 0; i < width; i++) {
auto tileId = static_cast<uint8_t>(SDL_SwapLE16(tileLayer[j * width + i]));
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");
int width = SDL_SwapLE16(dunData[0]);
int height = SDL_SwapLE16(dunData[1]);
setpc_x = x;
setpc_y = y;
setpc_x = position.x;
setpc_y = position.y;
setpc_w = width;
setpc_h = height;
@ -224,21 +224,21 @@ void DrawBlind(int x, int y)
for (int i = 0; i < width; i++) {
auto tileId = static_cast<uint8_t>(SDL_SwapLE16(tileLayer[j * width + i]));
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");
int width = SDL_SwapLE16(dunData[0]);
int height = SDL_SwapLE16(dunData[1]);
setpc_x = x;
setpc_y = y;
setpc_x = position.x;
setpc_y = position.y;
setpc_w = width;
setpc_h = height;
@ -248,7 +248,7 @@ void DrawBlood(int x, int y)
for (int i = 0; i < width; i++) {
auto tileId = static_cast<uint8_t>(SDL_SwapLE16(tileLayer[j * width + i]));
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) {
if (quest.IsAvailable()) {
@ -531,22 +531,22 @@ void DRLG_CheckQuests(int x, int y)
DrawButcher();
break;
case Q_LTBANNER:
DrawLTBanner(x, y);
DrawLTBanner(position);
break;
case Q_BLIND:
DrawBlind(x, y);
DrawBlind(position);
break;
case Q_BLOOD:
DrawBlood(x, y);
DrawBlood(position);
break;
case Q_WARLORD:
DrawWarLord(x, y);
DrawWarLord(position);
break;
case Q_SKELKING:
DrawSkelKing(quest._qidx, x, y);
DrawSkelKing(quest._qidx, position);
break;
case Q_SCHAMB:
DrawSChamber(quest._qidx, x, y);
DrawSChamber(quest._qidx, position);
break;
default:
break;

2
Source/quests.h

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