From ea74cd99214c85ad8181c68770a7f532be7c3e6e Mon Sep 17 00:00:00 2001 From: Justin Marshall Date: Sat, 30 May 2026 02:50:21 -0700 Subject: [PATCH] Lots of feature upgrades. --- CONTROL.CPP | 46 +++++ DIABLO.CPP | 44 +++- DIABLO.H | 3 +- DRLG_L1.CPP | 265 +++++++++++++++++++----- ENGINE.CPP | 547 ++++++++++++++++++++++++++++++++++++++++++++++++ INV.CPP | 85 ++++++++ LIGHTING.CPP | 19 ++ NTHREAD.CPP | 17 ++ PALETTE.CPP | 408 ++++++++++++++++++++++++++++++++++++ SCROLLRT.CPP | 551 ++++++++++++++++++++++++++++++++++++++++++------- Scroll_asm.cpp | 122 ++++++++++- THEMES.CPP | 204 +++++++++++++++++- TOWN.CPP | 275 +++++++++++++++++++++--- 13 files changed, 2433 insertions(+), 153 deletions(-) diff --git a/CONTROL.CPP b/CONTROL.CPP index a8a8dd8..8a82edc 100644 --- a/CONTROL.CPP +++ b/CONTROL.CPP @@ -126,6 +126,48 @@ BOOL drawhpflag; BOOL drawmanaflag; BOOL chrflag; +extern "C" { + extern BYTE gbHudAnimateActive; + extern BYTE gbHudHealthOrbTable[4][256]; + extern BYTE gbHudManaOrbTable[4][256]; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void HudAnimateRect(int x, int y, int w, int h, BYTE table[4][256], int phase) +{ + int row, col; + int wavePhase; + BYTE *p; + + if (!gbHudAnimateActive || gpBuffer == NULL) + return; + + if (x < 0) { + w += x; + x = 0; + } + if (y < 0) { + h += y; + y = 0; + } + if (x + w > BUFFERX) + w = BUFFERX - x; + if (y + h > BUFFERY) + h = BUFFERY - y; + if (w <= 0 || h <= 0) + return; + + for (row = 0; row < h; row++) { + p = gpBuffer + nBuffWTbl[y + row] + x; + for (col = 0; col < w; col++) { + wavePhase = (phase + ((row + (col >> 1)) / 10)) & 3; + p[col] = table[wavePhase][p[col]]; + } + } +} + + /*-----------------------------------------------------------------------*/ typedef enum { SI_INVALID, @@ -1074,6 +1116,7 @@ void DrawHealthTop() app_assert(gpBuffer); TransBuffCopy(pLifeBuff, 88, 277, gpBuffer, 383405, dy); if (dy != 13) TransBuffCopy(pBtmBuff, 640, (dy * 640) + 2029, gpBuffer, (dy * 768) + 383405, 13 - dy); + HudAnimateRect(160, 499, 88, 13, gbHudHealthOrbTable, GetTickCount() / 120); } /*-----------------------------------------------------------------------** @@ -1094,6 +1137,7 @@ void DrawHealthBar() if (dv > 69) dv = 69; if (dv != 69) BuffCopy(pLifeBuff, 16, 85-dv, 160, 512); if (dv != 0) CopyCtrlPan(96, 85-dv, 88, dv, 160, 581-dv); + HudAnimateRect(160, 512, 88, 75, gbHudHealthOrbTable, GetTickCount() / 120); } /*-----------------------------------------------------------------------** @@ -1110,6 +1154,7 @@ void DrawManaTop() app_assert(gpBuffer); TransBuffCopy(pManaBuff, 88, 277, gpBuffer, 383771, dy); if (dy != 13) TransBuffCopy(pBtmBuff, 640, (dy * 640) + 2395, gpBuffer, (dy * 768) + 383771, 13 - dy); + HudAnimateRect(528, 499, 88, 13, gbHudManaOrbTable, GetTickCount() / 135); } /*-----------------------------------------------------------------------** @@ -1159,6 +1204,7 @@ void DrawManaBar() if (dv > 69) dv = 69; if (dv != 69) BuffCopy(pManaBuff, 16, 85-dv, 528, 512); if (dv != 0) CopyCtrlPan(464, 85-dv, 88, dv, 528, 581-dv); + HudAnimateRect(528, 512, 88, 75, gbHudManaOrbTable, GetTickCount() / 135); DrawSpellIcon(); } diff --git a/DIABLO.CPP b/DIABLO.CPP index 134477b..b9d370f 100644 --- a/DIABLO.CPP +++ b/DIABLO.CPP @@ -144,6 +144,7 @@ BOOL gbRunGame; BOOL gbRunGameResult; BOOL gbProcessPlayers; BOOL gbGameLoopStartup; +extern int gnRenderFrameInterp; bool gbTheo = false; bool gbCowsuit = false; @@ -167,6 +168,7 @@ int glMid3Seed[NUMLEVELS+1]; //JKE 7/30 adds new levels **-----------------------------------------------------------------------*/ #define TIMEOUT_CURSOR WATCH_CURS static int sgnTimeoutCurs = NO_CURSOR; +static DWORD sgdwLastRenderFrame; #define LMOUSE_DOWN 1 #define RMOUSE_DOWN 2 @@ -184,6 +186,8 @@ BYTE sgbMouseDown = 0; static void alloc_plr(); static void DoTimedEvents(); static void game_loop(BOOL bStartup); +static void DrawInterpolatedFrame(); +static BOOL TryDrawInterpolatedFrame(); static void plr_encrypt(BOOL bEncrypt); void InitializeHashSource(); void Decrypt(LPDWORD data, DWORD bytes, DWORD key); @@ -205,6 +209,7 @@ static LRESULT CALLBACK GM_Game(HWND, UINT, WPARAM, LPARAM); void TrackInit(BOOL bMouseDown); void TrackMouse(); void run_delta_info(); +int nthread_get_render_interp(); void toggle_frame_counter(); WNDPROC my_SetWindowProc(WNDPROC wndProc); void plrmsg_update(); @@ -632,10 +637,14 @@ static void run_game_loop(UINT uMsg) { BOOL bRun = gbRunGame && nthread_run_gameloop(FALSE); //if (! bRun) plr_encrypt(TRUE); SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_NORMAL); - if (! bRun) continue; + if (! bRun) { + TryDrawInterpolatedFrame(); + continue; + } } else if (! nthread_run_gameloop(FALSE)) { // not enough time has elapsed since last gameloop + TryDrawInterpolatedFrame(); continue; } // pjw.patch2.end @@ -645,7 +654,7 @@ static void run_game_loop(UINT uMsg) { NetReceivePackets(); game_loop(gbGameLoopStartup); gbGameLoopStartup = FALSE; - DrawAndBlit(); + DrawInterpolatedFrame(); //plr_encrypt(TRUE); } //plr_encrypt(FALSE); @@ -678,6 +687,37 @@ static void run_game_loop(UINT uMsg) { } +//****************************************************************** +//****************************************************************** +static void DrawInterpolatedFrame() +{ + sgdwLastRenderFrame = GetTickCount(); + if (PauseMode || (gbMaxPlayers == 1 && gmenu_is_on())) + gnRenderFrameInterp = 0; + else + gnRenderFrameInterp = nthread_get_render_interp(); + DrawAndBlit(); +} + + +//****************************************************************** +//****************************************************************** +static BOOL TryDrawInterpolatedFrame() +{ + DWORD dwNow; + + dwNow = GetTickCount(); + if (dwNow - sgdwLastRenderFrame < 1000 / RENDER_FRAMES_PER_SECOND) + return FALSE; + + if (force_redraw == NODRAW) + force_redraw = VIEWDRAW; + + DrawInterpolatedFrame(); + return TRUE; +} + + /*-----------------------------------------------------------------------** // return FALSE to quit game // return TRUE to continue game diff --git a/DIABLO.H b/DIABLO.H index f7fef8e..420cfee 100644 --- a/DIABLO.H +++ b/DIABLO.H @@ -125,8 +125,9 @@ void trace_fcn(const char * pszFcn); **-----------------------------------------------------------------------*/ #define MAX_PLRS 4 -// frame rate +// logic and render rates #define GAME_FRAMES_PER_SECOND 20 +#define RENDER_FRAMES_PER_SECOND 27 // Our messages #define WM_DIABNEXTLVL WM_USER+2 diff --git a/DRLG_L1.CPP b/DRLG_L1.CPP index 5fb18aa..e4cfba8 100644 --- a/DRLG_L1.CPP +++ b/DRLG_L1.CPP @@ -1599,6 +1599,109 @@ static int DRLG_PlaceMiniSet(const byte miniset[], int tmin, int tmax, int cx, i return(3); } +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static BOOL L5MiniSetFits(const byte miniset[], int sx, int sy) +{ + int sw, sh; + int xx, yy; + int ii; + + sw = miniset[0]; + sh = miniset[1]; + + if (sx < 0 || sy < 0 || sx + sw >= MDMAXX || sy + sh >= MDMAXY) + return FALSE; + + ii = 2; + for (yy = 0; yy < sh; yy++) { + for (xx = 0; xx < sw; xx++) { + if ((miniset[ii] != 0) && (dungeon[sx + xx][sy + yy] != miniset[ii])) + return FALSE; + if (dflags[sx + xx][sy + yy] != 0) + return FALSE; + ii++; + } + } + + return TRUE; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void L5PlaceMiniSetAt(const byte miniset[], int sx, int sy) +{ + int sw, sh; + int xx, yy; + int ii; + + sw = miniset[0]; + sh = miniset[1]; + ii = (sw * sh) + 2; + + for (yy = 0; yy < sh; yy++) { + for (xx = 0; xx < sw; xx++) { + if (miniset[ii] != 0) + dungeon[sx + xx][sy + yy] = miniset[ii]; + ii++; + } + } +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static BOOL L5TryPlaceLamp(int sx, int sy) +{ + if (!L5MiniSetFits(LAMPS, sx, sy)) + return FALSE; + + L5PlaceMiniSetAt(LAMPS, sx, sy); + return TRUE; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static int L5PlaceLampNear(int cx, int cy, int max) +{ + static const int offsets[][2] = { + { -3, -2 }, { 2, -2 }, { -3, 2 }, { 2, 2 }, + { -4, 0 }, { 3, 0 }, { 0, -4 }, { 0, 3 }, + { -5, -1 }, { 4, -1 }, { -1, 4 }, { -1, -5 }, + }; + int i, n, start; + int placed; + + placed = 0; + n = sizeof(offsets) / sizeof(offsets[0]); + start = random(0, n); + + for (i = 0; i < n && placed < max; i++) { + if (L5TryPlaceLamp(cx + offsets[(start + i) % n][0], cy + offsets[(start + i) % n][1])) + placed++; + } + + return placed; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void L5PlaceLevel1Lamps() +{ + int i, j; + + if (currlevel != 1) + return; + + for (j = 1; j < MDMAXY - 1; j++) { + for (i = 1; i < MDMAXX - 1; i++) { + if (dungeon[i][j] == 64) + L5PlaceLampNear(i, j, 2); + if (dungeon[i][j] == 59) + L5PlaceLampNear(i, j, 1); + } + } +} + /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ /* @@ -1972,12 +2075,54 @@ void LoadPreL1Dungeon(char sFileName[], int vx, int vy) byte L5dungeon[L5DX][L5DY]; byte L5ConvTbl[16] = { 22, 13, 1, 13, 2, 13, 13, 13, 4, 13, 1, 13, 2, 13, 16, 13 }; +typedef struct { + int minArea; + int roomMin; + int roomMax; + int wallChance; + int archWallChance; + int grateWallChance; + int archDoorChance; + int loopChance; + int lampMin; + int lampMax; +} L5CathedralProfile; + +static L5CathedralProfile L5Profile; + /*------------------------------------------------------------------------* ** Global variables **------------------------------------------------------------------------*/ static BOOL HR1, HR2, HR3; static BOOL VR1, VR2, VR3; +/*------------------------------------------------------------------------* +**------------------------------------------------------------------------*/ +static const L5CathedralProfile *GetL5CathedralProfile() +{ + static const L5CathedralProfile profiles[4] = { + { 533, 2, 6, 92, 20, 10, 14, 0, 4, 7 }, + { 693, 2, 7, 96, 23, 13, 16, 3, 6, 10 }, + { 761, 4, 7, 100, 25, 16, 18, 5, 4, 8 }, + { 805, 4, 8, 100, 28, 20, 20, 7, 3, 6 }, + }; + static const L5CathedralProfile oldProfile = { + 761, L5ROOM_MIN, L5ROOM_MAX, 100, 25, 25, 16, 0, 5, 10 + }; + + if (currlevel >= 1 && currlevel <= 4) + return &profiles[currlevel - 1]; + + return &oldProfile; +} + +/*------------------------------------------------------------------------* +**------------------------------------------------------------------------*/ +static void InitL5CathedralProfile() +{ + L5Profile = *GetL5CathedralProfile(); +} + /*------------------------------------------------------------------------* **------------------------------------------------------------------------*/ static void InitL5Dungeon() @@ -2060,8 +2205,8 @@ static void L5roomGen(int x, int y, int w, int h, int dir) // left room num = 0; do { - width = ((random(0, L5ROOM_MAX - L5ROOM_MIN + 1) + L5ROOM_MIN) >> 1) << 1; - height = ((random(0, L5ROOM_MAX - L5ROOM_MIN + 1) + L5ROOM_MIN) >> 1) << 1; + width = ((random(0, L5Profile.roomMax - L5Profile.roomMin + 1) + L5Profile.roomMin) >> 1) << 1; + height = ((random(0, L5Profile.roomMax - L5Profile.roomMin + 1) + L5Profile.roomMin) >> 1) << 1; ry = y + (h / 2) - (height / 2); rx = x - width; cx1 = rx - 1; @@ -2089,8 +2234,8 @@ static void L5roomGen(int x, int y, int w, int h, int dir) // top room num = 0; do { - width = ((random(0, L5ROOM_MAX - L5ROOM_MIN + 1) + L5ROOM_MIN) >> 1) << 1; - height = ((random(0, L5ROOM_MAX - L5ROOM_MIN + 1) + L5ROOM_MIN) >> 1) << 1; + width = ((random(0, L5Profile.roomMax - L5Profile.roomMin + 1) + L5Profile.roomMin) >> 1) << 1; + height = ((random(0, L5Profile.roomMax - L5Profile.roomMin + 1) + L5Profile.roomMin) >> 1) << 1; rx = x + (w / 2) - (width / 2); ry = y - height; cx1 = rx - 1; @@ -2287,26 +2432,23 @@ static int L5VWallOk(int i, int j) static void L5HorizWall(int i, int j, char p, int dx) { int xx; + int rv; char wt, dt; - switch (random(0, 4)) { - case 0: - case 1: - wt = 2; // Normal solid wall - break; - case 2: + rv = random(0, 100); + if (rv < L5Profile.archWallChance) { wt = 12; // Arch wall if (p == 2) p = 12; if (p == 4) p = 10; - break; - case 3: + } else if (rv < L5Profile.archWallChance + L5Profile.grateWallChance) { wt = 36; // Grate wall if (p == 2) p = 36; if (p == 4) p = 27; - break; + } else { + wt = 2; // Normal solid wall } - if (random(0, 6) == 5) dt = 12; // Arch + if (random(0, 100) < L5Profile.archDoorChance) dt = 12; // Arch else dt = 26; // Door if (wt == 12) dt = 12; // If arch wall, force arch door @@ -2326,26 +2468,23 @@ static void L5HorizWall(int i, int j, char p, int dx) static void L5VertWall(int i, int j, char p, int dy) { int yy; + int rv; char wt, dt; - switch (random(0, 4)) { - case 0: - case 1: - wt = 1; // Normal solid wall - break; - case 2: + rv = random(0, 100); + if (rv < L5Profile.archWallChance) { wt = 11; // Arch wall if (p == 1) p = 11; if (p == 4) p = 14; - break; - case 3: + } else if (rv < L5Profile.archWallChance + L5Profile.grateWallChance) { wt = 35; // Grate wall if (p == 1) p = 35; if (p == 4) p = 37; - break; + } else { + wt = 1; // Normal solid wall } - if (random(0, 6) == 5) dt = 11; // Arch + if (random(0, 100) < L5Profile.archDoorChance) dt = 11; // Arch else dt = 25; // Door if (wt == 11) dt = 11; // If arch wall, force arch door @@ -2362,7 +2501,6 @@ static void L5VertWall(int i, int j, char p, int dy) /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ -#define WALLRND 100 static void L5AddWall() { int i, j; @@ -2371,27 +2509,27 @@ static void L5AddWall() for (j = 0; j < MDMAXY; j++) { for (i = 0; i < MDMAXX; i++) { if (dflags[i][j] == 0) { - if ((dungeon[i][j] == 3) && (random(0, 100) < WALLRND)) { + if ((dungeon[i][j] == 3) && (random(0, 100) < L5Profile.wallChance)) { x = L5HWallOk(i, j); if (x != -1) L5HorizWall(i, j, 2, x); } - if ((dungeon[i][j] == 3) && (random(0, 100) < WALLRND)) { + if ((dungeon[i][j] == 3) && (random(0, 100) < L5Profile.wallChance)) { y = L5VWallOk(i, j); if (y != -1) L5VertWall(i, j, 1, y); } - if ((dungeon[i][j] == 6) && (random(0, 100) < WALLRND)) { + if ((dungeon[i][j] == 6) && (random(0, 100) < L5Profile.wallChance)) { x = L5HWallOk(i, j); if (x != -1) L5HorizWall(i, j, 4, x); } - if ((dungeon[i][j] == 7) && (random(0, 100) < WALLRND)) { + if ((dungeon[i][j] == 7) && (random(0, 100) < L5Profile.wallChance)) { y = L5VWallOk(i, j); if (y != -1) L5VertWall(i, j, 4, y); } - if ((dungeon[i][j] == 2) && (random(0, 100) < WALLRND)) { + if ((dungeon[i][j] == 2) && (random(0, 100) < L5Profile.wallChance)) { x = L5HWallOk(i, j); if (x != -1) L5HorizWall(i, j, 2, x); } - if ((dungeon[i][j] == 1) && (random(0, 100) < WALLRND)) { + if ((dungeon[i][j] == 1) && (random(0, 100) < L5Profile.wallChance)) { y = L5VWallOk(i, j); if (y != -1) L5VertWall(i, j, 1, y); } @@ -2400,6 +2538,41 @@ static void L5AddWall() } } +/*------------------------------------------------------------------------* +**------------------------------------------------------------------------*/ +static BOOL L5OpenFloor(int x, int y) +{ + return dungeon[x][y] == D_FLOOR && dflags[x][y] == NODOOR; +} + +/*------------------------------------------------------------------------* +**------------------------------------------------------------------------*/ +static void L5AddLoops() +{ + int i, j; + + if (L5Profile.loopChance <= 0) return; + + for (j = 2; j < MDMAXY - 2; j++) { + for (i = 2; i < MDMAXX - 2; i++) { + if (dflags[i][j] != NODOOR) continue; + if (random(0, 100) >= L5Profile.loopChance) continue; + + if (dungeon[i][j] == D_VWALL && L5OpenFloor(i - 1, j) && L5OpenFloor(i + 1, j)) { + if (random(0, 100) < L5Profile.archDoorChance) + dungeon[i][j] = D_AVW; + else + dflags[i][j] |= VDOOR; + } else if (dungeon[i][j] == D_HWALL && L5OpenFloor(i, j - 1) && L5OpenFloor(i, j + 1)) { + if (random(0, 100) < L5Profile.archDoorChance) + dungeon[i][j] = D_AHW; + else + dflags[i][j] |= HDOOR; + } + } + } +} + /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ static void DRLG_L5GChamber(int sx, int sy, int topflag, int bottomflag, int leftflag, int rightflag) @@ -3252,6 +3425,7 @@ static void NormalGrate(int chance) DRLG_L5PlaceRndSet(FLOOR3, chance); DRLG_L5PlaceRndSet(FLOOR4, chance); } + /*-----------------------------------------------------------------------* **-----------------------------------------------------------------------*/ static void DRLG_L5(int entry) @@ -3262,21 +3436,9 @@ static void DRLG_L5(int entry) int xx, yy; doneflag = FALSE; + InitL5CathedralProfile(); + minarea = L5Profile.minArea; - switch (currlevel) { - case 1: - minarea = 533; //(L5DUNX*L5DUNY)/3; - break; - case 2: - minarea = 693; //((L5DUNX*L5DUNY)/3) + ((L5DUNX*L5DUNY)/10); - break; - case 3: - case 4: - minarea = 761; //((L5DUNX*L5DUNY)/3) + ((L5DUNX*L5DUNY)/7); - break; - default: - minarea = 761; // Crypt levels - } while (!doneflag) { DRLG_InitTrans(); do { @@ -3292,6 +3454,7 @@ static void DRLG_L5(int entry) L5tileFix(); L5AddWall(); + if (currlevel < CRYPTSTART) L5AddLoops(); L5ClearFlags(); DRLG_L5FloodTVal(); @@ -3435,7 +3598,11 @@ static void DRLG_L5(int entry) // Random subs if (currlevel < CRYPTSTART) // These are to turn off stuff in the crypt JKE + { + // Keep Cathedral levels on the L1-safe substitution table. The broken + // wall, grate, statue, and rubble minisets below belong to the Crypt art. DRLG_L5Subs(); + } else { @@ -3498,9 +3665,11 @@ static void DRLG_L5(int entry) // else // DRLG_L5Shadows(); - // Create mini set pieces - if (currlevel < CRYPTSTART) - DRLG_PlaceMiniSet(LAMPS, 5, 10, 0, 0, 0, -1, LVL_NODIR); + // Create mini set pieces + if (currlevel < CRYPTSTART) { + L5PlaceLevel1Lamps(); + DRLG_PlaceMiniSet(LAMPS, L5Profile.lampMin, L5Profile.lampMax, 0, 0, 0, -1, LVL_NODIR); + } // Floor subs if (currlevel < CRYPTSTART) diff --git a/ENGINE.CPP b/ENGINE.CPP index 8170d56..5c74f25 100644 --- a/ENGINE.CPP +++ b/ENGINE.CPP @@ -25,6 +25,14 @@ //****************************************************************** void ErrorDlg(int nDlgId,DWORD dwErr,const char * pszFile,int nLine); +extern "C" { + extern BYTE gbLevelTileEnhanceActive; + extern BYTE gbLevelUnitContrastTable[]; + extern BYTE gbLevelUnitLumaTable[]; + extern BYTE gbLevelUnitSharpenLightTable[]; + extern BYTE gbLevelUnitAoTable[]; +} + //****************************************************************** // Registration info @@ -3195,6 +3203,359 @@ NextBlock: #endif +//************************************************************************* +//************************************************************************* +#if RLE_DRAW +static BYTE LevelUnitPixel(const BYTE *row, int x, int width, BYTE *pLightTable) +{ + BYTE pixel, src; + int left, right, curr, nearAvg, darkest; + + src = row[x]; + if (src == 0) + return 0; + + pixel = gbLevelUnitContrastTable[src]; + if (pLightTable != NULL) + pixel = pLightTable[pixel]; + + if (x <= 0 || x + 1 >= width) + return pixel; + + left = gbLevelUnitLumaTable[row[x - 1]]; + right = gbLevelUnitLumaTable[row[x + 1]]; + curr = gbLevelUnitLumaTable[src]; + nearAvg = (left + right) >> 1; + darkest = (left < right) ? left : right; + + if (nearAvg - curr > 10) + return gbLevelUnitAoTable[pixel]; + if (curr - darkest > 16 && curr < 230) + return gbLevelUnitAoTable[pixel]; + if (curr - nearAvg > 18) + return gbLevelUnitSharpenLightTable[pixel]; + + return pixel; +} + +static BOOL UseLevelUnitEnhance(); + +static void RLEDrawEnhancedUnit(BYTE *pDst, BYTE *pRLEData, int nDataSize, int nWidth, BYTE *pLightTable, BOOL clipped) +{ + BYTE row[BUFFERX]; + BYTE mask[BUFFERX]; + BYTE *pSrc, *pRowDst; + int remaining, rowLeft, x, i; + signed char packet; + BYTE pixel; + int count; + + if (nWidth <= 0 || nWidth > BUFFERX) { + if (pLightTable != NULL) { + if (clipped) + RLEDrawLitUnitClipped(pDst, pRLEData, nDataSize, nWidth, pLightTable); + else + RLEDrawLitUnit(pDst, pRLEData, nDataSize, nWidth, pLightTable); + } + else { + if (clipped) + RLEDrawUnitClipped(pDst, pRLEData, nDataSize, nWidth); + else + RLEDrawUnit(pDst, pRLEData, nDataSize, nWidth); + } + return; + } + + memset(row, 0, nWidth); + memset(mask, 0, nWidth); + pSrc = pRLEData; + pRowDst = pDst; + remaining = nDataSize; + rowLeft = nWidth; + x = 0; + + while (remaining > 0) { + packet = (signed char)*pSrc++; + remaining--; + + if (packet >= 0) { + count = packet; + while (count > 0) { + i = (count < rowLeft) ? count : rowLeft; + x += i; + rowLeft -= i; + count -= i; + + if (rowLeft == 0) { + if (!clipped || pRowDst < (BYTE *)glClipY) { + for (i = 0; i < nWidth; i++) { + if (mask[i]) + pRowDst[i] = LevelUnitPixel(row, i, nWidth, pLightTable); + } + } + memset(row, 0, nWidth); + memset(mask, 0, nWidth); + pRowDst -= BUFFERX; + rowLeft = nWidth; + x = 0; + } + } + continue; + } + + count = -packet; + if (count > MAX_RLE_COPY) { + count -= MAX_RLE_COPY; + if (remaining <= 0) + break; + pixel = *pSrc++; + remaining--; + while (count-- > 0) { + row[x] = pixel; + mask[x] = TRUE; + x++; + rowLeft--; + + if (rowLeft == 0) { + if (!clipped || pRowDst < (BYTE*)glClipY) { + for (i = 0; i < nWidth; i++) { + if (mask[i]) + pRowDst[i] = LevelUnitPixel(row, i, nWidth, pLightTable); + } + } + memset(row, 0, nWidth); + memset(mask, 0, nWidth); + pRowDst -= BUFFERX; + rowLeft = nWidth; + x = 0; + } + } + } + else { + while (count-- > 0 && remaining > 0) { + pixel = *pSrc++; + remaining--; + row[x] = pixel; + mask[x] = TRUE; + x++; + rowLeft--; + + if (rowLeft == 0) { + if (!clipped || pRowDst < (BYTE*)glClipY) { + for (i = 0; i < nWidth; i++) { + if (mask[i]) + pRowDst[i] = LevelUnitPixel(row, i, nWidth, pLightTable); + } + } + memset(row, 0, nWidth); + memset(mask, 0, nWidth); + pRowDst -= BUFFERX; + rowLeft = nWidth; + x = 0; + } + } + } + } +} + +static void RLEDrawUnitLerpOverlay(BYTE *pDst, BYTE *pRLEData, int nDataSize, int nWidth, BYTE *pLightTable, BOOL clipped, int density) +{ + BYTE row[BUFFERX]; + BYTE mask[BUFFERX]; + BYTE *pSrc, *pRowDst; + int remaining, rowLeft, x, i, y; + signed char packet; + BYTE pixel; + int count; + BOOL enhanced; + + if (density <= 0) + return; + if (density > 3) + density = 3; + if (nWidth <= 0 || nWidth > BUFFERX) + return; + + memset(row, 0, nWidth); + memset(mask, 0, nWidth); + enhanced = UseLevelUnitEnhance(); + pSrc = pRLEData; + pRowDst = pDst; + remaining = nDataSize; + rowLeft = nWidth; + x = 0; + y = 0; + + while (remaining > 0) { + packet = (signed char)*pSrc++; + remaining--; + + if (packet >= 0) { + count = packet; + while (count > 0) { + i = (count < rowLeft) ? count : rowLeft; + x += i; + rowLeft -= i; + count -= i; + + if (rowLeft == 0) { + if (!clipped || pRowDst < (BYTE*)glClipY) { + for (i = 0; i < nWidth; i++) { + if (mask[i] && (((i + y) & 3) < density)) + pRowDst[i] = enhanced ? LevelUnitPixel(row, i, nWidth, pLightTable) : (pLightTable ? pLightTable[row[i]] : row[i]); + } + } + memset(row, 0, nWidth); + memset(mask, 0, nWidth); + pRowDst -= BUFFERX; + rowLeft = nWidth; + x = 0; + y++; + } + } + continue; + } + + count = -packet; + if (count > MAX_RLE_COPY) { + count -= MAX_RLE_COPY; + if (remaining <= 0) + break; + pixel = *pSrc++; + remaining--; + while (count-- > 0) { + row[x] = pixel; + mask[x] = TRUE; + x++; + rowLeft--; + + if (rowLeft == 0) { + if (!clipped || pRowDst < (BYTE*)glClipY) { + for (i = 0; i < nWidth; i++) { + if (mask[i] && (((i + y) & 3) < density)) + pRowDst[i] = enhanced ? LevelUnitPixel(row, i, nWidth, pLightTable) : (pLightTable ? pLightTable[row[i]] : row[i]); + } + } + memset(row, 0, nWidth); + memset(mask, 0, nWidth); + pRowDst -= BUFFERX; + rowLeft = nWidth; + x = 0; + y++; + } + } + } + else { + while (count-- > 0 && remaining > 0) { + pixel = *pSrc++; + remaining--; + row[x] = pixel; + mask[x] = TRUE; + x++; + rowLeft--; + + if (rowLeft == 0) { + if (!clipped || pRowDst < (BYTE*)glClipY) { + for (i = 0; i < nWidth; i++) { + if (mask[i] && (((i + y) & 3) < density)) + pRowDst[i] = enhanced ? LevelUnitPixel(row, i, nWidth, pLightTable) : (pLightTable ? pLightTable[row[i]] : row[i]); + } + } + memset(row, 0, nWidth); + memset(mask, 0, nWidth); + pRowDst -= BUFFERX; + rowLeft = nWidth; + x = 0; + y++; + } + } + } + } +} + +static BOOL UseLevelUnitEnhance() +{ + return gbLevelTileEnhanceActive && leveltype != 0; +} + +static void DrawEnhancedUnitCommon( + long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend, BYTE *pLightTable, BOOL clipped) +{ + BYTE *pDst, *pSrc; + DWORD *pFrameTable; + long RLELen, offval, offval2; + + app_assert(gpBuffer != NULL); + app_assert(pCelBuff != NULL); + app_assert(nCel > 0); + #ifdef GRACEFUL_EXIT + if (gpBuffer == NULL || pCelBuff == NULL || nCel <= 0) + return; + #endif + + pFrameTable = (DWORD*)pCelBuff; + app_assert(nCel <= (int)pFrameTable[0]); + pSrc = pCelBuff + pFrameTable[nCel]; + offval = *(WORD*)(pSrc + ostart); + if (!offval) + return; + offval2 = (oend == 8) ? 0 : *(WORD*)(pSrc + oend); + RLELen = (offval2 ? offval2 : pFrameTable[nCel + 1] - pFrameTable[nCel]) - offval; + pSrc += offval; + pDst = gpBuffer + nBuffWTbl[yp - ostart * 16] + xp; + + if (UseLevelUnitEnhance()) { + RLEDrawEnhancedUnit(pDst, pSrc, RLELen, nCelW, pLightTable, clipped); + return; + } + + if (pLightTable != NULL) { + if (clipped) + RLEDrawLitUnitClipped(pDst, pSrc, RLELen, nCelW, pLightTable); + else + RLEDrawLitUnit(pDst, pSrc, RLELen, nCelW, pLightTable); + } + else { + if (clipped) + RLEDrawUnitClipped(pDst, pSrc, RLELen, nCelW); + else + RLEDrawUnit(pDst, pSrc, RLELen, nCelW); + } +} + +static void DrawUnitLerpOverlayCommon( + long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend, BYTE *pLightTable, BOOL clipped, int density) +{ + BYTE *pDst, *pSrc; + DWORD *pFrameTable; + long RLELen, offval, offval2; + + if (density <= 0) + return; + + app_assert(gpBuffer != NULL); + app_assert(pCelBuff != NULL); + app_assert(nCel > 0); + #ifdef GRACEFUL_EXIT + if (gpBuffer == NULL || pCelBuff == NULL || nCel <= 0) + return; + #endif + + pFrameTable = (DWORD*)pCelBuff; + app_assert(nCel <= (int)pFrameTable[0]); + pSrc = pCelBuff + pFrameTable[nCel]; + offval = *(WORD*)(pSrc + ostart); + if (!offval) + return; + offval2 = (oend == 8) ? 0 : *(WORD*)(pSrc + oend); + RLELen = (offval2 ? offval2 : pFrameTable[nCel + 1] - pFrameTable[nCel]) - offval; + pSrc += offval; + pDst = gpBuffer + nBuffWTbl[yp - ostart * 16] + xp; + RLEDrawUnitLerpOverlay(pDst, pSrc, RLELen, nCelW, pLightTable, clipped, density); +} +#endif + + //************************************************************************* //************************************************************************* #if RLE_DRAW @@ -3486,6 +3847,192 @@ void DrawLitUnitClipped(long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, #endif +//************************************************************************* +//************************************************************************* +#if RLE_DRAW +void DrawEnhancedUnit(long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend) +{ + DrawEnhancedUnitCommon(xp, yp, pCelBuff, nCel, nCelW, ostart, oend, NULL, FALSE); +} +#endif + + +//************************************************************************* +//************************************************************************* +#if RLE_DRAW +void DrawUnitLerpOverlay(long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend, int density) +{ + DrawUnitLerpOverlayCommon(xp, yp, pCelBuff, nCel, nCelW, ostart, oend, NULL, FALSE, density); +} +#endif + + +//************************************************************************* +//************************************************************************* +#if RLE_DRAW +void DrawEnhancedUnitClipped(long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend) +{ + DrawEnhancedUnitCommon(xp, yp, pCelBuff, nCel, nCelW, ostart, oend, NULL, TRUE); +} +#endif + + +//************************************************************************* +//************************************************************************* +#if RLE_DRAW +void DrawUnitLerpOverlayClipped(long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend, int density) +{ + DrawUnitLerpOverlayCommon(xp, yp, pCelBuff, nCel, nCelW, ostart, oend, NULL, TRUE, density); +} +#endif + + +//************************************************************************* +//************************************************************************* +#if RLE_DRAW +void DrawEnhancedLitUnit(long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend) +{ + DrawEnhancedUnitCommon( + xp, + yp, + pCelBuff, + nCel, + nCelW, + ostart, + oend, + nLVal ? pLightTbl + (nLVal << 8) : NULL, + FALSE); +} +#endif + + +//************************************************************************* +//************************************************************************* +#if RLE_DRAW +void DrawLitUnitLerpOverlay(long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend, int density) +{ + DrawUnitLerpOverlayCommon( + xp, + yp, + pCelBuff, + nCel, + nCelW, + ostart, + oend, + nLVal ? pLightTbl + (nLVal << 8) : NULL, + FALSE, + density); +} +#endif + + +//************************************************************************* +//************************************************************************* +#if RLE_DRAW +void DrawEnhancedLitUnitClipped(long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend) +{ + DrawEnhancedUnitCommon( + xp, + yp, + pCelBuff, + nCel, + nCelW, + ostart, + oend, + nLVal ? pLightTbl + (nLVal << 8) : NULL, + TRUE); +} +#endif + + +//************************************************************************* +//************************************************************************* +#if RLE_DRAW +void DrawLitUnitLerpOverlayClipped(long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend, int density) +{ + DrawUnitLerpOverlayCommon( + xp, + yp, + pCelBuff, + nCel, + nCelW, + ostart, + oend, + nLVal ? pLightTbl + (nLVal << 8) : NULL, + TRUE, + density); +} +#endif + + +//************************************************************************* +//************************************************************************* +#if RLE_DRAW +void DrawEnhancedInfraUnit(long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend, char loff) +{ + long ltaboff; + + ltaboff = light4flag ? 1024 : 4096; + if (loff == LIGHT_STONE) + ltaboff += 256; + if (loff >= LIGHT_U) + ltaboff += ((loff - LIGHT_U) << 8) + 768; + DrawEnhancedUnitCommon(xp, yp, pCelBuff, nCel, nCelW, ostart, oend, pLightTbl + ltaboff, FALSE); +} +#endif + + +//************************************************************************* +//************************************************************************* +#if RLE_DRAW +void DrawInfraUnitLerpOverlay(long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend, char loff, int density) +{ + long ltaboff; + + ltaboff = light4flag ? 1024 : 4096; + if (loff == LIGHT_STONE) + ltaboff += 256; + if (loff >= LIGHT_U) + ltaboff += ((loff - LIGHT_U) << 8) + 768; + DrawUnitLerpOverlayCommon(xp, yp, pCelBuff, nCel, nCelW, ostart, oend, pLightTbl + ltaboff, FALSE, density); +} +#endif + + +//************************************************************************* +//************************************************************************* +#if RLE_DRAW +void DrawEnhancedInfraUnitClipped(long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend, char loff) +{ + long ltaboff; + + ltaboff = light4flag ? 1024 : 4096; + if (loff == LIGHT_STONE) + ltaboff += 256; + if (loff >= LIGHT_U) + ltaboff += ((loff - LIGHT_U) << 8) + 768; + DrawEnhancedUnitCommon(xp, yp, pCelBuff, nCel, nCelW, ostart, oend, pLightTbl + ltaboff, TRUE); +} +#endif + + +//************************************************************************* +//************************************************************************* +#if RLE_DRAW +void DrawInfraUnitLerpOverlayClipped(long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend, char loff, int density) +{ + long ltaboff; + + ltaboff = light4flag ? 1024 : 4096; + if (loff == LIGHT_STONE) + ltaboff += 256; + if (loff >= LIGHT_U) + ltaboff += ((loff - LIGHT_U) << 8) + 768; + DrawUnitLerpOverlayCommon(xp, yp, pCelBuff, nCel, nCelW, ostart, oend, pLightTbl + ltaboff, TRUE, density); +} +#endif + + //************************************************************************* //************************************************************************* void play_movie(const char * pszMovie,BOOL bAllowCancel); diff --git a/INV.CPP b/INV.CPP index 15e8fca..f146709 100644 --- a/INV.CPP +++ b/INV.CPP @@ -169,6 +169,89 @@ _Skip2: inc edi #define INVOMCLR 181 #define INVOICLR 229 +extern "C" { + extern BYTE gbHudAnimateActive; + extern BYTE gbHudPotionHealthTable[4][256]; + extern BYTE gbHudPotionManaTable[4][256]; + extern BYTE gbHudPotionRejuvTable[4][256]; +} + +#define HUDPOT_NONE 0 +#define HUDPOT_HEALTH 1 +#define HUDPOT_MANA 2 +#define HUDPOT_REJUV 3 + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static int HudPotionKind(ItemStruct *item) +{ + switch (item->_iMiscId) { + case IMID_PHEAL: + case IMID_PLHEAL: + case IMID_PSHEAL: + case IMID_PDHEAL: + return HUDPOT_HEALTH; + case IMID_PMANA: + case IMID_PFMANA: + return HUDPOT_MANA; + case IMID_REJUV: + case IMID_FREJUV: + return HUDPOT_REJUV; + default: + return HUDPOT_NONE; + } +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static BYTE *HudPotionTable(int kind, int phase) +{ + phase &= 3; + if (kind == HUDPOT_HEALTH) + return gbHudPotionHealthTable[phase]; + if (kind == HUDPOT_MANA) + return gbHudPotionManaTable[phase]; + return gbHudPotionRejuvTable[phase]; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void HudAnimatePotionIcon(int x, int y, int w, int h, int kind, int salt) +{ + int row, col; + int xclip, wclip; + int yy; + BYTE *p; + BYTE *table; + + if (kind == HUDPOT_NONE || !gbHudAnimateActive || gpBuffer == NULL) + return; + + xclip = x; + wclip = w; + if (xclip < 0) { + wclip += xclip; + xclip = 0; + } + if (xclip + wclip > BUFFERX) + wclip = BUFFERX - xclip; + if (wclip <= 0) + return; + + table = HudPotionTable(kind, (GetTickCount() / 115) + salt); + for (row = 0; row < h; row++) { + yy = y - row; + if (yy < 0 || yy >= BUFFERY) + continue; + p = gpBuffer + nBuffWTbl[yy] + xclip; + for (col = 0; col < wclip; col++) + p[col] = table[p[col]]; + } +} + + void DrawInv() { int i, f, w, ii, xx, yy, oc; @@ -431,6 +514,7 @@ void DrawInv() else DrawSlabCelI(InvRect[i+25].x + 64, InvRect[i+25].y + 159, pCursCels2, f - ICLAST, w, 0, 8, LIGHT_INFRA); } + HudAnimatePotionIcon(InvRect[i+25].x + 64, InvRect[i+25].y + 159, w, CursorHeight[f], HudPotionKind(&plr[myplr].InvList[ii]), i); } } } @@ -472,6 +556,7 @@ void DrawSpdBar() else DrawSlabCelI(InvRect[i+65].x + 64, InvRect[i+65].y + 159, pCursCels2, f - ICLAST, w, 0, 8, LIGHT_INFRA); } + HudAnimatePotionIcon(InvRect[i+65].x + 64, InvRect[i+65].y + 159, w, CursorHeight[f], HudPotionKind(&plr[myplr].SpdList[i]), i + 8); idata = plr[myplr].SpdList[i].IDidx; if (AllItemsList[idata].iUsable && plr[myplr].SpdList[i]._iStatFlag && (plr[myplr].SpdList[i]._itype != IT_GOLD)) diff --git a/LIGHTING.CPP b/LIGHTING.CPP index 09711ca..df8d824 100644 --- a/LIGHTING.CPP +++ b/LIGHTING.CPP @@ -207,6 +207,20 @@ char * pCrawlEntry[19] = { &(CrawlTable[2460]) // 18 }; +static int GetEffectiveLightRadius(int nRadius) +{ + if (nRadius <= 0) + return 0; + + nRadius = (nRadius * 4) / 5; + if (nRadius < 1) + nRadius = 1; + if (nRadius > 15) + nRadius = 15; + + return nRadius; +} + BYTE vCrawlTable[23][30] = { {1,0, 2,0, 3,0, 4,0, 5,0, 6,0, 7,0, 8,0, 9,0, 10,0, 11,0, 12,0, 13,0, 14,0, 15,0}, // 0 {1,0, 2,0, 3,0, 4,0, 5,0, 6,0, 7,0, 8,1, 9,1, 10,1, 11,1, 12,1, 13,1, 14,1, 15,1}, // 1 @@ -331,6 +345,7 @@ void DoLighting (int nXPos, int nYPos, int nRadius, int Lnum) nYPos--; } } + nRadius = GetEffectiveLightRadius(nRadius); rxoff = xoff; ryoff = yoff; @@ -455,6 +470,7 @@ void DoUnLight (int nXPos, int nYPos, int nRadius) int i, j; int x1,y1,x2,y2; + nRadius = GetEffectiveLightRadius(nRadius); nRadius++; y1 = nYPos - nRadius; y2 = nYPos + nRadius; @@ -476,6 +492,7 @@ void DoUnVision (int nXPos, int nYPos, int nRadius) int i, j; int x1,y1,x2,y2; + nRadius = GetEffectiveLightRadius(nRadius); nRadius++; y1 = nYPos - nRadius; y2 = nYPos + nRadius; @@ -499,6 +516,8 @@ void DoVision (int nXPos, int nYPos, int nRadius, BOOL doautomap, BOOL visible) int i, j, k, v; int x1adj, x2adj, y1adj, y2adj; + nRadius = GetEffectiveLightRadius(nRadius); + // handle origin separately. Why? I don't know. if (nXPos >= 0 && nXPos <= DMAXX && nYPos >= 0 && nYPos <= DMAXY) { if (doautomap) { diff --git a/NTHREAD.CPP b/NTHREAD.CPP index 465b438..3da046d 100644 --- a/NTHREAD.CPP +++ b/NTHREAD.CPP @@ -703,3 +703,20 @@ BOOL nthread_run_gameloop(BOOL bReloop) { return (lDelta >= 0); } + + +//****************************************************************** +//****************************************************************** +int nthread_get_render_interp() +{ + long lFrameMs = 1000 / GAME_FRAMES_PER_SECOND; + long lUntilNextFrame = sglGameClock - (long)GetTickCount(); + long lElapsed = lFrameMs - lUntilNextFrame; + + if (lElapsed <= 0) + return 0; + if (lElapsed >= lFrameMs) + return 256; + + return (int)((lElapsed * 256) / lFrameMs); +} diff --git a/PALETTE.CPP b/PALETTE.CPP index b79f35d..b6e45b6 100644 --- a/PALETTE.CPP +++ b/PALETTE.CPP @@ -37,6 +37,405 @@ static PALETTEENTRY sgCurr[256]; // palette to be displayed -- includes rotation static const char sgszGamma[] = "Gamma Correction"; static BYTE sgbFadedIn = TRUE; +extern "C" { + BYTE gbLevelTileEnhanceActive = FALSE; + BYTE gbLevelTileContrastTable[256]; + BYTE gbLevelTileLumaTable[256]; + BYTE gbLevelTileSharpenLightTable[256]; + BYTE gbLevelTileAoTable[256]; + BYTE gbLevelUnitContrastTable[256]; + BYTE gbLevelUnitLumaTable[256]; + BYTE gbLevelUnitSharpenLightTable[256]; + BYTE gbLevelUnitAoTable[256]; + BYTE gbTownWarmFlickerActive = FALSE; + BYTE gbTownWarmFlickerTable[4][256]; + BYTE gbHudAnimateActive = FALSE; + BYTE gbHudHealthOrbTable[4][256]; + BYTE gbHudManaOrbTable[4][256]; + BYTE gbHudPotionHealthTable[4][256]; + BYTE gbHudPotionManaTable[4][256]; + BYTE gbHudPotionRejuvTable[4][256]; + BYTE gbWorldGoldShimmerActive = FALSE; + BYTE gbWorldGoldShimmerTable[4][256]; + int gnTownTileX = -1; + int gnTownTileY = -1; + int gnTownFlickerFrame = 0; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static int PalClamp(int value, int max) +{ + if (value < 0) return 0; + if (value > max) return max; + return value; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static LONG PalDistance(const PALETTEENTRY *a, int red, int green, int blue) +{ + LONG dr, dg, db; + + dr = (LONG)a->peRed - red; + dg = (LONG)a->peGreen - green; + db = (LONG)a->peBlue - blue; + + return dr * dr + dg * dg + db * db; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static BYTE FindNearestPaletteColor(int red, int green, int blue) +{ + int i; + BYTE best; + LONG dist, bestDist; + + best = 1; + bestDist = PalDistance(&sgLoad[1], red, green, blue); + + for (i = 2; i < 256; i++) { + dist = PalDistance(&sgLoad[i], red, green, blue); + if (dist < bestDist) { + bestDist = dist; + best = (BYTE)i; + } + } + + return best; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void BuildLevelTileEnhanceTables() +{ + int i, max, mid; + int red, green, blue, brightness; + + max = 63; + for (i = 0; i < 256; i++) { + if (sgLoad[i].peRed > 63 || sgLoad[i].peGreen > 63 || sgLoad[i].peBlue > 63) { + max = 255; + break; + } + } + mid = max / 2; + + gbLevelTileContrastTable[0] = 0; + gbLevelTileLumaTable[0] = 0; + gbLevelTileSharpenLightTable[0] = 0; + gbLevelTileAoTable[0] = 0; + gbLevelUnitContrastTable[0] = 0; + gbLevelUnitLumaTable[0] = 0; + gbLevelUnitSharpenLightTable[0] = 0; + gbLevelUnitAoTable[0] = 0; + for (i = 1; i < 256; i++) { + brightness = ((int)sgLoad[i].peRed * 30 + (int)sgLoad[i].peGreen * 59 + (int)sgLoad[i].peBlue * 11) / 100; + gbLevelTileLumaTable[i] = (BYTE)((brightness * 255) / max); + gbLevelUnitLumaTable[i] = gbLevelTileLumaTable[i]; + + red = (int)sgLoad[i].peRed + (((int)max - (int)sgLoad[i].peRed) * 6) / 100; + green = (int)sgLoad[i].peGreen + (((int)max - (int)sgLoad[i].peGreen) * 6) / 100; + blue = (int)sgLoad[i].peBlue + (((int)max - (int)sgLoad[i].peBlue) * 6) / 100; + gbLevelTileSharpenLightTable[i] = FindNearestPaletteColor( + PalClamp(red, max), + PalClamp(green, max), + PalClamp(blue, max)); + + red = ((int)sgLoad[i].peRed * 90) / 100; + green = ((int)sgLoad[i].peGreen * 90) / 100; + blue = ((int)sgLoad[i].peBlue * 90) / 100; + gbLevelTileAoTable[i] = FindNearestPaletteColor( + PalClamp(red, max), + PalClamp(green, max), + PalClamp(blue, max)); + + red = (int)sgLoad[i].peRed + (((int)max - (int)sgLoad[i].peRed) * 12) / 100; + green = (int)sgLoad[i].peGreen + (((int)max - (int)sgLoad[i].peGreen) * 12) / 100; + blue = (int)sgLoad[i].peBlue + (((int)max - (int)sgLoad[i].peBlue) * 12) / 100; + gbLevelUnitSharpenLightTable[i] = FindNearestPaletteColor( + PalClamp(red, max), + PalClamp(green, max), + PalClamp(blue, max)); + + red = ((int)sgLoad[i].peRed * 82) / 100; + green = ((int)sgLoad[i].peGreen * 82) / 100; + blue = ((int)sgLoad[i].peBlue * 82) / 100; + gbLevelUnitAoTable[i] = FindNearestPaletteColor( + PalClamp(red, max), + PalClamp(green, max), + PalClamp(blue, max)); + + if (brightness < max / 5 || brightness > (max * 4) / 5) { + gbLevelTileContrastTable[i] = (BYTE)i; + gbLevelUnitContrastTable[i] = (BYTE)i; + continue; + } + + red = mid + (((int)sgLoad[i].peRed - mid) * 106) / 100; + green = mid + (((int)sgLoad[i].peGreen - mid) * 106) / 100; + blue = mid + (((int)sgLoad[i].peBlue - mid) * 106) / 100; + + gbLevelTileContrastTable[i] = FindNearestPaletteColor( + PalClamp(red, max), + PalClamp(green, max), + PalClamp(blue, max)); + + red = mid + (((int)sgLoad[i].peRed - mid) * 108) / 100; + green = mid + (((int)sgLoad[i].peGreen - mid) * 108) / 100; + blue = mid + (((int)sgLoad[i].peBlue - mid) * 108) / 100; + + gbLevelUnitContrastTable[i] = FindNearestPaletteColor( + PalClamp(red, max), + PalClamp(green, max), + PalClamp(blue, max)); + } +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static int IsWarmTownLightColor(int red, int green, int blue, int brightness, int max) +{ + if (brightness < max / 4) + return FALSE; + if (red < green || green < blue) + return FALSE; + if (red - blue < max / 7) + return FALSE; + if (green - blue < max / 12) + return FALSE; + return TRUE; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void BuildTownWarmFlickerTables() +{ + int i, p, max; + int red, green, blue, brightness; + static const int sPhaseRed[4] = { 6, 14, 9, -3 }; + static const int sPhaseGreen[4] = { 3, 8, 5, -2 }; + static const int sPhaseBlue[4] = { -3, -6, -4, 0 }; + + max = 63; + for (i = 0; i < 256; i++) { + if (sgLoad[i].peRed > 63 || sgLoad[i].peGreen > 63 || sgLoad[i].peBlue > 63) { + max = 255; + break; + } + } + + for (i = 0; i < 256; i++) { + brightness = ((int)sgLoad[i].peRed * 30 + (int)sgLoad[i].peGreen * 59 + (int)sgLoad[i].peBlue * 11) / 100; + for (p = 0; p < 4; p++) { + if (!IsWarmTownLightColor(sgLoad[i].peRed, sgLoad[i].peGreen, sgLoad[i].peBlue, brightness, max)) { + gbTownWarmFlickerTable[p][i] = (BYTE)i; + continue; + } + + red = (int)sgLoad[i].peRed + (((int)max - (int)sgLoad[i].peRed) * sPhaseRed[p]) / 100; + green = (int)sgLoad[i].peGreen + (((int)max - (int)sgLoad[i].peGreen) * sPhaseGreen[p]) / 100; + if (sPhaseBlue[p] < 0) + blue = ((int)sgLoad[i].peBlue * (100 + sPhaseBlue[p])) / 100; + else + blue = (int)sgLoad[i].peBlue + (((int)max - (int)sgLoad[i].peBlue) * sPhaseBlue[p]) / 100; + + gbTownWarmFlickerTable[p][i] = FindNearestPaletteColor( + PalClamp(red, max), + PalClamp(green, max), + PalClamp(blue, max)); + } + } +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static int IsHudHealthColor(int red, int green, int blue, int brightness, int max) +{ + if (brightness < max / 5) + return FALSE; + if (red < green - max / 16) + return FALSE; + if (red < blue - max / 12) + return FALSE; + return TRUE; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static int IsHudManaColor(int red, int green, int blue, int brightness, int max) +{ + if (brightness < max / 5) + return FALSE; + if (blue < red - max / 16) + return FALSE; + if (blue < green - max / 12) + return FALSE; + return TRUE; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static int IsHudRejuvColor(int red, int green, int blue, int brightness, int max) +{ + if (brightness < max / 5) + return FALSE; + if (red < green + max / 14) + return FALSE; + if (blue < green + max / 14) + return FALSE; + return TRUE; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static int HudShiftChannel(int value, int max, int percent) +{ + if (percent >= 0) + return value + ((max - value) * percent) / 100; + return (value * (100 + percent)) / 100; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void BuildHudAnimTable(BYTE table[4][256], const int redPhase[4], const int greenPhase[4], const int bluePhase[4], int kind, int max) +{ + int i, p; + int red, green, blue, brightness; + int useColor; + + for (i = 0; i < 256; i++) { + red = sgLoad[i].peRed; + green = sgLoad[i].peGreen; + blue = sgLoad[i].peBlue; + brightness = (red * 30 + green * 59 + blue * 11) / 100; + + useColor = FALSE; + if (kind == 0) + useColor = IsHudHealthColor(red, green, blue, brightness, max); + else if (kind == 1) + useColor = IsHudManaColor(red, green, blue, brightness, max); + else + useColor = IsHudRejuvColor(red, green, blue, brightness, max); + + for (p = 0; p < 4; p++) { + if (!useColor) { + table[p][i] = (BYTE)i; + continue; + } + + table[p][i] = FindNearestPaletteColor( + PalClamp(HudShiftChannel(red, max, redPhase[p]), max), + PalClamp(HudShiftChannel(green, max, greenPhase[p]), max), + PalClamp(HudShiftChannel(blue, max, bluePhase[p]), max)); + } + } +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void BuildHudAnimateTables() +{ + int i, max; + static const int sHealthOrbRed[4] = { 6, 16, 9, -4 }; + static const int sHealthOrbGreen[4] = { 1, 4, 2, -2 }; + static const int sHealthOrbBlue[4] = { -4, -10, -6, 0 }; + static const int sManaOrbRed[4] = { -4, -10, -6, 0 }; + static const int sManaOrbGreen[4] = { 2, 7, 4, -2 }; + static const int sManaOrbBlue[4] = { 7, 18, 10, -4 }; + static const int sHealthPotionRed[4] = { 3, 8, 5, -2 }; + static const int sHealthPotionGreen[4] = { 0, 2, 1, -1 }; + static const int sHealthPotionBlue[4] = { -2, -5, -3, 0 }; + static const int sManaPotionRed[4] = { -2, -5, -3, 0 }; + static const int sManaPotionGreen[4] = { 1, 4, 2, -1 }; + static const int sManaPotionBlue[4] = { 4, 11, 6, -2 }; + static const int sRejuvPotionRed[4] = { 4, 11, 6, -2 }; + static const int sRejuvPotionGreen[4] = { -1, 1, 0, -1 }; + static const int sRejuvPotionBlue[4] = { 4, 11, 6, -2 }; + + max = 63; + for (i = 0; i < 256; i++) { + if (sgLoad[i].peRed > 63 || sgLoad[i].peGreen > 63 || sgLoad[i].peBlue > 63) { + max = 255; + break; + } + } + + BuildHudAnimTable(gbHudHealthOrbTable, sHealthOrbRed, sHealthOrbGreen, sHealthOrbBlue, 0, max); + BuildHudAnimTable(gbHudManaOrbTable, sManaOrbRed, sManaOrbGreen, sManaOrbBlue, 1, max); + BuildHudAnimTable(gbHudPotionHealthTable, sHealthPotionRed, sHealthPotionGreen, sHealthPotionBlue, 0, max); + BuildHudAnimTable(gbHudPotionManaTable, sManaPotionRed, sManaPotionGreen, sManaPotionBlue, 1, max); + BuildHudAnimTable(gbHudPotionRejuvTable, sRejuvPotionRed, sRejuvPotionGreen, sRejuvPotionBlue, 2, max); +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static int IsWorldGoldColor(int red, int green, int blue, int brightness, int max) +{ + if (brightness < max / 8) + return FALSE; + if (red < green - max / 5) + return FALSE; + if (green < blue + max / 24) + return FALSE; + if (red < blue + max / 12) + return FALSE; + return TRUE; +} + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void BuildWorldGoldShimmerTables() +{ + int i, p, max; + int red, green, blue, brightness; + static const int sGoldRed[4] = { 2, 22, 8, -8 }; + static const int sGoldGreen[4] = { 1, 18, 6, -7 }; + static const int sGoldBlue[4] = { -3, -16, -7, -4 }; + + max = 63; + for (i = 0; i < 256; i++) { + if (sgLoad[i].peRed > 63 || sgLoad[i].peGreen > 63 || sgLoad[i].peBlue > 63) { + max = 255; + break; + } + } + + for (i = 0; i < 256; i++) { + red = sgLoad[i].peRed; + green = sgLoad[i].peGreen; + blue = sgLoad[i].peBlue; + brightness = (red * 30 + green * 59 + blue * 11) / 100; + + for (p = 0; p < 4; p++) { + if (!IsWorldGoldColor(red, green, blue, brightness, max)) { + gbWorldGoldShimmerTable[p][i] = (BYTE)i; + continue; + } + + gbWorldGoldShimmerTable[p][i] = FindNearestPaletteColor( + PalClamp(HudShiftChannel(red, max, sGoldRed[p]), max), + PalClamp(HudShiftChannel(green, max, sGoldGreen[p]), max), + PalClamp(HudShiftChannel(blue, max, sGoldBlue[p]), max)); + } + } +} + /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ @@ -184,6 +583,15 @@ void LoadRndLvlPal(int l) { } LoadPalette(filestr); } + + BuildLevelTileEnhanceTables(); + BuildTownWarmFlickerTables(); + BuildHudAnimateTables(); + BuildWorldGoldShimmerTables(); + gbLevelTileEnhanceActive = TRUE; + gbTownWarmFlickerActive = (l == 0); + gbHudAnimateActive = FALSE; + gbWorldGoldShimmerActive = TRUE; } diff --git a/SCROLLRT.CPP b/SCROLLRT.CPP index 4faad47..eabb6d9 100644 --- a/SCROLLRT.CPP +++ b/SCROLLRT.CPP @@ -71,11 +71,23 @@ void DrawUnit(long xp,long yp,BYTE *pCelBuff,long nCel,long nCelW,long ostart,lo void DrawUnitOutline(byte ocolor, long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend); void DrawInfraUnit(long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend, char loff); void DrawLitUnit(long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend); +void DrawEnhancedUnit(long xp,long yp,BYTE *pCelBuff,long nCel,long nCelW,long ostart,long oend); +void DrawEnhancedInfraUnit(long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend, char loff); +void DrawEnhancedLitUnit(long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend); +void DrawUnitLerpOverlay(long xp,long yp,BYTE *pCelBuff,long nCel,long nCelW,long ostart,long oend,int density); +void DrawInfraUnitLerpOverlay(long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend, char loff, int density); +void DrawLitUnitLerpOverlay(long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend, int density); void DrawUnitClipped(long xp,long yp,BYTE *pCelBuff,long nCel,long nCelW,long ostart,long oend); void DrawUnitOutlineClipped(byte ocolor, long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend); void DrawInfraUnitClipped(long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend, char loff); void DrawLitUnitClipped(long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend); +void DrawEnhancedUnitClipped(long xp,long yp,BYTE *pCelBuff,long nCel,long nCelW,long ostart,long oend); +void DrawEnhancedInfraUnitClipped(long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend, char loff); +void DrawEnhancedLitUnitClipped(long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend); +void DrawUnitLerpOverlayClipped(long xp,long yp,BYTE *pCelBuff,long nCel,long nCelW,long ostart,long oend,int density); +void DrawInfraUnitLerpOverlayClipped(long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend, char loff, int density); +void DrawLitUnitLerpOverlayClipped(long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend, int density); #endif void DrawHTLXsub (BYTE *pTo, int sx, int sy, int xp, int yp, BOOL chflag); @@ -98,9 +110,13 @@ extern "C" { char gbPartialTrans; DWORD gdwPNum; long glClipY; + extern BYTE gbWorldGoldShimmerActive; + extern BYTE gbWorldGoldShimmerTable[4][256]; } int gnMI; long nBuffWTbl[1024]; +int gnRenderFrameInterp; +extern int PlrWalkLenTbl[NUM_CLASSES]; // frame counter @@ -111,6 +127,340 @@ static BYTE sgfFrameCounterEnabled = FALSE; bool HighLightAllItems = false; +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void SetDungeonLightContext(int sx, int sy, int, int) +{ + nLVal = dLight[sx][sy]; + if (nLVal < lightmax) + nLVal++; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static int VisualHalfStep(long velocity, int fixedShift) +{ + int interp; + __int64 step; + + interp = gnRenderFrameInterp; + if (interp <= 0 || velocity == 0) + return 0; + if (interp > 256) + interp = 256; + + step = velocity; + if (step < 0) + return -(int)(((-step) * interp) >> (fixedShift + 8)); + + return (int)((step * interp) >> (fixedShift + 8)); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static BOOL PlayerUsesVisualLerp(PlayerStruct *pPlayer) +{ + return pPlayer->_pmode == PM_WALK + || pPlayer->_pmode == PM_WALK2 + || pPlayer->_pmode == PM_WALK3; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static BOOL PlayerHasVisualStep(PlayerStruct *pPlayer) +{ + int walkLen; + + walkLen = 8; + if (currlevel != 0) + walkLen = PlrWalkLenTbl[pPlayer->_pClass]; + + return pPlayer->_pVar8 < walkLen; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static int GetPlayerDrawX(PlayerStruct *pPlayer, int xp) +{ + xp += pPlayer->_pxoff; + if (PlayerUsesVisualLerp(pPlayer) && PlayerHasVisualStep(pPlayer)) + xp += VisualHalfStep(pPlayer->_pxvel, 8); + + return xp; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static int GetPlayerDrawY(PlayerStruct *pPlayer, int yp) +{ + yp += pPlayer->_pyoff; + if (PlayerUsesVisualLerp(pPlayer) && PlayerHasVisualStep(pPlayer)) + yp += VisualHalfStep(pPlayer->_pyvel, 8); + + return yp; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static int GetScrollDrawX() +{ + int sxoff; + PlayerStruct *pPlayer; + + sxoff = ScrollInfo._sxoff; + if (ScrollInfo._sdir == SCRL_NONE) + return sxoff; + + pPlayer = &plr[myplr]; + if (PlayerUsesVisualLerp(pPlayer) && PlayerHasVisualStep(pPlayer)) + sxoff -= VisualHalfStep(pPlayer->_pxvel, 8); + + return sxoff; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static int GetScrollDrawY() +{ + int syoff; + PlayerStruct *pPlayer; + + syoff = ScrollInfo._syoff; + if (ScrollInfo._sdir == SCRL_NONE) + return syoff; + + pPlayer = &plr[myplr]; + if (PlayerUsesVisualLerp(pPlayer) && PlayerHasVisualStep(pPlayer)) + syoff -= VisualHalfStep(pPlayer->_pyvel, 8); + + return syoff; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static BOOL MonsterUsesVisualLerp(MonsterStruct *pMonster) +{ + return pMonster->_mmode == MM_WALK + || pMonster->_mmode == MM_WALK2 + || pMonster->_mmode == MM_WALK3; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static BOOL MonsterHasVisualStep(MonsterStruct *pMonster) +{ + return pMonster->_mVar8 < pMonster->MType->Anims[MA_WALK].Frames; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static int GetMonsterDrawX(MonsterStruct *pMonster, int xp) +{ + xp += pMonster->_mxoff; + if (MonsterUsesVisualLerp(pMonster) && MonsterHasVisualStep(pMonster)) + xp += VisualHalfStep(pMonster->_mxvel, 4); + + return xp; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static int GetMonsterDrawY(MonsterStruct *pMonster, int yp) +{ + yp += pMonster->_myoff; + if (MonsterUsesVisualLerp(pMonster) && MonsterHasVisualStep(pMonster)) + yp += VisualHalfStep(pMonster->_myvel, 4); + + return yp; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static int GetMissileDrawX(MissileStruct *pMiss, int xp) +{ + xp += pMiss->_mixoff; + if (!(pMiss->_miAnimFlags & MFF_STATIC)) + xp += VisualHalfStep(pMiss->_mixvel, 16); + + return xp; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static int GetMissileDrawY(MissileStruct *pMiss, int yp) +{ + yp += pMiss->_miyoff; + if (!(pMiss->_miAnimFlags & MFF_STATIC)) + yp += VisualHalfStep(pMiss->_miyvel, 16); + + return yp; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static int GetVisualLerpDensity(int animCnt, int animDelay) +{ + int interp; + int progress; + int density; + + if (animDelay <= 1) + return 0; + + interp = gnRenderFrameInterp; + if (interp < 0) + interp = 0; + if (interp > 256) + interp = 256; + + progress = animCnt * 256 + interp; + density = (progress * 4) / (animDelay * 256); + if (density < 1) + return 0; + if (density > 3) + density = 3; + + return density; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static int GetForwardFrame(int frame, int length, int add, BOOL allowWrap) +{ + frame += add; + if (frame > length) + return allowWrap ? 1 : 0; + if (frame < 1) + return allowWrap ? length : 0; + + return frame; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static int GetPlayerLerpFrame(PlayerStruct *pPlayer, int *density) +{ + *density = GetVisualLerpDensity(pPlayer->_pAnimCnt, pPlayer->_pAnimDelay); + if (*density == 0) + return 0; + + return GetForwardFrame(pPlayer->_pAnimFrame, pPlayer->_pAnimLen, 1, FALSE); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static int GetMonsterLerpFrame(MonsterStruct *pMonster, int *density) +{ + int add; + + *density = GetVisualLerpDensity(pMonster->_mAnimCnt, pMonster->_mAnimDelay); + if (*density == 0 || (pMonster->_mFlags & MFLAG_STILL)) + return 0; + + add = (pMonster->_mFlags & MFLAG_BACKWARDS) ? -1 : 1; + return GetForwardFrame(pMonster->_mAnimFrame, pMonster->_mAnimLen, add, FALSE); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static int GetMissileLerpFrame(MissileStruct *pMiss, int *density) +{ + *density = GetVisualLerpDensity(pMiss->_miAnimCnt, pMiss->_miAnimDelay); + if (*density == 0 || (pMiss->_miAnimFlags & MFF_STATIC)) + return 0; + + return GetForwardFrame(pMiss->_miAnimFrame, pMiss->_miAnimLen, pMiss->_miAnimAdd, TRUE); +} + +#if RLE_DRAW +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static void DrawMissileLerpOverlay(MissileStruct *pMiss, int mx, int my, int ds, int de, BOOL clipped) +{ + int density, nextFrame; + + nextFrame = GetMissileLerpFrame(pMiss, &density); + if (!nextFrame) + return; + + if (pMiss->_miUniqTrans) { + if (clipped) + DrawInfraUnitLerpOverlayClipped(mx, my, pMiss->_miAnimData, nextFrame, pMiss->_miAnimWidth, ds, de, LIGHT_U + pMiss->_miUniqTrans - 1, density); + else + DrawInfraUnitLerpOverlay(mx, my, pMiss->_miAnimData, nextFrame, pMiss->_miAnimWidth, ds, de, LIGHT_U + pMiss->_miUniqTrans - 1, density); + } else if (pMiss->_miLightFlag) { + if (clipped) + DrawLitUnitLerpOverlayClipped(mx, my, pMiss->_miAnimData, nextFrame, pMiss->_miAnimWidth, ds, de, density); + else + DrawLitUnitLerpOverlay(mx, my, pMiss->_miAnimData, nextFrame, pMiss->_miAnimWidth, ds, de, density); + } else { + if (clipped) + DrawUnitLerpOverlayClipped(mx, my, pMiss->_miAnimData, nextFrame, pMiss->_miAnimWidth, ds, de, density); + else + DrawUnitLerpOverlay(mx, my, pMiss->_miAnimData, nextFrame, pMiss->_miAnimWidth, ds, de, density); + } +} +#endif + + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +void ApplyWorldGoldShimmer(ItemStruct *pItem, int itemIndex, int x, int y, int ostart, int oend) +{ + int row, col, frame, fleck, run, xx, yy; + int nWidth, nCel; + long RLELen, offval, offval2; + BYTE *pFrame; + BYTE *pRLE; + BYTE *pEnd; + + if (!gbWorldGoldShimmerActive || gpBuffer == NULL || pItem->_itype != IT_GOLD) + return; + + nCel = pItem->_iAnimFrame; + nWidth = pItem->_iAnimWidth; + if (pItem->_iAnimData == NULL || nCel < 1 || nWidth <= 0) + return; + + pFrame = pItem->_iAnimData + *((DWORD *)pItem->_iAnimData + nCel); + offval = *(WORD *)(pFrame + ostart); + if (!offval) + return; + RLELen = *((DWORD *)pItem->_iAnimData + nCel + 1) - *((DWORD *)pItem->_iAnimData + nCel); + offval2 = (oend == 8) ? 0 : *(WORD *)(pFrame + oend); + RLELen = offval2 ? offval2 - offval : RLELen - offval; + pRLE = pFrame + offval; + pEnd = pRLE + RLELen; + + y -= ostart << 4; + frame = (GetTickCount() / 130) + itemIndex * 17 + pItem->_ix * 5 + pItem->_iy * 11; + for (row = 0; pRLE < pEnd; row++) { + yy = y - row; + col = 0; + while (col < nWidth && pRLE < pEnd) { + run = (signed char)*pRLE++; + if (run >= 0) { + if (run == 0) + break; + for (int i = 0; i < run; i++) { + xx = x + col + i; + if (xx >= 0 && xx < BUFFERX && yy >= 0 && yy < BUFFERY) { + BYTE *p = gpBuffer + nBuffWTbl[yy] + xx; + fleck = (row * 37 + (col + i) * 53 + frame * 29) & 31; + if (*p != IOUTC) + *p = gbWorldGoldShimmerTable[fleck < 5 ? 1 : 3][*p]; + } + } + pRLE += run; + col += run; + } else { + col -= run; + } + } + } +} + + //****************************************************************** // savecrsr variables //****************************************************************** @@ -229,8 +579,8 @@ void DrawMissile(int sx, int sy, int xp, int yp, int ds, int de, BOOL pre) if (dMissile[sx][sy] != -1) { gnMI = dMissile[sx][sy] - 1; if(missile[gnMI]._miPreFlag == pre) { - mx = missile[gnMI]._mixoff + xp - missile[gnMI]._miAnimWidth2; - my = missile[gnMI]._miyoff + yp; + mx = GetMissileDrawX(&missile[gnMI], xp) - missile[gnMI]._miAnimWidth2; + my = GetMissileDrawY(&missile[gnMI], yp); if (missile[gnMI]._miUniqTrans) { DrawSlabCelI(mx, my, missile[gnMI]._miAnimData, missile[gnMI]._miAnimFrame, missile[gnMI]._miAnimWidth, ds, de, LIGHT_U + missile[gnMI]._miUniqTrans - 1); } @@ -250,8 +600,8 @@ void DrawMissile(int sx, int sy, int xp, int yp, int ds, int de, BOOL pre) if ((missile[gnMI]._mix == sx) && (missile[gnMI]._miy == sy) && (missile[gnMI]._miPreFlag == pre) && (missile[gnMI]._miDrawFlag == TRUE)) { - mx = missile[gnMI]._mixoff + xp - missile[gnMI]._miAnimWidth2; - my = missile[gnMI]._miyoff + yp; + mx = GetMissileDrawX(&missile[gnMI], xp) - missile[gnMI]._miAnimWidth2; + my = GetMissileDrawY(&missile[gnMI], yp); if (missile[gnMI]._miUniqTrans) { DrawSlabCelI(mx, my, missile[gnMI]._miAnimData, missile[gnMI]._miAnimFrame, missile[gnMI]._miAnimWidth, ds, de, LIGHT_U + missile[gnMI]._miUniqTrans - 1); } @@ -280,8 +630,8 @@ void CDrawMissile(int sx, int sy, int xp, int yp, int ds, int de, BOOL pre) if (dMissile[sx][sy] != -1) { gnMI = dMissile[sx][sy] - 1; if (missile[gnMI]._miPreFlag == pre) { - mx = missile[gnMI]._mixoff + xp - missile[gnMI]._miAnimWidth2; - my = missile[gnMI]._miyoff + yp; + mx = GetMissileDrawX(&missile[gnMI], xp) - missile[gnMI]._miAnimWidth2; + my = GetMissileDrawY(&missile[gnMI], yp); if (missile[gnMI]._miUniqTrans) CDrawSlabCelI(mx, my, missile[gnMI]._miAnimData, missile[gnMI]._miAnimFrame, missile[gnMI]._miAnimWidth, ds, de, LIGHT_U + missile[gnMI]._miUniqTrans - 1); else { @@ -295,8 +645,8 @@ void CDrawMissile(int sx, int sy, int xp, int yp, int ds, int de, BOOL pre) if ((missile[gnMI]._mix == sx) && (missile[gnMI]._miy == sy) && (missile[gnMI]._miPreFlag == pre) && (missile[gnMI]._miDrawFlag == TRUE)) { - mx = missile[gnMI]._mixoff + xp - missile[gnMI]._miAnimWidth2; - my = missile[gnMI]._miyoff + yp; + mx = GetMissileDrawX(&missile[gnMI], xp) - missile[gnMI]._miAnimWidth2; + my = GetMissileDrawY(&missile[gnMI], yp); if (missile[gnMI]._miUniqTrans) CDrawSlabCelI(mx, my, missile[gnMI]._miAnimData, missile[gnMI]._miAnimFrame, missile[gnMI]._miAnimWidth, ds, de, LIGHT_U + missile[gnMI]._miUniqTrans - 1); else { @@ -353,8 +703,8 @@ void DrawMissile(int sx, int sy, int xp, int yp, int ds, int de, BOOL pre) #endif // jcm.patch1.end.1/14/97 } - mx = pMiss->_mixoff + xp - pMiss->_miAnimWidth2; - my = pMiss->_miyoff + yp; + mx = GetMissileDrawX(pMiss, xp) - pMiss->_miAnimWidth2; + my = GetMissileDrawY(pMiss, yp); if (pMiss->_miUniqTrans) { DrawInfraUnit( mx, my, @@ -369,6 +719,7 @@ void DrawMissile(int sx, int sy, int xp, int yp, int ds, int de, BOOL pre) } else { DrawUnit(mx, my, pMiss->_miAnimData, pMiss->_miAnimFrame, pMiss->_miAnimWidth, ds, de); } + DrawMissileLerpOverlay(pMiss, mx, my, ds, de, FALSE); } return; } @@ -398,8 +749,8 @@ void DrawMissile(int sx, int sy, int xp, int yp, int ds, int de, BOOL pre) #endif // jcm.patch1.end.1/14/97 } - mx = pMiss->_mixoff + xp - pMiss->_miAnimWidth2; - my = pMiss->_miyoff + yp; + mx = GetMissileDrawX(pMiss, xp) - pMiss->_miAnimWidth2; + my = GetMissileDrawY(pMiss, yp); if (pMiss->_miUniqTrans) { DrawInfraUnit( mx, my, @@ -414,6 +765,7 @@ void DrawMissile(int sx, int sy, int xp, int yp, int ds, int de, BOOL pre) } else { DrawUnit(mx, my, pMiss->_miAnimData, pMiss->_miAnimFrame, pMiss->_miAnimWidth, ds, de); } + DrawMissileLerpOverlay(pMiss, mx, my, ds, de, FALSE); } #endif @@ -460,8 +812,8 @@ void CDrawMissile(int sx, int sy, int xp, int yp, int ds, int de, BOOL pre) #endif // jcm.patch1.end.1/14/97 } - mx = pMiss->_mixoff + xp - pMiss->_miAnimWidth2; - my = pMiss->_miyoff + yp; + mx = GetMissileDrawX(pMiss, xp) - pMiss->_miAnimWidth2; + my = GetMissileDrawY(pMiss, yp); if (pMiss->_miUniqTrans) { DrawInfraUnitClipped( mx, my, @@ -476,6 +828,7 @@ void CDrawMissile(int sx, int sy, int xp, int yp, int ds, int de, BOOL pre) } else { DrawUnitClipped(mx,my,pMiss->_miAnimData,pMiss->_miAnimFrame,pMiss->_miAnimWidth,ds,de); } + DrawMissileLerpOverlay(pMiss, mx, my, ds, de, TRUE); } return; } @@ -505,8 +858,8 @@ void CDrawMissile(int sx, int sy, int xp, int yp, int ds, int de, BOOL pre) #endif // jcm.patch1.end.1/14/97 } - mx = pMiss->_mixoff + xp - pMiss->_miAnimWidth2; - my = pMiss->_miyoff + yp; + mx = GetMissileDrawX(pMiss, xp) - pMiss->_miAnimWidth2; + my = GetMissileDrawY(pMiss, yp); if (pMiss->_miUniqTrans) { DrawInfraUnitClipped( mx, my, @@ -521,6 +874,7 @@ void CDrawMissile(int sx, int sy, int xp, int yp, int ds, int de, BOOL pre) } else { DrawUnitClipped(mx,my,pMiss->_miAnimData,pMiss->_miAnimFrame,pMiss->_miAnimWidth,ds,de); } + DrawMissileLerpOverlay(pMiss, mx, my, ds, de, TRUE); } #endif @@ -605,6 +959,8 @@ inline const char * MonsterActionString(DWORD dwAction) { #if RLE_DRAW static void DrawMSlabCelL (int sx, int sy, int xp, int yp, int gnMI, int ostart, int oend) { + int density, nextFrame; + if ((DWORD)gnMI >= MAXMONSTERS) // jcm.patch1.start.1/14/97 #ifdef GRACEFUL_EXIT @@ -639,7 +995,7 @@ static void DrawMSlabCelL (int sx, int sy, int xp, int yp, int gnMI, int ostart, // jcm.patch1.end.1/14/97 } if (!(dFlags[sx][sy] & BFLAG_VISIBLE)) { - DrawInfraUnit( + DrawEnhancedInfraUnit( xp, yp, monster[gnMI]._mAnimData, monster[gnMI]._mAnimFrame, @@ -648,6 +1004,9 @@ static void DrawMSlabCelL (int sx, int sy, int xp, int yp, int gnMI, int ostart, oend, LIGHT_INFRA ); + nextFrame = GetMonsterLerpFrame(&monster[gnMI], &density); + if (nextFrame) + DrawInfraUnitLerpOverlay(xp, yp, monster[gnMI]._mAnimData, nextFrame, monster[gnMI].MType->mAnimWidth, ostart, oend, LIGHT_INFRA, density); return; } char dinfra = LIGHT_NORM; @@ -658,7 +1017,7 @@ static void DrawMSlabCelL (int sx, int sy, int xp, int yp, int gnMI, int ostart, if (plr[myplr]._pInfraFlag && (nLVal > 8)) dinfra = LIGHT_INFRA; if (dinfra != LIGHT_NORM) - DrawInfraUnit( + DrawEnhancedInfraUnit( xp, yp, monster[gnMI]._mAnimData, monster[gnMI]._mAnimFrame, @@ -668,7 +1027,7 @@ static void DrawMSlabCelL (int sx, int sy, int xp, int yp, int gnMI, int ostart, dinfra ); else - DrawLitUnit( + DrawEnhancedLitUnit( xp, yp, monster[gnMI]._mAnimData, monster[gnMI]._mAnimFrame, @@ -676,6 +1035,13 @@ static void DrawMSlabCelL (int sx, int sy, int xp, int yp, int gnMI, int ostart, ostart, oend ); + nextFrame = GetMonsterLerpFrame(&monster[gnMI], &density); + if (nextFrame) { + if (dinfra != LIGHT_NORM) + DrawInfraUnitLerpOverlay(xp, yp, monster[gnMI]._mAnimData, nextFrame, monster[gnMI].MType->mAnimWidth, ostart, oend, dinfra, density); + else + DrawLitUnitLerpOverlay(xp, yp, monster[gnMI]._mAnimData, nextFrame, monster[gnMI].MType->mAnimWidth, ostart, oend, density); + } } #endif @@ -685,6 +1051,8 @@ static void DrawMSlabCelL (int sx, int sy, int xp, int yp, int gnMI, int ostart, #if RLE_DRAW static void CDrawMSlabCelL (int sx, int sy, int xp, int yp, int gnMI, int ostart, int oend) { + int density, nextFrame; + if ((DWORD)gnMI >= MAXMONSTERS) // jcm.patch1.start.1/14/97 #ifdef GRACEFUL_EXIT @@ -719,7 +1087,7 @@ static void CDrawMSlabCelL (int sx, int sy, int xp, int yp, int gnMI, int ostart // jcm.patch1.end.1/14/97 } if (!(dFlags[sx][sy] & BFLAG_VISIBLE)) { - DrawInfraUnitClipped( + DrawEnhancedInfraUnitClipped( xp, yp, monster[gnMI]._mAnimData, monster[gnMI]._mAnimFrame, @@ -728,6 +1096,9 @@ static void CDrawMSlabCelL (int sx, int sy, int xp, int yp, int gnMI, int ostart oend, LIGHT_INFRA ); + nextFrame = GetMonsterLerpFrame(&monster[gnMI], &density); + if (nextFrame) + DrawInfraUnitLerpOverlayClipped(xp, yp, monster[gnMI]._mAnimData, nextFrame, monster[gnMI].MType->mAnimWidth, ostart, oend, LIGHT_INFRA, density); return; } char dinfra = LIGHT_NORM; @@ -738,7 +1109,7 @@ static void CDrawMSlabCelL (int sx, int sy, int xp, int yp, int gnMI, int ostart if (plr[myplr]._pInfraFlag && (nLVal > 8)) dinfra = LIGHT_INFRA; if (dinfra != LIGHT_NORM) - DrawInfraUnitClipped( + DrawEnhancedInfraUnitClipped( xp, yp, monster[gnMI]._mAnimData, monster[gnMI]._mAnimFrame, @@ -748,7 +1119,7 @@ static void CDrawMSlabCelL (int sx, int sy, int xp, int yp, int gnMI, int ostart dinfra ); else - DrawLitUnitClipped( + DrawEnhancedLitUnitClipped( xp, yp, monster[gnMI]._mAnimData, monster[gnMI]._mAnimFrame, @@ -756,6 +1127,13 @@ static void CDrawMSlabCelL (int sx, int sy, int xp, int yp, int gnMI, int ostart ostart, oend ); + nextFrame = GetMonsterLerpFrame(&monster[gnMI], &density); + if (nextFrame) { + if (dinfra != LIGHT_NORM) + DrawInfraUnitLerpOverlayClipped(xp, yp, monster[gnMI]._mAnimData, nextFrame, monster[gnMI].MType->mAnimWidth, ostart, oend, dinfra, density); + else + DrawLitUnitLerpOverlayClipped(xp, yp, monster[gnMI]._mAnimData, nextFrame, monster[gnMI].MType->mAnimWidth, ostart, oend, density); + } } #endif @@ -864,6 +1242,8 @@ inline const char * PlayerActionString(DWORD dwAction) { static void DrawPSlabCelL ( int nPlayer, int sx, int sy, long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend) { + int density, nextFrame; + if (!(dFlags[sx][sy] & BFLAG_VISIBLE) && !plr[myplr]._pInfraFlag && (setlevel || currlevel)) return; if (pCelBuff == NULL) @@ -895,17 +1275,26 @@ static void DrawPSlabCelL ( DrawUnitOutline(POUTC,xp,yp,pCelBuff,nCel,nCelW,ostart,oend); if (nPlayer == myplr) { - DrawUnit(xp, yp, pCelBuff, nCel, nCelW, ostart, oend); + DrawEnhancedUnit(xp, yp, pCelBuff, nCel, nCelW, ostart, oend); + nextFrame = GetPlayerLerpFrame(&plr[nPlayer], &density); + if (nextFrame) + DrawUnitLerpOverlay(xp, yp, pCelBuff, nextFrame, nCelW, ostart, oend, density); } else if (!(dFlags[sx][sy] & BFLAG_VISIBLE) || plr[myplr]._pInfraFlag && (nLVal > 8)) { - DrawInfraUnit(xp, yp, pCelBuff, nCel, nCelW, ostart, oend, LIGHT_INFRA); + DrawEnhancedInfraUnit(xp, yp, pCelBuff, nCel, nCelW, ostart, oend, LIGHT_INFRA); + nextFrame = GetPlayerLerpFrame(&plr[nPlayer], &density); + if (nextFrame) + DrawInfraUnitLerpOverlay(xp, yp, pCelBuff, nextFrame, nCelW, ostart, oend, LIGHT_INFRA, density); } else { // Draw other players slightly brighter than monsters int templval = nLVal; nLVal = (nLVal < 5) ? 0 : nLVal - 5; - DrawLitUnit(xp, yp, pCelBuff, nCel, nCelW, ostart, oend); + DrawEnhancedLitUnit(xp, yp, pCelBuff, nCel, nCelW, ostart, oend); + nextFrame = GetPlayerLerpFrame(&plr[nPlayer], &density); + if (nextFrame) + DrawLitUnitLerpOverlay(xp, yp, pCelBuff, nextFrame, nCelW, ostart, oend, density); nLVal = templval; } } @@ -918,6 +1307,8 @@ static void DrawPSlabCelL ( static void CDrawPSlabCelL ( int nPlayer, int sx, int sy, long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend) { + int density, nextFrame; + if (!(dFlags[sx][sy] & BFLAG_VISIBLE) && !plr[myplr]._pInfraFlag) return; if (pCelBuff == NULL) @@ -948,15 +1339,29 @@ static void CDrawPSlabCelL ( if (nPlayer == cursplr) DrawUnitOutlineClipped(POUTC,xp,yp,pCelBuff,nCel,nCelW,ostart,oend); if (nPlayer == myplr) { - DrawUnitClipped(xp, yp, pCelBuff, nCel, nCelW, ostart, oend); + DrawEnhancedUnitClipped(xp, yp, pCelBuff, nCel, nCelW, ostart, oend); } else if (!(dFlags[sx][sy] & BFLAG_VISIBLE) || plr[myplr]._pInfraFlag && (nLVal > 8)) { - DrawInfraUnitClipped(xp, yp, pCelBuff, nCel, nCelW, ostart, oend, LIGHT_INFRA); + DrawEnhancedInfraUnitClipped(xp, yp, pCelBuff, nCel, nCelW, ostart, oend, LIGHT_INFRA); } else { // Draw other players slightly brighter than monsters int templval = nLVal; nLVal = (nLVal < 5) ? 0 : nLVal - 5; - DrawLitUnitClipped(xp, yp, pCelBuff, nCel, nCelW, ostart, oend); + DrawEnhancedLitUnitClipped(xp, yp, pCelBuff, nCel, nCelW, ostart, oend); + nLVal = templval; + } + nextFrame = GetPlayerLerpFrame(&plr[nPlayer], &density); + if (!nextFrame) + return; + if (nPlayer == myplr) { + DrawUnitLerpOverlayClipped(xp, yp, pCelBuff, nextFrame, nCelW, ostart, oend, density); + } else if (!(dFlags[sx][sy] & BFLAG_VISIBLE) + || plr[myplr]._pInfraFlag && (nLVal > 8)) { + DrawInfraUnitLerpOverlayClipped(xp, yp, pCelBuff, nextFrame, nCelW, ostart, oend, LIGHT_INFRA, density); + } else { + int templval = nLVal; + nLVal = (nLVal < 5) ? 0 : nLVal - 5; + DrawLitUnitLerpOverlayClipped(xp, yp, pCelBuff, nextFrame, nCelW, ostart, oend, density); nLVal = templval; } } @@ -1007,8 +1412,8 @@ void DrawDeadPlr(int sx, int sy, int xp, int yp, int ostart, int oend, BOOL clip } dFlags[sx][sy] |= BFLAG_DEADPLR; PlayerDraw(pnum, sx, sy, - pPlayer->_pxoff + xp - pPlayer->_pAnimWidth2, - pPlayer->_pyoff + yp, + GetPlayerDrawX(pPlayer, xp) - pPlayer->_pAnimWidth2, + GetPlayerDrawY(pPlayer, yp), pPlayer->_pAnimData, pPlayer->_pAnimFrame, pPlayer->_pAnimWidth, ostart, oend); } @@ -1158,7 +1563,7 @@ static void DrawEFlag1(BYTE *pTo2, int sx, int sy, int xp, int yp) oldnTrans = nTrans; oldPieceNum = gnPieceNum; gnPieceNum = dPiece[sx][sy]; - nLVal = dLight[sx][sy]; + SetDungeonLightContext(sx, sy, xp, yp); nTrans = TransList[dTransVal[sx][sy]] & nTransTable[gnPieceNum]; mt = &dMT2[CalcRot(sx,sy)].mt[0]; @@ -1361,6 +1766,7 @@ static void DrawHTLXsub (BYTE *pTo, int sx, int sy, int xp, int yp, BOOL chflag) 0, 8 ); + ApplyWorldGoldShimmer(pItem, bItem - 1, pxp, yp, 0, 8); } // jcm.patch1.start.1/14/97 #ifdef GRACEFUL_EXIT @@ -1384,8 +1790,8 @@ static void DrawHTLXsub (BYTE *pTo, int sx, int sy, int xp, int yp, BOOL chflag) #endif // jcm.patch1.end.1/14/97 PlayerStruct * pPlayer = &plr[nPlayer]; - pxp = pPlayer->_pxoff + xp - pPlayer->_pAnimWidth2; - pyp = pPlayer->_pyoff + yp; + pxp = GetPlayerDrawX(pPlayer, xp) - pPlayer->_pAnimWidth2; + pyp = GetPlayerDrawY(pPlayer, yp); CDrawPSlabCelL( -(bPlayerAbove + 1), sx, sy-1, @@ -1433,8 +1839,8 @@ static void DrawHTLXsub (BYTE *pTo, int sx, int sy, int xp, int yp, BOOL chflag) app_fatal("Draw Monster \"%s\" Clipped: uninitialized monster",pMonster->mName); #endif // jcm.patch1.end.1/14/97 - pxp = pMonster->_mxoff + xp - pMonster->MType->mAnimWidth2; - pyp = pMonster->_myoff + yp; + pxp = GetMonsterDrawX(pMonster, xp) - pMonster->MType->mAnimWidth2; + pyp = GetMonsterDrawY(pMonster, yp); #if RLE_DRAW if (gnMI == cursmonst) DrawUnitOutlineClipped( @@ -1488,8 +1894,8 @@ static void DrawHTLXsub (BYTE *pTo, int sx, int sy, int xp, int yp, BOOL chflag) #endif // jcm.patch1.end.1/14/97 PlayerStruct * pPlayer = &plr[nPlayer]; - pxp = pPlayer->_pxoff + xp - pPlayer->_pAnimWidth2; - pyp = pPlayer->_pyoff + yp; + pxp = GetPlayerDrawX(pPlayer, xp) - pPlayer->_pAnimWidth2; + pyp = GetPlayerDrawY(pPlayer, yp); CDrawPSlabCelL( bPlayer - 1, sx, sy, @@ -1537,8 +1943,8 @@ static void DrawHTLXsub (BYTE *pTo, int sx, int sy, int xp, int yp, BOOL chflag) app_fatal("Draw Monster \"%s\" Clipped: uninitialized monster",pMonster->mName); #endif // jcm.patch1.end.1/14/97 - pxp = pMonster->_mxoff + xp - pMonster->MType->mAnimWidth2; - pyp = pMonster->_myoff + yp; + pxp = GetMonsterDrawX(pMonster, xp) - pMonster->MType->mAnimWidth2; + pyp = GetMonsterDrawY(pMonster, yp); #if RLE_DRAW if (gnMI == cursmonst) DrawUnitOutlineClipped( @@ -1639,6 +2045,7 @@ static void DrawHTLXsub (BYTE *pTo, int sx, int sy, int xp, int yp, BOOL chflag) 0, 8 ); + ApplyWorldGoldShimmer(pItem, bItem - 1, pxp, yp, 0, 8); } // jcm.patch1.start.1/14/97 #ifdef GRACEFUL_EXIT @@ -1668,7 +2075,7 @@ static void DrawHTileLineX (int sx, int sy, int xp, int yp, int nd, int halfflag if (halfflag) { if (((unsigned)sy < DMAXY) && ((unsigned)sx < DMAXX)) { gnPieceNum = dPiece[sx][sy]; - nLVal = dLight[sx][sy]; + SetDungeonLightContext(sx, sy, xp, yp); if (gnPieceNum) { pTo = gpBuffer + nBuffWTbl[yp] + xp + 32; nTrans = TransList[dTransVal[sx][sy]] & nTransTable[gnPieceNum]; @@ -1717,7 +2124,7 @@ static void DrawHTileLineX (int sx, int sy, int xp, int yp, int nd, int halfflag if (sy >= DMAXY || sx < 0) continue; gnPieceNum = dPiece[sx][sy]; - nLVal = dLight[sx][sy]; + SetDungeonLightContext(sx, sy, xp, yp); if (!gnPieceNum) { pTo = gpBuffer + nBuffWTbl[yp] + xp; DrawBlankMTile(pTo); @@ -1748,7 +2155,7 @@ static void DrawHTileLineX (int sx, int sy, int xp, int yp, int nd, int halfflag if (!halfflag || !((unsigned)sy < DMAXY && (unsigned)sx < DMAXX)) return; gnPieceNum = dPiece[sx][sy]; - nLVal = dLight[sx][sy]; + SetDungeonLightContext(sx, sy, xp, yp); if (!gnPieceNum) { pTo = gpBuffer + nBuffWTbl[yp] + xp; DrawBlankMTile(pTo); @@ -1794,7 +2201,7 @@ static void DrawEFlag2(BYTE *pTo2, int sx, int sy, int sv, int sv2, int xp, int oldnTrans = nTrans; oldPieceNum = gnPieceNum; gnPieceNum = dPiece[sx][sy]; - nLVal = dLight[sx][sy]; + SetDungeonLightContext(sx, sy, xp, yp); pTo = pTo2 + (NBUFFWSL5 * sv); nTrans = TransList[dTransVal[sx][sy]] & nTransTable[gnPieceNum]; mt = &dMT2[CalcRot(sx,sy)].mt[0]; @@ -2005,6 +2412,7 @@ static void DrawHTLXsub2 (BYTE *pTo, int sx, int sy, int sv, int sv2, int xp, in sv2, 8 ); + ApplyWorldGoldShimmer(pItem, bItem - 1, pxp, yp, sv2, 8); } // jcm.patch1.start.1/14/97 #ifdef GRACEFUL_EXIT @@ -2028,8 +2436,8 @@ static void DrawHTLXsub2 (BYTE *pTo, int sx, int sy, int sv, int sv2, int xp, in #endif // jcm.patch1.end.1/14/97 PlayerStruct * pPlayer = &plr[nPlayer]; - pxp = pPlayer->_pxoff + xp - pPlayer->_pAnimWidth2; - pyp = pPlayer->_pyoff + yp; + pxp = GetPlayerDrawX(pPlayer, xp) - pPlayer->_pAnimWidth2; + pyp = GetPlayerDrawY(pPlayer, yp); CDrawPSlabCelL( -(bPlayerAbove + 1), sx, sy-1, @@ -2077,8 +2485,8 @@ static void DrawHTLXsub2 (BYTE *pTo, int sx, int sy, int sv, int sv2, int xp, in app_fatal("Draw Monster \"%s\" Clipped: uninitialized monster",pMonster->mName); #endif // jcm.patch1.end.1/14/97 - pxp = pMonster->_mxoff + xp - pMonster->MType->mAnimWidth2; - pyp = pMonster->_myoff + yp; + pxp = GetMonsterDrawX(pMonster, xp) - pMonster->MType->mAnimWidth2; + pyp = GetMonsterDrawY(pMonster, yp); #if RLE_DRAW if (gnMI == cursmonst) DrawUnitOutlineClipped( @@ -2132,8 +2540,8 @@ static void DrawHTLXsub2 (BYTE *pTo, int sx, int sy, int sv, int sv2, int xp, in #endif // jcm.patch1.end.1/14/97 PlayerStruct * pPlayer = &plr[nPlayer]; - pxp = pPlayer->_pxoff + xp - pPlayer->_pAnimWidth2; - pyp = pPlayer->_pyoff + yp; + pxp = GetPlayerDrawX(pPlayer, xp) - pPlayer->_pAnimWidth2; + pyp = GetPlayerDrawY(pPlayer, yp); CDrawPSlabCelL( bPlayer - 1, sx, sy, @@ -2181,8 +2589,8 @@ static void DrawHTLXsub2 (BYTE *pTo, int sx, int sy, int sv, int sv2, int xp, in app_fatal("Draw Monster \"%s\" Clipped: uninitialized monster",pMonster->mName); #endif // jcm.patch1.end.1/14/97 - pxp = pMonster->_mxoff + xp - pMonster->MType->mAnimWidth2; - pyp = pMonster->_myoff + yp; + pxp = GetMonsterDrawX(pMonster, xp) - pMonster->MType->mAnimWidth2; + pyp = GetMonsterDrawY(pMonster, yp); #if RLE_DRAW if (gnMI == cursmonst) DrawUnitOutlineClipped( @@ -2283,6 +2691,7 @@ static void DrawHTLXsub2 (BYTE *pTo, int sx, int sy, int sv, int sv2, int xp, in sv2, 8 ); + ApplyWorldGoldShimmer(pItem, bItem - 1, pxp, yp, sv2, 8); } // jcm.patch1.start.1/14/97 #ifdef GRACEFUL_EXIT @@ -2314,7 +2723,7 @@ static void DrawHTLX2 (int sx, int sy, int xp, int yp, int nd, int sv, int halff if (halfflag != 0) { if ((sy >= 0) && (sy < DMAXY) && (sx >= 0) && (sx < DMAXX)) { gnPieceNum = dPiece[sx][sy]; - nLVal = dLight[sx][sy]; + SetDungeonLightContext(sx, sy, xp, yp); if (gnPieceNum != 0) { pTo = gpBuffer + nBuffWTbl[yp] + xp - NBUFFWSL5 + 32; nTrans = TransList[dTransVal[sx][sy]] & nTransTable[gnPieceNum]; @@ -2342,7 +2751,7 @@ static void DrawHTLX2 (int sx, int sy, int xp, int yp, int nd, int sv, int halff if (sy >= DMAXY || sx < 0) continue; gnPieceNum = dPiece[sx][sy]; - nLVal = dLight[sx][sy]; + SetDungeonLightContext(sx, sy, xp, yp); if (!gnPieceNum) continue; pTo = gpBuffer + nBuffWTbl[yp] + xp - NBUFFWSL5; @@ -2368,7 +2777,7 @@ static void DrawHTLX2 (int sx, int sy, int xp, int yp, int nd, int sv, int halff return; gnPieceNum = dPiece[sx][sy]; - nLVal = dLight[sx][sy]; + SetDungeonLightContext(sx, sy, xp, yp); if (!gnPieceNum) return; @@ -2404,7 +2813,7 @@ static void DrawEFlag3(BYTE *pTo2, int sx, int sy, int ev, int ev2, int xp, int oldnTrans = nTrans; oldPieceNum = gnPieceNum; gnPieceNum = dPiece[sx][sy]; - nLVal = dLight[sx][sy]; + SetDungeonLightContext(sx, sy, xp, yp); pTo = pTo2; nTrans = TransList[dTransVal[sx][sy]] & nTransTable[gnPieceNum]; mt = &dMT2[CalcRot(sx,sy)].mt[0]; @@ -2605,6 +3014,7 @@ static void DrawHTLXsub3 (BYTE *pTo, int sx, int sy, int ev, int ev2, int xp, in 0, ev2//diff ); + ApplyWorldGoldShimmer(pItem, bItem - 1, pxp, yp, 0, ev2); } // jcm.patch1.start.1/14/97 #ifdef GRACEFUL_EXIT @@ -2628,8 +3038,8 @@ static void DrawHTLXsub3 (BYTE *pTo, int sx, int sy, int ev, int ev2, int xp, in #endif // jcm.patch1.end.1/14/97 PlayerStruct * pPlayer = &plr[nPlayer]; - pxp = pPlayer->_pxoff + xp - pPlayer->_pAnimWidth2; - pyp = pPlayer->_pyoff + yp; + pxp = GetPlayerDrawX(pPlayer, xp) - pPlayer->_pAnimWidth2; + pyp = GetPlayerDrawY(pPlayer, yp); DrawPSlabCelL( -(bPlayerAbove + 1), sx, sy-1, @@ -2677,8 +3087,8 @@ static void DrawHTLXsub3 (BYTE *pTo, int sx, int sy, int ev, int ev2, int xp, in app_fatal("Draw Monster \"%s\": uninitialized monster",pMonster->mName); #endif // jcm.patch1.end.1/14/97 - pxp = pMonster->_mxoff + xp - pMonster->MType->mAnimWidth2; - pyp = pMonster->_myoff + yp; + pxp = GetMonsterDrawX(pMonster, xp) - pMonster->MType->mAnimWidth2; + pyp = GetMonsterDrawY(pMonster, yp); #if RLE_DRAW if (gnMI == cursmonst) DrawUnitOutline( @@ -2732,8 +3142,8 @@ static void DrawHTLXsub3 (BYTE *pTo, int sx, int sy, int ev, int ev2, int xp, in #endif // jcm.patch1.end.1/14/97 PlayerStruct * pPlayer = &plr[nPlayer]; - pxp = pPlayer->_pxoff + xp - pPlayer->_pAnimWidth2; - pyp = pPlayer->_pyoff + yp; + pxp = GetPlayerDrawX(pPlayer, xp) - pPlayer->_pAnimWidth2; + pyp = GetPlayerDrawY(pPlayer, yp); DrawPSlabCelL( bPlayer - 1, sx, sy, @@ -2781,8 +3191,8 @@ static void DrawHTLXsub3 (BYTE *pTo, int sx, int sy, int ev, int ev2, int xp, in app_fatal("Draw Monster \"%s\": uninitialized monster",pMonster->mName); #endif // jcm.patch1.end.1/14/97 - pxp = pMonster->_mxoff + xp - pMonster->MType->mAnimWidth2; - pyp = pMonster->_myoff + yp; + pxp = GetMonsterDrawX(pMonster, xp) - pMonster->MType->mAnimWidth2; + pyp = GetMonsterDrawY(pMonster, yp); #if RLE_DRAW if (gnMI == cursmonst) DrawUnitOutline( @@ -2883,6 +3293,7 @@ static void DrawHTLXsub3 (BYTE *pTo, int sx, int sy, int ev, int ev2, int xp, in 0, ev2 ); + ApplyWorldGoldShimmer(pItem, bItem - 1, pxp, yp, 0, ev2); } // jcm.patch1.start.1/14/97 #ifdef GRACEFUL_EXIT @@ -2915,7 +3326,7 @@ static void DrawHTLX3 (int sx, int sy, int xp, int yp, int nd, int ev, int halff if (halfflag != 0) { if ((sy >= 0) && (sy < DMAXY) && (sx >= 0) && (sx < DMAXX)) { gnPieceNum = dPiece[sx][sy]; - nLVal = dLight[sx][sy]; + SetDungeonLightContext(sx, sy, xp, yp); if (gnPieceNum != 0) { pTo = gpBuffer + nBuffWTbl[yp] + xp + 32; nTrans = TransList[dTransVal[sx][sy]] & nTransTable[gnPieceNum]; @@ -2954,7 +3365,7 @@ static void DrawHTLX3 (int sx, int sy, int xp, int yp, int nd, int ev, int halff for (i = 0; i < nd; ++i) { if ((sy >= 0) && (sy < DMAXY) && (sx >= 0) && (sx < DMAXX)) { gnPieceNum = dPiece[sx][sy]; - nLVal = dLight[sx][sy]; + SetDungeonLightContext(sx, sy, xp, yp); if (gnPieceNum != 0) { pTo = gpBuffer + nBuffWTbl[yp] + xp; nTrans = TransList[dTransVal[sx][sy]] & nTransTable[gnPieceNum]; @@ -2990,7 +3401,7 @@ static void DrawHTLX3 (int sx, int sy, int xp, int yp, int nd, int ev, int halff if (halfflag != 0) { if ((sy >= 0) && (sy < DMAXY) && (sx >= 0) && (sx < DMAXX)) { gnPieceNum = dPiece[sx][sy]; - nLVal = dLight[sx][sy]; + SetDungeonLightContext(sx, sy, xp, yp); if (gnPieceNum != 0) { pTo = gpBuffer + nBuffWTbl[yp] + xp; nTrans = TransList[dTransVal[sx][sy]] & nTransTable[gnPieceNum]; @@ -3032,8 +3443,8 @@ static void SVGADrawView(int StartX, int StartY) ViewBX = 10; ViewBY = 11; - xpos = 64 + ScrollInfo._sxoff; - ypos = 175 + ScrollInfo._syoff; + xpos = 64 + GetScrollDrawX(); + ypos = 175 + GetScrollDrawY(); StartX -= 10; StartY -= 1; width = 10; @@ -3139,8 +3550,8 @@ static void VGADrawView (int StartX, int StartY) ViewBX = 6; ViewBY = 6; - xpos = 64 + ScrollInfo._sxoff; - ypos = 143 + ScrollInfo._syoff; + xpos = 64 + GetScrollDrawX(); + ypos = 143 + GetScrollDrawY(); StartX -= 6; StartY -= 1; width = 6; diff --git a/Scroll_asm.cpp b/Scroll_asm.cpp index e6c107b..7001d84 100644 --- a/Scroll_asm.cpp +++ b/Scroll_asm.cpp @@ -94,6 +94,16 @@ extern "C" { extern BYTE* pDungeonCels; extern BYTE* pSpeedCels; extern BYTE nWTypeTable[]; + extern BYTE gbLevelTileEnhanceActive; + extern BYTE gbLevelTileContrastTable[]; + extern BYTE gbLevelTileLumaTable[]; + extern BYTE gbLevelTileSharpenLightTable[]; + extern BYTE gbLevelTileAoTable[]; + extern BYTE gbTownWarmFlickerActive; + extern BYTE gbTownWarmFlickerTable[][256]; + extern int32_t gnTownTileX; + extern int32_t gnTownTileY; + extern int32_t gnTownFlickerFrame; #else int32_t nLVal; BYTE* glClipY; @@ -109,6 +119,16 @@ extern "C" { BYTE* pDungeonCels; BYTE* pSpeedCels; BYTE nWTypeTable[4096]; + BYTE gbLevelTileEnhanceActive; + BYTE gbLevelTileContrastTable[256]; + BYTE gbLevelTileLumaTable[256]; + BYTE gbLevelTileSharpenLightTable[256]; + BYTE gbLevelTileAoTable[256]; + BYTE gbTownWarmFlickerActive; + BYTE gbTownWarmFlickerTable[4][256]; + int32_t gnTownTileX; + int32_t gnTownTileY; + int32_t gnTownFlickerFrame; #endif #if defined(__cplusplus) && SCROLL_PORT_EXTERN_C_GLOBALS } @@ -377,6 +397,96 @@ static int PixelSelected(const RenderCtx* ctx, int x) return 1; } +static int InTownLightRect(int x, int y, int cx, int cy, int rx, int ry) +{ + return x >= cx - rx && x <= cx + rx && y >= cy - ry && y <= cy + ry; +} + +static int TownWarmLightPhase(void) +{ + int x, y; + + if (!gbTownWarmFlickerActive) { + return -1; + } + + x = gnTownTileX; + y = gnTownTileY; + if (x < 0 || y < 0) { + return -1; + } + + if (InTownLightRect(x, y, 55, 60, 11, 6)) /* tavern main building */ + return gnTownFlickerFrame & 3; + if (InTownLightRect(x, y, 55, 68, 6, 2)) /* tavern outside spill */ + return (gnTownFlickerFrame / 2 + 1) & 3; + if (InTownLightRect(x, y, 62, 63, 9, 7)) /* smith */ + return (gnTownFlickerFrame / 2 + 2) & 3; + if (InTownLightRect(x, y, 55, 79, 9, 7)) /* healer */ + return ((gnTownFlickerFrame * 3) / 2 + 1) & 3; + if (InTownLightRect(x, y, 80, 20, 10, 8)) /* witch */ + return (gnTownFlickerFrame / 3 + 3) & 3; + if (InTownLightRect(x, y, 62, 16, 9, 7)) /* farmhouse */ + return ((gnTownFlickerFrame * 2) / 3 + 1) & 3; + if (InTownLightRect(x, y, 24, 32, 8, 6)) /* wounded townsman house */ + return ((gnTownFlickerFrame * 3) / 4 + 2) & 3; + if (InTownLightRect(x, y, 75, 68, 9, 7)) /* player house */ + return ((gnTownFlickerFrame * 4) / 3 + 3) & 3; + if (InTownLightRect(x, y, 71, 84, 8, 6)) /* Farnham's house */ + return ((gnTownFlickerFrame * 5) / 4 + 1) & 3; + if (InTownLightRect(x, y, 43, 66, 8, 6)) /* Gillian's house */ + return ((gnTownFlickerFrame * 2) / 5 + 2) & 3; + if (InTownLightRect(x, y, 49, 21, 9, 7)) /* town portal house */ + return ((gnTownFlickerFrame * 5) / 3 + 3) & 3; + + return -1; +} + +static BYTE TownWarmFlickerPixel(BYTE pixel) +{ + int phase; + + phase = TownWarmLightPhase(); + if (phase < 0) { + return pixel; + } + + return gbTownWarmFlickerTable[phase][pixel]; +} + +static BYTE LevelTilePixel(const BYTE* src, const BYTE* lightTbl, int i, int count) +{ + BYTE pixel; + int left, right, curr, nearAvg, darkest; + + pixel = gbLevelTileContrastTable[src[i]]; + if (lightTbl != NULL) { + pixel = lightTbl[pixel]; + } + + if (i <= 0 || i + 1 >= count) { + return TownWarmFlickerPixel(pixel); + } + + left = gbLevelTileLumaTable[src[i - 1]]; + right = gbLevelTileLumaTable[src[i + 1]]; + curr = gbLevelTileLumaTable[src[i]]; + nearAvg = (left + right) >> 1; + darkest = (left < right) ? left : right; + + if (nearAvg - curr > 12) { + return TownWarmFlickerPixel(gbLevelTileAoTable[pixel]); + } + if (curr - darkest > 20 && curr < 220) { + return TownWarmFlickerPixel(gbLevelTileAoTable[pixel]); + } + if (curr - nearAvg > 22) { + return TownWarmFlickerPixel(gbLevelTileSharpenLightTable[pixel]); + } + + return TownWarmFlickerPixel(pixel); +} + static void DrawSpan(RenderCtx* ctx, int count, int xStart, PadMode pad, int draw) { int i; @@ -399,10 +509,18 @@ static void DrawSpan(RenderCtx* ctx, int count, int xStart, PadMode pad, int dra if (PixelSelected(ctx, xStart + i)) { switch (ctx->pixelMode) { case PIXELS_LIGHT: - dst[i] = ctx->lightTbl[src[i]]; + if (gbLevelTileEnhanceActive) { + dst[i] = LevelTilePixel(src, ctx->lightTbl, i, count); + } else { + dst[i] = ctx->lightTbl[src[i]]; + } break; case PIXELS_PRETRANS: - dst[i] = src[i]; + if (gbLevelTileEnhanceActive) { + dst[i] = LevelTilePixel(src, NULL, i, count); + } else { + dst[i] = src[i]; + } break; case PIXELS_BLACK: dst[i] = 0; diff --git a/THEMES.CPP b/THEMES.CPP index 61cffb4..fa0d167 100644 --- a/THEMES.CPP +++ b/THEMES.CPP @@ -410,6 +410,207 @@ BOOL CheckThemeRoom(int tv) return(TRUE); } +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static int ThemeRoomExitCount(int tv) +{ + int i, j; + int exits; + + exits = 0; + for (j = 1; j < DMAXY - 1; j++) { + for (i = 1; i < DMAXX - 1; i++) { + if ((dTransVal[i][j] == tv) && (!nSolidTable[dPiece[i][j]])) { + if ((dTransVal[i - 1][j] != tv) && (!nSolidTable[dPiece[i - 1][j]])) exits++; + if ((dTransVal[i + 1][j] != tv) && (!nSolidTable[dPiece[i + 1][j]])) exits++; + if ((dTransVal[i][j - 1] != tv) && (!nSolidTable[dPiece[i][j - 1]])) exits++; + if ((dTransVal[i][j + 1] != tv) && (!nSolidTable[dPiece[i][j + 1]])) exits++; + } + } + } + + return exits; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static BOOL IsDeadEndThemeRoom(int tv) +{ + return ThemeRoomExitCount(tv) <= 6; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static int ThemeRoomArea(int tv) +{ + int i, j; + int area; + + area = 0; + for (j = 0; j < DMAXY; j++) { + for (i = 0; i < DMAXX; i++) { + if ((dTransVal[i][j] == tv) && (!nSolidTable[dPiece[i][j]])) + area++; + } + } + + return area; +} + +#define CATROOM_DEADEND 0x01 +#define CATROOM_SMALL 0x02 +#define CATROOM_LARGE 0x04 + +typedef struct { + int minLevel; + int maxLevel; + int roomFlags; + const int *themeList; + int themeListLen; +} CathedralRoomPick; + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static BOOL CathedralRoomShapeFits(int tv, int roomFlags) +{ + int area; + + if ((roomFlags & CATROOM_DEADEND) && !IsDeadEndThemeRoom(tv)) + return FALSE; + + area = ThemeRoomArea(tv); + if ((roomFlags & CATROOM_SMALL) && area > 36) + return FALSE; + if ((roomFlags & CATROOM_LARGE) && area < 49) + return FALSE; + + return TRUE; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static BOOL PickThemeFromList(int i, const int *themeList, int themeListLen, int *themeType) +{ + int start, n, t; + + if (themeListLen <= 0) return FALSE; + + start = random(0, themeListLen); + for (n = 0; n < themeListLen; n++) { + t = themeList[(start + n) % themeListLen]; + if (SpecialThemeFit(i, t)) { + *themeType = t; + return TRUE; + } + } + + return FALSE; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static BOOL PickCathedralArchetypeTheme(int i, int depth, int *themeType) +{ + static const int candlelitEntryChapel[] = { + THEME_SHRINE, + THEME_LIBRARY, + }; + static const int collapsedPrayerNook[] = { + THEME_BARREL, + THEME_SHRINE, + THEME_SKELRM, + }; + static const int skeletonAmbushCryptlet[] = { + THEME_SKELRM, + THEME_MONSTPIT, + }; + static const int desecratedShrineRoom[] = { + THEME_GOATSHRINE, + THEME_BLOODFTN, + THEME_MURKYFTN, + }; + static const int abandonedStudy[] = { + THEME_LIBRARY, + THEME_SHRINE, + }; + static const int guardedSupplyRoom[] = { + THEME_BARREL, + THEME_TREASURE, + THEME_MONSTPIT, + }; + static const int processionHall[] = { + THEME_SHRINE, + THEME_LIBRARY, + THEME_BARREL, + }; + static const int sealedTreasureCloset[] = { + THEME_TREASURE, + }; + static const int bloodTrailRoom[] = { + THEME_BLOODFTN, + THEME_DECAP, + THEME_TORTURE, + }; + static const int falseSanctuary[] = { + THEME_SHRINE, + THEME_GOATSHRINE, + THEME_MONSTPIT, + }; + + static const CathedralRoomPick rooms[] = { + { 1, 2, CATROOM_LARGE, candlelitEntryChapel, sizeof(candlelitEntryChapel) / sizeof(candlelitEntryChapel[0]) }, + { 1, 3, CATROOM_DEADEND | CATROOM_SMALL, collapsedPrayerNook, sizeof(collapsedPrayerNook) / sizeof(collapsedPrayerNook[0]) }, + { 1, 4, 0, skeletonAmbushCryptlet, sizeof(skeletonAmbushCryptlet) / sizeof(skeletonAmbushCryptlet[0]) }, + { 2, 4, CATROOM_LARGE, desecratedShrineRoom, sizeof(desecratedShrineRoom) / sizeof(desecratedShrineRoom[0]) }, + { 1, 3, 0, abandonedStudy, sizeof(abandonedStudy) / sizeof(abandonedStudy[0]) }, + { 1, 2, CATROOM_DEADEND | CATROOM_SMALL, guardedSupplyRoom, sizeof(guardedSupplyRoom) / sizeof(guardedSupplyRoom[0]) }, + { 1, 4, CATROOM_LARGE, processionHall, sizeof(processionHall) / sizeof(processionHall[0]) }, + { 1, 4, CATROOM_DEADEND | CATROOM_SMALL, sealedTreasureCloset, sizeof(sealedTreasureCloset) / sizeof(sealedTreasureCloset[0]) }, + { 3, 4, 0, bloodTrailRoom, sizeof(bloodTrailRoom) / sizeof(bloodTrailRoom[0]) }, + { 2, 4, 0, falseSanctuary, sizeof(falseSanctuary) / sizeof(falseSanctuary[0]) }, + }; + int start, n, roomCount; + const CathedralRoomPick *room; + + roomCount = sizeof(rooms) / sizeof(rooms[0]); + start = random(0, roomCount); + + for (n = 0; n < roomCount; n++) { + room = &rooms[(start + n) % roomCount]; + if (depth < room->minLevel || depth > room->maxLevel) + continue; + if (!CathedralRoomShapeFits(theme[i].ttval, room->roomFlags)) + continue; + if (PickThemeFromList(i, room->themeList, room->themeListLen, themeType)) + return TRUE; + } + + return FALSE; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static int PickL1Theme(int i) +{ + int depth; + int tries; + int t; + + depth = currlevel; + if (depth < 1) depth = 1; + if (depth > 4) depth = 4; + + if (PickCathedralArchetypeTheme(i, depth, &t)) + return t; + + for (tries = 0; tries < 64; tries++) { + t = random(0, TOTAL_THEMES); + if (SpecialThemeFit(i, t)) return t; + } + + return THEME_BARREL; +} + /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ @@ -438,8 +639,7 @@ void InitThemes() for (i = 0; (i < 256) && (numthemes < MAXTHEMES); i++) { if (CheckThemeRoom(i)) { theme[numthemes].ttval = i; - t = ThemeGood[random(0, THEME_NUMGOOD)]; // Normal - while (!SpecialThemeFit(numthemes, t)) t = random(0, TOTAL_THEMES); + t = PickL1Theme(numthemes); theme[numthemes].ttype = t; numthemes++; } diff --git a/TOWN.CPP b/TOWN.CPP index 461bca0..670acb6 100644 --- a/TOWN.CPP +++ b/TOWN.CPP @@ -44,24 +44,233 @@ #include "multi.h" #define T_POUTC 165 +#define TOWN_PLAYER_LIGHT 1 // #define TESTINGCRYPT // JKE set this to keep the crypt open #if RLE_DRAW void DrawUnit (long xp,long yp,BYTE *pCelBuff,long nCel,long nCelW,long ostart,long oend); +void DrawLitUnit (long xp,long yp,BYTE *pCelBuff,long nCel,long nCelW,long ostart,long oend); +void DrawLitUnitLerpOverlay(long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend, int density); void DrawUnitClipped (long xp,long yp,BYTE *pCelBuff,long nCel,long nCelW,long ostart,long oend); +void DrawLitUnitClipped (long xp,long yp,BYTE *pCelBuff,long nCel,long nCelW,long ostart,long oend); +void DrawLitUnitLerpOverlayClipped(long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend, int density); void DrawUnitOutline(byte ocolor, long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend); void DrawUnitOutlineClipped(byte ocolor, long xp, long yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend); #endif +extern "C" { + extern int gnTownTileX; + extern int gnTownTileY; + extern int gnTownFlickerFrame; +} +extern int gnRenderFrameInterp; +extern int PlrWalkLenTbl[NUM_CLASSES]; + static void T_DrawHTLXsub (BYTE *pTo, int sx, int sy, int xp, int yp, BOOL chflag); static void T_DrawHTLXsub2 (BYTE *pTo, int sx, int sy, int sv, int sv2, int xp, int yp, BOOL chflag); static void T_DrawHTLXsub3 (BYTE *pTo, int sx, int sy, int ev, int ev2, int xp, int yp, BOOL chflag); +static void T_DrawPlayerTownUnit(PlayerStruct *pPlayer, int xp, int yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend, BOOL clipped); +void ApplyWorldGoldShimmer(ItemStruct *pItem, int itemIndex, int x, int y, int ostart, int oend); void plrmsg_draw(); /*-----------------------------------------------------------------------** **-----------------------------------------------------------------------*/ +static void T_SetTownTile(int sx, int sy) +{ + gnTownTileX = sx; + gnTownTileY = sy; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +static int T_VisualHalfStep(long velocity) +{ + int interp; + __int64 step; + + interp = gnRenderFrameInterp; + if (interp <= 0 || velocity == 0) + return 0; + if (interp > 256) + interp = 256; + + step = velocity; + if (step < 0) + return -(int)(((-step) * interp) >> 16); + + return (int)((step * interp) >> 16); +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +static BOOL T_PlayerUsesVisualLerp(PlayerStruct *pPlayer) +{ + return pPlayer->_pmode == PM_WALK + || pPlayer->_pmode == PM_WALK2 + || pPlayer->_pmode == PM_WALK3; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ +static BOOL T_PlayerHasVisualStep(PlayerStruct *pPlayer) +{ + int walkLen; + + walkLen = 8; + if (currlevel != 0) + walkLen = PlrWalkLenTbl[pPlayer->_pClass]; + + return pPlayer->_pVar8 < walkLen; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +static int T_GetPlayerDrawX(PlayerStruct *pPlayer, int xp) +{ + xp += pPlayer->_pxoff; + if (T_PlayerUsesVisualLerp(pPlayer) && T_PlayerHasVisualStep(pPlayer)) + xp += T_VisualHalfStep(pPlayer->_pxvel); + + return xp; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +static int T_GetPlayerDrawY(PlayerStruct *pPlayer, int yp) +{ + yp += pPlayer->_pyoff; + if (T_PlayerUsesVisualLerp(pPlayer) && T_PlayerHasVisualStep(pPlayer)) + yp += T_VisualHalfStep(pPlayer->_pyvel); + + return yp; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +static int T_GetScrollDrawX() +{ + int sxoff; + PlayerStruct *pPlayer; + + sxoff = ScrollInfo._sxoff; + if (ScrollInfo._sdir == SCRL_NONE) + return sxoff; + + pPlayer = &plr[myplr]; + if (T_PlayerUsesVisualLerp(pPlayer) && T_PlayerHasVisualStep(pPlayer)) + sxoff -= T_VisualHalfStep(pPlayer->_pxvel); + + return sxoff; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +static int T_GetScrollDrawY() +{ + int syoff; + PlayerStruct *pPlayer; + + syoff = ScrollInfo._syoff; + if (ScrollInfo._sdir == SCRL_NONE) + return syoff; + + pPlayer = &plr[myplr]; + if (T_PlayerUsesVisualLerp(pPlayer) && T_PlayerHasVisualStep(pPlayer)) + syoff -= T_VisualHalfStep(pPlayer->_pyvel); + + return syoff; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +static int T_GetVisualLerpDensity(int animCnt, int animDelay) +{ + int interp; + int progress; + int density; + + if (animDelay <= 1) + return 0; + + interp = gnRenderFrameInterp; + if (interp < 0) + interp = 0; + if (interp > 256) + interp = 256; + + progress = animCnt * 256 + interp; + density = (progress * 4) / (animDelay * 256); + if (density < 1) + return 0; + if (density > 3) + density = 3; + + return density; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +static int T_GetPlayerLerpFrame(PlayerStruct *pPlayer, int *density) +{ + int frame; + + *density = T_GetVisualLerpDensity(pPlayer->_pAnimCnt, pPlayer->_pAnimDelay); + if (*density == 0) + return 0; + + frame = pPlayer->_pAnimFrame + 1; + if (frame > pPlayer->_pAnimLen) + return 0; + + return frame; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + +static void T_DrawPlayerTownUnit(PlayerStruct *pPlayer, int xp, int yp, BYTE *pCelBuff, long nCel, long nCelW, long ostart, long oend, BOOL clipped) +{ + long oldnLVal; + int density, nextFrame; + + oldnLVal = nLVal; + nLVal = TOWN_PLAYER_LIGHT; + +#if RLE_DRAW + if (clipped) + DrawLitUnitClipped(xp, yp, pCelBuff, nCel, nCelW, ostart, oend); + else + DrawLitUnit(xp, yp, pCelBuff, nCel, nCelW, ostart, oend); + nextFrame = T_GetPlayerLerpFrame(pPlayer, &density); + if (nextFrame) { + if (clipped) + DrawLitUnitLerpOverlayClipped(xp, yp, pCelBuff, nextFrame, nCelW, ostart, oend, density); + else + DrawLitUnitLerpOverlay(xp, yp, pCelBuff, nextFrame, nCelW, ostart, oend, density); + } +#else + if (clipped) + CDrawSlabCelL(xp, yp, pCelBuff, nCel, nCelW, ostart, oend); + else + DrawSlabCelL(xp, yp, pCelBuff, nCel, nCelW, ostart, oend); +#endif + + nLVal = oldnLVal; +} + +/*-----------------------------------------------------------------------** +**-----------------------------------------------------------------------*/ + void TDrawBlankMini(BYTE *pDecodeTo) { app_assert(gpBuffer); @@ -289,6 +498,7 @@ void T_DrawEFlag1(BYTE *pTo2, int sx, int sy, int xp, int yp) pTo = pTo2; mt = &dMT2[CalcRot(sx,sy)].mt[0]; + T_SetTownTile(sx, sy); for(t = 0; t < 12; t += 2) { if (gdwPNum = mt[t]) DrawMTileClipBottom (pTo); @@ -315,6 +525,7 @@ static void T_DrawHTLXsub (BYTE *pTo, int sx, int sy, int xp, int yp, BOOL chfla pxp = xp - item[bv]._iAnimWidth2; if (bv == cursitem) COutlineSlabCel(181, pxp, yp, item[bv]._iAnimData, item[bv]._iAnimFrame, item[bv]._iAnimWidth, 0, 8); CDrawSlabCel(pxp, yp, item[bv]._iAnimData, item[bv]._iAnimFrame, item[bv]._iAnimWidth, 0, 8); + ApplyWorldGoldShimmer(&item[bv], bv, pxp, yp, 0, 8); } if ((dFlags[sx][sy] & BFLAG_MONSTLR) != 0) { mi = -(dMonster[sx][sy-1] + 1); @@ -332,16 +543,15 @@ static void T_DrawHTLXsub (BYTE *pTo, int sx, int sy, int xp, int yp, BOOL chfla } if ((dFlags[sx][sy] & BFLAG_PLRLR) != 0) { bv = -(dPlayer[sx][sy-1] + 1); - pxp = plr[bv]._pxoff + xp - plr[bv]._pAnimWidth2; - pyp = plr[bv]._pyoff + yp; + pxp = T_GetPlayerDrawX(&plr[bv], xp) - plr[bv]._pAnimWidth2; + pyp = T_GetPlayerDrawY(&plr[bv], yp); #if RLE_DRAW if (bv == cursplr) DrawUnitOutlineClipped(T_POUTC, pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, 0, 8); - DrawUnitClipped(pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, 0, 8); #else if (bv == cursplr) COutlineSlabCel(T_POUTC, pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, 0, 8); - CDrawSlabCel(pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, 0, 8); #endif + T_DrawPlayerTownUnit(&plr[bv], pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, 0, 8, TRUE); if (chflag) { @@ -353,16 +563,15 @@ static void T_DrawHTLXsub (BYTE *pTo, int sx, int sy, int xp, int yp, BOOL chfla DrawDeadPlr(sx, sy, xp, yp, 0, 8, TRUE); if (dPlayer[sx][sy] > 0) { bv = dPlayer[sx][sy] - 1; - pxp = plr[bv]._pxoff + xp - plr[bv]._pAnimWidth2; - pyp = plr[bv]._pyoff + yp; + pxp = T_GetPlayerDrawX(&plr[bv], xp) - plr[bv]._pAnimWidth2; + pyp = T_GetPlayerDrawY(&plr[bv], yp); #if RLE_DRAW if (bv == cursplr) DrawUnitOutlineClipped(T_POUTC, pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, 0, 8); - DrawUnitClipped(pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, 0, 8); #else if (bv == cursplr) COutlineSlabCel(T_POUTC, pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, 0, 8); - CDrawSlabCel(pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, 0, 8); #endif + T_DrawPlayerTownUnit(&plr[bv], pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, 0, 8, TRUE); if (chflag) { @@ -390,6 +599,7 @@ void T_DrawHTileLineX (int sx, int sy, int xp, int yp, int nd, int halfflag) if (gdwPNum = dPiece[sx][sy]) { pTo = gpBuffer + nBuffWTbl[yp] + xp + 32; mt = &dMT2[CalcRot(sx,sy)].mt[0]; + T_SetTownTile(sx, sy); for(t = 1; t < 17; t += 2) { @@ -419,6 +629,7 @@ void T_DrawHTileLineX (int sx, int sy, int xp, int yp, int nd, int halfflag) if (gdwPNum != 0) { pTo = gpBuffer + nBuffWTbl[yp] + xp; mt = &dMT2[CalcRot(sx,sy)].mt[0]; + T_SetTownTile(sx, sy); for(t = 0; t < 16; t+= 2) { @@ -447,6 +658,7 @@ void T_DrawHTileLineX (int sx, int sy, int xp, int yp, int nd, int halfflag) if (gdwPNum != 0) { pTo = gpBuffer + nBuffWTbl[yp] + xp; mt = &dMT2[CalcRot(sx,sy)].mt[0]; + T_SetTownTile(sx, sy); for(t = 0; t < 16; t+= 2) { @@ -480,6 +692,7 @@ void T_DrawEFlag2(BYTE *pTo2, int sx, int sy, int sv, int sv2, int xp, int yp) else pTo = pTo2 + (NBUFFWSL5 * sv); mt = &dMT2[CalcRot(sx,sy)].mt[0]; + T_SetTownTile(sx, sy); for(t = 0; t < 6; t++) { @@ -509,6 +722,7 @@ static void T_DrawHTLXsub2 (BYTE *pTo, int sx, int sy, int sv, int sv2, int xp, pxp = xp - item[bv]._iAnimWidth2; if (bv == cursitem) COutlineSlabCel(181, pxp, yp, item[bv]._iAnimData, item[bv]._iAnimFrame, item[bv]._iAnimWidth, sv2, 8); CDrawSlabCel(pxp, yp, item[bv]._iAnimData, item[bv]._iAnimFrame, item[bv]._iAnimWidth, sv2, 8); + ApplyWorldGoldShimmer(&item[bv], bv, pxp, yp, sv2, 8); } if ((dFlags[sx][sy] & BFLAG_MONSTLR) != 0) { mi = -(dMonster[sx][sy-1] + 1); @@ -526,16 +740,15 @@ static void T_DrawHTLXsub2 (BYTE *pTo, int sx, int sy, int sv, int sv2, int xp, } if ((dFlags[sx][sy] & BFLAG_PLRLR) != 0) { bv = -(dPlayer[sx][sy-1] + 1); - pxp = plr[bv]._pxoff + xp - plr[bv]._pAnimWidth2; - pyp = plr[bv]._pyoff + yp; + pxp = T_GetPlayerDrawX(&plr[bv], xp) - plr[bv]._pAnimWidth2; + pyp = T_GetPlayerDrawY(&plr[bv], yp); #if RLE_DRAW if (bv == cursplr) DrawUnitOutlineClipped(T_POUTC, pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, sv2, 8); - DrawUnitClipped(pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, sv2, 8); #else if (bv == cursplr) COutlineSlabCel(T_POUTC, pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, sv2, 8); - CDrawSlabCel(pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, sv2, 8); #endif + T_DrawPlayerTownUnit(&plr[bv], pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, sv2, 8, TRUE); if (chflag) { @@ -547,16 +760,15 @@ static void T_DrawHTLXsub2 (BYTE *pTo, int sx, int sy, int sv, int sv2, int xp, DrawDeadPlr(sx, sy, xp, yp, sv2, 8, TRUE); if (dPlayer[sx][sy] > 0) { bv = dPlayer[sx][sy] - 1; - pxp = plr[bv]._pxoff + xp - plr[bv]._pAnimWidth2; - pyp = plr[bv]._pyoff + yp; + pxp = T_GetPlayerDrawX(&plr[bv], xp) - plr[bv]._pAnimWidth2; + pyp = T_GetPlayerDrawY(&plr[bv], yp); #if RLE_DRAW if (bv == cursplr) DrawUnitOutlineClipped(T_POUTC, pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, sv2, 8); - DrawUnitClipped(pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, sv2, 8); #else if (bv == cursplr) COutlineSlabCel(T_POUTC, pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, sv2, 8); - CDrawSlabCel(pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, sv2, 8); #endif + T_DrawPlayerTownUnit(&plr[bv], pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, sv2, 8, TRUE); if (chflag) { @@ -586,6 +798,7 @@ void T_DrawHTLX2 (int sx, int sy, int xp, int yp, int nd, int sv, int halfflag) if (gdwPNum = dPiece[sx][sy]) { pTo = gpBuffer + nBuffWTbl[yp] + xp - NBUFFWSL5 + 32; mt = &dMT2[CalcRot(sx,sy)].mt[0]; + T_SetTownTile(sx, sy); for(t = 0; t < 7; t++) { @@ -617,6 +830,7 @@ void T_DrawHTLX2 (int sx, int sy, int xp, int yp, int nd, int sv, int halfflag) if (gdwPNum != 0) { pTo = gpBuffer + nBuffWTbl[yp] + xp - NBUFFWSL5; mt = &dMT2[CalcRot(sx,sy)].mt[0]; + T_SetTownTile(sx, sy); for(t = 0; t < 7; t++) { if (sv <= t) { @@ -649,6 +863,7 @@ void T_DrawHTLX2 (int sx, int sy, int xp, int yp, int nd, int sv, int halfflag) if (gdwPNum != 0) { pTo = gpBuffer + nBuffWTbl[yp] + xp - NBUFFWSL5; mt = &dMT2[CalcRot(sx,sy)].mt[0]; + T_SetTownTile(sx, sy); for(t = 0; t < 7; t++) { @@ -683,6 +898,7 @@ void T_DrawEFlag3(BYTE *pTo2, int sx, int sy, int ev, int ev2, int xp, int yp) pTo = pTo2; mt = &dMT2[CalcRot(sx,sy)].mt[0]; + T_SetTownTile(sx, sy); for(t = 0; t < 7; t++) { @@ -710,6 +926,7 @@ static void T_DrawHTLXsub3 (BYTE *pTo, int sx, int sy, int ev, int ev2, int xp, if (bv == cursitem) OutlineSlabCel(181, pxp, yp, item[bv]._iAnimData, item[bv]._iAnimFrame, item[bv]._iAnimWidth, 0, ev2); app_assert(item[bv]._iAnimData); DrawSlabCel(pxp, yp, item[bv]._iAnimData, item[bv]._iAnimFrame, item[bv]._iAnimWidth, 0, ev2); + ApplyWorldGoldShimmer(&item[bv], bv, pxp, yp, 0, ev2); } if ((dFlags[sx][sy] & BFLAG_MONSTLR) != 0) { mi = -(dMonster[sx][sy-1] + 1); @@ -729,18 +946,17 @@ static void T_DrawHTLXsub3 (BYTE *pTo, int sx, int sy, int ev, int ev2, int xp, } if ((dFlags[sx][sy] & BFLAG_PLRLR) != 0) { bv = -(dPlayer[sx][sy-1] + 1); - pxp = plr[bv]._pxoff + xp - plr[bv]._pAnimWidth2; - pyp = plr[bv]._pyoff + yp; + pxp = T_GetPlayerDrawX(&plr[bv], xp) - plr[bv]._pAnimWidth2; + pyp = T_GetPlayerDrawY(&plr[bv], yp); #if RLE_DRAW if (bv == cursplr) DrawUnitOutline(T_POUTC, pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, 0, ev2); app_assert(plr[bv]._pAnimData); - DrawUnit(pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, 0, ev2); #else if (bv == cursplr) OutlineSlabCel(T_POUTC, pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, 0, ev2); app_assert(plr[bv]._pAnimData); - DrawSlabCel(pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, 0, ev2); #endif + T_DrawPlayerTownUnit(&plr[bv], pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, 0, ev2, FALSE); if (chflag) { @@ -752,18 +968,17 @@ static void T_DrawHTLXsub3 (BYTE *pTo, int sx, int sy, int ev, int ev2, int xp, DrawDeadPlr(sx, sy, xp, yp, 0, ev2, FALSE); if (dPlayer[sx][sy] > 0) { bv = dPlayer[sx][sy] - 1; - pxp = plr[bv]._pxoff + xp - plr[bv]._pAnimWidth2; - pyp = plr[bv]._pyoff + yp; + pxp = T_GetPlayerDrawX(&plr[bv], xp) - plr[bv]._pAnimWidth2; + pyp = T_GetPlayerDrawY(&plr[bv], yp); #if RLE_DRAW if (bv == cursplr) DrawUnitOutline(T_POUTC, pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, 0, ev2); app_assert(plr[bv]._pAnimData); - DrawUnit(pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, 0, ev2); #else if (bv == cursplr) OutlineSlabCel(T_POUTC, pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, 0, ev2); app_assert(plr[bv]._pAnimData); - DrawSlabCel(pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, 0, ev2); #endif + T_DrawPlayerTownUnit(&plr[bv], pxp, pyp, plr[bv]._pAnimData, plr[bv]._pAnimFrame, plr[bv]._pAnimWidth, 0, ev2, FALSE); if (chflag) { @@ -794,6 +1009,7 @@ void T_DrawHTLX3 (int sx, int sy, int xp, int yp, int nd, int ev, int halfflag) if (gdwPNum = dPiece[sx][sy]) { pTo = gpBuffer + nBuffWTbl[yp] + xp + 32; mt = &dMT2[CalcRot(sx,sy)].mt[0]; + T_SetTownTile(sx, sy); for(t = 0; t < 7; t++) { @@ -823,6 +1039,7 @@ void T_DrawHTLX3 (int sx, int sy, int xp, int yp, int nd, int ev, int halfflag) if (gdwPNum != 0) { pTo = gpBuffer + nBuffWTbl[yp] + xp; mt = &dMT2[CalcRot(sx,sy)].mt[0]; + T_SetTownTile(sx, sy); for(t = 0; t < 7; t++) { if (ev >= t) { @@ -853,6 +1070,7 @@ void T_DrawHTLX3 (int sx, int sy, int xp, int yp, int nd, int ev, int halfflag) if (gdwPNum != 0) { pTo = gpBuffer + nBuffWTbl[yp] + xp; mt = &dMT2[CalcRot(sx,sy)].mt[0]; + T_SetTownTile(sx, sy); for(t = 0; t < 7; t++) { @@ -888,8 +1106,8 @@ void T_SVGADrawView (int StartX, int StartY) ViewBX = 10; ViewBY = 11; - xpos = 64 + ScrollInfo._sxoff; - ypos = 175 + ScrollInfo._syoff; + xpos = 64 + T_GetScrollDrawX(); + ypos = 175 + T_GetScrollDrawY(); StartX -= 10; StartY -= 1; width = 10; @@ -1007,8 +1225,8 @@ void T_VGADrawView (int StartX, int StartY) ViewBX = 6; ViewBY = 6; - xpos = 64 + ScrollInfo._sxoff; - ypos = 143 + ScrollInfo._syoff; + xpos = 64 + T_GetScrollDrawX(); + ypos = 143 + T_GetScrollDrawY(); StartX -= 6; StartY -= 1; width = 6; @@ -1199,6 +1417,7 @@ _YLp: mov ecx,160 // walls, so we set them here once for the whole screen nLVal = 0; nTrans = 0; + gnTownFlickerFrame = GetTickCount() / 120; if (svgamode) T_SVGADrawView (StartX, StartY); else T_VGADrawView (StartX, StartY);