Merge branch SRB2:next into disable-powerup-hud

This commit is contained in:
MIDIMan 2024-01-31 19:34:05 +00:00
commit 5bbc1e323a
13 changed files with 275 additions and 253 deletions

View file

@ -55,7 +55,7 @@ static UINT8 *demobuffer = NULL;
static UINT8 *demo_p, *demotime_p;
static UINT8 *demoend;
static UINT8 demoflags;
static UINT16 demoversion;
UINT16 demoversion;
boolean singledemo; // quit after playing a demo from cmdline
boolean demo_start; // don't start playing demo right away
boolean demo_forwardmove_rng; // old demo backwards compatibility
@ -98,7 +98,7 @@ demoghost *ghosts = NULL;
// DEMO RECORDING
//
#define DEMOVERSION 0x0010
#define DEMOVERSION 0x0011
#define DEMOHEADER "\xF0" "SRB2Replay" "\x0F"
#define DF_GHOST 0x01 // This demo contains ghost data too!

View file

@ -25,6 +25,7 @@
// demoplaying back and demo recording
extern boolean demoplayback, titledemo, demorecording, timingdemo;
extern tic_t demostarttime;
extern UINT16 demoversion;
typedef enum
{

View file

@ -116,8 +116,36 @@ void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPt
polygonArray[polygonArraySize].texture = current_texture;
polygonArray[polygonArraySize].shader = shader;
polygonArray[polygonArraySize].horizonSpecial = horizonSpecial;
// default to polygonArraySize so we don't lose order on horizon lines
// (yes, it's supposed to be negative, since we're sorting in that direction)
polygonArray[polygonArraySize].hash = -polygonArraySize;
polygonArraySize++;
if (!(PolyFlags & PF_NoTexture) && !horizonSpecial)
{
// use FNV-1a to hash polygons for later sorting.
INT32 hash = 0x811c9dc5;
#define DIGEST(h, x) h ^= (x); h *= 0x01000193
if (current_texture)
{
DIGEST(hash, current_texture->downloaded);
}
DIGEST(hash, PolyFlags);
DIGEST(hash, pSurf->PolyColor.rgba);
if (cv_glshaders.value && gl_shadersavailable)
{
DIGEST(hash, shader);
DIGEST(hash, pSurf->TintColor.rgba);
DIGEST(hash, pSurf->FadeColor.rgba);
DIGEST(hash, pSurf->LightInfo.light_level);
DIGEST(hash, pSurf->LightInfo.fade_start);
DIGEST(hash, pSurf->LightInfo.fade_end);
}
#undef DIGEST
// remove the sign bit to ensure that skybox and horizon line comes first.
polygonArray[polygonArraySize-1].hash = (hash & INT32_MAX);
}
memcpy(&unsortedVertexArray[unsortedVertexArraySize], pOutVerts, iNumPts * sizeof(FOutVector));
unsortedVertexArraySize += iNumPts;
}
@ -135,84 +163,7 @@ static int comparePolygons(const void *p1, const void *p2)
unsigned int index2 = *(const unsigned int*)p2;
PolygonArrayEntry* poly1 = &polygonArray[index1];
PolygonArrayEntry* poly2 = &polygonArray[index2];
int diff;
INT64 diff64;
UINT32 downloaded1 = 0;
UINT32 downloaded2 = 0;
int shader1 = poly1->shader;
int shader2 = poly2->shader;
// make skywalls and horizon lines first in order
if (poly1->polyFlags & PF_NoTexture || poly1->horizonSpecial)
shader1 = -1;
if (poly2->polyFlags & PF_NoTexture || poly2->horizonSpecial)
shader2 = -1;
diff = shader1 - shader2;
if (diff != 0) return diff;
// skywalls and horizon lines must retain their order for horizon lines to work
if (shader1 == -1 && shader2 == -1)
return index1 - index2;
if (poly1->texture)
downloaded1 = poly1->texture->downloaded; // there should be a opengl texture name here, usable for comparisons
if (poly2->texture)
downloaded2 = poly2->texture->downloaded;
diff64 = downloaded1 - downloaded2;
if (diff64 != 0) return diff64;
diff = poly1->polyFlags - poly2->polyFlags;
if (diff != 0) return diff;
diff64 = poly1->surf.PolyColor.rgba - poly2->surf.PolyColor.rgba;
if (diff64 < 0) return -1; else if (diff64 > 0) return 1;
diff64 = poly1->surf.TintColor.rgba - poly2->surf.TintColor.rgba;
if (diff64 < 0) return -1; else if (diff64 > 0) return 1;
diff64 = poly1->surf.FadeColor.rgba - poly2->surf.FadeColor.rgba;
if (diff64 < 0) return -1; else if (diff64 > 0) return 1;
diff = poly1->surf.LightInfo.light_level - poly2->surf.LightInfo.light_level;
if (diff != 0) return diff;
diff = poly1->surf.LightInfo.fade_start - poly2->surf.LightInfo.fade_start;
if (diff != 0) return diff;
diff = poly1->surf.LightInfo.fade_end - poly2->surf.LightInfo.fade_end;
return diff;
}
static int comparePolygonsNoShaders(const void *p1, const void *p2)
{
unsigned int index1 = *(const unsigned int*)p1;
unsigned int index2 = *(const unsigned int*)p2;
PolygonArrayEntry* poly1 = &polygonArray[index1];
PolygonArrayEntry* poly2 = &polygonArray[index2];
int diff;
INT64 diff64;
GLMipmap_t *texture1 = poly1->texture;
GLMipmap_t *texture2 = poly2->texture;
UINT32 downloaded1 = 0;
UINT32 downloaded2 = 0;
if (poly1->polyFlags & PF_NoTexture || poly1->horizonSpecial)
texture1 = NULL;
if (poly2->polyFlags & PF_NoTexture || poly2->horizonSpecial)
texture2 = NULL;
if (texture1)
downloaded1 = texture1->downloaded; // there should be a opengl texture name here, usable for comparisons
if (texture2)
downloaded2 = texture2->downloaded;
// skywalls and horizon lines must retain their order for horizon lines to work
if (!texture1 && !texture2)
return index1 - index2;
diff64 = downloaded1 - downloaded2;
if (diff64 != 0) return diff64;
diff = poly1->polyFlags - poly2->polyFlags;
if (diff != 0) return diff;
diff64 = poly1->surf.PolyColor.rgba - poly2->surf.PolyColor.rgba;
if (diff64 < 0) return -1; else if (diff64 > 0) return 1;
return 0;
return poly1->hash - poly2->hash;
}
// This function organizes the geometry collected by HWR_ProcessPolygon calls into batches and uses
@ -263,10 +214,7 @@ void HWR_RenderBatches(void)
// sort polygons
PS_START_TIMING(ps_hw_batchsorttime);
if (cv_glshaders.value && gl_shadersavailable)
qsort(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygons);
else
qsort(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygonsNoShaders);
qsort(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygons);
PS_STOP_TIMING(ps_hw_batchsorttime);
// sort order
// 1. shader
@ -362,46 +310,45 @@ void HWR_RenderBatches(void)
{
// check if a state change is required, set the change bools and next vars
int nextIndex = polygonIndexArray[polygonReadPos];
nextShader = polygonArray[nextIndex].shader;
nextTexture = polygonArray[nextIndex].texture;
nextPolyFlags = polygonArray[nextIndex].polyFlags;
nextSurfaceInfo = polygonArray[nextIndex].surf;
if (nextPolyFlags & PF_NoTexture)
nextTexture = 0;
if (currentShader != nextShader && cv_glshaders.value && gl_shadersavailable)
if (polygonArray[index].hash != polygonArray[nextIndex].hash)
{
changeState = true;
changeShader = true;
}
if (currentTexture != nextTexture)
{
changeState = true;
changeTexture = true;
}
if (currentPolyFlags != nextPolyFlags)
{
changeState = true;
changePolyFlags = true;
}
if (cv_glshaders.value && gl_shadersavailable)
{
if (currentSurfaceInfo.PolyColor.rgba != nextSurfaceInfo.PolyColor.rgba ||
currentSurfaceInfo.TintColor.rgba != nextSurfaceInfo.TintColor.rgba ||
currentSurfaceInfo.FadeColor.rgba != nextSurfaceInfo.FadeColor.rgba ||
currentSurfaceInfo.LightInfo.light_level != nextSurfaceInfo.LightInfo.light_level ||
currentSurfaceInfo.LightInfo.fade_start != nextSurfaceInfo.LightInfo.fade_start ||
currentSurfaceInfo.LightInfo.fade_end != nextSurfaceInfo.LightInfo.fade_end)
nextShader = polygonArray[nextIndex].shader;
nextTexture = polygonArray[nextIndex].texture;
nextPolyFlags = polygonArray[nextIndex].polyFlags;
nextSurfaceInfo = polygonArray[nextIndex].surf;
if (nextPolyFlags & PF_NoTexture)
nextTexture = 0;
if (currentShader != nextShader && cv_glshaders.value && gl_shadersavailable)
{
changeState = true;
changeSurfaceInfo = true;
changeShader = true;
}
}
else
{
if (currentSurfaceInfo.PolyColor.rgba != nextSurfaceInfo.PolyColor.rgba)
if (currentTexture != nextTexture)
{
changeState = true;
changeSurfaceInfo = true;
changeTexture = true;
}
if (currentPolyFlags != nextPolyFlags)
{
changePolyFlags = true;
}
if (cv_glshaders.value && gl_shadersavailable)
{
if (currentSurfaceInfo.PolyColor.rgba != nextSurfaceInfo.PolyColor.rgba ||
currentSurfaceInfo.TintColor.rgba != nextSurfaceInfo.TintColor.rgba ||
currentSurfaceInfo.FadeColor.rgba != nextSurfaceInfo.FadeColor.rgba ||
currentSurfaceInfo.LightInfo.light_level != nextSurfaceInfo.LightInfo.light_level ||
currentSurfaceInfo.LightInfo.fade_start != nextSurfaceInfo.LightInfo.fade_start ||
currentSurfaceInfo.LightInfo.fade_end != nextSurfaceInfo.LightInfo.fade_end)
{
changeSurfaceInfo = true;
}
}
else
{
if (currentSurfaceInfo.PolyColor.rgba != nextSurfaceInfo.PolyColor.rgba)
{
changeSurfaceInfo = true;
}
}
}
}
@ -423,36 +370,39 @@ void HWR_RenderBatches(void)
if (stopFlag) break;
// change state according to change bools and next vars, update current vars and reset bools
if (changeShader)
if (changeState)
{
HWD.pfnSetShader(nextShader);
currentShader = nextShader;
changeShader = false;
if (changeShader)
{
HWD.pfnSetShader(nextShader);
currentShader = nextShader;
changeShader = false;
ps_hw_numshaders.value.i++;
}
if (changeTexture)
{
// texture should be already ready for use from calls to SetTexture during batch collection
HWD.pfnSetTexture(nextTexture);
currentTexture = nextTexture;
changeTexture = false;
ps_hw_numshaders.value.i++;
}
if (changeTexture)
{
// texture should be already ready for use from calls to SetTexture during batch collection
HWD.pfnSetTexture(nextTexture);
currentTexture = nextTexture;
changeTexture = false;
ps_hw_numtextures.value.i++;
}
if (changePolyFlags)
{
currentPolyFlags = nextPolyFlags;
changePolyFlags = false;
ps_hw_numtextures.value.i++;
}
if (changePolyFlags)
{
currentPolyFlags = nextPolyFlags;
changePolyFlags = false;
ps_hw_numpolyflags.value.i++;
}
if (changeSurfaceInfo)
{
currentSurfaceInfo = nextSurfaceInfo;
changeSurfaceInfo = false;
ps_hw_numpolyflags.value.i++;
}
if (changeSurfaceInfo)
{
currentSurfaceInfo = nextSurfaceInfo;
changeSurfaceInfo = false;
ps_hw_numcolors.value.i++;
ps_hw_numcolors.value.i++;
}
}
// and that should be it?
}

View file

@ -26,6 +26,7 @@ typedef struct
int shader;
// this tells batching that the plane belongs to a horizon line and must be drawn in correct order with the skywalls
boolean horizonSpecial;
INT32 hash;
} PolygonArrayEntry;
void HWR_StartBatching(void);

View file

@ -1626,17 +1626,22 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
side_t *side = &sides[rover->master->sidenum[0]];
INT16 lineflags;
boolean do_texture_skew;
boolean dont_peg_bottom;
if (rover->master->flags & ML_TFERLINE)
{
size_t linenum = gl_curline->linedef-gl_backsector->lines[0];
newline = rover->master->frontsector->lines[0] + linenum;
side = &sides[newline->sidenum[0]];
lineflags = newline->flags;
do_texture_skew = newline->flags & ML_SKEWTD;
dont_peg_bottom = newline->flags & ML_DONTPEGBOTTOM;
}
else
lineflags = gl_curline->linedef->flags;
{
do_texture_skew = rover->master->flags & ML_SKEWTD;
dont_peg_bottom = gl_curline->linedef->flags & ML_DONTPEGBOTTOM;
}
texnum = R_GetTextureNum(side->midtexture);
@ -1675,15 +1680,14 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
// ...Oh well, anyway, Lower Unpegged now changes pegging of FOFs like in software
// -- Monster Iestyn 26/06/18
fixed_t texturevpeg = side->rowoffset + side->offsety_mid;
boolean attachtobottom = !!(lineflags & ML_DONTPEGBOTTOM);
grTex = HWR_GetTexture(texnum);
xscale = FixedToFloat(side->scalex_mid);
yscale = FixedToFloat(side->scaley_mid);
if (!(lineflags & ML_SKEWTD)) // no skewing
if (!do_texture_skew) // no skewing
{
if (attachtobottom)
if (dont_peg_bottom)
texturevpeg -= (*rover->topheight - *rover->bottomheight) * yscale;
wallVerts[3].t = (((*rover->topheight - h) * yscale) + texturevpeg) * grTex->scaleY;
@ -1693,7 +1697,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
}
else
{
if (!attachtobottom) // skew by top
if (!dont_peg_bottom) // skew by top
{
wallVerts[3].t = wallVerts[2].t = texturevpeg * grTex->scaleY;
wallVerts[0].t = (((h - l) * yscale) + texturevpeg) * grTex->scaleY;

View file

@ -415,16 +415,6 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
//CONS_Printf("\x82%s ", player_names[pnum]);
// If a verified admin banned someone, the server needs to know about it.
// If the playernum isn't zero (the server) then the server needs to record the ban.
if (server && playernum && (msg == KICK_MSG_BANNED || msg == KICK_MSG_CUSTOM_BAN))
{
if (I_Ban && !I_Ban(playernode[(INT32)pnum]))
CONS_Alert(CONS_WARNING, M_GetText("Too many bans! Geez, that's a lot of people you're excluding...\n"));
else
Ban_Add(reason);
}
switch (msg)
{
case KICK_MSG_GO_AWAY:
@ -500,6 +490,16 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
break;
}
// If a verified admin banned someone, the server needs to know about it.
// If the playernum isn't zero (the server) then the server needs to record the ban.
if (server && playernum && (msg == KICK_MSG_BANNED || msg == KICK_MSG_CUSTOM_BAN))
{
if (I_Ban && !I_Ban(playernode[(INT32)pnum]))
CONS_Alert(CONS_WARNING, M_GetText("Too many bans! Geez, that's a lot of people you're excluding...\n"));
else
Ban_Add(msg == KICK_MSG_CUSTOM_BAN ? reason : NULL);
}
if (pnum == consoleplayer)
{
LUA_HookBool(false, HOOK(GameQuit));

View file

@ -134,6 +134,7 @@ typedef union
#include "d_netfil.h"
#include "i_tcp.h"
#include "../m_argv.h"
#include "../i_threads.h"
#include "../doomstat.h"
@ -263,12 +264,33 @@ static const char* inet_ntopA(short af, const void *cp, char *buf, socklen_t len
#ifdef HAVE_MINIUPNPC // based on old XChat patch
static void I_ShutdownUPnP(void);
static void I_InitUPnP(void);
I_mutex upnp_mutex;
static struct UPNPUrls urls;
static struct IGDdatas data;
static char lanaddr[64];
static inline void I_InitUPnP(void)
struct upnpdata
{
int upnpc_started;
};
static struct upnpdata *upnpuser;
static void init_upnpc_once(struct upnpdata *upnpdata);
static void I_InitUPnP(void)
{
upnpuser = malloc(sizeof *upnpuser);
upnpuser->upnpc_started = 0;
I_spawn_thread("init_upnpc_once", (I_thread_fn)init_upnpc_once, upnpuser);
}
static void
init_upnpc_once(struct upnpdata *upnpuserdata)
{
if (upnpuserdata->upnpc_started != 0)
return;
I_lock_mutex(&upnp_mutex);
const char * const deviceTypes[] = {
"urn:schemas-upnp-org:device:InternetGatewayDevice:2",
"urn:schemas-upnp-org:device:InternetGatewayDevice:1",
@ -311,35 +333,43 @@ static inline void I_InitUPnP(void)
I_AddExitFunc(I_ShutdownUPnP);
}
freeUPNPDevlist(devlist);
I_unlock_mutex(upnp_mutex);
}
else if (upnp_error == UPNPDISCOVER_SOCKET_ERROR)
{
CONS_Printf(M_GetText("No UPnP devices discovered\n"));
}
upnpuserdata->upnpc_started =1;
}
static inline void I_UPnP_add(const char * addr, const char *port, const char * servicetype)
{
I_lock_mutex(&upnp_mutex);
if (addr == NULL)
addr = lanaddr;
if (!urls.controlURL || urls.controlURL[0] == '\0')
return;
UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
port, port, addr, "SRB2", servicetype, NULL, NULL);
I_unlock_mutex(upnp_mutex);
}
static inline void I_UPnP_rem(const char *port, const char * servicetype)
{
I_lock_mutex(&upnp_mutex);
if (!urls.controlURL || urls.controlURL[0] == '\0')
return;
UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype,
port, servicetype, NULL);
I_unlock_mutex(upnp_mutex);
}
static void I_ShutdownUPnP(void)
{
I_UPnP_rem(serverport_name, "UDP");
I_lock_mutex(&upnp_mutex);
FreeUPNPUrls(&urls);
I_unlock_mutex(upnp_mutex);
}
#endif

View file

@ -7975,6 +7975,18 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
{
clientGamedata->mapvisited[gamemap-1] |= MV_VISITED;
serverGamedata->mapvisited[gamemap-1] |= MV_VISITED;
M_SilentUpdateUnlockablesAndEmblems(serverGamedata);
if (M_UpdateUnlockablesAndExtraEmblems(clientGamedata))
{
S_StartSound(NULL, sfx_s3k68);
G_SaveGameData(clientGamedata);
}
else if (!reloadinggamestate)
{
G_SaveGameData(clientGamedata);
}
}
levelloading = false;

View file

@ -19,6 +19,7 @@
#include "d_event.h"
#include "netcode/d_net.h"
#include "netcode/net_command.h"
#include "g_demo.h" // demoplayback, demoversion
#include "g_game.h"
#include "p_local.h"
#include "r_fps.h"
@ -7521,49 +7522,46 @@ static void P_NiGHTSMovement(player_t *player)
newangle = 270;
}
else // AngleFixed(R_PointToAngle2()) results in slight inaccuracy! Don't use it unless movement is on both axises.
{
newangle = (INT16)FixedInt(AngleFixed(R_PointToAngle2(0,0, cmd->sidemove*FRACUNIT, cmd->forwardmove*FRACUNIT)));
if (cmd->forwardmove == -36 && cmd->sidemove == 35 && !(demoplayback && demoversion < 0x0011))
newangle = 315; // Hack to compensate for directly down-right returning 314, not 315
}
newangle -= player->viewrollangle / ANG1;
if (newangle < 0 && moved)
newangle = (INT16)(360+newangle);
}
if (player->pflags & PF_DRILLING)
thrustfactor = 2;
else
{
thrustfactor = 8;
// Decelerate while turning normally.
if (moved && player->flyangle != newangle && player->speed > 12000)
player->speed -= 60;
}
for (i = 0; i < thrustfactor; i++)
{
if (moved && player->flyangle != newangle)
{
INT32 anglediff = (((newangle-player->flyangle)+360)%360);
INT32 angledif2 = (((player->flyangle-newangle)+360)%360);
// "player->flyangle" is our current angle, "newangle" is where we want to go
INT32 anglediff = ((newangle - player->flyangle) + 360) % 360; // "+360" and then "%360" wraps it to 0-359
// player->flyangle is the one to move
// newangle is the "move to"
if (anglediff == 0 && angledif2 == 0)
break;
// How sharply can we turn?
if (player->pflags & PF_DRILLING)
thrustfactor = 2;
else
{
thrustfactor = 8;
if (player->speed > 12000) // Decelerate while turning normally
player->speed -= 60;
}
if (anglediff>angledif2)
player->flyangle--;
else // if (anglediff<angledif2)
player->flyangle++;
// Now, turn!
if (anglediff <= thrustfactor || anglediff >= (360-thrustfactor))
player->flyangle = newangle;
else if (anglediff <= 180)
player->flyangle += thrustfactor;
else
player->flyangle -= thrustfactor;
player->flyangle = (player->flyangle + 360) % 360; // Buff out negatives, >360 angles...
}
// Buff out negatives, >360 angles...
player->flyangle = ((player->flyangle + 360) % 360);
}
if (!(player->speed)
&& cmd->forwardmove == 0)
if (player->speed == 0 && cmd->forwardmove == 0 && (cmd->sidemove == 0 || (demoplayback && demoversion < 0x0011)))
still = true;
// No more bumper braking
@ -7724,6 +7722,9 @@ static void P_NiGHTSMovement(player_t *player)
visangle += 180;
}
if (player->mo->eflags & MFE_VERTICALFLIP) // Flip the roll angle in reverse gravity
visangle *= -1;
rollangle = FixedAngle(visangle<<FRACBITS);
}
}

View file

@ -1023,26 +1023,43 @@ void R_Init(void)
boolean R_IsPointInSector(sector_t *sector, fixed_t x, fixed_t y)
{
size_t i;
line_t *closest = NULL;
fixed_t closestdist = INT32_MAX;
size_t passes = 0;
for (i = 0; i < sector->linecount; i++)
{
vertex_t v;
fixed_t dist;
line_t *line = sector->lines[i];
vertex_t *v1, *v2;
// find the line closest to the point we're looking for.
P_ClosestPointOnLine(x, y, sector->lines[i], &v);
dist = R_PointToDist2(0, 0, v.x - x, v.y - y);
if (dist < closestdist)
if (line->frontsector == line->backsector)
continue;
v1 = line->v1;
v2 = line->v2;
// make sure v1 is below v2
if (v1->y > v2->y)
{
closest = sector->lines[i];
closestdist = dist;
vertex_t *tmp = v1;
v1 = v2;
v2 = tmp;
}
else if (v1->y == v2->y)
// horizontal line, we can't match this
continue;
if (v1->y < y && y <= v2->y)
{
// if the y axis in inside the line, find the point where we intersect on the x axis...
fixed_t vx = v1->x + (INT64)(v2->x - v1->x) * (y - v1->y) / (v2->y - v1->y);
// ...and if that point is to the left of the point, count it as inside.
if (vx < x)
passes++;
}
}
// if the side of the closest line is in this sector, we're inside of it.
return P_PointOnLineSide(x, y, closest) == 0 ? closest->frontsector == sector : closest->backsector == sector;
// and odd number of passes means we're inside the polygon.
return passes % 2;
}
//
@ -1201,7 +1218,7 @@ void R_SetupFrame(player_t *player)
newview->x += quake.x;
newview->y += quake.y;
if (r_viewmobj->subsector)
if (!P_MobjWasRemoved(r_viewmobj) && r_viewmobj->subsector)
newview->sector = r_viewmobj->subsector->sector;
else
newview->sector = R_PointInSubsector(newview->x, newview->y)->sector;

View file

@ -543,7 +543,6 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
lightlist_t *light;
r_lightlist_t *rlight;
INT32 range;
line_t *newline = NULL;
// Render FOF sides kinda like normal sides, with the frac and step and everything
// NOTE: INT64 instead of fixed_t because overflow concerns
INT64 top_frac, top_step, bottom_frac, bottom_step;
@ -553,7 +552,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
fixed_t left_top, left_bottom; // needed here for slope skewing
pslope_t *skewslope = NULL;
boolean do_texture_skew;
INT16 lineflags;
boolean dont_peg_bottom;
fixed_t wall_scalex, wall_scaley;
void (*colfunc_2s) (column_t *);
@ -573,12 +572,16 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
if (pfloor->master->flags & ML_TFERLINE)
{
size_t linenum = curline->linedef-backsector->lines[0];
newline = pfloor->master->frontsector->lines[0] + linenum;
line_t *newline = pfloor->master->frontsector->lines[0] + linenum;
sidedef = &sides[newline->sidenum[0]];
lineflags = newline->flags;
do_texture_skew = newline->flags & ML_SKEWTD;
dont_peg_bottom = newline->flags & ML_DONTPEGBOTTOM;
}
else
lineflags = curline->linedef->flags;
{
do_texture_skew = pfloor->master->flags & ML_SKEWTD;
dont_peg_bottom = curline->linedef->flags & ML_DONTPEGBOTTOM;
}
texnum = R_GetTextureNum(sidedef->midtexture);
@ -756,8 +759,6 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
left_top = P_GetFFloorTopZAt (pfloor, ds->leftpos.x, ds->leftpos.y) - viewz;
left_bottom = P_GetFFloorBottomZAt(pfloor, ds->leftpos.x, ds->leftpos.y) - viewz;
do_texture_skew = lineflags & ML_SKEWTD;
if (do_texture_skew)
{
skewslope = *pfloor->t_slope; // skew using top slope by default
@ -768,7 +769,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
offsetvalue = sidedef->rowoffset + sidedef->offsety_mid;
if (lineflags & ML_DONTPEGBOTTOM)
if (dont_peg_bottom)
{
if (do_texture_skew)
{

View file

@ -3496,7 +3496,7 @@ boolean R_ThingVisible (mobj_t *thing)
(thing->sprite == SPR_NULL) || // Don't draw null-sprites
(thing->flags2 & MF2_DONTDRAW) || // Don't draw MF2_LINKDRAW objects
(thing->drawonlyforplayer && thing->drawonlyforplayer != viewplayer) || // Don't draw other players' personal objects
(r_viewmobj && (
(!P_MobjWasRemoved(r_viewmobj) && (
(r_viewmobj == thing) || // Don't draw first-person players or awayviewmobj objects
(r_viewmobj->player && r_viewmobj->player->followmobj == thing) || // Don't draw first-person players' followmobj
(r_viewmobj == thing->dontdrawforviewmobj) // Don't draw objects that are hidden for the current view

View file

@ -1785,46 +1785,49 @@ static void ST_drawNightsRecords(void)
static void ST_drawNiGHTSLink(void)
{
static INT32 prevsel[2] = {0, 0}, prevtime[2] = {0, 0};
const UINT8 q = ((splitscreen && stplyr == &players[secondarydisplayplayer]) ? 1 : 0);
INT32 sel = ((stplyr->linkcount-1) / 5) % NUMLINKCOLORS, aflag = V_PERPLAYER, mag = ((stplyr->linkcount-1 >= 300) ? (stplyr->linkcount-1 >= 600) ? 2 : 1 : 0);
skincolornum_t colornum;
fixed_t x, y, scale;
if (sel != prevsel[q])
if (stplyr->linkcount != 0) // Don't show a faint 4294967295 link, even when debugging
{
prevsel[q] = sel;
prevtime[q] = 2 + mag;
static INT32 prevsel[2] = {0, 0}, prevtime[2] = {0, 0};
const UINT8 q = ((splitscreen && stplyr == &players[secondarydisplayplayer]) ? 1 : 0);
INT32 sel = ((stplyr->linkcount-1) / 5) % NUMLINKCOLORS, aflag = V_PERPLAYER, mag = ((stplyr->linkcount-1 >= 300) ? (stplyr->linkcount-1 >= 600) ? 2 : 1 : 0);
skincolornum_t colornum;
fixed_t x, y, scale;
if (sel != prevsel[q])
{
prevsel[q] = sel;
prevtime[q] = 2 + mag;
}
if (stplyr->powers[pw_nights_linkfreeze] && (!(stplyr->powers[pw_nights_linkfreeze] & 2) || (stplyr->powers[pw_nights_linkfreeze] > flashingtics)))
colornum = SKINCOLOR_ICY;
else
colornum = linkColor[mag][sel];
aflag |= ((stplyr->linktimer < (UINT32)nightslinktics/3)
? (9 - 9*stplyr->linktimer/(nightslinktics/3)) << V_ALPHASHIFT
: 0);
y = (160+11)<<FRACBITS;
aflag |= V_SNAPTOBOTTOM;
x = (160+4)<<FRACBITS;
if (prevtime[q])
{
scale = ((32 + prevtime[q])<<FRACBITS)/32;
prevtime[q]--;
}
else
scale = FRACUNIT;
y -= (11*scale);
ST_DrawNightsOverlayNum(x-(4*scale), y, scale, aflag, (stplyr->linkcount-1), nightsnum, colornum);
V_DrawFixedPatch(x+(4*scale), y, scale, aflag, nightslink,
colornum == 0 ? colormaps : R_GetTranslationColormap(TC_DEFAULT, colornum, GTC_CACHE));
}
if (stplyr->powers[pw_nights_linkfreeze] && (!(stplyr->powers[pw_nights_linkfreeze] & 2) || (stplyr->powers[pw_nights_linkfreeze] > flashingtics)))
colornum = SKINCOLOR_ICY;
else
colornum = linkColor[mag][sel];
aflag |= ((stplyr->linktimer < (UINT32)nightslinktics/3)
? (9 - 9*stplyr->linktimer/(nightslinktics/3)) << V_ALPHASHIFT
: 0);
y = (160+11)<<FRACBITS;
aflag |= V_SNAPTOBOTTOM;
x = (160+4)<<FRACBITS;
if (prevtime[q])
{
scale = ((32 + prevtime[q])<<FRACBITS)/32;
prevtime[q]--;
}
else
scale = FRACUNIT;
y -= (11*scale);
ST_DrawNightsOverlayNum(x-(4*scale), y, scale, aflag, (stplyr->linkcount-1), nightsnum, colornum);
V_DrawFixedPatch(x+(4*scale), y, scale, aflag, nightslink,
colornum == 0 ? colormaps : R_GetTranslationColormap(TC_DEFAULT, colornum, GTC_CACHE));
// Show remaining link time left in debug
if (cv_debug & DBG_NIGHTSBASIC)
V_DrawCenteredString(BASEVIDWIDTH/2, 180, V_SNAPTOBOTTOM, va("End in %d.%02d", stplyr->linktimer/TICRATE, G_TicsToCentiseconds(stplyr->linktimer)));
@ -1854,13 +1857,15 @@ static void ST_drawNiGHTSHUD(void)
for (dfill = 0; dfill < stplyr->drillmeter/20 && dfill < 96; ++dfill)
V_DrawScaledPatch(locx + 2 + dfill, locy + 3, V_PERPLAYER|V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_HUDTRANS, drillfill[fillpatch]);
// Display actual drill amount and bumper time
// Display actual flyangle, drill amount, and bumper time
if (!splitscreen && (cv_debug & DBG_NIGHTSBASIC))
{
V_DrawString(locx, locy - 16, V_MONOSPACE, va("ANGLE: %3d", stplyr->flyangle));
if (stplyr->bumpertime)
V_DrawString(locx, locy - 8, V_REDMAP|V_MONOSPACE, va("BUMPER: 0.%02d", G_TicsToCentiseconds(stplyr->bumpertime)));
else
V_DrawString(locx, locy - 8, V_MONOSPACE, va("Drill: %3d%%", (stplyr->drillmeter*100)/(96*20)));
V_DrawString(locx, locy - 8, V_MONOSPACE, va("DRILL: %3d%%", (stplyr->drillmeter*100)/(96*20)));
}
}