mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-11 15:21:51 +00:00
Merge remote-tracking branch 'origin/master' into asmjit
This commit is contained in:
commit
99849bc0c5
66 changed files with 1042 additions and 601 deletions
|
@ -154,31 +154,52 @@ Note: All <bool> fields default to false unless mentioned otherwise.
|
|||
|
||||
sidedef
|
||||
{
|
||||
scalex_top = <float>; // X scale for upper texture, Default = 1.0.
|
||||
scaley_top = <float>; // y scale for upper texture, Default = 1.0.
|
||||
scalex_mid = <float>; // X scale for mid texture, Default = 1.0.
|
||||
scaley_mid = <float>; // y scale for mid texture, Default = 1.0.
|
||||
scalex_bottom = <float>; // X scale for lower texture, Default = 1.0.
|
||||
scaley_bottom = <float>; // y scale for lower texture, Default = 1.0.
|
||||
offsetx_top = <float>; // X offset for upper texture, Default = 0.0.
|
||||
offsety_top = <float>; // y offset for upper texture, Default = 0.0.
|
||||
offsetx_mid = <float>; // X offset for mid texture, Default = 0.0.
|
||||
offsety_mid = <float>; // y offset for mid texture, Default = 0.0.
|
||||
offsetx_bottom = <float>; // X offset for lower texture, Default = 0.0.
|
||||
offsety_bottom = <float>; // y offset for lower texture, Default = 0.0.
|
||||
// When global texture offsets are used they will
|
||||
// be added on top of these values.
|
||||
light = <integer>; // This side's light level. Default is 0.
|
||||
lightabsolute = <bool>; // true = 'light' is an absolute value. Default is
|
||||
// relative to the owning sector's light level.
|
||||
lightfog = <bool>; // true = This side's relative lighting is used even in
|
||||
// foggy sectors. Default is to disable relative
|
||||
// lighting in foggy sectors.
|
||||
nofakecontrast = <bool>; // Disables use of fake contrast on this sidedef.
|
||||
smoothlighting = <bool>; // Use smooth fake contrast.
|
||||
clipmidtex = <bool>; // Side's mid textures are clipped to floor and ceiling.
|
||||
wrapmidtex = <bool>; // Side's mid textures are wrapped.
|
||||
nodecals = <bool>; // Disables decals on the sidedef.
|
||||
scalex_top = <float>; // X scale for upper texture, Default = 1.0.
|
||||
scaley_top = <float>; // y scale for upper texture, Default = 1.0.
|
||||
scalex_mid = <float>; // X scale for mid texture, Default = 1.0.
|
||||
scaley_mid = <float>; // y scale for mid texture, Default = 1.0.
|
||||
scalex_bottom = <float>; // X scale for lower texture, Default = 1.0.
|
||||
scaley_bottom = <float>; // y scale for lower texture, Default = 1.0.
|
||||
offsetx_top = <float>; // X offset for upper texture, Default = 0.0.
|
||||
offsety_top = <float>; // y offset for upper texture, Default = 0.0.
|
||||
offsetx_mid = <float>; // X offset for mid texture, Default = 0.0.
|
||||
offsety_mid = <float>; // y offset for mid texture, Default = 0.0.
|
||||
offsetx_bottom = <float>; // X offset for lower texture, Default = 0.0.
|
||||
offsety_bottom = <float>; // y offset for lower texture, Default = 0.0.
|
||||
// When global texture offsets are used they will
|
||||
// be added on top of these values.
|
||||
light = <integer>; // This side's light level. Default is 0.
|
||||
lightabsolute = <bool>; // true = 'light' is an absolute value. Default is
|
||||
// relative to the owning sector's light level.
|
||||
lightfog = <bool>; // true = This side's relative lighting is used even in
|
||||
// foggy sectors. Default is to disable relative
|
||||
// lighting in foggy sectors.
|
||||
nofakecontrast = <bool>; // Disables use of fake contrast on this sidedef.
|
||||
smoothlighting = <bool>; // Use smooth fake contrast.
|
||||
clipmidtex = <bool>; // Side's mid textures are clipped to floor and ceiling.
|
||||
wrapmidtex = <bool>; // Side's mid textures are wrapped.
|
||||
nodecals = <bool>; // Disables decals on the sidedef.
|
||||
|
||||
nogradient_top = <bool>; // disables color gradient on upper tier. (Hardware rendering only.)
|
||||
flipgradient_top = <bool>; // flips gradient colors on upper tier. (Hardware rendering only.)
|
||||
clampgradient_top = <bool>; // clamps gradient on upper tier to actual bounds (default is the entire front sector height, hardware rendering only.)
|
||||
useowncolors_top = <bool>; // Set to 1 to use the colors set in the sidedef. Default is using the colors from the owning sector.
|
||||
uppercolor_top = <int>; // Material color of the top of the upper tier.
|
||||
lowercolor_top = <int>; // Material color of the bottom of the upper tier. (Hardware rendering only.)
|
||||
|
||||
nogradient_mid = <bool>; // disables color gradient on middle tier. (Hardware rendering only.)
|
||||
flipgradient_mid = <bool>; // flips gradient colors on middle tier. (Hardware rendering only.)
|
||||
clampgradient_mid = <bool>; // clamps gradient on middle tier to actual bounds (default is the entire front sector height, hardware rendering only.)
|
||||
useowncolors_mid = <bool>; // Set to 1 to use the colors set in the sidedef. Default is using the colors from the owning sector.
|
||||
uppercolor_mid = <int>; // Material color of the top of the middle tier.
|
||||
lowercolor_mid = <int>; // Material color of the bottom of the middle tier. (Hardware rendering only.)
|
||||
|
||||
nogradient_bottom = <bool>; // disables color gradient on lower tier. (Hardware rendering only.)
|
||||
flipgradient_bottom = <bool>; // flips gradient colors on lower tier. (Hardware rendering only.)
|
||||
clampgradient_bottom = <bool>;// clamps gradient on lower tier to actual bounds (default is the entire front sector height, hardware rendering only.)
|
||||
useowncolors_bottom = <bool>; // Set to 1 to use the colors set in the sidedef. Default is using the colors from the owning sector.
|
||||
uppercolor_bottom = <int>; // Material color of the top of the lower tier.
|
||||
lowercolor_bottom = <int>; // Material color of the bottom of the lower tier. (Hardware rendering only.)
|
||||
}
|
||||
|
||||
sector
|
||||
|
@ -300,8 +321,8 @@ Note: All <bool> fields default to false unless mentioned otherwise.
|
|||
score = <int>; // Score value of this actor, overriding the class default if not null. Default = 0.
|
||||
pitch = <integer>; // Pitch of thing in degrees. Default = 0 (horizontal).
|
||||
roll = <integer>; // Pitch of thing in degrees. Default = 0 (horizontal).
|
||||
scalex = <float>; // Vertical scaling on thing. Default = 0 (ignored).
|
||||
scaley = <float>; // Horizontal scaling on thing. Default = 0 (ignored).
|
||||
scalex = <float>; // Horizontal scaling on thing. Default = 0 (ignored).
|
||||
scaley = <float>; // Vertical scaling on thing. Default = 0 (ignored).
|
||||
scale = <float>; // Vertical and horizontal scaling on thing. Default = 0 (ignored).
|
||||
floatbobphase = <int>; // Sets the thing's floatbobphase. Valid phase values are 0-63. Default = -1 (use actor class default).
|
||||
|
||||
|
|
|
@ -62,6 +62,7 @@
|
|||
#include "a_keys.h"
|
||||
#include "g_levellocals.h"
|
||||
#include "actorinlines.h"
|
||||
#include "earcut.hpp"
|
||||
|
||||
|
||||
//=============================================================================
|
||||
|
@ -2054,6 +2055,7 @@ sector_t * AM_FakeFlat(AActor *viewer, sector_t * sec, sector_t * dest)
|
|||
void AM_drawSubsectors()
|
||||
{
|
||||
static TArray<FVector2> points;
|
||||
std::vector<uint32_t> indices;
|
||||
double scale = scale_mtof;
|
||||
DAngle rotation;
|
||||
sector_t tempsec;
|
||||
|
@ -2067,27 +2069,28 @@ void AM_drawSubsectors()
|
|||
auto &subsectors = level.subsectors;
|
||||
for (unsigned i = 0; i < subsectors.Size(); ++i)
|
||||
{
|
||||
if (subsectors[i].flags & SSECF_POLYORG)
|
||||
auto sub = &subsectors[i];
|
||||
if (sub->flags & SSECF_POLYORG)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((!(subsectors[i].flags & SSECMF_DRAWN) || (subsectors[i].flags & SSECF_HOLE) || (subsectors[i].render_sector->MoreFlags & SECMF_HIDDEN)) && am_cheat == 0)
|
||||
if ((!(sub->flags & SSECMF_DRAWN) || (sub->flags & SSECF_HOLE) || (sub->render_sector->MoreFlags & SECMF_HIDDEN)) && am_cheat == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (am_portaloverlay && subsectors[i].render_sector->PortalGroup != MapPortalGroup && subsectors[i].render_sector->PortalGroup != 0)
|
||||
if (am_portaloverlay && sub->render_sector->PortalGroup != MapPortalGroup && sub->render_sector->PortalGroup != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Fill the points array from the subsector.
|
||||
points.Resize(subsectors[i].numlines);
|
||||
for (uint32_t j = 0; j < subsectors[i].numlines; ++j)
|
||||
points.Resize(sub->numlines);
|
||||
for (uint32_t j = 0; j < sub->numlines; ++j)
|
||||
{
|
||||
mpoint_t pt = { subsectors[i].firstline[j].v1->fX(),
|
||||
subsectors[i].firstline[j].v1->fY() };
|
||||
mpoint_t pt = { sub->firstline[j].v1->fX(),
|
||||
sub->firstline[j].v1->fY() };
|
||||
if (am_rotate == 1 || (am_rotate == 2 && viewactive))
|
||||
{
|
||||
AM_rotatePoint(&pt.x, &pt.y);
|
||||
|
@ -2096,7 +2099,7 @@ void AM_drawSubsectors()
|
|||
points[j].Y = float(f_y + (f_h - (pt.y - m_y) * scale));
|
||||
}
|
||||
// For lighting and texture determination
|
||||
sector_t *sec = AM_FakeFlat(players[consoleplayer].camera, subsectors[i].render_sector, &tempsec);
|
||||
sector_t *sec = AM_FakeFlat(players[consoleplayer].camera, sub->render_sector, &tempsec);
|
||||
floorlight = sec->GetFloorLight();
|
||||
// Find texture origin.
|
||||
originpt.x = -sec->GetXOffset(sector_t::floor);
|
||||
|
@ -2123,7 +2126,7 @@ void AM_drawSubsectors()
|
|||
double secx;
|
||||
double secy;
|
||||
double seczb, seczt;
|
||||
auto &vp = r_viewpoint;
|
||||
auto &vp = r_viewpoint;
|
||||
double cmpz = vp.Pos.Z;
|
||||
|
||||
if (players[consoleplayer].camera && sec == players[consoleplayer].camera->Sector)
|
||||
|
@ -2144,7 +2147,7 @@ void AM_drawSubsectors()
|
|||
{
|
||||
F3DFloor *rover = sec->e->XFloor.ffloors[i];
|
||||
if (!(rover->flags & FF_EXISTS)) continue;
|
||||
if (rover->flags & (FF_FOG|FF_THISINSIDE)) continue;
|
||||
if (rover->flags & (FF_FOG | FF_THISINSIDE)) continue;
|
||||
if (!(rover->flags & FF_RENDERPLANES)) continue;
|
||||
if (rover->alpha == 0) continue;
|
||||
double roverz = rover->top.plane->ZatPoint(secx, secy);
|
||||
|
@ -2194,7 +2197,7 @@ void AM_drawSubsectors()
|
|||
|
||||
// If this subsector has not actually been seen yet (because you are cheating
|
||||
// to see it on the map), tint and desaturate it.
|
||||
if (!(subsectors[i].flags & SSECMF_DRAWN))
|
||||
if (!(sub->flags & SSECMF_DRAWN))
|
||||
{
|
||||
colormap.LightColor = PalEntry(
|
||||
(colormap.LightColor.r + 255) / 2,
|
||||
|
@ -2210,8 +2213,28 @@ void AM_drawSubsectors()
|
|||
|
||||
// Draw the polygon.
|
||||
FTexture *pic = TexMan(maptex);
|
||||
if (pic != NULL && pic->UseType != ETextureType::Null)
|
||||
if (pic != nullptr && pic->UseType != ETextureType::Null)
|
||||
{
|
||||
// Hole filling "subsectors" are not necessarily convex so they require real triangulation.
|
||||
// These things are extremely rare so performance is secondary here.
|
||||
if (sub->flags & SSECF_HOLE && sub->numlines > 3)
|
||||
{
|
||||
using Point = std::pair<double, double>;
|
||||
std::vector<std::vector<Point>> polygon;
|
||||
std::vector<Point> *curPoly;
|
||||
|
||||
polygon.resize(1);
|
||||
curPoly = &polygon.back();
|
||||
curPoly->resize(points.Size());
|
||||
|
||||
for (unsigned i = 0; i < points.Size(); i++)
|
||||
{
|
||||
(*curPoly)[i] = { points[i].X, points[i].Y };
|
||||
}
|
||||
indices = mapbox::earcut(polygon);
|
||||
}
|
||||
else indices.clear();
|
||||
|
||||
screen->FillSimplePoly(TexMan(maptex),
|
||||
&points[0], points.Size(),
|
||||
originx, originy,
|
||||
|
@ -2221,8 +2244,8 @@ void AM_drawSubsectors()
|
|||
colormap,
|
||||
flatcolor,
|
||||
floorlight,
|
||||
f_y + f_h
|
||||
);
|
||||
f_y + f_h,
|
||||
indices.data(), indices.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -150,9 +150,9 @@ void FConsoleBuffer::AddText(int printlevel, const char *text, FILE *logfile)
|
|||
void FConsoleBuffer::WriteLineToLog(FILE *LogFile, const char *outline)
|
||||
{
|
||||
// Strip out any color escape sequences before writing to the log file
|
||||
char * copy = new char[strlen(outline)+1];
|
||||
TArray<char> copy(strlen(outline)+1);
|
||||
const char * srcp = outline;
|
||||
char * dstp = copy;
|
||||
char * dstp = copy.Data();
|
||||
|
||||
while (*srcp != 0)
|
||||
{
|
||||
|
@ -193,8 +193,7 @@ void FConsoleBuffer::WriteLineToLog(FILE *LogFile, const char *outline)
|
|||
}
|
||||
*dstp=0;
|
||||
|
||||
fputs (copy, LogFile);
|
||||
delete [] copy;
|
||||
fputs (copy.Data(), LogFile);
|
||||
fflush (LogFile);
|
||||
}
|
||||
|
||||
|
|
|
@ -257,7 +257,7 @@ FIWadManager::FIWadManager(const char *fn)
|
|||
if (lmp->Namespace == ns_global && !stricmp(lmp->Name, "IWADINFO"))
|
||||
{
|
||||
// Found one!
|
||||
ParseIWadInfo(resfile->Filename, (const char*)lmp->CacheLump(), lmp->LumpSize);
|
||||
ParseIWadInfo(resfile->FileName, (const char*)lmp->CacheLump(), lmp->LumpSize);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -349,7 +349,7 @@ int FIWadManager::CheckIWADInfo(const char *fn)
|
|||
try
|
||||
{
|
||||
FIWADInfo result;
|
||||
ParseIWadInfo(resfile->Filename, (const char*)lmp->CacheLump(), lmp->LumpSize, &result);
|
||||
ParseIWadInfo(resfile->FileName, (const char*)lmp->CacheLump(), lmp->LumpSize, &result);
|
||||
delete resfile;
|
||||
|
||||
for (unsigned i = 0, count = mIWadInfos.Size(); i < count; ++i)
|
||||
|
|
|
@ -1905,7 +1905,7 @@ static FString CheckGameInfo(TArray<FString> & pwads)
|
|||
if (lmp->Namespace == ns_global && !stricmp(lmp->Name, "GAMEINFO"))
|
||||
{
|
||||
// Found one!
|
||||
FString iwad = ParseGameInfo(pwads, resfile->Filename, (const char*)lmp->CacheLump(), lmp->LumpSize);
|
||||
FString iwad = ParseGameInfo(pwads, resfile->FileName, (const char*)lmp->CacheLump(), lmp->LumpSize);
|
||||
delete resfile;
|
||||
return iwad;
|
||||
}
|
||||
|
|
|
@ -32,29 +32,24 @@
|
|||
|
||||
class FBurnTexture : public FTexture
|
||||
{
|
||||
uint32_t *WorkBuffer;
|
||||
TArray<uint32_t> WorkBuffer;
|
||||
public:
|
||||
FBurnTexture(int w, int h)
|
||||
: WorkBuffer(w*h, true)
|
||||
{
|
||||
Width = w;
|
||||
Height = h;
|
||||
WorkBuffer = new uint32_t[w * h];
|
||||
}
|
||||
|
||||
~FBurnTexture()
|
||||
{
|
||||
delete [] WorkBuffer;
|
||||
}
|
||||
|
||||
int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf) override
|
||||
{
|
||||
bmp->CopyPixelDataRGB(x, y, (uint8_t*)WorkBuffer, Width, Height, 4, Width*4, rotate, CF_RGBA, inf);
|
||||
bmp->CopyPixelDataRGB(x, y, (uint8_t*)WorkBuffer.Data(), Width, Height, 4, Width*4, rotate, CF_RGBA, inf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t *GetBuffer()
|
||||
{
|
||||
return WorkBuffer;
|
||||
return WorkBuffer.Data();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -184,6 +184,14 @@ public:
|
|||
return mReader->Read(buffer, (long)len);
|
||||
}
|
||||
|
||||
TArray<uint8_t> Read(size_t len)
|
||||
{
|
||||
TArray<uint8_t> buffer((int)len, true);
|
||||
Size length = mReader->Read(&buffer[0], (long)len);
|
||||
buffer.Clamp((int)length);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
TArray<uint8_t> Read()
|
||||
{
|
||||
TArray<uint8_t> buffer(mReader->Length, true);
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
#include "hwrenderer/postprocessing/hw_shadowmapshader.h"
|
||||
#include "hwrenderer/data/flatvertices.h"
|
||||
#include "hwrenderer/scene/hw_skydome.h"
|
||||
#include "hwrenderer/scene/hw_fakeflat.h"
|
||||
#include "gl/shaders/gl_postprocessshaderinstance.h"
|
||||
#include "gl/textures/gl_samplers.h"
|
||||
#include "hwrenderer/dynlights/hw_lightbuffer.h"
|
||||
|
@ -231,6 +232,8 @@ sector_t *FGLRenderer::RenderView(player_t* player)
|
|||
}
|
||||
else
|
||||
{
|
||||
hw_ClearFakeFlat();
|
||||
|
||||
iter_dlightf = iter_dlight = draw_dlight = draw_dlightf = 0;
|
||||
|
||||
checkBenchActive();
|
||||
|
@ -302,6 +305,7 @@ void FGLRenderer::BindToFrameBuffer(FMaterial *mat)
|
|||
|
||||
void FGLRenderer::RenderTextureView(FCanvasTexture *tex, AActor *Viewpoint, double FOV)
|
||||
{
|
||||
// This doesn't need to clear the fake flat cache. It can be shared between camera textures and the main view of a scene.
|
||||
FMaterial * gltex = FMaterial::ValidateTexture(tex, false);
|
||||
|
||||
int width = gltex->TextureWidth();
|
||||
|
@ -343,7 +347,8 @@ void FGLRenderer::WriteSavePic (player_t *player, FileWriter *file, int width, i
|
|||
// Switch to render buffers dimensioned for the savepic
|
||||
mBuffers = mSaveBuffers;
|
||||
|
||||
P_FindParticleSubsectors(); // make sure that all recently spawned particles have a valid subsector.
|
||||
hw_ClearFakeFlat();
|
||||
P_FindParticleSubsectors(); // make sure that all recently spawned particles have a valid subsector.
|
||||
gl_RenderState.SetVertexBuffer(screen->mVertexData);
|
||||
screen->mVertexData->Reset();
|
||||
screen->mLights->Clear();
|
||||
|
|
|
@ -122,8 +122,6 @@ private:
|
|||
|
||||
};
|
||||
|
||||
#include "hwrenderer/scene/hw_fakeflat.h"
|
||||
|
||||
struct TexFilter_s
|
||||
{
|
||||
int minfilter;
|
||||
|
|
|
@ -138,7 +138,6 @@ bool FGLRenderState::ApplyShader()
|
|||
activeShader->muLightParms.Set(mLightParms);
|
||||
activeShader->muFogColor.Set(mFogColor);
|
||||
activeShader->muObjectColor.Set(mObjectColor);
|
||||
activeShader->muObjectColor2.Set(mObjectColor2);
|
||||
activeShader->muDynLightColor.Set(mDynColor.vec);
|
||||
activeShader->muInterpolationFactor.Set(mInterpolationFactor);
|
||||
activeShader->muTimer.Set((double)(screen->FrameTime - firstFrame) * (double)mShaderTimer / 1000.);
|
||||
|
@ -151,6 +150,8 @@ bool FGLRenderState::ApplyShader()
|
|||
{
|
||||
activeShader->muGlowTopColor.Set(mGlowTop.vec);
|
||||
activeShader->muGlowBottomColor.Set(mGlowBottom.vec);
|
||||
activeShader->muGlowTopPlane.Set(mGlowTopPlane.vec);
|
||||
activeShader->muGlowBottomPlane.Set(mGlowBottomPlane.vec);
|
||||
activeShader->currentglowstate = 1;
|
||||
}
|
||||
else if (activeShader->currentglowstate)
|
||||
|
@ -160,10 +161,18 @@ bool FGLRenderState::ApplyShader()
|
|||
activeShader->muGlowBottomColor.Set(nulvec);
|
||||
activeShader->currentglowstate = 0;
|
||||
}
|
||||
if (mGlowEnabled || mObjectColor2.a != 0)
|
||||
|
||||
if (mGradientEnabled)
|
||||
{
|
||||
activeShader->muGlowTopPlane.Set(mGlowTopPlane.vec);
|
||||
activeShader->muGlowBottomPlane.Set(mGlowBottomPlane.vec);
|
||||
activeShader->muObjectColor2.Set(mObjectColor2);
|
||||
activeShader->muGradientTopPlane.Set(mGradientTopPlane.vec);
|
||||
activeShader->muGradientBottomPlane.Set(mGradientBottomPlane.vec);
|
||||
activeShader->currentgradientstate = 1;
|
||||
}
|
||||
else if (activeShader->currentgradientstate)
|
||||
{
|
||||
activeShader->muObjectColor2.Set(0);
|
||||
activeShader->currentgradientstate = 0;
|
||||
}
|
||||
|
||||
if (mSplitEnabled)
|
||||
|
|
|
@ -93,6 +93,9 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char *
|
|||
i_data += "uniform vec4 uGlowBottomPlane;\n";
|
||||
i_data += "uniform vec4 uGlowBottomColor;\n";
|
||||
|
||||
i_data += "uniform vec4 uGradientTopPlane;\n";
|
||||
i_data += "uniform vec4 uGradientBottomPlane;\n";
|
||||
|
||||
i_data += "uniform vec4 uSplitTopPlane;\n";
|
||||
i_data += "uniform vec4 uSplitBottomPlane;\n";
|
||||
|
||||
|
@ -335,6 +338,8 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char *
|
|||
muGlowTopColor.Init(hShader, "uGlowTopColor");
|
||||
muGlowBottomPlane.Init(hShader, "uGlowBottomPlane");
|
||||
muGlowTopPlane.Init(hShader, "uGlowTopPlane");
|
||||
muGradientBottomPlane.Init(hShader, "uGradientBottomPlane");
|
||||
muGradientTopPlane.Init(hShader, "uGradientTopPlane");
|
||||
muSplitBottomPlane.Init(hShader, "uSplitBottomPlane");
|
||||
muSplitTopPlane.Init(hShader, "uSplitTopPlane");
|
||||
muInterpolationFactor.Init(hShader, "uInterpolationFactor");
|
||||
|
|
|
@ -249,6 +249,8 @@ class FShader
|
|||
FUniform4f muGlowTopColor;
|
||||
FUniform4f muGlowBottomPlane;
|
||||
FUniform4f muGlowTopPlane;
|
||||
FUniform4f muGradientBottomPlane;
|
||||
FUniform4f muGradientTopPlane;
|
||||
FUniform4f muSplitBottomPlane;
|
||||
FUniform4f muSplitTopPlane;
|
||||
FBufferedUniform1f muInterpolationFactor;
|
||||
|
@ -266,6 +268,7 @@ public:
|
|||
int fakevb_index;
|
||||
private:
|
||||
int currentglowstate = 0;
|
||||
int currentgradientstate = 0;
|
||||
int currentsplitstate = 0;
|
||||
int currentcliplinestate = 0;
|
||||
int currentfixedcolormap = 0;
|
||||
|
|
|
@ -53,12 +53,14 @@ static void CreateVerticesForSubsector(subsector_t *sub, VertexContainer &gen, i
|
|||
using Point = std::pair<double, double>;
|
||||
std::vector<std::vector<Point>> polygon;
|
||||
std::vector<Point> *curPoly;
|
||||
|
||||
|
||||
polygon.resize(1);
|
||||
curPoly = &polygon.back();
|
||||
curPoly->resize(sub->numlines);
|
||||
|
||||
for (unsigned i = 0; i < sub->numlines; i++)
|
||||
{
|
||||
polygon.resize(1);
|
||||
curPoly = &polygon.back();
|
||||
curPoly->push_back({ sub->firstline[i].v1->fX(), sub->firstline[i].v1->fY() });
|
||||
(*curPoly)[i] = { sub->firstline[i].v1->fX(), sub->firstline[i].v1->fY() };
|
||||
}
|
||||
auto indices = mapbox::earcut(polygon);
|
||||
for (auto vti : indices)
|
||||
|
|
|
@ -96,7 +96,7 @@ static RenderJobQueue jobQueue; // One static queue is sufficient here. This cod
|
|||
|
||||
void HWDrawInfo::WorkerThread()
|
||||
{
|
||||
sector_t fakefront, fakeback, *front, *back;
|
||||
sector_t *front, *back;
|
||||
|
||||
WTTotal.Clock();
|
||||
isWorkerThread = true; // for adding asserts in GL API code. The worker thread may never call any GL API.
|
||||
|
@ -118,6 +118,8 @@ void HWDrawInfo::WorkerThread()
|
|||
_mm_pause();
|
||||
_mm_pause();
|
||||
}
|
||||
// Note that the main thread MUST have prepared the fake sectors that get used below!
|
||||
// This worker thread cannot prepare them itself without costly synchronization.
|
||||
else switch (job->type)
|
||||
{
|
||||
case RenderJob::TerminateJob:
|
||||
|
@ -130,7 +132,7 @@ void HWDrawInfo::WorkerThread()
|
|||
SetupWall.Clock();
|
||||
wall.sub = job->sub;
|
||||
|
||||
front = hw_FakeFlat(job->sub->sector, &fakefront, in_area, false);
|
||||
front = hw_FakeFlat(job->sub->sector, in_area, false);
|
||||
auto seg = job->seg;
|
||||
if (seg->backsector)
|
||||
{
|
||||
|
@ -140,7 +142,7 @@ void HWDrawInfo::WorkerThread()
|
|||
}
|
||||
else
|
||||
{
|
||||
back = hw_FakeFlat(seg->backsector, &fakeback, in_area, true);
|
||||
back = hw_FakeFlat(seg->backsector, in_area, true);
|
||||
}
|
||||
}
|
||||
else back = nullptr;
|
||||
|
@ -156,7 +158,7 @@ void HWDrawInfo::WorkerThread()
|
|||
GLFlat flat;
|
||||
SetupFlat.Clock();
|
||||
flat.section = job->sub->section;
|
||||
front = hw_FakeFlat(job->sub->render_sector, &fakefront, in_area, false);
|
||||
front = hw_FakeFlat(job->sub->render_sector, in_area, false);
|
||||
flat.ProcessSector(this, front);
|
||||
SetupFlat.Unclock();
|
||||
break;
|
||||
|
@ -164,14 +166,14 @@ void HWDrawInfo::WorkerThread()
|
|||
|
||||
case RenderJob::SpriteJob:
|
||||
SetupSprite.Clock();
|
||||
front = hw_FakeFlat(job->sub->sector, &fakefront, in_area, false);
|
||||
front = hw_FakeFlat(job->sub->sector, in_area, false);
|
||||
RenderThings(job->sub, front);
|
||||
SetupSprite.Unclock();
|
||||
break;
|
||||
|
||||
case RenderJob::ParticleJob:
|
||||
SetupSprite.Clock();
|
||||
front = hw_FakeFlat(job->sub->sector, &fakefront, in_area, false);
|
||||
front = hw_FakeFlat(job->sub->sector, in_area, false);
|
||||
RenderParticles(job->sub, front);
|
||||
SetupSprite.Unclock();
|
||||
break;
|
||||
|
@ -228,7 +230,6 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip)
|
|||
#endif
|
||||
|
||||
sector_t * backsector = nullptr;
|
||||
sector_t bs;
|
||||
|
||||
if (portalclip)
|
||||
{
|
||||
|
@ -291,7 +292,7 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip)
|
|||
// clipping checks are only needed when the backsector is not the same as the front sector
|
||||
if (in_area == area_default) in_area = hw_CheckViewArea(seg->v1, seg->v2, seg->frontsector, seg->backsector);
|
||||
|
||||
backsector = hw_FakeFlat(seg->backsector, &bs, in_area, true);
|
||||
backsector = hw_FakeFlat(seg->backsector, in_area, true);
|
||||
|
||||
if (hw_CheckClip(seg->sidedef, currentsector, backsector))
|
||||
{
|
||||
|
@ -575,7 +576,6 @@ void HWDrawInfo::DoSubsector(subsector_t * sub)
|
|||
{
|
||||
sector_t * sector;
|
||||
sector_t * fakesector;
|
||||
sector_t fake;
|
||||
|
||||
#ifdef _DEBUG
|
||||
if (sub->sector->sectornum==931)
|
||||
|
@ -600,7 +600,7 @@ void HWDrawInfo::DoSubsector(subsector_t * sub)
|
|||
}
|
||||
if (mClipper->IsBlocked()) return; // if we are inside a stacked sector portal which hasn't unclipped anything yet.
|
||||
|
||||
fakesector=hw_FakeFlat(sector, &fake, in_area, false);
|
||||
fakesector=hw_FakeFlat(sector, in_area, false);
|
||||
|
||||
if (mClipPortal)
|
||||
{
|
||||
|
@ -677,7 +677,7 @@ void HWDrawInfo::DoSubsector(subsector_t * sub)
|
|||
sector = sub->render_sector;
|
||||
// the planes of this subsector are faked to belong to another sector
|
||||
// This means we need the heightsec parts and light info of the render sector, not the actual one.
|
||||
fakesector = hw_FakeFlat(sector, &fake, in_area, false);
|
||||
fakesector = hw_FakeFlat(sector, in_area, false);
|
||||
}
|
||||
|
||||
uint8_t &srf = section_renderflags[level.sections.SectionIndex(sub->section)];
|
||||
|
|
|
@ -95,7 +95,7 @@ void GLDecal::DrawDecal(HWDrawInfo *di, FRenderState &state)
|
|||
|
||||
for (unsigned k = 0; k < lightlist.Size(); k++)
|
||||
{
|
||||
secplane_t &lowplane = k == lightlist.Size() - 1 ? bottomplane : lightlist[k + 1].plane;
|
||||
secplane_t &lowplane = k == lightlist.Size() - 1 ? frontsector->floorplane : lightlist[k + 1].plane;
|
||||
|
||||
float low1 = lowplane.ZatPoint(dv[1].x, dv[1].y);
|
||||
float low2 = lowplane.ZatPoint(dv[2].x, dv[2].y);
|
||||
|
@ -404,7 +404,7 @@ void GLWall::ProcessDecal(HWDrawInfo *di, DBaseDecal *decal, const FVector3 &nor
|
|||
|
||||
gldecal->alpha = decal->Alpha;
|
||||
gldecal->zcenter = zpos - decalheight * 0.5f;
|
||||
gldecal->bottomplane = bottomplane;
|
||||
gldecal->frontsector = frontsector;
|
||||
gldecal->Normal = normal;
|
||||
gldecal->lightlist = lightlist;
|
||||
memcpy(gldecal->dv, dv, sizeof(dv));
|
||||
|
|
|
@ -193,8 +193,6 @@ private:
|
|||
subsector_t *currentsubsector; // used by the line processing code.
|
||||
sector_t *currentsector;
|
||||
|
||||
sector_t fakesec; // this is a struct member because it gets used in recursively called functions so it cannot be put on the stack.
|
||||
|
||||
void WorkerThread();
|
||||
|
||||
void UnclipSubsector(subsector_t *sub);
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "hwrenderer/utility/hw_clock.h"
|
||||
#include "hw_renderstate.h"
|
||||
#include "hw_drawinfo.h"
|
||||
#include "hw_fakeflat.h"
|
||||
|
||||
FMemArena RenderDataAllocator(1024*1024); // Use large blocks to reduce allocation time.
|
||||
|
||||
|
|
|
@ -186,7 +186,6 @@ public:
|
|||
};
|
||||
|
||||
|
||||
secplane_t topplane, bottomplane; // we need to save these to pass them to the shader for calculating glows.
|
||||
|
||||
// these are not the same as ytop and ybottom!!!
|
||||
float zceil[2];
|
||||
|
@ -198,6 +197,7 @@ public:
|
|||
public:
|
||||
seg_t * seg; // this gives the easiest access to all other structs involved
|
||||
subsector_t * sub; // For polyobjects
|
||||
sector_t *frontsector, *backsector;
|
||||
//private:
|
||||
|
||||
void PutWall(HWDrawInfo *di, bool translucent);
|
||||
|
@ -411,7 +411,7 @@ struct GLDecal
|
|||
int rellight;
|
||||
float alpha;
|
||||
FColormap Colormap;
|
||||
secplane_t bottomplane;
|
||||
sector_t *frontsector;
|
||||
FVector3 Normal;
|
||||
|
||||
void DrawDecal(HWDrawInfo *di, FRenderState &state);
|
||||
|
|
|
@ -36,6 +36,9 @@
|
|||
#include "hwrenderer/utility/hw_cvars.h"
|
||||
#include "r_utility.h"
|
||||
|
||||
static sector_t **fakesectorbuffer;
|
||||
|
||||
extern thread_local bool isWorkerThread;
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
@ -182,6 +185,24 @@ area_t hw_CheckViewArea(vertex_t *v1, vertex_t *v2, sector_t *frontsector, secto
|
|||
return area_default;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
static FMemArena FakeSectorAllocator(20 * sizeof(sector_t));
|
||||
|
||||
static sector_t *allocateSector(sector_t *sec)
|
||||
{
|
||||
if (fakesectorbuffer == nullptr)
|
||||
{
|
||||
fakesectorbuffer = (sector_t**)FakeSectorAllocator.Alloc(level.sectors.Size() * sizeof(sector_t*));
|
||||
memset(fakesectorbuffer, 0, level.sectors.Size() * sizeof(sector_t*));
|
||||
}
|
||||
auto sectornum = sec->sectornum;
|
||||
fakesectorbuffer[sectornum] = (sector_t*)FakeSectorAllocator.Alloc(sizeof(sector_t));
|
||||
return fakesectorbuffer[sectornum];
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
@ -189,7 +210,8 @@ area_t hw_CheckViewArea(vertex_t *v1, vertex_t *v2, sector_t *frontsector, secto
|
|||
// by hardware rendering
|
||||
//
|
||||
//==========================================================================
|
||||
sector_t * hw_FakeFlat(sector_t * sec, sector_t * dest, area_t in_area, bool back)
|
||||
|
||||
sector_t * hw_FakeFlat(sector_t * sec, area_t in_area, bool back, sector_t *localcopy)
|
||||
{
|
||||
if (!sec->GetHeightSec() || sec->heightsec==sec)
|
||||
{
|
||||
|
@ -197,6 +219,8 @@ sector_t * hw_FakeFlat(sector_t * sec, sector_t * dest, area_t in_area, bool bac
|
|||
// visual glitches because upper amd lower textures overlap.
|
||||
if (back && (sec->MoreFlags & SECMF_OVERLAPPING))
|
||||
{
|
||||
if (fakesectorbuffer && fakesectorbuffer[sec->sectornum]) return fakesectorbuffer[sec->sectornum];
|
||||
auto dest = localcopy? localcopy : allocateSector(sec);
|
||||
*dest = *sec;
|
||||
dest->ceilingplane = sec->floorplane;
|
||||
dest->ceilingplane.FlipVert();
|
||||
|
@ -215,6 +239,12 @@ sector_t * hw_FakeFlat(sector_t * sec, sector_t * dest, area_t in_area, bool bac
|
|||
}
|
||||
#endif
|
||||
|
||||
if (fakesectorbuffer && fakesectorbuffer[sec->sectornum])
|
||||
{
|
||||
return fakesectorbuffer[sec->sectornum];
|
||||
}
|
||||
assert(!(isWorkerThread && localcopy == nullptr));
|
||||
|
||||
if (in_area==area_above)
|
||||
{
|
||||
if (sec->heightsec->MoreFlags&SECMF_FAKEFLOORONLY /*|| sec->GetTexture(sector_t::ceiling)==skyflatnum*/) in_area=area_normal;
|
||||
|
@ -223,11 +253,8 @@ sector_t * hw_FakeFlat(sector_t * sec, sector_t * dest, area_t in_area, bool bac
|
|||
int diffTex = (sec->heightsec->MoreFlags & SECMF_CLIPFAKEPLANES);
|
||||
sector_t * s = sec->heightsec;
|
||||
|
||||
#if 0
|
||||
*dest=*sec; // This will invoke the copy operator which isn't really needed here. Memcpy is faster.
|
||||
#else
|
||||
memcpy(dest, sec, sizeof(sector_t));
|
||||
#endif
|
||||
auto dest = localcopy ? localcopy : allocateSector(sec);
|
||||
*dest = *sec;
|
||||
|
||||
// Replace floor and ceiling height with control sector's heights.
|
||||
if (diffTex)
|
||||
|
@ -309,7 +336,7 @@ sector_t * hw_FakeFlat(sector_t * sec, sector_t * dest, area_t in_area, bool bac
|
|||
dest->lightlevel = s->lightlevel;
|
||||
}
|
||||
|
||||
if (!back)
|
||||
//if (!back)
|
||||
{
|
||||
dest->SetTexture(sector_t::floor, diffTex ? sec->GetTexture(sector_t::floor) : s->GetTexture(sector_t::floor), false);
|
||||
dest->planes[sector_t::floor].xform = s->planes[sector_t::floor].xform;
|
||||
|
@ -362,7 +389,7 @@ sector_t * hw_FakeFlat(sector_t * sec, sector_t * dest, area_t in_area, bool bac
|
|||
dest->lightlevel = s->lightlevel;
|
||||
}
|
||||
|
||||
if (!back)
|
||||
//if (!back)
|
||||
{
|
||||
dest->SetTexture(sector_t::ceiling, diffTex ? sec->GetTexture(sector_t::ceiling) : s->GetTexture(sector_t::ceiling), false);
|
||||
dest->SetTexture(sector_t::floor, s->GetTexture(sector_t::ceiling), false);
|
||||
|
@ -386,3 +413,10 @@ sector_t * hw_FakeFlat(sector_t * sec, sector_t * dest, area_t in_area, bool bac
|
|||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
void hw_ClearFakeFlat()
|
||||
{
|
||||
FakeSectorAllocator.FreeAll();
|
||||
fakesectorbuffer = nullptr;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ enum area_t : int
|
|||
|
||||
// Global functions.
|
||||
bool hw_CheckClip(side_t * sidedef, sector_t * frontsector, sector_t * backsector);
|
||||
sector_t * hw_FakeFlat(sector_t * sec, sector_t * dest, area_t in_area, bool back);
|
||||
void hw_ClearFakeFlat();
|
||||
sector_t * hw_FakeFlat(sector_t * sec, area_t in_area, bool back, sector_t *localcopy = nullptr);
|
||||
area_t hw_CheckViewArea(vertex_t *v1, vertex_t *v2, sector_t *frontsector, sector_t *backsector);
|
||||
|
||||
|
|
|
@ -38,8 +38,7 @@
|
|||
#include "hwrenderer/data/flatvertices.h"
|
||||
#include "hwrenderer/dynlights/hw_lightbuffer.h"
|
||||
#include "hwrenderer/scene/hw_portal.h"
|
||||
|
||||
sector_t * hw_FakeFlat(sector_t * sec, sector_t * dest, area_t in_area, bool back);
|
||||
#include "hw_fakeflat.h"
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
@ -53,32 +52,31 @@ void HWDrawInfo::DispatchRenderHacks()
|
|||
TMap<int, gl_floodrendernode*>::Pair *fpair;
|
||||
TMap<int, gl_subsectorrendernode*>::Iterator ofi(otherFloorPlanes);
|
||||
GLFlat glflat;
|
||||
sector_t fakesec;
|
||||
glflat.section = nullptr;
|
||||
while (ofi.NextPair(pair))
|
||||
{
|
||||
auto sec = hw_FakeFlat(&level.sectors[pair->Key], &fakesec, in_area, false);
|
||||
auto sec = hw_FakeFlat(&level.sectors[pair->Key], in_area, false);
|
||||
glflat.ProcessSector(this, sec, SSRF_RENDERFLOOR | SSRF_PLANEHACK);
|
||||
}
|
||||
|
||||
TMap<int, gl_subsectorrendernode*>::Iterator oci(otherCeilingPlanes);
|
||||
while (ofi.NextPair(pair))
|
||||
while (oci.NextPair(pair))
|
||||
{
|
||||
auto sec = hw_FakeFlat(&level.sectors[pair->Key], &fakesec, in_area, false);
|
||||
auto sec = hw_FakeFlat(&level.sectors[pair->Key], in_area, false);
|
||||
glflat.ProcessSector(this, sec, SSRF_RENDERCEILING | SSRF_PLANEHACK);
|
||||
}
|
||||
|
||||
TMap<int, gl_floodrendernode*>::Iterator ffi(floodFloorSegs);
|
||||
while (ffi.NextPair(fpair))
|
||||
{
|
||||
auto sec = hw_FakeFlat(&level.sectors[fpair->Key], &fakesec, in_area, false);
|
||||
auto sec = hw_FakeFlat(&level.sectors[fpair->Key], in_area, false);
|
||||
glflat.ProcessSector(this, sec, SSRF_RENDERFLOOR | SSRF_FLOODHACK);
|
||||
}
|
||||
|
||||
TMap<int, gl_floodrendernode*>::Iterator fci(floodCeilingSegs);
|
||||
while (fci.NextPair(fpair))
|
||||
{
|
||||
auto sec = hw_FakeFlat(&level.sectors[fpair->Key], &fakesec, in_area, false);
|
||||
auto sec = hw_FakeFlat(&level.sectors[fpair->Key], in_area, false);
|
||||
glflat.ProcessSector(this, sec, SSRF_RENDERCEILING | SSRF_FLOODHACK);
|
||||
}
|
||||
}
|
||||
|
@ -336,7 +334,7 @@ bool HWDrawInfo::DoOneSectorUpper(subsector_t * subsec, float Planez, area_t in_
|
|||
// Note: if this is a real line between sectors
|
||||
// we can be sure that render_sector is the real sector!
|
||||
|
||||
sector_t * sec = hw_FakeFlat(seg->backsector, &fakesec, in_area, true);
|
||||
sector_t * sec = hw_FakeFlat(seg->backsector, in_area, true);
|
||||
|
||||
// Don't bother with slopes
|
||||
if (sec->ceilingplane.isSlope()) return false;
|
||||
|
@ -394,7 +392,7 @@ bool HWDrawInfo::DoOneSectorLower(subsector_t * subsec, float Planez, area_t in_
|
|||
// Note: if this is a real line between sectors
|
||||
// we can be sure that render_sector is the real sector!
|
||||
|
||||
sector_t * sec = hw_FakeFlat(seg->backsector, &fakesec, in_area, true);
|
||||
sector_t * sec = hw_FakeFlat(seg->backsector, in_area, true);
|
||||
|
||||
// Don't bother with slopes
|
||||
if (sec->floorplane.isSlope()) return false;
|
||||
|
@ -453,7 +451,7 @@ bool HWDrawInfo::DoFakeBridge(subsector_t * subsec, float Planez, area_t in_area
|
|||
// Note: if this is a real line between sectors
|
||||
// we can be sure that render_sector is the real sector!
|
||||
|
||||
sector_t * sec = hw_FakeFlat(seg->backsector, &fakesec, in_area, true);
|
||||
sector_t * sec = hw_FakeFlat(seg->backsector, in_area, true);
|
||||
|
||||
// Don't bother with slopes
|
||||
if (sec->floorplane.isSlope()) return false;
|
||||
|
@ -506,7 +504,7 @@ bool HWDrawInfo::DoFakeCeilingBridge(subsector_t * subsec, float Planez, area_t
|
|||
// Note: if this is a real line between sectors
|
||||
// we can be sure that render_sector is the real sector!
|
||||
|
||||
sector_t * sec = hw_FakeFlat(seg->backsector, &fakesec, in_area, true);
|
||||
sector_t * sec = hw_FakeFlat(seg->backsector, in_area, true);
|
||||
|
||||
// Don't bother with slopes
|
||||
if (sec->ceilingplane.isSlope()) return false;
|
||||
|
@ -538,8 +536,6 @@ bool HWDrawInfo::DoFakeCeilingBridge(subsector_t * subsec, float Planez, area_t
|
|||
//==========================================================================
|
||||
void HWDrawInfo::HandleMissingTextures(area_t in_area)
|
||||
{
|
||||
sector_t fake;
|
||||
|
||||
for (unsigned int i = 0; i < MissingUpperTextures.Size(); i++)
|
||||
{
|
||||
if (!MissingUpperTextures[i].seg) continue;
|
||||
|
@ -589,7 +585,7 @@ void HWDrawInfo::HandleMissingTextures(area_t in_area)
|
|||
|
||||
{
|
||||
// It isn't a hole. Now check whether it might be a fake bridge
|
||||
sector_t * fakesector = hw_FakeFlat(MissingUpperTextures[i].seg->frontsector, &fake, in_area, false);
|
||||
sector_t * fakesector = hw_FakeFlat(MissingUpperTextures[i].seg->frontsector, in_area, false);
|
||||
float planez = (float)fakesector->GetPlaneTexZ(sector_t::ceiling);
|
||||
|
||||
backsub->validcount = validcount;
|
||||
|
@ -655,7 +651,7 @@ void HWDrawInfo::HandleMissingTextures(area_t in_area)
|
|||
|
||||
{
|
||||
// It isn't a hole. Now check whether it might be a fake bridge
|
||||
sector_t * fakesector = hw_FakeFlat(MissingLowerTextures[i].seg->frontsector, &fake, in_area, false);
|
||||
sector_t * fakesector = hw_FakeFlat(MissingLowerTextures[i].seg->frontsector, in_area, false);
|
||||
float planez = (float)fakesector->GetPlaneTexZ(sector_t::floor);
|
||||
|
||||
backsub->validcount = validcount;
|
||||
|
@ -729,9 +725,8 @@ void HWDrawInfo::CreateFloodPoly(wallseg * ws, FFlatVertex *vertices, float plan
|
|||
void HWDrawInfo::PrepareUpperGap(seg_t * seg)
|
||||
{
|
||||
wallseg ws;
|
||||
sector_t ffake, bfake;
|
||||
sector_t * fakefsector = hw_FakeFlat(seg->frontsector, &ffake, in_area, true);
|
||||
sector_t * fakebsector = hw_FakeFlat(seg->backsector, &bfake, in_area, false);
|
||||
sector_t * fakefsector = hw_FakeFlat(seg->frontsector, in_area, false);
|
||||
sector_t * fakebsector = hw_FakeFlat(seg->backsector, in_area, true);
|
||||
|
||||
vertex_t * v1, *v2;
|
||||
|
||||
|
@ -786,9 +781,8 @@ void HWDrawInfo::PrepareUpperGap(seg_t * seg)
|
|||
void HWDrawInfo::PrepareLowerGap(seg_t * seg)
|
||||
{
|
||||
wallseg ws;
|
||||
sector_t ffake, bfake;
|
||||
sector_t * fakefsector = hw_FakeFlat(seg->frontsector, &ffake, in_area, true);
|
||||
sector_t * fakebsector = hw_FakeFlat(seg->backsector, &bfake, in_area, false);
|
||||
sector_t * fakefsector = hw_FakeFlat(seg->frontsector, in_area, false);
|
||||
sector_t * fakebsector = hw_FakeFlat(seg->backsector, in_area, true);
|
||||
|
||||
vertex_t * v1, *v2;
|
||||
|
||||
|
@ -826,13 +820,13 @@ void HWDrawInfo::PrepareLowerGap(seg_t * seg)
|
|||
CreateFloodPoly(&ws, vertices.first+4, ws.z1, fakebsector, false);
|
||||
|
||||
gl_floodrendernode *node = NewFloodRenderNode();
|
||||
auto pNode = floodCeilingSegs.CheckKey(fakebsector->sectornum);
|
||||
auto pNode = floodFloorSegs.CheckKey(fakebsector->sectornum);
|
||||
|
||||
node->next = pNode? *pNode : nullptr;
|
||||
|
||||
node->seg = seg;
|
||||
node->vertexindex = vertices.second;
|
||||
floodCeilingSegs[fakebsector->sectornum] = node;
|
||||
floodFloorSegs[fakebsector->sectornum] = node;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -1220,7 +1214,7 @@ void HWDrawInfo::CollectSectorStacksCeiling(subsector_t * sub, sector_t * anchor
|
|||
if (sub->numlines>2 && !(ss_renderflags[sub->Index()]&SSRF_PROCESSED)) return;
|
||||
|
||||
// Must be the exact same visplane
|
||||
sector_t * me = hw_FakeFlat(sub->render_sector, &fakesec, in_area, false);
|
||||
sector_t * me = hw_FakeFlat(sub->render_sector, in_area, false);
|
||||
if (me->GetTexture(sector_t::ceiling) != anchor->GetTexture(sector_t::ceiling) ||
|
||||
me->ceilingplane != anchor->ceilingplane ||
|
||||
me->GetCeilingLight() != anchor->GetCeilingLight() ||
|
||||
|
@ -1264,7 +1258,7 @@ void HWDrawInfo::CollectSectorStacksFloor(subsector_t * sub, sector_t * anchor,
|
|||
if (sub->numlines>2 && !(ss_renderflags[sub->Index()]&SSRF_PROCESSED)) return;
|
||||
|
||||
// Must be the exact same visplane
|
||||
sector_t * me = hw_FakeFlat(sub->render_sector, &fakesec, in_area, false);
|
||||
sector_t * me = hw_FakeFlat(sub->render_sector, in_area, false);
|
||||
if (me->GetTexture(sector_t::floor) != anchor->GetTexture(sector_t::floor) ||
|
||||
me->floorplane != anchor->floorplane ||
|
||||
me->GetFloorLight() != anchor->GetFloorLight() ||
|
||||
|
@ -1303,7 +1297,7 @@ void HWDrawInfo::ProcessSectorStacks(area_t in_area)
|
|||
validcount++;
|
||||
for (i=0;i<CeilingStacks.Size (); i++)
|
||||
{
|
||||
sector_t *sec = hw_FakeFlat(CeilingStacks[i], &fakesec, in_area, false);
|
||||
sector_t *sec = hw_FakeFlat(CeilingStacks[i], in_area, false);
|
||||
auto portal = sec->GetPortalGroup(sector_t::ceiling);
|
||||
if (portal != NULL) for(int k=0;k<sec->subsectorcount;k++)
|
||||
{
|
||||
|
@ -1347,7 +1341,7 @@ void HWDrawInfo::ProcessSectorStacks(area_t in_area)
|
|||
validcount++;
|
||||
for (i=0;i<FloorStacks.Size (); i++)
|
||||
{
|
||||
sector_t *sec = hw_FakeFlat(FloorStacks[i], &fakesec, in_area, false);
|
||||
sector_t *sec = hw_FakeFlat(FloorStacks[i], in_area, false);
|
||||
auto portal = sec->GetPortalGroup(sector_t::floor);
|
||||
if (portal != NULL) for(int k=0;k<sec->subsectorcount;k++)
|
||||
{
|
||||
|
|
|
@ -127,6 +127,7 @@ protected:
|
|||
uint8_t mFogEnabled;
|
||||
uint8_t mTextureEnabled:1;
|
||||
uint8_t mGlowEnabled : 1;
|
||||
uint8_t mGradientEnabled : 1;
|
||||
uint8_t mBrightmapEnabled : 1;
|
||||
uint8_t mModelMatrixEnabled : 1;
|
||||
uint8_t mTextureMatrixEnabled : 1;
|
||||
|
@ -147,6 +148,7 @@ protected:
|
|||
FStateVec4 mColor;
|
||||
FStateVec4 mGlowTop, mGlowBottom;
|
||||
FStateVec4 mGlowTopPlane, mGlowBottomPlane;
|
||||
FStateVec4 mGradientTopPlane, mGradientBottomPlane;
|
||||
FStateVec4 mSplitTopPlane, mSplitBottomPlane;
|
||||
PalEntry mFogColor;
|
||||
PalEntry mObjectColor;
|
||||
|
@ -172,7 +174,7 @@ public:
|
|||
void Reset()
|
||||
{
|
||||
mTextureEnabled = true;
|
||||
mBrightmapEnabled = mFogEnabled = mGlowEnabled = false;
|
||||
mGradientEnabled = mBrightmapEnabled = mFogEnabled = mGlowEnabled = false;
|
||||
mFogColor.d = -1;
|
||||
mTextureMode = -1;
|
||||
mDesaturation = 0;
|
||||
|
@ -201,6 +203,8 @@ public:
|
|||
mGlowBottom.Set(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
mGlowTopPlane.Set(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
mGlowBottomPlane.Set(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
mGradientTopPlane.Set(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
mGradientBottomPlane.Set(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
mSplitTopPlane.Set(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
mSplitBottomPlane.Set(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
mDynColor.Set(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
|
@ -290,6 +294,11 @@ public:
|
|||
mGlowEnabled = on;
|
||||
}
|
||||
|
||||
void EnableGradient(bool on)
|
||||
{
|
||||
mGradientEnabled = on;
|
||||
}
|
||||
|
||||
void EnableBrightmap(bool on)
|
||||
{
|
||||
mBrightmapEnabled = on;
|
||||
|
@ -324,18 +333,26 @@ public:
|
|||
|
||||
void SetGlowPlanes(const secplane_t &top, const secplane_t &bottom)
|
||||
{
|
||||
DVector3 tn = top.Normal();
|
||||
DVector3 bn = bottom.Normal();
|
||||
mGlowTopPlane.Set((float)tn.X, (float)tn.Y, (float)(1. / tn.Z), (float)top.fD());
|
||||
mGlowBottomPlane.Set((float)bn.X, (float)bn.Y, (float)(1. / bn.Z), (float)bottom.fD());
|
||||
auto &tn = top.Normal();
|
||||
auto &bn = bottom.Normal();
|
||||
mGlowTopPlane.Set((float)tn.X, (float)tn.Y, (float)top.negiC, (float)top.fD());
|
||||
mGlowBottomPlane.Set((float)bn.X, (float)bn.Y, (float)bottom.negiC, (float)bottom.fD());
|
||||
}
|
||||
|
||||
void SetGradientPlanes(const secplane_t &top, const secplane_t &bottom)
|
||||
{
|
||||
auto &tn = top.Normal();
|
||||
auto &bn = bottom.Normal();
|
||||
mGradientTopPlane.Set((float)tn.X, (float)tn.Y, (float)top.negiC, (float)top.fD());
|
||||
mGradientBottomPlane.Set((float)bn.X, (float)bn.Y, (float)bottom.negiC, (float)bottom.fD());
|
||||
}
|
||||
|
||||
void SetSplitPlanes(const secplane_t &top, const secplane_t &bottom)
|
||||
{
|
||||
DVector3 tn = top.Normal();
|
||||
DVector3 bn = bottom.Normal();
|
||||
mSplitTopPlane.Set((float)tn.X, (float)tn.Y, (float)(1. / tn.Z), (float)top.fD());
|
||||
mSplitBottomPlane.Set((float)bn.X, (float)bn.Y, (float)(1. / bn.Z), (float)bottom.fD());
|
||||
auto &tn = top.Normal();
|
||||
auto &bn = bottom.Normal();
|
||||
mSplitTopPlane.Set((float)tn.X, (float)tn.Y, (float)top.negiC, (float)top.fD());
|
||||
mSplitBottomPlane.Set((float)bn.X, (float)bn.Y, (float)bottom.negiC, (float)bottom.fD());
|
||||
}
|
||||
|
||||
void SetDynLight(float r, float g, float b)
|
||||
|
|
|
@ -207,8 +207,8 @@ void GLSprite::DrawSprite(HWDrawInfo *di, FRenderState &state, bool translucent)
|
|||
state.EnableSplit(true);
|
||||
}
|
||||
|
||||
secplane_t bottomp = { { 0, 0, -1. }, bottomclip };
|
||||
secplane_t topp = { { 0, 0, -1. }, topclip };
|
||||
secplane_t bottomp = { { 0, 0, -1. }, bottomclip, 1. };
|
||||
secplane_t topp = { { 0, 0, -1. }, topclip, 1. };
|
||||
for (unsigned i = 0; i < iter; i++)
|
||||
{
|
||||
if (lightlist)
|
||||
|
@ -755,7 +755,9 @@ void GLSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t
|
|||
|
||||
if (sector->sectornum != thing->Sector->sectornum && !thruportal)
|
||||
{
|
||||
rendersector = hw_FakeFlat(thing->Sector, &rs, in_area, false);
|
||||
// This cannot create a copy in the fake sector cache because it'd interfere with the main thread, so provide a local buffer for the copy.
|
||||
// Adding synchronization for this one case would cost more than it might save if the result here could be cached.
|
||||
rendersector = hw_FakeFlat(thing->Sector, in_area, false, &rs);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1287,7 +1289,8 @@ void HWDrawInfo::ProcessActorsInPortal(FLinePortalSpan *glport, area_t in_area)
|
|||
th->Prev += newpos - savedpos;
|
||||
|
||||
GLSprite spr;
|
||||
spr.Process(this, th, hw_FakeFlat(th->Sector, &fakesector, in_area, false), in_area, 2);
|
||||
// This is called from the worker thread and must not alter the fake sector cache.
|
||||
spr.Process(this, th, hw_FakeFlat(th->Sector, in_area, false, &fakesector), in_area, 2);
|
||||
th->Angles.Yaw = savedangle;
|
||||
th->SetXYZ(savedpos);
|
||||
th->Prev -= newpos - savedpos;
|
||||
|
|
|
@ -130,6 +130,20 @@ void GLWall::RenderMirrorSurface(HWDrawInfo *di, FRenderState &state)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
static const uint8_t renderwalltotier[] =
|
||||
{
|
||||
side_t::none,
|
||||
side_t::top,
|
||||
side_t::mid,
|
||||
side_t::mid,
|
||||
side_t::bottom,
|
||||
side_t::none,
|
||||
side_t::none,
|
||||
side_t::mid,
|
||||
side_t::none,
|
||||
side_t::mid,
|
||||
};
|
||||
|
||||
void GLWall::RenderTexturedWall(HWDrawInfo *di, FRenderState &state, int rflags)
|
||||
{
|
||||
int tmode = state.GetTextureMode();
|
||||
|
@ -139,8 +153,8 @@ void GLWall::RenderTexturedWall(HWDrawInfo *di, FRenderState &state, int rflags)
|
|||
{
|
||||
state.EnableGlow(true);
|
||||
state.SetGlowParams(topglowcolor, bottomglowcolor);
|
||||
state.SetGlowPlanes(frontsector->ceilingplane, frontsector->floorplane);
|
||||
}
|
||||
state.SetGlowPlanes(topplane, bottomplane);
|
||||
state.SetMaterial(gltexture, flags & 3, 0, -1);
|
||||
|
||||
if (type == RENDERWALL_M2SNF)
|
||||
|
@ -151,8 +165,41 @@ void GLWall::RenderTexturedWall(HWDrawInfo *di, FRenderState &state, int rflags)
|
|||
}
|
||||
state.SetFog(255, 0, di->isFullbrightScene(), nullptr, false);
|
||||
}
|
||||
state.SetObjectColor(seg->frontsector->SpecialColors[sector_t::walltop] | 0xff000000);
|
||||
state.SetObjectColor2(seg->frontsector->SpecialColors[sector_t::wallbottom] | 0xff000000);
|
||||
if (type != RENDERWALL_COLOR)
|
||||
{
|
||||
auto side = seg->sidedef;
|
||||
auto tierndx = renderwalltotier[type];
|
||||
auto &tier = side->textures[tierndx];
|
||||
PalEntry color1 = side->GetSpecialColor(tierndx, side_t::walltop, frontsector);
|
||||
PalEntry color2 = side->GetSpecialColor(tierndx, side_t::wallbottom, frontsector);
|
||||
state.SetObjectColor(color1);
|
||||
state.SetObjectColor2(color2);
|
||||
if (color1 != color2)
|
||||
{
|
||||
// Do gradient setup only if there actually is a gradient.
|
||||
|
||||
state.EnableGradient(true);
|
||||
if ((tier.flags & side_t::part::ClampGradient) && backsector)
|
||||
{
|
||||
if (tierndx == side_t::top)
|
||||
{
|
||||
state.SetGradientPlanes(frontsector->ceilingplane, backsector->ceilingplane);
|
||||
}
|
||||
else if (tierndx == side_t::mid)
|
||||
{
|
||||
state.SetGradientPlanes(backsector->ceilingplane, backsector->floorplane);
|
||||
}
|
||||
else // side_t::bottom:
|
||||
{
|
||||
state.SetGradientPlanes(backsector->floorplane, frontsector->floorplane);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
state.SetGradientPlanes(frontsector->ceilingplane, frontsector->floorplane);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float absalpha = fabsf(alpha);
|
||||
if (lightlist == nullptr)
|
||||
|
@ -167,14 +214,14 @@ void GLWall::RenderTexturedWall(HWDrawInfo *di, FRenderState &state, int rflags)
|
|||
|
||||
for (unsigned i = 0; i < lightlist->Size(); i++)
|
||||
{
|
||||
secplane_t &lowplane = i == (*lightlist).Size() - 1 ? bottomplane : (*lightlist)[i + 1].plane;
|
||||
secplane_t &lowplane = i == (*lightlist).Size() - 1 ? frontsector->floorplane : (*lightlist)[i + 1].plane;
|
||||
// this must use the exact same calculation method as GLWall::Process etc.
|
||||
float low1 = lowplane.ZatPoint(vertexes[0]);
|
||||
float low2 = lowplane.ZatPoint(vertexes[1]);
|
||||
|
||||
if (low1 < ztop[0] || low2 < ztop[1])
|
||||
{
|
||||
int thisll = (*lightlist)[i].caster != NULL ? hw_ClampLight(*(*lightlist)[i].p_lightlevel) : lightlevel;
|
||||
int thisll = (*lightlist)[i].caster != nullptr ? hw_ClampLight(*(*lightlist)[i].p_lightlevel) : lightlevel;
|
||||
FColormap thiscm;
|
||||
thiscm.FadeColor = Colormap.FadeColor;
|
||||
thiscm.FogDensity = Colormap.FogDensity;
|
||||
|
@ -193,6 +240,7 @@ void GLWall::RenderTexturedWall(HWDrawInfo *di, FRenderState &state, int rflags)
|
|||
state.SetObjectColor2(0);
|
||||
state.SetTextureMode(tmode);
|
||||
state.EnableGlow(false);
|
||||
state.EnableGradient(false);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -1799,6 +1847,8 @@ void GLWall::Process(HWDrawInfo *di, seg_t *seg, sector_t * frontsector, sector_
|
|||
// note: we always have a valid sidedef and linedef reference when getting here.
|
||||
|
||||
this->seg = seg;
|
||||
this->frontsector = frontsector;
|
||||
this->backsector = backsector;
|
||||
vertindex = 0;
|
||||
vertcount = 0;
|
||||
|
||||
|
@ -1893,8 +1943,6 @@ void GLWall::Process(HWDrawInfo *di, seg_t *seg, sector_t * frontsector, sector_
|
|||
|
||||
|
||||
if (frontsector->GetWallGlow(topglowcolor, bottomglowcolor)) flags |= GLWF_GLOW;
|
||||
topplane = frontsector->ceilingplane;
|
||||
bottomplane = frontsector->floorplane;
|
||||
|
||||
zfloor[0] = ffh1 = segfront->floorplane.ZatPoint(v1);
|
||||
zfloor[1] = ffh2 = segfront->floorplane.ZatPoint(v2);
|
||||
|
@ -2104,6 +2152,8 @@ void GLWall::ProcessLowerMiniseg(HWDrawInfo *di, seg_t *seg, sector_t * frontsec
|
|||
if (bfh > ffh)
|
||||
{
|
||||
this->seg = seg;
|
||||
this->frontsector = frontsector;
|
||||
this->backsector = backsector;
|
||||
this->sub = NULL;
|
||||
|
||||
vertex_t * v1 = seg->v1;
|
||||
|
@ -2129,8 +2179,6 @@ void GLWall::ProcessLowerMiniseg(HWDrawInfo *di, seg_t *seg, sector_t * frontsec
|
|||
Colormap = frontsector->Colormap;
|
||||
|
||||
if (frontsector->GetWallGlow(topglowcolor, bottomglowcolor)) flags |= GLWF_GLOW;
|
||||
topplane = frontsector->ceilingplane;
|
||||
bottomplane = frontsector->floorplane;
|
||||
dynlightindex = -1;
|
||||
|
||||
zfloor[0] = zfloor[1] = ffh;
|
||||
|
|
|
@ -222,8 +222,7 @@ static WeaponLighting GetWeaponLighting(sector_t *viewsector, const DVector3 &po
|
|||
}
|
||||
else
|
||||
{
|
||||
sector_t fs;
|
||||
auto fakesec = hw_FakeFlat(viewsector, &fs, in_area, false);
|
||||
auto fakesec = hw_FakeFlat(viewsector, in_area, false);
|
||||
|
||||
// calculate light level for weapon sprites
|
||||
l.lightlevel = hw_ClampLight(fakesec->lightlevel);
|
||||
|
|
|
@ -630,6 +630,26 @@ xx(hidden)
|
|||
xx(blocksight)
|
||||
xx(blockhitscan)
|
||||
|
||||
xx(nogradient_top)
|
||||
xx(flipgradient_top)
|
||||
xx(clampgradient_top)
|
||||
xx(useowncolors_top)
|
||||
xx(uppercolor_top)
|
||||
xx(lowercolor_top)
|
||||
xx(nogradient_mid)
|
||||
xx(flipgradient_mid)
|
||||
xx(clampgradient_mid)
|
||||
xx(useowncolors_mid)
|
||||
xx(uppercolor_mid)
|
||||
xx(lowercolor_mid)
|
||||
xx(nogradient_bottom)
|
||||
xx(flipgradient_bottom)
|
||||
xx(clampgradient_bottom)
|
||||
xx(useowncolors_bottom)
|
||||
xx(uppercolor_bottom)
|
||||
xx(lowercolor_bottom)
|
||||
|
||||
|
||||
xx(Renderstyle)
|
||||
|
||||
xx(ceilingplane_a)
|
||||
|
|
|
@ -4564,6 +4564,20 @@ DEFINE_ACTION_FUNCTION(AActor, A_RaiseSelf)
|
|||
ACTION_RETURN_BOOL(P_Thing_Raise(self, NULL, (flags & RF_NOCHECKPOSITION)));
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// RaiseActor
|
||||
//
|
||||
// Generalized version that allows passing pointers for ZScript's sake.
|
||||
//===========================================================================
|
||||
DEFINE_ACTION_FUNCTION(AActor, RaiseActor)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_OBJECT(other, AActor);
|
||||
PARAM_INT_DEF(flags);
|
||||
ACTION_RETURN_BOOL(P_Thing_Raise(other, self, (flags & RF_NOCHECKPOSITION)));
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// CanRaise
|
||||
|
|
|
@ -2757,11 +2757,63 @@ void A_DoChase (AActor *actor, bool fastchase, FState *meleestate, FState *missi
|
|||
actor->flags &= ~MF_INCHASE;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// CanResurrect
|
||||
//
|
||||
// Checks if an actor can resurrect with another one, calling virtual script
|
||||
// functions to check.
|
||||
//
|
||||
//==========================================================================
|
||||
// [MC] Code is almost a duplicate of CanCollideWith but with changes to
|
||||
// accommodate checking of just one actor.
|
||||
bool P_CanResurrect(AActor *tmthing, AActor *thing)
|
||||
{
|
||||
if (tmthing == nullptr)
|
||||
return false;
|
||||
|
||||
static unsigned VIndex = ~0u;
|
||||
if (VIndex == ~0u)
|
||||
{
|
||||
VIndex = GetVirtualIndex(RUNTIME_CLASS(AActor), "CanResurrect");
|
||||
assert(VIndex != ~0u);
|
||||
}
|
||||
|
||||
VMValue params[3] = { tmthing, thing, false };
|
||||
VMReturn ret;
|
||||
int retval;
|
||||
ret.IntAt(&retval);
|
||||
|
||||
auto clss = tmthing->GetClass();
|
||||
VMFunction *func = clss->Virtuals.Size() > VIndex ? clss->Virtuals[VIndex] : nullptr;
|
||||
if (func != nullptr)
|
||||
{
|
||||
VMCall(func, params, 3, &ret, 1);
|
||||
if (!retval) return false;
|
||||
}
|
||||
|
||||
// Pointless to be running it again if it's just self.
|
||||
if (thing == nullptr || thing == tmthing)
|
||||
return true;
|
||||
|
||||
std::swap(params[0].a, params[1].a);
|
||||
params[2].i = true;
|
||||
|
||||
// re-get for the other actor.
|
||||
clss = thing->GetClass();
|
||||
func = clss->Virtuals.Size() > VIndex ? clss->Virtuals[VIndex] : nullptr;
|
||||
if (func != nullptr)
|
||||
{
|
||||
VMCall(func, params, 3, &ret, 1);
|
||||
if (!retval) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// P_CheckForResurrection (formerly part of A_VileChase)
|
||||
// Check for ressurecting a body
|
||||
// Check for resurrecting a body
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
|
@ -2834,7 +2886,7 @@ static bool P_CheckForResurrection(AActor *self, bool usevilestates)
|
|||
corpsehit->flags = oldflags;
|
||||
corpsehit->radius = oldradius;
|
||||
corpsehit->Height = oldheight;
|
||||
if (!check) continue;
|
||||
if (!check || !P_CanResurrect(self, corpsehit)) continue;
|
||||
|
||||
// got one!
|
||||
temp = self->target;
|
||||
|
|
|
@ -210,16 +210,14 @@ static bool format5;
|
|||
|
||||
static bool LoadGLVertexes(FileReader &lump)
|
||||
{
|
||||
uint8_t *gldata;
|
||||
int i;
|
||||
|
||||
firstglvertex = level.vertexes.Size();
|
||||
|
||||
auto gllen=lump.GetLength();
|
||||
|
||||
gldata = new uint8_t[gllen];
|
||||
lump.Seek(0, FileReader::SeekSet);
|
||||
lump.Read(gldata, gllen);
|
||||
auto glbuf = lump.Read();
|
||||
auto gllen=lump.GetLength();
|
||||
auto gldata = glbuf.Data();
|
||||
|
||||
if (*(int *)gldata == gNd5)
|
||||
{
|
||||
|
@ -233,7 +231,6 @@ static bool LoadGLVertexes(FileReader &lump)
|
|||
Printf("GL nodes v%d found. This format is not supported by " GAMENAME "\n",
|
||||
(*(int *)gldata == gNd4)? 4:1);
|
||||
|
||||
delete [] gldata;
|
||||
return false;
|
||||
}
|
||||
else format5=false;
|
||||
|
@ -256,7 +253,6 @@ static bool LoadGLVertexes(FileReader &lump)
|
|||
level.vertexes[i].set(LittleLong(mgl->x)/65536., LittleLong(mgl->y)/65536.);
|
||||
mgl++;
|
||||
}
|
||||
delete[] gldata;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -288,139 +284,119 @@ static inline int checkGLVertex3(int num)
|
|||
|
||||
static bool LoadGLSegs(FileReader &lump)
|
||||
{
|
||||
char *data;
|
||||
int i;
|
||||
line_t *ldef=NULL;
|
||||
|
||||
int numsegs = (int)lump.GetLength();
|
||||
data= new char[numsegs];
|
||||
|
||||
lump.Seek(0, FileReader::SeekSet);
|
||||
lump.Read(data, numsegs);
|
||||
auto data = lump.Read();
|
||||
int numsegs = (int)lump.GetLength();
|
||||
auto &segs = level.segs;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
__try
|
||||
#endif
|
||||
if (!format5 && memcmp(data.Data(), "gNd3", 4))
|
||||
{
|
||||
if (!format5 && memcmp(data, "gNd3", 4))
|
||||
{
|
||||
numsegs/=sizeof(glseg_t);
|
||||
level.segs.Alloc(numsegs);
|
||||
memset(&segs[0],0,sizeof(seg_t)*numsegs);
|
||||
numsegs/=sizeof(glseg_t);
|
||||
level.segs.Alloc(numsegs);
|
||||
memset(&segs[0],0,sizeof(seg_t)*numsegs);
|
||||
|
||||
glseg_t * ml = (glseg_t*)data;
|
||||
for(i = 0; i < numsegs; i++)
|
||||
{
|
||||
// check for gl-vertices
|
||||
segs[i].v1 = &level.vertexes[checkGLVertex(LittleShort(ml->v1))];
|
||||
segs[i].v2 = &level.vertexes[checkGLVertex(LittleShort(ml->v2))];
|
||||
segs[i].PartnerSeg = ml->partner == 0xFFFF ? nullptr : &segs[LittleShort(ml->partner)];
|
||||
if(ml->linedef != 0xffff)
|
||||
{
|
||||
ldef = &level.lines[LittleShort(ml->linedef)];
|
||||
segs[i].linedef = ldef;
|
||||
glseg_t * ml = (glseg_t*)data.Data();
|
||||
for(i = 0; i < numsegs; i++)
|
||||
{
|
||||
// check for gl-vertices
|
||||
segs[i].v1 = &level.vertexes[checkGLVertex(LittleShort(ml->v1))];
|
||||
segs[i].v2 = &level.vertexes[checkGLVertex(LittleShort(ml->v2))];
|
||||
segs[i].PartnerSeg = ml->partner == 0xFFFF ? nullptr : &segs[LittleShort(ml->partner)];
|
||||
if(ml->linedef != 0xffff)
|
||||
{
|
||||
ldef = &level.lines[LittleShort(ml->linedef)];
|
||||
segs[i].linedef = ldef;
|
||||
|
||||
|
||||
ml->side=LittleShort(ml->side);
|
||||
segs[i].sidedef = ldef->sidedef[ml->side];
|
||||
if (ldef->sidedef[ml->side] != NULL)
|
||||
{
|
||||
segs[i].frontsector = ldef->sidedef[ml->side]->sector;
|
||||
}
|
||||
else
|
||||
{
|
||||
segs[i].frontsector = NULL;
|
||||
}
|
||||
if (ldef->flags & ML_TWOSIDED && ldef->sidedef[ml->side^1] != NULL)
|
||||
{
|
||||
segs[i].backsector = ldef->sidedef[ml->side^1]->sector;
|
||||
}
|
||||
else
|
||||
{
|
||||
ldef->flags &= ~ML_TWOSIDED;
|
||||
segs[i].backsector = NULL;
|
||||
}
|
||||
|
||||
ml->side=LittleShort(ml->side);
|
||||
segs[i].sidedef = ldef->sidedef[ml->side];
|
||||
if (ldef->sidedef[ml->side] != NULL)
|
||||
{
|
||||
segs[i].frontsector = ldef->sidedef[ml->side]->sector;
|
||||
}
|
||||
else
|
||||
{
|
||||
segs[i].linedef = NULL;
|
||||
segs[i].sidedef = NULL;
|
||||
|
||||
segs[i].frontsector = NULL;
|
||||
segs[i].backsector = NULL;
|
||||
}
|
||||
ml++;
|
||||
if (ldef->flags & ML_TWOSIDED && ldef->sidedef[ml->side^1] != NULL)
|
||||
{
|
||||
segs[i].backsector = ldef->sidedef[ml->side^1]->sector;
|
||||
}
|
||||
else
|
||||
{
|
||||
ldef->flags &= ~ML_TWOSIDED;
|
||||
segs[i].backsector = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
segs[i].linedef = NULL;
|
||||
segs[i].sidedef = NULL;
|
||||
|
||||
segs[i].frontsector = NULL;
|
||||
segs[i].backsector = NULL;
|
||||
}
|
||||
ml++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!format5) numsegs-=4;
|
||||
numsegs/=sizeof(glseg3_t);
|
||||
level.segs.Alloc(numsegs);
|
||||
memset(&segs[0],0,sizeof(seg_t)*numsegs);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!format5) numsegs-=4;
|
||||
numsegs/=sizeof(glseg3_t);
|
||||
level.segs.Alloc(numsegs);
|
||||
memset(&segs[0],0,sizeof(seg_t)*numsegs);
|
||||
|
||||
glseg3_t * ml = (glseg3_t*)(data+ (format5? 0:4));
|
||||
for(i = 0; i < numsegs; i++)
|
||||
{ // check for gl-vertices
|
||||
segs[i].v1 = &level.vertexes[checkGLVertex3(LittleLong(ml->v1))];
|
||||
segs[i].v2 = &level.vertexes[checkGLVertex3(LittleLong(ml->v2))];
|
||||
glseg3_t * ml = (glseg3_t*)(data.Data() + (format5? 0:4));
|
||||
for(i = 0; i < numsegs; i++)
|
||||
{ // check for gl-vertices
|
||||
segs[i].v1 = &level.vertexes[checkGLVertex3(LittleLong(ml->v1))];
|
||||
segs[i].v2 = &level.vertexes[checkGLVertex3(LittleLong(ml->v2))];
|
||||
|
||||
const uint32_t partner = LittleLong(ml->partner);
|
||||
segs[i].PartnerSeg = DWORD_MAX == partner ? nullptr : &segs[partner];
|
||||
const uint32_t partner = LittleLong(ml->partner);
|
||||
segs[i].PartnerSeg = DWORD_MAX == partner ? nullptr : &segs[partner];
|
||||
|
||||
if(ml->linedef != 0xffff) // skip minisegs
|
||||
{
|
||||
ldef = &level.lines[LittleLong(ml->linedef)];
|
||||
segs[i].linedef = ldef;
|
||||
if(ml->linedef != 0xffff) // skip minisegs
|
||||
{
|
||||
ldef = &level.lines[LittleLong(ml->linedef)];
|
||||
segs[i].linedef = ldef;
|
||||
|
||||
|
||||
ml->side=LittleShort(ml->side);
|
||||
segs[i].sidedef = ldef->sidedef[ml->side];
|
||||
if (ldef->sidedef[ml->side] != NULL)
|
||||
{
|
||||
segs[i].frontsector = ldef->sidedef[ml->side]->sector;
|
||||
}
|
||||
else
|
||||
{
|
||||
segs[i].frontsector = NULL;
|
||||
}
|
||||
if (ldef->flags & ML_TWOSIDED && ldef->sidedef[ml->side^1] != NULL)
|
||||
{
|
||||
segs[i].backsector = ldef->sidedef[ml->side^1]->sector;
|
||||
}
|
||||
else
|
||||
{
|
||||
ldef->flags &= ~ML_TWOSIDED;
|
||||
segs[i].backsector = NULL;
|
||||
}
|
||||
|
||||
ml->side=LittleShort(ml->side);
|
||||
segs[i].sidedef = ldef->sidedef[ml->side];
|
||||
if (ldef->sidedef[ml->side] != NULL)
|
||||
{
|
||||
segs[i].frontsector = ldef->sidedef[ml->side]->sector;
|
||||
}
|
||||
else
|
||||
{
|
||||
segs[i].linedef = NULL;
|
||||
segs[i].sidedef = NULL;
|
||||
segs[i].frontsector = NULL;
|
||||
segs[i].backsector = NULL;
|
||||
}
|
||||
ml++;
|
||||
if (ldef->flags & ML_TWOSIDED && ldef->sidedef[ml->side^1] != NULL)
|
||||
{
|
||||
segs[i].backsector = ldef->sidedef[ml->side^1]->sector;
|
||||
}
|
||||
else
|
||||
{
|
||||
ldef->flags &= ~ML_TWOSIDED;
|
||||
segs[i].backsector = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
segs[i].linedef = NULL;
|
||||
segs[i].sidedef = NULL;
|
||||
segs[i].frontsector = NULL;
|
||||
segs[i].backsector = NULL;
|
||||
}
|
||||
ml++;
|
||||
}
|
||||
delete [] data;
|
||||
return true;
|
||||
}
|
||||
#ifdef _MSC_VER
|
||||
__except(1)
|
||||
{
|
||||
// Invalid data has the bad habit of requiring extensive checks here
|
||||
// so let's just catch anything invalid and output a message.
|
||||
// (at least under MSVC. GCC can't do SEH even for Windows... :( )
|
||||
Printf("Invalid GL segs. The BSP will have to be rebuilt.\n");
|
||||
delete [] data;
|
||||
level.segs.Clear();
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -432,23 +408,20 @@ static bool LoadGLSegs(FileReader &lump)
|
|||
|
||||
static bool LoadGLSubsectors(FileReader &lump)
|
||||
{
|
||||
char * datab;
|
||||
int i;
|
||||
|
||||
|
||||
int numsubsectors = (int)lump.GetLength();
|
||||
datab = new char[numsubsectors];
|
||||
lump.Seek(0, FileReader::SeekSet);
|
||||
lump.Read(datab, numsubsectors);
|
||||
auto datab = lump.Read();
|
||||
|
||||
if (numsubsectors == 0)
|
||||
{
|
||||
delete [] datab;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!format5 && memcmp(datab, "gNd3", 4))
|
||||
if (!format5 && memcmp(datab.Data(), "gNd3", 4))
|
||||
{
|
||||
mapsubsector_t * data = (mapsubsector_t*) datab;
|
||||
mapsubsector_t * data = (mapsubsector_t*) datab.Data();
|
||||
numsubsectors /= sizeof(mapsubsector_t);
|
||||
level.subsectors.Alloc(numsubsectors);
|
||||
auto &subsectors = level.subsectors;
|
||||
|
@ -461,14 +434,13 @@ static bool LoadGLSubsectors(FileReader &lump)
|
|||
|
||||
if (subsectors[i].numlines == 0)
|
||||
{
|
||||
delete [] datab;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gl3_mapsubsector_t * data = (gl3_mapsubsector_t*) (datab+(format5? 0:4));
|
||||
gl3_mapsubsector_t * data = (gl3_mapsubsector_t*) (datab.Data()+(format5? 0:4));
|
||||
numsubsectors /= sizeof(gl3_mapsubsector_t);
|
||||
level.subsectors.Alloc(numsubsectors);
|
||||
auto &subsectors = level.subsectors;
|
||||
|
@ -481,7 +453,6 @@ static bool LoadGLSubsectors(FileReader &lump)
|
|||
|
||||
if (subsectors[i].numlines == 0)
|
||||
{
|
||||
delete [] datab;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -499,12 +470,10 @@ static bool LoadGLSubsectors(FileReader &lump)
|
|||
// The subsector must be closed. If it isn't we can't use these nodes and have to do a rebuild.
|
||||
if (lastseg->v2 != firstseg->v1)
|
||||
{
|
||||
delete [] datab;
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
delete [] datab;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -522,7 +491,7 @@ static bool LoadNodes (FileReader &lump)
|
|||
int j;
|
||||
int k;
|
||||
node_t* no;
|
||||
uint16_t* used;
|
||||
TArray<uint16_t> used;
|
||||
|
||||
if (!format5)
|
||||
{
|
||||
|
@ -534,11 +503,11 @@ static bool LoadNodes (FileReader &lump)
|
|||
level.nodes.Alloc(numnodes);
|
||||
lump.Seek(0, FileReader::SeekSet);
|
||||
|
||||
basemn = mn = new mapnode_t[numnodes];
|
||||
lump.Read(mn, lump.GetLength());
|
||||
auto buf = lump.Read();
|
||||
basemn = mn = (mapnode_t*)buf.Data();
|
||||
|
||||
used = (uint16_t *)alloca (sizeof(uint16_t)*numnodes);
|
||||
memset (used, 0, sizeof(uint16_t)*numnodes);
|
||||
used.Resize(numnodes);
|
||||
memset (used.Data(), 0, sizeof(uint16_t)*numnodes);
|
||||
|
||||
no = &level.nodes[0];
|
||||
|
||||
|
@ -556,19 +525,16 @@ static bool LoadNodes (FileReader &lump)
|
|||
child &= ~NF_SUBSECTOR;
|
||||
if (child >= level.subsectors.Size())
|
||||
{
|
||||
delete [] basemn;
|
||||
return false;
|
||||
}
|
||||
no->children[j] = (uint8_t *)&level.subsectors[child] + 1;
|
||||
}
|
||||
else if (child >= numnodes)
|
||||
{
|
||||
delete [] basemn;
|
||||
return false;
|
||||
}
|
||||
else if (used[child])
|
||||
{
|
||||
delete [] basemn;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
|
@ -582,7 +548,6 @@ static bool LoadNodes (FileReader &lump)
|
|||
}
|
||||
}
|
||||
}
|
||||
delete [] basemn;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -594,11 +559,11 @@ static bool LoadNodes (FileReader &lump)
|
|||
level.nodes.Alloc(numnodes);
|
||||
lump.Seek(0, FileReader::SeekSet);
|
||||
|
||||
basemn = mn = new gl5_mapnode_t[numnodes];
|
||||
lump.Read(mn, lump.GetLength());
|
||||
auto buf = lump.Read();
|
||||
basemn = mn = (gl5_mapnode_t*)buf.Data();
|
||||
|
||||
used = (uint16_t *)alloca (sizeof(uint16_t)*numnodes);
|
||||
memset (used, 0, sizeof(uint16_t)*numnodes);
|
||||
used.Resize(numnodes);
|
||||
memset(used.Data(), 0, sizeof(uint16_t)*numnodes);
|
||||
|
||||
no = &level.nodes[0];
|
||||
|
||||
|
@ -616,19 +581,16 @@ static bool LoadNodes (FileReader &lump)
|
|||
child &= ~GL5_NF_SUBSECTOR;
|
||||
if ((unsigned)child >= level.subsectors.Size())
|
||||
{
|
||||
delete [] basemn;
|
||||
return false;
|
||||
}
|
||||
no->children[j] = (uint8_t *)&level.subsectors[child] + 1;
|
||||
}
|
||||
else if ((unsigned)child >= numnodes)
|
||||
{
|
||||
delete [] basemn;
|
||||
return false;
|
||||
}
|
||||
else if (used[child])
|
||||
{
|
||||
delete [] basemn;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
|
@ -642,7 +604,6 @@ static bool LoadNodes (FileReader &lump)
|
|||
}
|
||||
}
|
||||
}
|
||||
delete [] basemn;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -1097,31 +1058,30 @@ static void CreateCachedNodes(MapData *map)
|
|||
}
|
||||
|
||||
uLongf outlen = ZNodes.Size();
|
||||
uint8_t *compressed;
|
||||
TArray<Bytef> compressed;
|
||||
int offset = level.lines.Size() * 8 + 12 + 16;
|
||||
int r;
|
||||
do
|
||||
{
|
||||
compressed = new Bytef[outlen + offset];
|
||||
r = compress (compressed + offset, &outlen, &ZNodes[0], ZNodes.Size());
|
||||
compressed.Resize(outlen + offset);
|
||||
r = compress (compressed.Data() + offset, &outlen, &ZNodes[0], ZNodes.Size());
|
||||
if (r == Z_BUF_ERROR)
|
||||
{
|
||||
delete[] compressed;
|
||||
outlen += 1024;
|
||||
}
|
||||
}
|
||||
while (r == Z_BUF_ERROR);
|
||||
|
||||
memcpy(compressed, "CACH", 4);
|
||||
memcpy(compressed.Data(), "CACH", 4);
|
||||
uint32_t len = LittleLong(level.lines.Size());
|
||||
memcpy(compressed+4, &len, 4);
|
||||
map->GetChecksum(compressed+8);
|
||||
memcpy(&compressed[4], &len, 4);
|
||||
map->GetChecksum(&compressed[8]);
|
||||
for (unsigned i = 0; i < level.lines.Size(); i++)
|
||||
{
|
||||
uint32_t ndx[2] = { LittleLong(uint32_t(level.lines[i].v1->Index())), LittleLong(uint32_t(level.lines[i].v2->Index())) };
|
||||
memcpy(compressed + 8 + 16 + 8 * i, ndx, 8);
|
||||
memcpy(&compressed[8 + 16 + 8 * i], ndx, 8);
|
||||
}
|
||||
memcpy(compressed + offset - 4, "ZGL3", 4);
|
||||
memcpy(&compressed[offset - 4], "ZGL3", 4);
|
||||
|
||||
FString path = CreateCacheName(map, true);
|
||||
FileWriter *fw = FileWriter::Open(path);
|
||||
|
@ -1129,7 +1089,7 @@ static void CreateCachedNodes(MapData *map)
|
|||
if (fw != nullptr)
|
||||
{
|
||||
const size_t length = outlen + offset;
|
||||
if (fw->Write(compressed, length) != length)
|
||||
if (fw->Write(compressed.Data(), length) != length)
|
||||
{
|
||||
Printf("Error saving nodes to file %s\n", path.GetChars());
|
||||
}
|
||||
|
@ -1139,8 +1099,6 @@ static void CreateCachedNodes(MapData *map)
|
|||
{
|
||||
Printf("Cannot open nodes file %s for writing\n", path.GetChars());
|
||||
}
|
||||
|
||||
delete [] compressed;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1150,29 +1108,29 @@ static bool CheckCachedNodes(MapData *map)
|
|||
uint8_t md5[16];
|
||||
uint8_t md5map[16];
|
||||
uint32_t numlin;
|
||||
uint32_t *verts = NULL;
|
||||
TArray<uint32_t> verts;
|
||||
|
||||
FString path = CreateCacheName(map, false);
|
||||
FileReader fr;
|
||||
|
||||
if (!fr.OpenFile(path)) return false;
|
||||
|
||||
if (fr.Read(magic, 4) != 4) goto errorout;
|
||||
if (memcmp(magic, "CACH", 4)) goto errorout;
|
||||
if (fr.Read(magic, 4) != 4) return false;
|
||||
if (memcmp(magic, "CACH", 4)) return false;
|
||||
|
||||
if (fr.Read(&numlin, 4) != 4) goto errorout;
|
||||
if (fr.Read(&numlin, 4) != 4) return false;
|
||||
numlin = LittleLong(numlin);
|
||||
if (numlin != level.lines.Size()) goto errorout;
|
||||
if (numlin != level.lines.Size()) return false;
|
||||
|
||||
if (fr.Read(md5, 16) != 16) goto errorout;
|
||||
if (fr.Read(md5, 16) != 16) return false;
|
||||
map->GetChecksum(md5map);
|
||||
if (memcmp(md5, md5map, 16)) goto errorout;
|
||||
if (memcmp(md5, md5map, 16)) return false;
|
||||
|
||||
verts = new uint32_t[numlin * 8];
|
||||
if (fr.Read(verts, 8 * numlin) != 8 * numlin) goto errorout;
|
||||
verts.Resize(numlin * 2);
|
||||
if (fr.Read(verts.Data(), 8 * numlin) != 8 * numlin) return false;
|
||||
|
||||
if (fr.Read(magic, 4) != 4) goto errorout;
|
||||
if (memcmp(magic, "ZGL2", 4) && memcmp(magic, "ZGL3", 4)) goto errorout;
|
||||
if (fr.Read(magic, 4) != 4) return false;
|
||||
if (memcmp(magic, "ZGL2", 4) && memcmp(magic, "ZGL3", 4)) return false;
|
||||
|
||||
|
||||
try
|
||||
|
@ -1186,7 +1144,7 @@ static bool CheckCachedNodes(MapData *map)
|
|||
level.subsectors.Clear();
|
||||
level.segs.Clear();
|
||||
level.nodes.Clear();
|
||||
goto errorout;
|
||||
return false;
|
||||
}
|
||||
|
||||
for(auto &line : level.lines)
|
||||
|
@ -1195,16 +1153,7 @@ static bool CheckCachedNodes(MapData *map)
|
|||
line.v1 = &level.vertexes[LittleLong(verts[i*2])];
|
||||
line.v2 = &level.vertexes[LittleLong(verts[i*2+1])];
|
||||
}
|
||||
delete [] verts;
|
||||
|
||||
return true;
|
||||
|
||||
errorout:
|
||||
if (verts != NULL)
|
||||
{
|
||||
delete[] verts;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
UNSAFE_CCMD(clearnodecache)
|
||||
|
@ -1308,32 +1257,6 @@ void P_SetRenderSector()
|
|||
TArray<subsector_t *> undetermined;
|
||||
subsector_t * ss;
|
||||
|
||||
#if 0 // doesn't work as expected :(
|
||||
|
||||
// hide all sectors on textured automap that only have hidden lines.
|
||||
bool *hidesec = new bool[numsectors];
|
||||
for(i = 0; i < numsectors; i++)
|
||||
{
|
||||
hidesec[i] = true;
|
||||
}
|
||||
for(i = 0; i < numlines; i++)
|
||||
{
|
||||
if (!(lines[i].flags & ML_DONTDRAW))
|
||||
{
|
||||
hidesec[lines[i].frontsector - sectors] = false;
|
||||
if (lines[i].backsector != NULL)
|
||||
{
|
||||
hidesec[lines[i].backsector - sectors] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
for(i = 0; i < numsectors; i++)
|
||||
{
|
||||
if (hidesec[i]) sectors[i].MoreFlags |= SECMF_HIDDEN;
|
||||
}
|
||||
delete [] hidesec;
|
||||
#endif
|
||||
|
||||
// Check for incorrect partner seg info so that the following code does not crash.
|
||||
|
||||
for (auto &seg : level.segs)
|
||||
|
|
|
@ -1086,7 +1086,7 @@ static int DamageMobj (AActor *target, AActor *inflictor, AActor *source, int da
|
|||
damage = int(damage * source->DamageMultiply);
|
||||
|
||||
// Handle active damage modifiers (e.g. PowerDamage)
|
||||
if (damage > 0)
|
||||
if (damage > 0 && !(flags & DMG_NO_ENHANCE))
|
||||
{
|
||||
damage = source->GetModifiedDamage(mod, damage, false);
|
||||
}
|
||||
|
|
|
@ -162,6 +162,7 @@ void P_Thing_SetVelocity(AActor *actor, const DVector3 &vec, bool add, bool setb
|
|||
void P_RemoveThing(AActor * actor);
|
||||
bool P_Thing_Raise(AActor *thing, AActor *raiser, int nocheck = false);
|
||||
bool P_Thing_CanRaise(AActor *thing);
|
||||
bool P_CanResurrect(AActor *ththing, AActor *thing);
|
||||
PClassActor *P_GetSpawnableType(int spawnnum);
|
||||
void InitSpawnablesFromMapinfo();
|
||||
int P_Thing_CheckInputNum(player_t *p, int inputnum);
|
||||
|
@ -454,6 +455,7 @@ enum EDmgFlags
|
|||
DMG_USEANGLE = 512,
|
||||
DMG_NO_PAIN = 1024,
|
||||
DMG_EXPLOSION = 2048,
|
||||
DMG_NO_ENHANCE = 4096,
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -7063,7 +7063,7 @@ void SpawnShootDecal(AActor *t1, const FTraceResults &trace)
|
|||
|
||||
if (t1->player != NULL && t1->player->ReadyWeapon != NULL)
|
||||
{
|
||||
decalbase = t1->player->ReadyWeapon->GetDefault()->DecalGenerator;
|
||||
decalbase = t1->player->ReadyWeapon->DecalGenerator;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -105,6 +105,9 @@ FSerializer &Serialize(FSerializer &arc, const char *key, side_t::part &part, si
|
|||
("yscale", part.yScale, def->yScale)
|
||||
("texture", part.texture, def->texture)
|
||||
("interpolation", part.interpolation)
|
||||
("flags", part.flags, def->flags)
|
||||
("color1", part.SpecialColors[0], def->SpecialColors[0])
|
||||
("color2", part.SpecialColors[1], def->SpecialColors[1])
|
||||
.EndObject();
|
||||
}
|
||||
return arc;
|
||||
|
|
|
@ -878,17 +878,6 @@ DEFINE_ACTION_FUNCTION(_Sector, SetFade)
|
|||
//
|
||||
//=====================================================================================
|
||||
|
||||
void sector_t::SetSpecialColor(int slot, int r, int g, int b)
|
||||
{
|
||||
SpecialColors[slot] = PalEntry(255, r, g, b);
|
||||
}
|
||||
|
||||
void sector_t::SetSpecialColor(int slot, PalEntry rgb)
|
||||
{
|
||||
rgb.a = 255;
|
||||
SpecialColors[slot] = rgb;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_Sector, SetSpecialColor)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(sector_t);
|
||||
|
@ -2241,6 +2230,26 @@ DEFINE_ACTION_FUNCTION(_Sector, NextLowestFloorAt)
|
|||
ACTION_RETURN_INT(self->Index());
|
||||
}
|
||||
|
||||
//=====================================================================================
|
||||
//
|
||||
//
|
||||
//=====================================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_Side, SetSpecialColor)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(side_t);
|
||||
PARAM_INT(tier);
|
||||
PARAM_INT(position);
|
||||
PARAM_COLOR(color);
|
||||
if (tier >= 0 && tier < 3 && position >= 0 && position < 2)
|
||||
{
|
||||
color.a = 255;
|
||||
self->SetSpecialColor(tier, position, color);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_Vertex, Index)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(vertex_t);
|
||||
|
|
182
src/p_setup.cpp
182
src/p_setup.cpp
|
@ -1691,15 +1691,10 @@ uint16_t MakeSkill(int flags)
|
|||
|
||||
void P_LoadThings (MapData * map)
|
||||
{
|
||||
int lumplen = map->Size(ML_THINGS);
|
||||
int numthings = lumplen / sizeof(mapthing_t);
|
||||
|
||||
char *mtp;
|
||||
mapthing_t *mt;
|
||||
|
||||
mtp = new char[lumplen];
|
||||
map->Read(ML_THINGS, mtp);
|
||||
mt = (mapthing_t*)mtp;
|
||||
auto mtp = map->Read(ML_THINGS);
|
||||
int numthings = mtp.Size() / sizeof(mapthing_t);
|
||||
mt = (mapthing_t*)mtp.Data();
|
||||
|
||||
MapThingsConverted.Resize(numthings);
|
||||
FMapThing *mti = &MapThingsConverted[0];
|
||||
|
@ -1767,7 +1762,6 @@ void P_LoadThings (MapData * map)
|
|||
if (flags & BTF_NOTSINGLE) mti[i].flags &= ~MTF_SINGLE;
|
||||
}
|
||||
}
|
||||
delete [] mtp;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
@ -2109,29 +2103,24 @@ void P_LoadLineDefs (MapData * map)
|
|||
{
|
||||
int i, skipped;
|
||||
line_t *ld;
|
||||
int lumplen = map->Size(ML_LINEDEFS);
|
||||
char * mldf;
|
||||
maplinedef_t *mld;
|
||||
|
||||
int numlines = lumplen / sizeof(maplinedef_t);
|
||||
auto mldf = map->Read(ML_LINEDEFS);
|
||||
int numlines = mldf.Size() / sizeof(maplinedef_t);
|
||||
linemap.Resize(numlines);
|
||||
|
||||
mldf = new char[lumplen];
|
||||
map->Read(ML_LINEDEFS, mldf);
|
||||
|
||||
// [RH] Count the number of sidedef references. This is the number of
|
||||
// sidedefs we need. The actual number in the SIDEDEFS lump might be less.
|
||||
// Lines with 0 length are also removed.
|
||||
|
||||
for (skipped = sidecount = i = 0; i < numlines; )
|
||||
{
|
||||
mld = ((maplinedef_t*)mldf) + i;
|
||||
mld = ((maplinedef_t*)mldf.Data()) + i;
|
||||
unsigned v1 = LittleShort(mld->v1);
|
||||
unsigned v2 = LittleShort(mld->v2);
|
||||
|
||||
if (v1 >= level.vertexes.Size() || v2 >= level.vertexes.Size())
|
||||
{
|
||||
delete [] mldf;
|
||||
I_Error ("Line %d has invalid vertices: %d and/or %d.\nThe map only contains %u vertices.", i+skipped, v1, v2, level.vertexes.Size());
|
||||
}
|
||||
else if (v1 == v2 ||
|
||||
|
@ -2164,7 +2153,7 @@ void P_LoadLineDefs (MapData * map)
|
|||
|
||||
P_AllocateSideDefs (map, sidecount);
|
||||
|
||||
mld = (maplinedef_t *)mldf;
|
||||
mld = (maplinedef_t *)mldf.Data();
|
||||
ld = &level.lines[0];
|
||||
for (i = 0; i < numlines; i++, mld++, ld++)
|
||||
{
|
||||
|
@ -2203,7 +2192,6 @@ void P_LoadLineDefs (MapData * map)
|
|||
if (level.flags2 & LEVEL2_WRAPMIDTEX) ld->flags |= ML_WRAP_MIDTEX;
|
||||
if (level.flags2 & LEVEL2_CHECKSWITCHRANGE) ld->flags |= ML_CHECKSWITCHRANGE;
|
||||
}
|
||||
delete[] mldf;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
@ -3644,7 +3632,7 @@ void P_FreeExtraLevelData()
|
|||
//
|
||||
//===========================================================================
|
||||
|
||||
void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
||||
void P_SetupLevel(const char *lumpname, int position, bool newGame)
|
||||
{
|
||||
cycle_t times[20];
|
||||
#if 0
|
||||
|
@ -3674,7 +3662,7 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
level.SetMusicVolume(level.MusicVolume);
|
||||
for (i = 0; i < MAXPLAYERS; ++i)
|
||||
{
|
||||
players[i].killcount = players[i].secretcount
|
||||
players[i].killcount = players[i].secretcount
|
||||
= players[i].itemcount = 0;
|
||||
}
|
||||
}
|
||||
|
@ -3695,16 +3683,16 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
translationtables[TRANSLATION_LevelScripted].Clear();
|
||||
|
||||
// Initial height of PointOfView will be set by player think.
|
||||
players[consoleplayer].viewz = NO_VALUE;
|
||||
players[consoleplayer].viewz = NO_VALUE;
|
||||
|
||||
// Make sure all sounds are stopped before Z_FreeTags.
|
||||
S_Start ();
|
||||
S_Start();
|
||||
|
||||
// [RH] clear out the mid-screen message
|
||||
C_MidPrint (NULL, NULL);
|
||||
C_MidPrint(NULL, NULL);
|
||||
|
||||
// Free all level data from the previous map
|
||||
P_FreeLevelData ();
|
||||
P_FreeLevelData();
|
||||
|
||||
MapData *map = P_OpenMapData(lumpname, true);
|
||||
if (map == NULL)
|
||||
|
@ -3736,7 +3724,7 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
uint8_t *mapdata = new uint8_t[map->Size(0)];
|
||||
map->Read(0, mapdata);
|
||||
times[0].Clock();
|
||||
buildmap = P_LoadBuildMap (mapdata, map->Size(0), &buildthings, &numbuildthings);
|
||||
buildmap = P_LoadBuildMap(mapdata, map->Size(0), &buildthings, &numbuildthings);
|
||||
times[0].Unclock();
|
||||
delete[] mapdata;
|
||||
}
|
||||
|
@ -3748,10 +3736,10 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
ForceNodeBuild = gennodes;
|
||||
|
||||
// [RH] Load in the BEHAVIOR lump
|
||||
FBehavior::StaticUnloadModules ();
|
||||
FBehavior::StaticUnloadModules();
|
||||
if (map->HasBehavior)
|
||||
{
|
||||
P_LoadBehavior (map);
|
||||
P_LoadBehavior(map);
|
||||
level.maptype = MAPTYPE_HEXEN;
|
||||
}
|
||||
else
|
||||
|
@ -3768,7 +3756,7 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
{
|
||||
// Has the user overridden the game's default translator with a commandline parameter?
|
||||
translator = Args->CheckValue("-xlat");
|
||||
if (translator == NULL)
|
||||
if (translator == NULL)
|
||||
{
|
||||
// Use the game's default.
|
||||
translator = gameinfo.translator.GetChars();
|
||||
|
@ -3808,25 +3796,25 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
level.flags2 |= LEVEL2_DUMMYSWITCHES;
|
||||
}
|
||||
|
||||
FBehavior::StaticLoadDefaultModules ();
|
||||
FBehavior::StaticLoadDefaultModules();
|
||||
#ifndef NO_EDATA
|
||||
LoadMapinfoACSLump();
|
||||
#endif
|
||||
|
||||
|
||||
P_LoadStrifeConversations (map, lumpname);
|
||||
P_LoadStrifeConversations(map, lumpname);
|
||||
|
||||
FMissingTextureTracker missingtex;
|
||||
|
||||
if (!map->isText)
|
||||
{
|
||||
times[0].Clock();
|
||||
P_LoadVertexes (map);
|
||||
P_LoadVertexes(map);
|
||||
times[0].Unclock();
|
||||
|
||||
|
||||
// Check for maps without any BSP data at all (e.g. SLIGE)
|
||||
times[1].Clock();
|
||||
P_LoadSectors (map, missingtex);
|
||||
P_LoadSectors(map, missingtex);
|
||||
times[1].Unclock();
|
||||
|
||||
times[2].Clock();
|
||||
|
@ -3834,23 +3822,23 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
|
||||
times[3].Clock();
|
||||
if (!map->HasBehavior)
|
||||
P_LoadLineDefs (map);
|
||||
P_LoadLineDefs(map);
|
||||
else
|
||||
P_LoadLineDefs2 (map); // [RH] Load Hexen-style linedefs
|
||||
P_LoadLineDefs2(map); // [RH] Load Hexen-style linedefs
|
||||
times[3].Unclock();
|
||||
|
||||
times[4].Clock();
|
||||
P_LoadSideDefs2 (map, missingtex);
|
||||
P_LoadSideDefs2(map, missingtex);
|
||||
times[4].Unclock();
|
||||
|
||||
times[5].Clock();
|
||||
P_FinishLoadingLineDefs ();
|
||||
P_FinishLoadingLineDefs();
|
||||
times[5].Unclock();
|
||||
|
||||
if (!map->HasBehavior)
|
||||
P_LoadThings (map);
|
||||
P_LoadThings(map);
|
||||
else
|
||||
P_LoadThings2 (map); // [RH] Load Hexen-style things
|
||||
P_LoadThings2(map); // [RH] Load Hexen-style things
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -3862,7 +3850,7 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
SetCompatibilityParams(checksum);
|
||||
|
||||
times[6].Clock();
|
||||
P_LoopSidedefs (true);
|
||||
P_LoopSidedefs(true);
|
||||
times[6].Unclock();
|
||||
|
||||
linemap.Clear();
|
||||
|
@ -3881,36 +3869,36 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
{
|
||||
// Check for compressed nodes first, then uncompressed nodes
|
||||
FileReader *fr = nullptr;
|
||||
uint32_t id = MAKE_ID('X','x','X','x'), idcheck = 0, idcheck2 = 0, idcheck3 = 0, idcheck4 = 0, idcheck5 = 0, idcheck6 = 0;
|
||||
uint32_t id = MAKE_ID('X', 'x', 'X', 'x'), idcheck = 0, idcheck2 = 0, idcheck3 = 0, idcheck4 = 0, idcheck5 = 0, idcheck6 = 0;
|
||||
|
||||
if (map->Size(ML_ZNODES) != 0)
|
||||
{
|
||||
// Test normal nodes first
|
||||
fr = &map->Reader(ML_ZNODES);
|
||||
idcheck = MAKE_ID('Z','N','O','D');
|
||||
idcheck2 = MAKE_ID('X','N','O','D');
|
||||
idcheck = MAKE_ID('Z', 'N', 'O', 'D');
|
||||
idcheck2 = MAKE_ID('X', 'N', 'O', 'D');
|
||||
}
|
||||
else if (map->Size(ML_GLZNODES) != 0)
|
||||
{
|
||||
fr = &map->Reader(ML_GLZNODES);
|
||||
idcheck = MAKE_ID('Z','G','L','N');
|
||||
idcheck2 = MAKE_ID('Z','G','L','2');
|
||||
idcheck3 = MAKE_ID('Z','G','L','3');
|
||||
idcheck4 = MAKE_ID('X','G','L','N');
|
||||
idcheck5 = MAKE_ID('X','G','L','2');
|
||||
idcheck6 = MAKE_ID('X','G','L','3');
|
||||
idcheck = MAKE_ID('Z', 'G', 'L', 'N');
|
||||
idcheck2 = MAKE_ID('Z', 'G', 'L', '2');
|
||||
idcheck3 = MAKE_ID('Z', 'G', 'L', '3');
|
||||
idcheck4 = MAKE_ID('X', 'G', 'L', 'N');
|
||||
idcheck5 = MAKE_ID('X', 'G', 'L', '2');
|
||||
idcheck6 = MAKE_ID('X', 'G', 'L', '3');
|
||||
}
|
||||
|
||||
if (fr != nullptr && fr->isOpen()) fr->Read (&id, 4);
|
||||
if (fr != nullptr && fr->isOpen()) fr->Read(&id, 4);
|
||||
if (id != 0 && (id == idcheck || id == idcheck2 || id == idcheck3 || id == idcheck4 || id == idcheck5 || id == idcheck6))
|
||||
{
|
||||
try
|
||||
{
|
||||
P_LoadZNodes (*fr, id);
|
||||
P_LoadZNodes(*fr, id);
|
||||
}
|
||||
catch (CRecoverableError &error)
|
||||
{
|
||||
Printf ("Error loading nodes: %s\n", error.GetMessage());
|
||||
Printf("Error loading nodes: %s\n", error.GetMessage());
|
||||
|
||||
ForceNodeBuild = true;
|
||||
level.subsectors.Clear();
|
||||
|
@ -3927,29 +3915,29 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
if (!P_CheckV4Nodes(map))
|
||||
{
|
||||
times[7].Clock();
|
||||
P_LoadSubsectors<mapsubsector_t, mapseg_t> (map);
|
||||
P_LoadSubsectors<mapsubsector_t, mapseg_t>(map);
|
||||
times[7].Unclock();
|
||||
|
||||
times[8].Clock();
|
||||
if (!ForceNodeBuild) P_LoadNodes<mapnode_t, mapsubsector_t> (map);
|
||||
if (!ForceNodeBuild) P_LoadNodes<mapnode_t, mapsubsector_t>(map);
|
||||
times[8].Unclock();
|
||||
|
||||
times[9].Clock();
|
||||
if (!ForceNodeBuild) P_LoadSegs<mapseg_t> (map);
|
||||
if (!ForceNodeBuild) P_LoadSegs<mapseg_t>(map);
|
||||
times[9].Unclock();
|
||||
}
|
||||
else
|
||||
{
|
||||
times[7].Clock();
|
||||
P_LoadSubsectors<mapsubsector4_t, mapseg4_t> (map);
|
||||
P_LoadSubsectors<mapsubsector4_t, mapseg4_t>(map);
|
||||
times[7].Unclock();
|
||||
|
||||
times[8].Clock();
|
||||
if (!ForceNodeBuild) P_LoadNodes<mapnode4_t, mapsubsector4_t> (map);
|
||||
if (!ForceNodeBuild) P_LoadNodes<mapnode4_t, mapsubsector4_t>(map);
|
||||
times[8].Unclock();
|
||||
|
||||
times[9].Clock();
|
||||
if (!ForceNodeBuild) P_LoadSegs<mapseg4_t> (map);
|
||||
if (!ForceNodeBuild) P_LoadSegs<mapseg4_t>(map);
|
||||
times[9].Unclock();
|
||||
}
|
||||
}
|
||||
|
@ -3960,7 +3948,7 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
// If loading the regular nodes failed try GL nodes before considering a rebuild
|
||||
if (ForceNodeBuild)
|
||||
{
|
||||
if (P_LoadGLNodes(map))
|
||||
if (P_LoadGLNodes(map))
|
||||
{
|
||||
ForceNodeBuild = false;
|
||||
reloop = true;
|
||||
|
@ -3969,16 +3957,16 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
}
|
||||
else reloop = true;
|
||||
|
||||
uint64_t startTime=0, endTime=0;
|
||||
uint64_t startTime = 0, endTime = 0;
|
||||
|
||||
bool BuildGLNodes;
|
||||
if (ForceNodeBuild)
|
||||
{
|
||||
BuildGLNodes = RequireGLNodes || multiplayer || demoplayback || demorecording || genglnodes;
|
||||
|
||||
startTime = I_msTime ();
|
||||
startTime = I_msTime();
|
||||
TArray<FNodeBuilder::FPolyStart> polyspots, anchors;
|
||||
P_GetPolySpots (map, polyspots, anchors);
|
||||
P_GetPolySpots(map, polyspots, anchors);
|
||||
FNodeBuilder::FLevel leveldata =
|
||||
{
|
||||
&level.vertexes[0], (int)level.vertexes.Size(),
|
||||
|
@ -3986,14 +3974,14 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
&level.lines[0], (int)level.lines.Size(),
|
||||
0, 0, 0, 0
|
||||
};
|
||||
leveldata.FindMapBounds ();
|
||||
leveldata.FindMapBounds();
|
||||
// We need GL nodes if am_textured is on.
|
||||
// In case a sync critical game mode is started, also build GL nodes to avoid problems
|
||||
// if the different machines' am_textured setting differs.
|
||||
FNodeBuilder builder (leveldata, polyspots, anchors, BuildGLNodes);
|
||||
builder.Extract (level);
|
||||
endTime = I_msTime ();
|
||||
DPrintf (DMSG_NOTIFY, "BSP generation took %.3f sec (%d segs)\n", (endTime - startTime) * 0.001, level.segs.Size());
|
||||
FNodeBuilder builder(leveldata, polyspots, anchors, BuildGLNodes);
|
||||
builder.Extract(level);
|
||||
endTime = I_msTime();
|
||||
DPrintf(DMSG_NOTIFY, "BSP generation took %.3f sec (%d segs)\n", (endTime - startTime) * 0.001, level.segs.Size());
|
||||
oldvertextable = builder.GetOldVertexTable();
|
||||
reloop = true;
|
||||
}
|
||||
|
@ -4001,14 +3989,14 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
{
|
||||
BuildGLNodes = false;
|
||||
// Older ZDBSPs had problems with compressed sidedefs and assigned wrong sides to the segs if both sides were the same sidedef.
|
||||
for(auto &seg : level.segs)
|
||||
for (auto &seg : level.segs)
|
||||
{
|
||||
if (seg.backsector == seg.frontsector && seg.linedef)
|
||||
{
|
||||
double d1 = (seg.v1->fPos() - seg.linedef->v1->fPos()).LengthSquared();
|
||||
double d2 = (seg.v2->fPos() - seg.linedef->v1->fPos()).LengthSquared();
|
||||
|
||||
if (d2<d1) // backside
|
||||
if (d2 < d1) // backside
|
||||
{
|
||||
seg.sidedef = seg.linedef->sidedef[1];
|
||||
}
|
||||
|
@ -4035,22 +4023,22 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
}
|
||||
|
||||
// set the head node for gameplay purposes. If the separate gamenodes array is not empty, use that, otherwise use the render nodes.
|
||||
level.headgamenode = level.gamenodes.Size() > 0 ? &level.gamenodes[level.gamenodes.Size() - 1] : level.nodes.Size()? &level.nodes[level.nodes.Size() - 1] : nullptr;
|
||||
level.headgamenode = level.gamenodes.Size() > 0 ? &level.gamenodes[level.gamenodes.Size() - 1] : level.nodes.Size() ? &level.nodes[level.nodes.Size() - 1] : nullptr;
|
||||
|
||||
times[10].Clock();
|
||||
P_LoadBlockMap (map);
|
||||
P_LoadBlockMap(map);
|
||||
times[10].Unclock();
|
||||
|
||||
times[11].Clock();
|
||||
P_LoadReject (map, buildmap);
|
||||
P_LoadReject(map, buildmap);
|
||||
times[11].Unclock();
|
||||
|
||||
times[12].Clock();
|
||||
P_GroupLines (buildmap);
|
||||
P_GroupLines(buildmap);
|
||||
times[12].Unclock();
|
||||
|
||||
times[13].Clock();
|
||||
P_FloodZones ();
|
||||
P_FloodZones();
|
||||
times[13].Unclock();
|
||||
|
||||
if (hasglnodes)
|
||||
|
@ -4061,8 +4049,8 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
}
|
||||
|
||||
bodyqueslot = 0;
|
||||
// phares 8/10/98: Clear body queue so the corpses from previous games are
|
||||
// not assumed to be from this one.
|
||||
// phares 8/10/98: Clear body queue so the corpses from previous games are
|
||||
// not assumed to be from this one.
|
||||
|
||||
for (i = 0; i < BODYQUESIZE; i++)
|
||||
bodyque[i] = NULL;
|
||||
|
@ -4072,7 +4060,7 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
if (!buildmap)
|
||||
{
|
||||
// [RH] Spawn slope creating things first.
|
||||
P_SpawnSlopeMakers (&MapThingsConverted[0], &MapThingsConverted[MapThingsConverted.Size()], oldvertextable);
|
||||
P_SpawnSlopeMakers(&MapThingsConverted[0], &MapThingsConverted[MapThingsConverted.Size()], oldvertextable);
|
||||
P_CopySlopes();
|
||||
|
||||
// Spawn 3d floors - must be done before spawning things so it can't be done in P_SpawnSpecials
|
||||
|
@ -4090,7 +4078,7 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
|
||||
times[15].Clock();
|
||||
if (!map->HasBehavior && !map->isText)
|
||||
P_TranslateTeleportThings (); // [RH] Assign teleport destination TIDs
|
||||
P_TranslateTeleportThings(); // [RH] Assign teleport destination TIDs
|
||||
times[15].Unclock();
|
||||
}
|
||||
#if 0 // There is no such thing as a build map.
|
||||
|
@ -4098,7 +4086,7 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
{
|
||||
for (i = 0; i < numbuildthings; ++i)
|
||||
{
|
||||
SpawnMapThing (i, &buildthings[i], 0);
|
||||
SpawnMapThing(i, &buildthings[i], 0);
|
||||
}
|
||||
delete[] buildthings;
|
||||
}
|
||||
|
@ -4110,7 +4098,7 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
}
|
||||
|
||||
// set up world state
|
||||
P_SpawnSpecials ();
|
||||
P_SpawnSpecials();
|
||||
|
||||
// disable reflective planes on sloped sectors.
|
||||
for (auto &sec : level.sectors)
|
||||
|
@ -4133,8 +4121,8 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
P_InitHealthGroups();
|
||||
|
||||
times[16].Clock();
|
||||
if (reloop) P_LoopSidedefs (false);
|
||||
PO_Init (); // Initialize the polyobjs
|
||||
if (reloop) P_LoopSidedefs(false);
|
||||
PO_Init(); // Initialize the polyobjs
|
||||
if (!level.IsReentering())
|
||||
P_FinalizePortals(); // finalize line portals after polyobjects have been initialized. This info is needed for properly flagging them.
|
||||
times[16].Unclock();
|
||||
|
@ -4146,12 +4134,12 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
// if deathmatch, randomly spawn the active players
|
||||
if (deathmatch)
|
||||
{
|
||||
for (i=0 ; i<MAXPLAYERS ; i++)
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i])
|
||||
{
|
||||
players[i].mo = NULL;
|
||||
G_DeathMatchSpawnPlayer (i);
|
||||
G_DeathMatchSpawnPlayer(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4171,7 +4159,7 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
|
||||
// [SP] move unfriendly players around
|
||||
// horribly hacky - yes, this needs rewritten.
|
||||
if (level.deathmatchstarts.Size () > 0)
|
||||
if (level.deathmatchstarts.Size() > 0)
|
||||
{
|
||||
for (i = 0; i < MAXPLAYERS; ++i)
|
||||
{
|
||||
|
@ -4180,7 +4168,7 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
if (!(players[i].mo->flags & MF_FRIENDLY))
|
||||
{
|
||||
AActor * oldSpawn = players[i].mo;
|
||||
G_DeathMatchSpawnPlayer (i);
|
||||
G_DeathMatchSpawnPlayer(i);
|
||||
oldSpawn->Destroy();
|
||||
}
|
||||
}
|
||||
|
@ -4194,11 +4182,11 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
TThinkerIterator<AActor> it;
|
||||
AActor * mo;
|
||||
|
||||
while ((mo=it.Next()))
|
||||
while ((mo = it.Next()))
|
||||
{
|
||||
if (mo->flags & MF_COUNTKILL)
|
||||
{
|
||||
if (mo->Sector->damageamount > 0 && (mo->Sector->Flags & (SECF_ENDGODMODE|SECF_ENDLEVEL)) == (SECF_ENDGODMODE|SECF_ENDLEVEL))
|
||||
if (mo->Sector->damageamount > 0 && (mo->Sector->Flags & (SECF_ENDGODMODE | SECF_ENDLEVEL)) == (SECF_ENDGODMODE | SECF_ENDLEVEL))
|
||||
{
|
||||
mo->ClearCounters();
|
||||
}
|
||||
|
@ -4214,20 +4202,20 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
R_OldBlend = 0xffffffff;
|
||||
|
||||
// [RH] Remove all particles
|
||||
P_ClearParticles ();
|
||||
P_ClearParticles();
|
||||
|
||||
times[17].Clock();
|
||||
// preload graphics and sounds
|
||||
if (precache)
|
||||
{
|
||||
P_PrecacheLevel ();
|
||||
S_PrecacheLevel ();
|
||||
P_PrecacheLevel();
|
||||
S_PrecacheLevel();
|
||||
}
|
||||
times[17].Unclock();
|
||||
|
||||
if (deathmatch)
|
||||
{
|
||||
AnnounceGameStart ();
|
||||
AnnounceGameStart();
|
||||
}
|
||||
|
||||
// This check was previously done at run time each time the heightsec was checked.
|
||||
|
@ -4247,12 +4235,12 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
}
|
||||
}
|
||||
|
||||
P_ResetSightCounters (true);
|
||||
P_ResetSightCounters(true);
|
||||
//Printf ("free memory: 0x%x\n", Z_FreeMemory());
|
||||
|
||||
if (showloadtimes)
|
||||
{
|
||||
Printf ("---Total load times---\n");
|
||||
Printf("---Total load times---\n");
|
||||
for (i = 0; i < 18; ++i)
|
||||
{
|
||||
static const char *timenames[] =
|
||||
|
@ -4276,7 +4264,7 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
"init polys",
|
||||
"precache"
|
||||
};
|
||||
Printf ("Time%3d:%9.4f ms (%s)\n", i, times[i].TimeMS(), timenames[i]);
|
||||
Printf("Time%3d:%9.4f ms (%s)\n", i, times[i].TimeMS(), timenames[i]);
|
||||
}
|
||||
}
|
||||
MapThingsConverted.Clear();
|
||||
|
@ -4294,8 +4282,6 @@ void P_SetupLevel (const char *lumpname, int position, bool newGame)
|
|||
memcpy(&level.loadsides[0], &level.sides[0], level.sides.Size() * sizeof(level.sides[0]));
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// P_Init
|
||||
//
|
||||
|
|
|
@ -104,6 +104,13 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
TArray<uint8_t> Read(unsigned lumpindex)
|
||||
{
|
||||
TArray<uint8_t> buffer(Size(lumpindex), true);
|
||||
Read(lumpindex, buffer.Data(), (int)buffer.Size());
|
||||
return buffer;
|
||||
}
|
||||
|
||||
uint32_t Size(unsigned int lumpindex)
|
||||
{
|
||||
if (lumpindex<countof(MapLumps) && MapLumps[lumpindex].Reader.isOpen())
|
||||
|
|
|
@ -434,10 +434,13 @@ void P_RemoveThing(AActor * actor)
|
|||
|
||||
bool P_Thing_Raise(AActor *thing, AActor *raiser, int nocheck)
|
||||
{
|
||||
if (!thing)
|
||||
return false;
|
||||
|
||||
FState * RaiseState = thing->GetRaiseState();
|
||||
if (RaiseState == NULL)
|
||||
{
|
||||
return true; // monster doesn't have a raise state
|
||||
return false; // monster doesn't have a raise state
|
||||
}
|
||||
|
||||
AActor *info = thing->GetDefault ();
|
||||
|
@ -460,6 +463,8 @@ bool P_Thing_Raise(AActor *thing, AActor *raiser, int nocheck)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!P_CanResurrect(thing, raiser))
|
||||
return false;
|
||||
|
||||
S_Sound (thing, CHAN_BODY, "vile/raise", 1, ATTN_IDLE);
|
||||
|
||||
|
|
|
@ -1223,6 +1223,7 @@ public:
|
|||
{
|
||||
FName key = ParseKey();
|
||||
switch(key)
|
||||
|
||||
{
|
||||
case NAME_Offsetx:
|
||||
texOfs[0] = CheckInt(key);
|
||||
|
@ -1334,6 +1335,79 @@ public:
|
|||
Flag(sd->Flags, WALLF_NOAUTODECALS, key);
|
||||
continue;
|
||||
|
||||
case NAME_nogradient_top:
|
||||
Flag(sd->textures[side_t::top].flags, side_t::part::NoGradient, key);
|
||||
break;
|
||||
|
||||
case NAME_flipgradient_top:
|
||||
Flag(sd->textures[side_t::top].flags, side_t::part::FlipGradient, key);
|
||||
break;
|
||||
|
||||
case NAME_clampgradient_top:
|
||||
Flag(sd->textures[side_t::top].flags, side_t::part::ClampGradient, key);
|
||||
break;
|
||||
|
||||
case NAME_useowncolors_top:
|
||||
Flag(sd->textures[side_t::top].flags, side_t::part::UseOwnColors, key);
|
||||
break;
|
||||
|
||||
case NAME_uppercolor_top:
|
||||
sd->SetSpecialColor(side_t::top, 0, CheckInt(key));
|
||||
break;
|
||||
|
||||
case NAME_lowercolor_top:
|
||||
sd->SetSpecialColor(side_t::top, 1, CheckInt(key));
|
||||
break;
|
||||
|
||||
case NAME_nogradient_mid:
|
||||
Flag(sd->textures[side_t::mid].flags, side_t::part::NoGradient, key);
|
||||
break;
|
||||
|
||||
case NAME_flipgradient_mid:
|
||||
Flag(sd->textures[side_t::mid].flags, side_t::part::FlipGradient, key);
|
||||
break;
|
||||
|
||||
case NAME_clampgradient_mid:
|
||||
Flag(sd->textures[side_t::mid].flags, side_t::part::ClampGradient, key);
|
||||
break;
|
||||
|
||||
case NAME_useowncolors_mid:
|
||||
Flag(sd->textures[side_t::mid].flags, side_t::part::UseOwnColors, key);
|
||||
break;
|
||||
|
||||
case NAME_uppercolor_mid:
|
||||
sd->SetSpecialColor(side_t::mid, 0, CheckInt(key));
|
||||
break;
|
||||
|
||||
case NAME_lowercolor_mid:
|
||||
sd->SetSpecialColor(side_t::mid, 1, CheckInt(key));
|
||||
break;
|
||||
|
||||
case NAME_nogradient_bottom:
|
||||
Flag(sd->textures[side_t::bottom].flags, side_t::part::NoGradient, key);
|
||||
break;
|
||||
|
||||
case NAME_flipgradient_bottom:
|
||||
Flag(sd->textures[side_t::bottom].flags, side_t::part::FlipGradient, key);
|
||||
break;
|
||||
|
||||
case NAME_clampgradient_bottom:
|
||||
Flag(sd->textures[side_t::bottom].flags, side_t::part::ClampGradient, key);
|
||||
break;
|
||||
|
||||
case NAME_useowncolors_bottom:
|
||||
Flag(sd->textures[side_t::bottom].flags, side_t::part::UseOwnColors, key);
|
||||
break;
|
||||
|
||||
case NAME_uppercolor_bottom:
|
||||
sd->SetSpecialColor(side_t::bottom, 0, CheckInt(key));
|
||||
break;
|
||||
|
||||
case NAME_lowercolor_bottom:
|
||||
sd->SetSpecialColor(side_t::bottom, 1, CheckInt(key));
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
break;
|
||||
|
||||
|
@ -2045,15 +2119,11 @@ public:
|
|||
|
||||
void ParseTextMap(MapData *map)
|
||||
{
|
||||
char *buffer = new char[map->Size(ML_TEXTMAP)];
|
||||
|
||||
isTranslated = true;
|
||||
isExtended = false;
|
||||
floordrop = false;
|
||||
|
||||
map->Read(ML_TEXTMAP, buffer);
|
||||
sc.OpenMem(Wads.GetLumpFullName(map->lumpnum), buffer, map->Size(ML_TEXTMAP));
|
||||
delete [] buffer;
|
||||
sc.OpenMem(Wads.GetLumpFullName(map->lumpnum), map->Read(ML_TEXTMAP));
|
||||
sc.SetCMode(true);
|
||||
if (sc.CheckString("namespace"))
|
||||
{
|
||||
|
|
|
@ -473,10 +473,7 @@ class USDFParser : public UDMFParserBase
|
|||
public:
|
||||
bool Parse(int lumpnum, FileReader &lump, int lumplen)
|
||||
{
|
||||
char *buffer = new char[lumplen];
|
||||
lump.Read(buffer, lumplen);
|
||||
sc.OpenMem(Wads.GetLumpFullName(lumpnum), buffer, lumplen);
|
||||
delete [] buffer;
|
||||
sc.OpenMem(Wads.GetLumpFullName(lumpnum), lump.Read(lumplen));
|
||||
sc.SetCMode(true);
|
||||
// Namespace must be the first field because everything else depends on it.
|
||||
if (sc.CheckString("namespace"))
|
||||
|
|
|
@ -323,15 +323,12 @@ void FParseContext::ParseLump(const char *lumpname)
|
|||
}
|
||||
|
||||
// Read the lump into a buffer and add a 0-terminator
|
||||
int lumplen = Wads.LumpLength(lumpno);
|
||||
char *lumpdata = new char[lumplen+1];
|
||||
Wads.ReadLump(lumpno, lumpdata);
|
||||
lumpdata[lumplen] = 0;
|
||||
auto lumpdata = Wads.ReadLumpIntoArray(lumpno, 1);
|
||||
|
||||
SourceLine = 0;
|
||||
SourceFile = lumpname;
|
||||
|
||||
char *sourcep = lumpdata;
|
||||
char *sourcep = (char*)lumpdata.Data();
|
||||
while ( (tokentype = GetToken(sourcep, &token)) )
|
||||
{
|
||||
// It is much easier to handle include statements outside the main parser.
|
||||
|
@ -349,7 +346,6 @@ void FParseContext::ParseLump(const char *lumpname)
|
|||
Parse(pParser, tokentype, token, this);
|
||||
}
|
||||
}
|
||||
delete [] lumpdata;
|
||||
SourceLine = SavedSourceLine;
|
||||
SourceFile = SavedSourceFile;
|
||||
}
|
||||
|
|
|
@ -88,7 +88,6 @@ bool RenderPolyWall::RenderLine(PolyRenderThread *thread, seg_t *line, sector_t
|
|||
wall.Line = line->linedef;
|
||||
wall.Side = line->sidedef;
|
||||
wall.LineSegLine = line->linedef;
|
||||
wall.Colormap = GetColorTable(frontsector->Colormap, frontsector->SpecialColors[sector_t::walltop]);
|
||||
wall.Masked = false;
|
||||
wall.SubsectorDepth = subsectorDepth;
|
||||
wall.StencilValue = stencilValue;
|
||||
|
@ -102,6 +101,7 @@ bool RenderPolyWall::RenderLine(PolyRenderThread *thread, seg_t *line, sector_t
|
|||
wall.TopTexZ = topTexZ;
|
||||
wall.BottomTexZ = bottomTexZ;
|
||||
wall.Wallpart = side_t::mid;
|
||||
wall.Colormap = GetColorTable(frontsector->Colormap, wall.Side->GetSpecialColor(wall.Wallpart, side_t::walltop, frontsector));
|
||||
wall.Texture = GetTexture(wall.Line, wall.Side, side_t::mid);
|
||||
wall.Polyportal = polyportal;
|
||||
wall.Render(thread);
|
||||
|
@ -140,6 +140,7 @@ bool RenderPolyWall::RenderLine(PolyRenderThread *thread, seg_t *line, sector_t
|
|||
wall.TopTexZ = topTexZ;
|
||||
wall.BottomTexZ = MIN(MIN(backceilz1, frontceilz1), MIN(backceilz2, frontceilz2));
|
||||
wall.Wallpart = side_t::top;
|
||||
wall.Colormap = GetColorTable(frontsector->Colormap, wall.Side->GetSpecialColor(wall.Wallpart, side_t::walltop, frontsector));
|
||||
wall.Texture = GetTexture(wall.Line, wall.Side, side_t::top);
|
||||
wall.Render(thread);
|
||||
}
|
||||
|
@ -152,6 +153,7 @@ bool RenderPolyWall::RenderLine(PolyRenderThread *thread, seg_t *line, sector_t
|
|||
wall.UnpeggedCeil1 = topceilz1;
|
||||
wall.UnpeggedCeil2 = topceilz2;
|
||||
wall.Wallpart = side_t::bottom;
|
||||
wall.Colormap = GetColorTable(frontsector->Colormap, wall.Side->GetSpecialColor(wall.Wallpart, side_t::walltop, frontsector));
|
||||
wall.Texture = GetTexture(wall.Line, wall.Side, side_t::bottom);
|
||||
wall.Render(thread);
|
||||
}
|
||||
|
@ -162,6 +164,7 @@ bool RenderPolyWall::RenderLine(PolyRenderThread *thread, seg_t *line, sector_t
|
|||
wall.TopTexZ = MAX(middleceilz1, middleceilz2);
|
||||
wall.BottomTexZ = MIN(middlefloorz1, middlefloorz2);
|
||||
wall.Wallpart = side_t::mid;
|
||||
wall.Colormap = GetColorTable(frontsector->Colormap, wall.Side->GetSpecialColor(wall.Wallpart, side_t::walltop, frontsector));
|
||||
wall.Texture = GetTexture(wall.Line, wall.Side, side_t::mid);
|
||||
wall.Masked = true;
|
||||
wall.Additive = !!(wall.Line->flags & ML_ADDTRANS);
|
||||
|
@ -212,7 +215,6 @@ void RenderPolyWall::Render3DFloorLine(PolyRenderThread *thread, seg_t *line, se
|
|||
wall.LineSegLine = line->linedef;
|
||||
wall.Line = fakeFloor->master;
|
||||
wall.Side = fakeFloor->master->sidedef[0];
|
||||
wall.Colormap = GetColorTable(frontsector->Colormap, frontsector->SpecialColors[sector_t::walltop]);
|
||||
wall.SectorLightLevel = frontsector->lightlevel;
|
||||
wall.Additive = !!(fakeFloor->flags & FF_ADDITIVETRANS);
|
||||
if (!wall.Additive && fakeFloor->alpha == 255)
|
||||
|
@ -231,6 +233,7 @@ void RenderPolyWall::Render3DFloorLine(PolyRenderThread *thread, seg_t *line, se
|
|||
wall.TopTexZ = topTexZ;
|
||||
wall.BottomTexZ = bottomTexZ;
|
||||
wall.Wallpart = side_t::mid;
|
||||
wall.Colormap = GetColorTable(frontsector->Colormap, wall.Side->GetSpecialColor(wall.Wallpart, side_t::walltop, frontsector));
|
||||
if (fakeFloor->flags & FF_UPPERTEXTURE)
|
||||
wall.Texture = GetTexture(line->linedef, line->sidedef, side_t::top);
|
||||
else if (fakeFloor->flags & FF_LOWERTEXTURE)
|
||||
|
|
|
@ -64,6 +64,7 @@ struct WorkSection
|
|||
int sectorindex;
|
||||
int mapsection;
|
||||
bool hasminisegs;
|
||||
bool bad; // Did not produce a proper area and cannot be triangulated by tesselation.
|
||||
TArray<WorkSectionLine*>segments;
|
||||
TArray<side_t *> originalSides; // The segs will lose some of these while working on them.
|
||||
TArray<int> subsectors;
|
||||
|
@ -184,6 +185,33 @@ public:
|
|||
{
|
||||
CompileSections(pair->Value, rawsections);
|
||||
}
|
||||
|
||||
// Make sure that all subsectors have a sector. In some degenerate cases a subsector may come up empty.
|
||||
// An example is in Doom.wad E3M4 near linedef 1087. With the grouping data here this is relatively easy to fix.
|
||||
sector_t *lastsector = &level.sectors[0];
|
||||
for (auto &rawsection : rawsections)
|
||||
{
|
||||
sector_t *mysector = nullptr;
|
||||
bool missing = false;
|
||||
for (auto num : rawsection)
|
||||
{
|
||||
auto &sub = level.subsectors[num];
|
||||
if (sub.sector == nullptr) missing = true;
|
||||
else mysector = sub.sector;
|
||||
}
|
||||
// Should the worst case happen and no sector be found, use the last used one. Subsectors must not be sector-less!
|
||||
if (mysector == nullptr) mysector = lastsector;
|
||||
else lastsector = mysector;
|
||||
for (auto num : rawsection)
|
||||
{
|
||||
auto &sub = level.subsectors[num];
|
||||
if (sub.sector == nullptr)
|
||||
{
|
||||
sub.sector = mysector;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
subsectormap.Clear();
|
||||
return rawsections;
|
||||
}
|
||||
|
@ -253,8 +281,7 @@ public:
|
|||
{
|
||||
MakeOutline(list, lineForSeg);
|
||||
}
|
||||
rawsections.Clear();
|
||||
rawsections.ShrinkToFit();
|
||||
rawsections.Reset();
|
||||
|
||||
// Assign partners after everything has been collected
|
||||
for (auto §ion : sections)
|
||||
|
@ -281,6 +308,7 @@ public:
|
|||
TArray<seg_t *> outersegs;
|
||||
TArray<seg_t *> loopedsegs;
|
||||
bool hasminisegs = false;
|
||||
bool bad = false;
|
||||
|
||||
// Collect all the segs that make up the outline of this section.
|
||||
for (auto j : rawsection)
|
||||
|
@ -371,7 +399,8 @@ public:
|
|||
{
|
||||
// Did not find another one but have an unclosed loop. This should never happen and would indicate broken nodes.
|
||||
// Error out and let the calling code deal with it.
|
||||
I_Error("Unclosed loop in sector %d at position (%d, %d)\n", loopedsegs[0]->Subsector->render_sector->Index(), (int)loopedsegs[0]->v1->fX(), (int)loopedsegs[0]->v1->fY());
|
||||
DPrintf(DMSG_NOTIFY, "Unclosed loop in sector %d at position (%d, %d)\n", loopedsegs[0]->Subsector->render_sector->Index(), (int)loopedsegs[0]->v1->fX(), (int)loopedsegs[0]->v1->fY());
|
||||
bad = true;
|
||||
}
|
||||
seg = nullptr;
|
||||
loopedsegs.Push(nullptr); // A separator is not really needed but useful for debugging.
|
||||
|
@ -402,6 +431,7 @@ public:
|
|||
section.sectorindex = sector;
|
||||
section.mapsection = mapsec;
|
||||
section.hasminisegs = hasminisegs;
|
||||
section.bad = bad;
|
||||
section.originalSides = std::move(foundsides);
|
||||
section.segments = std::move(sectionlines);
|
||||
section.subsectors = std::move(rawsection);
|
||||
|
@ -720,8 +750,59 @@ public:
|
|||
curgroup++;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Check if some subsectors have come up empty on sections.
|
||||
// In this case assign the best fit from the containing sector.
|
||||
// This is only to ensure that the section pointer is not null.
|
||||
// These are always degenerate and do not produce any actual render output.
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
void FixMissingReferences()
|
||||
{
|
||||
for (auto &sub : level.subsectors)
|
||||
{
|
||||
if (sub.section == nullptr)
|
||||
{
|
||||
int sector = sub.sector->Index();
|
||||
int mapsection = sub.mapsection;
|
||||
auto sections = level.sections.SectionsForSector(sector);
|
||||
FSection *bestfit = nullptr;
|
||||
for (auto §ion : sections)
|
||||
{
|
||||
if (bestfit == nullptr)
|
||||
{
|
||||
bestfit = §ion;
|
||||
}
|
||||
else if (bestfit->mapsection != section.mapsection && section.mapsection == mapsection)
|
||||
{
|
||||
bestfit = §ion;
|
||||
}
|
||||
else if (section.mapsection == mapsection)
|
||||
{
|
||||
BoundingRect rc;
|
||||
for (unsigned i = 0; i < sub.numlines; i++)
|
||||
{
|
||||
rc.addVertex(sub.firstline[i].v1->fX(), sub.firstline[i].v1->fY());
|
||||
rc.addVertex(sub.firstline[i].v2->fX(), sub.firstline[i].v2->fY());
|
||||
}
|
||||
// Pick the one closer to this subsector.
|
||||
if (rc.distanceTo(section.bounds) < rc.distanceTo(bestfit->bounds))
|
||||
{
|
||||
bestfit = §ion;
|
||||
}
|
||||
}
|
||||
}
|
||||
// This should really never happen, but better be safe than sorry and assign at least something.
|
||||
if (bestfit == nullptr) bestfit = &level.sections.allSections[0];
|
||||
sub.section = bestfit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
|
@ -787,6 +868,7 @@ void CreateSections(FSectionContainer &container)
|
|||
creat.FindOuterLoops();
|
||||
creat.GroupSections();
|
||||
creat.ConstructOutput(container);
|
||||
creat.FixMissingReferences();
|
||||
}
|
||||
|
||||
CCMD(printsections)
|
||||
|
|
54
src/r_defs.h
54
src/r_defs.h
|
@ -325,7 +325,7 @@ public:
|
|||
return !normal.XY().isZero();
|
||||
}
|
||||
|
||||
DVector3 Normal() const
|
||||
const DVector3 &Normal() const
|
||||
{
|
||||
return normal;
|
||||
}
|
||||
|
@ -645,8 +645,6 @@ public:
|
|||
void SetColor(int r, int g, int b, int desat);
|
||||
void SetFade(int r, int g, int b);
|
||||
void SetFogDensity(int dens);
|
||||
void SetSpecialColor(int num, int r, int g, int b);
|
||||
void SetSpecialColor(int num, PalEntry rgb);
|
||||
void ClosestPoint(const DVector2 &pos, DVector2 &out) const;
|
||||
int GetFloorLight () const;
|
||||
int GetCeilingLight () const;
|
||||
|
@ -917,6 +915,17 @@ public:
|
|||
Flags &= ~SECF_SPECIALFLAGS;
|
||||
}
|
||||
|
||||
void SetSpecialColor(int slot, int r, int g, int b)
|
||||
{
|
||||
SpecialColors[slot] = PalEntry(255, r, g, b);
|
||||
}
|
||||
|
||||
void SetSpecialColor(int slot, PalEntry rgb)
|
||||
{
|
||||
rgb.a = 255;
|
||||
SpecialColors[slot] = rgb;
|
||||
}
|
||||
|
||||
inline bool PortalBlocksView(int plane);
|
||||
inline bool PortalBlocksSight(int plane);
|
||||
inline bool PortalBlocksMovement(int plane);
|
||||
|
@ -1138,16 +1147,31 @@ struct side_t
|
|||
{
|
||||
top=0,
|
||||
mid=1,
|
||||
bottom=2
|
||||
bottom=2,
|
||||
none = 1, // this is just for clarification in a mapping table
|
||||
};
|
||||
enum EColorSlot
|
||||
{
|
||||
walltop = 0,
|
||||
wallbottom = 1,
|
||||
};
|
||||
struct part
|
||||
{
|
||||
enum EPartFlags
|
||||
{
|
||||
NoGradient = 1,
|
||||
FlipGradient = 2,
|
||||
ClampGradient = 4,
|
||||
UseOwnColors = 8,
|
||||
};
|
||||
double xOffset;
|
||||
double yOffset;
|
||||
double xScale;
|
||||
double yScale;
|
||||
TObjPtr<DInterpolation*> interpolation;
|
||||
FTextureID texture;
|
||||
int flags;
|
||||
PalEntry SpecialColors[2];
|
||||
|
||||
void InitFrom(const part &other)
|
||||
{
|
||||
|
@ -1270,6 +1294,28 @@ struct side_t
|
|||
textures[which].yScale *= delta;
|
||||
}
|
||||
|
||||
void SetSpecialColor(int which, int slot, int r, int g, int b)
|
||||
{
|
||||
textures[which].SpecialColors[slot] = PalEntry(255, r, g, b);
|
||||
}
|
||||
|
||||
void SetSpecialColor(int which, int slot, PalEntry rgb)
|
||||
{
|
||||
rgb.a = 255;
|
||||
textures[which].SpecialColors[slot] = rgb;
|
||||
}
|
||||
|
||||
// Note that the sector being passed in here may not be the actual sector this sidedef belongs to
|
||||
// (either for polyobjects or FakeFlat'ed temporaries.)
|
||||
PalEntry GetSpecialColor(int which, int slot, sector_t *frontsector) const
|
||||
{
|
||||
auto &part = textures[which];
|
||||
if (part.flags & part::NoGradient) slot = 0;
|
||||
if (part.flags & part::FlipGradient) slot ^= 1;
|
||||
return (part.flags & part::UseOwnColors) ? part.SpecialColors[slot] : frontsector->SpecialColors[sector_t::walltop + slot];
|
||||
}
|
||||
|
||||
|
||||
DInterpolation *SetInterpolation(int position);
|
||||
void StopInterpolation(int position);
|
||||
|
||||
|
|
|
@ -230,7 +230,7 @@ bool F7ZFile::Open(bool quiet)
|
|||
Archive = NULL;
|
||||
if (!quiet)
|
||||
{
|
||||
Printf("\n" TEXTCOLOR_RED "%s: ", Filename);
|
||||
Printf("\n" TEXTCOLOR_RED "%s: ", FileName.GetChars());
|
||||
if (res == SZ_ERROR_UNSUPPORTED)
|
||||
{
|
||||
Printf("Decoder does not support this archive\n");
|
||||
|
@ -309,7 +309,7 @@ bool F7ZFile::Open(bool quiet)
|
|||
|
||||
if (SZ_OK != Archive->Extract(Lumps[0].Position, &temp[0]))
|
||||
{
|
||||
if (!quiet) Printf("\n%s: unsupported 7z/LZMA file!\n", Filename);
|
||||
if (!quiet) Printf("\n%s: unsupported 7z/LZMA file!\n", FileName.GetChars());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -102,9 +102,9 @@ FDirectory::FDirectory(const char * directory)
|
|||
#ifdef _WIN32
|
||||
free((void *)directory);
|
||||
#endif
|
||||
dirname.ReplaceChars('\\', '/');
|
||||
FixPathSeperator(dirname);
|
||||
if (dirname[dirname.Len()-1] != '/') dirname += '/';
|
||||
Filename = copystring(dirname);
|
||||
FileName = dirname;
|
||||
}
|
||||
|
||||
|
||||
|
@ -195,7 +195,7 @@ int FDirectory::AddDirectory(const char *dirpath)
|
|||
return 0;
|
||||
}
|
||||
|
||||
const size_t namepos = strlen(Filename);
|
||||
const size_t namepos = strlen(FileName);
|
||||
FString pathfix;
|
||||
|
||||
while ((ent = fts_read(fts)) != NULL)
|
||||
|
@ -248,7 +248,7 @@ int FDirectory::AddDirectory(const char *dirpath)
|
|||
|
||||
bool FDirectory::Open(bool quiet)
|
||||
{
|
||||
NumLumps = AddDirectory(Filename);
|
||||
NumLumps = AddDirectory(FileName);
|
||||
if (!quiet) Printf(", %d lumps\n", NumLumps);
|
||||
PostProcessArchive(&Lumps[0], sizeof(FDirectoryLump));
|
||||
return true;
|
||||
|
@ -268,7 +268,7 @@ void FDirectory::AddEntry(const char *fullpath, int size)
|
|||
lump_p->mFullPath = fullpath;
|
||||
|
||||
// [mxd] Convert name to lowercase
|
||||
FString name = fullpath + strlen(Filename);
|
||||
FString name = fullpath + strlen(FileName);
|
||||
name.ToLower();
|
||||
|
||||
// The lump's name is only the part relative to the main directory
|
||||
|
|
|
@ -85,7 +85,6 @@ public:
|
|||
FGrpFile::FGrpFile(const char *filename, FileReader &file)
|
||||
: FUncompressedFile(filename, file)
|
||||
{
|
||||
Lumps = NULL;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -104,7 +103,7 @@ bool FGrpFile::Open(bool quiet)
|
|||
GrpLump *fileinfo = new GrpLump[NumLumps];
|
||||
Reader.Read (fileinfo, NumLumps * sizeof(GrpLump));
|
||||
|
||||
Lumps = new FUncompressedLump[NumLumps];
|
||||
Lumps.Resize(NumLumps);
|
||||
|
||||
int Position = sizeof(GrpInfo) + NumLumps * sizeof(GrpLump);
|
||||
|
||||
|
|
|
@ -69,17 +69,17 @@ FLumpFile::FLumpFile(const char *filename, FileReader &file)
|
|||
|
||||
bool FLumpFile::Open(bool quiet)
|
||||
{
|
||||
FString name(ExtractFileBase (Filename));
|
||||
FString name(ExtractFileBase (FileName));
|
||||
|
||||
Lumps = new FUncompressedLump[1]; // must use array allocator
|
||||
uppercopy(Lumps->Name, name);
|
||||
Lumps->Name[8] = 0;
|
||||
Lumps->Owner = this;
|
||||
Lumps->Position = 0;
|
||||
Lumps->LumpSize = (int)Reader.GetLength();
|
||||
Lumps->Namespace = ns_global;
|
||||
Lumps->Flags = 0;
|
||||
Lumps->FullName = NULL;
|
||||
Lumps.Resize(1);
|
||||
uppercopy(Lumps[0].Name, name);
|
||||
Lumps[0].Name[8] = 0;
|
||||
Lumps[0].Owner = this;
|
||||
Lumps[0].Position = 0;
|
||||
Lumps[0].LumpSize = (int)Reader.GetLength();
|
||||
Lumps[0].Namespace = ns_global;
|
||||
Lumps[0].Flags = 0;
|
||||
Lumps[0].FullName = NULL;
|
||||
NumLumps = 1;
|
||||
if (!quiet)
|
||||
{
|
||||
|
|
|
@ -80,7 +80,6 @@ public:
|
|||
FPakFile::FPakFile(const char *filename, FileReader &file)
|
||||
: FUncompressedFile(filename, file)
|
||||
{
|
||||
Lumps = NULL;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -101,7 +100,7 @@ bool FPakFile::Open(bool quiet)
|
|||
Reader.Seek (header.dirofs, FileReader::SeekSet);
|
||||
Reader.Read (fileinfo, NumLumps * sizeof(dpackfile_t));
|
||||
|
||||
Lumps = new FUncompressedLump[NumLumps];
|
||||
Lumps.Resize(NumLumps);
|
||||
|
||||
if (!quiet && !batchrun) Printf(", %d lumps\n", NumLumps);
|
||||
|
||||
|
|
|
@ -165,7 +165,7 @@ bool FWadFile::Open(bool quiet)
|
|||
// Check again to detect broken wads
|
||||
if (InfoTableOfs + NumLumps*sizeof(wadlump_t) > (unsigned)wadSize)
|
||||
{
|
||||
I_Error("Cannot load broken WAD file %s\n", Filename);
|
||||
I_Error("Cannot load broken WAD file %s\n", FileName.GetChars());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -194,7 +194,7 @@ bool FWadFile::Open(bool quiet)
|
|||
{
|
||||
if (Lumps[i].LumpSize != 0)
|
||||
{
|
||||
Printf(PRINT_HIGH, "%s: Lump %s contains invalid positioning info and will be ignored\n", Filename, Lumps[i].Name);
|
||||
Printf(PRINT_HIGH, "%s: Lump %s contains invalid positioning info and will be ignored\n", FileName.GetChars(), Lumps[i].Name);
|
||||
Lumps[i].Name[0] = 0;
|
||||
}
|
||||
Lumps[i].LumpSize = Lumps[i].Position = 0;
|
||||
|
@ -439,7 +439,7 @@ void FWadFile::SkinHack ()
|
|||
"The maps in %s will not be loaded because it has a skin.\n"
|
||||
TEXTCOLOR_BLUE
|
||||
"You should remove the skin from the wad to play these maps.\n",
|
||||
Filename);
|
||||
FileName.GetChars());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -181,7 +181,7 @@ bool FZipFile::Open(bool quiet)
|
|||
|
||||
if (centraldir == 0)
|
||||
{
|
||||
if (!quiet) Printf(TEXTCOLOR_RED "\n%s: ZIP file corrupt!\n", Filename);
|
||||
if (!quiet) Printf(TEXTCOLOR_RED "\n%s: ZIP file corrupt!\n", FileName.GetChars());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -193,7 +193,7 @@ bool FZipFile::Open(bool quiet)
|
|||
if (info.NumEntries != info.NumEntriesOnAllDisks ||
|
||||
info.FirstDisk != 0 || info.DiskNumber != 0)
|
||||
{
|
||||
if (!quiet) Printf(TEXTCOLOR_RED "\n%s: Multipart Zip files are not supported.\n", Filename);
|
||||
if (!quiet) Printf(TEXTCOLOR_RED "\n%s: Multipart Zip files are not supported.\n", FileName.GetChars());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -229,7 +229,7 @@ bool FZipFile::Open(bool quiet)
|
|||
if (dirptr > ((char*)directory) + dirsize) // This directory entry goes beyond the end of the file.
|
||||
{
|
||||
free(directory);
|
||||
if (!quiet) Printf(TEXTCOLOR_RED "\n%s: Central directory corrupted.", Filename);
|
||||
if (!quiet) Printf(TEXTCOLOR_RED "\n%s: Central directory corrupted.", FileName.GetChars());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -300,7 +300,7 @@ bool FZipFile::Open(bool quiet)
|
|||
if (dirptr > ((char*)directory) + dirsize) // This directory entry goes beyond the end of the file.
|
||||
{
|
||||
free(directory);
|
||||
if (!quiet) Printf(TEXTCOLOR_RED "\n%s: Central directory corrupted.", Filename);
|
||||
if (!quiet) Printf(TEXTCOLOR_RED "\n%s: Central directory corrupted.", FileName.GetChars());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -320,7 +320,7 @@ bool FZipFile::Open(bool quiet)
|
|||
zip_fh->Method != METHOD_IMPLODE &&
|
||||
zip_fh->Method != METHOD_SHRINK)
|
||||
{
|
||||
if (!quiet) Printf(TEXTCOLOR_YELLOW "\n%s: '%s' uses an unsupported compression algorithm (#%d).\n", Filename, name.GetChars(), zip_fh->Method);
|
||||
if (!quiet) Printf(TEXTCOLOR_YELLOW "\n%s: '%s' uses an unsupported compression algorithm (#%d).\n", FileName.GetChars(), name.GetChars(), zip_fh->Method);
|
||||
skipped++;
|
||||
continue;
|
||||
}
|
||||
|
@ -328,7 +328,7 @@ bool FZipFile::Open(bool quiet)
|
|||
zip_fh->Flags = LittleShort(zip_fh->Flags);
|
||||
if (zip_fh->Flags & ZF_ENCRYPTED)
|
||||
{
|
||||
if (!quiet) Printf(TEXTCOLOR_YELLOW "\n%s: '%s' is encrypted. Encryption is not supported.\n", Filename, name.GetChars());
|
||||
if (!quiet) Printf(TEXTCOLOR_YELLOW "\n%s: '%s' is encrypted. Encryption is not supported.\n", FileName.GetChars(), name.GetChars());
|
||||
skipped++;
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -156,7 +156,7 @@ static bool IsWadInFolder(const FResourceFile* const archive, const char* const
|
|||
return false;
|
||||
}
|
||||
|
||||
const FString dirName = ExtractFileBase(archive->Filename);
|
||||
const FString dirName = ExtractFileBase(archive->FileName);
|
||||
const FString fileName = ExtractFileBase(resPath, true);
|
||||
const FString filePath = dirName + '/' + fileName;
|
||||
|
||||
|
@ -323,9 +323,8 @@ FResourceFile *FResourceFile::OpenDirectory(const char *filename, bool quiet)
|
|||
//==========================================================================
|
||||
|
||||
FResourceFile::FResourceFile(const char *filename)
|
||||
: FileName(filename)
|
||||
{
|
||||
if (filename != NULL) Filename = copystring(filename);
|
||||
else Filename = NULL;
|
||||
}
|
||||
|
||||
FResourceFile::FResourceFile(const char *filename, FileReader &r)
|
||||
|
@ -336,7 +335,6 @@ FResourceFile::FResourceFile(const char *filename, FileReader &r)
|
|||
|
||||
FResourceFile::~FResourceFile()
|
||||
{
|
||||
if (Filename != NULL) delete [] Filename;
|
||||
}
|
||||
|
||||
int lumpcmp(const void * a, const void * b)
|
||||
|
@ -653,12 +651,6 @@ FUncompressedFile::FUncompressedFile(const char *filename, FileReader &r)
|
|||
: FResourceFile(filename, r)
|
||||
{}
|
||||
|
||||
FUncompressedFile::~FUncompressedFile()
|
||||
{
|
||||
if (Lumps != NULL) delete [] Lumps;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
@ -667,9 +659,8 @@ FUncompressedFile::~FUncompressedFile()
|
|||
//==========================================================================
|
||||
|
||||
FExternalLump::FExternalLump(const char *_filename, int filesize)
|
||||
: Filename(_filename)
|
||||
{
|
||||
filename = _filename? copystring(_filename) : NULL;
|
||||
|
||||
if (filesize == -1)
|
||||
{
|
||||
FileReader f;
|
||||
|
@ -690,11 +681,6 @@ FExternalLump::FExternalLump(const char *_filename, int filesize)
|
|||
}
|
||||
|
||||
|
||||
FExternalLump::~FExternalLump()
|
||||
{
|
||||
if (filename != NULL) delete [] filename;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Caches a lump's content and increases the reference counter
|
||||
|
@ -707,7 +693,7 @@ int FExternalLump::FillCache()
|
|||
Cache = new char[LumpSize];
|
||||
FileReader f;
|
||||
|
||||
if (f.OpenFile(filename))
|
||||
if (f.OpenFile(Filename))
|
||||
{
|
||||
f.Read(Cache, LumpSize);
|
||||
}
|
||||
|
@ -722,19 +708,19 @@ int FExternalLump::FillCache()
|
|||
|
||||
bool FMemoryFile::Open(bool quiet)
|
||||
{
|
||||
FString name(ExtractFileBase(Filename));
|
||||
FString fname(ExtractFileBase(Filename, true));
|
||||
FString name(ExtractFileBase(FileName));
|
||||
FString fname(ExtractFileBase(FileName, true));
|
||||
|
||||
Lumps = new FUncompressedLump[1]; // must use array allocator
|
||||
uppercopy(Lumps->Name, name);
|
||||
Lumps->Name[8] = 0;
|
||||
Lumps->FullName = fname;
|
||||
Lumps->Owner = this;
|
||||
Lumps->Position = 0;
|
||||
Lumps->LumpSize = (int)Reader.GetLength();
|
||||
Lumps->Namespace = ns_global;
|
||||
Lumps->Flags = 0;
|
||||
Lumps->FullName = NULL;
|
||||
Lumps.Resize(1);
|
||||
uppercopy(Lumps[0].Name, name);
|
||||
Lumps[0].Name[8] = 0;
|
||||
Lumps[0].FullName = fname;
|
||||
Lumps[0].Owner = this;
|
||||
Lumps[0].Position = 0;
|
||||
Lumps[0].LumpSize = (int)Reader.GetLength();
|
||||
Lumps[0].Namespace = ns_global;
|
||||
Lumps[0].Flags = 0;
|
||||
Lumps[0].FullName = nullptr;
|
||||
NumLumps = 1;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -82,7 +82,7 @@ class FResourceFile
|
|||
{
|
||||
public:
|
||||
FileReader Reader;
|
||||
const char *Filename;
|
||||
FString FileName;
|
||||
protected:
|
||||
uint32_t NumLumps;
|
||||
|
||||
|
@ -133,21 +133,19 @@ struct FUncompressedLump : public FResourceLump
|
|||
class FUncompressedFile : public FResourceFile
|
||||
{
|
||||
protected:
|
||||
FUncompressedLump * Lumps = nullptr;
|
||||
TArray<FUncompressedLump> Lumps;
|
||||
|
||||
FUncompressedFile(const char *filename);
|
||||
FUncompressedFile(const char *filename, FileReader &r);
|
||||
virtual ~FUncompressedFile();
|
||||
virtual FResourceLump *GetLump(int no) { return ((unsigned)no < NumLumps)? &Lumps[no] : NULL; }
|
||||
};
|
||||
|
||||
|
||||
struct FExternalLump : public FResourceLump
|
||||
{
|
||||
const char *filename; // the actual file name. This is not necessarily the same as the lump name!
|
||||
FString Filename;
|
||||
|
||||
FExternalLump(const char *_filename, int filesize = -1);
|
||||
~FExternalLump();
|
||||
virtual int FillCache();
|
||||
|
||||
};
|
||||
|
|
|
@ -21,6 +21,10 @@ public:
|
|||
void Open(const char *lumpname);
|
||||
bool OpenFile(const char *filename);
|
||||
void OpenMem(const char *name, const char *buffer, int size);
|
||||
void OpenMem(const char *name, const TArray<uint8_t> &buffer)
|
||||
{
|
||||
OpenMem(name, (const char*)buffer.Data(), buffer.Size());
|
||||
}
|
||||
void OpenString(const char *name, FString buffer);
|
||||
void OpenLumpNum(int lump);
|
||||
void Close();
|
||||
|
|
|
@ -443,7 +443,7 @@ static void DoParse(int lumpnum)
|
|||
// If the parser fails, there is no point starting the compiler, because it'd only flood the output with endless errors.
|
||||
if (FScriptPosition::ErrorCounter > 0)
|
||||
{
|
||||
I_Error("%d errors while parsing %s", FScriptPosition::ErrorCounter, Wads.GetLumpFullPath(lumpnum).GetChars());
|
||||
I_Error("%d errors while parsing %s", FScriptPosition::ErrorCounter, Wads.GetLumpFullPath(baselump).GetChars());
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
@ -457,7 +457,7 @@ static void DoParse(int lumpnum)
|
|||
if (Args->CheckParm("-dumpast"))
|
||||
{
|
||||
FString ast = ZCC_PrintAST(state.TopNode);
|
||||
FString filename = Wads.GetLumpFullPath(lumpnum);
|
||||
FString filename = Wads.GetLumpFullPath(baselump);
|
||||
filename.ReplaceChars(":\\/?|", '.');
|
||||
filename << ".ast";
|
||||
FileWriter *ff = FileWriter::Open(filename);
|
||||
|
@ -469,19 +469,19 @@ static void DoParse(int lumpnum)
|
|||
}
|
||||
|
||||
PSymbolTable symtable;
|
||||
auto newns = Wads.GetLumpFile(lumpnum) == 0 ? Namespaces.GlobalNamespace : Namespaces.NewNamespace(Wads.GetLumpFile(lumpnum));
|
||||
ZCCCompiler cc(state, NULL, symtable, newns, lumpnum, state.ParseVersion);
|
||||
auto newns = Wads.GetLumpFile(baselump) == 0 ? Namespaces.GlobalNamespace : Namespaces.NewNamespace(Wads.GetLumpFile(baselump));
|
||||
ZCCCompiler cc(state, NULL, symtable, newns, baselump, state.ParseVersion);
|
||||
cc.Compile();
|
||||
|
||||
if (FScriptPosition::ErrorCounter > 0)
|
||||
{
|
||||
// Abort if the compiler produced any errors. Also do not compile further lumps, because they very likely miss some stuff.
|
||||
I_Error("%d errors, %d warnings while compiling %s", FScriptPosition::ErrorCounter, FScriptPosition::WarnCounter, Wads.GetLumpFullPath(lumpnum).GetChars());
|
||||
I_Error("%d errors, %d warnings while compiling %s", FScriptPosition::ErrorCounter, FScriptPosition::WarnCounter, Wads.GetLumpFullPath(baselump).GetChars());
|
||||
}
|
||||
else if (FScriptPosition::WarnCounter > 0)
|
||||
{
|
||||
// If we got warnings, but no errors, print the information but continue.
|
||||
Printf(TEXTCOLOR_ORANGE "%d warnings while compiling %s\n", FScriptPosition::WarnCounter, Wads.GetLumpFullPath(lumpnum).GetChars());
|
||||
Printf(TEXTCOLOR_ORANGE "%d warnings while compiling %s\n", FScriptPosition::WarnCounter, Wads.GetLumpFullPath(baselump).GetChars());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
65
src/tarray.h
65
src/tarray.h
|
@ -157,14 +157,14 @@ public:
|
|||
Count = 0;
|
||||
Array = NULL;
|
||||
}
|
||||
TArray (int max, bool reserve = false)
|
||||
TArray (size_t max, bool reserve = false)
|
||||
{
|
||||
Most = max;
|
||||
Count = reserve? max : 0;
|
||||
Most = (unsigned)max;
|
||||
Count = (unsigned)(reserve? max : 0);
|
||||
Array = (T *)M_Malloc (sizeof(T)*max);
|
||||
if (reserve)
|
||||
if (reserve && Count > 0)
|
||||
{
|
||||
for (unsigned i = 0; i < Count; i++) ::new(&Array[i]) T();
|
||||
ConstructEmpty(0, Count - 1);
|
||||
}
|
||||
}
|
||||
TArray (const TArray<T,TT> &other)
|
||||
|
@ -362,17 +362,6 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
// Reserves a range of entries in the middle of the array, shifting elements as needed
|
||||
void ReserveAt(unsigned int index, unsigned int amount)
|
||||
{
|
||||
Grow(amount);
|
||||
memmove(&Array[index + amount], &Array[index], sizeof(T)*(Count - index - amount));
|
||||
for (unsigned i = 0; i < amount; i++)
|
||||
{
|
||||
::new ((void *)&Array[index + i]) T();
|
||||
}
|
||||
}
|
||||
|
||||
void ShrinkToFit ()
|
||||
{
|
||||
if (Most > Count)
|
||||
|
@ -411,10 +400,7 @@ public:
|
|||
{
|
||||
// Adding new entries
|
||||
Grow (amount - Count);
|
||||
for (unsigned int i = Count; i < amount; ++i)
|
||||
{
|
||||
::new((void *)&Array[i]) T;
|
||||
}
|
||||
ConstructEmpty(Count, amount - 1);
|
||||
}
|
||||
else if (Count != amount)
|
||||
{
|
||||
|
@ -423,6 +409,18 @@ public:
|
|||
}
|
||||
Count = amount;
|
||||
}
|
||||
// Ensures that the array has at most amount entries.
|
||||
// Useful in cases where the initial allocation may be larger than the final result.
|
||||
// Resize would create a lot of unneeded code in those cases.
|
||||
void Clamp(unsigned int amount)
|
||||
{
|
||||
if (Count > amount)
|
||||
{
|
||||
// Deleting old entries
|
||||
DoDelete(amount, Count - 1);
|
||||
Count = amount;
|
||||
}
|
||||
}
|
||||
void Alloc(unsigned int amount)
|
||||
{
|
||||
// first destroys all content and then rebuilds the array.
|
||||
|
@ -433,15 +431,12 @@ public:
|
|||
}
|
||||
// Reserves amount entries at the end of the array, but does nothing
|
||||
// with them.
|
||||
unsigned int Reserve (unsigned int amount)
|
||||
unsigned int Reserve (size_t amount)
|
||||
{
|
||||
Grow (amount);
|
||||
Grow ((unsigned)amount);
|
||||
unsigned int place = Count;
|
||||
Count += amount;
|
||||
for (unsigned int i = place; i < Count; ++i)
|
||||
{
|
||||
::new((void *)&Array[i]) T;
|
||||
}
|
||||
Count += (unsigned)amount;
|
||||
if (Count > 0) ConstructEmpty(place, Count - 1);
|
||||
return place;
|
||||
}
|
||||
unsigned int Size () const
|
||||
|
@ -463,7 +458,12 @@ public:
|
|||
void Reset()
|
||||
{
|
||||
Clear();
|
||||
ShrinkToFit();
|
||||
Most = 0;
|
||||
if (Array != nullptr)
|
||||
{
|
||||
M_Free(Array);
|
||||
Array = nullptr;
|
||||
}
|
||||
}
|
||||
private:
|
||||
T *Array;
|
||||
|
@ -501,6 +501,15 @@ private:
|
|||
Array[i].~T();
|
||||
}
|
||||
}
|
||||
|
||||
void ConstructEmpty(unsigned int first, unsigned int last)
|
||||
{
|
||||
assert(last != ~0u);
|
||||
for (unsigned int i = first; i <= last; ++i)
|
||||
{
|
||||
::new(&Array[i]) T;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// TDeletingArray -----------------------------------------------------------
|
||||
|
|
|
@ -419,7 +419,8 @@ void F2DDrawer::AddShape( FTexture *img, DShape2D *shape, DrawParms &parms )
|
|||
|
||||
void F2DDrawer::AddPoly(FTexture *texture, FVector2 *points, int npoints,
|
||||
double originx, double originy, double scalex, double scaley,
|
||||
DAngle rotation, const FColormap &colormap, PalEntry flatcolor, int lightlevel)
|
||||
DAngle rotation, const FColormap &colormap, PalEntry flatcolor, int lightlevel,
|
||||
uint32_t *indices, size_t indexcount)
|
||||
{
|
||||
// Use an equation similar to player sprites to determine shade
|
||||
|
||||
|
@ -487,9 +488,20 @@ void F2DDrawer::AddPoly(FTexture *texture, FVector2 *points, int npoints,
|
|||
poly.mIndexIndex = mIndices.Size();
|
||||
poly.mIndexCount += (npoints - 2) * 3;
|
||||
|
||||
for (int i = 2; i < npoints; ++i)
|
||||
if (indices == nullptr || indexcount == 0)
|
||||
{
|
||||
AddIndices(poly.mVertIndex, 3, 0, i - 1, i);
|
||||
for (int i = 2; i < npoints; ++i)
|
||||
{
|
||||
AddIndices(poly.mVertIndex, 3, 0, i - 1, i);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int addr = mIndices.Reserve(indexcount);
|
||||
for (size_t i = 0; i < indexcount; i++)
|
||||
{
|
||||
mIndices[addr + i] = addr + indices[i];
|
||||
}
|
||||
}
|
||||
|
||||
AddCommand(&poly);
|
||||
|
|
|
@ -130,7 +130,7 @@ public:
|
|||
void AddShape(FTexture *img, DShape2D *shape, DrawParms &parms);
|
||||
void AddPoly(FTexture *texture, FVector2 *points, int npoints,
|
||||
double originx, double originy, double scalex, double scaley,
|
||||
DAngle rotation, const FColormap &colormap, PalEntry flatcolor, int lightlevel);
|
||||
DAngle rotation, const FColormap &colormap, PalEntry flatcolor, int lightlevel, uint32_t *indices, size_t indexcount);
|
||||
void AddFlatFill(int left, int top, int right, int bottom, FTexture *src, bool local_origin);
|
||||
|
||||
void AddColorOnlyQuad(int left, int top, int width, int height, PalEntry color, FRenderStyle *style);
|
||||
|
|
|
@ -1253,9 +1253,9 @@ DEFINE_ACTION_FUNCTION(_Screen, Dim)
|
|||
|
||||
void DFrameBuffer::FillSimplePoly(FTexture *tex, FVector2 *points, int npoints,
|
||||
double originx, double originy, double scalex, double scaley, DAngle rotation,
|
||||
const FColormap &colormap, PalEntry flatcolor, int lightlevel, int bottomclip)
|
||||
const FColormap &colormap, PalEntry flatcolor, int lightlevel, int bottomclip, uint32_t *indices, size_t indexcount)
|
||||
{
|
||||
m2DDrawer.AddPoly(tex, points, npoints, originx, originy, scalex, scaley, rotation, colormap, flatcolor, lightlevel);
|
||||
m2DDrawer.AddPoly(tex, points, npoints, originx, originy, scalex, scaley, rotation, colormap, flatcolor, lightlevel, indices, indexcount);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -529,7 +529,7 @@ public:
|
|||
// Fill a simple polygon with a texture
|
||||
void FillSimplePoly(FTexture *tex, FVector2 *points, int npoints,
|
||||
double originx, double originy, double scalex, double scaley, DAngle rotation,
|
||||
const FColormap &colormap, PalEntry flatcolor, int lightlevel, int bottomclip);
|
||||
const FColormap &colormap, PalEntry flatcolor, int lightlevel, int bottomclip, uint32_t *indices, size_t indexcount);
|
||||
|
||||
// Set an area to a specified color
|
||||
void Clear(int left, int top, int right, int bottom, int palcolor, uint32_t color);
|
||||
|
|
|
@ -1281,6 +1281,30 @@ void FWadCollection::ReadLump (int lump, void *dest)
|
|||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// W_ReadLump
|
||||
//
|
||||
// Loads the lump into a TArray and returns it.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
TArray<uint8_t> FWadCollection::ReadLumpIntoArray(int lump, int pad)
|
||||
{
|
||||
auto lumpr = OpenLumpReader(lump);
|
||||
auto size = lumpr.GetLength();
|
||||
TArray<uint8_t> data(size + pad);
|
||||
auto numread = lumpr.Read(data.Data(), size);
|
||||
|
||||
if (numread != size)
|
||||
{
|
||||
I_Error("W_ReadLump: only read %ld of %ld on lump %i\n",
|
||||
numread, size, lump);
|
||||
}
|
||||
if (pad > 0) memset(&data[size], 0, pad);
|
||||
return data;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// ReadLump - variant 2
|
||||
|
@ -1389,7 +1413,7 @@ const char *FWadCollection::GetWadName (int wadnum) const
|
|||
return NULL;
|
||||
}
|
||||
|
||||
name = Files[wadnum]->Filename;
|
||||
name = Files[wadnum]->FileName;
|
||||
slash = strrchr (name, '/');
|
||||
return slash != NULL ? slash+1 : name;
|
||||
}
|
||||
|
@ -1452,10 +1476,10 @@ const char *FWadCollection::GetWadFullName (int wadnum) const
|
|||
{
|
||||
if ((unsigned int)wadnum >= Files.Size())
|
||||
{
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return Files[wadnum]->Filename;
|
||||
return Files[wadnum]->FileName;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -148,6 +148,7 @@ public:
|
|||
|
||||
|
||||
void ReadLump (int lump, void *dest);
|
||||
TArray<uint8_t> ReadLumpIntoArray(int lump, int pad = 0); // reads lump into a writable buffer and optionally adds some padding at the end. (FMemLump isn't writable!)
|
||||
FMemLump ReadLump (int lump);
|
||||
FMemLump ReadLump (const char *name) { return ReadLump (GetNumForName (name)); }
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
in vec4 pixelpos;
|
||||
in vec3 glowdist;
|
||||
in vec3 gradientdist;
|
||||
|
||||
in vec4 vWorldNormal;
|
||||
in vec4 vEyeNormal;
|
||||
|
@ -111,7 +112,7 @@ vec4 getTexel(vec2 st)
|
|||
|
||||
}
|
||||
if (uObjectColor2.a == 0.0) texel *= uObjectColor;
|
||||
else texel *= mix(uObjectColor, uObjectColor2, glowdist.z);
|
||||
else texel *= mix(uObjectColor, uObjectColor2, gradientdist.z);
|
||||
|
||||
return desaturate(texel);
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ layout(location = 3) in vec4 aVertex2;
|
|||
layout(location = 4) in vec4 aNormal;
|
||||
out vec4 pixelpos;
|
||||
out vec3 glowdist;
|
||||
out vec3 gradientdist;
|
||||
|
||||
out vec4 vWorldNormal;
|
||||
out vec4 vEyeNormal;
|
||||
|
@ -37,16 +38,28 @@ void main()
|
|||
pixelpos.xyz = worldcoord.xyz;
|
||||
pixelpos.w = -eyeCoordPos.z/eyeCoordPos.w;
|
||||
|
||||
float topatpoint = -((uGlowTopPlane.w + uGlowTopPlane.x * worldcoord.x + uGlowTopPlane.y * worldcoord.z) * uGlowTopPlane.z);
|
||||
float bottomatpoint = -((uGlowBottomPlane.w + uGlowBottomPlane.x * worldcoord.x + uGlowBottomPlane.y * worldcoord.z) * uGlowBottomPlane.z);
|
||||
glowdist.x = topatpoint - worldcoord.y;
|
||||
glowdist.y = worldcoord.y - bottomatpoint;
|
||||
glowdist.z = clamp(glowdist.x / (topatpoint - bottomatpoint), 0.0, 1.0);
|
||||
if (uGlowTopColor.a > 0 || uGlowBottomColor.a > 0)
|
||||
{
|
||||
float topatpoint = (uGlowTopPlane.w + uGlowTopPlane.x * worldcoord.x + uGlowTopPlane.y * worldcoord.z) * uGlowTopPlane.z;
|
||||
float bottomatpoint = (uGlowBottomPlane.w + uGlowBottomPlane.x * worldcoord.x + uGlowBottomPlane.y * worldcoord.z) * uGlowBottomPlane.z;
|
||||
glowdist.x = topatpoint - worldcoord.y;
|
||||
glowdist.y = worldcoord.y - bottomatpoint;
|
||||
glowdist.z = clamp(glowdist.x / (topatpoint - bottomatpoint), 0.0, 1.0);
|
||||
}
|
||||
|
||||
if (uObjectColor2.a != 0)
|
||||
{
|
||||
float topatpoint = (uGradientTopPlane.w + uGradientTopPlane.x * worldcoord.x + uGradientTopPlane.y * worldcoord.z) * uGradientTopPlane.z;
|
||||
float bottomatpoint = (uGradientBottomPlane.w + uGradientBottomPlane.x * worldcoord.x + uGradientBottomPlane.y * worldcoord.z) * uGradientBottomPlane.z;
|
||||
gradientdist.x = topatpoint - worldcoord.y;
|
||||
gradientdist.y = worldcoord.y - bottomatpoint;
|
||||
gradientdist.z = clamp(gradientdist.x / (topatpoint - bottomatpoint), 0.0, 1.0);
|
||||
}
|
||||
|
||||
if (uSplitBottomPlane.z != 0.0)
|
||||
{
|
||||
gl_ClipDistance[3] = -((uSplitTopPlane.w + uSplitTopPlane.x * worldcoord.x + uSplitTopPlane.y * worldcoord.z) * uSplitTopPlane.z) - worldcoord.y;
|
||||
gl_ClipDistance[4] = worldcoord.y + ((uSplitBottomPlane.w + uSplitBottomPlane.x * worldcoord.x + uSplitBottomPlane.y * worldcoord.z) * uSplitBottomPlane.z);
|
||||
gl_ClipDistance[3] = ((uSplitTopPlane.w + uSplitTopPlane.x * worldcoord.x + uSplitTopPlane.y * worldcoord.z) * uSplitTopPlane.z) - worldcoord.y;
|
||||
gl_ClipDistance[4] = worldcoord.y - ((uSplitBottomPlane.w + uSplitBottomPlane.x * worldcoord.x + uSplitBottomPlane.y * worldcoord.z) * uSplitBottomPlane.z);
|
||||
}
|
||||
|
||||
vWorldNormal = NormalModelMatrix * vec4(normalize(aNormal.xyz), 1.0);
|
||||
|
|
|
@ -445,6 +445,13 @@ class Actor : Thinker native
|
|||
return true;
|
||||
}
|
||||
|
||||
// Called by revival/resurrection to check if one can resurrect the other.
|
||||
// "other" can be null when not passive.
|
||||
virtual bool CanResurrect(Actor other, bool passive)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Called when an actor is to be reflected by a disc of repulsion.
|
||||
// Returns true to continue normal blast processing.
|
||||
virtual bool SpecialBlastHandling (Actor source, double strength)
|
||||
|
@ -1085,6 +1092,7 @@ class Actor : Thinker native
|
|||
native void A_RaiseChildren(int flags = 0);
|
||||
native void A_RaiseSiblings(int flags = 0);
|
||||
native bool A_RaiseSelf(int flags = 0);
|
||||
native bool RaiseActor(Actor other, int flags = 0);
|
||||
native bool CanRaise();
|
||||
native void Revive();
|
||||
action native bool, Actor A_ThrowGrenade(class<Actor> itemtype, double zheight = 0, double xyvel = 0, double zvel = 0, bool useammo = true);
|
||||
|
|
|
@ -940,6 +940,7 @@ enum EDmgFlags
|
|||
DMG_USEANGLE = 512,
|
||||
DMG_NO_PAIN = 1024,
|
||||
DMG_EXPLOSION = 2048,
|
||||
DMG_NO_ENHANCE = 4096,
|
||||
}
|
||||
|
||||
enum EReplace
|
||||
|
|
|
@ -45,6 +45,12 @@ struct Side native play
|
|||
bottom=2
|
||||
};
|
||||
|
||||
enum EColorPos
|
||||
{
|
||||
walltop = 0,
|
||||
wallbottom = 1
|
||||
}
|
||||
|
||||
enum EWallFlags
|
||||
{
|
||||
WALLF_ABSLIGHTING = 1, // Light is absolute instead of relative
|
||||
|
@ -57,6 +63,7 @@ struct Side native play
|
|||
WALLF_LIGHT_FOG = 128, // This wall's Light is used even in fog.
|
||||
};
|
||||
|
||||
|
||||
native readonly Sector sector; // Sector the SideDef is facing.
|
||||
//DBaseDecal* AttachedDecals; // [RH] Decals bound to the wall
|
||||
native readonly Line linedef;
|
||||
|
@ -77,6 +84,7 @@ struct Side native play
|
|||
native void SetTextureYScale(int which, double scale);
|
||||
native double GetTextureYScale(int which);
|
||||
native void MultiplyTextureYScale(int which, double delta);
|
||||
native void SetSpecialColor(int tier, int position, Color scolor);
|
||||
//native DInterpolation *SetInterpolation(int position);
|
||||
//native void StopInterpolation(int position);
|
||||
|
||||
|
|
Loading…
Reference in a new issue