You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1039 lines
22 KiB

#include "diablo.h"
DEVILUTION_BEGIN_NAMESPACE
int numthemes;
BOOL armorFlag;
BOOL ThemeGoodIn[4];
BOOL weaponFlag;
BOOL treasureFlag;
BOOL mFountainFlag;
BOOL cauldronFlag;
BOOL tFountainFlag;
int zharlib;
int themex;
int themey;
int themeVar1;
ThemeStruct themes[MAXTHEMES];
BOOL pFountainFlag;
BOOL bFountainFlag;
BOOL bCrossFlag;
int ThemeGood[4] = { THEME_GOATSHRINE, THEME_SHRINE, THEME_SKELROOM, THEME_LIBRARY };
int trm5x[25] = {
-2, -1, 0, 1, 2,
-2, -1, 0, 1, 2,
-2, -1, 0, 1, 2,
-2, -1, 0, 1, 2,
-2, -1, 0, 1, 2
};
int trm5y[25] = {
-2, -2, -2, -2, -2,
-1, -1, -1, -1, -1,
0, 0, 0, 0, 0,
1, 1, 1, 1, 1,
2, 2, 2, 2, 2
};
int trm3x[9] = {
-1, 0, 1,
-1, 0, 1,
-1, 0, 1
};
int trm3y[9] = {
-1, -1, -1,
0, 0, 0,
1, 1, 1
};
BOOL TFit_Shrine(int i)
{
int xp, yp, found;
xp = 0;
yp = 0;
found = 0;
while (found == 0) {
if (dTransVal[xp][yp] == themes[i].ttval) {
if (nTrapTable[dPiece[xp][yp - 1]]
&& !nSolidTable[dPiece[xp - 1][yp]]
&& !nSolidTable[dPiece[xp + 1][yp]]
&& dTransVal[xp - 1][yp] == themes[i].ttval
&& dTransVal[xp + 1][yp] == themes[i].ttval
&& dObject[xp - 1][yp - 1] == 0
&& dObject[xp + 1][yp - 1] == 0) {
found = 1;
}
if (!found
&& nTrapTable[dPiece[xp - 1][yp]]
&& !nSolidTable[dPiece[xp][yp - 1]]
&& !nSolidTable[dPiece[xp][yp + 1]]
&& dTransVal[xp][yp - 1] == themes[i].ttval
&& dTransVal[xp][yp + 1] == themes[i].ttval
&& dObject[xp - 1][yp - 1] == 0
&& dObject[xp - 1][yp + 1] == 0) {
found = 2;
}
}
if (found == 0) {
xp++;
if (xp == MAXDUNX) {
xp = 0;
yp++;
if (yp == MAXDUNY)
return FALSE;
}
}
}
themex = xp;
themey = yp;
themeVar1 = found;
return TRUE;
}
BOOL TFit_Obj5(int t)
{
int xp, yp;
int i, r, rs;
BOOL found;
xp = 0;
yp = 0;
r = random(0, 5) + 1;
rs = r;
while (r > 0) {
found = FALSE;
if (dTransVal[xp][yp] == themes[t].ttval && !nSolidTable[dPiece[xp][yp]]) {
found = TRUE;
for (i = 0; found && i < 25; i++) {
if (nSolidTable[dPiece[xp + trm5x[i]][yp + trm5y[i]]]) {
found = FALSE;
}
if (dTransVal[xp + trm5x[i]][yp + trm5y[i]] != themes[t].ttval) {
found = FALSE;
}
}
}
if (!found) {
xp++;
if (xp == MAXDUNX) {
xp = 0;
yp++;
if (yp == MAXDUNY) {
if (r == rs) {
return FALSE;
}
yp = 0;
}
}
continue;
}
r--;
}
themex = xp;
themey = yp;
return TRUE;
}
BOOL TFit_SkelRoom(int t)
{
int i;
if (leveltype != 1 && leveltype != 2) {
return FALSE;
}
for (i = 0; i < nummtypes; i++) {
if (IsSkel(Monsters[i].mtype)) {
themeVar1 = i;
return TFit_Obj5(t);
}
}
return FALSE;
}
BOOL TFit_GoatShrine(int t)
{
int i;
for (i = 0; i < nummtypes; i++) {
if (IsGoat(Monsters[i].mtype)) {
themeVar1 = i;
return TFit_Obj5(t);
}
}
return FALSE;
}
BOOL CheckThemeObj3(int xp, int yp, int t, int f)
{
int i;
for (i = 0; i < 9; i++) {
if (xp + trm3x[i] < 0 || yp + trm3y[i] < 0)
return FALSE;
if (nSolidTable[dPiece[xp + trm3x[i]][yp + trm3y[i]]])
return FALSE;
if (dTransVal[xp + trm3x[i]][yp + trm3y[i]] != themes[t].ttval)
return FALSE;
if (dObject[xp + trm3x[i]][yp + trm3y[i]])
return FALSE;
if (f != -1 && !random(0, f))
return FALSE;
}
return TRUE;
}
BOOL TFit_Obj3(int t)
{
int xp, yp;
char objrnd[4] = { 4, 4, 3, 5 };
for (yp = 1; yp < MAXDUNY - 1; yp++) {
for (xp = 1; xp < MAXDUNX - 1; xp++) {
if (CheckThemeObj3(xp, yp, t, objrnd[leveltype - 1])) {
themex = xp;
themey = yp;
return TRUE;
}
}
}
return FALSE;
}
BOOL CheckThemeReqs(int t)
{
BOOL rv;
rv = TRUE;
switch (t) {
case THEME_SHRINE:
case THEME_SKELROOM:
case THEME_LIBRARY:
if (leveltype == DTYPE_CAVES || leveltype == DTYPE_HELL) {
rv = FALSE;
}
break;
case THEME_BLOODFOUNTAIN:
if (!bFountainFlag) {
rv = FALSE;
}
break;
case THEME_PURIFYINGFOUNTAIN:
if (!pFountainFlag) {
rv = FALSE;
}
break;
case THEME_ARMORSTAND:
if (leveltype == DTYPE_CATHEDRAL) {
rv = FALSE;
}
break;
case THEME_CAULDRON:
if (leveltype != DTYPE_HELL || !cauldronFlag) {
rv = FALSE;
}
break;
case THEME_MURKYFOUNTAIN:
if (!mFountainFlag) {
rv = FALSE;
}
break;
case THEME_TEARFOUNTAIN:
if (!tFountainFlag) {
rv = FALSE;
}
break;
case THEME_WEAPONRACK:
if (leveltype == DTYPE_CATHEDRAL) {
rv = FALSE;
}
break;
}
return rv;
}
BOOL SpecialThemeFit(int i, int t)
{
BOOL rv;
rv = CheckThemeReqs(t);
switch (t) {
case THEME_SHRINE:
case THEME_LIBRARY:
if (rv) {
rv = TFit_Shrine(i);
}
break;
case THEME_SKELROOM:
if (rv) {
rv = TFit_SkelRoom(i);
}
break;
case THEME_BLOODFOUNTAIN:
if (rv) {
rv = TFit_Obj5(i);
if (rv) {
bFountainFlag = FALSE;
}
}
break;
case THEME_PURIFYINGFOUNTAIN:
if (rv) {
rv = TFit_Obj5(i);
if (rv) {
pFountainFlag = FALSE;
}
}
break;
case THEME_MURKYFOUNTAIN:
if (rv) {
rv = TFit_Obj5(i);
if (rv) {
mFountainFlag = FALSE;
}
}
break;
case THEME_TEARFOUNTAIN:
if (rv) {
rv = TFit_Obj5(i);
if (rv) {
tFountainFlag = FALSE;
}
}
break;
case THEME_CAULDRON:
if (rv) {
rv = TFit_Obj5(i);
if (rv) {
cauldronFlag = FALSE;
}
}
break;
case THEME_GOATSHRINE:
if (rv) {
rv = TFit_GoatShrine(i);
}
break;
case THEME_TORTURE:
case THEME_DECAPITATED:
case THEME_ARMORSTAND:
case THEME_BRNCROSS:
case THEME_WEAPONRACK:
if (rv) {
rv = TFit_Obj3(i);
}
break;
case THEME_TREASURE:
rv = treasureFlag;
if (treasureFlag) {
treasureFlag = FALSE;
}
break;
}
return rv;
}
BOOL CheckThemeRoom(int tv)
{
int i, j, tarea;
for (i = 0; i < numtrigs; i++) {
if (dTransVal[trigs[i]._tx][trigs[i]._ty] == tv)
return FALSE;
}
tarea = 0;
for (j = 0; j < MAXDUNY; j++) {
for (i = 0; i < MAXDUNX; i++) {
if (dTransVal[i][j] != tv)
continue;
if (dFlags[i][j] & DFLAG_POPULATED)
return FALSE;
tarea++;
}
}
if (leveltype == DTYPE_CATHEDRAL && (tarea < 9 || tarea > 100))
return FALSE;
for (j = 0; j < MAXDUNY; j++) {
for (i = 0; i < MAXDUNX; i++) {
if (dTransVal[i][j] != tv || nSolidTable[dPiece[i][j]])
continue;
if (dTransVal[i - 1][j] != tv && !nSolidTable[dPiece[i - 1][j]])
return FALSE;
if (dTransVal[i + 1][j] != tv && !nSolidTable[dPiece[i + 1][j]])
return FALSE;
if (dTransVal[i][j - 1] != tv && !nSolidTable[dPiece[i][j - 1]])
return FALSE;
if (dTransVal[i][j + 1] != tv && !nSolidTable[dPiece[i][j + 1]])
return FALSE;
}
}
return TRUE;
}
void InitThemes()
{
int i, j;
zharlib = -1;
numthemes = 0;
bCrossFlag = FALSE;
armorFlag = TRUE;
bFountainFlag = TRUE;
cauldronFlag = TRUE;
mFountainFlag = TRUE;
pFountainFlag = TRUE;
tFountainFlag = TRUE;
treasureFlag = TRUE;
weaponFlag = TRUE;
if (currlevel == 16)
return;
if (leveltype == DTYPE_CATHEDRAL) {
for (i = 0; i < sizeof(ThemeGoodIn) / sizeof(ThemeGoodIn[0]); i++)
ThemeGoodIn[i] = FALSE;
for (i = 0; i < 256 && numthemes < MAXTHEMES; i++) {
if (CheckThemeRoom(i)) {
themes[numthemes].ttval = i;
for (j = ThemeGood[random(0, 4)];; j = random(0, 17)) {
if (SpecialThemeFit(numthemes, j)) {
break;
}
}
themes[numthemes].ttype = j;
numthemes++;
}
}
}
if (leveltype == 2 || leveltype == 3 || leveltype == 4) {
for (i = 0; i < themeCount; i++)
themes[i].ttype = THEME_NONE;
if (QuestStatus(QTYPE_ZHAR)) {
for (j = 0; j < themeCount; j++) {
themes[j].ttval = themeLoc[j].ttval;
if (SpecialThemeFit(j, THEME_LIBRARY)) {
themes[j].ttype = THEME_LIBRARY;
zharlib = j;
break;
}
}
}
for (i = 0; i < themeCount; i++) {
if (themes[i].ttype == THEME_NONE) {
themes[i].ttval = themeLoc[i].ttval;
for (j = ThemeGood[random(0, 4)];; j = random(0, 17)) {
if (SpecialThemeFit(i, j)) {
break;
}
}
themes[i].ttype = j;
}
}
numthemes += themeCount;
}
}
// HoldThemeRooms marks theme rooms as populated.
void HoldThemeRooms()
{
int i, x, y;
if (currlevel != 16) {
if (leveltype == DTYPE_CATHEDRAL) {
for (i = 0; i < numthemes; i++) {
for (y = 0; y < MAXDUNY; y++) {
for (x = 0; x < MAXDUNX; x++) {
if (dTransVal[x][y] == (char)themes[i].ttval) {
dFlags[x][y] |= DFLAG_POPULATED;
}
}
}
}
} else {
DRLG_HoldThemeRooms();
}
}
}
// PlaceThemeMonsts places theme monsters with the specified frequency.
//
// Parameters:
// - t: theme number (index into themes array).
// - f: frequency (1/f likelihood of adding monster).
void PlaceThemeMonsts(int t, int f)
{
int xp, yp;
int scattertypes[111];
int numscattypes, mtype, i;
numscattypes = 0;
for (i = 0; i < nummtypes; i++) {
if (Monsters[i].mPlaceFlags & 1) {
scattertypes[numscattypes] = i;
numscattypes++;
}
}
mtype = scattertypes[random(0, numscattypes)];
for (yp = 0; yp < MAXDUNY; yp++) {
for (xp = 0; xp < MAXDUNX; xp++) {
if (dTransVal[xp][yp] == themes[t].ttval && !nSolidTable[dPiece[xp][yp]] && dItem[xp][yp] == 0 && dObject[xp][yp] == 0) {
if (random(0, f) == 0) {
AddMonster(xp, yp, random(0, 8), mtype, 1);
}
}
}
}
}
// Theme_Barrel initializes the barrel theme.
//
// Parameters:
// - t: theme number (index into themes array).
void Theme_Barrel(int t)
{
int xp, yp, r;
char barrnd[4] = { 2, 6, 4, 8 };
char monstrnd[4] = { 5, 7, 3, 9 };
for (yp = 0; yp < MAXDUNY; yp++) {
for (xp = 0; xp < MAXDUNX; xp++) {
if (dTransVal[xp][yp] == themes[t].ttval && !nSolidTable[dPiece[xp][yp]]) {
if (random(0, barrnd[leveltype - 1]) == 0) {
r = random(0, barrnd[leveltype - 1]) != 0;
r += OBJ_BARREL;
AddObject(r, xp, yp);
}
}
}
}
PlaceThemeMonsts(t, monstrnd[leveltype - 1]);
}
// Theme_Shrine initializes the shrine theme.
//
// Parameters:
// - t: theme number (index into themes array).
void Theme_Shrine(int t)
{
char monstrnd[4] = { 6, 6, 3, 9 };
TFit_Shrine(t);
if (themeVar1 == 1) {
AddObject(OBJ_CANDLE2, themex - 1, themey);
AddObject(OBJ_SHRINER, themex, themey);
AddObject(OBJ_CANDLE2, themex + 1, themey);
} else {
AddObject(OBJ_CANDLE2, themex, themey - 1);
AddObject(OBJ_SHRINEL, themex, themey);
AddObject(OBJ_CANDLE2, themex, themey + 1);
}
PlaceThemeMonsts(t, monstrnd[leveltype - 1]);
}
// Theme_MonstPit initializes the monster pit theme.
//
// Parameters:
// - t: theme number (index into themes array).
void Theme_MonstPit(int t)
{
int r;
int ixp, iyp;
char monstrnd[4] = { 6, 7, 3, 9 };
r = random(0, 100) + 1;
ixp = 0;
iyp = 0;
if (r > 0) {
while (TRUE) {
if (dTransVal[ixp][iyp] == themes[t].ttval && !nSolidTable[dPiece[ixp][iyp]]) {
--r;
}
if (r <= 0) {
break;
}
ixp++;
if (ixp == MAXDUNX) {
ixp = 0;
iyp++;
if (iyp == MAXDUNY) {
iyp = 0;
}
}
}
}
CreateRndItem(ixp, iyp, TRUE, FALSE, TRUE);
ItemNoFlippy();
PlaceThemeMonsts(t, monstrnd[leveltype - 1]);
}
// Theme_SkelRoom initializes the skeleton room theme.
//
// Parameters:
// - t: theme number (index into themes array).
void Theme_SkelRoom(int t)
{
int xp, yp, i;
char monstrnd[4] = { 6, 7, 3, 9 };
TFit_SkelRoom(t);
xp = themex;
yp = themey;
AddObject(OBJ_SKFIRE, xp, yp);
if(random(0, monstrnd[leveltype - 1]) != 0) {
i = PreSpawnSkeleton();
SpawnSkeleton(i, xp - 1, yp - 1);
} else {
AddObject(OBJ_BANNERL, xp - 1, yp - 1);
}
i = PreSpawnSkeleton();
SpawnSkeleton(i, xp, yp - 1);
if(random(0, monstrnd[leveltype - 1]) != 0) {
i = PreSpawnSkeleton();
SpawnSkeleton(i, xp + 1, yp - 1);
} else {
AddObject(OBJ_BANNERR, xp + 1, yp - 1);
}
if(random(0, monstrnd[leveltype - 1]) != 0) {
i = PreSpawnSkeleton();
SpawnSkeleton(i, xp - 1, yp);
} else {
AddObject(OBJ_BANNERM, xp - 1, yp);
}
if(random(0, monstrnd[leveltype - 1]) != 0) {
i = PreSpawnSkeleton();
SpawnSkeleton(i, xp + 1, yp);
} else {
AddObject(OBJ_BANNERM, xp + 1, yp);
}
if(random(0, monstrnd[leveltype - 1]) != 0) {
i = PreSpawnSkeleton();
SpawnSkeleton(i, xp - 1, yp + 1);
} else {
AddObject(OBJ_BANNERR, xp - 1, yp + 1);
}
i = PreSpawnSkeleton();
SpawnSkeleton(i, xp, yp + 1);
if(random(0, monstrnd[leveltype - 1]) != 0) {
i = PreSpawnSkeleton();
SpawnSkeleton(i, xp + 1, yp + 1);
} else {
AddObject(OBJ_BANNERL, xp + 1, yp + 1);
}
if(dObject[xp][yp - 3] == 0) {
AddObject(OBJ_SKELBOOK, xp, yp - 2);
}
if(dObject[xp][yp + 3] == 0) {
AddObject(OBJ_SKELBOOK, xp, yp + 2);
}
}
// Theme_Treasure initializes the treasure theme.
//
// Parameters:
// - t: theme number (index into themes array).
void Theme_Treasure(int t)
{
int xp, yp;
int i;
char treasrnd[4] = { 4, 9, 7, 10 };
char monstrnd[4] = { 6, 8, 3, 7 };
GetRndSeed();
for (yp = 0; yp < MAXDUNY; yp++) {
for (xp = 0; xp < MAXDUNX; xp++) {
if (dTransVal[xp][yp] == themes[t].ttval && !nSolidTable[dPiece[xp][yp]]) {
int rv = random(0, treasrnd[leveltype - 1]);
// BUGFIX: the `2*` in `2*random(0, treasrnd...) == 0` has no effect, should probably be `random(0, 2*treasrnd...) == 0`
if ((2 * random(0, treasrnd[leveltype - 1])) == 0) {
CreateTypeItem(xp, yp, FALSE, ITYPE_GOLD, IMISC_NONE, FALSE, TRUE);
ItemNoFlippy();
}
if (rv == 0) {
CreateRndItem(xp, yp, FALSE, FALSE, TRUE);
ItemNoFlippy();
}
if (rv == 0 || rv >= treasrnd[leveltype - 1] - 2) {
i = ItemNoFlippy();
if (rv >= treasrnd[leveltype - 1] - 2 && leveltype != DTYPE_CATHEDRAL) {
item[i]._ivalue >>= 1;
}
}
}
}
}
PlaceThemeMonsts(t, monstrnd[leveltype - 1]);
}
// Theme_Library initializes the library theme.
//
// Parameters:
// - t: theme number (index into themes array).
void Theme_Library(int t)
{
int xp, yp, oi;
char librnd[4] = { 1, 2, 2, 5 };
char monstrnd[4] = { 5, 7, 3, 9 };
TFit_Shrine(t);
if(themeVar1 == 1) {
AddObject(OBJ_BOOKCANDLE, themex - 1, themey);
AddObject(OBJ_BOOKCASER, themex, themey);
AddObject(OBJ_BOOKCANDLE, themex + 1, themey);
} else {
AddObject(OBJ_BOOKCANDLE, themex, themey - 1);
AddObject(OBJ_BOOKCASEL, themex, themey);
AddObject(OBJ_BOOKCANDLE, themex, themey + 1);
}
for(yp = 1; yp < MAXDUNY - 1; yp++) {
for(xp = 1; xp < MAXDUNX - 1; xp++) {
if(CheckThemeObj3(xp, yp, t, -1) && dMonster[xp][yp] == 0 && random(0, librnd[leveltype - 1]) == 0) {
AddObject(OBJ_BOOKSTAND, xp, yp);
if(random(0, 2 * librnd[leveltype - 1]) != 0) {
oi = dObject[xp][yp] - 1;
object[oi]._oSelFlag = 0;
object[oi]._oAnimFrame += 2;
}
}
}
}
if(!QuestStatus(QTYPE_ZHAR)) {
PlaceThemeMonsts(t, monstrnd[leveltype]); /// BUGFIX: `leveltype - 1`
} else if(t != zharlib) {
PlaceThemeMonsts(t, monstrnd[leveltype]); /// BUGFIX: `leveltype - 1`
}
}
// Theme_Torture initializes the torture theme.
//
// Parameters:
// - t: theme number (index into themes array).
void Theme_Torture(int t)
{
int xp, yp;
char tortrnd[4] = { 6, 8, 3, 8 };
char monstrnd[4] = { 6, 8, 3, 9 };
for (yp = 1; yp < MAXDUNY - 1; yp++) {
for (xp = 1; xp < MAXDUNX - 1; xp++) {
if (dTransVal[xp][yp] == themes[t].ttval && !nSolidTable[dPiece[xp][yp]]) {
if (CheckThemeObj3(xp, yp, t, -1)) {
if (random(0, tortrnd[leveltype - 1]) == 0) {
AddObject(OBJ_TNUDEM2, xp, yp);
}
}
}
}
}
PlaceThemeMonsts(t, monstrnd[leveltype - 1]);
}
// Theme_BloodFountain initializes the blood fountain theme.
//
// Parameters:
// - t: theme number (index into themes array).
void Theme_BloodFountain(int t)
{
char monstrnd[4] = { 6, 8, 3, 9 };
TFit_Obj5(t);
AddObject(OBJ_BLOODFTN, themex, themey);
PlaceThemeMonsts(t, monstrnd[leveltype - 1]);
}
// Theme_Decap initializes the decapitated theme.
//
// Parameters:
// - t: theme number (index into themes array).
void Theme_Decap(int t)
{
int xp, yp;
char decaprnd[4] = { 6, 8, 3, 8 };
char monstrnd[4] = { 6, 8, 3, 9 };
for (yp = 1; yp < MAXDUNY - 1; yp++) {
for (xp = 1; xp < MAXDUNX - 1; xp++) {
if (dTransVal[xp][yp] == themes[t].ttval && !nSolidTable[dPiece[xp][yp]]) {
if (CheckThemeObj3(xp, yp, t, -1)) {
if (random(0, decaprnd[leveltype - 1]) == 0) {
AddObject(OBJ_DECAP, xp, yp);
}
}
}
}
}
PlaceThemeMonsts(t, monstrnd[leveltype - 1]);
}
// Theme_PurifyingFountain initializes the purifying fountain theme.
//
// Parameters:
// - t: theme number (index into themes array).
void Theme_PurifyingFountain(int t)
{
char monstrnd[4] = { 6, 7, 3, 9 };
TFit_Obj5(t);
AddObject(OBJ_PURIFYINGFTN, themex, themey);
PlaceThemeMonsts(t, monstrnd[leveltype - 1]);
}
// Theme_ArmorStand initializes the armor stand theme.
//
// Parameters:
// - t: theme number (index into themes array).
void Theme_ArmorStand(int t)
{
int xp, yp;
char armorrnd[4] = { 6, 8, 3, 8 };
char monstrnd[4] = { 6, 7, 3, 9 };
if (armorFlag) {
TFit_Obj3(t);
AddObject(OBJ_ARMORSTAND, themex, themey);
}
for (yp = 0; yp < MAXDUNY; yp++) {
for (xp = 0; xp < MAXDUNX; xp++) {
if (dTransVal[xp][yp] == themes[t].ttval && !nSolidTable[dPiece[xp][yp]]) {
if (CheckThemeObj3(xp, yp, t, -1)) {
if (random(0, armorrnd[leveltype - 1]) == 0) {
AddObject(OBJ_ARMORSTANDN, xp, yp);
}
}
}
}
}
PlaceThemeMonsts(t, monstrnd[leveltype - 1]);
armorFlag = FALSE;
}
// Theme_GoatShrine initializes the goat shrine theme.
//
// Parameters:
// - t: theme number (index into themes array).
void Theme_GoatShrine(int t)
{
int xx, yy;
TFit_GoatShrine(t);
AddObject(OBJ_GOATSHRINE, themex, themey);
for (yy = themey - 1; yy <= themey + 1; yy++) {
for (xx = themex - 1; xx <= themex + 1; xx++) {
if (dTransVal[xx][yy] == themes[t].ttval && !nSolidTable[dPiece[xx][yy]] && (xx != themex || yy != themey)) {
AddMonster(xx, yy, DIR_SW, themeVar1, 1);
}
}
}
}
// Theme_Cauldron initializes the cauldron theme.
//
// Parameters:
// - t: theme number (index into themes array).
void Theme_Cauldron(int t)
{
char monstrnd[4] = { 6, 7, 3, 9 };
TFit_Obj5(t);
AddObject(OBJ_CAULDRON, themex, themey);
PlaceThemeMonsts(t, monstrnd[leveltype - 1]);
}
// Theme_MurkyFountain initializes the murky fountain theme.
//
// Parameters:
// - t: theme number (index into themes array).
void Theme_MurkyFountain(int t)
{
char monstrnd[4] = { 6, 7, 3, 9 };
TFit_Obj5(t);
AddObject(OBJ_MURKYFTN, themex, themey);
PlaceThemeMonsts(t, monstrnd[leveltype - 1]);
}
// Theme_TearFountain initializes the tear fountain theme.
//
// Parameters:
// - t: theme number (index into themes array).
void Theme_TearFountain(int t)
{
char monstrnd[4] = { 6, 7, 3, 9 };
TFit_Obj5(t);
AddObject(OBJ_TEARFTN, themex, themey);
PlaceThemeMonsts(t, monstrnd[leveltype - 1]);
}
// Theme_BrnCross initializes the burning cross theme.
//
// Parameters:
// - t: theme number (index into themes array).
void Theme_BrnCross(int t)
{
int xp, yp;
char monstrnd[4] = { 6, 8, 3, 9 };
char bcrossrnd[4] = { 5, 7, 3, 8 };
for (yp = 0; yp < MAXDUNY; yp++) {
for (xp = 0; xp < MAXDUNX; xp++) {
if (dTransVal[xp][yp] == themes[t].ttval && !nSolidTable[dPiece[xp][yp]]) {
if (CheckThemeObj3(xp, yp, t, -1)) {
if (random(0, bcrossrnd[leveltype - 1]) == 0) {
AddObject(OBJ_TBCROSS, xp, yp);
}
}
}
}
}
PlaceThemeMonsts(t, monstrnd[leveltype - 1]);
bCrossFlag = TRUE;
}
// Theme_WeaponRack initializes the weapon rack theme.
//
// Parameters:
// - t: theme number (index into themes array).
void Theme_WeaponRack(int t)
{
int xp, yp;
char weaponrnd[4] = { 6, 8, 5, 8 };
char monstrnd[4] = { 6, 7, 3, 9 };
if (weaponFlag) {
TFit_Obj3(t);
AddObject(OBJ_WEAPONRACK, themex, themey);
}
for (yp = 0; yp < MAXDUNY; yp++) {
for (xp = 0; xp < MAXDUNX; xp++) {
if (dTransVal[xp][yp] == themes[t].ttval && !nSolidTable[dPiece[xp][yp]]) {
if (CheckThemeObj3(xp, yp, t, -1)) {
if (random(0, weaponrnd[leveltype - 1]) == 0) {
AddObject(OBJ_WEAPONRACKN, xp, yp);
}
}
}
}
}
PlaceThemeMonsts(t, monstrnd[leveltype - 1]);
weaponFlag = FALSE;
}
// UpdateL4Trans sets each value of the transparency map to 1.
void UpdateL4Trans()
{
int i, j;
for (j = 0; j < MAXDUNY; j++) {
for (i = 0; i < MAXDUNX; i++) {
if (dTransVal[i][j]) {
dTransVal[i][j] = 1;
}
}
}
}
// CreateThemeRooms adds thematic elements to rooms.
void CreateThemeRooms()
{
int i;
if (currlevel == 16) {
return;
}
InitObjFlag = TRUE;
for (i = 0; i < numthemes; i++) {
themex = 0;
themey = 0;
switch (themes[i].ttype) {
case THEME_BARREL:
Theme_Barrel(i);
break;
case THEME_SHRINE:
Theme_Shrine(i);
break;
case THEME_MONSTPIT:
Theme_MonstPit(i);
break;
case THEME_SKELROOM:
Theme_SkelRoom(i);
break;
case THEME_TREASURE:
Theme_Treasure(i);
break;
case THEME_LIBRARY:
Theme_Library(i);
break;
case THEME_TORTURE:
Theme_Torture(i);
break;
case THEME_BLOODFOUNTAIN:
Theme_BloodFountain(i);
break;
case THEME_DECAPITATED:
Theme_Decap(i);
break;
case THEME_PURIFYINGFOUNTAIN:
Theme_PurifyingFountain(i);
break;
case THEME_ARMORSTAND:
Theme_ArmorStand(i);
break;
case THEME_GOATSHRINE:
Theme_GoatShrine(i);
break;
case THEME_CAULDRON:
Theme_Cauldron(i);
break;
case THEME_MURKYFOUNTAIN:
Theme_MurkyFountain(i);
break;
case THEME_TEARFOUNTAIN:
Theme_TearFountain(i);
break;
case THEME_BRNCROSS:
Theme_BrnCross(i);
break;
case THEME_WEAPONRACK:
Theme_WeaponRack(i);
break;
}
}
InitObjFlag = FALSE;
if (leveltype == DTYPE_HELL && themeCount > 0) {
UpdateL4Trans();
}
}
DEVILUTION_END_NAMESPACE