- normalize line endings.

This commit is contained in:
Christoph Oelckers 2022-01-22 14:37:17 +01:00
parent a34c6d6b5f
commit 276597fc36
3 changed files with 960 additions and 960 deletions

View file

@ -1,71 +1,71 @@
BUILD SOURCE CODE LICENSE TERMS: 06/20/2000 BUILD SOURCE CODE LICENSE TERMS: 06/20/2000
[1] I give you permission to make modifications to my Build source and [1] I give you permission to make modifications to my Build source and
distribute it, BUT: distribute it, BUT:
[2] Any derivative works based on my Build source may be distributed ONLY [2] Any derivative works based on my Build source may be distributed ONLY
through the INTERNET. through the INTERNET.
[3] Distribution of any derivative works MUST be done completely FREE of [3] Distribution of any derivative works MUST be done completely FREE of
charge - no commercial exploitation whatsoever. charge - no commercial exploitation whatsoever.
[4] Anything you distribute which uses a part of my Build Engine source [4] Anything you distribute which uses a part of my Build Engine source
code MUST include: code MUST include:
[A] The following message somewhere in the archive: [A] The following message somewhere in the archive:
// "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman // "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman
// Ken Silverman's official web site: "http://www.advsys.net/ken" // Ken Silverman's official web site: "http://www.advsys.net/ken"
// See the included license file "BUILDLIC.TXT" for license info. // See the included license file "BUILDLIC.TXT" for license info.
[B] This text file "BUILDLIC.TXT" along with it. [B] This text file "BUILDLIC.TXT" along with it.
[C] Any source files that you modify must include this message as well: [C] Any source files that you modify must include this message as well:
// This file has been modified from Ken Silverman's original release // This file has been modified from Ken Silverman's original release
[5] The use of the Build Engine for commercial purposes will require an [5] The use of the Build Engine for commercial purposes will require an
appropriate license arrangement with me. Contact information is appropriate license arrangement with me. Contact information is
on my web site. on my web site.
[6] I take no responsibility for damage to your system. [6] I take no responsibility for damage to your system.
[7] Technical support: Before contacting me with questions, please read [7] Technical support: Before contacting me with questions, please read
and do ALL of the following! and do ALL of the following!
[A] Look through ALL of my text files. There are 7 of them (including this [A] Look through ALL of my text files. There are 7 of them (including this
one). I like to think that I wrote them for a reason. You will find one). I like to think that I wrote them for a reason. You will find
many of your answers in the history section of BUILD.TXT and many of your answers in the history section of BUILD.TXT and
BUILD2.TXT (they're located inside SRC.ZIP). BUILD2.TXT (they're located inside SRC.ZIP).
[B] If that doesn't satisfy you, then try going to: [B] If that doesn't satisfy you, then try going to:
"http://www.advsys.net/ken/buildsrc" "http://www.advsys.net/ken/buildsrc"
where I will maintain a Build Source Code FAQ (or perhaps I might where I will maintain a Build Source Code FAQ (or perhaps I might
just provide a link to a good FAQ). just provide a link to a good FAQ).
[C] I am willing to respond to questions, but ONLY if they come at a rate [C] I am willing to respond to questions, but ONLY if they come at a rate
that I can handle. that I can handle.
PLEASE TRY TO AVOID ASKING DUPLICATE QUESTIONS! PLEASE TRY TO AVOID ASKING DUPLICATE QUESTIONS!
As my line of defense, I will post my current policy about As my line of defense, I will post my current policy about
answering Build source questions (right below the E-mail address answering Build source questions (right below the E-mail address
on my web site.) You can check there to see if I'm getting on my web site.) You can check there to see if I'm getting
overloaded with questions or not. overloaded with questions or not.
If I'm too busy, it might say something like this: If I'm too busy, it might say something like this:
I'm too busy to answer Build source questions right now. I'm too busy to answer Build source questions right now.
Sorry, but don't expect a reply from me any time soon. Sorry, but don't expect a reply from me any time soon.
If I'm open for Build source questions, please state your question If I'm open for Build source questions, please state your question
clearly and don't include any unsolicited attachments unless clearly and don't include any unsolicited attachments unless
they're really small (like less than 50k). Assume that I have they're really small (like less than 50k). Assume that I have
a 28.8k modem. Also, don't leave out important details just a 28.8k modem. Also, don't leave out important details just
to make your question appear shorter - making me guess what to make your question appear shorter - making me guess what
you're asking doesn't save me time! you're asking doesn't save me time!
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-Ken S. (official web site: http://www.advsys.net/ken) -Ken S. (official web site: http://www.advsys.net/ken)

View file

@ -1,483 +1,483 @@
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
/* /*
Copyright (C) 2021 Christoph Oelckers & Mitchell Richters Copyright (C) 2021 Christoph Oelckers & Mitchell Richters
This is free software; you can redistribute it and/or This is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
#include "gamefuncs.h" #include "gamefuncs.h"
#include "gamestruct.h" #include "gamestruct.h"
#include "intvec.h" #include "intvec.h"
#include "coreactor.h" #include "coreactor.h"
#include "interpolate.h" #include "interpolate.h"
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// //
// Unified chasecam function for all games. // Unified chasecam function for all games.
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
int cameradist, cameraclock; int cameradist, cameraclock;
bool calcChaseCamPos(int* px, int* py, int* pz, DCoreActor* act, sectortype** psect, binangle ang, fixedhoriz horiz, double const smoothratio) bool calcChaseCamPos(int* px, int* py, int* pz, DCoreActor* act, sectortype** psect, binangle ang, fixedhoriz horiz, double const smoothratio)
{ {
HitInfoBase hitinfo; HitInfoBase hitinfo;
binangle daang; binangle daang;
int newdist; int newdist;
if (!*psect) return false; if (!*psect) return false;
// Calculate new pos to shoot backwards, using averaged values from the big three. // Calculate new pos to shoot backwards, using averaged values from the big three.
int nx = gi->chaseCamX(ang); int nx = gi->chaseCamX(ang);
int ny = gi->chaseCamY(ang); int ny = gi->chaseCamY(ang);
int nz = gi->chaseCamZ(horiz); int nz = gi->chaseCamZ(horiz);
auto bakcstat = act->spr.cstat; auto bakcstat = act->spr.cstat;
act->spr.cstat &= ~CSTAT_SPRITE_BLOCK_ALL; act->spr.cstat &= ~CSTAT_SPRITE_BLOCK_ALL;
updatesectorz(*px, *py, *pz, psect); updatesectorz(*px, *py, *pz, psect);
hitscan({ *px, *py, *pz }, *psect, { nx, ny, nz }, hitinfo, CLIPMASK1); hitscan({ *px, *py, *pz }, *psect, { nx, ny, nz }, hitinfo, CLIPMASK1);
act->spr.cstat = bakcstat; act->spr.cstat = bakcstat;
int hx = hitinfo.hitpos.X - *px; int hx = hitinfo.hitpos.X - *px;
int hy = hitinfo.hitpos.Y - *py; int hy = hitinfo.hitpos.Y - *py;
if (*psect == nullptr) if (*psect == nullptr)
{ {
return false; return false;
} }
// If something is in the way, make pp->camera_dist lower if necessary // If something is in the way, make pp->camera_dist lower if necessary
if (abs(nx) + abs(ny) > abs(hx) + abs(hy)) if (abs(nx) + abs(ny) > abs(hx) + abs(hy))
{ {
if (hitinfo.hitWall != nullptr) if (hitinfo.hitWall != nullptr)
{ {
// Push you a little bit off the wall // Push you a little bit off the wall
*psect = hitinfo.hitSector; *psect = hitinfo.hitSector;
daang = bvectangbam(hitinfo.hitWall->point2Wall()->pos.X - hitinfo.hitWall->pos.X, daang = bvectangbam(hitinfo.hitWall->point2Wall()->pos.X - hitinfo.hitWall->pos.X,
hitinfo.hitWall->point2Wall()->pos.Y - hitinfo.hitWall->pos.Y); hitinfo.hitWall->point2Wall()->pos.Y - hitinfo.hitWall->pos.Y);
newdist = nx * daang.bsin() + ny * -daang.bcos(); newdist = nx * daang.bsin() + ny * -daang.bcos();
if (abs(nx) > abs(ny)) if (abs(nx) > abs(ny))
hx -= MulScale(nx, newdist, 28); hx -= MulScale(nx, newdist, 28);
else else
hy -= MulScale(ny, newdist, 28); hy -= MulScale(ny, newdist, 28);
} }
else if (hitinfo.hitActor == nullptr) else if (hitinfo.hitActor == nullptr)
{ {
// Push you off the ceiling/floor // Push you off the ceiling/floor
*psect = hitinfo.hitSector; *psect = hitinfo.hitSector;
if (abs(nx) > abs(ny)) if (abs(nx) > abs(ny))
hx -= (nx >> 5); hx -= (nx >> 5);
else else
hy -= (ny >> 5); hy -= (ny >> 5);
} }
else else
{ {
// If you hit a sprite that's not a wall sprite - try again. // If you hit a sprite that's not a wall sprite - try again.
auto hit = hitinfo.hitActor; auto hit = hitinfo.hitActor;
if (!(hit->spr.cstat & CSTAT_SPRITE_ALIGNMENT_WALL)) if (!(hit->spr.cstat & CSTAT_SPRITE_ALIGNMENT_WALL))
{ {
bakcstat = hit->spr.cstat; bakcstat = hit->spr.cstat;
hit->spr.cstat &= ~(CSTAT_SPRITE_BLOCK | CSTAT_SPRITE_BLOCK_HITSCAN); hit->spr.cstat &= ~(CSTAT_SPRITE_BLOCK | CSTAT_SPRITE_BLOCK_HITSCAN);
calcChaseCamPos(px, py, pz, act, psect, ang, horiz, smoothratio); calcChaseCamPos(px, py, pz, act, psect, ang, horiz, smoothratio);
hit->spr.cstat = bakcstat; hit->spr.cstat = bakcstat;
return false; return false;
} }
else else
{ {
// same as wall calculation. // same as wall calculation.
daang = buildang(act->spr.ang - 512); daang = buildang(act->spr.ang - 512);
newdist = nx * daang.bsin() + ny * -daang.bcos(); newdist = nx * daang.bsin() + ny * -daang.bcos();
if (abs(nx) > abs(ny)) if (abs(nx) > abs(ny))
hx -= MulScale(nx, newdist, 28); hx -= MulScale(nx, newdist, 28);
else else
hy -= MulScale(ny, newdist, 28); hy -= MulScale(ny, newdist, 28);
} }
} }
if (abs(nx) > abs(ny)) if (abs(nx) > abs(ny))
newdist = DivScale(hx, nx, 16); newdist = DivScale(hx, nx, 16);
else else
newdist = DivScale(hy, ny, 16); newdist = DivScale(hy, ny, 16);
if (newdist < cameradist) if (newdist < cameradist)
cameradist = newdist; cameradist = newdist;
} }
// Actually move you! (Camerdist is 65536 if nothing is in the way) // Actually move you! (Camerdist is 65536 if nothing is in the way)
*px += MulScale(nx, cameradist, 16); *px += MulScale(nx, cameradist, 16);
*py += MulScale(ny, cameradist, 16); *py += MulScale(ny, cameradist, 16);
*pz += MulScale(nz, cameradist, 16); *pz += MulScale(nz, cameradist, 16);
// Caculate clock using GameTicRate so it increases the same rate on all speed computers. // Caculate clock using GameTicRate so it increases the same rate on all speed computers.
int myclock = PlayClock + MulScale(120 / GameTicRate, int(smoothratio), 16); int myclock = PlayClock + MulScale(120 / GameTicRate, int(smoothratio), 16);
if (cameraclock == INT_MIN) if (cameraclock == INT_MIN)
{ {
// Third person view was just started. // Third person view was just started.
cameraclock = myclock; cameraclock = myclock;
} }
// Slowly increase cameradist until it reaches 65536. // Slowly increase cameradist until it reaches 65536.
cameradist = min(cameradist + ((myclock - cameraclock) << 10), 65536); cameradist = min(cameradist + ((myclock - cameraclock) << 10), 65536);
cameraclock = myclock; cameraclock = myclock;
// Make sure psectnum is correct. // Make sure psectnum is correct.
updatesectorz(*px, *py, *pz, psect); updatesectorz(*px, *py, *pz, psect);
return true; return true;
} }
//========================================================================== //==========================================================================
// //
// consolidated slope calculation // consolidated slope calculation
// //
//========================================================================== //==========================================================================
void calcSlope(const sectortype* sec, float xpos, float ypos, float* pceilz, float* pflorz) void calcSlope(const sectortype* sec, float xpos, float ypos, float* pceilz, float* pflorz)
{ {
int bits = 0; int bits = 0;
if (pceilz) if (pceilz)
{ {
bits |= sec->ceilingstat; bits |= sec->ceilingstat;
*pceilz = float(sec->ceilingz); *pceilz = float(sec->ceilingz);
} }
if (pflorz) if (pflorz)
{ {
bits |= sec->floorstat; bits |= sec->floorstat;
*pflorz = float(sec->floorz); *pflorz = float(sec->floorz);
} }
if ((bits & CSTAT_SECTOR_SLOPE) == CSTAT_SECTOR_SLOPE) if ((bits & CSTAT_SECTOR_SLOPE) == CSTAT_SECTOR_SLOPE)
{ {
auto wal = sec->firstWall(); auto wal = sec->firstWall();
int len = wal->Length(); int len = wal->Length();
if (len != 0) if (len != 0)
{ {
float fac = (wal->deltax() * (float(ypos - wal->pos.Y)) - wal->deltay() * (float(xpos - wal->pos.X))) * (1.f / 256.f) / len; float fac = (wal->deltax() * (float(ypos - wal->pos.Y)) - wal->deltay() * (float(xpos - wal->pos.X))) * (1.f / 256.f) / len;
if (pceilz && sec->ceilingstat & CSTAT_SECTOR_SLOPE) *pceilz += (sec->ceilingheinum * fac); if (pceilz && sec->ceilingstat & CSTAT_SECTOR_SLOPE) *pceilz += (sec->ceilingheinum * fac);
if (pflorz && sec->floorstat & CSTAT_SECTOR_SLOPE) *pflorz += (sec->floorheinum * fac); if (pflorz && sec->floorstat & CSTAT_SECTOR_SLOPE) *pflorz += (sec->floorheinum * fac);
} }
} }
} }
//========================================================================== //==========================================================================
// //
// for the renderer (Polymost variants are in polymost.cpp) // for the renderer (Polymost variants are in polymost.cpp)
// //
//========================================================================== //==========================================================================
void PlanesAtPoint(const sectortype* sec, float dax, float day, float* pceilz, float* pflorz) void PlanesAtPoint(const sectortype* sec, float dax, float day, float* pceilz, float* pflorz)
{ {
calcSlope(sec, dax, day, pceilz, pflorz); calcSlope(sec, dax, day, pceilz, pflorz);
if (pceilz) *pceilz *= -(1 / 256.f); if (pceilz) *pceilz *= -(1 / 256.f);
if (pflorz) *pflorz *= -(1 / 256.f); if (pflorz) *pflorz *= -(1 / 256.f);
} }
//========================================================================== //==========================================================================
// //
// for the games (these are not inlined so that they can inline calcSlope) // for the games (these are not inlined so that they can inline calcSlope)
// //
//========================================================================== //==========================================================================
int getceilzofslopeptr(const sectortype* sec, int dax, int day) int getceilzofslopeptr(const sectortype* sec, int dax, int day)
{ {
float z; float z;
calcSlope(sec, dax, day, &z, nullptr); calcSlope(sec, dax, day, &z, nullptr);
return int(z); return int(z);
} }
int getflorzofslopeptr(const sectortype* sec, int dax, int day) int getflorzofslopeptr(const sectortype* sec, int dax, int day)
{ {
float z; float z;
calcSlope(sec, dax, day, nullptr, &z); calcSlope(sec, dax, day, nullptr, &z);
return int(z); return int(z);
} }
void getzsofslopeptr(const sectortype* sec, int dax, int day, int* ceilz, int* florz) void getzsofslopeptr(const sectortype* sec, int dax, int day, int* ceilz, int* florz)
{ {
float c, f; float c, f;
calcSlope(sec, dax, day, &c, &f); calcSlope(sec, dax, day, &c, &f);
*ceilz = int(c); *ceilz = int(c);
*florz = int(f); *florz = int(f);
} }
//========================================================================== //==========================================================================
// //
// //
// //
//========================================================================== //==========================================================================
int getslopeval(sectortype* sect, int x, int y, int z, int basez) int getslopeval(sectortype* sect, int x, int y, int z, int basez)
{ {
auto wal = sect->firstWall(); auto wal = sect->firstWall();
auto delta = wal->delta(); auto delta = wal->delta();
int i = (y - wal->pos.Y) * delta.X - (x - wal->pos.X) * delta.Y; int i = (y - wal->pos.Y) * delta.X - (x - wal->pos.X) * delta.Y;
return i == 0? 0 : Scale((z - basez) << 8, wal->Length(), i); return i == 0? 0 : Scale((z - basez) << 8, wal->Length(), i);
} }
//========================================================================== //==========================================================================
// //
// Calculate the position of a wall sprite in the world // Calculate the position of a wall sprite in the world
// //
//========================================================================== //==========================================================================
void GetWallSpritePosition(const tspritetype* spr, vec2_t pos, vec2_t* out, bool render) void GetWallSpritePosition(const tspritetype* spr, vec2_t pos, vec2_t* out, bool render)
{ {
auto tex = tileGetTexture(spr->picnum); auto tex = tileGetTexture(spr->picnum);
int width, leftofs; int width, leftofs;
if (render && hw_hightile && TileFiles.tiledata[spr->picnum].hiofs.xsize) if (render && hw_hightile && TileFiles.tiledata[spr->picnum].hiofs.xsize)
{ {
width = TileFiles.tiledata[spr->picnum].hiofs.xsize; width = TileFiles.tiledata[spr->picnum].hiofs.xsize;
leftofs = (TileFiles.tiledata[spr->picnum].hiofs.xoffs + spr->xoffset); leftofs = (TileFiles.tiledata[spr->picnum].hiofs.xoffs + spr->xoffset);
} }
else else
{ {
width = (int)tex->GetDisplayWidth(); width = (int)tex->GetDisplayWidth();
leftofs = ((int)tex->GetDisplayLeftOffset() + spr->xoffset); leftofs = ((int)tex->GetDisplayLeftOffset() + spr->xoffset);
} }
int x = bsin(spr->ang) * spr->xrepeat; int x = bsin(spr->ang) * spr->xrepeat;
int y = -bcos(spr->ang) * spr->xrepeat; int y = -bcos(spr->ang) * spr->xrepeat;
int xoff = leftofs; int xoff = leftofs;
if (spr->cstat & CSTAT_SPRITE_XFLIP) xoff = -xoff; if (spr->cstat & CSTAT_SPRITE_XFLIP) xoff = -xoff;
int origin = (width >> 1) + xoff; int origin = (width >> 1) + xoff;
out[0].X = pos.X - MulScale(x, origin, 16); out[0].X = pos.X - MulScale(x, origin, 16);
out[0].Y = pos.Y - MulScale(y, origin, 16); out[0].Y = pos.Y - MulScale(y, origin, 16);
out[1].X = out[0].X + MulScale(x, width, 16); out[1].X = out[0].X + MulScale(x, width, 16);
out[1].Y = out[0].Y + MulScale(y, width, 16); out[1].Y = out[0].Y + MulScale(y, width, 16);
} }
//========================================================================== //==========================================================================
// //
// Calculate the position of a wall sprite in the world // Calculate the position of a wall sprite in the world
// //
//========================================================================== //==========================================================================
void TGetFlatSpritePosition(const spritetypebase* spr, vec2_t pos, vec2_t* out, int* outz, int heinum, bool render) void TGetFlatSpritePosition(const spritetypebase* spr, vec2_t pos, vec2_t* out, int* outz, int heinum, bool render)
{ {
auto tex = tileGetTexture(spr->picnum); auto tex = tileGetTexture(spr->picnum);
int width, height, leftofs, topofs; int width, height, leftofs, topofs;
int ratio = ksqrt(heinum * heinum + 4096 * 4096); int ratio = ksqrt(heinum * heinum + 4096 * 4096);
int xo = heinum ? 0 : spr->xoffset; int xo = heinum ? 0 : spr->xoffset;
int yo = heinum ? 0 : spr->yoffset; int yo = heinum ? 0 : spr->yoffset;
if (render && hw_hightile && TileFiles.tiledata[spr->picnum].hiofs.xsize) if (render && hw_hightile && TileFiles.tiledata[spr->picnum].hiofs.xsize)
{ {
width = TileFiles.tiledata[spr->picnum].hiofs.xsize * spr->xrepeat; width = TileFiles.tiledata[spr->picnum].hiofs.xsize * spr->xrepeat;
height = TileFiles.tiledata[spr->picnum].hiofs.ysize * spr->yrepeat; height = TileFiles.tiledata[spr->picnum].hiofs.ysize * spr->yrepeat;
leftofs = (TileFiles.tiledata[spr->picnum].hiofs.xoffs + xo) * spr->xrepeat; leftofs = (TileFiles.tiledata[spr->picnum].hiofs.xoffs + xo) * spr->xrepeat;
topofs = (TileFiles.tiledata[spr->picnum].hiofs.yoffs + yo) * spr->yrepeat; topofs = (TileFiles.tiledata[spr->picnum].hiofs.yoffs + yo) * spr->yrepeat;
} }
else else
{ {
width = (int)tex->GetDisplayWidth() * spr->xrepeat; width = (int)tex->GetDisplayWidth() * spr->xrepeat;
height = (int)tex->GetDisplayHeight() * spr->yrepeat; height = (int)tex->GetDisplayHeight() * spr->yrepeat;
leftofs = ((int)tex->GetDisplayLeftOffset() + xo) * spr->xrepeat; leftofs = ((int)tex->GetDisplayLeftOffset() + xo) * spr->xrepeat;
topofs = ((int)tex->GetDisplayTopOffset() + yo) * spr->yrepeat; topofs = ((int)tex->GetDisplayTopOffset() + yo) * spr->yrepeat;
} }
if (spr->cstat & CSTAT_SPRITE_XFLIP) leftofs = -leftofs; if (spr->cstat & CSTAT_SPRITE_XFLIP) leftofs = -leftofs;
if (spr->cstat & CSTAT_SPRITE_YFLIP) topofs = -topofs; if (spr->cstat & CSTAT_SPRITE_YFLIP) topofs = -topofs;
int sprcenterx = (width >> 1) + leftofs; int sprcenterx = (width >> 1) + leftofs;
int sprcentery = (height >> 1) + topofs; int sprcentery = (height >> 1) + topofs;
int cosang = bcos(spr->ang); int cosang = bcos(spr->ang);
int sinang = bsin(spr->ang); int sinang = bsin(spr->ang);
int cosangslope = DivScale(cosang, ratio, 12); int cosangslope = DivScale(cosang, ratio, 12);
int sinangslope = DivScale(sinang, ratio, 12); int sinangslope = DivScale(sinang, ratio, 12);
out[0].X = pos.X + DMulScale(sinang, sprcenterx, cosangslope, sprcentery, 16); out[0].X = pos.X + DMulScale(sinang, sprcenterx, cosangslope, sprcentery, 16);
out[0].Y = pos.Y + DMulScale(sinangslope, sprcentery, -cosang, sprcenterx, 16); out[0].Y = pos.Y + DMulScale(sinangslope, sprcentery, -cosang, sprcenterx, 16);
out[1].X = out[0].X - MulScale(sinang, width, 16); out[1].X = out[0].X - MulScale(sinang, width, 16);
out[1].Y = out[0].Y + MulScale(cosang, width, 16); out[1].Y = out[0].Y + MulScale(cosang, width, 16);
vec2_t sub = { MulScale(cosangslope, height, 16), MulScale(sinangslope, height, 16) }; vec2_t sub = { MulScale(cosangslope, height, 16), MulScale(sinangslope, height, 16) };
out[2] = out[1] - sub; out[2] = out[1] - sub;
out[3] = out[0] - sub; out[3] = out[0] - sub;
if (outz) if (outz)
{ {
if (!heinum) outz[3] = outz[2] = outz[1] = outz[0] = 0; if (!heinum) outz[3] = outz[2] = outz[1] = outz[0] = 0;
else else
{ {
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
{ {
int spos = DMulScale(-sinang, out[i].Y - spr->pos.Y, -cosang, out[i].X - spr->pos.X, 4); int spos = DMulScale(-sinang, out[i].Y - spr->pos.Y, -cosang, out[i].X - spr->pos.X, 4);
outz[i] = MulScale(heinum, spos, 18); outz[i] = MulScale(heinum, spos, 18);
} }
} }
} }
} }
void GetFlatSpritePosition(DCoreActor* actor, vec2_t pos, vec2_t* out, bool render) void GetFlatSpritePosition(DCoreActor* actor, vec2_t pos, vec2_t* out, bool render)
{ {
TGetFlatSpritePosition(&actor->spr, pos, out, nullptr, spriteGetSlope(actor), render); TGetFlatSpritePosition(&actor->spr, pos, out, nullptr, spriteGetSlope(actor), render);
} }
void GetFlatSpritePosition(const tspritetype* spr, vec2_t pos, vec2_t* out, int* outz, bool render) void GetFlatSpritePosition(const tspritetype* spr, vec2_t pos, vec2_t* out, int* outz, bool render)
{ {
TGetFlatSpritePosition(spr, pos, out, outz, tspriteGetSlope(spr), render); TGetFlatSpritePosition(spr, pos, out, outz, tspriteGetSlope(spr), render);
} }
//========================================================================== //==========================================================================
// //
// Check if some walls are set to use rotated textures. // Check if some walls are set to use rotated textures.
// Ideally this should just have been done with texture rotation, // Ideally this should just have been done with texture rotation,
// but the effects on the render code would be too severe due to the alignment mess. // but the effects on the render code would be too severe due to the alignment mess.
// //
//========================================================================== //==========================================================================
void checkRotatedWalls() void checkRotatedWalls()
{ {
for (auto& w : wall) for (auto& w : wall)
{ {
if (w.cstat & CSTAT_WALL_ROTATE_90) if (w.cstat & CSTAT_WALL_ROTATE_90)
{ {
auto& tile = RotTile(w.picnum + animateoffs(w.picnum, 16384)); auto& tile = RotTile(w.picnum + animateoffs(w.picnum, 16384));
if (tile.newtile == -1 && tile.owner == -1) if (tile.newtile == -1 && tile.owner == -1)
{ {
auto owner = w.picnum + animateoffs(w.picnum, 16384); auto owner = w.picnum + animateoffs(w.picnum, 16384);
tile.newtile = TileFiles.tileCreateRotated(owner); tile.newtile = TileFiles.tileCreateRotated(owner);
assert(tile.newtile != -1); assert(tile.newtile != -1);
RotTile(tile.newtile).owner = w.picnum + animateoffs(w.picnum, 16384); RotTile(tile.newtile).owner = w.picnum + animateoffs(w.picnum, 16384);
} }
} }
} }
} }
//========================================================================== //==========================================================================
// //
// check if two sectors share a wall connection // check if two sectors share a wall connection
// //
//========================================================================== //==========================================================================
bool sectorsConnected(int sect1, int sect2) bool sectorsConnected(int sect1, int sect2)
{ {
for (auto& wal : wallsofsector(sect1)) for (auto& wal : wallsofsector(sect1))
{ {
if (wal.nextsector == sect2) return true; if (wal.nextsector == sect2) return true;
} }
return false; return false;
} }
//========================================================================== //==========================================================================
// //
// //
// //
//========================================================================== //==========================================================================
void dragpoint(walltype* startwall, int newx, int newy) void dragpoint(walltype* startwall, int newx, int newy)
{ {
vertexscan(startwall, [&](walltype* wal) vertexscan(startwall, [&](walltype* wal)
{ {
wal->move(newx, newy); wal->move(newx, newy);
wal->sectorp()->exflags |= SECTOREX_DRAGGED; wal->sectorp()->exflags |= SECTOREX_DRAGGED;
}); });
} }
//========================================================================== //==========================================================================
// //
// //
// //
//========================================================================== //==========================================================================
tspritetype* renderAddTsprite(tspritetype* tsprite, int& spritesortcnt, DCoreActor* actor) tspritetype* renderAddTsprite(tspritetype* tsprite, int& spritesortcnt, DCoreActor* actor)
{ {
validateTSpriteSize(tsprite, spritesortcnt); validateTSpriteSize(tsprite, spritesortcnt);
if (spritesortcnt >= MAXSPRITESONSCREEN) return nullptr; if (spritesortcnt >= MAXSPRITESONSCREEN) return nullptr;
auto tspr = &tsprite[spritesortcnt++]; auto tspr = &tsprite[spritesortcnt++];
tspr->pos = actor->spr.pos; tspr->pos = actor->spr.pos;
tspr->cstat = actor->spr.cstat; tspr->cstat = actor->spr.cstat;
tspr->picnum = actor->spr.picnum; tspr->picnum = actor->spr.picnum;
tspr->shade = actor->spr.shade; tspr->shade = actor->spr.shade;
tspr->pal = actor->spr.pal; tspr->pal = actor->spr.pal;
tspr->clipdist = 0; tspr->clipdist = 0;
tspr->blend = actor->spr.blend; tspr->blend = actor->spr.blend;
tspr->xrepeat = actor->spr.xrepeat; tspr->xrepeat = actor->spr.xrepeat;
tspr->yrepeat = actor->spr.yrepeat; tspr->yrepeat = actor->spr.yrepeat;
tspr->xoffset = actor->spr.xoffset; tspr->xoffset = actor->spr.xoffset;
tspr->yoffset = actor->spr.yoffset; tspr->yoffset = actor->spr.yoffset;
tspr->sectp = actor->spr.sectp; tspr->sectp = actor->spr.sectp;
tspr->statnum = actor->spr.statnum; tspr->statnum = actor->spr.statnum;
tspr->ang = actor->spr.ang; tspr->ang = actor->spr.ang;
tspr->xvel = actor->spr.xvel; tspr->xvel = actor->spr.xvel;
tspr->yvel = actor->spr.yvel; tspr->yvel = actor->spr.yvel;
tspr->zvel = actor->spr.zvel; tspr->zvel = actor->spr.zvel;
tspr->lotag = actor->spr.lotag; tspr->lotag = actor->spr.lotag;
tspr->hitag = actor->spr.hitag; tspr->hitag = actor->spr.hitag;
tspr->extra = actor->spr.extra; tspr->extra = actor->spr.extra;
tspr->time = actor->time; tspr->time = actor->time;
tspr->ownerActor = actor; tspr->ownerActor = actor;
// need to copy the slope sprite flag around because for tsprites the bit combination means 'voxel'. // need to copy the slope sprite flag around because for tsprites the bit combination means 'voxel'.
if ((tspr->cstat & CSTAT_SPRITE_ALIGNMENT_MASK) == CSTAT_SPRITE_ALIGNMENT_SLOPE) if ((tspr->cstat & CSTAT_SPRITE_ALIGNMENT_MASK) == CSTAT_SPRITE_ALIGNMENT_SLOPE)
{ {
tspr->cstat &= ~CSTAT_SPRITE_ALIGNMENT_WALL; tspr->cstat &= ~CSTAT_SPRITE_ALIGNMENT_WALL;
tspr->clipdist |= TSPR_SLOPESPRITE; tspr->clipdist |= TSPR_SLOPESPRITE;
} }
return tspr; return tspr;
} }
//========================================================================== //==========================================================================
// //
// vector serializers // vector serializers
// //
//========================================================================== //==========================================================================
FSerializer& Serialize(FSerializer& arc, const char* key, vec2_t& c, vec2_t* def) FSerializer& Serialize(FSerializer& arc, const char* key, vec2_t& c, vec2_t* def)
{ {
if (arc.isWriting() && def && !memcmp(&c, def, sizeof(c))) return arc; if (arc.isWriting() && def && !memcmp(&c, def, sizeof(c))) return arc;
if (arc.BeginObject(key)) if (arc.BeginObject(key))
{ {
arc("x", c.X, def ? &def->X : nullptr) arc("x", c.X, def ? &def->X : nullptr)
("y", c.Y, def ? &def->Y : nullptr) ("y", c.Y, def ? &def->Y : nullptr)
.EndObject(); .EndObject();
} }
return arc; return arc;
} }
FSerializer& Serialize(FSerializer& arc, const char* key, vec3_t& c, vec3_t* def) FSerializer& Serialize(FSerializer& arc, const char* key, vec3_t& c, vec3_t* def)
{ {
if (arc.isWriting() && def && !memcmp(&c, def, sizeof(c))) return arc; if (arc.isWriting() && def && !memcmp(&c, def, sizeof(c))) return arc;
if (arc.BeginObject(key)) if (arc.BeginObject(key))
{ {
arc("x", c.X, def ? &def->X : nullptr) arc("x", c.X, def ? &def->X : nullptr)
("y", c.Y, def ? &def->Y : nullptr) ("y", c.Y, def ? &def->Y : nullptr)
("z", c.Z, def ? &def->Z : nullptr) ("z", c.Z, def ? &def->Z : nullptr)
.EndObject(); .EndObject();
} }
return arc; return arc;
} }

View file

@ -1,406 +1,406 @@
#pragma once #pragma once
#include "gamecontrol.h" #include "gamecontrol.h"
#include "binaryangle.h" #include "binaryangle.h"
#include "build.h" #include "build.h"
#include "coreactor.h" #include "coreactor.h"
// breadth first search, this gets used multiple times throughout the engine, mainly for iterating over sectors. // breadth first search, this gets used multiple times throughout the engine, mainly for iterating over sectors.
// Only works on indices, this has no knowledge of the actual objects being looked at. // Only works on indices, this has no knowledge of the actual objects being looked at.
// All objects of this type operate on the same shared store. Interleaved use is not allowed, nested use is fine. // All objects of this type operate on the same shared store. Interleaved use is not allowed, nested use is fine.
class BFSSearch class BFSSearch
{ {
static inline TArray<unsigned> store; static inline TArray<unsigned> store;
unsigned bitpos; unsigned bitpos;
unsigned startpos; unsigned startpos;
unsigned curpos; unsigned curpos;
public: public:
enum { EOL = ~0u }; enum { EOL = ~0u };
BFSSearch(unsigned datasize, unsigned startnode) BFSSearch(unsigned datasize, unsigned startnode)
{ {
bitpos = store.Size(); bitpos = store.Size();
unsigned bitsize = (datasize + 31) >> 5; unsigned bitsize = (datasize + 31) >> 5;
store.Reserve(bitsize); store.Reserve(bitsize);
memset(&store[bitpos], 0, bitsize*4); memset(&store[bitpos], 0, bitsize*4);
startpos = store.Size(); startpos = store.Size();
curpos = startpos; curpos = startpos;
Set(startnode); Set(startnode);
store.Push(startnode); store.Push(startnode);
} }
// This allows this object to just work as a bit array // This allows this object to just work as a bit array
// which is useful for using its shared storage. // which is useful for using its shared storage.
BFSSearch(unsigned datasize) BFSSearch(unsigned datasize)
{ {
bitpos = store.Size(); bitpos = store.Size();
unsigned bitsize = (datasize + 31) >> 5; unsigned bitsize = (datasize + 31) >> 5;
store.Reserve(bitsize); store.Reserve(bitsize);
memset(&store[bitpos], 0, bitsize * 4); memset(&store[bitpos], 0, bitsize * 4);
} }
~BFSSearch() ~BFSSearch()
{ {
store.Clamp(bitpos); store.Clamp(bitpos);
} }
bool Check(unsigned index) const bool Check(unsigned index) const
{ {
return !!(store[bitpos + (index >> 5)] & (1 << (index & 31))); return !!(store[bitpos + (index >> 5)] & (1 << (index & 31)));
} }
void Set(unsigned index) void Set(unsigned index)
{ {
store[bitpos + (index >> 5)] |= (1 << (index & 31)); store[bitpos + (index >> 5)] |= (1 << (index & 31));
} }
private: private:
public: public:
unsigned GetNext() unsigned GetNext()
{ {
curpos++; curpos++;
if (curpos <= store.Size()) if (curpos <= store.Size())
return store[curpos-1]; return store[curpos-1];
else else
return ~0; return ~0;
} }
void Rewind() void Rewind()
{ {
curpos = startpos; curpos = startpos;
} }
void Add(unsigned elem) void Add(unsigned elem)
{ {
if (!Check(elem)) if (!Check(elem))
{ {
Set(elem); Set(elem);
store.Push(elem); store.Push(elem);
} }
} }
}; };
class BFSSectorSearch : public BFSSearch class BFSSectorSearch : public BFSSearch
{ {
public: public:
BFSSectorSearch(const sectortype* startnode) : BFSSearch(sector.Size(), sector.IndexOf(startnode)) BFSSectorSearch(const sectortype* startnode) : BFSSearch(sector.Size(), sector.IndexOf(startnode))
{ {
} }
bool Check(const sectortype* index) const bool Check(const sectortype* index) const
{ {
return BFSSearch::Check(sector.IndexOf(index)); return BFSSearch::Check(sector.IndexOf(index));
} }
void Set(const sectortype* index) void Set(const sectortype* index)
{ {
BFSSearch::Set(sector.IndexOf(index)); BFSSearch::Set(sector.IndexOf(index));
} }
sectortype* GetNext() sectortype* GetNext()
{ {
unsigned ret = BFSSearch::GetNext(); unsigned ret = BFSSearch::GetNext();
return ret == EOL? nullptr : &sector[ret]; return ret == EOL? nullptr : &sector[ret];
} }
void Add(sectortype* elem) void Add(sectortype* elem)
{ {
BFSSearch::Add(sector.IndexOf(elem)); BFSSearch::Add(sector.IndexOf(elem));
} }
}; };
//========================================================================== //==========================================================================
// //
// scans all vertices equivalent with a given spot and performs some work on them. // scans all vertices equivalent with a given spot and performs some work on them.
// //
//========================================================================== //==========================================================================
template<class func> template<class func>
void vertexscan(walltype* startwall, func mark) void vertexscan(walltype* startwall, func mark)
{ {
BFSSearch walbitmap(wall.Size()); BFSSearch walbitmap(wall.Size());
// first pass: scan the the next-in-loop of the partner // first pass: scan the the next-in-loop of the partner
auto wal = startwall; auto wal = startwall;
do do
{ {
mark(wal); mark(wal);
walbitmap.Set(wall.IndexOf(wal)); walbitmap.Set(wall.IndexOf(wal));
if (wal->nextwall < 0) break; if (wal->nextwall < 0) break;
wal = wal->nextWall()->point2Wall(); wal = wal->nextWall()->point2Wall();
} while (!walbitmap.Check(wall.IndexOf(wal))); } while (!walbitmap.Check(wall.IndexOf(wal)));
// second pass: scan the partner of the previous-in-loop. // second pass: scan the partner of the previous-in-loop.
wal = startwall; wal = startwall;
while (true) while (true)
{ {
auto thelastwall = wal->lastWall(); auto thelastwall = wal->lastWall();
// thelastwall can be null here if the map is bogus. // thelastwall can be null here if the map is bogus.
if (!thelastwall || !thelastwall->twoSided()) break; if (!thelastwall || !thelastwall->twoSided()) break;
wal = thelastwall->nextWall(); wal = thelastwall->nextWall();
if (walbitmap.Check(wall.IndexOf(wal))) break; if (walbitmap.Check(wall.IndexOf(wal))) break;
mark(wal); mark(wal);
walbitmap.Set(wall.IndexOf(wal)); walbitmap.Set(wall.IndexOf(wal));
} }
} }
extern int cameradist, cameraclock; extern int cameradist, cameraclock;
void loaddefinitionsfile(const char* fn, bool cumulative = false, bool maingrp = false); void loaddefinitionsfile(const char* fn, bool cumulative = false, bool maingrp = false);
bool calcChaseCamPos(int* px, int* py, int* pz, DCoreActor* pspr, sectortype** psectnum, binangle ang, fixedhoriz horiz, double const smoothratio); bool calcChaseCamPos(int* px, int* py, int* pz, DCoreActor* pspr, sectortype** psectnum, binangle ang, fixedhoriz horiz, double const smoothratio);
void PlanesAtPoint(const sectortype* sec, float dax, float day, float* ceilz, float* florz); void PlanesAtPoint(const sectortype* sec, float dax, float day, float* ceilz, float* florz);
int getslopeval(sectortype* sect, int x, int y, int z, int planez); int getslopeval(sectortype* sect, int x, int y, int z, int planez);
void setWallSectors(); void setWallSectors();
void GetWallSpritePosition(const tspritetype* spr, vec2_t pos, vec2_t* out, bool render = false); void GetWallSpritePosition(const tspritetype* spr, vec2_t pos, vec2_t* out, bool render = false);
void GetFlatSpritePosition(DCoreActor* spr, vec2_t pos, vec2_t* out, bool render = false); void GetFlatSpritePosition(DCoreActor* spr, vec2_t pos, vec2_t* out, bool render = false);
void GetFlatSpritePosition(const tspritetype* spr, vec2_t pos, vec2_t* out, int* outz = nullptr, bool render = false); void GetFlatSpritePosition(const tspritetype* spr, vec2_t pos, vec2_t* out, int* outz = nullptr, bool render = false);
void checkRotatedWalls(); void checkRotatedWalls();
bool sectorsConnected(int sect1, int sect2); bool sectorsConnected(int sect1, int sect2);
void dragpoint(walltype* wal, int newx, int newy); void dragpoint(walltype* wal, int newx, int newy);
// y is negated so that the orientation is the same as in GZDoom, in order to use its utilities. // y is negated so that the orientation is the same as in GZDoom, in order to use its utilities.
// The render code should NOT use Build coordinates for anything! // The render code should NOT use Build coordinates for anything!
inline double RenderX(int x) inline double RenderX(int x)
{ {
return x * (1 / 16.); return x * (1 / 16.);
} }
inline double RenderY(int y) inline double RenderY(int y)
{ {
return y * (1 / -16.); return y * (1 / -16.);
} }
inline double WallStartX(int wallnum) inline double WallStartX(int wallnum)
{ {
return wall[wallnum].pos.X * (1 / 16.); return wall[wallnum].pos.X * (1 / 16.);
} }
inline double WallStartY(int wallnum) inline double WallStartY(int wallnum)
{ {
return wall[wallnum].pos.Y * (1 / -16.); return wall[wallnum].pos.Y * (1 / -16.);
} }
inline double WallEndX(int wallnum) inline double WallEndX(int wallnum)
{ {
return wall[wallnum].point2Wall()->pos.X * (1 / 16.); return wall[wallnum].point2Wall()->pos.X * (1 / 16.);
} }
inline double WallEndY(int wallnum) inline double WallEndY(int wallnum)
{ {
return wall[wallnum].point2Wall()->pos.Y * (1 / -16.); return wall[wallnum].point2Wall()->pos.Y * (1 / -16.);
} }
inline double WallStartX(const walltype* wallnum) inline double WallStartX(const walltype* wallnum)
{ {
return wallnum->pos.X * (1 / 16.); return wallnum->pos.X * (1 / 16.);
} }
inline double WallStartY(const walltype* wallnum) inline double WallStartY(const walltype* wallnum)
{ {
return wallnum->pos.Y * (1 / -16.); return wallnum->pos.Y * (1 / -16.);
} }
inline DVector2 WallStart(const walltype* wallnum) inline DVector2 WallStart(const walltype* wallnum)
{ {
return { WallStartX(wallnum), WallStartY(wallnum) }; return { WallStartX(wallnum), WallStartY(wallnum) };
} }
inline double WallEndX(const walltype* wallnum) inline double WallEndX(const walltype* wallnum)
{ {
return wallnum->point2Wall()->pos.X * (1 / 16.); return wallnum->point2Wall()->pos.X * (1 / 16.);
} }
inline double WallEndY(const walltype* wallnum) inline double WallEndY(const walltype* wallnum)
{ {
return wallnum->point2Wall()->pos.Y * (1 / -16.); return wallnum->point2Wall()->pos.Y * (1 / -16.);
} }
inline DVector2 WallEnd(const walltype* wallnum) inline DVector2 WallEnd(const walltype* wallnum)
{ {
return { WallEndX(wallnum), WallEndY(wallnum) }; return { WallEndX(wallnum), WallEndY(wallnum) };
} }
inline DVector2 WallDelta(const walltype* wallnum) inline DVector2 WallDelta(const walltype* wallnum)
{ {
return WallEnd(wallnum) - WallStart(wallnum); return WallEnd(wallnum) - WallStart(wallnum);
} }
inline double PointOnLineSide(double x, double y, double linex, double liney, double deltax, double deltay) inline double PointOnLineSide(double x, double y, double linex, double liney, double deltax, double deltay)
{ {
return (x - linex) * deltay - (y - liney) * deltax; return (x - linex) * deltay - (y - liney) * deltax;
} }
inline double PointOnLineSide(const DVector2 &pos, const walltype *line) inline double PointOnLineSide(const DVector2 &pos, const walltype *line)
{ {
return (pos.X - WallStartX(line)) * WallDelta(line).Y - (pos.Y - WallStartY(line)) * WallDelta(line).X; return (pos.X - WallStartX(line)) * WallDelta(line).Y - (pos.Y - WallStartY(line)) * WallDelta(line).X;
} }
template<class T> template<class T>
inline double PointOnLineSide(const TVector2<T>& pos, const TVector2<T>& linestart, const TVector2<T>& lineend) inline double PointOnLineSide(const TVector2<T>& pos, const TVector2<T>& linestart, const TVector2<T>& lineend)
{ {
return (pos.X - linestart.X) * (lineend.Y - linestart.Y) - (pos.Y - linestart.Y) * (lineend.X - linestart.X); return (pos.X - linestart.X) * (lineend.Y - linestart.Y) - (pos.Y - linestart.Y) * (lineend.X - linestart.X);
} }
extern int numshades; extern int numshades;
// Return type is int because this gets passed to variadic functions where structs may produce undefined behavior. // Return type is int because this gets passed to variadic functions where structs may produce undefined behavior.
inline int shadeToLight(int shade) inline int shadeToLight(int shade)
{ {
shade = clamp(shade, 0, numshades - 1); shade = clamp(shade, 0, numshades - 1);
int light = Scale(numshades - 1 - shade, 255, numshades - 1); int light = Scale(numshades - 1 - shade, 255, numshades - 1);
return PalEntry(255, light, light, light); return PalEntry(255, light, light, light);
} }
inline void copyfloorpal(tspritetype* spr, const sectortype* sect) inline void copyfloorpal(tspritetype* spr, const sectortype* sect)
{ {
if (!lookups.noFloorPal(sect->floorpal)) spr->pal = sect->floorpal; if (!lookups.noFloorPal(sect->floorpal)) spr->pal = sect->floorpal;
} }
inline void spriteSetSlope(DCoreActor* actor, int heinum) inline void spriteSetSlope(DCoreActor* actor, int heinum)
{ {
if (actor->spr.cstat & CSTAT_SPRITE_ALIGNMENT_FLOOR) if (actor->spr.cstat & CSTAT_SPRITE_ALIGNMENT_FLOOR)
{ {
actor->spr.xoffset = heinum & 255; actor->spr.xoffset = heinum & 255;
actor->spr.yoffset = (heinum >> 8) & 255; actor->spr.yoffset = (heinum >> 8) & 255;
actor->spr.cstat = (actor->spr.cstat & ~CSTAT_SPRITE_ALIGNMENT_MASK) | (heinum != 0 ? CSTAT_SPRITE_ALIGNMENT_SLOPE : CSTAT_SPRITE_ALIGNMENT_FLOOR); actor->spr.cstat = (actor->spr.cstat & ~CSTAT_SPRITE_ALIGNMENT_MASK) | (heinum != 0 ? CSTAT_SPRITE_ALIGNMENT_SLOPE : CSTAT_SPRITE_ALIGNMENT_FLOOR);
} }
} }
inline int spriteGetSlope(DCoreActor* actor) inline int spriteGetSlope(DCoreActor* actor)
{ {
return ((actor->spr.cstat & CSTAT_SPRITE_ALIGNMENT_MASK) != CSTAT_SPRITE_ALIGNMENT_SLOPE) ? 0 : uint8_t(actor->spr.xoffset) + (uint8_t(actor->spr.yoffset) << 8); return ((actor->spr.cstat & CSTAT_SPRITE_ALIGNMENT_MASK) != CSTAT_SPRITE_ALIGNMENT_SLOPE) ? 0 : uint8_t(actor->spr.xoffset) + (uint8_t(actor->spr.yoffset) << 8);
} }
// same stuff, different flag... // same stuff, different flag...
inline int tspriteGetSlope(const tspritetype* spr) inline int tspriteGetSlope(const tspritetype* spr)
{ {
return !(spr->clipdist & TSPR_SLOPESPRITE) ? 0 : uint8_t(spr->xoffset) + (int8_t(spr->yoffset) << 8); return !(spr->clipdist & TSPR_SLOPESPRITE) ? 0 : uint8_t(spr->xoffset) + (int8_t(spr->yoffset) << 8);
} }
inline int32_t tspriteGetZOfSlope(const tspritetype* tspr, int dax, int day) inline int32_t tspriteGetZOfSlope(const tspritetype* tspr, int dax, int day)
{ {
int heinum = tspriteGetSlope(tspr); int heinum = tspriteGetSlope(tspr);
if (heinum == 0) return tspr->pos.Z; if (heinum == 0) return tspr->pos.Z;
int const j = DMulScale(bsin(tspr->ang + 1024), day - tspr->pos.Y, -bsin(tspr->ang + 512), dax - tspr->pos.X, 4); int const j = DMulScale(bsin(tspr->ang + 1024), day - tspr->pos.Y, -bsin(tspr->ang + 512), dax - tspr->pos.X, 4);
return tspr->pos.Z + MulScale(heinum, j, 18); return tspr->pos.Z + MulScale(heinum, j, 18);
} }
inline int I_GetBuildTime() inline int I_GetBuildTime()
{ {
return I_GetTime(120); return I_GetTime(120);
} }
inline int32_t getangle(walltype* wal) inline int32_t getangle(walltype* wal)
{ {
return getangle( return getangle(
wal->point2Wall()->pos.X - wal->pos.X, wal->point2Wall()->pos.X - wal->pos.X,
wal->point2Wall()->pos.Y - wal->pos.Y); wal->point2Wall()->pos.Y - wal->pos.Y);
} }
inline TArrayView<walltype> wallsofsector(const sectortype* sec) inline TArrayView<walltype> wallsofsector(const sectortype* sec)
{ {
return TArrayView<walltype>(sec->firstWall(), sec->wallnum); return TArrayView<walltype>(sec->firstWall(), sec->wallnum);
} }
inline TArrayView<walltype> wallsofsector(int sec) inline TArrayView<walltype> wallsofsector(int sec)
{ {
return wallsofsector(&sector[sec]); return wallsofsector(&sector[sec]);
} }
// these are mainly meant as refactoring aids to mark function calls to work on. // these are mainly meant as refactoring aids to mark function calls to work on.
inline int wallnum(const walltype* wal) inline int wallnum(const walltype* wal)
{ {
return wall.IndexOf(wal); return wall.IndexOf(wal);
} }
inline int sectnum(const sectortype* sect) inline int sectnum(const sectortype* sect)
{ {
return sector.IndexOf(sect); return sector.IndexOf(sect);
} }
inline double SquareDist(double lx1, double ly1, double lx2, double ly2) inline double SquareDist(double lx1, double ly1, double lx2, double ly2)
{ {
double dx = lx2 - lx1; double dx = lx2 - lx1;
double dy = ly2 - ly1; double dy = ly2 - ly1;
return dx * dx + dy * dy; return dx * dx + dy * dy;
} }
inline DVector2 NearestPointLine(double px, double py, const walltype* wal) inline DVector2 NearestPointLine(double px, double py, const walltype* wal)
{ {
double lx1 = wal->pos.X; double lx1 = wal->pos.X;
double ly1 = wal->pos.Y; double ly1 = wal->pos.Y;
double lx2 = wal->point2Wall()->pos.X; double lx2 = wal->point2Wall()->pos.X;
double ly2 = wal->point2Wall()->pos.Y; double ly2 = wal->point2Wall()->pos.Y;
double wall_length = SquareDist(lx1, ly1, lx2, ly2); double wall_length = SquareDist(lx1, ly1, lx2, ly2);
if (wall_length == 0) return { lx1, ly1 }; if (wall_length == 0) return { lx1, ly1 };
double t = ((px - lx1) * (lx2 - lx1) + (py - ly1) * (ly2 - ly1)) / wall_length; double t = ((px - lx1) * (lx2 - lx1) + (py - ly1) * (ly2 - ly1)) / wall_length;
double xx = lx1 + t * (lx2 - lx1); double xx = lx1 + t * (lx2 - lx1);
double yy = ly1 + t * (ly2 - ly1); double yy = ly1 + t * (ly2 - ly1);
return { xx, yy }; return { xx, yy };
} }
inline double SquareDistToWall(double px, double py, const walltype* wal, DVector2* point = nullptr) inline double SquareDistToWall(double px, double py, const walltype* wal, DVector2* point = nullptr)
{ {
double lx1 = wal->pos.X; double lx1 = wal->pos.X;
double ly1 = wal->pos.Y; double ly1 = wal->pos.Y;
double lx2 = wal->point2Wall()->pos.X; double lx2 = wal->point2Wall()->pos.X;
double ly2 = wal->point2Wall()->pos.Y; double ly2 = wal->point2Wall()->pos.Y;
double wall_length = SquareDist(lx1, ly1, lx2, ly2); double wall_length = SquareDist(lx1, ly1, lx2, ly2);
if (wall_length == 0) return SquareDist(px, py, lx1, ly1); if (wall_length == 0) return SquareDist(px, py, lx1, ly1);
double t = ((px - lx1) * (lx2 - lx1) + (py - ly1) * (ly2 - ly1)) / wall_length; double t = ((px - lx1) * (lx2 - lx1) + (py - ly1) * (ly2 - ly1)) / wall_length;
t = clamp(t, 0., 1.); t = clamp(t, 0., 1.);
double xx = lx1 + t * (lx2 - lx1); double xx = lx1 + t * (lx2 - lx1);
double yy = ly1 + t * (ly2 - ly1); double yy = ly1 + t * (ly2 - ly1);
if (point) *point = { xx, yy }; if (point) *point = { xx, yy };
return SquareDist(px, py, xx, yy); return SquareDist(px, py, xx, yy);
} }
inline double SquareDistToLine(double px, double py, double lx1, double ly1, double lx2, double ly2) inline double SquareDistToLine(double px, double py, double lx1, double ly1, double lx2, double ly2)
{ {
double wall_length = SquareDist(lx1, ly1, lx2, ly2); double wall_length = SquareDist(lx1, ly1, lx2, ly2);
if (wall_length == 0) return SquareDist(px, py, lx1, ly1); if (wall_length == 0) return SquareDist(px, py, lx1, ly1);
double t = ((px - lx1) * (lx2 - lx1) + (py - ly1) * (ly2 - ly1)) / wall_length; double t = ((px - lx1) * (lx2 - lx1) + (py - ly1) * (ly2 - ly1)) / wall_length;
t = clamp(t, 0., 1.); t = clamp(t, 0., 1.);
double xx = lx1 + t * (lx2 - lx1); double xx = lx1 + t * (lx2 - lx1);
double yy = ly1 + t * (ly2 - ly1); double yy = ly1 + t * (ly2 - ly1);
return SquareDist(px, py, xx, yy); return SquareDist(px, py, xx, yy);
} }
inline void alignceilslope(sectortype* sect, int x, int y, int z) inline void alignceilslope(sectortype* sect, int x, int y, int z)
{ {
sect->setceilingslope(getslopeval(sect, x, y, z, sect->ceilingz)); sect->setceilingslope(getslopeval(sect, x, y, z, sect->ceilingz));
} }
inline void alignflorslope(sectortype* sect, int x, int y, int z) inline void alignflorslope(sectortype* sect, int x, int y, int z)
{ {
sect->setfloorslope(getslopeval(sect, x, y, z, sect->floorz)); sect->setfloorslope(getslopeval(sect, x, y, z, sect->floorz));
} }
inline void updatesectorneighbor(int32_t const x, int32_t const y, sectortype* * const sect, int32_t maxDistance = MAXUPDATESECTORDIST) inline void updatesectorneighbor(int32_t const x, int32_t const y, sectortype* * const sect, int32_t maxDistance = MAXUPDATESECTORDIST)
{ {
int sectno = *sect? sector.IndexOf(*sect) : -1; int sectno = *sect? sector.IndexOf(*sect) : -1;
updatesectorneighbor(x, y, &sectno, maxDistance); updatesectorneighbor(x, y, &sectno, maxDistance);
*sect = sectno < 0? nullptr : &sector[sectno]; *sect = sectno < 0? nullptr : &sector[sectno];
} }