mirror of
https://github.com/ZDoom/Raze.git
synced 2025-01-07 09:40:43 +00:00
847fa48724
In particular this means to remove the option to disable widescreen aspect ratios. The way this was handled makes no sense with the current render backend. The aspect ratio code will have to be redone entirely to properly obey the backend's settings.
513 lines
13 KiB
C++
513 lines
13 KiB
C++
//-------------------------------------------------------------------------
|
|
/*
|
|
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
|
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
|
This file is part of PCExhumed.
|
|
PCExhumed is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License version 2
|
|
as published by the Free Software Foundation.
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
See the GNU General Public License for more details.
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*/
|
|
//-------------------------------------------------------------------------
|
|
#include "ns.h"
|
|
#include "compat.h"
|
|
#include "engine.h"
|
|
#include "names.h"
|
|
#include "view.h"
|
|
#include "status.h"
|
|
#include "exhumed.h"
|
|
#include "player.h"
|
|
#include "aistuff.h"
|
|
#include "sound.h"
|
|
#include "mapinfo.h"
|
|
#include "v_video.h"
|
|
#include "glbackend/glbackend.h"
|
|
#include <string.h>
|
|
|
|
BEGIN_PS_NS
|
|
|
|
short bSubTitles = true;
|
|
|
|
int zbob;
|
|
|
|
fix16_t nDestVertPan[kMaxPlayers] = { 0 };
|
|
short dVertPan[kMaxPlayers];
|
|
int nCamerax;
|
|
int nCameray;
|
|
int nCameraz;
|
|
|
|
|
|
short bTouchFloor;
|
|
|
|
short nQuake[kMaxPlayers] = { 0 };
|
|
|
|
short nChunkTotal = 0;
|
|
|
|
fix16_t nCameraa;
|
|
fix16_t nCamerapan;
|
|
short nViewTop;
|
|
short bCamera = false;
|
|
|
|
int viewz;
|
|
|
|
short enemy;
|
|
|
|
short nEnemyPal = 0;
|
|
|
|
#define MAXINTERPOLATIONS MAXSPRITES
|
|
int32_t g_interpolationCnt;
|
|
int32_t oldipos[MAXINTERPOLATIONS];
|
|
int32_t* curipos[MAXINTERPOLATIONS];
|
|
int32_t bakipos[MAXINTERPOLATIONS];
|
|
|
|
int viewSetInterpolation(int32_t *const posptr)
|
|
{
|
|
if (g_interpolationCnt >= MAXINTERPOLATIONS)
|
|
return 1;
|
|
|
|
for (bssize_t i = 0; i < g_interpolationCnt; ++i)
|
|
if (curipos[i] == posptr)
|
|
return 0;
|
|
|
|
curipos[g_interpolationCnt] = posptr;
|
|
oldipos[g_interpolationCnt] = *posptr;
|
|
g_interpolationCnt++;
|
|
return 0;
|
|
}
|
|
|
|
void viewStopInterpolation(const int32_t * const posptr)
|
|
{
|
|
for (bssize_t i = 0; i < g_interpolationCnt; ++i)
|
|
if (curipos[i] == posptr)
|
|
{
|
|
g_interpolationCnt--;
|
|
oldipos[i] = oldipos[g_interpolationCnt];
|
|
bakipos[i] = bakipos[g_interpolationCnt];
|
|
curipos[i] = curipos[g_interpolationCnt];
|
|
}
|
|
}
|
|
|
|
void viewDoInterpolations(int smoothRatio)
|
|
{
|
|
int32_t ndelta = 0;
|
|
|
|
for (bssize_t i = 0, j = 0; i < g_interpolationCnt; ++i)
|
|
{
|
|
int32_t const odelta = ndelta;
|
|
bakipos[i] = *curipos[i];
|
|
ndelta = (*curipos[i]) - oldipos[i];
|
|
if (odelta != ndelta)
|
|
j = mulscale16(ndelta, smoothRatio);
|
|
*curipos[i] = oldipos[i] + j;
|
|
}
|
|
}
|
|
|
|
void viewUpdateInterpolations(void) //Stick at beginning of G_DoMoveThings
|
|
{
|
|
for (bssize_t i=g_interpolationCnt-1; i>=0; i--) oldipos[i] = *curipos[i];
|
|
}
|
|
|
|
void viewRestoreInterpolations(void) //Stick at end of drawscreen
|
|
{
|
|
int32_t i=g_interpolationCnt-1;
|
|
|
|
for (; i>=0; i--) *curipos[i] = bakipos[i];
|
|
}
|
|
|
|
void InitView()
|
|
{
|
|
polymostcenterhoriz = 92;
|
|
}
|
|
|
|
// 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 = §or[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 = kCreepyCount;
|
|
|
|
if (!cansee(x, y, z, nSector, pTarget->x, pTarget->y, pTarget->z - GetSpriteHeight(besttarget), pTarget->sectnum))
|
|
{
|
|
besttarget = -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ResetView()
|
|
{
|
|
EraseScreen(overscanindex);
|
|
#ifdef USE_OPENGL
|
|
videoTintBlood(0, 0, 0);
|
|
#endif
|
|
}
|
|
|
|
static inline int interpolate16(int a, int b, int smooth)
|
|
{
|
|
return a + mulscale16(b - a, smooth);
|
|
}
|
|
|
|
static TextOverlay subtitleOverlay;
|
|
|
|
void DrawView(double smoothRatio, bool sceneonly)
|
|
{
|
|
int playerX;
|
|
int playerY;
|
|
int playerZ;
|
|
short nSector;
|
|
fix16_t nAngle;
|
|
fix16_t pan;
|
|
|
|
zbob = Sin(2 * bobangle) >> 3;
|
|
|
|
int nPlayerSprite = PlayerList[nLocalPlayer].nSprite;
|
|
int nPlayerOldCstat = sprite[nPlayerSprite].cstat;
|
|
int nDoppleOldCstat = sprite[nDoppleSprite[nLocalPlayer]].cstat;
|
|
|
|
if (nSnakeCam >= 0 && !sceneonly)
|
|
{
|
|
int nSprite = SnakeList[nSnakeCam].nSprites[0];
|
|
|
|
playerX = sprite[nSprite].x;
|
|
playerY = sprite[nSprite].y;
|
|
playerZ = sprite[nSprite].z;
|
|
nSector = sprite[nSprite].sectnum;
|
|
nAngle = fix16_from_int(sprite[nSprite].ang);
|
|
|
|
SetGreenPal();
|
|
|
|
enemy = SnakeList[nSnakeCam].nEnemy;
|
|
|
|
if (enemy <= -1 || totalmoves & 1)
|
|
{
|
|
nEnemyPal = -1;
|
|
}
|
|
else
|
|
{
|
|
nEnemyPal = sprite[enemy].pal;
|
|
sprite[enemy].pal = 5;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
playerX = interpolate16(PlayerList[nLocalPlayer].opos.x, sprite[nPlayerSprite].x, smoothRatio);
|
|
playerY = interpolate16(PlayerList[nLocalPlayer].opos.y, sprite[nPlayerSprite].y, smoothRatio);
|
|
playerZ = interpolate16(PlayerList[nLocalPlayer].opos.z, sprite[nPlayerSprite].z, smoothRatio)
|
|
+ interpolate16(oeyelevel[nLocalPlayer], eyelevel[nLocalPlayer], smoothRatio);
|
|
nSector = nPlayerViewSect[nLocalPlayer];
|
|
nAngle = PlayerList[nLocalPlayer].q16angle;
|
|
|
|
if (!bCamera)
|
|
{
|
|
sprite[nPlayerSprite].cstat |= CSTAT_SPRITE_INVISIBLE;
|
|
sprite[nDoppleSprite[nLocalPlayer]].cstat |= CSTAT_SPRITE_INVISIBLE;
|
|
}
|
|
}
|
|
|
|
nCameraa = nAngle;
|
|
|
|
if (!bCamera || nFreeze || sceneonly)
|
|
{
|
|
if (nSnakeCam >= 0 && !sceneonly)
|
|
{
|
|
pan = F16(92);
|
|
viewz = playerZ;
|
|
}
|
|
else
|
|
{
|
|
viewz = playerZ + nQuake[nLocalPlayer];
|
|
int floorZ = sector[sprite[nPlayerSprite].sectnum].floorz;
|
|
|
|
pan = PlayerList[nLocalPlayer].q16horiz;
|
|
|
|
if (viewz > floorZ)
|
|
viewz = floorZ;
|
|
|
|
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);
|
|
|
|
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);
|
|
}
|
|
|
|
UpdateMap();
|
|
|
|
if (nFreeze != 3)
|
|
{
|
|
static uint8_t sectorFloorPal[MAXSECTORS];
|
|
static uint8_t sectorCeilingPal[MAXSECTORS];
|
|
static uint8_t wallPal[MAXWALLS];
|
|
int const viewingRange = viewingrange;
|
|
int const vr = Blrintf(65536.f * tanf(r_fov * (fPI / 360.f)));
|
|
|
|
|
|
videoSetCorrectedAspect();
|
|
renderSetAspect(mulscale16(vr, viewingrange), yxaspect);
|
|
|
|
if (HavePLURemap())
|
|
{
|
|
for (int i = 0; i < numsectors; i++)
|
|
{
|
|
sectorFloorPal[i] = sector[i].floorpal;
|
|
sectorCeilingPal[i] = sector[i].ceilingpal;
|
|
sector[i].floorpal = RemapPLU(sectorFloorPal[i]);
|
|
sector[i].ceilingpal = RemapPLU(sectorCeilingPal[i]);
|
|
}
|
|
for (int i = 0; i < numwalls; i++)
|
|
{
|
|
wallPal[i] = wall[i].pal;
|
|
wall[i].pal = RemapPLU(wallPal[i]);
|
|
}
|
|
}
|
|
|
|
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];
|
|
}
|
|
}
|
|
|
|
|
|
renderSetAspect(viewingRange, divscale16(ydim * 8, xdim * 5));
|
|
|
|
if (nFreeze)
|
|
{
|
|
nSnakeCam = -1;
|
|
|
|
if (nFreeze == 2)
|
|
{
|
|
if (nHeadStage == 4)
|
|
{
|
|
nHeadStage = 5;
|
|
|
|
sprite[nPlayerSprite].cstat |= 0x8000;
|
|
|
|
int ang2 = fix16_to_int(nCameraa) - sprite[nPlayerSprite].ang;
|
|
if (ang2 < 0)
|
|
ang2 = -ang2;
|
|
|
|
if (ang2 > 10)
|
|
{
|
|
inita -= (ang2 >> 3);
|
|
return;
|
|
}
|
|
|
|
if (bSubTitles)
|
|
{
|
|
subtitleOverlay.Start(gameclock);
|
|
if (currentLevel->levelNumber == 1)
|
|
subtitleOverlay.ReadyCinemaText(0);
|
|
else
|
|
subtitleOverlay.ReadyCinemaText(4);
|
|
}
|
|
inputState.ClearAllInput();
|
|
}
|
|
else if (nHeadStage == 5)
|
|
{
|
|
if ((bSubTitles && !subtitleOverlay.AdvanceCinemaText(gameclock)) || inputState.CheckAllInput())
|
|
{
|
|
inputState.ClearAllInput();
|
|
EndLevel = 2;
|
|
|
|
if (CDplaying()) {
|
|
fadecdaudio();
|
|
}
|
|
}
|
|
else subtitleOverlay.DisplayText();
|
|
}
|
|
}
|
|
}
|
|
else if (!sceneonly)
|
|
{
|
|
if (nSnakeCam < 0)
|
|
{
|
|
DrawWeapons(smoothRatio);
|
|
DrawMap();
|
|
}
|
|
else
|
|
{
|
|
RestoreGreenPal();
|
|
if (nEnemyPal > -1) {
|
|
sprite[enemy].pal = nEnemyPal;
|
|
}
|
|
|
|
DrawMap();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
twod->ClearScreen();
|
|
}
|
|
|
|
sprite[nPlayerSprite].cstat = nPlayerOldCstat;
|
|
sprite[nDoppleSprite[nLocalPlayer]].cstat = nDoppleOldCstat;
|
|
|
|
flash = 0;
|
|
}
|
|
|
|
bool GameInterface::GenerateSavePic()
|
|
{
|
|
DrawView(65536, true);
|
|
return true;
|
|
}
|
|
|
|
void NoClip()
|
|
{
|
|
}
|
|
|
|
void Clip()
|
|
{
|
|
}
|
|
|
|
|
|
static SavegameHelper sgh("view",
|
|
SV(nCamerax),
|
|
SV(nCameray),
|
|
SV(nCameraz),
|
|
SV(bTouchFloor),
|
|
SV(nChunkTotal),
|
|
SV(nCameraa),
|
|
SV(nCamerapan),
|
|
SV(bCamera),
|
|
SV(viewz),
|
|
SV(enemy),
|
|
SV(nEnemyPal),
|
|
SA(nDestVertPan),
|
|
SA(dVertPan),
|
|
SA(nQuake),
|
|
SV(g_interpolationCnt),
|
|
SA(oldipos),
|
|
SA(curipos),
|
|
SA(bakipos),
|
|
nullptr);
|
|
|
|
END_PS_NS
|