Browse Source

Clean up use of currlevel

pull/4682/head
Anders Jenbo 4 years ago
parent
commit
1203514383
  1. 13
      Source/automap.cpp
  2. 2
      Source/control.cpp
  3. 2
      Source/controls/modifier_hints.cpp
  4. 2
      Source/controls/plrctrls.cpp
  5. 4
      Source/debug.cpp
  6. 17
      Source/diablo.cpp
  7. 254
      Source/drlg_l1.cpp
  8. 58
      Source/drlg_l2.cpp
  9. 539
      Source/drlg_l3.cpp
  10. 118
      Source/drlg_l4.cpp
  11. 2
      Source/gmenu.cpp
  12. 6
      Source/inv.cpp
  13. 12
      Source/items.cpp
  14. 6
      Source/lighting.cpp
  15. 6
      Source/loadsave.cpp
  16. 10
      Source/missiles.cpp
  17. 2
      Source/monster.cpp
  18. 28
      Source/msg.cpp
  19. 9
      Source/objects.cpp
  20. 2
      Source/panels/spell_book.cpp
  21. 4
      Source/panels/spell_list.cpp
  22. 18
      Source/player.cpp
  23. 10
      Source/portal.cpp
  24. 2
      Source/qol/monhealthbar.cpp
  25. 2
      Source/qol/stash.cpp
  26. 2
      Source/scrollrt.cpp
  27. 420
      Source/trigs.cpp
  28. 2
      Source/trigs.h
  29. 6
      test/drlg_l1_test.cpp
  30. 4
      test/drlg_l2_test.cpp
  31. 4
      test/drlg_l3_test.cpp
  32. 4
      test/drlg_l4_test.cpp

13
Source/automap.cpp

@ -10,6 +10,7 @@
#include "control.h"
#include "engine/load_file.hpp"
#include "engine/render/automap_render.hpp"
#include "gendung.h"
#include "palette.h"
#include "player.h"
#include "setmaps.h"
@ -501,14 +502,18 @@ void DrawAutomapText(const Surface &out)
return;
}
if (currlevel != 0) {
if (leveltype != DTYPE_TOWN) {
std::string description;
if (currlevel >= 17 && currlevel <= 20) {
switch (leveltype) {
case DTYPE_NEST:
description = fmt::format(_("Level: Nest {:d}"), currlevel - 16);
} else if (currlevel >= 21 && currlevel <= 24) {
break;
case DTYPE_CRYPT:
description = fmt::format(_("Level: Crypt {:d}"), currlevel - 20);
} else {
break;
default:
description = fmt::format(_("Level: {:d}"), currlevel);
break;
}
DrawString(out, description, linePosition);

2
Source/control.cpp

@ -687,7 +687,7 @@ void control_check_btn_press()
void DoAutoMap()
{
if (currlevel != 0 || gbIsMultiplayer) {
if (leveltype != DTYPE_TOWN || gbIsMultiplayer) {
if (!AutomapActive)
StartAutomap();
else

2
Source/controls/modifier_hints.cpp

@ -132,7 +132,7 @@ void DrawSpellsCircleMenuHint(const Surface &out, const Point &origin)
splId = myPlayer._pSplHotKey[slot];
if (splId != SPL_INVALID && splId != SPL_NULL && (spells & GetSpellBitmask(splId)) != 0)
splType = (currlevel == 0 && !spelldata[splId].sTownSpell) ? RSPLTYPE_INVALID : myPlayer._pSplTHotKey[slot];
splType = (leveltype == DTYPE_TOWN && !spelldata[splId].sTownSpell) ? RSPLTYPE_INVALID : myPlayer._pSplTHotKey[slot];
else {
splType = RSPLTYPE_INVALID;
splId = SPL_NULL;

2
Source/controls/plrctrls.cpp

@ -1816,7 +1816,7 @@ bool TryDropItem()
return false;
}
if (currlevel == 0) {
if (leveltype == DTYPE_TOWN) {
if (UseItemOpensHive(myPlayer.HoldItem, myPlayer.position.tile)) {
NetSendCmdPItem(true, CMD_PUTITEM, { 79, 61 }, myPlayer.HoldItem.pop());
NewCursor(CURSOR_HAND);

4
Source/debug.cpp

@ -663,7 +663,7 @@ std::string DebugCmdLevelSeed(const string_view parameter)
std::string DebugCmdSpawnUniqueMonster(const string_view parameter)
{
if (currlevel == 0)
if (leveltype == DTYPE_TOWN)
return "Do you want to kill the towners?!?";
std::stringstream paramsStream(parameter.data());
@ -750,7 +750,7 @@ std::string DebugCmdSpawnUniqueMonster(const string_view parameter)
std::string DebugCmdSpawnMonster(const string_view parameter)
{
if (currlevel == 0)
if (leveltype == DTYPE_TOWN)
return "Do you want to kill the towners?!?";
std::stringstream paramsStream(parameter.data());

17
Source/diablo.cpp

@ -1183,27 +1183,30 @@ void CreateLevel(lvl_entry entry)
InitTownTriggers();
break;
case DTYPE_CATHEDRAL:
case DTYPE_CRYPT:
InitL1Triggers();
Freeupstairs();
break;
case DTYPE_CATACOMBS:
InitL2Triggers();
Freeupstairs();
break;
case DTYPE_CAVES:
case DTYPE_NEST:
InitL3Triggers();
Freeupstairs();
break;
case DTYPE_HELL:
InitL4Triggers();
Freeupstairs();
break;
case DTYPE_NEST:
InitHiveTriggers();
break;
case DTYPE_CRYPT:
InitCryptTriggers();
break;
default:
app_fatal("CreateLevel");
}
if (leveltype != DTYPE_TOWN) {
Freeupstairs();
}
LoadRndLvlPal(leveltype);
}
@ -2313,7 +2316,7 @@ void LoadGameLevel(bool firstflag, lvl_entry lvldir)
ProcessVisionList();
}
if (currlevel >= 21) {
if (leveltype == DTYPE_CRYPT) {
if (currlevel == 21) {
CornerstoneLoad(CornerStone.position);
}

254
Source/drlg_l1.cpp

@ -759,7 +759,7 @@ void ApplyShadowsPatterns()
}
}
int PlaceMiniSet(const BYTE *miniset, int tmin, int tmax, int cx, int cy, bool setview, int noquad)
bool PlaceMiniSet(const BYTE *miniset, int tmin, int tmax, int cx, int cy, bool setview, int noquad)
{
int sx;
int sy;
@ -830,7 +830,7 @@ int PlaceMiniSet(const BYTE *miniset, int tmin, int tmax, int cx, int cy, bool s
}
}
if (++found > 4000)
return -1;
return false;
}
}
@ -859,14 +859,7 @@ int PlaceMiniSet(const BYTE *miniset, int tmin, int tmax, int cx, int cy, bool s
ViewPosition = Point { 19, 20 } + Displacement { sx, sy } * 2;
}
if (sx < cx && sy < cy)
return 0;
if (sx > cx && sy < cy)
return 1;
if (sx < cx && sy > cy)
return 2;
return 3;
return true;
}
void PlaceMiniSetRandom(const BYTE *miniset, int rndper)
@ -1988,32 +1981,32 @@ void FixTransparency()
void FixDirtTiles()
{
if (currlevel < 21) {
for (int j = 0; j < DMAXY - 1; j++) {
for (int i = 0; i < DMAXX - 1; i++) {
if (dungeon[i][j] == 21 && dungeon[i + 1][j] != 19) {
dungeon[i][j] = 202;
}
if (dungeon[i][j] == 19 && dungeon[i + 1][j] != 19) {
dungeon[i][j] = 200;
}
if (dungeon[i][j] == 24 && dungeon[i + 1][j] != 19) {
dungeon[i][j] = 205;
}
if (dungeon[i][j] == 18 && dungeon[i][j + 1] != 18) {
dungeon[i][j] = 199;
}
if (dungeon[i][j] == 21 && dungeon[i][j + 1] != 18) {
dungeon[i][j] = 202;
}
if (dungeon[i][j] == 23 && dungeon[i][j + 1] != 18) {
dungeon[i][j] = 204;
}
for (int j = 0; j < DMAXY - 1; j++) {
for (int i = 0; i < DMAXX - 1; i++) {
if (dungeon[i][j] == 21 && dungeon[i + 1][j] != 19) {
dungeon[i][j] = 202;
}
if (dungeon[i][j] == 19 && dungeon[i + 1][j] != 19) {
dungeon[i][j] = 200;
}
if (dungeon[i][j] == 24 && dungeon[i + 1][j] != 19) {
dungeon[i][j] = 205;
}
if (dungeon[i][j] == 18 && dungeon[i][j + 1] != 18) {
dungeon[i][j] = 199;
}
if (dungeon[i][j] == 21 && dungeon[i][j + 1] != 18) {
dungeon[i][j] = 202;
}
if (dungeon[i][j] == 23 && dungeon[i][j + 1] != 18) {
dungeon[i][j] = 204;
}
}
return;
}
}
void FixCryptDirtTiles()
{
for (int j = 0; j < DMAXY - 1; j++) {
for (int i = 0; i < DMAXX - 1; i++) {
if (dungeon[i][j] == 19)
@ -2168,6 +2161,69 @@ void CryptPatternGroup7(int rndper)
PlaceMiniSetRandom(CryptPattern8, rndper);
}
bool PlaceCathedralStairs(lvl_entry entry)
{
bool success = true;
// Place poison water entrance
if (Quests[Q_PWATER].IsAvailable()) {
if (!PlaceMiniSet(PWATERIN, 1, 1, 0, 0, entry == ENTRY_RTNLVL, -1))
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, -1)) {
if (MyPlayer->pOriginalCathedral)
return false;
success = false;
}
// Place stairs down
if (!Quests[Q_LTBANNER].IsAvailable() && !PlaceMiniSet(STAIRSDOWN, 1, 1, 0, 0, entry == ENTRY_PREV, -1))
success = false;
if (entry == ENTRY_PREV) {
if (Quests[Q_LTBANNER].IsAvailable())
ViewPosition = Point { 20, 28 } + Displacement { setpc_x, setpc_y } * 2;
else
ViewPosition.y--;
}
return success;
}
bool PlaceCryptStairs(lvl_entry entry)
{
bool success = true;
// Place stairs up
bool enteringFromAbove = entry == ENTRY_MAIN || entry == ENTRY_TWARPDN;
if (!PlaceMiniSet(currlevel != 21 ? L5STAIRSUPHF : L5STAIRSTOWN, 1, 1, 0, 0, enteringFromAbove, -1))
success = false;
if (enteringFromAbove)
ViewPosition.y++;
// Place stairs down
if (currlevel != 24) {
if (!PlaceMiniSet(L5STAIRSDOWN, 1, 1, 0, 0, entry == ENTRY_PREV, -1))
success = false;
if (entry == ENTRY_PREV)
ViewPosition.y += 3;
}
return success;
}
bool PlaceStairs(lvl_entry entry)
{
if (leveltype == DTYPE_CRYPT) {
return PlaceCryptStairs(entry);
}
return PlaceCathedralStairs(entry);
}
void GenerateLevel(lvl_entry entry)
{
int minarea = 761;
@ -2182,8 +2238,7 @@ void GenerateLevel(lvl_entry entry)
break;
}
bool doneflag;
do {
while (true) {
DRLG_InitTrans();
do {
@ -2198,111 +2253,9 @@ void GenerateLevel(lvl_entry entry)
AddWall();
ClearFlags();
FloodTransparencyValues(13);
doneflag = true;
if (Quests[Q_PWATER].IsAvailable()) {
if (entry == ENTRY_MAIN) {
if (PlaceMiniSet(PWATERIN, 1, 1, 0, 0, true, -1) < 0)
doneflag = false;
} else {
if (PlaceMiniSet(PWATERIN, 1, 1, 0, 0, false, -1) < 0)
doneflag = false;
ViewPosition.y--;
}
}
if (Quests[Q_LTBANNER].IsAvailable()) {
if (entry == ENTRY_MAIN) {
if (PlaceMiniSet(STAIRSUP, 1, 1, 0, 0, true, -1) < 0)
doneflag = false;
} else {
if (PlaceMiniSet(STAIRSUP, 1, 1, 0, 0, false, -1) < 0)
doneflag = false;
if (entry == ENTRY_PREV) {
ViewPosition = Point { 20, 28 } + Displacement { setpc_x, setpc_y } * 2;
} else {
ViewPosition.y--;
}
}
} else if (entry == ENTRY_MAIN) {
if (currlevel < 21) {
if (!MyPlayer->pOriginalCathedral) {
if (PlaceMiniSet(STAIRSUP, 1, 1, 0, 0, true, -1) < 0)
doneflag = false;
if (PlaceMiniSet(STAIRSDOWN, 1, 1, 0, 0, false, -1) < 0)
doneflag = false;
} else {
if (PlaceMiniSet(L5STAIRSUP, 1, 1, 0, 0, true, -1) < 0)
doneflag = false;
else if (PlaceMiniSet(STAIRSDOWN, 1, 1, 0, 0, false, -1) < 0)
doneflag = false;
}
} else if (currlevel == 21) {
if (PlaceMiniSet(L5STAIRSTOWN, 1, 1, 0, 0, false, -1) < 0)
doneflag = false;
if (PlaceMiniSet(L5STAIRSDOWN, 1, 1, 0, 0, false, -1) < 0)
doneflag = false;
ViewPosition.y++;
} else {
if (PlaceMiniSet(L5STAIRSUPHF, 1, 1, 0, 0, true, -1) < 0)
doneflag = false;
if (currlevel != 24) {
if (PlaceMiniSet(L5STAIRSDOWN, 1, 1, 0, 0, false, -1) < 0)
doneflag = false;
}
ViewPosition.y++;
}
} else if (!MyPlayer->pOriginalCathedral && entry == ENTRY_PREV) {
if (currlevel < 21) {
if (PlaceMiniSet(STAIRSUP, 1, 1, 0, 0, false, -1) < 0)
doneflag = false;
if (PlaceMiniSet(STAIRSDOWN, 1, 1, 0, 0, true, -1) < 0)
doneflag = false;
ViewPosition.y--;
} else if (currlevel == 21) {
if (PlaceMiniSet(L5STAIRSTOWN, 1, 1, 0, 0, false, -1) < 0)
doneflag = false;
if (PlaceMiniSet(L5STAIRSDOWN, 1, 1, 0, 0, true, -1) < 0)
doneflag = false;
ViewPosition.y += 3;
} else {
if (PlaceMiniSet(L5STAIRSUPHF, 1, 1, 0, 0, true, -1) < 0)
doneflag = false;
if (currlevel != 24) {
if (PlaceMiniSet(L5STAIRSDOWN, 1, 1, 0, 0, true, -1) < 0)
doneflag = false;
}
ViewPosition.y += 3;
}
} else {
if (currlevel < 21) {
if (!MyPlayer->pOriginalCathedral) {
if (PlaceMiniSet(STAIRSUP, 1, 1, 0, 0, false, -1) < 0)
doneflag = false;
if (PlaceMiniSet(STAIRSDOWN, 1, 1, 0, 0, false, -1) < 0)
doneflag = false;
} else {
if (PlaceMiniSet(L5STAIRSUP, 1, 1, 0, 0, false, -1) < 0)
doneflag = false;
else if (PlaceMiniSet(STAIRSDOWN, 1, 1, 0, 0, true, -1) < 0)
doneflag = false;
ViewPosition.y--;
}
} else if (currlevel == 21) {
if (PlaceMiniSet(L5STAIRSTOWN, 1, 1, 0, 0, true, -1) < 0)
doneflag = false;
if (PlaceMiniSet(L5STAIRSDOWN, 1, 1, 0, 0, false, -1) < 0)
doneflag = false;
} else {
if (PlaceMiniSet(L5STAIRSUPHF, 1, 1, 0, 0, true, -1) < 0)
doneflag = false;
if (currlevel != 24) {
if (PlaceMiniSet(L5STAIRSDOWN, 1, 1, 0, 0, false, -1) < 0)
doneflag = false;
}
}
}
} while (!doneflag);
if (PlaceStairs(entry))
break;
}
for (int j = 0; j < DMAXY; j++) {
for (int i = 0; i < DMAXX; i++) {
@ -2316,7 +2269,11 @@ void GenerateLevel(lvl_entry entry)
}
FixTransparency();
FixDirtTiles();
if (leveltype == DTYPE_CRYPT) {
FixCryptDirtTiles();
} else {
FixDirtTiles();
}
FixCornerTiles();
for (int j = 0; j < DMAXY; j++) {
@ -2326,9 +2283,7 @@ void GenerateLevel(lvl_entry entry)
}
}
if (currlevel < 21) {
Substitution();
} else {
if (leveltype == DTYPE_CRYPT) {
CryptPatternGroup1(10);
PlaceMiniSetRandom(CryptPattern1, 95);
PlaceMiniSetRandom(CryptPattern2, 95);
@ -2374,9 +2329,8 @@ void GenerateLevel(lvl_entry entry)
CryptLavafloor();
break;
}
}
if (currlevel < 21) {
} else {
Substitution();
ApplyShadowsPatterns();
PlaceMiniSet(LAMPS, 5, 10, 0, 0, false, -1);
FillFloor();
@ -2440,7 +2394,7 @@ void LoadL1Dungeon(const char *path, int vx, int vy)
Pass3();
DRLG_Init_Globals();
if (currlevel < 17)
if (leveltype != DTYPE_CRYPT)
InitDungeonPieces();
SetMapMonsters(dunData.get(), { 0, 0 });
@ -2508,10 +2462,10 @@ void CreateL5Dungeon(uint32_t rseed, lvl_entry entry)
Pass3();
FreeQuestSetPieces();
if (currlevel < 17) {
InitDungeonPieces();
} else {
if (leveltype == DTYPE_CRYPT) {
InitCryptPieces();
} else {
InitDungeonPieces();
}
DRLG_SetPC();

58
Source/drlg_l2.cpp

@ -2864,10 +2864,34 @@ void FixDoors()
}
}
bool PlaceStairs(lvl_entry entry)
{
// Place stairs up
if (!PlaceMiniSet(USTAIRS, 1, 1, -1, -1, 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))
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))
return false;
if (entry == ENTRY_TWARPDN)
ViewPosition.y -= 2;
}
return true;
}
void GenerateLevel(lvl_entry entry)
{
bool doneflag = false;
while (!doneflag) {
while (true) {
nRoomCnt = 0;
InitDungeonFlags();
DRLG_InitTrans();
@ -2880,34 +2904,8 @@ void GenerateLevel(lvl_entry entry)
}
FloodTransparencyValues(3);
FixTransparency();
if (entry == ENTRY_MAIN) {
doneflag = PlaceMiniSet(USTAIRS, 1, 1, -1, -1, true);
if (doneflag) {
doneflag = PlaceMiniSet(DSTAIRS, 1, 1, -1, -1, false);
if (doneflag && currlevel == 5) {
doneflag = PlaceMiniSet(WARPSTAIRS, 1, 1, -1, -1, false);
}
}
ViewPosition.y -= 2;
} else if (entry == ENTRY_PREV) {
doneflag = PlaceMiniSet(USTAIRS, 1, 1, -1, -1, false);
if (doneflag) {
doneflag = PlaceMiniSet(DSTAIRS, 1, 1, -1, -1, true);
if (doneflag && currlevel == 5) {
doneflag = PlaceMiniSet(WARPSTAIRS, 1, 1, -1, -1, false);
}
}
ViewPosition.x--;
} else {
doneflag = PlaceMiniSet(USTAIRS, 1, 1, -1, -1, false);
if (doneflag) {
doneflag = PlaceMiniSet(DSTAIRS, 1, 1, -1, -1, false);
if (doneflag && currlevel == 5) {
doneflag = PlaceMiniSet(WARPSTAIRS, 1, 1, -1, -1, true);
}
}
ViewPosition.y -= 2;
}
if (PlaceStairs(entry))
break;
}
FixLockout();

539
Source/drlg_l3.cpp

@ -20,8 +20,6 @@ namespace devilution {
namespace {
/** This will be true if a lava pool has been generated for the level */
uint8_t lavapool;
int lockoutcnt;
bool lockout[DMAXX][DMAXY];
@ -1518,15 +1516,90 @@ bool Spawn(int x, int y, int *totarea)
return false;
}
bool HivePlaceSetRandom(const BYTE *miniset, int rndper)
{
bool placed = false;
int sw = miniset[0];
int sh = miniset[1];
for (int sy = 0; sy < DMAXX - sh; sy++) {
for (int sx = 0; sx < DMAXY - sw; sx++) {
bool found = true;
int ii = 2;
for (int yy = 0; yy < sh && found; yy++) {
for (int xx = 0; xx < sw && found; xx++) {
if (miniset[ii] != 0 && dungeon[xx + sx][yy + sy] != miniset[ii]) {
found = false;
}
if (dflags[xx + sx][yy + sy] != 0) {
found = false;
}
ii++;
}
}
int kk = sw * sh + 2;
if (found) {
if (miniset[kk] >= 84 && miniset[kk] <= 100) {
// BUGFIX: accesses to dungeon can go out of bounds
// BUGFIX: Comparisons vs 100 should use same tile as comparisons vs 84.
if (dungeon[sx - 1][sy] >= 84 && dungeon[sx - 1][sy] <= 100) {
found = false;
}
if (dungeon[sx + 1][sy] >= 84 && dungeon[sx - 1][sy] <= 100) {
found = false;
}
if (dungeon[sx][sy + 1] >= 84 && dungeon[sx - 1][sy] <= 100) {
found = false;
}
if (dungeon[sx][sy - 1] >= 84 && dungeon[sx - 1][sy] <= 100) {
found = false;
}
}
}
if (found && GenerateRnd(100) < rndper) {
placed = true;
for (int yy = 0; yy < sh; yy++) {
for (int xx = 0; xx < sw; xx++) {
if (miniset[kk] != 0) {
dungeon[xx + sx][yy + sy] = miniset[kk];
}
kk++;
}
}
}
}
}
return placed;
}
bool PlaceSlimePool()
{
int lavapool = 0;
if (HivePlaceSetRandom(HivePattern41, 30))
lavapool++;
if (HivePlaceSetRandom(HivePattern42, 40))
lavapool++;
if (HivePlaceSetRandom(HivePattern39, 50))
lavapool++;
if (HivePlaceSetRandom(HivePattern40, 60))
lavapool++;
return lavapool >= 3;
}
/**
* Flood fills dirt and wall tiles looking for
* an area of at most 40 tiles and disconnected from the map edge.
* If it finds one, converts it to lava tiles and sets lavapool to true.
* If it finds one, converts it to lava tiles and return true.
*/
void Pool()
bool PlaceLavaPool()
{
constexpr uint8_t Poolsub[15] = { 0, 35, 26, 36, 25, 29, 34, 7, 33, 28, 27, 37, 32, 31, 30 };
bool lavePoolPlaced = false;
for (int duny = 0; duny < DMAXY; duny++) {
for (int dunx = 0; dunx < DMAXY; dunx++) {
if (dungeon[dunx][duny] != 8) {
@ -1565,13 +1638,24 @@ void Pool()
if (k != 0 && k <= 37) {
dungeon[i][j] = k;
}
lavapool = 1;
lavePoolPlaced = true;
}
}
}
}
}
}
return lavePoolPlaced;
}
bool PlacePool()
{
if (leveltype == DTYPE_NEST) {
return PlaceSlimePool();
}
return PlaceLavaPool();
}
void PoolFix()
@ -1651,7 +1735,7 @@ bool PlaceMiniSet(const BYTE *miniset, int tmin, int tmax, int cx, int cy, bool
}
}
if (bailcnt >= 200) {
return true;
return false;
}
int ii = sw * sh + 2;
@ -1669,7 +1753,7 @@ bool PlaceMiniSet(const BYTE *miniset, int tmin, int tmax, int cx, int cy, bool
ViewPosition = Point { 17, 19 } + Displacement { sx, sy } * 2;
}
return false;
return true;
}
void PlaceMiniSetRandom(const BYTE *miniset, int rndper)
@ -1725,63 +1809,6 @@ void PlaceMiniSetRandom(const BYTE *miniset, int rndper)
}
}
bool HivePlaceSetRandom(const BYTE *miniset, int rndper)
{
bool placed = false;
int sw = miniset[0];
int sh = miniset[1];
for (int sy = 0; sy < DMAXX - sh; sy++) {
for (int sx = 0; sx < DMAXY - sw; sx++) {
bool found = true;
int ii = 2;
for (int yy = 0; yy < sh && found; yy++) {
for (int xx = 0; xx < sw && found; xx++) {
if (miniset[ii] != 0 && dungeon[xx + sx][yy + sy] != miniset[ii]) {
found = false;
}
if (dflags[xx + sx][yy + sy] != 0) {
found = false;
}
ii++;
}
}
int kk = sw * sh + 2;
if (found) {
if (miniset[kk] >= 84 && miniset[kk] <= 100) {
// BUGFIX: accesses to dungeon can go out of bounds
// BUGFIX: Comparisons vs 100 should use same tile as comparisons vs 84.
if (dungeon[sx - 1][sy] >= 84 && dungeon[sx - 1][sy] <= 100) {
found = false;
}
if (dungeon[sx + 1][sy] >= 84 && dungeon[sx - 1][sy] <= 100) {
found = false;
}
if (dungeon[sx][sy + 1] >= 84 && dungeon[sx - 1][sy] <= 100) {
found = false;
}
if (dungeon[sx][sy - 1] >= 84 && dungeon[sx - 1][sy] <= 100) {
found = false;
}
}
}
if (found && GenerateRnd(100) < rndper) {
placed = true;
for (int yy = 0; yy < sh; yy++) {
for (int xx = 0; xx < sw; xx++) {
if (miniset[kk] != 0) {
dungeon[xx + sx][yy + sy] = miniset[kk];
}
kk++;
}
}
}
}
}
return placed;
}
bool FenceVerticalUp(int i, int y)
{
if ((dungeon[i + 1][y] > 152 || dungeon[i + 1][y] < 130)
@ -2078,7 +2105,7 @@ void Fence()
FenceDoorFix();
}
bool Anvil()
bool PlaceAnvil()
{
int sw = L3ANVIL[0];
int sh = L3ANVIL[1];
@ -2114,7 +2141,7 @@ bool Anvil()
}
}
if (trys >= 200) {
return true;
return false;
}
int ii = sw * sh + 2;
@ -2133,7 +2160,7 @@ bool Anvil()
setpc_w = sw;
setpc_h = sh;
return false;
return true;
}
void Warp()
@ -2218,143 +2245,88 @@ bool Lockout()
return t == lockoutcnt;
}
void GenerateLevel(lvl_entry entry)
bool PlaceCaveStairs(lvl_entry entry)
{
bool found;
bool genok;
lavapool = 0;
do {
do {
do {
InitDungeonFlags();
int x1 = GenerateRnd(20) + 10;
int y1 = GenerateRnd(20) + 10;
int x2 = x1 + 2;
int y2 = y1 + 2;
FillRoom(x1, y1, x2, y2);
CreateBlock(x1, y1, 2, 0);
CreateBlock(x2, y1, 2, 1);
CreateBlock(x1, y2, 2, 2);
CreateBlock(x1, y1, 2, 3);
if (Quests[Q_ANVIL].IsAvailable()) {
x1 = GenerateRnd(10) + 10;
y1 = GenerateRnd(10) + 10;
x2 = x1 + 12;
y2 = y1 + 12;
FloorArea(x1, y1, x2, y2);
}
FillDiagonals();
FillSingles();
FillStraights();
FillDiagonals();
Edges();
if (GetFloorArea() >= 600) {
found = Lockout();
} else {
found = false;
}
} while (!found);
MakeMegas();
if (entry == ENTRY_MAIN) {
if (currlevel < 17) {
genok = PlaceMiniSet(L3UP, 1, 1, -1, -1, true);
} else {
if (currlevel != 17)
genok = PlaceMiniSet(L6UP, 1, 1, -1, -1, true);
else
genok = PlaceMiniSet(L6HOLDWARP, 1, 1, -1, -1, true);
}
if (!genok) {
if (currlevel < 17) {
genok = PlaceMiniSet(L3DOWN, 1, 1, -1, -1, false);
} else {
if (currlevel != 20)
genok = PlaceMiniSet(L6DOWN, 1, 1, -1, -1, false);
}
if (!genok && currlevel == 9) {
genok = PlaceMiniSet(L3HOLDWARP, 1, 1, -1, -1, false);
}
}
} else if (entry == ENTRY_PREV) {
if (currlevel < 17) {
genok = PlaceMiniSet(L3UP, 1, 1, -1, -1, false);
} else {
if (currlevel != 17)
genok = PlaceMiniSet(L6UP, 1, 1, -1, -1, false);
else
genok = PlaceMiniSet(L6HOLDWARP, 1, 1, -1, -1, false);
}
if (!genok) {
if (currlevel < 17) {
genok = PlaceMiniSet(L3DOWN, 1, 1, -1, -1, true);
ViewPosition += { 2, -2 };
} else {
if (currlevel != 20) {
genok = PlaceMiniSet(L6DOWN, 1, 1, -1, -1, true);
ViewPosition += { 2, -2 };
}
}
if (!genok && currlevel == 9) {
genok = PlaceMiniSet(L3HOLDWARP, 1, 1, -1, -1, false);
}
}
} else {
if (currlevel < 17) {
genok = PlaceMiniSet(L3UP, 1, 1, -1, -1, false);
} else {
if (currlevel != 17)
genok = PlaceMiniSet(L6UP, 1, 1, -1, -1, false);
else
genok = PlaceMiniSet(L6HOLDWARP, 1, 1, -1, -1, true);
}
if (!genok) {
if (currlevel < 17) {
genok = PlaceMiniSet(L3DOWN, 1, 1, -1, -1, false);
} else {
if (currlevel != 20)
genok = PlaceMiniSet(L6DOWN, 1, 1, -1, -1, false);
}
if (!genok && currlevel == 9) {
genok = PlaceMiniSet(L3HOLDWARP, 1, 1, -1, -1, true);
}
}
}
if (!genok && Quests[Q_ANVIL].IsAvailable()) {
genok = Anvil();
}
} while (genok);
if (currlevel < 17) {
Pool();
} else {
if (HivePlaceSetRandom(HivePattern41, 30))
lavapool++;
if (HivePlaceSetRandom(HivePattern42, 40))
lavapool++;
if (HivePlaceSetRandom(HivePattern39, 50))
lavapool++;
if (HivePlaceSetRandom(HivePattern40, 60))
lavapool++;
if (lavapool < 3)
lavapool = 0;
}
} while (lavapool == 0);
if (currlevel < 17)
PoolFix();
if (currlevel < 17)
Warp();
// Place stairs up
if (!PlaceMiniSet(L3UP, 1, 1, -1, -1, entry == ENTRY_MAIN))
return false;
if (currlevel < 17) {
PlaceMiniSetRandom(L3ISLE1, 70);
PlaceMiniSetRandom(L3ISLE2, 70);
PlaceMiniSetRandom(L3ISLE3, 30);
PlaceMiniSetRandom(L3ISLE4, 30);
PlaceMiniSetRandom(L3ISLE1, 100);
PlaceMiniSetRandom(L3ISLE2, 100);
PlaceMiniSetRandom(L3ISLE5, 90);
} else {
// Place stairs down
if (!PlaceMiniSet(L3DOWN, 1, 1, -1, -1, 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))
return false;
return true;
}
bool PlaceNestStairs(lvl_entry entry)
{
// Place stairs up
if (!PlaceMiniSet(currlevel != 17 ? L6UP : L6HOLDWARP, 1, 1, -1, -1, entry == ENTRY_MAIN || entry == ENTRY_TWARPDN))
return false;
// Place stairs down
if (currlevel != 20) {
if (!PlaceMiniSet(L6DOWN, 1, 1, -1, -1, entry == ENTRY_PREV))
return false;
if (entry == ENTRY_PREV)
ViewPosition += { 2, -2 };
}
return true;
}
bool PlaceStairs(lvl_entry entry)
{
if (leveltype == DTYPE_NEST) {
return PlaceNestStairs(entry);
}
return PlaceCaveStairs(entry);
}
void GenerateLevel(lvl_entry entry)
{
while (true) {
InitDungeonFlags();
int x1 = GenerateRnd(20) + 10;
int y1 = GenerateRnd(20) + 10;
int x2 = x1 + 2;
int y2 = y1 + 2;
FillRoom(x1, y1, x2, y2);
CreateBlock(x1, y1, 2, 0);
CreateBlock(x2, y1, 2, 1);
CreateBlock(x1, y2, 2, 2);
CreateBlock(x1, y1, 2, 3);
if (Quests[Q_ANVIL].IsAvailable()) {
x1 = GenerateRnd(10) + 10;
y1 = GenerateRnd(10) + 10;
x2 = x1 + 12;
y2 = y1 + 12;
FloorArea(x1, y1, x2, y2);
}
FillDiagonals();
FillSingles();
FillStraights();
FillDiagonals();
Edges();
if (GetFloorArea() < 600 || !Lockout())
continue;
MakeMegas();
if (!PlaceStairs(entry))
continue;
if (Quests[Q_ANVIL].IsAvailable() && !PlaceAnvil())
continue;
if (PlacePool())
break;
}
if (leveltype == DTYPE_NEST) {
PlaceMiniSetRandom(L6ISLE1, 70);
PlaceMiniSetRandom(L6ISLE2, 70);
PlaceMiniSetRandom(L6ISLE3, 30);
@ -2362,55 +2334,6 @@ void GenerateLevel(lvl_entry entry)
PlaceMiniSetRandom(L6ISLE1, 100);
PlaceMiniSetRandom(L6ISLE2, 100);
PlaceMiniSetRandom(L6ISLE5, 90);
}
if (currlevel < 17)
HallOfHeroes();
if (currlevel < 17)
River();
if (Quests[Q_ANVIL].IsAvailable()) {
dungeon[setpc_x + 7][setpc_y + 5] = 7;
dungeon[setpc_x + 8][setpc_y + 5] = 7;
dungeon[setpc_x + 9][setpc_y + 5] = 7;
if (dungeon[setpc_x + 10][setpc_y + 5] == 17 || dungeon[setpc_x + 10][setpc_y + 5] == 18) {
dungeon[setpc_x + 10][setpc_y + 5] = 45;
}
}
if (currlevel < 17)
DRLG_PlaceThemeRooms(5, 10, 7, 0, false);
if (currlevel < 17) {
Fence();
PlaceMiniSetRandom(L3TITE1, 10);
PlaceMiniSetRandom(L3TITE2, 10);
PlaceMiniSetRandom(L3TITE3, 10);
PlaceMiniSetRandom(L3TITE6, 20);
PlaceMiniSetRandom(L3TITE7, 20);
PlaceMiniSetRandom(L3TITE8, 20);
PlaceMiniSetRandom(L3TITE9, 20);
PlaceMiniSetRandom(L3TITE10, 20);
PlaceMiniSetRandom(L3TITE11, 30);
PlaceMiniSetRandom(L3TITE12, 20);
PlaceMiniSetRandom(L3TITE13, 20);
PlaceMiniSetRandom(L3CREV1, 30);
PlaceMiniSetRandom(L3CREV2, 30);
PlaceMiniSetRandom(L3CREV3, 30);
PlaceMiniSetRandom(L3CREV4, 30);
PlaceMiniSetRandom(L3CREV5, 30);
PlaceMiniSetRandom(L3CREV6, 30);
PlaceMiniSetRandom(L3CREV7, 30);
PlaceMiniSetRandom(L3CREV8, 30);
PlaceMiniSetRandom(L3CREV9, 30);
PlaceMiniSetRandom(L3CREV10, 30);
PlaceMiniSetRandom(L3CREV11, 30);
PlaceMiniSetRandom(L3XTRA1, 25);
PlaceMiniSetRandom(L3XTRA2, 25);
PlaceMiniSetRandom(L3XTRA3, 25);
PlaceMiniSetRandom(L3XTRA4, 25);
PlaceMiniSetRandom(L3XTRA5, 25);
} else {
PlaceMiniSetRandom(HivePattern1, 20);
PlaceMiniSetRandom(HivePattern2, 20);
PlaceMiniSetRandom(HivePattern3, 20);
@ -2459,6 +2382,59 @@ void GenerateLevel(lvl_entry entry)
PlaceMiniSetRandom(HivePattern22, 25);
PlaceMiniSetRandom(HivePattern27, 25);
PlaceMiniSetRandom(HivePattern28, 25);
} else {
PoolFix();
Warp();
PlaceMiniSetRandom(L3ISLE1, 70);
PlaceMiniSetRandom(L3ISLE2, 70);
PlaceMiniSetRandom(L3ISLE3, 30);
PlaceMiniSetRandom(L3ISLE4, 30);
PlaceMiniSetRandom(L3ISLE1, 100);
PlaceMiniSetRandom(L3ISLE2, 100);
PlaceMiniSetRandom(L3ISLE5, 90);
HallOfHeroes();
River();
if (Quests[Q_ANVIL].IsAvailable()) {
dungeon[setpc_x + 7][setpc_y + 5] = 7;
dungeon[setpc_x + 8][setpc_y + 5] = 7;
dungeon[setpc_x + 9][setpc_y + 5] = 7;
if (dungeon[setpc_x + 10][setpc_y + 5] == 17 || dungeon[setpc_x + 10][setpc_y + 5] == 18) {
dungeon[setpc_x + 10][setpc_y + 5] = 45;
}
}
DRLG_PlaceThemeRooms(5, 10, 7, 0, false);
Fence();
PlaceMiniSetRandom(L3TITE1, 10);
PlaceMiniSetRandom(L3TITE2, 10);
PlaceMiniSetRandom(L3TITE3, 10);
PlaceMiniSetRandom(L3TITE6, 20);
PlaceMiniSetRandom(L3TITE7, 20);
PlaceMiniSetRandom(L3TITE8, 20);
PlaceMiniSetRandom(L3TITE9, 20);
PlaceMiniSetRandom(L3TITE10, 20);
PlaceMiniSetRandom(L3TITE11, 30);
PlaceMiniSetRandom(L3TITE12, 20);
PlaceMiniSetRandom(L3TITE13, 20);
PlaceMiniSetRandom(L3CREV1, 30);
PlaceMiniSetRandom(L3CREV2, 30);
PlaceMiniSetRandom(L3CREV3, 30);
PlaceMiniSetRandom(L3CREV4, 30);
PlaceMiniSetRandom(L3CREV5, 30);
PlaceMiniSetRandom(L3CREV6, 30);
PlaceMiniSetRandom(L3CREV7, 30);
PlaceMiniSetRandom(L3CREV8, 30);
PlaceMiniSetRandom(L3CREV9, 30);
PlaceMiniSetRandom(L3CREV10, 30);
PlaceMiniSetRandom(L3CREV11, 30);
PlaceMiniSetRandom(L3XTRA1, 25);
PlaceMiniSetRandom(L3XTRA2, 25);
PlaceMiniSetRandom(L3XTRA3, 25);
PlaceMiniSetRandom(L3XTRA4, 25);
PlaceMiniSetRandom(L3XTRA5, 25);
}
for (int j = 0; j < DMAXY; j++) {
@ -2475,6 +2451,43 @@ void Pass3()
DRLG_LPass3(8 - 1);
}
void PlaceCaveLights()
{
for (int j = 0; j < MAXDUNY; j++) {
for (int i = 0; i < MAXDUNX; i++) {
if (dPiece[i][j] >= 56 && dPiece[i][j] <= 147) {
DoLighting({ i, j }, 7, -1);
} else if (dPiece[i][j] >= 154 && dPiece[i][j] <= 161) {
DoLighting({ i, j }, 7, -1);
} else if (IsAnyOf(dPiece[i][j], 150, 152)) {
DoLighting({ i, j }, 7, -1);
}
}
}
}
void PlaceHiveLights()
{
for (int j = 0; j < MAXDUNY; j++) {
for (int i = 0; i < MAXDUNX; i++) {
if (dPiece[i][j] >= 382 && dPiece[i][j] <= 457) {
DoLighting({ i, j }, 9, -1);
}
}
}
}
void PlaceLights()
{
if (leveltype == DTYPE_NEST) {
PlaceHiveLights();
return;
}
PlaceCaveLights();
}
} // namespace
void CreateL3Dungeon(uint32_t rseed, lvl_entry entry)
@ -2488,29 +2501,7 @@ void CreateL3Dungeon(uint32_t rseed, lvl_entry entry)
DRLG_InitSetPC();
GenerateLevel(entry);
Pass3();
if (currlevel < 17) {
for (int j = 0; j < MAXDUNY; j++) {
for (int i = 0; i < MAXDUNX; i++) {
if (dPiece[i][j] >= 56 && dPiece[i][j] <= 147) {
DoLighting({ i, j }, 7, -1);
} else if (dPiece[i][j] >= 154 && dPiece[i][j] <= 161) {
DoLighting({ i, j }, 7, -1);
} else if (IsAnyOf(dPiece[i][j], 150, 152)) {
DoLighting({ i, j }, 7, -1);
}
}
}
} else {
for (int j = 0; j < MAXDUNY; j++) {
for (int i = 0; i < MAXDUNX; i++) {
if (dPiece[i][j] >= 382 && dPiece[i][j] <= 457) {
DoLighting({ i, j }, 9, -1);
}
}
}
}
PlaceLights();
DRLG_SetPC();
}

118
Source/drlg_l4.cpp

@ -1283,12 +1283,50 @@ void GeneralFix()
}
}
bool PlaceStairs(lvl_entry entry)
{
// Place stairs up
if (!PlaceMiniSet(L4USTAIRS, 1, 1, -1, -1, entry == ENTRY_MAIN))
return false;
if (entry == ENTRY_MAIN)
ViewPosition.x++;
if (currlevel != 15) {
// Place stairs down
if (currlevel != 16 && !Quests[Q_WARLORD].IsAvailable()) {
if (!PlaceMiniSet(L4DSTAIRS, 1, 1, -1, -1, entry == ENTRY_PREV))
return false;
}
// Place town warp stairs
if (currlevel == 13) {
if (!PlaceMiniSet(L4TWARP, 1, 1, -1, -1, entry == ENTRY_TWARPDN))
return false;
if (entry == ENTRY_TWARPDN)
ViewPosition.x++;
}
} 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))
return false;
}
if (entry == ENTRY_PREV) {
if (Quests[Q_WARLORD].IsAvailable())
ViewPosition = Point { 22, 22 } + Displacement { setpc_x, setpc_y } * 2;
else
ViewPosition.y++;
}
return true;
}
void GenerateLevel(lvl_entry entry)
{
constexpr int Minarea = 173;
int ar;
bool doneflag;
do {
while (true) {
DRLG_InitTrans();
do {
@ -1323,79 +1361,9 @@ void GenerateLevel(lvl_entry entry)
if (currlevel == 16) {
LoadDiabQuads(true);
}
if (Quests[Q_WARLORD].IsAvailable()) {
if (entry == ENTRY_MAIN) {
doneflag = PlaceMiniSet(L4USTAIRS, 1, 1, -1, -1, true);
if (doneflag && currlevel == 13) {
doneflag = PlaceMiniSet(L4TWARP, 1, 1, -1, -1, false);
}
ViewPosition.x++;
} else if (entry == ENTRY_PREV) {
doneflag = PlaceMiniSet(L4USTAIRS, 1, 1, -1, -1, false);
if (doneflag && currlevel == 13) {
doneflag = PlaceMiniSet(L4TWARP, 1, 1, -1, -1, false);
}
ViewPosition = Point { 22, 22 } + Displacement { setpc_x, setpc_y } * 2;
} else {
doneflag = PlaceMiniSet(L4USTAIRS, 1, 1, -1, -1, false);
if (doneflag && currlevel == 13) {
doneflag = PlaceMiniSet(L4TWARP, 1, 1, -1, -1, true);
}
ViewPosition.x++;
}
} else if (currlevel != 15) {
if (entry == ENTRY_MAIN) {
doneflag = PlaceMiniSet(L4USTAIRS, 1, 1, -1, -1, true);
if (doneflag && currlevel != 16) {
doneflag = PlaceMiniSet(L4DSTAIRS, 1, 1, -1, -1, false);
}
if (doneflag && currlevel == 13) {
doneflag = PlaceMiniSet(L4TWARP, 1, 1, -1, -1, false);
}
ViewPosition.x++;
} else if (entry == ENTRY_PREV) {
doneflag = PlaceMiniSet(L4USTAIRS, 1, 1, -1, -1, false);
if (doneflag && currlevel != 16) {
doneflag = PlaceMiniSet(L4DSTAIRS, 1, 1, -1, -1, true);
}
if (doneflag && currlevel == 13) {
doneflag = PlaceMiniSet(L4TWARP, 1, 1, -1, -1, false);
}
ViewPosition.y++;
} else {
doneflag = PlaceMiniSet(L4USTAIRS, 1, 1, -1, -1, false);
if (doneflag && currlevel != 16) {
doneflag = PlaceMiniSet(L4DSTAIRS, 1, 1, -1, -1, false);
}
if (doneflag && currlevel == 13) {
doneflag = PlaceMiniSet(L4TWARP, 1, 1, -1, -1, true);
}
ViewPosition.x++;
}
} else {
if (entry == ENTRY_MAIN) {
doneflag = PlaceMiniSet(L4USTAIRS, 1, 1, -1, -1, true);
if (doneflag) {
if (!gbIsMultiplayer && Quests[Q_DIABLO]._qactive != QUEST_ACTIVE) {
doneflag = PlaceMiniSet(L4PENTA, 1, 1, -1, -1, false);
} else {
doneflag = PlaceMiniSet(L4PENTA2, 1, 1, -1, -1, false);
}
}
ViewPosition.x++;
} else {
doneflag = PlaceMiniSet(L4USTAIRS, 1, 1, -1, -1, false);
if (doneflag) {
if (!gbIsMultiplayer && Quests[Q_DIABLO]._qactive != QUEST_ACTIVE) {
doneflag = PlaceMiniSet(L4PENTA, 1, 1, -1, -1, true);
} else {
doneflag = PlaceMiniSet(L4PENTA2, 1, 1, -1, -1, true);
}
}
ViewPosition.y++;
}
}
} while (!doneflag);
if (PlaceStairs(entry))
break;
}
GeneralFix();

2
Source/gmenu.cpp

@ -164,7 +164,7 @@ TMenuItem *sgpCurrentMenu;
void gmenu_draw_pause(const Surface &out)
{
if (currlevel != 0)
if (leveltype != DTYPE_TOWN)
RedBack(out);
if (sgpCurrentMenu == nullptr) {
LightTableIndex = 0;

6
Source/inv.cpp

@ -1728,7 +1728,7 @@ bool CanPut(Point position)
return false;
}
if (currlevel == 0) {
if (leveltype == DTYPE_TOWN) {
if (dMonster[position.x][position.y] != 0) {
return false;
}
@ -2084,11 +2084,11 @@ bool UseInvItem(int pnum, int cii)
dropGoldValue = 0;
}
if (item->isScroll() && currlevel == 0 && !spelldata[item->_iSpell].sTownSpell) {
if (item->isScroll() && leveltype == DTYPE_TOWN && !spelldata[item->_iSpell].sTownSpell) {
return true;
}
if (item->_iMiscId > IMISC_RUNEFIRST && item->_iMiscId < IMISC_RUNELAST && currlevel == 0) {
if (item->_iMiscId > IMISC_RUNEFIRST && item->_iMiscId < IMISC_RUNELAST && leveltype == DTYPE_TOWN) {
return true;
}

12
Source/items.cpp

@ -383,13 +383,13 @@ bool IsSuffixValidForItemType(int i, AffixItemType flgs)
int ItemsGetCurrlevel()
{
int lvl = currlevel;
if (currlevel >= 17 && currlevel <= 20)
lvl = currlevel - 8;
if (currlevel >= 21 && currlevel <= 24)
lvl = currlevel - 7;
if (leveltype == DTYPE_NEST)
return currlevel - 8;
if (leveltype == DTYPE_CRYPT)
return currlevel - 7;
return lvl;
return currlevel;
}
bool ItemPlace(Point position)

6
Source/lighting.cpp

@ -565,7 +565,7 @@ void DoLighting(Point position, int nRadius, int lnum)
}
if (InDungeonBounds(position)) {
if (currlevel < 17) {
if (IsNoneOf(leveltype, DTYPE_NEST, DTYPE_CRYPT)) {
SetLight(position, 0);
} else if (GetLight(position) > lightradius[nRadius][0]) {
SetLight(position, lightradius[nRadius][0]);
@ -799,7 +799,7 @@ void MakeLightTable()
}
tbl += 224;
}
if (currlevel >= 17) {
if (IsAnyOf(leveltype, DTYPE_NEST, DTYPE_CRYPT)) {
tbl = LightTables.data();
for (int i = 0; i < lights; i++) {
*tbl++ = 0;
@ -856,7 +856,7 @@ void MakeLightTable()
}
}
if (currlevel >= 17) {
if (IsAnyOf(leveltype, DTYPE_NEST, DTYPE_CRYPT)) {
for (int j = 0; j < 16; j++) {
double fa = (sqrt((double)(16 - j))) / 128;
fa *= fa;

6
Source/loadsave.cpp

@ -642,7 +642,7 @@ void LoadMonster(LoadHelper *file, Monster &monster)
monster.mlid = NO_LIGHT; // Correct incorect values in old saves
if ((monster._mFlags & MFLAG_BERSERK) != 0) {
int lightRadius = (currlevel < 17 || currlevel > 20) ? 3 : 9;
int lightRadius = leveltype == DTYPE_NEST ? 9 : 3;
monster.mlid = AddLight(monster.position.tile, lightRadius);
}
@ -1991,7 +1991,7 @@ void LoadGame(bool firstflag)
int tmpNummissiles = file.NextBE<int32_t>();
int tmpNobjects = file.NextBE<int32_t>();
if (!gbIsHellfire && currlevel > 17)
if (!gbIsHellfire && IsAnyOf(leveltype, DTYPE_NEST, DTYPE_CRYPT))
app_fatal("%s", _("Player is on a Hellfire only level").c_str());
for (uint8_t i = 0; i < giNumberOfLevels; i++) {
@ -2404,7 +2404,7 @@ void SaveLevel()
DoUnVision(myPlayer.position.tile, myPlayer._pLightRad); // fix for vision staying on the level
if (currlevel == 0)
if (leveltype == DTYPE_TOWN)
glSeedTbl[0] = AdvanceRndSeed();
char szName[MAX_PATH];

10
Source/missiles.cpp

@ -1188,7 +1188,7 @@ void AddBerserk(Missile &missile, const AddMissileParameter &parameter)
monster.mMaxDamage = (GenerateRnd(10) + 120) * monster.mMaxDamage / 100 + slvl;
monster.mMinDamage2 = (GenerateRnd(10) + 120) * monster.mMinDamage2 / 100 + slvl;
monster.mMaxDamage2 = (GenerateRnd(10) + 120) * monster.mMaxDamage2 / 100 + slvl;
int lightRadius = (currlevel < 17 || currlevel > 20) ? 3 : 9;
int lightRadius = leveltype == DTYPE_NEST ? 9 : 3;
monster.mlid = AddLight(monster.position.tile, lightRadius);
UseMana(missile._misource, SPL_BERSERK);
}
@ -1851,7 +1851,7 @@ void AddWeapexp(Missile &missile, const AddMissileParameter &parameter)
void AddTown(Missile &missile, const AddMissileParameter &parameter)
{
if (currlevel == 0) {
if (leveltype == DTYPE_TOWN) {
missile.position.tile = parameter.dst;
missile.position.start = parameter.dst;
} else {
@ -1894,7 +1894,7 @@ void AddTown(Missile &missile, const AddMissileParameter &parameter)
other._mirange = 0;
}
PutMissile(missile);
if (missile._misource == MyPlayerId && !missile._miDelFlag && currlevel != 0) {
if (missile._misource == MyPlayerId && !missile._miDelFlag && leveltype != DTYPE_TOWN) {
if (!setlevel) {
NetSendCmdLocParam3(true, CMD_ACTIVATEPORTAL, missile.position.tile, currlevel, leveltype, 0);
} else {
@ -3195,7 +3195,7 @@ void MI_Town(Missile &missile)
missile._mirange--;
if (missile._mirange == missile.var1)
SetMissDir(missile, 1);
if (currlevel != 0 && missile._mimfnum != 1 && missile._mirange != 0) {
if (leveltype != DTYPE_TOWN && missile._mimfnum != 1 && missile._mirange != 0) {
if (missile.var2 == 0)
missile._mlid = AddLight(missile.position.tile, 1);
ChangeLight(missile._mlid, missile.position.tile, expLight[missile.var2]);
@ -3973,7 +3973,7 @@ void MI_Rportal(Missile &missile)
if (missile._mirange == missile.var1)
SetMissDir(missile, 1);
if (currlevel != 0 && missile._mimfnum != 1 && missile._mirange != 0) {
if (leveltype != DTYPE_TOWN && missile._mimfnum != 1 && missile._mirange != 0) {
if (missile.var2 == 0)
missile._mlid = AddLight(missile.position.tile, 1);
ChangeLight(missile._mlid, missile.position.tile, expLight[missile.var2]);

2
Source/monster.cpp

@ -3852,7 +3852,7 @@ void InitMonsters()
int mtype = scattertypes[GenerateRnd(numscattypes)];
if (currlevel == 1 || GenerateRnd(2) == 0)
na = 1;
else if (currlevel == 2 || (currlevel >= 21 && currlevel <= 24))
else if (currlevel == 2 || leveltype == DTYPE_CRYPT)
na = GenerateRnd(2) + 2;
else
na = GenerateRnd(3) + 3;

28
Source/msg.cpp

@ -432,10 +432,10 @@ void DeltaLeaveSync(uint8_t bLevel)
{
if (!gbIsMultiplayer)
return;
if (currlevel == 0)
if (leveltype == DTYPE_TOWN) {
glSeedTbl[0] = AdvanceRndSeed();
if (currlevel <= 0)
return;
}
for (int i = 0; i < ActiveMonsterCount; i++) {
int ma = ActiveMonsters[i];
@ -1035,7 +1035,7 @@ DWORD OnSpellWall(const TCmd *pCmd, Player &player)
return sizeof(message);
auto spell = static_cast<spell_id>(message.wParam1);
if (currlevel == 0 && !spelldata[spell].sTownSpell) {
if (leveltype == DTYPE_TOWN && !spelldata[spell].sTownSpell) {
LogError(_("{:s} has cast an illegal spell.").c_str(), player._pName);
return sizeof(message);
}
@ -1070,7 +1070,7 @@ DWORD OnSpellTile(const TCmd *pCmd, Player &player)
return sizeof(message);
auto spell = static_cast<spell_id>(message.wParam1);
if (currlevel == 0 && !spelldata[spell].sTownSpell) {
if (leveltype == DTYPE_TOWN && !spelldata[spell].sTownSpell) {
LogError(_("{:s} has cast an illegal spell.").c_str(), player._pName);
return sizeof(message);
}
@ -1101,7 +1101,7 @@ DWORD OnTargetSpellTile(const TCmd *pCmd, Player &player)
return sizeof(message);
auto spell = static_cast<spell_id>(message.wParam1);
if (currlevel == 0 && !spelldata[spell].sTownSpell) {
if (leveltype == DTYPE_TOWN && !spelldata[spell].sTownSpell) {
LogError(_("{:s} has cast an illegal spell.").c_str(), player._pName);
return sizeof(message);
}
@ -1228,7 +1228,7 @@ DWORD OnSpellMonster(const TCmd *pCmd, Player &player)
return sizeof(message);
auto spell = static_cast<spell_id>(message.wParam2);
if (currlevel == 0 && !spelldata[spell].sTownSpell) {
if (leveltype == DTYPE_TOWN && !spelldata[spell].sTownSpell) {
LogError(_("{:s} has cast an illegal spell.").c_str(), player._pName);
return sizeof(message);
}
@ -1260,7 +1260,7 @@ DWORD OnSpellPlayer(const TCmd *pCmd, Player &player)
return sizeof(message);
auto spell = static_cast<spell_id>(message.wParam2);
if (currlevel == 0 && !spelldata[spell].sTownSpell) {
if (leveltype == DTYPE_TOWN && !spelldata[spell].sTownSpell) {
LogError(_("{:s} has cast an illegal spell.").c_str(), player._pName);
return sizeof(message);
}
@ -1292,7 +1292,7 @@ DWORD OnTargetSpellMonster(const TCmd *pCmd, Player &player)
return sizeof(message);
auto spell = static_cast<spell_id>(message.wParam2);
if (currlevel == 0 && !spelldata[spell].sTownSpell) {
if (leveltype == DTYPE_TOWN && !spelldata[spell].sTownSpell) {
LogError(_("{:s} has cast an illegal spell.").c_str(), player._pName);
return sizeof(message);
}
@ -1322,7 +1322,7 @@ DWORD OnTargetSpellPlayer(const TCmd *pCmd, Player &player)
return sizeof(message);
auto spell = static_cast<spell_id>(message.wParam2);
if (currlevel == 0 && !spelldata[spell].sTownSpell) {
if (leveltype == DTYPE_TOWN && !spelldata[spell].sTownSpell) {
LogError(_("{:s} has cast an illegal spell.").c_str(), player._pName);
return sizeof(message);
}
@ -1530,7 +1530,7 @@ DWORD OnPlayerDamage(const TCmd *pCmd, Player &player)
{
const auto &message = *reinterpret_cast<const TCmdDamage *>(pCmd);
if (message.bPlr == MyPlayerId && currlevel != 0 && gbBufferMsgs != 1) {
if (message.bPlr == MyPlayerId && leveltype != DTYPE_TOWN && gbBufferMsgs != 1) {
if (currlevel == player.plrlevel && message.dwDam <= 192000 && Players[message.bPlr]._pHitPoints >> 6 > 0) {
ApplyPlrDamage(message.bPlr, 0, 0, message.dwDam, 1);
}
@ -1771,7 +1771,7 @@ DWORD OnActivatePortal(const TCmd *pCmd, int pnum)
ActivatePortal(pnum, position, level, dungeonType, isSetLevel);
if (pnum != MyPlayerId) {
if (currlevel == 0) {
if (leveltype == DTYPE_TOWN) {
AddInTownPortal(pnum);
} else if (currlevel == Players[pnum].plrlevel) {
bool addPortal = true;
@ -2012,7 +2012,7 @@ DWORD OnOpenCrypt(const TCmd *pCmd)
if (gbBufferMsgs != 1) {
TownOpenGrave();
InitTownTriggers();
if (currlevel == 0)
if (leveltype == DTYPE_TOWN)
PlaySFX(IS_SARC);
}
return sizeof(*pCmd);
@ -2270,7 +2270,7 @@ void DeltaLoadLevel()
return;
deltaload = true;
if (currlevel != 0) {
if (leveltype != DTYPE_TOWN) {
for (int i = 0; i < ActiveMonsterCount; i++) {
if (sgLevels[currlevel].monster[i]._mx == 0xFF)
continue;
@ -2376,7 +2376,7 @@ void DeltaLoadLevel()
}
}
if (currlevel != 0) {
if (leveltype != DTYPE_TOWN) {
for (int i = 0; i < MAXOBJECTS; i++) {
switch (sgLevels[currlevel].object[i].bCmd) {
case CMD_OPENDOOR:

9
Source/objects.cpp

@ -3762,9 +3762,7 @@ void OperateArmorStand(int pnum, int i, bool sendmsg)
CreateTypeItem(Objects[i].position, uniqueRnd, ItemType::MediumArmor, IMISC_NONE, sendmsg, false);
} else if (currlevel >= 10 && currlevel <= 12) {
CreateTypeItem(Objects[i].position, false, ItemType::HeavyArmor, IMISC_NONE, sendmsg, false);
} else if (currlevel >= 13 && currlevel <= 16) {
CreateTypeItem(Objects[i].position, true, ItemType::HeavyArmor, IMISC_NONE, sendmsg, false);
} else if (currlevel >= 17) {
} else if (currlevel >= 13) {
CreateTypeItem(Objects[i].position, true, ItemType::HeavyArmor, IMISC_NONE, sendmsg, false);
}
if (pnum == MyPlayerId)
@ -4637,7 +4635,7 @@ void InitObjects()
}
InitRndBarrels();
}
if (IsAnyOf(leveltype, DTYPE_CAVES, DTYPE_NEST)) {
if (leveltype == DTYPE_CAVES) {
AddL3Objs(0, 0, MAXDUNX, MAXDUNY);
InitRndBarrels();
}
@ -4673,6 +4671,9 @@ void InitObjects()
InitRndBarrels();
AddL4Goodies();
}
if (leveltype == DTYPE_NEST) {
InitRndBarrels();
}
if (leveltype == DTYPE_CRYPT) {
InitRndLocBigObj(10, 15, OBJ_L5SARC);
AddCryptObjects(0, 0, MAXDUNX, MAXDUNY);

2
Source/panels/spell_book.cpp

@ -71,7 +71,7 @@ spell_type GetSBookTrans(spell_id ii, bool townok)
st = RSPLTYPE_INVALID;
}
}
if (townok && currlevel == 0 && st != RSPLTYPE_INVALID && !spelldata[ii].sTownSpell) {
if (townok && leveltype == DTYPE_TOWN && st != RSPLTYPE_INVALID && !spelldata[ii].sTownSpell) {
st = RSPLTYPE_INVALID;
}

4
Source/panels/spell_list.cpp

@ -110,7 +110,7 @@ void DrawSpell(const Surface &out)
if (tlvl <= 0)
st = RSPLTYPE_INVALID;
}
if (currlevel == 0 && st != RSPLTYPE_INVALID && !spelldata[spl].sTownSpell)
if (leveltype == DTYPE_TOWN && st != RSPLTYPE_INVALID && !spelldata[spl].sTownSpell)
st = RSPLTYPE_INVALID;
SetSpellTrans(st);
const int nCel = (spl != SPL_INVALID) ? SpellITbl[spl] : 26;
@ -134,7 +134,7 @@ void DrawSpellList(const Surface &out)
spell_type transType = spellListItem.type;
int spellLevel = 0;
const SpellData &spellDataItem = spelldata[static_cast<size_t>(spellListItem.id)];
if (currlevel == 0 && !spellDataItem.sTownSpell) {
if (leveltype == DTYPE_TOWN && !spellDataItem.sTownSpell) {
transType = RSPLTYPE_INVALID;
}
if (spellListItem.type == RSPLTYPE_SPELL) {

18
Source/player.cpp

@ -341,7 +341,7 @@ void HandleWalkMode(int pnum, Displacement vel, Direction dir)
void StartWalkAnimation(Player &player, Direction dir, bool pmWillBeCalled)
{
int skippedFrames = -2;
if (currlevel == 0 && sgGameInitInfo.bRunInTown != 0)
if (leveltype == DTYPE_TOWN && sgGameInitInfo.bRunInTown != 0)
skippedFrames = 2;
if (pmWillBeCalled)
skippedFrames += 1;
@ -416,7 +416,7 @@ void ChangeOffset(int pnum)
player.position.offset2 += player.position.velocity;
if (currlevel == 0 && sgGameInitInfo.bRunInTown != 0) {
if (leveltype == DTYPE_TOWN && sgGameInitInfo.bRunInTown != 0) {
player.position.offset2 += player.position.velocity;
}
@ -661,7 +661,7 @@ bool DoWalk(int pnum, int variant)
Player &player = Players[pnum];
// Play walking sound effect on certain animation frames
if (*sgOptions.Audio.walkingSound && (currlevel != 0 || sgGameInitInfo.bRunInTown == 0)) {
if (*sgOptions.Audio.walkingSound && (leveltype != DTYPE_TOWN || sgGameInitInfo.bRunInTown == 0)) {
if (player.AnimInfo.CurrentFrame == 0
|| player.AnimInfo.CurrentFrame == 4) {
PlaySfxLoc(PS_WALK1, player.position.tile);
@ -1528,7 +1528,7 @@ void CheckNewPath(int pnum, bool pmWillBeCalled)
int xvel3 = 2048;
int xvel = 1024;
int yvel = 512;
if (currlevel != 0) {
if (leveltype != DTYPE_TOWN) {
xvel3 = PWVel[static_cast<std::size_t>(player._pClass)][0];
xvel = PWVel[static_cast<std::size_t>(player._pClass)][1];
yvel = PWVel[static_cast<std::size_t>(player._pClass)][2];
@ -2803,7 +2803,7 @@ void InitPlayer(Player &player, bool firstTime)
player._pdir = Direction::South;
if (&player == &myPlayer) {
if (!firstTime || currlevel != 0) {
if (!firstTime || leveltype != DTYPE_TOWN) {
player.position.tile = ViewPosition;
}
} else {
@ -3211,7 +3211,7 @@ void SyncPlrKill(int pnum, int earflag)
{
Player &player = Players[pnum];
if (player._pHitPoints <= 0 && currlevel == 0) {
if (player._pHitPoints <= 0 && leveltype == DTYPE_TOWN) {
SetPlayerHitPoints(player, 64);
return;
}
@ -3222,7 +3222,7 @@ void SyncPlrKill(int pnum, int earflag)
void RemovePlrMissiles(int pnum)
{
if (currlevel != 0 && pnum == MyPlayerId) {
if (leveltype != DTYPE_TOWN && pnum == MyPlayerId) {
auto &golem = Monsters[MyPlayerId];
if (golem.position.tile.x != 1 || golem.position.tile.y != 0) {
M_StartKill(MyPlayerId, MyPlayerId);
@ -3378,7 +3378,7 @@ void ProcessPlayers()
}
if (pnum == MyPlayerId) {
if (HasAnyOf(player._pIFlags, ItemSpecialEffect::DrainLife) && currlevel != 0) {
if (HasAnyOf(player._pIFlags, ItemSpecialEffect::DrainLife) && leveltype != DTYPE_TOWN) {
ApplyPlrDamage(pnum, 0, 0, 4);
}
if (HasAnyOf(player._pIFlags, ItemSpecialEffect::NoMana) && player._pManaBase > 0) {
@ -3458,7 +3458,7 @@ bool PosOkPlayer(const Player &player, Point position)
}
if (dMonster[position.x][position.y] != 0) {
if (currlevel == 0) {
if (leveltype == DTYPE_TOWN) {
return false;
}
if (dMonster[position.x][position.y] <= 0) {

10
Source/portal.cpp

@ -55,7 +55,7 @@ void AddWarpMissile(int i, Point position)
if (missile != nullptr) {
SetMissDir(*missile, 1);
if (currlevel != 0)
if (leveltype != DTYPE_TOWN)
missile->_mlid = AddLight(missile->position.tile, 15);
}
@ -67,7 +67,7 @@ void SyncPortals()
for (int i = 0; i < MAXPORTAL; i++) {
if (!Portals[i].open)
continue;
if (currlevel == 0)
if (leveltype == DTYPE_TOWN)
AddWarpMissile(i, WarpDrop[i]);
else {
int lvl = currlevel;
@ -106,7 +106,7 @@ bool PortalOnLevel(int i)
if (Portals[i].level == currlevel)
return true;
return currlevel == 0;
return leveltype == DTYPE_TOWN;
}
void RemovePortalMissile(int id)
@ -131,7 +131,7 @@ void SetCurrentPortal(int p)
void GetPortalLevel()
{
if (currlevel != 0) {
if (leveltype != DTYPE_TOWN) {
setlevel = false;
currlevel = 0;
MyPlayer->plrlevel = 0;
@ -160,7 +160,7 @@ void GetPortalLevel()
void GetPortalLvlPos()
{
if (currlevel == 0) {
if (leveltype == DTYPE_TOWN) {
ViewPosition = WarpDrop[portalindex] + Displacement { 1, 1 };
} else {
ViewPosition = Portals[portalindex].position;

2
Source/qol/monhealthbar.cpp

@ -66,7 +66,7 @@ void DrawMonsterHealthBar(const Surface &out)
assert(healthBlue.surface != nullptr);
assert(resistance.surface != nullptr);
if (currlevel == 0)
if (leveltype == DTYPE_TOWN)
return;
if (pcursmonst == -1)
return;

2
Source/qol/stash.cpp

@ -474,7 +474,7 @@ bool UseStashItem(uint16_t c)
return true;
}
if (item->_iMiscId > IMISC_RUNEFIRST && item->_iMiscId < IMISC_RUNELAST && currlevel == 0) {
if (item->_iMiscId > IMISC_RUNEFIRST && item->_iMiscId < IMISC_RUNELAST && leveltype == DTYPE_TOWN) {
return true;
}

2
Source/scrollrt.cpp

@ -582,7 +582,7 @@ void DrawDeadPlayer(const Surface &out, Point tilePosition, Point targetBufferPo
for (int i = 0; i < MAX_PLRS; i++) {
Player &player = Players[i];
if (player.plractive && player._pHitPoints == 0 && player.plrlevel == (BYTE)currlevel && player.position.tile == tilePosition) {
if (player.plractive && player._pHitPoints == 0 && player.plrlevel == currlevel && player.position.tile == tilePosition) {
dFlags[tilePosition.x][tilePosition.y] |= DungeonFlag::DeadPlayer;
const Point playerRenderPosition { targetBufferPosition + player.position.offset };
DrawPlayer(out, i, tilePosition, playerRenderPosition);

420
Source/trigs.cpp

@ -144,40 +144,17 @@ void InitTownTriggers()
void InitL1Triggers()
{
numtrigs = 0;
if (currlevel < 17) {
for (int j = 0; j < MAXDUNY; j++) {
for (int i = 0; i < MAXDUNX; i++) {
if (dPiece[i][j] == 129) {
trigs[numtrigs].position = { i, j };
trigs[numtrigs]._tmsg = WM_DIABPREVLVL;
numtrigs++;
}
if (dPiece[i][j] == 115) {
trigs[numtrigs].position = { i, j };
trigs[numtrigs]._tmsg = WM_DIABNEXTLVL;
numtrigs++;
}
for (int j = 0; j < MAXDUNY; j++) {
for (int i = 0; i < MAXDUNX; i++) {
if (dPiece[i][j] == 129) {
trigs[numtrigs].position = { i, j };
trigs[numtrigs]._tmsg = WM_DIABPREVLVL;
numtrigs++;
}
}
} else {
for (int j = 0; j < MAXDUNY; j++) {
for (int i = 0; i < MAXDUNX; i++) {
if (dPiece[i][j] == 184) {
trigs[numtrigs].position = { i, j };
trigs[numtrigs]._tmsg = WM_DIABTWARPUP;
trigs[numtrigs]._tlvl = 0;
numtrigs++;
}
if (dPiece[i][j] == 158) {
trigs[numtrigs].position = { i, j };
trigs[numtrigs]._tmsg = WM_DIABPREVLVL;
numtrigs++;
}
if (dPiece[i][j] == 126) {
trigs[numtrigs].position = { i, j };
trigs[numtrigs]._tmsg = WM_DIABNEXTLVL;
numtrigs++;
}
if (dPiece[i][j] == 115) {
trigs[numtrigs].position = { i, j };
trigs[numtrigs]._tmsg = WM_DIABNEXTLVL;
numtrigs++;
}
}
}
@ -214,50 +191,25 @@ void InitL2Triggers()
void InitL3Triggers()
{
if (currlevel < 17) {
numtrigs = 0;
for (int j = 0; j < MAXDUNY; j++) {
for (int i = 0; i < MAXDUNX; i++) {
if (dPiece[i][j] == 171) {
trigs[numtrigs].position = { i, j };
trigs[numtrigs]._tmsg = WM_DIABPREVLVL;
numtrigs++;
}
if (dPiece[i][j] == 168) {
trigs[numtrigs].position = { i, j };
trigs[numtrigs]._tmsg = WM_DIABNEXTLVL;
numtrigs++;
}
if (dPiece[i][j] == 549) {
trigs[numtrigs].position = { i, j };
trigs[numtrigs]._tmsg = WM_DIABTWARPUP;
numtrigs++;
}
numtrigs = 0;
for (int j = 0; j < MAXDUNY; j++) {
for (int i = 0; i < MAXDUNX; i++) {
if (dPiece[i][j] == 171) {
trigs[numtrigs].position = { i, j };
trigs[numtrigs]._tmsg = WM_DIABPREVLVL;
numtrigs++;
}
}
} else {
numtrigs = 0;
for (int j = 0; j < MAXDUNY; j++) {
for (int i = 0; i < MAXDUNX; i++) {
if (dPiece[i][j] == 66) {
trigs[numtrigs].position = { i, j };
trigs[numtrigs]._tmsg = WM_DIABPREVLVL;
numtrigs++;
}
if (dPiece[i][j] == 63) {
trigs[numtrigs].position = { i, j };
trigs[numtrigs]._tmsg = WM_DIABNEXTLVL;
numtrigs++;
}
if (dPiece[i][j] == 168) {
trigs[numtrigs].position = { i, j };
trigs[numtrigs]._tmsg = WM_DIABNEXTLVL;
numtrigs++;
}
if (dPiece[i][j] == 80) {
trigs[numtrigs].position = { i, j };
trigs[numtrigs]._tmsg = WM_DIABTWARPUP;
numtrigs++;
}
if (dPiece[i][j] == 549) {
trigs[numtrigs].position = { i, j };
trigs[numtrigs]._tmsg = WM_DIABTWARPUP;
numtrigs++;
}
}
}
@ -302,6 +254,59 @@ void InitL4Triggers()
trigflag = false;
}
void InitHiveTriggers()
{
numtrigs = 0;
for (int j = 0; j < MAXDUNY; j++) {
for (int i = 0; i < MAXDUNX; i++) {
if (dPiece[i][j] == 66) {
trigs[numtrigs].position = { i, j };
trigs[numtrigs]._tmsg = WM_DIABPREVLVL;
numtrigs++;
}
if (dPiece[i][j] == 63) {
trigs[numtrigs].position = { i, j };
trigs[numtrigs]._tmsg = WM_DIABNEXTLVL;
numtrigs++;
}
if (dPiece[i][j] == 80) {
trigs[numtrigs].position = { i, j };
trigs[numtrigs]._tmsg = WM_DIABTWARPUP;
numtrigs++;
}
}
}
trigflag = false;
}
void InitCryptTriggers()
{
numtrigs = 0;
for (int j = 0; j < MAXDUNY; j++) {
for (int i = 0; i < MAXDUNX; i++) {
if (dPiece[i][j] == 184) {
trigs[numtrigs].position = { i, j };
trigs[numtrigs]._tmsg = WM_DIABTWARPUP;
trigs[numtrigs]._tlvl = 0;
numtrigs++;
}
if (dPiece[i][j] == 158) {
trigs[numtrigs].position = { i, j };
trigs[numtrigs]._tmsg = WM_DIABPREVLVL;
numtrigs++;
}
if (dPiece[i][j] == 126) {
trigs[numtrigs].position = { i, j };
trigs[numtrigs]._tmsg = WM_DIABNEXTLVL;
numtrigs++;
}
}
}
trigflag = false;
}
void InitSKingTriggers()
{
trigflag = false;
@ -407,73 +412,27 @@ bool ForceTownTrig()
bool ForceL1Trig()
{
if (currlevel < 17) {
for (int i = 0; L1UpList[i] != -1; i++) {
if (dPiece[cursPosition.x][cursPosition.y] == L1UpList[i]) {
if (currlevel > 1)
InfoString = fmt::format(_("Up to level {:d}"), currlevel - 1);
else
InfoString = _("Up to town");
for (int j = 0; j < numtrigs; j++) {
if (trigs[j]._tmsg == WM_DIABPREVLVL) {
cursPosition = trigs[j].position;
return true;
}
}
}
}
for (int i = 0; L1DownList[i] != -1; i++) {
if (dPiece[cursPosition.x][cursPosition.y] == L1DownList[i]) {
InfoString = fmt::format(_("Down to level {:d}"), currlevel + 1);
for (int j = 0; j < numtrigs; j++) {
if (trigs[j]._tmsg == WM_DIABNEXTLVL) {
cursPosition = trigs[j].position;
return true;
}
}
}
}
} else {
for (int i = 0; L5UpList[i] != -1; i++) {
if (dPiece[cursPosition.x][cursPosition.y] == L5UpList[i]) {
InfoString = fmt::format(_("Up to Crypt level {:d}"), currlevel - 21);
for (int j = 0; j < numtrigs; j++) {
if (trigs[j]._tmsg == WM_DIABPREVLVL) {
cursPosition = trigs[j].position;
return true;
}
}
}
}
if (dPiece[cursPosition.x][cursPosition.y] == 317) {
InfoString = _("Cornerstone of the World");
return true;
}
for (int i = 0; L5DownList[i] != -1; i++) {
if (dPiece[cursPosition.x][cursPosition.y] == L5DownList[i]) {
InfoString = fmt::format(_("Down to Crypt level {:d}"), currlevel - 19);
for (int j = 0; j < numtrigs; j++) {
if (trigs[j]._tmsg == WM_DIABNEXTLVL) {
cursPosition = trigs[j].position;
return true;
}
for (int i = 0; L1UpList[i] != -1; i++) {
if (dPiece[cursPosition.x][cursPosition.y] == L1UpList[i]) {
if (currlevel > 1)
InfoString = fmt::format(_("Up to level {:d}"), currlevel - 1);
else
InfoString = _("Up to town");
for (int j = 0; j < numtrigs; j++) {
if (trigs[j]._tmsg == WM_DIABPREVLVL) {
cursPosition = trigs[j].position;
return true;
}
}
}
if (currlevel == 21) {
for (int i = 0; L5TWarpUpList[i] != -1; i++) {
if (dPiece[cursPosition.x][cursPosition.y] == L5TWarpUpList[i]) {
for (int j = 0; j < numtrigs; j++) {
if (trigs[j]._tmsg == WM_DIABTWARPUP) {
int dx = abs(trigs[j].position.x - cursPosition.x);
int dy = abs(trigs[j].position.y - cursPosition.y);
if (dx < 4 && dy < 4) {
InfoString = _("Up to town");
cursPosition = trigs[j].position;
return true;
}
}
}
}
for (int i = 0; L1DownList[i] != -1; i++) {
if (dPiece[cursPosition.x][cursPosition.y] == L1DownList[i]) {
InfoString = fmt::format(_("Down to level {:d}"), currlevel + 1);
for (int j = 0; j < numtrigs; j++) {
if (trigs[j]._tmsg == WM_DIABNEXTLVL) {
cursPosition = trigs[j].position;
return true;
}
}
}
@ -535,57 +494,30 @@ bool ForceL2Trig()
bool ForceL3Trig()
{
if (currlevel < 17) {
for (int i = 0; L3UpList[i] != -1; ++i) {
if (dPiece[cursPosition.x][cursPosition.y] == L3UpList[i]) {
InfoString = fmt::format(_("Up to level {:d}"), currlevel - 1);
for (int j = 0; j < numtrigs; j++) {
if (trigs[j]._tmsg == WM_DIABPREVLVL) {
int dx = abs(trigs[j].position.x - cursPosition.x);
int dy = abs(trigs[j].position.y - cursPosition.y);
if (dx < 4 && dy < 4) {
cursPosition = trigs[j].position;
return true;
}
}
}
}
}
for (int i = 0; L3DownList[i] != -1; i++) {
if (dPiece[cursPosition.x][cursPosition.y] == L3DownList[i]
|| dPiece[cursPosition.x + 1][cursPosition.y] == L3DownList[i]
|| dPiece[cursPosition.x + 2][cursPosition.y] == L3DownList[i]) {
InfoString = fmt::format(_("Down to level {:d}"), currlevel + 1);
for (int j = 0; j < numtrigs; j++) {
if (trigs[j]._tmsg == WM_DIABNEXTLVL) {
cursPosition = trigs[j].position;
return true;
}
}
}
}
} else {
for (int i = 0; L6UpList[i] != -1; ++i) {
if (dPiece[cursPosition.x][cursPosition.y] == L6UpList[i]) {
InfoString = fmt::format(_("Up to Nest level {:d}"), currlevel - 17);
for (int j = 0; j < numtrigs; j++) {
if (trigs[j]._tmsg == WM_DIABPREVLVL) {
for (int i = 0; L3UpList[i] != -1; ++i) {
if (dPiece[cursPosition.x][cursPosition.y] == L3UpList[i]) {
InfoString = fmt::format(_("Up to level {:d}"), currlevel - 1);
for (int j = 0; j < numtrigs; j++) {
if (trigs[j]._tmsg == WM_DIABPREVLVL) {
int dx = abs(trigs[j].position.x - cursPosition.x);
int dy = abs(trigs[j].position.y - cursPosition.y);
if (dx < 4 && dy < 4) {
cursPosition = trigs[j].position;
return true;
}
}
}
}
for (int i = 0; L6DownList[i] != -1; i++) {
if (dPiece[cursPosition.x][cursPosition.y] == L6DownList[i]
|| dPiece[cursPosition.x + 1][cursPosition.y] == L6DownList[i]
|| dPiece[cursPosition.x + 2][cursPosition.y] == L6DownList[i]) {
InfoString = fmt::format(_("Down to level {:d}"), currlevel - 15);
for (int j = 0; j < numtrigs; j++) {
if (trigs[j]._tmsg == WM_DIABNEXTLVL) {
cursPosition = trigs[j].position;
return true;
}
}
for (int i = 0; L3DownList[i] != -1; i++) {
if (dPiece[cursPosition.x][cursPosition.y] == L3DownList[i]
|| dPiece[cursPosition.x + 1][cursPosition.y] == L3DownList[i]
|| dPiece[cursPosition.x + 2][cursPosition.y] == L3DownList[i]) {
InfoString = fmt::format(_("Down to level {:d}"), currlevel + 1);
for (int j = 0; j < numtrigs; j++) {
if (trigs[j]._tmsg == WM_DIABNEXTLVL) {
cursPosition = trigs[j].position;
return true;
}
}
}
@ -608,23 +540,6 @@ bool ForceL3Trig()
}
}
}
if (currlevel == 17) {
for (int i = 0; L6TWarpUpList[i] != -1; i++) {
if (dPiece[cursPosition.x][cursPosition.y] == L6TWarpUpList[i]) {
for (int j = 0; j < numtrigs; j++) {
if (trigs[j]._tmsg == WM_DIABTWARPUP) {
int dx = abs(trigs[j].position.x - cursPosition.x);
int dy = abs(trigs[j].position.y - cursPosition.y);
if (dx < 4 && dy < 4) {
InfoString = _("Up to town");
cursPosition = trigs[j].position;
return true;
}
}
}
}
}
}
return false;
}
@ -690,6 +605,103 @@ bool ForceL4Trig()
return false;
}
bool ForceHiveTrig()
{
for (int i = 0; L6UpList[i] != -1; ++i) {
if (dPiece[cursPosition.x][cursPosition.y] == L6UpList[i]) {
InfoString = fmt::format(_("Up to Nest level {:d}"), currlevel - 17);
for (int j = 0; j < numtrigs; j++) {
if (trigs[j]._tmsg == WM_DIABPREVLVL) {
cursPosition = trigs[j].position;
return true;
}
}
}
}
for (int i = 0; L6DownList[i] != -1; i++) {
if (dPiece[cursPosition.x][cursPosition.y] == L6DownList[i]
|| dPiece[cursPosition.x + 1][cursPosition.y] == L6DownList[i]
|| dPiece[cursPosition.x + 2][cursPosition.y] == L6DownList[i]) {
InfoString = fmt::format(_("Down to level {:d}"), currlevel - 15);
for (int j = 0; j < numtrigs; j++) {
if (trigs[j]._tmsg == WM_DIABNEXTLVL) {
cursPosition = trigs[j].position;
return true;
}
}
}
}
if (currlevel == 17) {
for (int i = 0; L6TWarpUpList[i] != -1; i++) {
if (dPiece[cursPosition.x][cursPosition.y] == L6TWarpUpList[i]) {
for (int j = 0; j < numtrigs; j++) {
if (trigs[j]._tmsg == WM_DIABTWARPUP) {
int dx = abs(trigs[j].position.x - cursPosition.x);
int dy = abs(trigs[j].position.y - cursPosition.y);
if (dx < 4 && dy < 4) {
InfoString = _("Up to town");
cursPosition = trigs[j].position;
return true;
}
}
}
}
}
}
return false;
}
bool ForceCryptTrig()
{
for (int i = 0; L5UpList[i] != -1; i++) {
if (dPiece[cursPosition.x][cursPosition.y] == L5UpList[i]) {
InfoString = fmt::format(_("Up to Crypt level {:d}"), currlevel - 21);
for (int j = 0; j < numtrigs; j++) {
if (trigs[j]._tmsg == WM_DIABPREVLVL) {
cursPosition = trigs[j].position;
return true;
}
}
}
}
if (dPiece[cursPosition.x][cursPosition.y] == 317) {
InfoString = _("Cornerstone of the World");
return true;
}
for (int i = 0; L5DownList[i] != -1; i++) {
if (dPiece[cursPosition.x][cursPosition.y] == L5DownList[i]) {
InfoString = fmt::format(_("Down to Crypt level {:d}"), currlevel - 19);
for (int j = 0; j < numtrigs; j++) {
if (trigs[j]._tmsg == WM_DIABNEXTLVL) {
cursPosition = trigs[j].position;
return true;
}
}
}
}
if (currlevel == 21) {
for (int i = 0; L5TWarpUpList[i] != -1; i++) {
if (dPiece[cursPosition.x][cursPosition.y] == L5TWarpUpList[i]) {
for (int j = 0; j < numtrigs; j++) {
if (trigs[j]._tmsg == WM_DIABTWARPUP) {
int dx = abs(trigs[j].position.x - cursPosition.x);
int dy = abs(trigs[j].position.y - cursPosition.y);
if (dx < 4 && dy < 4) {
InfoString = _("Up to town");
cursPosition = trigs[j].position;
return true;
}
}
}
}
}
}
return false;
}
void Freeupstairs()
{
for (int i = 0; i < numtrigs; i++) {
@ -760,19 +772,23 @@ void CheckTrigForce()
trigflag = ForceTownTrig();
break;
case DTYPE_CATHEDRAL:
case DTYPE_CRYPT:
trigflag = ForceL1Trig();
break;
case DTYPE_CATACOMBS:
trigflag = ForceL2Trig();
break;
case DTYPE_CAVES:
case DTYPE_NEST:
trigflag = ForceL3Trig();
break;
case DTYPE_HELL:
trigflag = ForceL4Trig();
break;
case DTYPE_NEST:
trigflag = ForceHiveTrig();
break;
case DTYPE_CRYPT:
trigflag = ForceCryptTrig();
break;
default:
break;
}

2
Source/trigs.h

@ -31,6 +31,8 @@ void InitL1Triggers();
void InitL2Triggers();
void InitL3Triggers();
void InitL4Triggers();
void InitHiveTriggers();
void InitCryptTriggers();
void InitSKingTriggers();
void InitSChambTriggers();
void InitPWaterTriggers();

6
test/drlg_l1_test.cpp

@ -50,6 +50,8 @@ TEST(Drlg_l1, CreateL5Dungeon_diablo_2_1383137027)
EXPECT_EQ(ViewPosition, Point(57, 74));
TestCreateDungeon(2, 1383137027, ENTRY_PREV);
EXPECT_EQ(ViewPosition, Point(57, 79));
TestCreateDungeon(2, 1383137027, ENTRY_RTNLVL);
EXPECT_EQ(ViewPosition, Point(49, 89));
}
TEST(Drlg_l1, CreateL5Dungeon_diablo_3_844660068)
@ -180,8 +182,8 @@ TEST(Drlg_l1, CreateL5Dungeon_crypt_1_2122696790)
{
LoadExpectedLevelData("hellfire/21-2122696790.dun");
TestCreateDungeon(21, 2122696790, ENTRY_TWARPUP);
EXPECT_EQ(ViewPosition, Point(61, 80));
TestCreateDungeon(21, 2122696790, ENTRY_TWARPDN);
EXPECT_EQ(ViewPosition, Point(61, 81));
TestCreateDungeon(21, 2122696790, ENTRY_PREV);
EXPECT_EQ(ViewPosition, Point(53, 67));
}

4
test/drlg_l2_test.cpp

@ -20,7 +20,7 @@ TEST(Drlg_l2, CreateL2Dungeon_diablo_5_1677631846)
EXPECT_EQ(ViewPosition, Point(27, 28));
TestCreateDungeon(5, 1677631846, ENTRY_PREV);
EXPECT_EQ(ViewPosition, Point(26, 62));
TestCreateDungeon(5, 1677631846, ENTRY_TWARPUP);
TestCreateDungeon(5, 1677631846, ENTRY_TWARPDN);
EXPECT_EQ(ViewPosition, Point(33, 56));
}
@ -35,7 +35,7 @@ TEST(Drlg_l2, CreateL2Dungeon_diablo_5_68685319)
EXPECT_EQ(ViewPosition, Point(37, 36));
TestCreateDungeon(5, 68685319, ENTRY_PREV);
EXPECT_EQ(ViewPosition, Point(44, 28));
TestCreateDungeon(5, 68685319, ENTRY_TWARPUP);
TestCreateDungeon(5, 68685319, ENTRY_TWARPDN);
EXPECT_EQ(ViewPosition, Point(45, 76));
}

4
test/drlg_l3_test.cpp

@ -17,7 +17,7 @@ TEST(Drlg_l3, CreateL3Dungeon_diablo_9_262005438)
EXPECT_EQ(ViewPosition, Point(41, 73));
TestCreateDungeon(9, 262005438, ENTRY_PREV);
EXPECT_EQ(ViewPosition, Point(73, 59));
TestCreateDungeon(9, 262005438, ENTRY_TWARPUP);
TestCreateDungeon(9, 262005438, ENTRY_TWARPDN);
EXPECT_EQ(ViewPosition, Point(37, 35));
}
@ -70,7 +70,7 @@ TEST(Drlg_l3, CreateL3Dungeon_hive_1_19770182)
{
LoadExpectedLevelData("hellfire/17-19770182.dun");
TestCreateDungeon(17, 19770182, ENTRY_TWARPUP);
TestCreateDungeon(17, 19770182, ENTRY_TWARPDN);
EXPECT_EQ(ViewPosition, Point(75, 81));
TestCreateDungeon(17, 19770182, ENTRY_PREV);
EXPECT_EQ(ViewPosition, Point(59, 41));

4
test/drlg_l4_test.cpp

@ -21,7 +21,7 @@ TEST(Drlg_l4, CreateL4Dungeon_diablo_13_428074402)
EXPECT_EQ(ViewPosition, Point(26, 64));
TestCreateDungeon(13, 428074402, ENTRY_PREV);
EXPECT_EQ(ViewPosition, Point(47, 79));
TestCreateDungeon(13, 428074402, ENTRY_TWARPUP);
TestCreateDungeon(13, 428074402, ENTRY_TWARPDN);
EXPECT_EQ(ViewPosition, Point(26, 44));
}
@ -36,7 +36,7 @@ TEST(Drlg_l4, CreateL4Dungeon_diablo_13_594689775)
EXPECT_EQ(ViewPosition, Point(72, 38));
TestCreateDungeon(13, 594689775, ENTRY_PREV);
EXPECT_EQ(ViewPosition, Point(32, 40));
TestCreateDungeon(13, 594689775, ENTRY_TWARPUP);
TestCreateDungeon(13, 594689775, ENTRY_TWARPDN);
EXPECT_EQ(ViewPosition, Point(36, 88));
}

Loading…
Cancel
Save