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.
 
 
 
 
 
 

1712 lines
40 KiB

#include "diablo.h"
/**
* Used under building to avoid HOM and outside of level
* @brief world_draw_black_tile but limited to upper half of screen
* @param pBuff location in back buffer to render the tile, must be on upper half of screen
*/
void town_clear_upper_buf(BYTE *pBuff)
{
/// ASSERT: assert(gpBuffer);
#ifdef USE_ASM
__asm {
mov edi, pBuff
mov edx, 30
mov ebx, 1
xor eax, eax
label1:
cmp edi, gpBufEnd
jb label4
add edi, edx
mov ecx, ebx
rep stosd
add edi, edx
sub edi, BUFFER_WIDTH + 64
or edx, edx
jz label2
sub edx, 2
inc ebx
jmp label1
label2:
mov edx, 2
mov ebx, 15
label3:
cmp edi, gpBufEnd
jb label4
add edi, edx
mov ecx, ebx
rep stosd
add edi, edx
sub edi, BUFFER_WIDTH + 64
dec ebx
add edx, 2
cmp edx, 32
jnz label3
label4:
nop
}
#else
int i, j, k;
BYTE *dst;
dst = pBuff;
for (i = 30, j = 1; i >= 0 && dst >= gpBufEnd; i -= 2, j++, dst -= BUFFER_WIDTH + 64) {
dst += i;
for (k = 0; k < 4 * j; k++)
*dst++ = 0;
dst += i;
}
for (i = 2, j = 15; i != 32 && dst >= gpBufEnd; i += 2, j--, dst -= BUFFER_WIDTH + 64) {
dst += i;
for (k = 0; k < 4 * j; k++)
*dst++ = 0;
dst += i;
}
#endif
}
/**
* Used under building to avoid HOM and outside of level
* @brief world_draw_black_tile but limited to lower half of screen
* @param pBuff location in back buffer to render the tile, must be on lower half of screen
*/
void town_clear_low_buf(BYTE *pBuff)
{
/// ASSERT: assert(gpBuffer);
#ifdef USE_ASM
__asm {
mov edi, pBuff
mov edx, 30
mov ebx, 1
xor eax, eax
label1:
cmp edi, gpBufEnd
jb label2
add edi, 64
jmp label3
label2:
add edi, edx
mov ecx, ebx
rep stosd
add edi, edx
label3:
sub edi, BUFFER_WIDTH + 64
or edx, edx
jz label4
sub edx, 2
inc ebx
jmp label1
label4:
mov edx, 2
mov ebx, 15
label5:
cmp edi, gpBufEnd
jb label6
add edi, 64
jmp label7
label6:
add edi, edx
mov ecx, ebx
rep stosd
add edi, edx
label7:
sub edi, BUFFER_WIDTH + 64
dec ebx
add edx, 2
cmp edx, 32
jnz label5
}
#else
int i, j, k;
BYTE *dst;
dst = pBuff;
for (i = 30, j = 1; i >= 0; i -= 2, j++, dst -= BUFFER_WIDTH + 64) {
if (dst < gpBufEnd) {
dst += i;
for (k = 0; k < 4 * j; k++)
*dst++ = 0;
dst += i;
} else {
dst += 64;
}
}
for (i = 2, j = 15; i != 32; i += 2, j--, dst -= BUFFER_WIDTH + 64) {
if (dst < gpBufEnd) {
dst += i;
for (k = 0; k < 4 * j; k++)
*dst++ = 0;
dst += i;
} else {
dst += 64;
}
}
#endif
}
/**
* @brief Render trees on top of player, buggy disabled in 1.09
* @param pBuff backbuffer pointing where to render on lower part of screen
* @param nCel Frame number for pSpecialCels tile to draw
*/
void town_special_lower(BYTE *pBuff, int nCel)
{
#if 0
int w;
BYTE *end;
#ifdef USE_ASM
__asm {
mov ebx, pSpecialCels
mov eax, nCel
shl eax, 2
add ebx, eax
mov eax, [ebx+4]
sub eax, [ebx]
mov end, eax
mov esi, pSpecialCels
add esi, [ebx]
mov edi, pBuff
mov eax, BUFFER_WIDTH + 64
mov w, eax
mov ebx, end
add ebx, esi
label1:
mov edx, 64
label2:
xor eax, eax
lodsb
or al, al
js label7
sub edx, eax
cmp edi, gpBufEnd
jb label3
add esi, eax
add edi, eax
jmp label6
label3:
mov ecx, eax
shr ecx, 1
jnb label4
movsb
jecxz label6
label4:
shr ecx, 1
jnb label5
movsw
jecxz label6
label5:
rep movsd
label6:
or edx, edx
jz label8
jmp label2
label7:
neg al
add edi, eax
sub edx, eax
jnz label2
label8:
sub edi, w
cmp ebx, esi
jnz label1
}
#else
BYTE width;
BYTE *src, *dst;
DWORD *pFrameTable;
pFrameTable = (DWORD *)pSpecialCels;
src = &pSpecialCels[pFrameTable[nCel]];
dst = pBuff;
end = &src[pFrameTable[nCel + 1] - pFrameTable[nCel]];
for(; src != end; dst -= BUFFER_WIDTH + 64) {
for(w = 64; w;) {
width = *src++;
if(!(width & 0x80)) {
w -= width;
if(dst < gpBufEnd) {
if(width & 1) {
dst[0] = src[0];
src++;
dst++;
}
width >>= 1;
if(width & 1) {
dst[0] = src[0];
dst[1] = src[1];
src += 2;
dst += 2;
}
width >>= 1;
for(; width; width--) {
dst[0] = src[0];
dst[1] = src[1];
dst[2] = src[2];
dst[3] = src[3];
src += 4;
dst += 4;
}
} else {
src += width;
dst += width;
}
} else {
width = -(char)width;
dst += width;
w -= width;
}
}
}
#endif
#endif
}
/**
* @brief Render trees on top of player, buggy disabled in 1.09
* @param pBuff backbuffer pointing where to render on upper part of screen
* @param nCel Frame number for pSpecialCels tile to draw
*/
void town_special_upper(BYTE *pBuff, int nCel)
{
#if 0
int w;
BYTE *end;
#ifdef USE_ASM
__asm {
mov ebx, pSpecialCels
mov eax, nCel
shl eax, 2
add ebx, eax
mov eax, [ebx+4]
sub eax, [ebx]
mov end, eax
mov esi, pSpecialCels
add esi, [ebx]
mov edi, pBuff
mov eax, BUFFER_WIDTH + 64
mov w, eax
mov ebx, end
add ebx, esi
label1:
mov edx, 64
label2:
xor eax, eax
lodsb
or al, al
js label6
sub edx, eax
cmp edi, gpBufEnd
jb label8
mov ecx, eax
shr ecx, 1
jnb label3
movsb
jecxz label5
label3:
shr ecx, 1
jnb label4
movsw
jecxz label5
label4:
rep movsd
label5:
or edx, edx
jz label7
jmp label2
label6:
neg al
add edi, eax
sub edx, eax
jnz label2
label7:
sub edi, w
cmp ebx, esi
jnz label1
label8:
nop
}
#else
BYTE width;
BYTE *src, *dst;
DWORD *pFrameTable;
pFrameTable = (DWORD *)pSpecialCels;
src = &pSpecialCels[pFrameTable[nCel]];
dst = pBuff;
end = &src[pFrameTable[nCel + 1] - pFrameTable[nCel]];
for(; src != end; dst -= BUFFER_WIDTH + 64) {
for(w = 64; w;) {
width = *src++;
if(!(width & 0x80)) {
w -= width;
if(dst < gpBufEnd) {
return;
}
if(width & 1) {
dst[0] = src[0];
src++;
dst++;
}
width >>= 1;
if(width & 1) {
dst[0] = src[0];
dst[1] = src[1];
src += 2;
dst += 2;
}
width >>= 1;
for(; width; width--) {
dst[0] = src[0];
dst[1] = src[1];
dst[2] = src[2];
dst[3] = src[3];
src += 4;
dst += 4;
}
} else {
width = -(char)width;
dst += width;
w -= width;
}
}
}
#endif
#endif
}
/**
* This variant checks for of screen element on the lower screen
* This function it self causes rendering issues since it will render on top of objects on the other side of walls
* @brief Re render tile to workaround sorting issues with players walking east/west
* @param pBuff Pointer to output buffer at location sx,sy
* @param y dPiece coordinate
* @param x dPiece coordinate
* @param sx Backbuffer coordinate
* @param sy Backbuffer coordinate
*/
void town_draw_clipped_e_flag(BYTE *pBuff, int x, int y, int sx, int sy)
{
int i;
BYTE *dst;
MICROS *pMap;
dst = pBuff;
pMap = &dpiece_defs_map_1[IsometricCoord(x, y)];
for (i = 0; i < 12; i += 2) {
level_cel_block = pMap->mt[i];
if (level_cel_block != 0) {
drawLowerScreen(dst);
}
level_cel_block = pMap->mt[i + 1];
if (level_cel_block != 0) {
drawLowerScreen(dst + 32);
}
dst -= BUFFER_WIDTH * 32;
}
town_draw_clipped_town(pBuff, x, y, sx, sy, 0);
}
/**
* @brief Render object sprites
* @param pBuff where to render to with sx,sy already applied
* @param sx dPiece coordinate
* @param sy dPiece coordinate
* @param dx Backbuffer coordinate
* @param dy Backbuffer coordinate
* @param eflag Should the sorting workaround be applied
*/
void town_draw_clipped_town(BYTE *pBuff, int sx, int sy, int dx, int dy, int eflag)
{
int mi, px, py;
char bv;
/// ASSERT: assert(gpBuffer);
pBuff = &gpBuffer[dx + PitchTbl[dy]];
if (dItem[sx][sy] != 0) {
bv = dItem[sx][sy] - 1;
px = dx - item[bv]._iAnimWidth2;
if (bv == pcursitem) {
CelBlitOutlineSafe(181, px, dy, item[bv]._iAnimData, item[bv]._iAnimFrame, item[bv]._iAnimWidth, 0, 8);
}
CelClippedDrawSafe(px, dy, item[bv]._iAnimData, item[bv]._iAnimFrame, item[bv]._iAnimWidth, 0, 8);
}
if (dFlags[sx][sy] & BFLAG_MONSTLR) {
mi = -(dMonster[sx][sy - 1] + 1);
px = dx - towner[mi]._tAnimWidth2;
if (mi == pcursmonst) {
CelBlitOutlineSafe(166, px, dy, towner[mi]._tAnimData, towner[mi]._tAnimFrame, towner[mi]._tAnimWidth, 0, 8);
}
CelClippedDrawSafe(px, dy, towner[mi]._tAnimData, towner[mi]._tAnimFrame, towner[mi]._tAnimWidth, 0, 8);
}
if (dMonster[sx][sy] > 0) {
mi = dMonster[sx][sy] - 1;
px = dx - towner[mi]._tAnimWidth2;
if (mi == pcursmonst) {
CelBlitOutlineSafe(166, px, dy, towner[mi]._tAnimData, towner[mi]._tAnimFrame, towner[mi]._tAnimWidth, 0, 8);
}
CelClippedDrawSafe(px, dy, towner[mi]._tAnimData, towner[mi]._tAnimFrame, towner[mi]._tAnimWidth, 0, 8);
}
if (dFlags[sx][sy] & BFLAG_PLAYERLR) {
bv = -(dPlayer[sx][sy - 1] + 1);
px = dx + plr[bv]._pxoff - plr[bv]._pAnimWidth2;
py = dy + plr[bv]._pyoff;
if (bv == pcursplr) {
Cl2DrawOutlineSafe(165, px, py, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, 0, 8);
}
Cl2DrawSafe(px, py, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, 0, 8);
if (eflag && plr[bv]._peflag) {
town_draw_clipped_e_flag(pBuff - 64, sx - 1, sy + 1, dx - 64, dy);
}
}
if (dFlags[sx][sy] & BFLAG_DEAD_PLAYER) {
DrawDeadPlayer(sx, sy, dx, dy, 0, 8, 1);
}
if (dPlayer[sx][sy] > 0) {
bv = dPlayer[sx][sy] - 1;
px = dx + plr[bv]._pxoff - plr[bv]._pAnimWidth2;
py = dy + plr[bv]._pyoff;
if (bv == pcursplr) {
Cl2DrawOutlineSafe(165, px, py, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, 0, 8);
}
Cl2DrawSafe(px, py, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, 0, 8);
if (eflag && plr[bv]._peflag) {
town_draw_clipped_e_flag(pBuff - 64, sx - 1, sy + 1, dx - 64, dy);
}
}
if (dFlags[sx][sy] & BFLAG_MISSILE) {
DrawClippedMissile(sx, sy, dx, dy, 0, 8, 0);
}
if (dArch[sx][sy] != 0) {
town_special_lower(pBuff, dArch[sx][sy]);
}
}
/**
* @brief Render a row of tile
* @param x dPiece coordinate
* @param y dPiece coordinate
* @param sx Backbuffer coordinate
* @param sy Backbuffer coordinate
* @param chunks tile width of row
* @param eflag is it an even (0) or odd (1) row
*/
void town_draw_lower(int x, int y, int sx, int sy, int chunks, int eflag)
{
int i, j;
BYTE *dst;
MICROS *pMap;
/// ASSERT: assert(gpBuffer);
if (eflag) {
if (y >= 0 && y < MAXDUNY && x >= 0 && x < MAXDUNX) {
level_cel_block = dPiece[x][y];
if (level_cel_block != 0) {
dst = &gpBuffer[sx + 32 + PitchTbl[sy]];
pMap = &dpiece_defs_map_1[IsometricCoord(x, y)];
for (i = 1; i < 17; i += 2) {
level_cel_block = pMap->mt[i];
if (level_cel_block != 0) {
drawLowerScreen(dst);
}
dst -= BUFFER_WIDTH * 32;
}
town_draw_clipped_town(&gpBuffer[sx + PitchTbl[sy]], x, y, sx, sy, 0);
} else {
town_clear_low_buf(&gpBuffer[sx + PitchTbl[sy]]);
}
} else {
town_clear_low_buf(&gpBuffer[sx + PitchTbl[sy]]);
}
x++;
y--;
sx += 64;
}
for (j = 0; j < chunks - eflag; j++) {
if (y >= 0 && y < MAXDUNY && x >= 0 && x < MAXDUNX) {
level_cel_block = dPiece[x][y];
if (level_cel_block != 0) {
dst = &gpBuffer[sx + PitchTbl[sy]];
pMap = &dpiece_defs_map_1[IsometricCoord(x, y)];
for (i = 0; i < 16; i += 2) {
level_cel_block = pMap->mt[i];
if (level_cel_block != 0) {
drawLowerScreen(dst);
}
level_cel_block = pMap->mt[i + 1];
if (level_cel_block != 0) {
drawLowerScreen(dst + 32);
}
dst -= BUFFER_WIDTH * 32;
}
town_draw_clipped_town(&gpBuffer[sx + PitchTbl[sy]], x, y, sx, sy, 1);
} else {
town_clear_low_buf(&gpBuffer[sx + PitchTbl[sy]]);
}
} else {
town_clear_low_buf(&gpBuffer[sx + PitchTbl[sy]]);
}
x++;
y--;
sx += 64;
}
if (eflag) {
if (y >= 0 && y < MAXDUNY && x >= 0 && x < MAXDUNX) {
level_cel_block = dPiece[x][y];
if (level_cel_block != 0) {
dst = &gpBuffer[sx + PitchTbl[sy]];
pMap = &dpiece_defs_map_1[IsometricCoord(x, y)];
for (i = 0; i < 16; i += 2) {
level_cel_block = pMap->mt[i];
if (level_cel_block != 0) {
drawLowerScreen(dst);
}
dst -= BUFFER_WIDTH * 32;
}
town_draw_clipped_town(&gpBuffer[sx + PitchTbl[sy]], x, y, sx, sy, 0);
} else {
town_clear_low_buf(&gpBuffer[sx + PitchTbl[sy]]);
}
} else {
town_clear_low_buf(&gpBuffer[sx + PitchTbl[sy]]);
}
}
}
/**
* This variant checks for of screen element on the lower screen
* This function it self causes rendering issues since it will render on top of objects on the other side of walls
* @brief Re render tile to workaround sorting issues with players walking east/west
* @param pBuff Pointer to output buffer at location sx,sy
* @param y dPiece coordinate
* @param x dPiece coordinate
* @param row The current row being rendered
* @param CelSkip chunks of cell to skip
* @param sx Backbuffer coordinate
* @param sy Backbuffer coordinate
*/
void town_draw_clipped_e_flag_2(BYTE *pBuff, int x, int y, int row, int CelSkip, int sx, int sy)
{
int i;
BYTE *dst;
MICROS *pMap;
if (row == 0) {
dst = pBuff;
} else {
dst = &pBuff[BUFFER_WIDTH * 32 * row];
}
pMap = &dpiece_defs_map_1[IsometricCoord(x, y)];
for (i = 0; i < 6; i++) {
if (row <= i) {
level_cel_block = pMap->mt[2 * i + 2];
if (level_cel_block != 0) {
drawLowerScreen(dst);
}
level_cel_block = pMap->mt[2 * i + 3];
if (level_cel_block != 0) {
drawLowerScreen(dst + 32);
}
}
dst -= BUFFER_WIDTH * 32;
}
if (CelSkip < 8) {
town_draw_clipped_town_2(pBuff, x, y, row, CelSkip, sx, sy, 0);
}
}
/**
* @brief Render object sprites, skip offscreen parts for lower screen
* @param pBuff where to render to with sx,sy already applied
* @param sx dPiece coordinate
* @param sy dPiece coordinate
* @param row The current row being rendered
* @param CelSkip chunks of cell to skip
* @param dx Backbuffer coordinate
* @param dy Backbuffer coordinate
* @param eflag Should the sorting workaround be applied
*/
void town_draw_clipped_town_2(BYTE *pBuff, int sx, int sy, int row, int CelSkip, int dx, int dy, int eflag)
{
int mi, px, py;
char bv;
if (dItem[sx][sy] != 0) {
bv = dItem[sx][sy] - 1;
px = dx - item[bv]._iAnimWidth2;
if (bv == pcursitem) {
CelBlitOutlineSafe(181, px, dy, item[bv]._iAnimData, item[bv]._iAnimFrame, item[bv]._iAnimWidth, CelSkip, 8);
}
CelClippedDrawSafe(px, dy, item[bv]._iAnimData, item[bv]._iAnimFrame, item[bv]._iAnimWidth, CelSkip, 8);
}
if (dFlags[sx][sy] & BFLAG_MONSTLR) {
mi = -(dMonster[sx][sy - 1] + 1);
px = dx - towner[mi]._tAnimWidth2;
if (mi == pcursmonst) {
CelBlitOutlineSafe(166, px, dy, towner[mi]._tAnimData, towner[mi]._tAnimFrame, towner[mi]._tAnimWidth, CelSkip, 8);
}
CelClippedDrawSafe(px, dy, towner[mi]._tAnimData, towner[mi]._tAnimFrame, towner[mi]._tAnimWidth, CelSkip, 8);
}
if (dMonster[sx][sy] > 0) {
mi = dMonster[sx][sy] - 1;
px = dx - towner[mi]._tAnimWidth2;
if (mi == pcursmonst) {
CelBlitOutlineSafe(166, px, dy, towner[mi]._tAnimData, towner[mi]._tAnimFrame, towner[mi]._tAnimWidth, CelSkip, 8);
}
CelClippedDrawSafe(px, dy, towner[mi]._tAnimData, towner[mi]._tAnimFrame, towner[mi]._tAnimWidth, CelSkip, 8);
}
if (dFlags[sx][sy] & BFLAG_PLAYERLR) {
bv = -(dPlayer[sx][sy - 1] + 1);
px = dx + plr[bv]._pxoff - plr[bv]._pAnimWidth2;
py = dy + plr[bv]._pyoff;
if (bv == pcursplr) {
Cl2DrawOutlineSafe(165, px, py, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, CelSkip, 8);
}
Cl2DrawSafe(px, py, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, CelSkip, 8);
if (eflag && plr[bv]._peflag) {
town_draw_clipped_e_flag_2(pBuff - 64, sx - 1, sy + 1, row, CelSkip, dx - 64, dy);
}
}
if (dFlags[sx][sy] & BFLAG_DEAD_PLAYER) {
DrawDeadPlayer(sx, sy, dx, dy, CelSkip, 8, 1);
}
if (dPlayer[sx][sy] > 0) {
bv = dPlayer[sx][sy] - 1;
px = dx + plr[bv]._pxoff - plr[bv]._pAnimWidth2;
py = dy + plr[bv]._pyoff;
if (bv == pcursplr) {
Cl2DrawOutlineSafe(165, px, py, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, CelSkip, 8);
}
Cl2DrawSafe(px, py, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, CelSkip, 8);
if (eflag && plr[bv]._peflag) {
town_draw_clipped_e_flag_2(pBuff - 64, sx - 1, sy + 1, row, CelSkip, dx - 64, dy);
}
}
if (dFlags[sx][sy] & BFLAG_MISSILE) {
DrawClippedMissile(sx, sy, dx, dy, CelSkip, 8, 0);
}
if (dArch[sx][sy] != 0) {
town_special_lower(&pBuff[PitchTbl[16 * CelSkip]], dArch[sx][sy]);
}
}
/**
* @brief Render a row of tile, checking for overdrawing on lower part of screen
* @param x dPiece coordinate
* @param y dPiece coordinate
* @param sx Backbuffer coordinate
* @param sy Backbuffer coordinate
* @param chunks tile width of row
* @param row current row being rendered
* @param eflag is it an even (0) or odd (1) row
*/
void town_draw_lower_2(int x, int y, int sx, int sy, int chunks, int row, int eflag)
{
int i, j, CelSkip;
BYTE *dst;
MICROS *pMap;
/// ASSERT: assert(gpBuffer);
CelSkip = 2 * row + 2;
if (eflag) {
if (y >= 0 && y < MAXDUNY && x >= 0 && x < MAXDUNX) {
level_cel_block = dPiece[x][y];
if (level_cel_block != 0) {
dst = &gpBuffer[sx - (BUFFER_WIDTH * 32 - 32) + PitchTbl[sy]];
pMap = &dpiece_defs_map_1[IsometricCoord(x, y)];
for (i = 0; i < 7; i++) {
if (row <= i) {
level_cel_block = pMap->mt[2 * i + 3];
if (level_cel_block != 0) {
drawLowerScreen(dst);
}
}
dst -= BUFFER_WIDTH * 32;
}
if (CelSkip < 8) {
town_draw_clipped_town_2(&gpBuffer[sx + PitchTbl[sy]], x, y, row, CelSkip, sx, sy, 0);
}
} else {
town_clear_low_buf(&gpBuffer[sx + PitchTbl[sy]]);
}
} else {
town_clear_low_buf(&gpBuffer[sx + PitchTbl[sy]]);
}
x++;
y--;
sx += 64;
}
for (j = 0; j < chunks - eflag; j++) {
if (y >= 0 && y < MAXDUNY && x >= 0 && x < MAXDUNX) {
level_cel_block = dPiece[x][y];
if (level_cel_block != 0) {
dst = &gpBuffer[sx - BUFFER_WIDTH * 32 + PitchTbl[sy]];
pMap = &dpiece_defs_map_1[IsometricCoord(x, y)];
for (i = 0; i < 7; i++) {
if (row <= i) {
level_cel_block = pMap->mt[2 * i + 2];
if (level_cel_block != 0) {
drawLowerScreen(dst);
}
level_cel_block = pMap->mt[2 * i + 3];
if (level_cel_block != 0) {
drawLowerScreen(dst + 32);
}
}
dst -= BUFFER_WIDTH * 32;
}
if (CelSkip < 8) {
town_draw_clipped_town_2(&gpBuffer[sx + PitchTbl[sy] - BUFFER_WIDTH * 16 * CelSkip], x, y, row, CelSkip, sx, sy, 1);
}
} else {
town_clear_low_buf(&gpBuffer[sx + PitchTbl[sy]]);
}
} else {
town_clear_low_buf(&gpBuffer[sx + PitchTbl[sy]]);
}
x++;
y--;
sx += 64;
}
if (eflag) {
if (y >= 0 && y < MAXDUNY && x >= 0 && x < MAXDUNX) {
level_cel_block = dPiece[x][y];
if (level_cel_block != 0) {
dst = &gpBuffer[sx - BUFFER_WIDTH * 32 + PitchTbl[sy]];
pMap = &dpiece_defs_map_1[IsometricCoord(x, y)];
for (i = 0; i < 7; i++) {
if (row <= i) {
level_cel_block = pMap->mt[2 * i + 2];
if (level_cel_block != 0) {
drawLowerScreen(dst);
}
}
dst -= BUFFER_WIDTH * 32;
}
if (CelSkip < 8) {
town_draw_clipped_town_2(&gpBuffer[sx + PitchTbl[sy]], x, y, row, CelSkip, sx, sy, 0);
}
} else {
town_clear_low_buf(&gpBuffer[sx + PitchTbl[sy]]);
}
} else {
town_clear_low_buf(&gpBuffer[sx + PitchTbl[sy]]);
}
}
}
/**
* This variant checks for of screen element on the upper screen
* This function it self causes rendering issues since it will render on top of objects on the other side of walls
* @brief Re render tile to workaround sorting issues with players walking east/west
* @param pBuff Pointer to output buffer at location sx,sy
* @param y dPiece coordinate
* @param x dPiece coordinate
* @param row The current row being rendered
* @param CelCap chunks of cell to skip
* @param sx Backbuffer coordinate
* @param sy Backbuffer coordinate
*/
void town_draw_e_flag(BYTE *pBuff, int x, int y, int row, int CelCap, int sx, int sy)
{
int i;
BYTE *dst;
MICROS *pMap;
dst = pBuff;
pMap = &dpiece_defs_map_1[IsometricCoord(x, y)];
for (i = 0; i < 7; i++) {
if (row >= i) {
level_cel_block = pMap->mt[2 * i];
if (level_cel_block != 0) {
drawUpperScreen(dst);
}
level_cel_block = pMap->mt[2 * i + 1];
if (level_cel_block != 0) {
drawUpperScreen(dst + 32);
}
}
dst -= BUFFER_WIDTH * 32;
}
town_draw_town_all(pBuff, x, y, row, CelCap, sx, sy, 0);
}
/**
* @brief Render object sprites, skip offscreen parts for upper screen
* @param pBuff where to render to with sx,sx already applied
* @param x dPiece coordinate
* @param y dPiece coordinate
* @param row The current row being rendered
* @param CelCap chunks of cell to skip
* @param sx Backbuffer coordinate
* @param sy Backbuffer coordinate
* @param eflag Should the sorting workaround be applied
*/
void town_draw_town_all(BYTE *pBuff, int x, int y, int row, int CelCap, int sx, int sy, int eflag)
{
int mi, px, py;
char bv;
if (dItem[x][y] != 0) {
bv = dItem[x][y] - 1;
px = sx - item[bv]._iAnimWidth2;
if (bv == pcursitem) {
CelBlitOutline(181, px, sy, item[bv]._iAnimData, item[bv]._iAnimFrame, item[bv]._iAnimWidth, 0, CelCap);
}
/// ASSERT: assert(item[bv]._iAnimData);
CelClippedDraw(px, sy, item[bv]._iAnimData, item[bv]._iAnimFrame, item[bv]._iAnimWidth, 0, CelCap);
}
if (dFlags[x][y] & BFLAG_MONSTLR) {
mi = -(dMonster[x][y - 1] + 1);
px = sx - towner[mi]._tAnimWidth2;
if (mi == pcursmonst) {
CelBlitOutline(166, px, sy, towner[mi]._tAnimData, towner[mi]._tAnimFrame, towner[mi]._tAnimWidth, 0, CelCap);
}
/// ASSERT: assert(towner[mi]._tAnimData);
CelClippedDraw(px, sy, towner[mi]._tAnimData, towner[mi]._tAnimFrame, towner[mi]._tAnimWidth, 0, CelCap);
}
if (dMonster[x][y] > 0) {
mi = dMonster[x][y] - 1;
px = sx - towner[mi]._tAnimWidth2;
if (mi == pcursmonst) {
CelBlitOutline(166, px, sy, towner[mi]._tAnimData, towner[mi]._tAnimFrame, towner[mi]._tAnimWidth, 0, CelCap);
}
/// ASSERT: assert(towner[mi]._tAnimData);
CelClippedDraw(px, sy, towner[mi]._tAnimData, towner[mi]._tAnimFrame, towner[mi]._tAnimWidth, 0, CelCap);
}
if (dFlags[x][y] & BFLAG_PLAYERLR) {
bv = -(dPlayer[x][y - 1] + 1);
px = sx + plr[bv]._pxoff - plr[bv]._pAnimWidth2;
py = sy + plr[bv]._pyoff;
if (bv == pcursplr) {
Cl2DrawOutline(165, px, py, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, 0, CelCap);
}
/// ASSERT: assert(plr[bv]._pAnimData);
Cl2Draw(px, py, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, 0, CelCap);
if (eflag && plr[bv]._peflag) {
town_draw_e_flag(pBuff - 64, x - 1, y + 1, row, CelCap, sx - 64, sy);
}
}
if (dFlags[x][y] & BFLAG_DEAD_PLAYER) {
DrawDeadPlayer(x, y, sx, sy, 0, CelCap, 0);
}
if (dPlayer[x][y] > 0) {
bv = dPlayer[x][y] - 1;
px = sx + plr[bv]._pxoff - plr[bv]._pAnimWidth2;
py = sy + plr[bv]._pyoff;
if (bv == pcursplr) {
Cl2DrawOutline(165, px, py, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, 0, CelCap);
}
/// ASSERT: assert(plr[bv]._pAnimData);
Cl2Draw(px, py, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, 0, CelCap);
if (eflag && plr[bv]._peflag) {
town_draw_e_flag(pBuff - 64, x - 1, y + 1, row, CelCap, sx - 64, sy);
}
}
if (dFlags[x][y] & BFLAG_MISSILE) {
DrawMissile(x, y, sx, sy, 0, CelCap, 0);
}
if (dArch[x][y] != 0) {
town_special_upper(pBuff, dArch[x][y]);
}
}
/**
* @brief Render a row of tile, checking for overdrawing on upper part of screen
* @param x dPiece coordinate
* @param y dPiece coordinate
* @param sx Backbuffer coordinate
* @param sy Backbuffer coordinate
* @param chunks tile width of row
* @param row current row being rendered
* @param eflag is it an even (0) or odd (1) row
*/
void town_draw_upper(int x, int y, int sx, int sy, int chunks, int row, int eflag)
{
int i, j, CelCap;
BYTE *dst;
MICROS *pMap;
/// ASSERT: assert(gpBuffer);
CelCap = 2 * row + 2;
if (CelCap > 8) {
CelCap = 8;
}
if (eflag) {
if (y >= 0 && y < MAXDUNY && x >= 0 && x < MAXDUNX) {
level_cel_block = dPiece[x][y];
if (level_cel_block != 0) {
dst = &gpBuffer[sx + 32 + PitchTbl[sy]];
pMap = &dpiece_defs_map_1[IsometricCoord(x, y)];
for (i = 0; i < 7; i++) {
if (row >= i) {
level_cel_block = pMap->mt[2 * i + 1];
if (level_cel_block != 0) {
drawUpperScreen(dst);
}
}
dst -= BUFFER_WIDTH * 32;
}
town_draw_town_all(&gpBuffer[sx + PitchTbl[sy]], x, y, row, CelCap, sx, sy, 0);
} else {
town_clear_upper_buf(&gpBuffer[sx + PitchTbl[sy]]);
}
} else {
town_clear_upper_buf(&gpBuffer[sx + PitchTbl[sy]]);
}
x++;
y--;
sx += 64;
}
for (j = 0; j < chunks - eflag; j++) {
if (y >= 0 && y < MAXDUNY && x >= 0 && x < MAXDUNX) {
level_cel_block = dPiece[x][y];
if (level_cel_block != 0) {
dst = &gpBuffer[sx + PitchTbl[sy]];
pMap = &dpiece_defs_map_1[IsometricCoord(x, y)];
for (i = 0; i < 7; i++) {
if (row >= i) {
level_cel_block = pMap->mt[2 * i];
if (level_cel_block != 0) {
drawUpperScreen(dst);
}
level_cel_block = pMap->mt[2 * i + 1];
if (level_cel_block != 0) {
drawUpperScreen(dst + 32);
}
}
dst -= BUFFER_WIDTH * 32;
}
town_draw_town_all(&gpBuffer[sx + PitchTbl[sy]], x, y, row, CelCap, sx, sy, 1);
} else {
town_clear_upper_buf(&gpBuffer[sx + PitchTbl[sy]]);
}
} else {
town_clear_upper_buf(&gpBuffer[sx + PitchTbl[sy]]);
}
x++;
y--;
sx += 64;
}
if (eflag) {
if (y >= 0 && y < MAXDUNY && x >= 0 && x < MAXDUNX) {
level_cel_block = dPiece[x][y];
if (level_cel_block != 0) {
dst = &gpBuffer[sx + PitchTbl[sy]];
pMap = &dpiece_defs_map_1[IsometricCoord(x, y)];
for (i = 0; i < 7; i++) {
if (row >= i) {
level_cel_block = pMap->mt[2 * i];
if (level_cel_block != 0) {
drawUpperScreen(dst);
}
}
dst -= BUFFER_WIDTH * 32;
}
town_draw_town_all(&gpBuffer[sx + PitchTbl[sy]], x, y, row, CelCap, sx, sy, 0);
} else {
town_clear_upper_buf(&gpBuffer[sx + PitchTbl[sy]]);
}
} else {
town_clear_upper_buf(&gpBuffer[sx + PitchTbl[sy]]);
}
}
}
/**
* @brief Configure render and process screen rows
* @param x Center of view in dPiece coordinate
* @param y Center of view in dPiece coordinate
*/
void T_DrawGame(int x, int y)
{
int i, sx, sy, chunks, blocks;
scr_pix_width = SCREEN_WIDTH;
scr_pix_height = VIEWPORT_HEIGHT;
dword_5C2FF8 = SCREEN_WIDTH / 64;
dword_5C2FFC = VIEWPORT_HEIGHT / 32;
sx = ScrollInfo._sxoff + 64;
sy = ScrollInfo._syoff + 175;
x -= SCREEN_WIDTH / 64;
y--;
chunks = SCREEN_WIDTH / 64;
blocks = 5;
if (chrflag || questlog) {
x += 2;
y -= 2;
sx += (SCREEN_WIDTH / 2) - 32;
chunks = 6;
}
if (invflag || sbookflag) {
x += 2;
y -= 2;
sx -= 32;
chunks = 6;
}
switch (ScrollInfo._sdir) {
case SDIR_NONE:
break;
case SDIR_N:
sy -= 32;
x--;
y--;
blocks++;
break;
case SDIR_NE:
sy -= 32;
x--;
y--;
chunks++;
blocks++;
break;
case SDIR_E:
chunks++;
break;
case SDIR_SE:
chunks++;
blocks++;
break;
case SDIR_S:
blocks++;
break;
case SDIR_SW:
sx -= 64;
x--;
y++;
chunks++;
blocks++;
break;
case SDIR_W:
sx -= 64;
x--;
y++;
chunks++;
break;
case SDIR_NW:
sx -= 64;
sy -= 32;
x -= 2;
chunks++;
blocks++;
break;
}
/// ASSERT: assert(gpBuffer);
gpBufEnd = &gpBuffer[PitchTbl[SCREEN_Y]];
for (i = 0; i < 7; i++) {
town_draw_upper(x, y, sx, sy, chunks, i, 0);
y++;
sx -= 32;
sy += 16;
town_draw_upper(x, y, sx, sy, chunks, i, 1);
x++;
sx += 32;
sy += 16;
}
/// ASSERT: assert(gpBuffer);
gpBufEnd = &gpBuffer[PitchTbl[VIEWPORT_HEIGHT + SCREEN_Y]];
for (i = 0; i < blocks; i++) {
town_draw_lower(x, y, sx, sy, chunks, 0);
y++;
sx -= 32;
sy += 16;
town_draw_lower(x, y, sx, sy, chunks, 1);
x++;
sx += 32;
sy += 16;
}
for (i = 0; i < 7; i++) {
town_draw_lower_2(x, y, sx, sy, chunks, i, 0);
y++;
sx -= 32;
sy += 16;
town_draw_lower_2(x, y, sx, sy, chunks, i, 1);
x++;
sx += 32;
sy += 16;
}
}
/**
* @brief Configure render for zoomed view and process screen rows
* @param x Center of view in dPiece coordinate
* @param y Center of view in dPiece coordinate
*/
void T_DrawZoom(int x, int y)
{
int i, sx, sy, chunks, blocks;
int wdt, nSrcOff, nDstOff;
scr_pix_width = ZOOM_WIDTH;
scr_pix_height = 192;
dword_5C2FF8 = ZOOM_WIDTH / 64;
dword_5C2FFC = 192 / 32;
sx = ScrollInfo._sxoff + 64;
sy = ScrollInfo._syoff + 143;
x -= 6;
y--;
chunks = 6;
blocks = 0;
switch (ScrollInfo._sdir) {
case SDIR_NONE:
break;
case SDIR_N:
sy -= 32;
x--;
y--;
blocks++;
break;
case SDIR_NE:
sy -= 32;
x--;
y--;
chunks++;
blocks++;
break;
case SDIR_E:
chunks++;
break;
case SDIR_SE:
chunks++;
blocks++;
break;
case SDIR_S:
blocks++;
break;
case SDIR_SW:
sx -= 64;
x--;
y++;
chunks++;
blocks++;
break;
case SDIR_W:
sx -= 64;
x--;
y++;
chunks++;
break;
case SDIR_NW:
sx -= 64;
sy -= 32;
x -= 2;
chunks++;
blocks++;
break;
}
/// ASSERT: assert(gpBuffer);
gpBufEnd = &gpBuffer[PitchTbl[-17 + SCREEN_Y]];
for (i = 0; i < 7; i++) {
town_draw_upper(x, y, sx, sy, chunks, i, 0);
y++;
sx -= 32;
sy += 16;
town_draw_upper(x, y, sx, sy, chunks, i, 1);
x++;
sx += 32;
sy += 16;
}
/// ASSERT: assert(gpBuffer);
gpBufEnd = &gpBuffer[PitchTbl[160 + SCREEN_Y]];
for (i = 0; i < blocks; i++) {
town_draw_lower(x, y, sx, sy, chunks, 0);
y++;
sx -= 32;
sy += 16;
town_draw_lower(x, y, sx, sy, chunks, 1);
x++;
sx += 32;
sy += 16;
}
for (i = 0; i < 7; i++) {
town_draw_lower_2(x, y, sx, sy, chunks, i, 0);
y++;
sx -= 32;
sy += 16;
town_draw_lower_2(x, y, sx, sy, chunks, i, 1);
x++;
sx += 32;
sy += 16;
}
if (chrflag || questlog) {
nSrcOff = SCREENXY(112, 159);
nDstOff = SCREENXY(320, 350);
wdt = (SCREEN_WIDTH - 320) / 2;
} else if (invflag || sbookflag) {
nSrcOff = SCREENXY(112, 159);
nDstOff = SCREENXY(0, 350);
wdt = (SCREEN_WIDTH - 320) / 2;
} else {
nSrcOff = SCREENXY(32, 159);
nDstOff = SCREENXY(0, 350);
wdt = SCREEN_WIDTH / 2;
}
/// ASSERT: assert(gpBuffer);
#ifdef USE_ASM
__asm {
mov esi, gpBuffer
mov edx, nDstOff
mov edi, esi
mov ecx, nSrcOff
add edi, edx
add esi, ecx
mov ebx, edi
add ebx, BUFFER_WIDTH
mov edx, 176
label1:
mov ecx, wdt
label2:
mov al, [esi]
inc esi
mov ah, al
mov [edi], ax
mov [ebx], ax
add edi, 2
add ebx, 2
dec ecx
jnz label2
mov eax, BUFFER_WIDTH
add eax, wdt
sub esi, eax
add eax, eax
sub ebx, eax
sub edi, eax
dec edx
jnz label1
}
#else
int hgt;
BYTE *src, *dst1, *dst2;
src = &gpBuffer[nSrcOff];
dst1 = &gpBuffer[nDstOff];
dst2 = &gpBuffer[nDstOff + BUFFER_WIDTH];
for (hgt = 176; hgt != 0; hgt--, src -= BUFFER_WIDTH + wdt, dst1 -= 2 * (BUFFER_WIDTH + wdt), dst2 -= 2 * (BUFFER_WIDTH + wdt)) {
for (i = wdt; i != 0; i--) {
*dst1++ = *src;
*dst1++ = *src;
*dst2++ = *src;
*dst2++ = *src;
src++;
}
}
#endif
}
/**
* Mostly like DrawView but enables stores and lacks death screen
* @brief Start rendering of screen, town variation
* @param StartX Center of view in dPiece coordinate
* @param StartY Center of view in dPiece coordinate
*/
void T_DrawView(int StartX, int StartY)
{
light_table_index = 0;
cel_transparency_active = 0;
if (zoomflag) {
T_DrawGame(StartX, StartY);
} else {
T_DrawZoom(StartX, StartY);
}
if (automapflag) {
DrawAutomap();
}
if (stextflag && !qtextflag)
DrawSText();
if (invflag) {
DrawInv();
} else if (sbookflag) {
DrawSpellBook();
}
DrawDurIcon();
if (chrflag) {
DrawChr();
} else if (questlog) {
DrawQuestLog();
} else if (plr[myplr]._pStatPts != 0 && !spselflag) {
DrawLevelUpIcon();
}
if (uitemflag) {
DrawUniqueInfo();
}
if (qtextflag) {
DrawQText();
}
if (spselflag) {
DrawSpellList();
}
if (dropGoldFlag) {
DrawGoldSplit(dropGoldValue);
}
if (helpflag) {
DrawHelp();
}
if (msgflag) {
DrawDiabloMsg();
}
if (PauseMode != 0 && !deathflag) {
gmenu_draw_pause();
}
DrawPlrMsg();
gmenu_draw();
doom_draw();
DrawInfoBox();
DrawLifeFlask();
DrawManaFlask();
}
void SetTownMicros()
{
int i, x, y, lv;
WORD *pPiece;
MICROS *pMap;
for (y = 0; y < MAXDUNY; y++) {
for (x = 0; x < MAXDUNX; x++) {
lv = dPiece[x][y];
pMap = &dpiece_defs_map_1[IsometricCoord(x, y)];
if (lv != 0) {
lv--;
pPiece = (WORD *)&pLevelPieces[32 * lv];
for (i = 0; i < 16; i++) {
pMap->mt[i] = pPiece[(i & 1) + 14 - (i & 0xE)];
}
} else {
for (i = 0; i < 16; i++) {
pMap->mt[i] = 0;
}
}
}
}
if (zoomflag) {
scr_pix_width = SCREEN_WIDTH;
scr_pix_height = VIEWPORT_HEIGHT;
dword_5C2FF8 = SCREEN_WIDTH / 64;
dword_5C2FFC = VIEWPORT_HEIGHT / 32;
} else {
scr_pix_width = ZOOM_WIDTH;
scr_pix_height = ZOOM_HEIGHT;
dword_5C2FF8 = ZOOM_WIDTH / 64;
dword_5C2FFC = ZOOM_HEIGHT / 32;
}
}
/**
* @brief Load level data into dPiece
* @param P3Tiles Tile set
* @param pSector Sector data
* @param xi upper left destination
* @param yi upper left destination
* @param w width of sector
* @param h height of sector
*/
void T_FillSector(BYTE *P3Tiles, BYTE *pSector, int xi, int yi, int w, int h)
{
int i, j, xx, yy;
long v1, v2, v3, v4, ii;
ii = 4;
yy = yi;
for (j = 0; j < h; j++) {
xx = xi;
for (i = 0; i < w; i++) {
#ifdef USE_ASM
__asm {
mov esi, pSector
mov eax, ii
add esi, eax
xor eax, eax
lodsw
or eax, eax
jz label1
dec eax
mov esi, P3Tiles
shl eax, 3
add esi, eax
xor eax, eax
lodsw
inc eax
mov v1, eax
lodsw
inc eax
mov v2, eax
lodsw
inc eax
mov v3, eax
lodsw
inc eax
mov v4, eax
jmp label2
label1:
mov v1, eax
mov v2, eax
mov v3, eax
mov v4, eax
label2:
nop
}
#else
WORD *Map;
Map = (WORD *)&pSector[ii];
if (*Map) {
v1 = *((WORD *)&P3Tiles[(*Map - 1) * 8] + 0) + 1;
v2 = *((WORD *)&P3Tiles[(*Map - 1) * 8] + 1) + 1;
v3 = *((WORD *)&P3Tiles[(*Map - 1) * 8] + 2) + 1;
v4 = *((WORD *)&P3Tiles[(*Map - 1) * 8] + 3) + 1;
} else {
v1 = 0;
v2 = 0;
v3 = 0;
v4 = 0;
}
#endif
dPiece[xx][yy] = v1;
dPiece[xx + 1][yy] = v2;
dPiece[xx][yy + 1] = v3;
dPiece[xx + 1][yy + 1] = v4;
xx += 2;
ii += 2;
}
yy += 2;
}
}
/**
* @brief Load a tile in to dPiece
* @param P3Tiles Tile set
* @param xx upper left destination
* @param yy upper left destination
* @param t tile id
*/
void T_FillTile(BYTE *P3Tiles, int xx, int yy, int t)
{
long v1, v2, v3, v4;
#ifdef USE_ASM
__asm {
mov eax, t
dec eax
mov esi, P3Tiles
shl eax, 3
add esi, eax
xor eax, eax
lodsw
inc eax
mov v1, eax
lodsw
inc eax
mov v2, eax
lodsw
inc eax
mov v3, eax
lodsw
inc eax
mov v4, eax
jmp label1
mov v1, eax
mov v2, eax
mov v3, eax
mov v4, eax
label1:
nop
}
#else
v1 = *((WORD *)&P3Tiles[(t - 1) * 8] + 0) + 1;
v2 = *((WORD *)&P3Tiles[(t - 1) * 8] + 1) + 1;
v3 = *((WORD *)&P3Tiles[(t - 1) * 8] + 2) + 1;
v4 = *((WORD *)&P3Tiles[(t - 1) * 8] + 3) + 1;
#endif
dPiece[xx][yy] = v1;
dPiece[xx + 1][yy] = v2;
dPiece[xx][yy + 1] = v3;
dPiece[xx + 1][yy + 1] = v4;
}
/**
* @brief Initialize all of the levels data
*/
void T_Pass3()
{
int xx, yy, x;
BYTE *P3Tiles, *pSector;
for (yy = 0; yy < MAXDUNY; yy += 2) {
for (xx = 0; xx < MAXDUNX; xx += 2) {
dPiece[xx][yy] = 0;
dPiece[xx + 1][yy] = 0;
dPiece[xx][yy + 1] = 0;
dPiece[xx + 1][yy + 1] = 0;
}
}
P3Tiles = LoadFileInMem("Levels\\TownData\\Town.TIL", NULL);
pSector = LoadFileInMem("Levels\\TownData\\Sector1s.DUN", NULL);
T_FillSector(P3Tiles, pSector, 46, 46, 25, 25);
mem_free_dbg(pSector);
pSector = LoadFileInMem("Levels\\TownData\\Sector2s.DUN", NULL);
T_FillSector(P3Tiles, pSector, 46, 0, 25, 23);
mem_free_dbg(pSector);
pSector = LoadFileInMem("Levels\\TownData\\Sector3s.DUN", NULL);
T_FillSector(P3Tiles, pSector, 0, 46, 23, 25);
mem_free_dbg(pSector);
pSector = LoadFileInMem("Levels\\TownData\\Sector4s.DUN", NULL);
T_FillSector(P3Tiles, pSector, 0, 0, 23, 23);
mem_free_dbg(pSector);
#ifndef SPAWN
if (gbMaxPlayers == 1) {
if (!(plr[myplr].pTownWarps & 1)) {
#endif
T_FillTile(P3Tiles, 48, 20, 320);
#ifndef SPAWN
}
if (!(plr[myplr].pTownWarps & 2)) {
#endif
T_FillTile(P3Tiles, 16, 68, 332);
T_FillTile(P3Tiles, 16, 70, 331);
#ifndef SPAWN
}
if (!(plr[myplr].pTownWarps & 4)) {
#endif
for (x = 36; x < 46; x++) {
T_FillTile(P3Tiles, x, 78, random_(0, 4) + 1);
}
#ifndef SPAWN
}
}
#endif
if (quests[QTYPE_PW]._qactive != 3 && quests[QTYPE_PW]._qactive) {
T_FillTile(P3Tiles, 60, 70, 342);
} else {
T_FillTile(P3Tiles, 60, 70, 71);
}
mem_free_dbg(P3Tiles);
}
/**
* @brief Initialize town level
* @param entry Methode of entry
*/
void CreateTown(int entry)
{
int x, y;
dminx = 10;
dminy = 10;
dmaxx = 84;
dmaxy = 84;
if (entry == 0) {
ViewX = 75;
ViewY = 68;
} else if (entry == 1) {
ViewX = 25;
ViewY = 31;
} else if (entry == 7) {
if (TWarpFrom == 5) {
ViewX = 49;
ViewY = 22;
}
if (TWarpFrom == 9) {
ViewX = 18;
ViewY = 69;
}
if (TWarpFrom == 13) {
ViewX = 41;
ViewY = 81;
}
}
T_Pass3();
memset(dLight, 0, sizeof(dLight));
memset(dFlags, 0, sizeof(dFlags));
memset(dPlayer, 0, sizeof(dPlayer));
memset(dMonster, 0, sizeof(dMonster));
memset(dObject, 0, sizeof(dObject));
memset(dItem, 0, sizeof(dItem));
memset(dArch, 0, sizeof(dArch));
for (y = 0; y < MAXDUNY; y++) {
for (x = 0; x < MAXDUNX; x++) {
if (dPiece[x][y] == 360) {
dArch[x][y] = 1;
} else if (dPiece[x][y] == 358) {
dArch[x][y] = 2;
} else if (dPiece[x][y] == 129) {
dArch[x][y] = 6;
} else if (dPiece[x][y] == 130) {
dArch[x][y] = 7;
} else if (dPiece[x][y] == 128) {
dArch[x][y] = 8;
} else if (dPiece[x][y] == 117) {
dArch[x][y] = 9;
} else if (dPiece[x][y] == 157) {
dArch[x][y] = 10;
} else if (dPiece[x][y] == 158) {
dArch[x][y] = 11;
} else if (dPiece[x][y] == 156) {
dArch[x][y] = 12;
} else if (dPiece[x][y] == 162) {
dArch[x][y] = 13;
} else if (dPiece[x][y] == 160) {
dArch[x][y] = 14;
} else if (dPiece[x][y] == 214) {
dArch[x][y] = 15;
} else if (dPiece[x][y] == 212) {
dArch[x][y] = 16;
} else if (dPiece[x][y] == 217) {
dArch[x][y] = 17;
} else if (dPiece[x][y] == 216) {
dArch[x][y] = 18;
}
}
}
SetTownMicros();
}