raze/source/exhumed/src/view.cpp

545 lines
13 KiB
C++
Raw Normal View History

#include "compat.h"
#include "keyboard.h"
#include "control.h"
#include "engine.h"
#include "config.h"
#include "names.h"
#include "view.h"
#include "status.h"
#include "exhumed.h"
#include "player.h"
#include "snake.h"
#include "gun.h"
#include "light.h"
#include "init.h"
#include "menu.h"
#include "keyboard.h"
#include "cd.h"
#include "cdaudio.h"
#include "typedefs.h"
#include "move.h"
#include "sound.h"
#include "engine.h"
#include "trigdat.h"
#include "runlist.h"
#include <string.h>
short bSubTitles = kTrue;
int zbob;
2019-10-29 17:35:22 +00:00
fix16_t nDestVertPan[kMaxPlayers] = { 0 };
short dVertPan[kMaxPlayers];
2019-10-29 17:35:22 +00:00
fix16_t nVertPan[kMaxPlayers];
int nCamerax;
int nCameray;
int nCameraz;
short bTouchFloor;
short nQuake[kMaxPlayers] = { 0 };
short nChunkTotal = 0;
2019-10-29 17:35:22 +00:00
fix16_t nCameraa;
fix16_t nCamerapan;
short nViewTop;
short bClip = kFalse;
short nViewBottom;
short nViewRight;
short besttarget;
short nViewLeft;
short bCamera = kFalse;
short nViewy;
int viewz;
short enemy;
short nEnemyPal = 0;
void InitView()
{
screensize = 0;
#ifdef USE_OPENGL
polymostcenterhoriz = 92;
#endif
}
// NOTE - not to be confused with Ken's analyzesprites()
static void analyzesprites()
{
short nPlayerSprite = PlayerList[nLocalPlayer].nSprite;
int var_38 = 20;
int var_2C = 30000;
spritetype *pPlayerSprite = &sprite[nPlayerSprite];
besttarget = -1;
int x = pPlayerSprite->x;
int y = pPlayerSprite->y;
int z = pPlayerSprite->z - (GetSpriteHeight(nPlayerSprite) / 2);
short nSector = pPlayerSprite->sectnum;
int nAngle = (2048 - pPlayerSprite->ang) & kAngleMask;
int nTSprite;
tspritetype *pTSprite;
// int var_20 = var_24;
for (nTSprite = spritesortcnt-1, pTSprite = &tsprite[nTSprite]; nTSprite >= 0; nTSprite--, pTSprite--)
{
int nSprite = pTSprite->owner;
spritetype *pSprite = &sprite[nSprite];
if (pTSprite->sectnum >= 0)
{
sectortype *pSector = &sector[pTSprite->sectnum];
int nSectShade = (pSector->ceilingstat & 1) ? pSector->ceilingshade : pSector->floorshade;
int nShade = pTSprite->shade + nSectShade + 6;
pTSprite->shade = clamp(nShade, -128, 127);
}
pTSprite->pal = RemapPLU(pTSprite->pal);
if (pSprite->statnum > 0)
{
runlist_SignalRun(pSprite->lotag - 1, nTSprite | 0x90000);
if ((pSprite->statnum < 150) && (pSprite->cstat & 0x101) && (nSprite != nPlayerSprite))
{
int xval = pSprite->x - x;
int yval = pSprite->y - y;
int vcos = Cos(nAngle);
int vsin = Sin(nAngle);
int edx = ((vcos * yval) + (xval * vsin)) >> 14;
int ebx = klabs(((vcos * xval) - (yval * vsin)) >> 14);
if (!ebx)
continue;
edx = (klabs(edx) * 32) / ebx;
if (ebx < 1000 && ebx < var_2C && edx < 10)
{
besttarget = nSprite;
var_38 = edx;
var_2C = ebx;
}
else if (ebx < 30000)
{
int t = var_38 - edx;
if (t > 3 || (ebx < var_2C && klabs(t) < 5))
{
var_38 = edx;
var_2C = ebx;
besttarget = nSprite;
}
}
}
}
}
if (besttarget != -1)
{
spritetype *pTarget = &sprite[besttarget];
nCreepyTimer = 450;
if (!cansee(x, y, z, nSector, pTarget->x, pTarget->y, pTarget->z - GetSpriteHeight(besttarget), pTarget->sectnum))
{
besttarget = -1;
}
}
}
void ResetView()
{
videoSetGameMode(gSetup.fullscreen, gSetup.xdim, gSetup.ydim, gSetup.bpp, 0);
DoOverscanSet(overscanindex);
EraseScreen(overscanindex);
memcpy(curpalettefaded, curpalette, sizeof(curpalette));
videoUpdatePalette(0, 256);
2019-10-12 22:27:12 +00:00
#ifdef USE_OPENGL
videoTintBlood(0, 0, 0);
#endif
LoadStatus();
}
void SetView1()
{
}
void FlushMessageLine()
{
int tileX = tilesiz[nBackgroundPic].x;
int nTileOffset = 0;
int xPos = 0;
while (xPos < xdim)
{
overwritesprite(xPos, 0, nBackgroundPic + nTileOffset, -32, 0, kPalNormal);
nTileOffset = nTileOffset == 0;
xPos += tileX;
}
}
void RefreshBackground()
{
if (screensize <= 0)
return;
int nTileOffset = 0;
int tileX = tilesiz[nBackgroundPic].x;
int tileY = tilesiz[nBackgroundPic].y;
videoSetViewableArea(0, 0, xdim - 1, ydim - 1);
MaskStatus();
for (int y = 0; y < nViewTop; y += tileY)
{
nTileOffset = (y/tileY)&1;
for (int x = 0; x < xdim; x += tileX)
{
rotatesprite(x<<16, y<<16, 65536L, 0, nBackgroundPic + nTileOffset, -32, kPalNormal, 8 + 16 + 64, 0, 0, xdim-1, nViewTop-1);
nTileOffset ^= 1;
}
}
for (int y = (nViewTop/tileY)*tileY; y <= nViewBottom; y += tileY)
{
nTileOffset = (y/tileY)&1;
for (int x = 0; x < nViewLeft; x += tileX)
{
rotatesprite(x<<16, y<<16, 65536L, 0, nBackgroundPic + nTileOffset, -32, kPalNormal, 8 + 16 + 64, 0, nViewTop, nViewLeft-1, nViewBottom);
nTileOffset ^= 1;
}
}
for (int y = (nViewTop/tileY)*tileY; y <= nViewBottom; y += tileY)
{
nTileOffset = ((y/tileY)^((nViewRight+1)/tileX))&1;
for (int x = ((nViewRight+1)/tileX)*tileX; x < xdim; x += tileX)
{
rotatesprite(x<<16, y<<16, 65536L, 0, nBackgroundPic + nTileOffset, -32, kPalNormal, 8 + 16 + 64, nViewRight+1, nViewTop, xdim-1, nViewBottom);
nTileOffset ^= 1;
}
}
for (int y = ((nViewBottom+1)/tileY)*tileY; y < ydim; y += tileY)
{
nTileOffset = (y/tileY)&1;
for (int x = 0; x < xdim; x += tileX)
{
rotatesprite(x<<16, y<<16, 65536L, 0, nBackgroundPic + nTileOffset, -32, kPalNormal, 8 + 16 + 64, 0, nViewBottom+1, xdim-1, ydim-1);
nTileOffset ^= 1;
}
}
videoSetViewableArea(nViewLeft, nViewTop, nViewRight, nViewBottom);
}
void MySetView(int x1, int y1, int x2, int y2)
{
if (!bFullScreen) {
MaskStatus();
}
nViewLeft = x1;
nViewTop = y1;
nViewRight = x2;
nViewBottom = y2;
videoSetViewableArea(x1, y1, x2, y2);
nViewy = y1;
}
// unused function
void TestLava()
{
}
void DrawView()
{
int playerX;
int playerY;
int playerZ;
short nSector;
2019-10-29 17:35:22 +00:00
fix16_t nAngle;
fix16_t pan;
2019-08-31 16:05:11 +00:00
#if 0
if (bgpages <= 0)
{
if (textpages > 0)
{
textpages--;
FlushMessageLine();
}
}
else
{
RefreshBackground();
bgpages--;
}
2019-08-31 16:05:11 +00:00
#else
FlushMessageLine();
RefreshBackground();
#endif
if (!bFullScreen) {
MaskStatus();
}
zbob = Sin(2 * bobangle) >> 3;
int nPlayerSprite = PlayerList[nLocalPlayer].nSprite;
if (nSnakeCam >= 0)
{
int nSprite = SnakeList[nSnakeCam].nSprites[0];
playerX = sprite[nSprite].x;
playerY = sprite[nSprite].y;
playerZ = sprite[nSprite].z;
nSector = sprite[nSprite].sectnum;
2019-10-29 17:35:22 +00:00
nAngle = fix16_from_int(sprite[nSprite].ang);
SetGreenPal();
UnMaskStatus();
enemy = SnakeList[nSnakeCam].nEnemy;
if (enemy <= -1 || totalmoves & 1)
{
nEnemyPal = -1;
}
else
{
nEnemyPal = sprite[enemy].pal;
sprite[enemy].pal = 5;
}
}
else
{
playerX = sprite[nPlayerSprite].x;
playerY = sprite[nPlayerSprite].y;
playerZ = sprite[nPlayerSprite].z + eyelevel[nLocalPlayer];
nSector = nPlayerViewSect[nLocalPlayer];
2019-10-29 17:35:22 +00:00
nAngle = PlayerList[nLocalPlayer].q16angle;
}
nCameraa = nAngle;
if (!bCamera || nFreeze)
{
if (nSnakeCam >= 0)
{
2019-10-29 17:35:22 +00:00
pan = F16(92);
viewz = playerZ;
}
else
{
viewz = playerZ + nQuake[nLocalPlayer];
int floorZ = sector[sprite[nPlayerSprite].sectnum].floorz;
2019-10-30 17:06:05 +00:00
// pan = nVertPan[nLocalPlayer];
pan = PlayerList[nLocalPlayer].q16horiz;
if (viewz > floorZ)
viewz = floorZ;
2019-10-29 17:35:22 +00:00
nCameraa += fix16_from_int((nQuake[nLocalPlayer] >> 7) % 31);
nCameraa &= 0x7FFFFFF;
}
}
else
{
clipmove_old((int32_t*)&playerX, (int32_t*)&playerY, (int32_t*)&playerZ, &nSector,
-2000 * Sin(inita + 512),
-2000 * Sin(inita),
4, 0, 0, CLIPMASK1);
2019-10-29 17:35:22 +00:00
pan = F16(92);
viewz = playerZ;
}
nCamerax = playerX;
nCameray = playerY;
nCameraz = playerZ;
int Z = sector[nSector].ceilingz + 256;
if (Z <= viewz)
{
Z = sector[nSector].floorz - 256;
if (Z < viewz)
viewz = Z;
}
else {
viewz = Z;
}
nCamerapan = pan;
if (nFreeze == 2 || nFreeze == 1)
{
nSnakeCam = -1;
videoSetViewableArea(0, 0, xdim - 1, ydim - 1);
UnMaskStatus();
}
if (nFreeze != 3)
{
static uint8_t sectorFloorPal[MAXSECTORS];
static uint8_t sectorCeilingPal[MAXSECTORS];
static uint8_t wallPal[MAXWALLS];
2019-10-11 12:14:30 +00:00
int const viewingRange = viewingrange;
if (r_usenewaspect)
{
newaspect_enable = 1;
videoSetCorrectedAspect();
}
if (HavePLURemap())
{
for (int i = 0; i < numsectors; i++)
{
sectorFloorPal[i] = sector[i].floorpal;
sectorCeilingPal[i] = sector[i].ceilingpal;
2019-10-29 07:37:34 +00:00
sector[i].floorpal = RemapPLU(sectorFloorPal[i]);
sector[i].ceilingpal = RemapPLU(sectorCeilingPal[i]);
}
for (int i = 0; i < numwalls; i++)
{
wallPal[i] = wall[i].pal;
2019-10-29 07:37:34 +00:00
wall[i].pal = RemapPLU(wallPal[i]);
}
}
2019-10-29 17:35:22 +00:00
renderDrawRoomsQ16(nCamerax, nCameray, viewz, nCameraa, nCamerapan, nSector);
analyzesprites();
renderDrawMasks();
if (HavePLURemap())
{
for (int i = 0; i < numsectors; i++)
{
sector[i].floorpal = sectorFloorPal[i];
sector[i].ceilingpal = sectorCeilingPal[i];
}
for (int i = 0; i < numwalls; i++)
{
wall[i].pal = wallPal[i];
}
}
2019-10-11 12:14:30 +00:00
if (r_usenewaspect)
{
newaspect_enable = 0;
renderSetAspect(viewingRange, tabledivide32_noinline(65536 * ydim * 8, xdim * 5));
}
if (nFreeze)
{
nSnakeCam = -1;
if (nFreeze == 2)
{
if (nHeadStage == 4)
{
nHeadStage = 5;
sprite[nPlayerSprite].cstat |= 0x8000;
2019-10-29 17:35:22 +00:00
int ang2 = fix16_to_int(nCameraa) - sprite[nPlayerSprite].ang;
if (ang2 < 0)
ang2 = -ang2;
if (ang2 > 10)
{
inita -= (ang2 >> 3);
return;
}
if (bSubTitles)
{
if (levelnum == 1)
ReadyCinemaText(1);
else
ReadyCinemaText(5);
}
}
else
{
if ((bSubTitles && !AdvanceCinemaText()) || KB_KeyDown[sc_Escape] || KB_KeyDown[sc_Return] || KB_KeyDown[sc_Space])
{
levelnew = levelnum + 1;
if (CDplaying())
fadecdaudio();
}
videoSetViewableArea(nViewLeft, nViewTop, nViewRight, nViewBottom);
}
}
}
else
{
if (nSnakeCam < 0)
{
DrawWeapons();
DrawStatus();
}
else
{
RestoreGreenPal();
if (nEnemyPal > -1) {
sprite[enemy].pal = nEnemyPal;
}
if (!bFullScreen) {
MaskStatus();
}
}
}
}
else
{
videoClearScreen(overscanindex);
DrawStatus();
}
flash = 0;
}
void NoClip()
{
videoSetViewableArea(0, 0, xdim - 1, ydim - 1);
bClip = kFalse;
}
void Clip()
{
videoSetViewableArea(nViewLeft, nViewTop, nViewRight, nViewBottom);
if (!bFullScreen) {
MaskStatus();
}
bClip = kTrue;
}