raze/source/blood/src/mirrors.cpp

481 lines
16 KiB
C++
Raw Normal View History

2019-09-19 22:42:45 +00:00
//-------------------------------------------------------------------------
/*
Copyright (C) 2010-2019 EDuke32 developers and contributors
Copyright (C) 2019 Nuke.YKT
This file is part of NBlood.
NBlood 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" // Must come before everything else!
2019-09-19 22:42:45 +00:00
#include "build.h"
#include "compat.h"
#include "blood.h"
BEGIN_BLD_NS
2019-09-19 22:42:45 +00:00
int mirrorcnt, mirrorsector, mirrorwall[4];
typedef struct
{
2020-11-21 22:40:08 +00:00
int type;
int link;
int dx;
int dy;
int dz;
2020-11-21 22:40:08 +00:00
int wallnum;
2019-09-19 22:42:45 +00:00
} MIRROR;
MIRROR mirror[16];
void InitMirrors(void)
{
r_rortexture = 4080;
r_rortexturerange = 16;
mirrorcnt = 0;
tileDelete(504);
for (int i = 0; i < 16; i++)
{
tileDelete(4080 + i);
}
2019-09-19 22:42:45 +00:00
for (int i = numwalls - 1; i >= 0; i--)
{
if (mirrorcnt == 16)
break;
int nTile = 4080+mirrorcnt;
if (wall[i].overpicnum == 504)
{
if (wall[i].extra > 0 && GetWallType(i) == kWallStack)
2019-09-19 22:42:45 +00:00
{
wall[i].overpicnum = nTile;
2020-11-21 22:40:08 +00:00
mirror[mirrorcnt].wallnum = i;
mirror[mirrorcnt].type = 0;
2019-09-19 22:42:45 +00:00
wall[i].cstat |= 32;
int tmp = xwall[wall[i].extra].data;
int j;
for (j = numwalls - 1; j >= 0; j--)
{
if (j == i)
continue;
if (wall[j].extra > 0 && GetWallType(i) == kWallStack)
2019-09-19 22:42:45 +00:00
{
if (tmp != xwall[wall[j].extra].data)
continue;
wall[i].hitag = j;
wall[j].hitag = i;
2020-11-21 22:40:08 +00:00
mirror[mirrorcnt].link = j;
2019-09-19 22:42:45 +00:00
break;
}
}
if (j < 0)
I_Error("wall[%d] has no matching wall link! (data=%d)\n", i, tmp);
2019-09-19 22:42:45 +00:00
mirrorcnt++;
}
continue;
}
if (wall[i].picnum == 504)
{
2020-11-21 22:40:08 +00:00
mirror[mirrorcnt].link = i;
mirror[mirrorcnt].wallnum = i;
2019-09-19 22:42:45 +00:00
wall[i].picnum = nTile;
2020-11-21 22:40:08 +00:00
mirror[mirrorcnt].type = 0;
2019-09-19 22:42:45 +00:00
wall[i].cstat |= 32;
mirrorcnt++;
continue;
}
}
for (int i = numsectors - 1; i >= 0; i--)
{
if (mirrorcnt >= 15)
break;
if (sector[i].floorpicnum == 504)
{
int nLink = gUpperLink[i];
if (nLink < 0)
continue;
int nLink2 = sprite[nLink].owner & 0xfff;
int j = sprite[nLink2].sectnum;
if (sector[j].ceilingpicnum != 504)
I_Error("Lower link sector %d doesn't have mirror picnum\n", j);
2020-11-21 22:40:08 +00:00
mirror[mirrorcnt].type = 2;
mirror[mirrorcnt].dx = sprite[nLink2].x-sprite[nLink].x;
mirror[mirrorcnt].dy = sprite[nLink2].y-sprite[nLink].y;
mirror[mirrorcnt].dz = sprite[nLink2].z-sprite[nLink].z;
2020-11-21 22:40:08 +00:00
mirror[mirrorcnt].wallnum = i;
mirror[mirrorcnt].link = j;
2019-09-19 22:42:45 +00:00
sector[i].floorpicnum = 4080+mirrorcnt;
mirrorcnt++;
2020-11-21 22:40:08 +00:00
mirror[mirrorcnt].type = 1;
mirror[mirrorcnt].dx = sprite[nLink].x-sprite[nLink2].x;
mirror[mirrorcnt].dy = sprite[nLink].y-sprite[nLink2].y;
mirror[mirrorcnt].dz = sprite[nLink].z-sprite[nLink2].z;
2020-11-21 22:40:08 +00:00
mirror[mirrorcnt].wallnum = j;
mirror[mirrorcnt].link = i;
2019-09-19 22:42:45 +00:00
sector[j].ceilingpicnum = 4080+mirrorcnt;
mirrorcnt++;
}
}
mirrorsector = numsectors;
for (int i = 0; i < 4; i++)
{
mirrorwall[i] = numwalls+i;
wall[mirrorwall[i]].picnum = 504;
wall[mirrorwall[i]].overpicnum = 504;
wall[mirrorwall[i]].cstat = 0;
wall[mirrorwall[i]].nextsector = -1;
wall[mirrorwall[i]].nextwall = -1;
2019-06-24 08:09:29 +00:00
wall[mirrorwall[i]].point2 = numwalls+i+1;
2019-09-19 22:42:45 +00:00
}
wall[mirrorwall[3]].point2 = mirrorwall[0];
sector[mirrorsector].ceilingpicnum = 504;
sector[mirrorsector].floorpicnum = 504;
sector[mirrorsector].wallptr = mirrorwall[0];
sector[mirrorsector].wallnum = 4;
}
void TranslateMirrorColors(int nShade, int nPalette)
{
}
void sub_5571C(char mode)
{
for (int i = mirrorcnt-1; i >= 0; i--)
{
int nTile = 4080+i;
if (TestBitString(gotpic, nTile))
{
2020-11-21 22:40:08 +00:00
switch (mirror[i].type)
2019-09-19 22:42:45 +00:00
{
case 1:
if (mode)
2020-11-21 22:40:08 +00:00
sector[mirror[i].wallnum].ceilingstat |= 1;
2019-09-19 22:42:45 +00:00
else
2020-11-21 22:40:08 +00:00
sector[mirror[i].wallnum].ceilingstat &= ~1;
2019-09-19 22:42:45 +00:00
break;
case 2:
if (mode)
2020-11-21 22:40:08 +00:00
sector[mirror[i].wallnum].floorstat |= 1;
2019-09-19 22:42:45 +00:00
else
2020-11-21 22:40:08 +00:00
sector[mirror[i].wallnum].floorstat &= ~1;
2019-09-19 22:42:45 +00:00
break;
}
}
}
}
void sub_557C4(int x, int y, int interpolation)
{
if (spritesortcnt == 0) return;
int nViewSprites = spritesortcnt-1;
for (int nTSprite = nViewSprites; nTSprite >= 0; nTSprite--)
{
tspritetype *pTSprite = &tsprite[nTSprite];
2019-09-19 22:42:45 +00:00
pTSprite->xrepeat = pTSprite->yrepeat = 0;
}
for (int i = mirrorcnt-1; i >= 0; i--)
{
int nTile = 4080+i;
if (TestBitString(gotpic, nTile))
{
2020-11-21 22:40:08 +00:00
if (mirror[i].type == 1 || mirror[i].type == 2)
2019-09-19 22:42:45 +00:00
{
2020-11-21 22:40:08 +00:00
int nSector = mirror[i].link;
int nSector2 = mirror[i].wallnum;
int nSprite;
SectIterator it(nSector);
while ((nSprite = it.NextIndex()) >= 0)
2019-09-19 22:42:45 +00:00
{
spritetype *pSprite = &sprite[nSprite];
if (pSprite == gView->pSprite)
continue;
int top, bottom;
GetSpriteExtents(pSprite, &top, &bottom);
int zCeil, zFloor;
getzsofslope(nSector, pSprite->x, pSprite->y, &zCeil, &zFloor);
if (pSprite->statnum == kStatDude && (top < zCeil || bottom > zFloor))
2019-09-19 22:42:45 +00:00
{
int j = i;
2020-11-21 22:40:08 +00:00
if (mirror[i].type == 2)
2019-09-19 22:42:45 +00:00
j++;
else
j--;
int dx = mirror[j].dx;
int dy = mirror[j].dy;
int dz = mirror[j].dz;
tspritetype *pTSprite = &tsprite[spritesortcnt];
memset(pTSprite, 0, sizeof(tspritetype));
pTSprite->type = pSprite->type;
pTSprite->index = pSprite->index;
2019-09-19 22:42:45 +00:00
pTSprite->sectnum = nSector2;
pTSprite->x = pSprite->x+dx;
pTSprite->y = pSprite->y+dy;
pTSprite->z = pSprite->z+dz;
pTSprite->ang = pSprite->ang;
pTSprite->picnum = pSprite->picnum;
pTSprite->shade = pSprite->shade;
pTSprite->pal = pSprite->pal;
pTSprite->xrepeat = pSprite->xrepeat;
pTSprite->yrepeat = pSprite->yrepeat;
pTSprite->xoffset = pSprite->xoffset;
pTSprite->yoffset = pSprite->yoffset;
pTSprite->cstat = pSprite->cstat;
pTSprite->statnum = kStatDecoration;
2019-09-19 22:42:45 +00:00
pTSprite->owner = pSprite->index;
pTSprite->extra = pSprite->extra;
pTSprite->flags = pSprite->hitag|0x200;
2019-09-19 22:42:45 +00:00
LOCATION *pLocation = &gPrevSpriteLoc[pSprite->index];
pTSprite->x = dx+interpolate(pLocation->x, pSprite->x, interpolation);
pTSprite->y = dy+interpolate(pLocation->y, pSprite->y, interpolation);
pTSprite->z = dz+interpolate(pLocation->z, pSprite->z, interpolation);
pTSprite->ang = pLocation->ang+mulscale16(((pSprite->ang-pLocation->ang+1024)&2047)-1024,interpolation);
spritesortcnt++;
}
}
}
}
}
for (int nTSprite = spritesortcnt-1; nTSprite >= nViewSprites; nTSprite--)
{
tspritetype *pTSprite = &tsprite[nTSprite];
2019-09-19 22:42:45 +00:00
int nAnim = 0;
switch (picanm[pTSprite->picnum].extra&7)
{
case 1:
{
int dX = x - pTSprite->x;
int dY = y - pTSprite->y;
RotateVector(&dX, &dY, 128 - pTSprite->ang);
nAnim = GetOctant(dX, dY);
if (nAnim <= 4)
{
pTSprite->cstat &= ~4;
}
else
{
nAnim = 8 - nAnim;
pTSprite->cstat |= 4;
}
break;
}
case 2:
{
int dX = x - pTSprite->x;
int dY = y - pTSprite->y;
RotateVector(&dX, &dY, 128 - pTSprite->ang);
nAnim = GetOctant(dX, dY);
break;
}
}
while (nAnim > 0)
{
pTSprite->picnum += picanm[pTSprite->picnum].num+1;
nAnim--;
}
}
}
void DrawMirrors(int x, int y, int z, fixed_t a, fixed_t horiz, int smooth, int viewPlayer)
2019-09-19 22:42:45 +00:00
{
for (int i = mirrorcnt - 1; i >= 0; i--)
{
int nTile = 4080+i;
if (TestBitString(gotpic, nTile))
{
ClearBitString(gotpic, nTile);
2020-11-21 22:40:08 +00:00
switch (mirror[i].type)
2019-09-19 22:42:45 +00:00
{
case 0:
{
2020-11-21 22:40:08 +00:00
int nWall = mirror[i].link;
2019-09-19 22:42:45 +00:00
int nSector = sectorofwall(nWall);
walltype *pWall = &wall[nWall];
int nNextWall = pWall->nextwall;
int nNextSector = pWall->nextsector;
pWall->nextwall = mirrorwall[0];
pWall->nextsector = mirrorsector;
wall[mirrorwall[0]].nextwall = nWall;
wall[mirrorwall[0]].nextsector = nSector;
wall[mirrorwall[0]].x = wall[pWall->point2].x;
wall[mirrorwall[0]].y = wall[pWall->point2].y;
wall[mirrorwall[1]].x = pWall->x;
wall[mirrorwall[1]].y = pWall->y;
wall[mirrorwall[2]].x = wall[mirrorwall[1]].x+(wall[mirrorwall[1]].x-wall[mirrorwall[0]].x)*16;
wall[mirrorwall[2]].y = wall[mirrorwall[1]].y+(wall[mirrorwall[1]].y-wall[mirrorwall[0]].y)*16;
wall[mirrorwall[3]].x = wall[mirrorwall[0]].x+(wall[mirrorwall[0]].x-wall[mirrorwall[1]].x)*16;
wall[mirrorwall[3]].y = wall[mirrorwall[0]].y+(wall[mirrorwall[0]].y-wall[mirrorwall[1]].y)*16;
sector[mirrorsector].floorz = sector[nSector].floorz;
sector[mirrorsector].ceilingz = sector[nSector].ceilingz;
int cx, cy, ca;
if (GetWallType(nWall) == kWallStack)
2019-09-19 22:42:45 +00:00
{
cx = x - (wall[pWall->hitag].x-wall[pWall->point2].x);
cy = y - (wall[pWall->hitag].y-wall[pWall->point2].y);
ca = a;
}
else
{
2019-09-20 17:37:29 +00:00
renderPrepareMirror(x,y,z,a,horiz,nWall,&cx,&cy,&ca);
2019-09-19 22:42:45 +00:00
}
int32_t didmirror = renderDrawRoomsQ16(cx, cy, z, ca,horiz,mirrorsector|MAXSECTORS);
viewProcessSprites(cx,cy,z,FixedToInt(ca),smooth);
2019-09-19 22:42:45 +00:00
renderDrawMasks();
if (GetWallType(nWall) != kWallStack)
2019-09-20 17:37:29 +00:00
renderCompleteMirror();
2019-09-19 22:42:45 +00:00
if (wall[nWall].pal != 0 || wall[nWall].shade != 0)
TranslateMirrorColors(wall[nWall].shade, wall[nWall].pal);
pWall->nextwall = nNextWall;
pWall->nextsector = nNextSector;
return;
}
case 1:
{
r_rorphase = 1;
2020-11-21 22:40:08 +00:00
int nSector = mirror[i].link;
2019-09-08 14:29:17 +00:00
int bakCstat;
if (viewPlayer >= 0)
{
bakCstat = gPlayer[viewPlayer].pSprite->cstat;
if (gViewPos == 0)
{
gPlayer[viewPlayer].pSprite->cstat |= 32768;
}
else
{
gPlayer[viewPlayer].pSprite->cstat |= 514;
}
}
renderDrawRoomsQ16(x+mirror[i].dx, y+mirror[i].dy, z+mirror[i].dz, a, horiz, nSector|MAXSECTORS);
viewProcessSprites(x+mirror[i].dx, y+mirror[i].dy, z+mirror[i].dz, FixedToInt(a), smooth);
2019-09-19 22:42:45 +00:00
short fstat = sector[nSector].floorstat;
sector[nSector].floorstat |= 1;
renderDrawMasks();
sector[nSector].floorstat = fstat;
for (int i = 0; i < 16; i++)
ClearBitString(gotpic, 4080+i);
2019-09-08 14:29:17 +00:00
if (viewPlayer >= 0)
{
gPlayer[viewPlayer].pSprite->cstat = bakCstat;
}
r_rorphase = 0;
2019-09-19 22:42:45 +00:00
return;
}
case 2:
{
r_rorphase = 1;
2020-11-21 22:40:08 +00:00
int nSector = mirror[i].link;
2019-09-08 14:29:17 +00:00
int bakCstat;
if (viewPlayer >= 0)
{
bakCstat = gPlayer[viewPlayer].pSprite->cstat;
if (gViewPos == 0)
{
gPlayer[viewPlayer].pSprite->cstat |= 32768;
}
else
{
gPlayer[viewPlayer].pSprite->cstat |= 514;
}
}
renderDrawRoomsQ16(x+mirror[i].dx, y+mirror[i].dy, z+mirror[i].dz, a, horiz, nSector|MAXSECTORS);
viewProcessSprites(x+mirror[i].dx, y+mirror[i].dy, z+mirror[i].dz, FixedToInt(a), smooth);
2019-09-19 22:42:45 +00:00
short cstat = sector[nSector].ceilingstat;
sector[nSector].ceilingstat |= 1;
renderDrawMasks();
sector[nSector].ceilingstat = cstat;
for (int i = 0; i < 16; i++)
ClearBitString(gotpic, 4080+i);
2019-09-08 14:29:17 +00:00
if (viewPlayer >= 0)
{
gPlayer[viewPlayer].pSprite->cstat = bakCstat;
}
r_rorphase = 0;
2019-09-19 22:42:45 +00:00
return;
}
}
}
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
2019-09-19 22:42:45 +00:00
FSerializer& Serialize(FSerializer& arc, const char* keyname, MIRROR& w, MIRROR* def)
2019-09-19 22:42:45 +00:00
{
if (arc.BeginObject(keyname))
{
arc ("type", w.type)
("link", w.link)
("dx", w.dx)
("dy", w.dy)
("dz", w.dz)
("wallnum", w.wallnum)
.EndObject();
}
return arc;
2019-09-19 22:42:45 +00:00
}
void SerializeMirrors(FSerializer& arc)
2019-09-19 22:42:45 +00:00
{
if (arc.BeginObject("mirror"))
{
arc("mirrorcnt", mirrorcnt)
("mirrorsector", mirrorsector)
.Array("mirror", mirror, countof(mirror))
.Array("mirrorwall", mirrorwall, countof(mirrorwall))
.EndObject();
}
2019-09-19 22:42:45 +00:00
if (arc.isReading())
{
tileDelete(504);
#ifdef USE_OPENGL
r_rortexture = 4080;
r_rortexturerange = 16;
#endif
for (int i = 0; i < 16; i++)
{
tileDelete(4080 + i);
}
for (int i = 0; i < 4; i++)
{
wall[mirrorwall[i]].picnum = 504;
wall[mirrorwall[i]].overpicnum = 504;
wall[mirrorwall[i]].cstat = 0;
wall[mirrorwall[i]].nextsector = -1;
wall[mirrorwall[i]].nextwall = -1;
wall[mirrorwall[i]].point2 = numwalls + i + 1;
}
wall[mirrorwall[3]].point2 = mirrorwall[0];
sector[mirrorsector].ceilingpicnum = 504;
sector[mirrorsector].floorpicnum = 504;
sector[mirrorsector].wallptr = mirrorwall[0];
sector[mirrorsector].wallnum = 4;
}
2019-09-19 22:42:45 +00:00
}
END_BLD_NS