Browse Source

Unify PlaceMiniSet

pull/4698/head
Anders Jenbo 4 years ago
parent
commit
98a10d262e
  1. 115
      Source/drlg_l1.cpp
  2. 52
      Source/drlg_l2.cpp
  3. 68
      Source/drlg_l3.cpp
  4. 73
      Source/drlg_l4.cpp
  5. 8
      Source/engine/point.hpp
  6. 50
      Source/gendung.cpp
  7. 5
      Source/gendung.h
  8. 2
      Source/objects.cpp

115
Source/drlg_l1.cpp

@ -741,64 +741,6 @@ void ApplyShadowsPatterns()
}
}
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);
for (int bailcnt = 0;; bailcnt++) {
if (bailcnt > 4000)
return false;
sx++;
if (sx == DMAXX - sw) {
sx = 0;
sy++;
if (sy == DMAXY - sh) {
sy = 0;
}
}
// 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 (SetPiecesRoom.Contains({ sx, sy }))
continue;
if (miniset.matches({ sx, sy }))
break;
}
miniset.place({ sx, sy });
if (&miniset == &PWATERIN) {
int8_t t = TransVal;
TransVal = 0;
DRLG_MRectTrans(sx, sy + 2, sx + 5, sy + 4);
TransVal = t;
Quests[Q_PWATER].position = { 2 * sx + 21, 2 * sy + 22 };
}
if (setview) {
ViewPosition = Point { 19, 20 } + Displacement { sx, sy } * 2;
}
return true;
}
bool CanReplaceTile(uint8_t replace, Point tile)
{
if (replace < 84 || replace > 100) {
@ -2048,30 +1990,46 @@ void CryptFloor(int rndper)
bool PlaceCathedralStairs(lvl_entry entry)
{
bool success = true;
std::optional<Point> position;
// Place poison water entrance
if (Quests[Q_PWATER].IsAvailable()) {
if (!PlaceMiniSet(PWATERIN, entry == ENTRY_RTNLVL))
position = PlaceMiniSet(PWATERIN, 4000, true);
if (!position) {
success = false;
if (entry == ENTRY_RTNLVL)
ViewPosition += Displacement { 2, 3 };
} else {
int8_t t = TransVal;
TransVal = 0;
Point miniPosition = *position;
DRLG_MRectTrans(miniPosition.x, miniPosition.y + 2, miniPosition.x + 5, miniPosition.y + 4);
TransVal = t;
Quests[Q_PWATER].position = miniPosition.megaToWorld() + Displacement { 5, 7 };
if (entry == ENTRY_RTNLVL)
ViewPosition = Quests[Q_PWATER].position;
}
}
// Place stairs up
if (!PlaceMiniSet(MyPlayer->pOriginalCathedral ? L5STAIRSUP : STAIRSUP, entry == ENTRY_MAIN)) {
position = PlaceMiniSet(MyPlayer->pOriginalCathedral ? L5STAIRSUP : STAIRSUP, 4000, true);
if (!position) {
if (MyPlayer->pOriginalCathedral)
return false;
success = false;
} else if (entry == ENTRY_MAIN) {
ViewPosition = position->megaToWorld() + Displacement { 3, 4 };
}
// Place stairs down
if (!Quests[Q_LTBANNER].IsAvailable() && !PlaceMiniSet(STAIRSDOWN, entry == ENTRY_PREV))
success = false;
if (entry == ENTRY_PREV) {
if (Quests[Q_LTBANNER].IsAvailable())
ViewPosition = Point { 20, 28 } + Displacement { setpc_x, setpc_y } * 2;
else
ViewPosition.y--;
if (Quests[Q_LTBANNER].IsAvailable()) {
if (entry == ENTRY_PREV)
ViewPosition = Point(setpc_x, setpc_y).megaToWorld() + Displacement { 4, 12 };
} else {
position = PlaceMiniSet(STAIRSDOWN, 4000, true);
if (!position) {
success = false;
} else if (entry == ENTRY_PREV) {
ViewPosition = position->megaToWorld() + Displacement { 3, 3 };
}
}
return success;
@ -2080,20 +2038,23 @@ bool PlaceCathedralStairs(lvl_entry entry)
bool PlaceCryptStairs(lvl_entry entry)
{
bool success = true;
std::optional<Point> position;
// Place stairs up
bool enteringFromAbove = entry == ENTRY_MAIN || entry == ENTRY_TWARPDN;
if (!PlaceMiniSet(currlevel != 21 ? L5STAIRSUPHF : L5STAIRSTOWN, enteringFromAbove))
position = PlaceMiniSet(currlevel != 21 ? L5STAIRSUPHF : L5STAIRSTOWN, 4000, true);
if (!position) {
success = false;
if (enteringFromAbove)
ViewPosition.y++;
} else if (entry == ENTRY_MAIN || entry == ENTRY_TWARPDN) {
ViewPosition = position->megaToWorld() + Displacement { 3, 5 };
}
// Place stairs down
if (currlevel != 24) {
if (!PlaceMiniSet(L5STAIRSDOWN, entry == ENTRY_PREV))
position = PlaceMiniSet(L5STAIRSDOWN, 4000, true);
if (!position)
success = false;
if (entry == ENTRY_PREV)
ViewPosition.y += 3;
else if (entry == ENTRY_PREV)
ViewPosition = position->megaToWorld() + Displacement { 3, 7 };
}
return success;
@ -2211,7 +2172,7 @@ void GenerateLevel(lvl_entry entry)
int numt = GenerateRnd(5) + 5;
for (int i = 0; i < numt; i++) {
PlaceMiniSet(LAMPS, false);
PlaceMiniSet(LAMPS, 4000, true);
}
FillFloor();

52
Source/drlg_l2.cpp

@ -1571,41 +1571,6 @@ void ApplyShadowsPatterns()
}
}
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);
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 (SetPiecesRoom.Contains({ sx, sy }))
continue;
if (miniset.matches({ sx, sy }))
break;
}
miniset.place({ sx, sy });
if (setview) {
ViewPosition = Point { 21, 22 } + Displacement { sx, sy } * 2;
}
return true;
}
void PlaceMiniSetRandom(const Miniset &miniset, int rndper)
{
int sw = miniset.size.width;
@ -2772,24 +2737,29 @@ void FixDoors()
bool PlaceStairs(lvl_entry entry)
{
std::optional<Point> position;
// Place stairs up
if (!PlaceMiniSet(USTAIRS, entry == ENTRY_MAIN))
position = PlaceMiniSet(USTAIRS);
if (!position)
return false;
if (entry == ENTRY_MAIN)
ViewPosition.y -= 2;
ViewPosition = position->megaToWorld() + Displacement { 5, 4 };
// Place stairs down
if (!PlaceMiniSet(DSTAIRS, entry == ENTRY_PREV))
position = PlaceMiniSet(DSTAIRS);
if (!position)
return false;
if (entry == ENTRY_PREV)
ViewPosition.x--;
ViewPosition = position->megaToWorld() + Displacement { 4, 6 };
// Place town warp stairs
if (currlevel == 5) {
if (!PlaceMiniSet(WARPSTAIRS, entry == ENTRY_TWARPDN))
position = PlaceMiniSet(WARPSTAIRS);
if (!position)
return false;
if (entry == ENTRY_TWARPDN)
ViewPosition.y -= 2;
ViewPosition = position->megaToWorld() + Displacement { 5, 4 };
}
return true;

68
Source/drlg_l3.cpp

@ -1375,41 +1375,6 @@ bool Spawn(int x, int y, int *totarea)
return false;
}
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);
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 (SetPiecesRoom.Contains({ sx, sy }))
continue;
if (miniset.matches({ sx, sy }))
break;
}
miniset.place({ sx, sy });
if (setview) {
ViewPosition = Point { 17, 19 } + Displacement { sx, sy } * 2;
}
return true;
}
bool CanReplaceTile(uint8_t replace, Point tile)
{
if (replace < 84 || replace > 100) {
@ -2018,35 +1983,52 @@ bool Lockout()
bool PlaceCaveStairs(lvl_entry entry)
{
std::optional<Point> position;
// Place stairs up
if (!PlaceMiniSet(L3UP, entry == ENTRY_MAIN))
position = PlaceMiniSet(L3UP);
if (!position)
return false;
if (entry == ENTRY_MAIN)
ViewPosition = position->megaToWorld() + Displacement { 1, 3 };
// Place stairs down
if (!PlaceMiniSet(L3DOWN, entry == ENTRY_PREV))
position = PlaceMiniSet(L3DOWN);
if (!position)
return false;
if (entry == ENTRY_PREV)
ViewPosition += { 2, -2 };
ViewPosition = position->megaToWorld() + Displacement { 3, 1 };
// Place town warp stairs
if (currlevel == 9 && !PlaceMiniSet(L3HOLDWARP, entry == ENTRY_TWARPDN))
return false;
if (currlevel == 9) {
position = PlaceMiniSet(L3HOLDWARP);
if (!position)
return false;
if (entry == ENTRY_TWARPDN)
ViewPosition = position->megaToWorld() + Displacement { 1, 3 };
}
return true;
}
bool PlaceNestStairs(lvl_entry entry)
{
std::optional<Point> position;
// Place stairs up
if (!PlaceMiniSet(currlevel != 17 ? L6UP : L6HOLDWARP, entry == ENTRY_MAIN || entry == ENTRY_TWARPDN))
position = PlaceMiniSet(currlevel != 17 ? L6UP : L6HOLDWARP);
if (!position)
return false;
if (entry == ENTRY_MAIN || entry == ENTRY_TWARPDN)
ViewPosition = position->megaToWorld() + Displacement { 1, 3 };
// Place stairs down
if (currlevel != 20) {
if (!PlaceMiniSet(L6DOWN, entry == ENTRY_PREV))
position = PlaceMiniSet(L6DOWN);
if (!position)
return false;
if (entry == ENTRY_PREV)
ViewPosition += { 2, -2 };
ViewPosition = position->megaToWorld() + Displacement { 3, 1 };
}
return true;

73
Source/drlg_l4.cpp

@ -164,41 +164,6 @@ void ApplyShadowsPatterns()
}
}
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);
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 (SetPiecesRoom.Contains({ sx, sy }))
continue;
if (miniset.matches({ sx, sy }))
break;
}
miniset.place({ sx, sy }, true);
if (setview) {
ViewPosition = Point { 21, 22 } + Displacement { sx, sy } * 2;
}
return true;
}
void LoadQuestSetPieces()
{
setloadflag = false;
@ -1236,38 +1201,46 @@ void GeneralFix()
bool PlaceStairs(lvl_entry entry)
{
std::optional<Point> position;
// Place stairs up
if (!PlaceMiniSet(L4USTAIRS, entry == ENTRY_MAIN))
position = PlaceMiniSet(L4USTAIRS);
if (!position)
return false;
if (entry == ENTRY_MAIN)
ViewPosition.x++;
ViewPosition = position->megaToWorld() + Displacement { 6, 6 };
if (currlevel != 15) {
// Place stairs down
if (currlevel != 16 && !Quests[Q_WARLORD].IsAvailable()) {
if (!PlaceMiniSet(L4DSTAIRS, entry == ENTRY_PREV))
return false;
if (currlevel != 16) {
if (Quests[Q_WARLORD].IsAvailable()) {
if (entry == ENTRY_PREV)
ViewPosition = Point(setpc_x, setpc_y).megaToWorld() + Displacement { 6, 6 };
} else {
position = PlaceMiniSet(L4DSTAIRS);
if (!position)
return false;
if (entry == ENTRY_PREV)
ViewPosition = position->megaToWorld() + Displacement { 5, 7 };
}
}
// Place town warp stairs
if (currlevel == 13) {
if (!PlaceMiniSet(L4TWARP, entry == ENTRY_TWARPDN))
position = PlaceMiniSet(L4TWARP);
if (!position)
return false;
if (entry == ENTRY_TWARPDN)
ViewPosition.x++;
ViewPosition = position->megaToWorld() + Displacement { 6, 6 };
}
} else {
// Place hell gate
bool isGateOpen = gbIsMultiplayer || Quests[Q_DIABLO]._qactive == QUEST_ACTIVE;
if (!PlaceMiniSet(isGateOpen ? L4PENTA2 : L4PENTA, entry == ENTRY_PREV))
position = PlaceMiniSet(isGateOpen ? L4PENTA2 : L4PENTA);
if (!position)
return false;
}
if (entry == ENTRY_PREV) {
if (Quests[Q_WARLORD].IsAvailable())
ViewPosition = Point { 22, 22 } + Displacement { setpc_x, setpc_y } * 2;
else
ViewPosition.y++;
if (entry == ENTRY_PREV)
ViewPosition = position->megaToWorld() + Displacement { 5, 7 };
}
return true;

8
Source/engine/point.hpp

@ -161,6 +161,14 @@ struct Point {
return std::max<int>(offset.deltaX, offset.deltaY);
}
/**
* @brief Converte from mega tile cordinates to dungeon piece cordinates
*/
constexpr Point megaToWorld()
{
return { 16 + 2 * x, 16 + 2 * y };
}
#ifdef BUILD_TESTING
/**
* @brief Format points nicely in test failure messages

50
Source/gendung.cpp

@ -489,8 +489,8 @@ void DRLG_RectTrans(int x1, int y1, int x2, int y2)
void DRLG_MRectTrans(int x1, int y1, int x2, int y2)
{
x1 = 2 * x1 + 17;
y1 = 2 * y1 + 17;
x1 = 2 * x1 + 16 + 1;
y1 = 2 * y1 + 16 + 1;
x2 = 2 * x2 + 16;
y2 = 2 * y2 + 16;
@ -563,6 +563,52 @@ void Make_SetPC(int x, int y, int w, int h)
}
}
std::optional<Point> PlaceMiniSet(const Miniset &miniset, int tries, bool drlg1Quirk)
{
int sw = miniset.size.width;
int sh = miniset.size.height;
int sx = GenerateRnd(DMAXX - sw);
int sy = GenerateRnd(DMAXY - sh);
for (int bailcnt = 0;; bailcnt++, sx++) {
if (bailcnt > tries)
return {};
if (sx == DMAXX - sw) {
sx = 0;
sy++;
if (sy == DMAXY - sh) {
sy = 0;
}
}
// Limit the position of SetPieces for compatibility with Diablo bug
if (drlg1Quirk) {
bool valid = true;
if (sx <= 12) {
sx++;
valid = false;
}
if (sy <= 12) {
sy++;
valid = false;
}
if (!valid) {
continue;
}
}
if (SetPiecesRoom.Contains({ sx, sy }))
continue;
if (miniset.matches({ sx, sy }))
break;
}
miniset.place({ sx, sy });
return Point(sx, sy);
}
void DRLG_PlaceThemeRooms(int minSize, int maxSize, int floor, int freq, bool rndSize)
{
themeCount = 0;

5
Source/gendung.h

@ -338,6 +338,11 @@ void DRLG_AreaTrans(int num, BYTE *List);
void DRLG_InitSetPC();
void DRLG_SetPC();
void Make_SetPC(int x, int y, int w, int h);
/**
* @param tries Tiles to try, 1600 will scan the full map
* @param drlg1Quirk Match buggy behaviour of Diablo's Cathedral
*/
std::optional<Point> PlaceMiniSet(const Miniset &miniset, int tries = 198, bool drlg1Quirk = false);
void DRLG_PlaceThemeRooms(int minSize, int maxSize, int floor, int freq, bool rndSize);
void DRLG_HoldThemeRooms();
void DRLG_LPass3(int lv);

2
Source/objects.cpp

@ -1612,7 +1612,7 @@ void ObjSetMini(Point position, int v)
{
MegaTile mega = pMegaTiles[v - 1];
Point megaOrigin = position * 2 + Displacement { 16, 16 };
Point megaOrigin = position.megaToWorld();
ObjSetMicro(megaOrigin, SDL_SwapLE16(mega.micro1) + 1);
ObjSetMicro(megaOrigin + Direction::SouthEast, SDL_SwapLE16(mega.micro2) + 1);

Loading…
Cancel
Save