mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-11 15:21:51 +00:00
This commit is contained in:
commit
de5f5a1221
30 changed files with 628 additions and 554 deletions
|
@ -1150,6 +1150,7 @@ set (PCH_SOURCES
|
||||||
p_pusher.cpp
|
p_pusher.cpp
|
||||||
p_saveg.cpp
|
p_saveg.cpp
|
||||||
p_scroll.cpp
|
p_scroll.cpp
|
||||||
|
p_secnodes.cpp
|
||||||
p_sectors.cpp
|
p_sectors.cpp
|
||||||
p_setup.cpp
|
p_setup.cpp
|
||||||
p_sight.cpp
|
p_sight.cpp
|
||||||
|
|
|
@ -1148,8 +1148,8 @@ public:
|
||||||
|
|
||||||
// a linked list of sectors where this object appears
|
// a linked list of sectors where this object appears
|
||||||
struct msecnode_t *touching_sectorlist; // phares 3/14/98
|
struct msecnode_t *touching_sectorlist; // phares 3/14/98
|
||||||
struct msecnode_t *render_sectorlist; // same for cross-sectorportal rendering
|
struct msecnode_t *touching_sectorportallist; // same for cross-sectorportal rendering
|
||||||
struct portnode_t *render_portallist; // and for cross-lineportal
|
struct portnode_t *touching_lineportallist; // and for cross-lineportal
|
||||||
struct msecnode_t *touching_rendersectors; // this is the list of sectors that this thing interesects with it's max(radius, renderradius).
|
struct msecnode_t *touching_rendersectors; // this is the list of sectors that this thing interesects with it's max(radius, renderradius).
|
||||||
int validcount;
|
int validcount;
|
||||||
|
|
||||||
|
|
|
@ -302,9 +302,9 @@ static void PrepareSectorData()
|
||||||
static void PrepareTransparentDoors(sector_t * sector)
|
static void PrepareTransparentDoors(sector_t * sector)
|
||||||
{
|
{
|
||||||
bool solidwall=false;
|
bool solidwall=false;
|
||||||
int notextures=0;
|
unsigned int notextures=0;
|
||||||
int nobtextures=0;
|
unsigned int nobtextures=0;
|
||||||
int selfref=0;
|
unsigned int selfref=0;
|
||||||
sector_t * nextsec=NULL;
|
sector_t * nextsec=NULL;
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
|
|
|
@ -125,7 +125,7 @@ int gl_CheckSpriteGlow(sector_t *sector, int lightlevel, const DVector3 &pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (c != -1)
|
else if (c != ~0u)
|
||||||
{
|
{
|
||||||
bottomglowcolor[0] = c.r / 255.f;
|
bottomglowcolor[0] = c.r / 255.f;
|
||||||
bottomglowcolor[1] = c.g / 255.f;
|
bottomglowcolor[1] = c.g / 255.f;
|
||||||
|
@ -171,7 +171,7 @@ bool gl_GetWallGlow(sector_t *sector, float *topglowcolor, float *bottomglowcolo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (c != -1)
|
else if (c != ~0u)
|
||||||
{
|
{
|
||||||
topglowcolor[0] = c.r / 255.f;
|
topglowcolor[0] = c.r / 255.f;
|
||||||
topglowcolor[1] = c.g / 255.f;
|
topglowcolor[1] = c.g / 255.f;
|
||||||
|
@ -195,7 +195,7 @@ bool gl_GetWallGlow(sector_t *sector, float *topglowcolor, float *bottomglowcolo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (c != -1)
|
else if (c != ~0u)
|
||||||
{
|
{
|
||||||
bottomglowcolor[0] = c.r / 255.f;
|
bottomglowcolor[0] = c.r / 255.f;
|
||||||
bottomglowcolor[1] = c.g / 255.f;
|
bottomglowcolor[1] = c.g / 255.f;
|
||||||
|
|
|
@ -48,9 +48,9 @@ static inline uint32_t rgb_to_yuv(uint32_t c)
|
||||||
|
|
||||||
/* Test if there is difference in color */
|
/* Test if there is difference in color */
|
||||||
static inline int yuv_diff(uint32_t yuv1, uint32_t yuv2) {
|
static inline int yuv_diff(uint32_t yuv1, uint32_t yuv2) {
|
||||||
return (( abs((int64_t)(yuv1 & Ymask) - (int64_t)(yuv2 & Ymask)) > trY ) ||
|
return (( abs((int32_t)(yuv1 & Ymask) - (int32_t)(yuv2 & Ymask)) > trY ) ||
|
||||||
( abs((int64_t)(yuv1 & Umask) - (int64_t)(yuv2 & Umask)) > trU ) ||
|
( abs((int32_t)(yuv1 & Umask) - (int32_t)(yuv2 & Umask)) > trU ) ||
|
||||||
( abs((int64_t)(yuv1 & Vmask) - (int64_t)(yuv2 & Vmask)) > trV ) );
|
( abs((int32_t)(yuv1 & Vmask) - (int32_t)(yuv2 & Vmask)) > trV ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int Diff(uint32_t c1, uint32_t c2)
|
static inline int Diff(uint32_t c1, uint32_t c2)
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#include "v_palette.h"
|
#include "v_palette.h"
|
||||||
#include "r_data/colormaps.h"
|
#include "r_data/colormaps.h"
|
||||||
|
|
||||||
extern DWORD gl_fixedcolormap;
|
extern int gl_fixedcolormap;
|
||||||
|
|
||||||
struct lightlist_t;
|
struct lightlist_t;
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ inline bool gl_isWhite(PalEntry color)
|
||||||
return color.r + color.g + color.b == 3*0xff;
|
return color.r + color.g + color.b == 3*0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern DWORD gl_fixedcolormap;
|
extern int gl_fixedcolormap;
|
||||||
|
|
||||||
inline bool gl_isFullbright(PalEntry color, int lightlevel)
|
inline bool gl_isFullbright(PalEntry color, int lightlevel)
|
||||||
{
|
{
|
||||||
|
|
|
@ -323,7 +323,7 @@ void FGLRenderer::UpdateCameraExposure()
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
|
||||||
// Find the average value:
|
// Find the average value:
|
||||||
for (int i = 0; i + 1 < mBuffers->ExposureLevels.Size(); i++)
|
for (unsigned int i = 0; i + 1 < mBuffers->ExposureLevels.Size(); i++)
|
||||||
{
|
{
|
||||||
const auto &level = mBuffers->ExposureLevels[i];
|
const auto &level = mBuffers->ExposureLevels[i];
|
||||||
const auto &next = mBuffers->ExposureLevels[i + 1];
|
const auto &next = mBuffers->ExposureLevels[i + 1];
|
||||||
|
|
|
@ -448,7 +448,7 @@ void FGLRenderBuffers::CreateExposureLevels(int width, int height)
|
||||||
|
|
||||||
void FGLRenderBuffers::CreateEyeBuffers(int eye)
|
void FGLRenderBuffers::CreateEyeBuffers(int eye)
|
||||||
{
|
{
|
||||||
if (mEyeFBs.Size() > eye)
|
if (mEyeFBs.Size() > unsigned(eye))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
GLint activeTex, textureBinding, frameBufferBinding;
|
GLint activeTex, textureBinding, frameBufferBinding;
|
||||||
|
@ -457,7 +457,7 @@ void FGLRenderBuffers::CreateEyeBuffers(int eye)
|
||||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, &textureBinding);
|
glGetIntegerv(GL_TEXTURE_BINDING_2D, &textureBinding);
|
||||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &frameBufferBinding);
|
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &frameBufferBinding);
|
||||||
|
|
||||||
while (mEyeFBs.Size() <= eye)
|
while (mEyeFBs.Size() <= unsigned(eye))
|
||||||
{
|
{
|
||||||
GLuint texture = Create2DTexture("EyeTexture", GL_RGBA16F, mWidth, mHeight);
|
GLuint texture = Create2DTexture("EyeTexture", GL_RGBA16F, mWidth, mHeight);
|
||||||
mEyeTextures.Push(texture);
|
mEyeTextures.Push(texture);
|
||||||
|
@ -482,7 +482,7 @@ GLuint FGLRenderBuffers::Create2DTexture(const FString &name, GLuint format, int
|
||||||
glBindTexture(GL_TEXTURE_2D, handle);
|
glBindTexture(GL_TEXTURE_2D, handle);
|
||||||
FGLDebug::LabelObject(GL_TEXTURE, handle, name);
|
FGLDebug::LabelObject(GL_TEXTURE, handle, name);
|
||||||
|
|
||||||
GLenum dataformat, datatype;
|
GLenum dataformat = 0, datatype = 0;
|
||||||
switch (format)
|
switch (format)
|
||||||
{
|
{
|
||||||
case GL_RGBA8: dataformat = GL_RGBA; datatype = GL_UNSIGNED_BYTE; break;
|
case GL_RGBA8: dataformat = GL_RGBA; datatype = GL_UNSIGNED_BYTE; break;
|
||||||
|
|
|
@ -383,7 +383,7 @@ static inline void RenderThings(subsector_t * sub, sector_t * sector)
|
||||||
GLRenderer->ProcessSprite(thing, sector, false);
|
GLRenderer->ProcessSprite(thing, sector, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (msecnode_t *node = sec->render_thinglist; node; node = node->m_snext)
|
for (msecnode_t *node = sec->sectorportal_thinglist; node; node = node->m_snext)
|
||||||
{
|
{
|
||||||
AActor *thing = node->m_thing;
|
AActor *thing = node->m_thing;
|
||||||
FIntCVar *cvar = thing->GetClass()->distancecheck;
|
FIntCVar *cvar = thing->GetClass()->distancecheck;
|
||||||
|
|
|
@ -88,7 +88,7 @@ extern int viewpitch;
|
||||||
extern bool NoInterpolateView;
|
extern bool NoInterpolateView;
|
||||||
extern bool r_showviewer;
|
extern bool r_showviewer;
|
||||||
|
|
||||||
DWORD gl_fixedcolormap;
|
int gl_fixedcolormap;
|
||||||
area_t in_area;
|
area_t in_area;
|
||||||
TArray<BYTE> currentmapsection;
|
TArray<BYTE> currentmapsection;
|
||||||
int camtexcount;
|
int camtexcount;
|
||||||
|
|
|
@ -1189,7 +1189,7 @@ void gl_RenderActorsInPortal(FGLLinePortal *glport)
|
||||||
if (port2 != nullptr && port->mDestination == port2->mOrigin && port->mOrigin == port2->mDestination)
|
if (port2 != nullptr && port->mDestination == port2->mOrigin && port->mOrigin == port2->mDestination)
|
||||||
{
|
{
|
||||||
|
|
||||||
for (portnode_t *node = port->render_thinglist; node != nullptr; node = node->m_snext)
|
for (portnode_t *node = port->lineportal_thinglist; node != nullptr; node = node->m_snext)
|
||||||
{
|
{
|
||||||
AActor *th = node->m_thing;
|
AActor *th = node->m_thing;
|
||||||
|
|
||||||
|
|
|
@ -1245,7 +1245,7 @@ void GLWall::ClipFFloors(seg_t * seg, F3DFloor * ffloor, sector_t * frontsector,
|
||||||
{
|
{
|
||||||
TArray<F3DFloor *> & frontffloors = frontsector->e->XFloor.ffloors;
|
TArray<F3DFloor *> & frontffloors = frontsector->e->XFloor.ffloors;
|
||||||
|
|
||||||
int flags = ffloor->flags & (FF_SWIMMABLE | FF_TRANSLUCENT);
|
const unsigned int flags = ffloor->flags & (FF_SWIMMABLE | FF_TRANSLUCENT);
|
||||||
|
|
||||||
for (unsigned int i = 0; i < frontffloors.Size(); i++)
|
for (unsigned int i = 0; i < frontffloors.Size(); i++)
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
class FPresentShaderBase
|
class FPresentShaderBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
virtual ~FPresentShaderBase() {}
|
||||||
virtual void Bind() = 0;
|
virtual void Bind() = 0;
|
||||||
|
|
||||||
FBufferedUniform1f InvGamma;
|
FBufferedUniform1f InvGamma;
|
||||||
|
|
|
@ -143,7 +143,7 @@ void FGLDebug::SetupBreakpointMode()
|
||||||
|
|
||||||
void FGLDebug::UpdateLoggingLevel()
|
void FGLDebug::UpdateLoggingLevel()
|
||||||
{
|
{
|
||||||
int level = gl_debug_level;
|
const GLenum level = gl_debug_level;
|
||||||
if (level != mCurrentLevel)
|
if (level != mCurrentLevel)
|
||||||
{
|
{
|
||||||
glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_HIGH, 0, nullptr, level > 0);
|
glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_HIGH, 0, nullptr, level > 0);
|
||||||
|
|
|
@ -285,7 +285,7 @@ const FHardwareTexture *FGLTexture::Bind(int texunit, int clampmode, int transla
|
||||||
if (translation <= 0) translation = -translation;
|
if (translation <= 0) translation = -translation;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
alphatrans = (gl.legacyMode && translation == TRANSLATION(TRANSLATION_Standard, 8));
|
alphatrans = (gl.legacyMode && DWORD(translation) == TRANSLATION(TRANSLATION_Standard, 8));
|
||||||
translation = GLTranslationPalette::GetInternalTranslation(translation);
|
translation = GLTranslationPalette::GetInternalTranslation(translation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,13 @@ extern double bmaporgx;
|
||||||
extern double bmaporgy; // origin of block map
|
extern double bmaporgy; // origin of block map
|
||||||
extern FBlockNode** blocklinks; // for thing chains
|
extern FBlockNode** blocklinks; // for thing chains
|
||||||
|
|
||||||
|
// mapblocks are used to check movement
|
||||||
|
// against lines and things
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
MAPBLOCKUNITS = 128
|
||||||
|
};
|
||||||
|
|
||||||
inline int GetBlockX(double xpos)
|
inline int GetBlockX(double xpos)
|
||||||
{
|
{
|
||||||
return int((xpos - bmaporgx) / MAPBLOCKUNITS);
|
return int((xpos - bmaporgx) / MAPBLOCKUNITS);
|
||||||
|
|
|
@ -38,9 +38,11 @@ class APlayerPawn;
|
||||||
struct line_t;
|
struct line_t;
|
||||||
struct sector_t;
|
struct sector_t;
|
||||||
struct msecnode_t;
|
struct msecnode_t;
|
||||||
|
struct portnode_t;
|
||||||
struct secplane_t;
|
struct secplane_t;
|
||||||
struct FCheckPosition;
|
struct FCheckPosition;
|
||||||
struct FTranslatedLineTarget;
|
struct FTranslatedLineTarget;
|
||||||
|
struct FLinePortal;
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
@ -48,10 +50,6 @@ struct FTranslatedLineTarget;
|
||||||
|
|
||||||
#define BONUSADD 6
|
#define BONUSADD 6
|
||||||
|
|
||||||
// mapblocks are used to check movement
|
|
||||||
// against lines and things
|
|
||||||
#define MAPBLOCKUNITS 128
|
|
||||||
|
|
||||||
// Inspired by Maes
|
// Inspired by Maes
|
||||||
extern int bmapnegx;
|
extern int bmapnegx;
|
||||||
extern int bmapnegy;
|
extern int bmapnegy;
|
||||||
|
@ -393,8 +391,14 @@ int P_RadiusAttack (AActor *spot, AActor *source, int damage, int distance,
|
||||||
FName damageType, int flags, int fulldamagedistance=0);
|
FName damageType, int flags, int fulldamagedistance=0);
|
||||||
|
|
||||||
void P_DelSeclist(msecnode_t *, msecnode_t *sector_t::*seclisthead);
|
void P_DelSeclist(msecnode_t *, msecnode_t *sector_t::*seclisthead);
|
||||||
msecnode_t *P_AddSecnode(sector_t *s, AActor *thing, msecnode_t *nextnode, msecnode_t *&sec_thinglist);
|
void P_DelSeclist(portnode_t *, portnode_t *FLinePortal::*seclisthead);
|
||||||
msecnode_t* P_DelSecnode(msecnode_t *, msecnode_t *sector_t::*head);
|
|
||||||
|
template<class nodetype, class linktype>
|
||||||
|
nodetype *P_AddSecnode(linktype *s, AActor *thing, nodetype *nextnode, nodetype *&sec_thinglist);
|
||||||
|
|
||||||
|
template<class nodetype, class linktype>
|
||||||
|
nodetype* P_DelSecnode(nodetype *, nodetype *linktype::*head);
|
||||||
|
|
||||||
msecnode_t *P_CreateSecNodeList(AActor *thing, double radius, msecnode_t *sector_list, msecnode_t *sector_t::*seclisthead);
|
msecnode_t *P_CreateSecNodeList(AActor *thing, double radius, msecnode_t *sector_list, msecnode_t *sector_t::*seclisthead);
|
||||||
double P_GetMoveFactor(const AActor *mo, double *frictionp); // phares 3/6/98
|
double P_GetMoveFactor(const AActor *mo, double *frictionp); // phares 3/6/98
|
||||||
double P_GetFriction(const AActor *mo, double *frictionfactor);
|
double P_GetFriction(const AActor *mo, double *frictionfactor);
|
||||||
|
|
407
src/p_map.cpp
407
src/p_map.cpp
|
@ -6448,413 +6448,6 @@ bool P_ChangeSector(sector_t *sector, int crunch, double amt, int floorOrCeil, b
|
||||||
return cpos.nofit;
|
return cpos.nofit;
|
||||||
}
|
}
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
// phares 3/21/98
|
|
||||||
//
|
|
||||||
// Maintain a freelist of msecnode_t's to reduce memory allocs and frees.
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
msecnode_t *headsecnode = NULL;
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
//
|
|
||||||
// P_GetSecnode
|
|
||||||
//
|
|
||||||
// Retrieve a node from the freelist. The calling routine
|
|
||||||
// should make sure it sets all fields properly.
|
|
||||||
//
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
msecnode_t *P_GetSecnode()
|
|
||||||
{
|
|
||||||
msecnode_t *node;
|
|
||||||
|
|
||||||
if (headsecnode)
|
|
||||||
{
|
|
||||||
node = headsecnode;
|
|
||||||
headsecnode = headsecnode->m_snext;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
node = (msecnode_t *)M_Malloc(sizeof(*node));
|
|
||||||
}
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
//
|
|
||||||
// P_PutSecnode
|
|
||||||
//
|
|
||||||
// Returns a node to the freelist.
|
|
||||||
//
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
void P_PutSecnode(msecnode_t *node)
|
|
||||||
{
|
|
||||||
node->m_snext = headsecnode;
|
|
||||||
headsecnode = node;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
// phares 3/16/98
|
|
||||||
//
|
|
||||||
// P_AddSecnode
|
|
||||||
//
|
|
||||||
// Searches the current list to see if this sector is
|
|
||||||
// already there. If not, it adds a sector node at the head of the list of
|
|
||||||
// sectors this object appears in. This is called when creating a list of
|
|
||||||
// nodes that will get linked in later. Returns a pointer to the new node.
|
|
||||||
//
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
msecnode_t *P_AddSecnode(sector_t *s, AActor *thing, msecnode_t *nextnode, msecnode_t *&sec_thinglist)
|
|
||||||
{
|
|
||||||
msecnode_t *node;
|
|
||||||
|
|
||||||
if (s == 0)
|
|
||||||
{
|
|
||||||
I_FatalError("AddSecnode of 0 for %s\n", thing->GetClass()->TypeName.GetChars());
|
|
||||||
}
|
|
||||||
|
|
||||||
node = nextnode;
|
|
||||||
while (node)
|
|
||||||
{
|
|
||||||
if (node->m_sector == s) // Already have a node for this sector?
|
|
||||||
{
|
|
||||||
node->m_thing = thing; // Yes. Setting m_thing says 'keep it'.
|
|
||||||
return nextnode;
|
|
||||||
}
|
|
||||||
node = node->m_tnext;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Couldn't find an existing node for this sector. Add one at the head
|
|
||||||
// of the list.
|
|
||||||
|
|
||||||
node = P_GetSecnode();
|
|
||||||
|
|
||||||
// killough 4/4/98, 4/7/98: mark new nodes unvisited.
|
|
||||||
node->visited = 0;
|
|
||||||
|
|
||||||
node->m_sector = s; // sector
|
|
||||||
node->m_thing = thing; // mobj
|
|
||||||
node->m_tprev = NULL; // prev node on Thing thread
|
|
||||||
node->m_tnext = nextnode; // next node on Thing thread
|
|
||||||
if (nextnode)
|
|
||||||
nextnode->m_tprev = node; // set back link on Thing
|
|
||||||
|
|
||||||
// Add new node at head of sector thread starting at s->touching_thinglist
|
|
||||||
|
|
||||||
node->m_sprev = NULL; // prev node on sector thread
|
|
||||||
node->m_snext = sec_thinglist; // next node on sector thread
|
|
||||||
if (sec_thinglist)
|
|
||||||
node->m_snext->m_sprev = node;
|
|
||||||
sec_thinglist = node;
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
//
|
|
||||||
// P_DelSecnode
|
|
||||||
//
|
|
||||||
// Deletes a sector node from the list of
|
|
||||||
// sectors this object appears in. Returns a pointer to the next node
|
|
||||||
// on the linked list, or NULL.
|
|
||||||
//
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
msecnode_t *P_DelSecnode(msecnode_t *node, msecnode_t *sector_t::*listhead)
|
|
||||||
{
|
|
||||||
msecnode_t* tp; // prev node on thing thread
|
|
||||||
msecnode_t* tn; // next node on thing thread
|
|
||||||
msecnode_t* sp; // prev node on sector thread
|
|
||||||
msecnode_t* sn; // next node on sector thread
|
|
||||||
|
|
||||||
if (node)
|
|
||||||
{
|
|
||||||
// Unlink from the Thing thread. The Thing thread begins at
|
|
||||||
// sector_list and not from AActor->touching_sectorlist.
|
|
||||||
|
|
||||||
tp = node->m_tprev;
|
|
||||||
tn = node->m_tnext;
|
|
||||||
if (tp)
|
|
||||||
tp->m_tnext = tn;
|
|
||||||
if (tn)
|
|
||||||
tn->m_tprev = tp;
|
|
||||||
|
|
||||||
// Unlink from the sector thread. This thread begins at
|
|
||||||
// sector_t->touching_thinglist.
|
|
||||||
|
|
||||||
sp = node->m_sprev;
|
|
||||||
sn = node->m_snext;
|
|
||||||
if (sp)
|
|
||||||
sp->m_snext = sn;
|
|
||||||
else
|
|
||||||
node->m_sector->*listhead = sn;
|
|
||||||
if (sn)
|
|
||||||
sn->m_sprev = sp;
|
|
||||||
|
|
||||||
// Return this node to the freelist
|
|
||||||
|
|
||||||
P_PutSecnode(node);
|
|
||||||
return tn;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
} // phares 3/13/98
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
//
|
|
||||||
// P_DelSeclist
|
|
||||||
//
|
|
||||||
// Delete an entire sector list
|
|
||||||
//
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
void P_DelSeclist(msecnode_t *node, msecnode_t *sector_t::*sechead)
|
|
||||||
{
|
|
||||||
while (node)
|
|
||||||
node = P_DelSecnode(node, sechead);
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
// phares 3/14/98
|
|
||||||
//
|
|
||||||
// P_CreateSecNodeList
|
|
||||||
//
|
|
||||||
// Alters/creates the sector_list that shows what sectors the object resides in
|
|
||||||
//
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
msecnode_t *P_CreateSecNodeList(AActor *thing, double radius, msecnode_t *sector_list, msecnode_t *sector_t::*seclisthead)
|
|
||||||
{
|
|
||||||
msecnode_t *node;
|
|
||||||
|
|
||||||
// First, clear out the existing m_thing fields. As each node is
|
|
||||||
// added or verified as needed, m_thing will be set properly. When
|
|
||||||
// finished, delete all nodes where m_thing is still NULL. These
|
|
||||||
// represent the sectors the Thing has vacated.
|
|
||||||
|
|
||||||
node = sector_list;
|
|
||||||
while (node)
|
|
||||||
{
|
|
||||||
node->m_thing = NULL;
|
|
||||||
node = node->m_tnext;
|
|
||||||
}
|
|
||||||
|
|
||||||
FBoundingBox box(thing->X(), thing->Y(), radius);
|
|
||||||
FBlockLinesIterator it(box);
|
|
||||||
line_t *ld;
|
|
||||||
|
|
||||||
while ((ld = it.Next()))
|
|
||||||
{
|
|
||||||
if (!box.inRange(ld) || box.BoxOnLineSide(ld) != -1)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// This line crosses through the object.
|
|
||||||
|
|
||||||
// Collect the sector(s) from the line and add to the
|
|
||||||
// sector_list you're examining. If the Thing ends up being
|
|
||||||
// allowed to move to this position, then the sector_list
|
|
||||||
// will be attached to the Thing's AActor at touching_sectorlist.
|
|
||||||
|
|
||||||
sector_list = P_AddSecnode(ld->frontsector, thing, sector_list, ld->frontsector->*seclisthead);
|
|
||||||
|
|
||||||
// Don't assume all lines are 2-sided, since some Things
|
|
||||||
// like MT_TFOG are allowed regardless of whether their radius takes
|
|
||||||
// them beyond an impassable linedef.
|
|
||||||
|
|
||||||
// killough 3/27/98, 4/4/98:
|
|
||||||
// Use sidedefs instead of 2s flag to determine two-sidedness.
|
|
||||||
|
|
||||||
if (ld->backsector)
|
|
||||||
sector_list = P_AddSecnode(ld->backsector, thing, sector_list, ld->backsector->*seclisthead);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the sector of the (x,y) point to sector_list.
|
|
||||||
|
|
||||||
sector_list = P_AddSecnode(thing->Sector, thing, sector_list, thing->Sector->*seclisthead);
|
|
||||||
|
|
||||||
// Now delete any nodes that won't be used. These are the ones where
|
|
||||||
// m_thing is still NULL.
|
|
||||||
|
|
||||||
node = sector_list;
|
|
||||||
while (node)
|
|
||||||
{
|
|
||||||
if (node->m_thing == NULL)
|
|
||||||
{
|
|
||||||
if (node == sector_list)
|
|
||||||
sector_list = node->m_tnext;
|
|
||||||
node = P_DelSecnode(node, seclisthead);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
node = node->m_tnext;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return sector_list;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
//
|
|
||||||
// P_DelPortalnode
|
|
||||||
//
|
|
||||||
// Same for line portal nodes
|
|
||||||
//
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
portnode_t *P_DelPortalnode(portnode_t *node)
|
|
||||||
{
|
|
||||||
portnode_t* tp; // prev node on thing thread
|
|
||||||
portnode_t* tn; // next node on thing thread
|
|
||||||
portnode_t* sp; // prev node on sector thread
|
|
||||||
portnode_t* sn; // next node on sector thread
|
|
||||||
|
|
||||||
if (node)
|
|
||||||
{
|
|
||||||
// Unlink from the Thing thread. The Thing thread begins at
|
|
||||||
// sector_list and not from AActor->touching_sectorlist.
|
|
||||||
|
|
||||||
tp = node->m_tprev;
|
|
||||||
tn = node->m_tnext;
|
|
||||||
if (tp)
|
|
||||||
tp->m_tnext = tn;
|
|
||||||
if (tn)
|
|
||||||
tn->m_tprev = tp;
|
|
||||||
|
|
||||||
// Unlink from the sector thread. This thread begins at
|
|
||||||
// sector_t->touching_thinglist.
|
|
||||||
|
|
||||||
sp = node->m_sprev;
|
|
||||||
sn = node->m_snext;
|
|
||||||
if (sp)
|
|
||||||
sp->m_snext = sn;
|
|
||||||
else
|
|
||||||
node->m_portal->render_thinglist = sn;
|
|
||||||
if (sn)
|
|
||||||
sn->m_sprev = sp;
|
|
||||||
|
|
||||||
// Return this node to the freelist (use the same one as for msecnodes, since both types are the same size.)
|
|
||||||
P_PutSecnode(reinterpret_cast<msecnode_t *>(node));
|
|
||||||
return tn;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
//
|
|
||||||
// P_AddPortalnode
|
|
||||||
//
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
portnode_t *P_AddPortalnode(FLinePortal *s, AActor *thing, portnode_t *nextnode)
|
|
||||||
{
|
|
||||||
portnode_t *node;
|
|
||||||
|
|
||||||
if (s == 0)
|
|
||||||
{
|
|
||||||
I_FatalError("AddSecnode of 0 for %s\n", thing->GetClass()->TypeName.GetChars());
|
|
||||||
}
|
|
||||||
|
|
||||||
node = reinterpret_cast<portnode_t*>(P_GetSecnode());
|
|
||||||
|
|
||||||
// killough 4/4/98, 4/7/98: mark new nodes unvisited.
|
|
||||||
node->visited = 0;
|
|
||||||
|
|
||||||
node->m_portal = s; // portal
|
|
||||||
node->m_thing = thing; // mobj
|
|
||||||
node->m_tprev = NULL; // prev node on Thing thread
|
|
||||||
node->m_tnext = nextnode; // next node on Thing thread
|
|
||||||
if (nextnode)
|
|
||||||
nextnode->m_tprev = node; // set back link on Thing
|
|
||||||
|
|
||||||
// Add new node at head of portal thread starting at s->touching_thinglist
|
|
||||||
|
|
||||||
node->m_sprev = NULL; // prev node on portal thread
|
|
||||||
node->m_snext = s->render_thinglist; // next node on portal thread
|
|
||||||
if (s->render_thinglist)
|
|
||||||
node->m_snext->m_sprev = node;
|
|
||||||
s->render_thinglist = node;
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// Handle the lists used to render actors from other portal areas
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
void AActor::UpdateRenderSectorList()
|
|
||||||
{
|
|
||||||
static const double SPRITE_SPACE = 64.;
|
|
||||||
if (Pos() != OldRenderPos && !(flags & MF_NOSECTOR))
|
|
||||||
{
|
|
||||||
// Only check if the map contains line portals
|
|
||||||
ClearRenderLineList();
|
|
||||||
if (PortalBlockmap.containsLines && Pos().XY() != OldRenderPos.XY())
|
|
||||||
{
|
|
||||||
int bx = GetBlockX(X());
|
|
||||||
int by = GetBlockY(Y());
|
|
||||||
FBoundingBox bb(X(), Y(), MIN(radius*1.5, 128.)); // Don't go further than 128 map units, even for large actors
|
|
||||||
// Are there any portals near the actor's position?
|
|
||||||
if (bx >= 0 && by >= 0 && bx < bmapwidth && by < bmapheight && PortalBlockmap(bx, by).neighborContainsLines)
|
|
||||||
{
|
|
||||||
// Go through the entire list. In most cases this is faster than setting up a blockmap iterator
|
|
||||||
for (auto &p : linePortals)
|
|
||||||
{
|
|
||||||
if (p.mType == PORTT_VISUAL) continue;
|
|
||||||
if (bb.inRange(p.mOrigin) && bb.BoxOnLineSide(p.mOrigin))
|
|
||||||
{
|
|
||||||
render_portallist = P_AddPortalnode(&p, this, render_portallist);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sector_t *sec = Sector;
|
|
||||||
double lasth = -FLT_MAX;
|
|
||||||
ClearRenderSectorList();
|
|
||||||
while (!sec->PortalBlocksMovement(sector_t::ceiling))
|
|
||||||
{
|
|
||||||
double planeh = sec->GetPortalPlaneZ(sector_t::ceiling);
|
|
||||||
if (planeh <= lasth) break; // broken setup.
|
|
||||||
if (Top() + SPRITE_SPACE < planeh) break;
|
|
||||||
lasth = planeh;
|
|
||||||
DVector2 newpos = Pos() + sec->GetPortalDisplacement(sector_t::ceiling);
|
|
||||||
sec = P_PointInSector(newpos);
|
|
||||||
render_sectorlist = P_AddSecnode(sec, this, render_sectorlist, sec->render_thinglist);
|
|
||||||
}
|
|
||||||
sec = Sector;
|
|
||||||
lasth = FLT_MAX;
|
|
||||||
while (!sec->PortalBlocksMovement(sector_t::floor))
|
|
||||||
{
|
|
||||||
double planeh = sec->GetPortalPlaneZ(sector_t::floor);
|
|
||||||
if (planeh >= lasth) break; // broken setup.
|
|
||||||
if (Z() - SPRITE_SPACE > planeh) break;
|
|
||||||
lasth = planeh;
|
|
||||||
DVector2 newpos = Pos() + sec->GetPortalDisplacement(sector_t::floor);
|
|
||||||
sec = P_PointInSector(newpos);
|
|
||||||
render_sectorlist = P_AddSecnode(sec, this, render_sectorlist, sec->render_thinglist);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AActor::ClearRenderSectorList()
|
|
||||||
{
|
|
||||||
msecnode_t *node = render_sectorlist;
|
|
||||||
while (node)
|
|
||||||
node = P_DelSecnode(node, §or_t::render_thinglist);
|
|
||||||
render_sectorlist = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AActor::ClearRenderLineList()
|
|
||||||
{
|
|
||||||
portnode_t *node = render_portallist;
|
|
||||||
while (node)
|
|
||||||
node = P_DelPortalnode(node);
|
|
||||||
render_portallist = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
|
|
@ -138,10 +138,10 @@ DPSprite::DPSprite(player_t *owner, AActor *caller, int id)
|
||||||
: x(.0), y(.0),
|
: x(.0), y(.0),
|
||||||
oldx(.0), oldy(.0),
|
oldx(.0), oldy(.0),
|
||||||
firstTic(true),
|
firstTic(true),
|
||||||
Sprite(0),
|
|
||||||
Flags(0),
|
Flags(0),
|
||||||
Caller(caller),
|
Caller(caller),
|
||||||
Owner(owner),
|
Owner(owner),
|
||||||
|
Sprite(0),
|
||||||
ID(id),
|
ID(id),
|
||||||
processPending(true),
|
processPending(true),
|
||||||
alpha(1),
|
alpha(1),
|
||||||
|
|
444
src/p_secnodes.cpp
Normal file
444
src/p_secnodes.cpp
Normal file
|
@ -0,0 +1,444 @@
|
||||||
|
// Emacs style mode select -*- C++ -*-
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// $Id:$
|
||||||
|
//
|
||||||
|
// Copyright (C) 1998-1996 by id Software, Inc.
|
||||||
|
//
|
||||||
|
// This source is available for distribution and/or modification
|
||||||
|
// only under the terms of the DOOM Source Code License as
|
||||||
|
// published by id Software. All rights reserved.
|
||||||
|
//
|
||||||
|
// The source is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||||
|
// for more details.
|
||||||
|
//
|
||||||
|
// $Log:$
|
||||||
|
//
|
||||||
|
// DESCRIPTION:
|
||||||
|
// Boom secnodes
|
||||||
|
//
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "r_state.h"
|
||||||
|
#include "p_maputl.h"
|
||||||
|
#include "p_blockmap.h"
|
||||||
|
#include "memarena.h"
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// phares 3/21/98
|
||||||
|
//
|
||||||
|
// Maintain a freelist of msecnode_t's to reduce memory allocs and frees.
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
msecnode_t *headsecnode = nullptr;
|
||||||
|
FMemArena secnodearena;
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
// P_GetSecnode
|
||||||
|
//
|
||||||
|
// Retrieve a node from the freelist. The calling routine
|
||||||
|
// should make sure it sets all fields properly.
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
msecnode_t *P_GetSecnode()
|
||||||
|
{
|
||||||
|
msecnode_t *node;
|
||||||
|
|
||||||
|
if (headsecnode)
|
||||||
|
{
|
||||||
|
node = headsecnode;
|
||||||
|
headsecnode = headsecnode->m_snext;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
node = (msecnode_t *)secnodearena.Alloc(sizeof(*node));
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
// P_PutSecnode
|
||||||
|
//
|
||||||
|
// Returns a node to the freelist.
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
void P_PutSecnode(msecnode_t *node)
|
||||||
|
{
|
||||||
|
node->m_snext = headsecnode;
|
||||||
|
headsecnode = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// phares 3/16/98
|
||||||
|
//
|
||||||
|
// P_AddSecnode
|
||||||
|
//
|
||||||
|
// Searches the current list to see if this sector is
|
||||||
|
// already there. If not, it adds a sector node at the head of the list of
|
||||||
|
// sectors this object appears in. This is called when creating a list of
|
||||||
|
// nodes that will get linked in later. Returns a pointer to the new node.
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
template<class nodetype, class linktype>
|
||||||
|
nodetype *P_AddSecnode(linktype *s, AActor *thing, nodetype *nextnode, nodetype *&sec_thinglist)
|
||||||
|
{
|
||||||
|
nodetype *node;
|
||||||
|
|
||||||
|
if (s == 0)
|
||||||
|
{
|
||||||
|
I_FatalError("AddSecnode of 0 for %s\n", thing->GetClass()->TypeName.GetChars());
|
||||||
|
}
|
||||||
|
|
||||||
|
node = nextnode;
|
||||||
|
while (node)
|
||||||
|
{
|
||||||
|
if (node->m_sector == s) // Already have a node for this sector?
|
||||||
|
{
|
||||||
|
node->m_thing = thing; // Yes. Setting m_thing says 'keep it'.
|
||||||
|
return nextnode;
|
||||||
|
}
|
||||||
|
node = node->m_tnext;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Couldn't find an existing node for this sector. Add one at the head
|
||||||
|
// of the list.
|
||||||
|
|
||||||
|
node = (nodetype*)P_GetSecnode();
|
||||||
|
|
||||||
|
// killough 4/4/98, 4/7/98: mark new nodes unvisited.
|
||||||
|
node->visited = 0;
|
||||||
|
|
||||||
|
node->m_sector = s; // sector
|
||||||
|
node->m_thing = thing; // mobj
|
||||||
|
node->m_tprev = nullptr; // prev node on Thing thread
|
||||||
|
node->m_tnext = nextnode; // next node on Thing thread
|
||||||
|
if (nextnode)
|
||||||
|
nextnode->m_tprev = node; // set back link on Thing
|
||||||
|
|
||||||
|
// Add new node at head of sector thread starting at s->touching_thinglist
|
||||||
|
|
||||||
|
node->m_sprev = nullptr; // prev node on sector thread
|
||||||
|
node->m_snext = sec_thinglist; // next node on sector thread
|
||||||
|
if (sec_thinglist)
|
||||||
|
node->m_snext->m_sprev = node;
|
||||||
|
sec_thinglist = node;
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
template msecnode_t *P_AddSecnode<msecnode_t, sector_t>(sector_t *s, AActor *thing, msecnode_t *nextnode, msecnode_t *&sec_thinglist);
|
||||||
|
template portnode_t *P_AddSecnode<portnode_t, FLinePortal>(FLinePortal *s, AActor *thing, portnode_t *nextnode, portnode_t *&sec_thinglist);
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
// P_DelSecnode
|
||||||
|
//
|
||||||
|
// Deletes a sector node from the list of
|
||||||
|
// sectors this object appears in. Returns a pointer to the next node
|
||||||
|
// on the linked list, or nullptr.
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
template<class nodetype, class linktype>
|
||||||
|
nodetype *P_DelSecnode(nodetype *node, nodetype *linktype::*listhead)
|
||||||
|
{
|
||||||
|
nodetype* tp; // prev node on thing thread
|
||||||
|
nodetype* tn; // next node on thing thread
|
||||||
|
nodetype* sp; // prev node on sector thread
|
||||||
|
nodetype* sn; // next node on sector thread
|
||||||
|
|
||||||
|
if (node)
|
||||||
|
{
|
||||||
|
// Unlink from the Thing thread. The Thing thread begins at
|
||||||
|
// sector_list and not from AActor->touching_sectorlist.
|
||||||
|
|
||||||
|
tp = node->m_tprev;
|
||||||
|
tn = node->m_tnext;
|
||||||
|
if (tp)
|
||||||
|
tp->m_tnext = tn;
|
||||||
|
if (tn)
|
||||||
|
tn->m_tprev = tp;
|
||||||
|
|
||||||
|
// Unlink from the sector thread. This thread begins at
|
||||||
|
// sector_t->touching_thinglist.
|
||||||
|
|
||||||
|
sp = node->m_sprev;
|
||||||
|
sn = node->m_snext;
|
||||||
|
if (sp)
|
||||||
|
sp->m_snext = sn;
|
||||||
|
else
|
||||||
|
node->m_sector->*listhead = sn;
|
||||||
|
if (sn)
|
||||||
|
sn->m_sprev = sp;
|
||||||
|
|
||||||
|
// Return this node to the freelist
|
||||||
|
|
||||||
|
P_PutSecnode((msecnode_t*)node);
|
||||||
|
return tn;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
} // phares 3/13/98
|
||||||
|
|
||||||
|
template msecnode_t *P_DelSecnode(msecnode_t *node, msecnode_t *sector_t::*listhead);
|
||||||
|
template portnode_t *P_DelSecnode(portnode_t *node, portnode_t *FLinePortal::*listhead);
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
// P_DelSeclist
|
||||||
|
//
|
||||||
|
// Delete an entire sector list
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
void P_DelSeclist(msecnode_t *node, msecnode_t *sector_t::*sechead)
|
||||||
|
{
|
||||||
|
while (node)
|
||||||
|
node = P_DelSecnode(node, sechead);
|
||||||
|
}
|
||||||
|
|
||||||
|
void P_DelSeclist(portnode_t *node, portnode_t *FLinePortal::*sechead)
|
||||||
|
{
|
||||||
|
while (node)
|
||||||
|
node = P_DelSecnode(node, sechead);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// phares 3/14/98
|
||||||
|
//
|
||||||
|
// P_CreateSecNodeList
|
||||||
|
//
|
||||||
|
// Alters/creates the sector_list that shows what sectors the object resides in
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
msecnode_t *P_CreateSecNodeList(AActor *thing, double radius, msecnode_t *sector_list, msecnode_t *sector_t::*seclisthead)
|
||||||
|
{
|
||||||
|
msecnode_t *node;
|
||||||
|
|
||||||
|
// First, clear out the existing m_thing fields. As each node is
|
||||||
|
// added or verified as needed, m_thing will be set properly. When
|
||||||
|
// finished, delete all nodes where m_thing is still nullptr. These
|
||||||
|
// represent the sectors the Thing has vacated.
|
||||||
|
|
||||||
|
node = sector_list;
|
||||||
|
while (node)
|
||||||
|
{
|
||||||
|
node->m_thing = nullptr;
|
||||||
|
node = node->m_tnext;
|
||||||
|
}
|
||||||
|
|
||||||
|
FBoundingBox box(thing->X(), thing->Y(), radius);
|
||||||
|
FBlockLinesIterator it(box);
|
||||||
|
line_t *ld;
|
||||||
|
|
||||||
|
while ((ld = it.Next()))
|
||||||
|
{
|
||||||
|
if (!box.inRange(ld) || box.BoxOnLineSide(ld) != -1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// This line crosses through the object.
|
||||||
|
|
||||||
|
// Collect the sector(s) from the line and add to the
|
||||||
|
// sector_list you're examining. If the Thing ends up being
|
||||||
|
// allowed to move to this position, then the sector_list
|
||||||
|
// will be attached to the Thing's AActor at touching_sectorlist.
|
||||||
|
|
||||||
|
sector_list = P_AddSecnode(ld->frontsector, thing, sector_list, ld->frontsector->*seclisthead);
|
||||||
|
|
||||||
|
// Don't assume all lines are 2-sided, since some Things
|
||||||
|
// like MT_TFOG are allowed regardless of whether their radius takes
|
||||||
|
// them beyond an impassable linedef.
|
||||||
|
|
||||||
|
// killough 3/27/98, 4/4/98:
|
||||||
|
// Use sidedefs instead of 2s flag to determine two-sidedness.
|
||||||
|
|
||||||
|
if (ld->backsector)
|
||||||
|
sector_list = P_AddSecnode(ld->backsector, thing, sector_list, ld->backsector->*seclisthead);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the sector of the (x,y) point to sector_list.
|
||||||
|
|
||||||
|
sector_list = P_AddSecnode(thing->Sector, thing, sector_list, thing->Sector->*seclisthead);
|
||||||
|
|
||||||
|
// Now delete any nodes that won't be used. These are the ones where
|
||||||
|
// m_thing is still nullptr.
|
||||||
|
|
||||||
|
node = sector_list;
|
||||||
|
while (node)
|
||||||
|
{
|
||||||
|
if (node->m_thing == nullptr)
|
||||||
|
{
|
||||||
|
if (node == sector_list)
|
||||||
|
sector_list = node->m_tnext;
|
||||||
|
node = P_DelSecnode(node, seclisthead);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
node = node->m_tnext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sector_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
// P_DelPortalnode
|
||||||
|
//
|
||||||
|
// Same for line portal nodes
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
portnode_t *P_DelPortalnode(portnode_t *node)
|
||||||
|
{
|
||||||
|
portnode_t* tp; // prev node on thing thread
|
||||||
|
portnode_t* tn; // next node on thing thread
|
||||||
|
portnode_t* sp; // prev node on sector thread
|
||||||
|
portnode_t* sn; // next node on sector thread
|
||||||
|
|
||||||
|
if (node)
|
||||||
|
{
|
||||||
|
// Unlink from the Thing thread. The Thing thread begins at
|
||||||
|
// sector_list and not from AActor->touching_sectorlist.
|
||||||
|
|
||||||
|
tp = node->m_tprev;
|
||||||
|
tn = node->m_tnext;
|
||||||
|
if (tp)
|
||||||
|
tp->m_tnext = tn;
|
||||||
|
if (tn)
|
||||||
|
tn->m_tprev = tp;
|
||||||
|
|
||||||
|
// Unlink from the sector thread. This thread begins at
|
||||||
|
// sector_t->touching_thinglist.
|
||||||
|
|
||||||
|
sp = node->m_sprev;
|
||||||
|
sn = node->m_snext;
|
||||||
|
if (sp)
|
||||||
|
sp->m_snext = sn;
|
||||||
|
else
|
||||||
|
node->m_sector->lineportal_thinglist = sn;
|
||||||
|
if (sn)
|
||||||
|
sn->m_sprev = sp;
|
||||||
|
|
||||||
|
// Return this node to the freelist (use the same one as for msecnodes, since both types are the same size.)
|
||||||
|
P_PutSecnode(reinterpret_cast<msecnode_t *>(node));
|
||||||
|
return tn;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
// P_AddPortalnode
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
portnode_t *P_AddPortalnode(FLinePortal *s, AActor *thing, portnode_t *nextnode)
|
||||||
|
{
|
||||||
|
portnode_t *node;
|
||||||
|
|
||||||
|
if (s == 0)
|
||||||
|
{
|
||||||
|
I_FatalError("AddSecnode of 0 for %s\n", thing->GetClass()->TypeName.GetChars());
|
||||||
|
}
|
||||||
|
|
||||||
|
node = reinterpret_cast<portnode_t*>(P_GetSecnode());
|
||||||
|
|
||||||
|
// killough 4/4/98, 4/7/98: mark new nodes unvisited.
|
||||||
|
node->visited = 0;
|
||||||
|
|
||||||
|
node->m_sector = s; // portal
|
||||||
|
node->m_thing = thing; // mobj
|
||||||
|
node->m_tprev = nullptr; // prev node on Thing thread
|
||||||
|
node->m_tnext = nextnode; // next node on Thing thread
|
||||||
|
if (nextnode)
|
||||||
|
nextnode->m_tprev = node; // set back link on Thing
|
||||||
|
|
||||||
|
// Add new node at head of portal thread starting at s->touching_thinglist
|
||||||
|
|
||||||
|
node->m_sprev = nullptr; // prev node on portal thread
|
||||||
|
node->m_snext = s->lineportal_thinglist; // next node on portal thread
|
||||||
|
if (s->lineportal_thinglist)
|
||||||
|
node->m_snext->m_sprev = node;
|
||||||
|
s->lineportal_thinglist = node;
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// Handle the lists used to render actors from other portal areas
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void AActor::UpdateRenderSectorList()
|
||||||
|
{
|
||||||
|
static const double SPRITE_SPACE = 64.;
|
||||||
|
if (Pos() != OldRenderPos && !(flags & MF_NOSECTOR))
|
||||||
|
{
|
||||||
|
// Only check if the map contains line portals
|
||||||
|
ClearRenderLineList();
|
||||||
|
if (PortalBlockmap.containsLines && Pos().XY() != OldRenderPos.XY())
|
||||||
|
{
|
||||||
|
int bx = GetBlockX(X());
|
||||||
|
int by = GetBlockY(Y());
|
||||||
|
FBoundingBox bb(X(), Y(), MIN(radius*1.5, 128.)); // Don't go further than 128 map units, even for large actors
|
||||||
|
// Are there any portals near the actor's position?
|
||||||
|
if (bx >= 0 && by >= 0 && bx < bmapwidth && by < bmapheight && PortalBlockmap(bx, by).neighborContainsLines)
|
||||||
|
{
|
||||||
|
// Go through the entire list. In most cases this is faster than setting up a blockmap iterator
|
||||||
|
for (auto &p : linePortals)
|
||||||
|
{
|
||||||
|
if (p.mType == PORTT_VISUAL) continue;
|
||||||
|
if (bb.inRange(p.mOrigin) && bb.BoxOnLineSide(p.mOrigin))
|
||||||
|
{
|
||||||
|
touching_lineportallist = P_AddPortalnode(&p, this, touching_lineportallist);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sector_t *sec = Sector;
|
||||||
|
double lasth = -FLT_MAX;
|
||||||
|
ClearRenderSectorList();
|
||||||
|
while (!sec->PortalBlocksMovement(sector_t::ceiling))
|
||||||
|
{
|
||||||
|
double planeh = sec->GetPortalPlaneZ(sector_t::ceiling);
|
||||||
|
if (planeh <= lasth) break; // broken setup.
|
||||||
|
if (Top() + SPRITE_SPACE < planeh) break;
|
||||||
|
lasth = planeh;
|
||||||
|
DVector2 newpos = Pos() + sec->GetPortalDisplacement(sector_t::ceiling);
|
||||||
|
sec = P_PointInSector(newpos);
|
||||||
|
touching_sectorportallist = P_AddSecnode(sec, this, touching_sectorportallist, sec->sectorportal_thinglist);
|
||||||
|
}
|
||||||
|
sec = Sector;
|
||||||
|
lasth = FLT_MAX;
|
||||||
|
while (!sec->PortalBlocksMovement(sector_t::floor))
|
||||||
|
{
|
||||||
|
double planeh = sec->GetPortalPlaneZ(sector_t::floor);
|
||||||
|
if (planeh >= lasth) break; // broken setup.
|
||||||
|
if (Z() - SPRITE_SPACE > planeh) break;
|
||||||
|
lasth = planeh;
|
||||||
|
DVector2 newpos = Pos() + sec->GetPortalDisplacement(sector_t::floor);
|
||||||
|
sec = P_PointInSector(newpos);
|
||||||
|
touching_sectorportallist = P_AddSecnode(sec, this, touching_sectorportallist, sec->sectorportal_thinglist);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AActor::ClearRenderSectorList()
|
||||||
|
{
|
||||||
|
P_DelSeclist(touching_sectorportallist, §or_t::sectorportal_thinglist);
|
||||||
|
touching_sectorportallist = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AActor::ClearRenderLineList()
|
||||||
|
{
|
||||||
|
P_DelSeclist(touching_lineportallist, &FLinePortal::lineportal_thinglist);
|
||||||
|
touching_lineportallist = nullptr;
|
||||||
|
}
|
|
@ -1337,7 +1337,7 @@ DEFINE_FIELD_X(Sector, sector_t, bottommap)
|
||||||
DEFINE_FIELD_X(Sector, sector_t, midmap)
|
DEFINE_FIELD_X(Sector, sector_t, midmap)
|
||||||
DEFINE_FIELD_X(Sector, sector_t, topmap)
|
DEFINE_FIELD_X(Sector, sector_t, topmap)
|
||||||
DEFINE_FIELD_X(Sector, sector_t, touching_thinglist)
|
DEFINE_FIELD_X(Sector, sector_t, touching_thinglist)
|
||||||
DEFINE_FIELD_X(Sector, sector_t, render_thinglist)
|
DEFINE_FIELD_X(Sector, sector_t, sectorportal_thinglist)
|
||||||
DEFINE_FIELD_X(Sector, sector_t, gravity)
|
DEFINE_FIELD_X(Sector, sector_t, gravity)
|
||||||
DEFINE_FIELD_X(Sector, sector_t, damagetype)
|
DEFINE_FIELD_X(Sector, sector_t, damagetype)
|
||||||
DEFINE_FIELD_X(Sector, sector_t, damageamount)
|
DEFINE_FIELD_X(Sector, sector_t, damageamount)
|
||||||
|
|
|
@ -1508,7 +1508,7 @@ void P_LoadSectors (MapData *map, FMissingTextureTracker &missingtex)
|
||||||
tagManager.AddSectorTag(i, LittleShort(ms->tag));
|
tagManager.AddSectorTag(i, LittleShort(ms->tag));
|
||||||
ss->thinglist = nullptr;
|
ss->thinglist = nullptr;
|
||||||
ss->touching_thinglist = nullptr; // phares 3/14/98
|
ss->touching_thinglist = nullptr; // phares 3/14/98
|
||||||
ss->render_thinglist = nullptr;
|
ss->sectorportal_thinglist = nullptr;
|
||||||
ss->touching_renderthings = nullptr;
|
ss->touching_renderthings = nullptr;
|
||||||
ss->seqType = defSeqType;
|
ss->seqType = defSeqType;
|
||||||
ss->SeqName = NAME_None;
|
ss->SeqName = NAME_None;
|
||||||
|
@ -3088,7 +3088,7 @@ line_t** linebuffer;
|
||||||
static void P_GroupLines (bool buildmap)
|
static void P_GroupLines (bool buildmap)
|
||||||
{
|
{
|
||||||
cycle_t times[16];
|
cycle_t times[16];
|
||||||
int* linesDoneInEachSector;
|
unsigned int* linesDoneInEachSector;
|
||||||
int i;
|
int i;
|
||||||
int total;
|
int total;
|
||||||
line_t* li;
|
line_t* li;
|
||||||
|
@ -3156,7 +3156,7 @@ static void P_GroupLines (bool buildmap)
|
||||||
times[3].Clock();
|
times[3].Clock();
|
||||||
linebuffer = new line_t *[total];
|
linebuffer = new line_t *[total];
|
||||||
line_t **lineb_p = linebuffer;
|
line_t **lineb_p = linebuffer;
|
||||||
linesDoneInEachSector = new int[numsectors];
|
linesDoneInEachSector = new unsigned int[numsectors];
|
||||||
memset (linesDoneInEachSector, 0, sizeof(int)*numsectors);
|
memset (linesDoneInEachSector, 0, sizeof(int)*numsectors);
|
||||||
|
|
||||||
for (sector = sectors, i = 0; i < numsectors; i++, sector++)
|
for (sector = sectors, i = 0; i < numsectors; i++, sector++)
|
||||||
|
@ -3552,6 +3552,7 @@ void P_FreeLevelData ()
|
||||||
P_ClearUDMFKeys();
|
P_ClearUDMFKeys();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern FMemArena secnodearena;
|
||||||
extern msecnode_t *headsecnode;
|
extern msecnode_t *headsecnode;
|
||||||
|
|
||||||
void P_FreeExtraLevelData()
|
void P_FreeExtraLevelData()
|
||||||
|
@ -3569,19 +3570,11 @@ void P_FreeExtraLevelData()
|
||||||
}
|
}
|
||||||
FBlockNode::FreeBlocks = NULL;
|
FBlockNode::FreeBlocks = NULL;
|
||||||
}
|
}
|
||||||
{
|
secnodearena.FreeAllBlocks();
|
||||||
msecnode_t *node = headsecnode;
|
headsecnode = nullptr;
|
||||||
|
|
||||||
while (node != NULL)
|
|
||||||
{
|
|
||||||
msecnode_t *next = node->m_snext;
|
|
||||||
M_Free (node);
|
|
||||||
node = next;
|
|
||||||
}
|
|
||||||
headsecnode = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// P_SetupLevel
|
// P_SetupLevel
|
||||||
//
|
//
|
||||||
|
|
|
@ -1297,7 +1297,7 @@ public:
|
||||||
sec->SetAlpha(sector_t::ceiling, 1.);
|
sec->SetAlpha(sector_t::ceiling, 1.);
|
||||||
sec->thinglist = nullptr;
|
sec->thinglist = nullptr;
|
||||||
sec->touching_thinglist = nullptr; // phares 3/14/98
|
sec->touching_thinglist = nullptr; // phares 3/14/98
|
||||||
sec->render_thinglist = nullptr;
|
sec->sectorportal_thinglist = nullptr;
|
||||||
sec->touching_renderthings = nullptr;
|
sec->touching_renderthings = nullptr;
|
||||||
sec->seqType = (level.flags & LEVEL_SNDSEQTOTALCTRL) ? 0 : -1;
|
sec->seqType = (level.flags & LEVEL_SNDSEQTOTALCTRL) ? 0 : -1;
|
||||||
sec->nextsec = -1; //jff 2/26/98 add fields to support locking out
|
sec->nextsec = -1; //jff 2/26/98 add fields to support locking out
|
||||||
|
@ -1695,7 +1695,7 @@ public:
|
||||||
sec->ceilingplane.set(n.X, n.Y, n.Z, cp[3]);
|
sec->ceilingplane.set(n.X, n.Y, n.Z, cp[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lightcolor == -1 && fadecolor == -1 && desaturation == -1 && fogdensity == -1)
|
if (lightcolor == ~0u && fadecolor == ~0u && desaturation == -1 && fogdensity == -1)
|
||||||
{
|
{
|
||||||
// [RH] Sectors default to white light with the default fade.
|
// [RH] Sectors default to white light with the default fade.
|
||||||
// If they are outside (have a sky ceiling), they use the outside fog.
|
// If they are outside (have a sky ceiling), they use the outside fog.
|
||||||
|
@ -1714,8 +1714,8 @@ public:
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (lightcolor == -1) lightcolor = PalEntry(255,255,255);
|
if (lightcolor == ~0u) lightcolor = PalEntry(255,255,255);
|
||||||
if (fadecolor == -1)
|
if (fadecolor == ~0u)
|
||||||
{
|
{
|
||||||
if (level.outsidefog != 0xff000000 && (sec->GetTexture(sector_t::ceiling) == skyflatnum || (sec->special & 0xff) == Sector_Outside))
|
if (level.outsidefog != 0xff000000 && (sec->GetTexture(sector_t::ceiling) == skyflatnum || (sec->special & 0xff) == Sector_Outside))
|
||||||
fadecolor = level.outsidefog;
|
fadecolor = level.outsidefog;
|
||||||
|
|
209
src/p_user.cpp
209
src/p_user.cpp
|
@ -95,9 +95,19 @@ static int PredictionLerptics;
|
||||||
|
|
||||||
static player_t PredictionPlayerBackup;
|
static player_t PredictionPlayerBackup;
|
||||||
static BYTE PredictionActorBackup[sizeof(APlayerPawn)];
|
static BYTE PredictionActorBackup[sizeof(APlayerPawn)];
|
||||||
static TArray<sector_t *> PredictionTouchingSectorsBackup;
|
|
||||||
static TArray<AActor *> PredictionSectorListBackup;
|
static TArray<AActor *> PredictionSectorListBackup;
|
||||||
static TArray<msecnode_t *> PredictionSector_sprev_Backup;
|
|
||||||
|
static TArray<sector_t *> PredictionTouchingSectorsBackup;
|
||||||
|
static TArray<msecnode_t *> PredictionTouchingSectors_sprev_Backup;
|
||||||
|
|
||||||
|
static TArray<sector_t *> PredictionRenderSectorsBackup;
|
||||||
|
static TArray<msecnode_t *> PredictionRenderSectors_sprev_Backup;
|
||||||
|
|
||||||
|
static TArray<sector_t *> PredictionPortalSectorsBackup;
|
||||||
|
static TArray<msecnode_t *> PredictionPortalSectors_sprev_Backup;
|
||||||
|
|
||||||
|
static TArray<FLinePortal *> PredictionPortalLinesBackup;
|
||||||
|
static TArray<portnode_t *> PredictionPortalLines_sprev_Backup;
|
||||||
|
|
||||||
// [GRB] Custom player classes
|
// [GRB] Custom player classes
|
||||||
TArray<FPlayerClass> PlayerClasses;
|
TArray<FPlayerClass> PlayerClasses;
|
||||||
|
@ -2776,6 +2786,100 @@ bool P_LerpCalculate(AActor *pmo, PredictPos from, PredictPos to, PredictPos &re
|
||||||
return (delta.LengthSquared() > cl_predict_lerpthreshold && scale <= 1.00f);
|
return (delta.LengthSquared() > cl_predict_lerpthreshold && scale <= 1.00f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class nodetype, class linktype>
|
||||||
|
void BackupNodeList(AActor *act, nodetype *head, nodetype *linktype::*otherlist, TArray<nodetype*, nodetype*> &prevbackup, TArray<linktype *, linktype *> &otherbackup)
|
||||||
|
{
|
||||||
|
// The ordering of the touching_sectorlist needs to remain unchanged
|
||||||
|
// Also store a copy of all previous sector_thinglist nodes
|
||||||
|
prevbackup.Clear();
|
||||||
|
otherbackup.Clear();
|
||||||
|
|
||||||
|
for (auto mnode = head; mnode != nullptr; mnode = mnode->m_tnext)
|
||||||
|
{
|
||||||
|
otherbackup.Push(mnode->m_sector);
|
||||||
|
|
||||||
|
for (auto snode = mnode->m_sector->*otherlist; snode; snode = snode->m_snext)
|
||||||
|
{
|
||||||
|
if (snode->m_thing == act)
|
||||||
|
{
|
||||||
|
prevbackup.Push(snode->m_sprev);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class nodetype, class linktype>
|
||||||
|
nodetype *RestoreNodeList(AActor *act, nodetype *head, nodetype *linktype::*otherlist, TArray<nodetype*, nodetype*> &prevbackup, TArray<linktype *, linktype *> &otherbackup)
|
||||||
|
{
|
||||||
|
// Destroy old refrences
|
||||||
|
nodetype *node = head;
|
||||||
|
while (node)
|
||||||
|
{
|
||||||
|
node->m_thing = NULL;
|
||||||
|
node = node->m_tnext;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make the sector_list match the player's touching_sectorlist before it got predicted.
|
||||||
|
P_DelSeclist(head, otherlist);
|
||||||
|
head = NULL;
|
||||||
|
for (auto i = otherbackup.Size(); i-- > 0;)
|
||||||
|
{
|
||||||
|
head = P_AddSecnode(otherbackup[i], act, head, otherbackup[i]->*otherlist);
|
||||||
|
}
|
||||||
|
//act->touching_sectorlist = ctx.sector_list; // Attach to thing
|
||||||
|
//ctx.sector_list = NULL; // clear for next time
|
||||||
|
|
||||||
|
// In the old code this block never executed because of the commented-out NULL assignment above. Needs to be checked
|
||||||
|
node = head;
|
||||||
|
while (node)
|
||||||
|
{
|
||||||
|
if (node->m_thing == NULL)
|
||||||
|
{
|
||||||
|
if (node == head)
|
||||||
|
head = node->m_tnext;
|
||||||
|
node = P_DelSecnode(node, otherlist);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
node = node->m_tnext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nodetype *snode;
|
||||||
|
|
||||||
|
// Restore sector thinglist order
|
||||||
|
for (auto i = otherbackup.Size(); i-- > 0;)
|
||||||
|
{
|
||||||
|
// If we were already the head node, then nothing needs to change
|
||||||
|
if (prevbackup[i] == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (snode = otherbackup[i]->*otherlist; snode; snode = snode->m_snext)
|
||||||
|
{
|
||||||
|
if (snode->m_thing == act)
|
||||||
|
{
|
||||||
|
if (snode->m_sprev)
|
||||||
|
snode->m_sprev->m_snext = snode->m_snext;
|
||||||
|
else
|
||||||
|
snode->m_sector->*otherlist = snode->m_snext;
|
||||||
|
if (snode->m_snext)
|
||||||
|
snode->m_snext->m_sprev = snode->m_sprev;
|
||||||
|
|
||||||
|
snode->m_sprev = prevbackup[i];
|
||||||
|
|
||||||
|
// At the moment, we don't exist in the list anymore, but we do know what our previous node is, so we set its current m_snext->m_sprev to us.
|
||||||
|
if (snode->m_sprev->m_snext)
|
||||||
|
snode->m_sprev->m_snext->m_sprev = snode;
|
||||||
|
snode->m_snext = snode->m_sprev->m_snext;
|
||||||
|
snode->m_sprev->m_snext = snode;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return head;
|
||||||
|
}
|
||||||
|
|
||||||
void P_PredictPlayer (player_t *player)
|
void P_PredictPlayer (player_t *player)
|
||||||
{
|
{
|
||||||
int maxtic;
|
int maxtic;
|
||||||
|
@ -2810,28 +2914,10 @@ void P_PredictPlayer (player_t *player)
|
||||||
act->flags2 &= ~MF2_PUSHWALL;
|
act->flags2 &= ~MF2_PUSHWALL;
|
||||||
player->cheats |= CF_PREDICTING;
|
player->cheats |= CF_PREDICTING;
|
||||||
|
|
||||||
// The ordering of the touching_sectorlist needs to remain unchanged
|
BackupNodeList(act, act->touching_sectorlist, §or_t::touching_thinglist, PredictionTouchingSectors_sprev_Backup, PredictionTouchingSectorsBackup);
|
||||||
// Also store a copy of all previous sector_thinglist nodes
|
BackupNodeList(act, act->touching_rendersectors, §or_t::touching_renderthings, PredictionRenderSectors_sprev_Backup, PredictionRenderSectorsBackup);
|
||||||
msecnode_t *mnode = act->touching_sectorlist;
|
BackupNodeList(act, act->touching_sectorportallist, §or_t::sectorportal_thinglist, PredictionPortalSectors_sprev_Backup, PredictionPortalSectorsBackup);
|
||||||
msecnode_t *snode;
|
BackupNodeList(act, act->touching_lineportallist, &FLinePortal::lineportal_thinglist, PredictionPortalLines_sprev_Backup, PredictionPortalLinesBackup);
|
||||||
PredictionSector_sprev_Backup.Clear();
|
|
||||||
PredictionTouchingSectorsBackup.Clear ();
|
|
||||||
|
|
||||||
while (mnode != NULL)
|
|
||||||
{
|
|
||||||
PredictionTouchingSectorsBackup.Push (mnode->m_sector);
|
|
||||||
|
|
||||||
for (snode = mnode->m_sector->touching_thinglist; snode; snode = snode->m_snext)
|
|
||||||
{
|
|
||||||
if (snode->m_thing == act)
|
|
||||||
{
|
|
||||||
PredictionSector_sprev_Backup.Push(snode->m_sprev);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mnode = mnode->m_tnext;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keep an ordered list off all actors in the linked sector.
|
// Keep an ordered list off all actors in the linked sector.
|
||||||
PredictionSectorListBackup.Clear();
|
PredictionSectorListBackup.Clear();
|
||||||
|
@ -2941,6 +3027,12 @@ void P_UnPredictPlayer ()
|
||||||
player->camera = savedcamera;
|
player->camera = savedcamera;
|
||||||
|
|
||||||
FLinkContext ctx;
|
FLinkContext ctx;
|
||||||
|
// Unlink from all list, includeing those which are not being handled by UnlinkFromWorld.
|
||||||
|
auto sectorportal_list = act->touching_sectorportallist;
|
||||||
|
auto lineportal_list = act->touching_lineportallist;
|
||||||
|
act->touching_sectorportallist = nullptr;
|
||||||
|
act->touching_lineportallist = nullptr;
|
||||||
|
|
||||||
act->UnlinkFromWorld(&ctx);
|
act->UnlinkFromWorld(&ctx);
|
||||||
memcpy(&act->snext, PredictionActorBackup, sizeof(APlayerPawn) - ((BYTE *)&act->snext - (BYTE *)act));
|
memcpy(&act->snext, PredictionActorBackup, sizeof(APlayerPawn) - ((BYTE *)&act->snext - (BYTE *)act));
|
||||||
|
|
||||||
|
@ -2969,71 +3061,10 @@ void P_UnPredictPlayer ()
|
||||||
*link = me;
|
*link = me;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destroy old refrences
|
act->touching_sectorlist = RestoreNodeList(act, ctx.sector_list, §or_t::touching_thinglist, PredictionTouchingSectors_sprev_Backup, PredictionTouchingSectorsBackup);
|
||||||
msecnode_t *node = ctx.sector_list;
|
act->touching_rendersectors = RestoreNodeList(act, ctx.render_list, §or_t::touching_renderthings, PredictionRenderSectors_sprev_Backup, PredictionRenderSectorsBackup);
|
||||||
while (node)
|
act->touching_sectorportallist = RestoreNodeList(act, sectorportal_list, §or_t::sectorportal_thinglist, PredictionPortalSectors_sprev_Backup, PredictionPortalSectorsBackup);
|
||||||
{
|
act->touching_lineportallist = RestoreNodeList(act, lineportal_list, &FLinePortal::lineportal_thinglist, PredictionPortalLines_sprev_Backup, PredictionPortalLinesBackup);
|
||||||
node->m_thing = NULL;
|
|
||||||
node = node->m_tnext;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make the sector_list match the player's touching_sectorlist before it got predicted.
|
|
||||||
P_DelSeclist(ctx.sector_list, §or_t::touching_thinglist);
|
|
||||||
ctx.sector_list = NULL;
|
|
||||||
for (i = PredictionTouchingSectorsBackup.Size(); i-- > 0;)
|
|
||||||
{
|
|
||||||
ctx.sector_list = P_AddSecnode(PredictionTouchingSectorsBackup[i], act, ctx.sector_list, PredictionTouchingSectorsBackup[i]->touching_thinglist);
|
|
||||||
}
|
|
||||||
act->touching_sectorlist = ctx.sector_list; // Attach to thing
|
|
||||||
ctx.sector_list = NULL; // clear for next time
|
|
||||||
|
|
||||||
// Huh???
|
|
||||||
node = ctx.sector_list;
|
|
||||||
while (node)
|
|
||||||
{
|
|
||||||
if (node->m_thing == NULL)
|
|
||||||
{
|
|
||||||
if (node == ctx.sector_list)
|
|
||||||
ctx.sector_list = node->m_tnext;
|
|
||||||
node = P_DelSecnode(node, §or_t::touching_thinglist);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
node = node->m_tnext;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
msecnode_t *snode;
|
|
||||||
|
|
||||||
// Restore sector thinglist order
|
|
||||||
for (i = PredictionTouchingSectorsBackup.Size(); i-- > 0;)
|
|
||||||
{
|
|
||||||
// If we were already the head node, then nothing needs to change
|
|
||||||
if (PredictionSector_sprev_Backup[i] == NULL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for (snode = PredictionTouchingSectorsBackup[i]->touching_thinglist; snode; snode = snode->m_snext)
|
|
||||||
{
|
|
||||||
if (snode->m_thing == act)
|
|
||||||
{
|
|
||||||
if (snode->m_sprev)
|
|
||||||
snode->m_sprev->m_snext = snode->m_snext;
|
|
||||||
else
|
|
||||||
snode->m_sector->touching_thinglist = snode->m_snext;
|
|
||||||
if (snode->m_snext)
|
|
||||||
snode->m_snext->m_sprev = snode->m_sprev;
|
|
||||||
|
|
||||||
snode->m_sprev = PredictionSector_sprev_Backup[i];
|
|
||||||
|
|
||||||
// At the moment, we don't exist in the list anymore, but we do know what our previous node is, so we set its current m_snext->m_sprev to us.
|
|
||||||
if (snode->m_sprev->m_snext)
|
|
||||||
snode->m_sprev->m_snext->m_sprev = snode;
|
|
||||||
snode->m_snext = snode->m_sprev->m_snext;
|
|
||||||
snode->m_sprev->m_snext = snode;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now fix the pointers in the blocknode chain
|
// Now fix the pointers in the blocknode chain
|
||||||
|
|
|
@ -191,7 +191,7 @@ struct FLinePortal
|
||||||
DAngle mAngleDiff;
|
DAngle mAngleDiff;
|
||||||
double mSinRot;
|
double mSinRot;
|
||||||
double mCosRot;
|
double mCosRot;
|
||||||
portnode_t *render_thinglist;
|
portnode_t *lineportal_thinglist;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern TArray<FLinePortal> linePortals;
|
extern TArray<FLinePortal> linePortals;
|
||||||
|
|
|
@ -1048,7 +1048,7 @@ public:
|
||||||
// list of mobjs that are at least partially in the sector
|
// list of mobjs that are at least partially in the sector
|
||||||
// thinglist is a subset of touching_thinglist
|
// thinglist is a subset of touching_thinglist
|
||||||
struct msecnode_t *touching_thinglist; // phares 3/14/98
|
struct msecnode_t *touching_thinglist; // phares 3/14/98
|
||||||
struct msecnode_t *render_thinglist; // for cross-portal rendering.
|
struct msecnode_t *sectorportal_thinglist; // for cross-portal rendering.
|
||||||
struct msecnode_t *touching_renderthings; // this is used to allow wide things to be rendered not only from their main sector.
|
struct msecnode_t *touching_renderthings; // this is used to allow wide things to be rendered not only from their main sector.
|
||||||
|
|
||||||
double gravity; // [RH] Sector gravity (1.0 is normal)
|
double gravity; // [RH] Sector gravity (1.0 is normal)
|
||||||
|
@ -1371,7 +1371,7 @@ struct msecnode_t
|
||||||
// use the same memory layout as msecnode_t so both can be used from the same freelist.
|
// use the same memory layout as msecnode_t so both can be used from the same freelist.
|
||||||
struct portnode_t
|
struct portnode_t
|
||||||
{
|
{
|
||||||
FLinePortal *m_portal; // a portal containing this object
|
FLinePortal *m_sector; // a portal containing this object (no, this isn't a sector, but if we want to use templates it needs the same variable names as msecnode_t.)
|
||||||
AActor *m_thing; // this object
|
AActor *m_thing; // this object
|
||||||
struct portnode_t *m_tprev; // prev msecnode_t for this thing
|
struct portnode_t *m_tprev; // prev msecnode_t for this thing
|
||||||
struct portnode_t *m_tnext; // next msecnode_t for this thing
|
struct portnode_t *m_tnext; // next msecnode_t for this thing
|
||||||
|
|
|
@ -3980,7 +3980,7 @@ ExpEmit FxConcat::Emit(VMFunctionBuilder *build)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int cast;
|
int cast = 0;
|
||||||
strng = ExpEmit(build, REGT_STRING);
|
strng = ExpEmit(build, REGT_STRING);
|
||||||
if (op1.Konst)
|
if (op1.Konst)
|
||||||
{
|
{
|
||||||
|
|
|
@ -43,7 +43,7 @@
|
||||||
|
|
||||||
|
|
||||||
FWarpTexture::FWarpTexture (FTexture *source, int warptype)
|
FWarpTexture::FWarpTexture (FTexture *source, int warptype)
|
||||||
: GenTime (0), SourcePic (source), Pixels (0), Spans (0), Speed (1.f)
|
: GenTime (0), Speed (1.f), SourcePic (source), Pixels (0), Spans (0)
|
||||||
{
|
{
|
||||||
CopyInfo(source);
|
CopyInfo(source);
|
||||||
if (warptype == 2) SetupMultipliers(256, 128);
|
if (warptype == 2) SetupMultipliers(256, 128);
|
||||||
|
|
|
@ -283,7 +283,7 @@ struct Sector native
|
||||||
native uint bottommap, midmap, topmap;
|
native uint bottommap, midmap, topmap;
|
||||||
|
|
||||||
//struct msecnode_t *touching_thinglist;
|
//struct msecnode_t *touching_thinglist;
|
||||||
//struct msecnode_t *render_thinglist;
|
//struct msecnode_t *sectorportal_thinglist;
|
||||||
|
|
||||||
native double gravity;
|
native double gravity;
|
||||||
native Name damagetype;
|
native Name damagetype;
|
||||||
|
|
Loading…
Reference in a new issue