mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-24 04:51:19 +00:00
- added GZDoom's 3D floor physics code. This is not active yet so anything compiled from this code won't have any support for it!
SVN r1351 (trunk)
This commit is contained in:
parent
f7148b6b40
commit
78933df10d
21 changed files with 1892 additions and 122 deletions
|
@ -1,4 +1,6 @@
|
|||
January 4, 2009 (Changes by Graf Zahl)
|
||||
- added GZDoom's 3D floor physics code. This is not active yet so anything
|
||||
compiled from this code won't have any support for it!
|
||||
- Used new functionality to avoid moving the puff around in SpawnDeepSplash.
|
||||
- Fixed: P_RailAttack used the shooting actor or a default puff for some splash
|
||||
related actions. It should use the puff type passed to it as a parameter instead.
|
||||
|
|
|
@ -2188,7 +2188,7 @@ void Net_DoCommand (int type, BYTE **stream, int player)
|
|||
{
|
||||
DImpactDecal::StaticCreate (s,
|
||||
trace.X, trace.Y, trace.Z,
|
||||
sides + trace.Line->sidenum[trace.Side]);
|
||||
sides + trace.Line->sidenum[trace.Side], NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2879,6 +2879,10 @@ void G_SerializeLevel (FArchive &arc, bool hubLoad)
|
|||
|
||||
P_SerializePlayers (arc, hubLoad);
|
||||
P_SerializeSounds (arc);
|
||||
if (arc.IsLoading()) for(i=0;i<numsectors;i++)
|
||||
{
|
||||
P_Recalculate3DFloors(§ors[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Archives the current level
|
||||
|
|
|
@ -131,7 +131,8 @@ void DBaseDecal::Serialize (FArchive &arc)
|
|||
<< Translation
|
||||
<< PicNum
|
||||
<< RenderFlags
|
||||
<< RenderStyle;
|
||||
<< RenderStyle
|
||||
<< Sector;
|
||||
}
|
||||
|
||||
void DBaseDecal::SerializeChain (FArchive &arc, DBaseDecal **first)
|
||||
|
@ -207,7 +208,7 @@ void DBaseDecal::SetShade (int r, int g, int b)
|
|||
}
|
||||
|
||||
// Returns the texture the decal stuck to.
|
||||
FTextureID DBaseDecal::StickToWall (side_t *wall, fixed_t x, fixed_t y)
|
||||
FTextureID DBaseDecal::StickToWall (side_t *wall, fixed_t x, fixed_t y, F3DFloor * ffloor)
|
||||
{
|
||||
// Stick the decal at the end of the chain so it appears on top
|
||||
DBaseDecal *next, **prev;
|
||||
|
@ -262,7 +263,7 @@ FTextureID DBaseDecal::StickToWall (side_t *wall, fixed_t x, fixed_t y)
|
|||
Z -= back->GetPlaneTexZ(sector_t::floor);
|
||||
tex = wall->GetTexture(side_t::bottom);
|
||||
}
|
||||
else
|
||||
else if (back->ceilingplane.ZatPoint (x, y) <= Z)
|
||||
{
|
||||
RenderFlags |= RF_RELUPPER|RF_CLIPUPPER;
|
||||
if (line->flags & ML_DONTPEGTOP)
|
||||
|
@ -271,7 +272,31 @@ FTextureID DBaseDecal::StickToWall (side_t *wall, fixed_t x, fixed_t y)
|
|||
Z -= back->GetPlaneTexZ(sector_t::ceiling);
|
||||
tex = wall->GetTexture(side_t::top);
|
||||
}
|
||||
#ifdef _3DFLOORS
|
||||
else if (ffloor) // this is a 3d-floor segment - do this only if we know which one!
|
||||
{
|
||||
Sector=ffloor->model;
|
||||
RenderFlags |= RF_RELMID|RF_CLIPMID;
|
||||
if (line->flags & ML_DONTPEGBOTTOM)
|
||||
Z -= Sector->GetPlaneTexZ(sector_t::floor);
|
||||
else
|
||||
Z -= Sector->GetPlaneTexZ(sector_t::ceiling);
|
||||
|
||||
if (ffloor->flags & FF_UPPERTEXTURE)
|
||||
{
|
||||
tex = wall->GetTexture(side_t::top);
|
||||
}
|
||||
else if (ffloor->flags & FF_LOWERTEXTURE)
|
||||
{
|
||||
tex = wall->GetTexture(side_t::bottom);
|
||||
}
|
||||
else
|
||||
{
|
||||
tex = sides[ffloor->master->sidenum[0]].GetTexture(side_t::mid);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else return FNullTextureID();
|
||||
CalcFracPos (wall, x, y);
|
||||
|
||||
return tex;
|
||||
|
@ -406,7 +431,7 @@ static side_t *NextWall (const side_t *wall)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void DBaseDecal::SpreadLeft (fixed_t r, vertex_t *v1, side_t *feelwall)
|
||||
void DBaseDecal::SpreadLeft (fixed_t r, vertex_t *v1, side_t *feelwall, F3DFloor * ffloor)
|
||||
{
|
||||
fixed_t ldx, ldy;
|
||||
|
||||
|
@ -426,7 +451,7 @@ void DBaseDecal::SpreadLeft (fixed_t r, vertex_t *v1, side_t *feelwall)
|
|||
x += Scale (r, ldx, wallsize);
|
||||
y += Scale (r, ldy, wallsize);
|
||||
r = wallsize + startr;
|
||||
SpreadSource->CloneSelf (SpreadTemplate, x, y, SpreadZ, feelwall);
|
||||
SpreadSource->CloneSelf (SpreadTemplate, x, y, SpreadZ, feelwall, ffloor);
|
||||
SpreadStack.Push (feelwall);
|
||||
|
||||
side_t *nextwall = NextWall (feelwall);
|
||||
|
@ -444,13 +469,13 @@ void DBaseDecal::SpreadLeft (fixed_t r, vertex_t *v1, side_t *feelwall)
|
|||
vertex_t *v2;
|
||||
|
||||
GetWallStuff (nextwall, v2, ldx, ldy);
|
||||
SpreadLeft (startr, v2, nextwall);
|
||||
SpreadLeft (startr, v2, nextwall, ffloor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DBaseDecal::SpreadRight (fixed_t r, side_t *feelwall, fixed_t wallsize)
|
||||
void DBaseDecal::SpreadRight (fixed_t r, side_t *feelwall, fixed_t wallsize, F3DFloor * ffloor)
|
||||
{
|
||||
vertex_t *v1;
|
||||
fixed_t x, y, ldx, ldy;
|
||||
|
@ -473,7 +498,7 @@ void DBaseDecal::SpreadRight (fixed_t r, side_t *feelwall, fixed_t wallsize)
|
|||
}
|
||||
if (i == -1)
|
||||
{
|
||||
SpreadRight (r, nextwall, wallsize);
|
||||
SpreadRight (r, nextwall, wallsize, ffloor);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -485,12 +510,12 @@ void DBaseDecal::SpreadRight (fixed_t r, side_t *feelwall, fixed_t wallsize)
|
|||
x -= Scale (r, ldx, wallsize);
|
||||
y -= Scale (r, ldy, wallsize);
|
||||
r = DecalRight - r;
|
||||
SpreadSource->CloneSelf (SpreadTemplate, x, y, SpreadZ, feelwall);
|
||||
SpreadSource->CloneSelf (SpreadTemplate, x, y, SpreadZ, feelwall, ffloor);
|
||||
SpreadStack.Push (feelwall);
|
||||
}
|
||||
}
|
||||
|
||||
void DBaseDecal::Spread (const FDecalTemplate *tpl, side_t *wall, fixed_t x, fixed_t y, fixed_t z)
|
||||
void DBaseDecal::Spread (const FDecalTemplate *tpl, side_t *wall, fixed_t x, fixed_t y, fixed_t z, F3DFloor * ffloor)
|
||||
{
|
||||
FTexture *tex;
|
||||
vertex_t *v1;
|
||||
|
@ -510,21 +535,21 @@ void DBaseDecal::Spread (const FDecalTemplate *tpl, side_t *wall, fixed_t x, fix
|
|||
SpreadZ = z;
|
||||
|
||||
// Try spreading left first
|
||||
SpreadLeft (rorg - DecalLeft, v1, wall);
|
||||
SpreadLeft (rorg - DecalLeft, v1, wall, ffloor);
|
||||
SpreadStack.Clear ();
|
||||
|
||||
// Then try spreading right
|
||||
SpreadRight (rorg + DecalRight, wall,
|
||||
Length (lines[wall->linenum].dx, lines[wall->linenum].dy));
|
||||
Length (lines[wall->linenum].dx, lines[wall->linenum].dy), ffloor);
|
||||
SpreadStack.Clear ();
|
||||
}
|
||||
|
||||
DBaseDecal *DBaseDecal::CloneSelf (const FDecalTemplate *tpl, fixed_t ix, fixed_t iy, fixed_t iz, side_t *wall) const
|
||||
DBaseDecal *DBaseDecal::CloneSelf (const FDecalTemplate *tpl, fixed_t ix, fixed_t iy, fixed_t iz, side_t *wall, F3DFloor * ffloor) const
|
||||
{
|
||||
DBaseDecal *decal = new DBaseDecal(iz);
|
||||
if (decal != NULL)
|
||||
{
|
||||
decal->StickToWall (wall, ix, iy);
|
||||
decal->StickToWall (wall, ix, iy, ffloor);
|
||||
tpl->ApplyToDecal (decal, wall);
|
||||
decal->AlphaColor = AlphaColor;
|
||||
decal->RenderFlags = (decal->RenderFlags & RF_DECALMASK) |
|
||||
|
@ -598,7 +623,7 @@ void DImpactDecal::CheckMax ()
|
|||
}
|
||||
}
|
||||
|
||||
DImpactDecal *DImpactDecal::StaticCreate (const char *name, fixed_t x, fixed_t y, fixed_t z, side_t *wall, PalEntry color)
|
||||
DImpactDecal *DImpactDecal::StaticCreate (const char *name, fixed_t x, fixed_t y, fixed_t z, side_t *wall, F3DFloor * ffloor, PalEntry color)
|
||||
{
|
||||
if (cl_maxdecals > 0)
|
||||
{
|
||||
|
@ -606,13 +631,13 @@ DImpactDecal *DImpactDecal::StaticCreate (const char *name, fixed_t x, fixed_t y
|
|||
|
||||
if (tpl != NULL && (tpl = tpl->GetDecal()) != NULL)
|
||||
{
|
||||
return StaticCreate (tpl, x, y, z, wall, color);
|
||||
return StaticCreate (tpl, x, y, z, wall, ffloor, color);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DImpactDecal *DImpactDecal::StaticCreate (const FDecalTemplate *tpl, fixed_t x, fixed_t y, fixed_t z, side_t *wall, PalEntry color)
|
||||
DImpactDecal *DImpactDecal::StaticCreate (const FDecalTemplate *tpl, fixed_t x, fixed_t y, fixed_t z, side_t *wall, F3DFloor * ffloor, PalEntry color)
|
||||
{
|
||||
DImpactDecal *decal = NULL;
|
||||
if (tpl != NULL && cl_maxdecals > 0 && !(wall->Flags & WALLF_NOAUTODECALS))
|
||||
|
@ -625,12 +650,12 @@ DImpactDecal *DImpactDecal::StaticCreate (const FDecalTemplate *tpl, fixed_t x,
|
|||
// If the default color of the lower decal is the same as the main decal's
|
||||
// apply the custom color as well.
|
||||
if (tpl->ShadeColor == tpl_low->ShadeColor) lowercolor=0;
|
||||
StaticCreate (tpl_low, x, y, z, wall, lowercolor);
|
||||
StaticCreate (tpl_low, x, y, z, wall, ffloor, lowercolor);
|
||||
}
|
||||
DImpactDecal::CheckMax();
|
||||
decal = new DImpactDecal (z);
|
||||
|
||||
FTextureID stickypic = decal->StickToWall (wall, x, y);
|
||||
FTextureID stickypic = decal->StickToWall (wall, x, y, ffloor);
|
||||
FTexture *tex = TexMan[stickypic];
|
||||
|
||||
if (tex != NULL && tex->bNoDecals)
|
||||
|
@ -655,18 +680,18 @@ DImpactDecal *DImpactDecal::StaticCreate (const FDecalTemplate *tpl, fixed_t x,
|
|||
}
|
||||
|
||||
// Spread decal to nearby walls if it does not all fit on this one
|
||||
decal->Spread (tpl, wall, x, y, z);
|
||||
decal->Spread (tpl, wall, x, y, z, ffloor);
|
||||
}
|
||||
return decal;
|
||||
}
|
||||
|
||||
DBaseDecal *DImpactDecal::CloneSelf (const FDecalTemplate *tpl, fixed_t ix, fixed_t iy, fixed_t iz, side_t *wall) const
|
||||
DBaseDecal *DImpactDecal::CloneSelf (const FDecalTemplate *tpl, fixed_t ix, fixed_t iy, fixed_t iz, side_t *wall, F3DFloor * ffloor) const
|
||||
{
|
||||
DImpactDecal::CheckMax();
|
||||
DImpactDecal *decal = new DImpactDecal(iz);
|
||||
if (decal != NULL)
|
||||
{
|
||||
decal->StickToWall (wall, ix, iy);
|
||||
decal->StickToWall (wall, ix, iy, ffloor);
|
||||
tpl->ApplyToDecal (decal, wall);
|
||||
decal->AlphaColor = AlphaColor;
|
||||
decal->RenderFlags = (decal->RenderFlags & RF_DECALMASK) |
|
||||
|
@ -751,12 +776,12 @@ void ADecal::BeginPlay ()
|
|||
{
|
||||
decal = new DBaseDecal (this);
|
||||
wall = sides + trace.Line->sidenum[trace.Side];
|
||||
decal->StickToWall (wall, trace.X, trace.Y);
|
||||
decal->StickToWall (wall, trace.X, trace.Y, trace.ffloor);
|
||||
tpl->ApplyToDecal (decal, wall);
|
||||
// Spread decal to nearby walls if it does not all fit on this one
|
||||
if (cl_spreaddecals)
|
||||
{
|
||||
decal->Spread (tpl, wall, trace.X, trace.Y, z);
|
||||
decal->Spread (tpl, wall, trace.X, trace.Y, z, trace.ffloor);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
class FDecalTemplate;
|
||||
struct vertex_t;
|
||||
struct side_t;
|
||||
struct F3DFloor;
|
||||
|
||||
extern void P_SpawnDirt (AActor *actor, fixed_t radius);
|
||||
|
||||
|
@ -23,11 +24,11 @@ public:
|
|||
|
||||
void Serialize (FArchive &arc);
|
||||
void Destroy ();
|
||||
FTextureID StickToWall (side_t *wall, fixed_t x, fixed_t y);
|
||||
FTextureID StickToWall (side_t *wall, fixed_t x, fixed_t y, F3DFloor * ffloor);
|
||||
fixed_t GetRealZ (const side_t *wall) const;
|
||||
void SetShade (DWORD rgb);
|
||||
void SetShade (int r, int g, int b);
|
||||
void Spread (const FDecalTemplate *tpl, side_t *wall, fixed_t x, fixed_t y, fixed_t z);
|
||||
void Spread (const FDecalTemplate *tpl, side_t *wall, fixed_t x, fixed_t y, fixed_t z, F3DFloor * ffloor);
|
||||
void GetXY (side_t *side, fixed_t &x, fixed_t &y) const;
|
||||
|
||||
static void SerializeChain (FArchive &arc, DBaseDecal **firstptr);
|
||||
|
@ -43,14 +44,15 @@ public:
|
|||
FTextureID PicNum;
|
||||
DWORD RenderFlags;
|
||||
FRenderStyle RenderStyle;
|
||||
sector_t * Sector; // required for 3D floors
|
||||
|
||||
protected:
|
||||
virtual DBaseDecal *CloneSelf (const FDecalTemplate *tpl, fixed_t x, fixed_t y, fixed_t z, side_t *wall) const;
|
||||
virtual DBaseDecal *CloneSelf (const FDecalTemplate *tpl, fixed_t x, fixed_t y, fixed_t z, side_t *wall, F3DFloor * ffloor) const;
|
||||
void CalcFracPos (side_t *wall, fixed_t x, fixed_t y);
|
||||
void Remove ();
|
||||
|
||||
static void SpreadLeft (fixed_t r, vertex_t *v1, side_t *feelwall);
|
||||
static void SpreadRight (fixed_t r, side_t *feelwall, fixed_t wallsize);
|
||||
static void SpreadLeft (fixed_t r, vertex_t *v1, side_t *feelwall, F3DFloor * ffloor);
|
||||
static void SpreadRight (fixed_t r, side_t *feelwall, fixed_t wallsize, F3DFloor * ffloor);
|
||||
};
|
||||
|
||||
class DImpactDecal : public DBaseDecal
|
||||
|
@ -60,8 +62,8 @@ public:
|
|||
DImpactDecal (fixed_t z);
|
||||
DImpactDecal (side_t *wall, const FDecalTemplate *templ);
|
||||
|
||||
static DImpactDecal *StaticCreate (const char *name, fixed_t x, fixed_t y, fixed_t z, side_t *wall, PalEntry color=0);
|
||||
static DImpactDecal *StaticCreate (const FDecalTemplate *tpl, fixed_t x, fixed_t y, fixed_t z, side_t *wall, PalEntry color=0);
|
||||
static DImpactDecal *StaticCreate (const char *name, fixed_t x, fixed_t y, fixed_t z, side_t *wall, F3DFloor * ffloor, PalEntry color=0);
|
||||
static DImpactDecal *StaticCreate (const FDecalTemplate *tpl, fixed_t x, fixed_t y, fixed_t z, side_t *wall, F3DFloor * ffloor, PalEntry color=0);
|
||||
|
||||
void BeginPlay ();
|
||||
void Destroy ();
|
||||
|
@ -70,7 +72,7 @@ public:
|
|||
static void SerializeTime (FArchive &arc);
|
||||
|
||||
protected:
|
||||
DBaseDecal *CloneSelf (const FDecalTemplate *tpl, fixed_t x, fixed_t y, fixed_t z, side_t *wall) const;
|
||||
DBaseDecal *CloneSelf (const FDecalTemplate *tpl, fixed_t x, fixed_t y, fixed_t z, side_t *wall, F3DFloor * ffloor) const;
|
||||
static void CheckMax ();
|
||||
|
||||
private:
|
||||
|
|
678
src/p_3dfloors.cpp
Normal file
678
src/p_3dfloors.cpp
Normal file
|
@ -0,0 +1,678 @@
|
|||
/*
|
||||
** p_3dfloor.cpp
|
||||
**
|
||||
** 3D-floor handling
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2005-2008 Christoph Oelckers
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
** 4. Full disclosure of the entire project's source code, except for third
|
||||
** party libraries is mandatory. (NOTE: This clause is non-negotiable!)
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
#ifdef _3DFLOORS
|
||||
|
||||
#include "templates.h"
|
||||
#include "p_local.h"
|
||||
#include "p_lnspec.h"
|
||||
#include "w_wad.h"
|
||||
#include "sc_man.h"
|
||||
#include "v_palette.h"
|
||||
#include "g_level.h"
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// 3D Floors
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Add one 3D floor to the sector
|
||||
//
|
||||
//==========================================================================
|
||||
static void P_Add3DFloor(sector_t* sec, sector_t* sec2, line_t* master, int flags,int transluc)
|
||||
{
|
||||
F3DFloor* ffloor;
|
||||
unsigned i;
|
||||
|
||||
for(i = 0; i < sec2->e->XFloor.attached.Size(); i++) if(sec2->e->XFloor.attached[i] == sec) return;
|
||||
sec2->e->XFloor.attached.Push(sec);
|
||||
|
||||
//Add the floor
|
||||
ffloor = new F3DFloor;
|
||||
ffloor->top.model = ffloor->bottom.model = ffloor->model = sec2;
|
||||
ffloor->target = sec;
|
||||
|
||||
if (!(flags&FF_THINFLOOR))
|
||||
{
|
||||
ffloor->bottom.plane = &sec2->floorplane;
|
||||
ffloor->bottom.texture = &sec2->planes[sector_t::floor].Texture;
|
||||
ffloor->bottom.texheight = &sec2->planes[sector_t::floor].TexZ;
|
||||
ffloor->bottom.isceiling = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ffloor->bottom.plane = &sec2->ceilingplane;
|
||||
ffloor->bottom.texture = &sec2->planes[sector_t::ceiling].Texture;
|
||||
ffloor->bottom.texheight = &sec2->planes[sector_t::ceiling].TexZ;
|
||||
ffloor->bottom.isceiling = true;
|
||||
}
|
||||
|
||||
if (!(flags&FF_FIX))
|
||||
{
|
||||
ffloor->top.plane = &sec2->ceilingplane;
|
||||
ffloor->top.texture = &sec2->planes[sector_t::ceiling].Texture;
|
||||
ffloor->top.texheight = &sec2->planes[sector_t::ceiling].TexZ;
|
||||
ffloor->toplightlevel = &sec2->lightlevel;
|
||||
ffloor->top.isceiling = true;
|
||||
}
|
||||
else // FF_FIX is a special case to patch rendering holes
|
||||
{
|
||||
ffloor->top.plane = &sec->floorplane;
|
||||
ffloor->top.texture = &sec2->planes[sector_t::floor].Texture;
|
||||
ffloor->top.texheight = &sec2->planes[sector_t::floor].TexZ;
|
||||
ffloor->toplightlevel = &sec->lightlevel;
|
||||
ffloor->top.isceiling = false;
|
||||
ffloor->top.model = sec;
|
||||
}
|
||||
|
||||
// Hacks for Vavoom's idiotic implementation
|
||||
if (flags&FF_INVERTSECTOR)
|
||||
{
|
||||
// switch the planes
|
||||
F3DFloor::planeref sp = ffloor->top;
|
||||
|
||||
ffloor->top=ffloor->bottom;
|
||||
ffloor->bottom=sp;
|
||||
|
||||
if (flags&FF_SWIMMABLE)
|
||||
{
|
||||
// Vavoom floods the lower part if it is swimmable.
|
||||
// fortunately this plane won't be rendered - otherwise this wouldn't work...
|
||||
ffloor->bottom.plane=&sec->floorplane;
|
||||
ffloor->bottom.model=sec;
|
||||
}
|
||||
}
|
||||
|
||||
ffloor->flags = flags;
|
||||
ffloor->master = master;
|
||||
ffloor->alpha = transluc;
|
||||
|
||||
// The engine cannot handle sloped translucent floors. Sorry
|
||||
if (ffloor->top.plane->a || ffloor->top.plane->b || ffloor->bottom.plane->a || ffloor->bottom.plane->b)
|
||||
{
|
||||
ffloor->alpha = FRACUNIT;
|
||||
}
|
||||
|
||||
sec->e->XFloor.ffloors.Push(ffloor);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Creates all 3D floors defined by one linedef
|
||||
//
|
||||
//==========================================================================
|
||||
static int P_Set3DFloor(line_t * line, int param,int param2, int alpha)
|
||||
{
|
||||
int s,i;
|
||||
int flags;
|
||||
int tag=line->args[0];
|
||||
sector_t * sec = line->frontsector, * ss;
|
||||
|
||||
for (s=-1; (s = P_FindSectorFromTag(tag,s)) >= 0;)
|
||||
{
|
||||
ss=§ors[s];
|
||||
|
||||
if (param==0)
|
||||
{
|
||||
flags=FF_EXISTS|FF_RENDERALL|FF_SOLID|FF_INVERTSECTOR;
|
||||
for (i=0;i<sec->linecount;i++)
|
||||
{
|
||||
line_t * l=sec->lines[i];
|
||||
|
||||
alpha=255;
|
||||
if (l->special==Sector_SetContents && l->frontsector==sec)
|
||||
{
|
||||
alpha=clamp<int>(l->args[1], 0, 100);
|
||||
if (l->args[2] & 1) flags &= ~FF_SOLID;
|
||||
if (l->args[2] & 2) flags |= FF_SEETHROUGH;
|
||||
if (l->args[2] & 4) flags |= FF_SHOOTTHROUGH;
|
||||
if (l->args[2] & 8) flags |= FF_ADDITIVETRANS;
|
||||
if (alpha!=100) flags|=FF_TRANSLUCENT;//|FF_BOTHPLANES|FF_ALLSIDES;
|
||||
if (l->args[0])
|
||||
{
|
||||
// Yes, Vavoom's 3D-floor definitions suck!
|
||||
static DWORD vavoomcolors[]={
|
||||
0, 0x101080, 0x801010, 0x108010, 0x287020, 0xf0f010};
|
||||
flags|=FF_SWIMMABLE|FF_BOTHPLANES|FF_ALLSIDES|FF_FLOOD;
|
||||
|
||||
l->frontsector->ColorMap = GetSpecialLights (l->frontsector->ColorMap->Color,
|
||||
vavoomcolors[l->args[0]],
|
||||
l->frontsector->ColorMap->Desaturate);
|
||||
}
|
||||
alpha=(alpha*255)/100;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (param==4)
|
||||
{
|
||||
flags=FF_EXISTS|FF_RENDERPLANES|FF_INVERTPLANES|FF_NOSHADE|FF_FIX;
|
||||
alpha=255;
|
||||
}
|
||||
else
|
||||
{
|
||||
static const int defflags[]= {0,
|
||||
FF_SOLID,
|
||||
FF_SWIMMABLE|FF_BOTHPLANES|FF_ALLSIDES|FF_SHOOTTHROUGH|FF_SEETHROUGH,
|
||||
FF_SHOOTTHROUGH|FF_SEETHROUGH,
|
||||
};
|
||||
|
||||
flags = defflags[param&3] | FF_EXISTS|FF_RENDERALL;
|
||||
|
||||
if (param&4) flags |= FF_ALLSIDES|FF_BOTHPLANES;
|
||||
if (param&16) flags ^= FF_SEETHROUGH;
|
||||
if (param&32) flags ^= FF_SHOOTTHROUGH;
|
||||
|
||||
if (param2&1) flags |= FF_NOSHADE;
|
||||
if (param2&2) flags |= FF_DOUBLESHADOW;
|
||||
if (param2&4) flags |= FF_FOG;
|
||||
if (param2&8) flags |= FF_THINFLOOR;
|
||||
if (param2&16) flags |= FF_UPPERTEXTURE;
|
||||
if (param2&32) flags |= FF_LOWERTEXTURE;
|
||||
if (param2&64) flags |= FF_ADDITIVETRANS|FF_TRANSLUCENT;
|
||||
// if flooding is used the floor must be non-solid and is automatically made shootthrough and seethrough
|
||||
if ((param2&128) && !(flags & FF_SOLID)) flags |= FF_FLOOD|FF_SEETHROUGH|FF_SHOOTTHROUGH;
|
||||
if (param2&512) flags |= FF_FADEWALLS;
|
||||
FTextureID tex = sides[line->sidenum[0]].GetTexture(side_t::top);
|
||||
if (!tex.Exists() && alpha<255)
|
||||
{
|
||||
alpha=clamp(-tex.GetIndex(), 0, 255);
|
||||
}
|
||||
if (alpha==0) flags&=~(FF_RENDERALL|FF_BOTHPLANES|FF_ALLSIDES);
|
||||
else if (alpha!=255) flags|=FF_TRANSLUCENT;
|
||||
|
||||
}
|
||||
P_Add3DFloor(ss, sec, line, flags, alpha);
|
||||
}
|
||||
// To be 100% safe this should be done even if the alpha by texture value isn't used.
|
||||
if (!sides[line->sidenum[0]].GetTexture(side_t::top).isValid())
|
||||
sides[line->sidenum[0]].SetTexture(side_t::top, FNullTextureID());
|
||||
return 1;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// P_PlayerOnSpecial3DFloor
|
||||
// Checks to see if a player is standing on or is inside a 3D floor (water)
|
||||
// and applies any specials..
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void P_PlayerOnSpecial3DFloor(player_t* player)
|
||||
{
|
||||
sector_t * sector = player->mo->Sector;
|
||||
|
||||
for(unsigned i=0;i<sector->e->XFloor.ffloors.Size();i++)
|
||||
{
|
||||
F3DFloor* rover=sector->e->XFloor.ffloors[i];
|
||||
|
||||
if (!(rover->flags & FF_EXISTS)) continue;
|
||||
if (rover->flags & FF_FIX) continue;
|
||||
|
||||
// Check the 3D floor's type...
|
||||
if(rover->flags & FF_SOLID)
|
||||
{
|
||||
// Player must be on top of the floor to be affected...
|
||||
if(player->mo->z != rover->top.plane->ZatPoint(player->mo->x, player->mo->y)) continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Water and DEATH FOG!!! heh
|
||||
if (player->mo->z > rover->top.plane->ZatPoint(player->mo->x, player->mo->y) ||
|
||||
(player->mo->z + player->mo->height) < rover->bottom.plane->ZatPoint(player->mo->x, player->mo->y))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (rover->model->special || rover->model->damage) P_PlayerInSpecialSector(player, rover->model);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// P_CheckFor3DFloorHit
|
||||
// Checks whether the player's feet touch a solid 3D floor in the sector
|
||||
//
|
||||
//==========================================================================
|
||||
bool P_CheckFor3DFloorHit(AActor * mo)
|
||||
{
|
||||
sector_t * sector = mo->Sector;
|
||||
|
||||
if ((mo->player && (mo->player->cheats & CF_PREDICTING))) return false;
|
||||
|
||||
for(unsigned i=0;i<sector->e->XFloor.ffloors.Size();i++)
|
||||
{
|
||||
F3DFloor* rover=sector->e->XFloor.ffloors[i];
|
||||
|
||||
if (!(rover->flags & FF_EXISTS)) continue;
|
||||
|
||||
if(rover->flags & FF_SOLID && rover->model->SecActTarget)
|
||||
{
|
||||
if(mo->z == rover->top.plane->ZatPoint(mo->x, mo->y))
|
||||
{
|
||||
rover->model->SecActTarget->TriggerAction (mo, SECSPAC_HitFloor);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// P_CheckFor3DCeilingHit
|
||||
// Checks whether the player's head touches a solid 3D floor in the sector
|
||||
//
|
||||
//==========================================================================
|
||||
bool P_CheckFor3DCeilingHit(AActor * mo)
|
||||
{
|
||||
sector_t * sector = mo->Sector;
|
||||
|
||||
if ((mo->player && (mo->player->cheats & CF_PREDICTING))) return false;
|
||||
|
||||
for(unsigned i=0;i<sector->e->XFloor.ffloors.Size();i++)
|
||||
{
|
||||
F3DFloor* rover=sector->e->XFloor.ffloors[i];
|
||||
|
||||
if (!(rover->flags & FF_EXISTS)) continue;
|
||||
|
||||
if(rover->flags & FF_SOLID && rover->model->SecActTarget)
|
||||
{
|
||||
if(mo->z+mo->height == rover->bottom.plane->ZatPoint(mo->x, mo->y))
|
||||
{
|
||||
rover->model->SecActTarget->TriggerAction (mo, SECSPAC_HitCeiling);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// P_Recalculate3DFloors
|
||||
//
|
||||
// This function sorts the ffloors by height and creates the lightlists
|
||||
// that the given sector uses to light floors/ceilings/walls according to the 3D floors.
|
||||
//
|
||||
//==========================================================================
|
||||
#define CenterSpot(sec) (vertex_t*)&(sec)->soundorg[0]
|
||||
|
||||
void P_Recalculate3DFloors(sector_t * sector)
|
||||
{
|
||||
F3DFloor * rover;
|
||||
F3DFloor * pick;
|
||||
unsigned pickindex;
|
||||
F3DFloor * clipped=NULL;
|
||||
fixed_t clipped_top;
|
||||
fixed_t clipped_bottom=0;
|
||||
fixed_t maxheight, minheight;
|
||||
unsigned i, j;
|
||||
lightlist_t newlight;
|
||||
|
||||
TArray<F3DFloor*> & ffloors=sector->e->XFloor.ffloors;
|
||||
TArray<lightlist_t> & lightlist = sector->e->XFloor.lightlist;
|
||||
|
||||
// Sort the floors top to bottom for quicker access here and later
|
||||
// Translucent and swimmable floors are split if they overlap with solid ones.
|
||||
if (ffloors.Size()>1)
|
||||
{
|
||||
TArray<F3DFloor*> oldlist;
|
||||
|
||||
oldlist = ffloors;
|
||||
ffloors.Clear();
|
||||
|
||||
// first delete the old dynamic stuff
|
||||
for(i=0;i<oldlist.Size();i++)
|
||||
{
|
||||
F3DFloor * rover=oldlist[i];
|
||||
|
||||
if (rover->flags&FF_DYNAMIC)
|
||||
{
|
||||
delete rover;
|
||||
oldlist.Delete(i);
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
if (rover->flags&FF_CLIPPED)
|
||||
{
|
||||
rover->flags&=~FF_CLIPPED;
|
||||
rover->flags|=FF_EXISTS;
|
||||
}
|
||||
}
|
||||
|
||||
while (oldlist.Size())
|
||||
{
|
||||
pick=oldlist[0];
|
||||
fixed_t height=pick->top.plane->ZatPoint(CenterSpot(sector));
|
||||
|
||||
// find highest starting ffloor - intersections are not supported!
|
||||
pickindex=0;
|
||||
for (j=1;j<oldlist.Size();j++)
|
||||
{
|
||||
fixed_t h2=oldlist[j]->top.plane->ZatPoint(CenterSpot(sector));
|
||||
|
||||
if (h2>height)
|
||||
{
|
||||
pick=oldlist[j];
|
||||
pickindex=j;
|
||||
height=h2;
|
||||
}
|
||||
}
|
||||
|
||||
oldlist.Delete(pickindex);
|
||||
|
||||
if (pick->flags&(FF_SWIMMABLE|FF_TRANSLUCENT) && pick->flags&FF_EXISTS)
|
||||
{
|
||||
clipped=pick;
|
||||
clipped_top=height;
|
||||
clipped_bottom=pick->bottom.plane->ZatPoint(CenterSpot(sector));
|
||||
ffloors.Push(pick);
|
||||
}
|
||||
else if (clipped && clipped_bottom<height)
|
||||
{
|
||||
// translucent floor above must be clipped to this one!
|
||||
F3DFloor * dyn=new F3DFloor;
|
||||
*dyn=*clipped;
|
||||
clipped->flags|=FF_CLIPPED;
|
||||
clipped->flags&=~FF_EXISTS;
|
||||
dyn->flags|=FF_DYNAMIC;
|
||||
dyn->bottom=pick->top;
|
||||
ffloors.Push(dyn);
|
||||
ffloors.Push(pick);
|
||||
|
||||
fixed_t pick_bottom=pick->bottom.plane->ZatPoint(CenterSpot(sector));
|
||||
|
||||
if (pick_bottom<=clipped_bottom)
|
||||
{
|
||||
clipped=NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
// the translucent part extends below the clipper
|
||||
dyn=new F3DFloor;
|
||||
*dyn=*clipped;
|
||||
dyn->flags|=FF_DYNAMIC|FF_EXISTS;
|
||||
dyn->top=pick->bottom;
|
||||
ffloors.Push(dyn);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
clipped=NULL;
|
||||
ffloors.Push(pick);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// having the floors sorted makes this routine significantly simpler
|
||||
// Only some overlapping cases with FF_DOUBLESHADOW might create anomalies
|
||||
// but these are clearly undefined.
|
||||
if(ffloors.Size())
|
||||
{
|
||||
lightlist.Resize(1);
|
||||
lightlist[0].plane = sector->ceilingplane;
|
||||
lightlist[0].p_lightlevel = §or->lightlevel;
|
||||
lightlist[0].caster = NULL;
|
||||
lightlist[0].p_extra_colormap = §or->ColorMap;
|
||||
lightlist[0].flags = 0;
|
||||
|
||||
maxheight = sector->CenterCeiling();
|
||||
minheight = sector->CenterFloor();
|
||||
for(i = 0; i < ffloors.Size(); i++)
|
||||
{
|
||||
rover=ffloors[i];
|
||||
|
||||
if ( !(rover->flags & FF_EXISTS) || rover->flags & FF_NOSHADE )
|
||||
continue;
|
||||
|
||||
fixed_t ff_top=rover->top.plane->ZatPoint(CenterSpot(sector));
|
||||
if (ff_top < minheight) break; // reached the floor
|
||||
if (ff_top < maxheight)
|
||||
{
|
||||
newlight.plane = *rover->top.plane;
|
||||
newlight.p_lightlevel = rover->toplightlevel;
|
||||
newlight.caster = rover;
|
||||
newlight.p_extra_colormap=&rover->model->ColorMap;
|
||||
newlight.flags = rover->flags;
|
||||
lightlist.Push(newlight);
|
||||
}
|
||||
else if (i==0)
|
||||
{
|
||||
fixed_t ff_bottom=rover->bottom.plane->ZatPoint(CenterSpot(sector));
|
||||
if (ff_bottom<maxheight)
|
||||
{
|
||||
// this segment begins over the ceiling and extends beyond it
|
||||
lightlist[0].p_lightlevel = rover->toplightlevel;
|
||||
lightlist[0].caster = rover;
|
||||
lightlist[0].p_extra_colormap=&rover->model->ColorMap;
|
||||
lightlist[0].flags = rover->flags;
|
||||
}
|
||||
}
|
||||
if (rover->flags&FF_DOUBLESHADOW)
|
||||
{
|
||||
fixed_t ff_bottom=rover->bottom.plane->ZatPoint(CenterSpot(sector));
|
||||
if(ff_bottom < maxheight && ff_bottom>minheight)
|
||||
{
|
||||
newlight.caster = rover;
|
||||
newlight.plane = *rover->bottom.plane;
|
||||
if (lightlist.Size()>1)
|
||||
{
|
||||
newlight.p_lightlevel = lightlist[lightlist.Size()-2].p_lightlevel;
|
||||
newlight.p_extra_colormap = lightlist[lightlist.Size()-2].p_extra_colormap;
|
||||
}
|
||||
else
|
||||
{
|
||||
newlight.p_lightlevel = §or->lightlevel;
|
||||
newlight.p_extra_colormap = §or->ColorMap;
|
||||
}
|
||||
newlight.flags = rover->flags;
|
||||
lightlist.Push(newlight);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void P_RecalculateAttached3DFloors(sector_t * sec)
|
||||
{
|
||||
extsector_t::xfloor &x = sec->e->XFloor;
|
||||
|
||||
for(unsigned int i=0; i<x.attached.Size(); i++)
|
||||
{
|
||||
P_Recalculate3DFloors(x.attached[i]);
|
||||
}
|
||||
P_Recalculate3DFloors(sec);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
lightlist_t * P_GetPlaneLight(sector_t * sector, secplane_t * plane, bool underside)
|
||||
{
|
||||
unsigned i;
|
||||
TArray<lightlist_t> &lightlist = sector->e->XFloor.lightlist;
|
||||
|
||||
fixed_t planeheight=plane->ZatPoint(CenterSpot(sector));
|
||||
if(underside) planeheight--;
|
||||
|
||||
for(i = 1; i < lightlist.Size(); i++)
|
||||
if (lightlist[i].plane.ZatPoint(CenterSpot(sector)) <= planeheight)
|
||||
return &lightlist[i - 1];
|
||||
|
||||
return &lightlist[lightlist.Size() - 1];
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Extended P_LineOpening
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void P_LineOpening_XFloors (FLineOpening &open, AActor * thing, const line_t *linedef,
|
||||
fixed_t x, fixed_t y, fixed_t refx, fixed_t refy)
|
||||
{
|
||||
if(thing)
|
||||
{
|
||||
fixed_t thingbot, thingtop;
|
||||
|
||||
thingbot = thing->z;
|
||||
thingtop = thingbot + thing->height;
|
||||
|
||||
extsector_t::xfloor *xf[2] = {&linedef->frontsector->e->XFloor, &linedef->backsector->e->XFloor};
|
||||
|
||||
// Check for 3D-floors in the sector (mostly identical to what Legacy does here)
|
||||
if(xf[0]->ffloors.Size() || xf[1]->ffloors.Size())
|
||||
{
|
||||
fixed_t lowestceiling = open.top;
|
||||
fixed_t highestfloor = open.bottom;
|
||||
fixed_t lowestfloor[2] = {
|
||||
linedef->frontsector->floorplane.ZatPoint(x, y),
|
||||
linedef->backsector->floorplane.ZatPoint(x, y) };
|
||||
FTextureID highestfloorpic;
|
||||
FTextureID lowestceilingpic;
|
||||
|
||||
highestfloorpic.SetInvalid();
|
||||
lowestceilingpic.SetInvalid();
|
||||
thingtop = thing->z + (thing->height==0? 1:thing->height);
|
||||
|
||||
for(int j=0;j<2;j++)
|
||||
{
|
||||
// Check for frontsector's 3D-floors
|
||||
for(unsigned i=0;i<xf[j]->ffloors.Size();i++)
|
||||
{
|
||||
F3DFloor *rover = xf[j]->ffloors[i];
|
||||
|
||||
if (!(rover->flags&FF_EXISTS)) continue;
|
||||
if (!(rover->flags & FF_SOLID)) continue;
|
||||
|
||||
fixed_t ff_bottom=rover->bottom.plane->ZatPoint(x, y);
|
||||
fixed_t ff_top=rover->top.plane->ZatPoint(x, y);
|
||||
|
||||
fixed_t delta1 = abs(thingbot - ((ff_bottom + ff_top) / 2));
|
||||
fixed_t delta2 = abs(thingtop - ((ff_bottom + ff_top) / 2));
|
||||
|
||||
if(ff_bottom < lowestceiling && delta1 >= delta2)
|
||||
{
|
||||
lowestceiling = ff_bottom;
|
||||
lowestceilingpic = *rover->bottom.texture;
|
||||
}
|
||||
|
||||
if(ff_top > highestfloor && delta1 < delta2)
|
||||
{
|
||||
highestfloor = ff_top;
|
||||
highestfloorpic = *rover->top.texture;
|
||||
}
|
||||
if(ff_top > lowestfloor[j] && ff_top <= thing->z) lowestfloor[j] = ff_top;
|
||||
}
|
||||
}
|
||||
|
||||
if(highestfloor > open.bottom)
|
||||
{
|
||||
open.bottom = highestfloor;
|
||||
open.floorpic = highestfloorpic;
|
||||
}
|
||||
|
||||
if(lowestceiling < open.top)
|
||||
{
|
||||
open.top = lowestceiling;
|
||||
open.ceilingpic = lowestceilingpic;
|
||||
}
|
||||
|
||||
open.lowfloor = MIN(lowestfloor[0], lowestfloor[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Spawns 3D floors
|
||||
//
|
||||
//==========================================================================
|
||||
void P_Spawn3DFloors (void)
|
||||
{
|
||||
static int flagvals[] = {128+512, 2+512, 512};
|
||||
int i;
|
||||
line_t * line;
|
||||
|
||||
for (i=0,line=lines;i<numlines;i++,line++)
|
||||
{
|
||||
switch(line->special)
|
||||
{
|
||||
case ExtraFloor_LightOnly:
|
||||
// Note: I am spawning both this and ZDoom's ExtraLight data
|
||||
// I don't want to mess with both at the same time during rendering
|
||||
// so inserting this into the 3D-floor table as well seemed to be
|
||||
// the best option.
|
||||
//
|
||||
// This does not yet handle case 0 properly!
|
||||
if (line->args[1] < 0 || line->args[1] > 2) line->args[1] = 0;
|
||||
P_Set3DFloor(line, 3, flagvals[line->args[1]], 0);
|
||||
break;
|
||||
|
||||
case Sector_Set3DFloor:
|
||||
if (line->args[1]&8)
|
||||
{
|
||||
line->id = line->args[4];
|
||||
}
|
||||
else
|
||||
{
|
||||
line->args[0]+=256*line->args[4];
|
||||
line->args[4]=0;
|
||||
}
|
||||
P_Set3DFloor(line, line->args[1]&~8, line->args[2], line->args[3]);
|
||||
break;
|
||||
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
line->special=0;
|
||||
line->args[0] = line->args[1] = line->args[2] = line->args[3] = line->args[4] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
138
src/p_3dfloors.h
Normal file
138
src/p_3dfloors.h
Normal file
|
@ -0,0 +1,138 @@
|
|||
#ifndef __SECTORE_H
|
||||
#define __SECTORE_H
|
||||
|
||||
|
||||
//#define _3DFLOORS
|
||||
|
||||
#ifdef _3DFLOORS
|
||||
|
||||
// 3D floor flags. Most are the same as in Legacy but I added some for EDGE's and Vavoom's features as well.
|
||||
typedef enum
|
||||
{
|
||||
FF_EXISTS = 0x1, //MAKE SURE IT'S VALID
|
||||
FF_SOLID = 0x2, //Does it clip things?
|
||||
FF_RENDERSIDES = 0x4, //Render the sides?
|
||||
FF_RENDERPLANES = 0x8, //Render the floor/ceiling?
|
||||
FF_RENDERALL = 0xC, //Render everything?
|
||||
FF_SWIMMABLE = 0x10, //Can we swim?
|
||||
FF_NOSHADE = 0x20, //Does it mess with the lighting?
|
||||
FF_BOTHPLANES = 0x200, //Render both planes all the time?
|
||||
FF_TRANSLUCENT = 0x800, //See through!
|
||||
FF_FOG = 0x1000, //Fog "brush"?
|
||||
FF_INVERTPLANES = 0x2000, //Reverse the plane visibility rules?
|
||||
FF_ALLSIDES = 0x4000, //Render inside and outside sides?
|
||||
FF_INVERTSIDES = 0x8000, //Only render inside sides?
|
||||
FF_DOUBLESHADOW = 0x10000,//Make two lightlist entries to reset light?
|
||||
FF_UPPERTEXTURE = 0x20000,
|
||||
FF_LOWERTEXTURE = 0x40000,
|
||||
FF_THINFLOOR = 0x80000, // EDGE
|
||||
FF_SCROLLY = 0x100000, // EDGE - not yet implemented!!!
|
||||
FF_FIX = 0x200000, // use floor of model sector as floor and floor of real sector as ceiling
|
||||
FF_INVERTSECTOR = 0x400000, // swap meaning of sector planes
|
||||
FF_DYNAMIC = 0x800000, // created by partitioning another 3D-floor due to overlap
|
||||
FF_CLIPPED = 0x1000000, // split into several dynamic ffloors
|
||||
FF_SEETHROUGH = 0x2000000,
|
||||
FF_SHOOTTHROUGH = 0x4000000,
|
||||
FF_FADEWALLS = 0x8000000, // Applies real fog to walls and doesn't blend the view
|
||||
FF_ADDITIVETRANS = 0x10000000, // Render this floor with additive translucency
|
||||
FF_FLOOD = 0x20000000, // extends towards the next lowest flooding or solid 3D floor or the bottom of the sector
|
||||
|
||||
} ffloortype_e;
|
||||
|
||||
|
||||
struct secplane_t;
|
||||
|
||||
struct F3DFloor
|
||||
{
|
||||
struct planeref
|
||||
{
|
||||
secplane_t * plane;
|
||||
const FTextureID * texture;
|
||||
const fixed_t * texheight;
|
||||
sector_t * model;
|
||||
bool isceiling;
|
||||
};
|
||||
|
||||
planeref bottom;
|
||||
planeref top;
|
||||
|
||||
unsigned char *toplightlevel;
|
||||
|
||||
fixed_t delta;
|
||||
|
||||
int flags;
|
||||
line_t* master;
|
||||
|
||||
sector_t * model;
|
||||
sector_t * target;
|
||||
|
||||
int lastlight;
|
||||
int alpha;
|
||||
|
||||
};
|
||||
|
||||
|
||||
struct FDynamicColormap;
|
||||
|
||||
|
||||
struct lightlist_t
|
||||
{
|
||||
secplane_t plane;
|
||||
unsigned char * p_lightlevel;
|
||||
FDynamicColormap ** p_extra_colormap;
|
||||
int flags;
|
||||
F3DFloor* caster;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class player_s;
|
||||
void P_PlayerOnSpecial3DFloor(player_t* player);
|
||||
|
||||
void P_Get3DFloorAndCeiling(AActor * thing, sector_t * sector, fixed_t * floorz, fixed_t * ceilingz, int * floorpic);
|
||||
bool P_CheckFor3DFloorHit(AActor * mo);
|
||||
bool P_CheckFor3DCeilingHit(AActor * mo);
|
||||
void P_Recalculate3DFloors(sector_t *);
|
||||
void P_RecalculateAttached3DFloors(sector_t * sec);
|
||||
lightlist_t * P_GetPlaneLight(sector_t * , secplane_t * plane, bool underside);
|
||||
void P_Spawn3DFloors( void );
|
||||
|
||||
struct FLineOpening;
|
||||
|
||||
void P_LineOpening_XFloors (FLineOpening &open, AActor * thing, const line_t *linedef,
|
||||
fixed_t x, fixed_t y, fixed_t refx, fixed_t refy);
|
||||
|
||||
#else
|
||||
|
||||
// Dummy definitions for disabled 3D floor code
|
||||
|
||||
struct F3DFloor
|
||||
{
|
||||
int dummy;
|
||||
};
|
||||
|
||||
struct lightlist_t
|
||||
{
|
||||
int dummy;
|
||||
};
|
||||
|
||||
class player_s;
|
||||
inline void P_PlayerOnSpecial3DFloor(player_t* player) {}
|
||||
|
||||
inline void P_Get3DFloorAndCeiling(AActor * thing, sector_t * sector, fixed_t * floorz, fixed_t * ceilingz, int * floorpic) {}
|
||||
inline bool P_CheckFor3DFloorHit(AActor * mo) { return false; }
|
||||
inline bool P_CheckFor3DCeilingHit(AActor * mo) { return false; }
|
||||
inline void P_Recalculate3DFloors(sector_t *) {}
|
||||
inline void P_RecalculateAttached3DFloors(sector_t * sec) {}
|
||||
inline lightlist_t * P_GetPlaneLight(sector_t * , secplane_t * plane, bool underside) { return NULL; }
|
||||
inline void P_Spawn3DFloors( void ) {}
|
||||
|
||||
struct FLineOpening;
|
||||
|
||||
inline void P_LineOpening_XFloors (FLineOpening &open, AActor * thing, const line_t *linedef,
|
||||
fixed_t x, fixed_t y, fixed_t refx, fixed_t refy) {}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
|
@ -366,8 +366,8 @@ bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y, FCheckPosition &tm);
|
|||
bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y);
|
||||
AActor *P_CheckOnmobj (AActor *thing);
|
||||
void P_FakeZMovement (AActor *mo);
|
||||
bool P_TryMove (AActor* thing, fixed_t x, fixed_t y, bool dropoff, bool onfloor, FCheckPosition &tm);
|
||||
bool P_TryMove (AActor* thing, fixed_t x, fixed_t y, bool dropoff, bool onfloor = false);
|
||||
bool P_TryMove (AActor* thing, fixed_t x, fixed_t y, bool dropoff, const secplane_t * onfloor, FCheckPosition &tm);
|
||||
bool P_TryMove (AActor* thing, fixed_t x, fixed_t y, bool dropoff, const secplane_t * onfloor = NULL);
|
||||
bool P_TeleportMove (AActor* thing, fixed_t x, fixed_t y, fixed_t z, bool telefrag); // [RH] Added z and telefrag parameters
|
||||
void P_PlayerStartStomp (AActor *actor); // [RH] Stomp on things for a newly spawned player
|
||||
void P_SlideMove (AActor* mo, fixed_t tryx, fixed_t tryy, int numsteps);
|
||||
|
@ -407,7 +407,7 @@ int P_GetFriction(const AActor *mo, int *frictionfactor);
|
|||
bool Check_Sides(AActor *, int, int); // phares
|
||||
|
||||
// [RH]
|
||||
bool P_CheckSlopeWalk (AActor *actor, fixed_t &xmove, fixed_t &ymove);
|
||||
const secplane_t * P_CheckSlopeWalk (AActor *actor, fixed_t &xmove, fixed_t &ymove);
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
//
|
||||
|
|
410
src/p_map.cpp
410
src/p_map.cpp
|
@ -106,10 +106,11 @@ static bool PIT_FindFloorCeiling (line_t *ld, const FBoundingBox &box, FCheckPos
|
|||
FLineOpening open;
|
||||
|
||||
// set openrange, opentop, openbottom
|
||||
if (((ld->frontsector->floorplane.a | ld->frontsector->floorplane.b) |
|
||||
if ((((ld->frontsector->floorplane.a | ld->frontsector->floorplane.b) |
|
||||
(ld->backsector->floorplane.a | ld->backsector->floorplane.b) |
|
||||
(ld->frontsector->ceilingplane.a | ld->frontsector->ceilingplane.b) |
|
||||
(ld->backsector->ceilingplane.a | ld->backsector->ceilingplane.b)) == 0)
|
||||
&& ld->backsector->e->XFloor.ffloors.Size()==0 && ld->frontsector->e->XFloor.ffloors.Size()==0)
|
||||
{
|
||||
P_LineOpening (open, tmf.thing, ld, sx=tmf.x, sy=tmf.y, tmf.x, tmf.y);
|
||||
}
|
||||
|
@ -165,7 +166,7 @@ static bool PIT_FindFloorCeiling (line_t *ld, const FBoundingBox &box, FCheckPos
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void P_FindFloorCeiling (AActor *actor, bool onlymidtex)
|
||||
void P_FindFloorCeiling (AActor *actor, bool onlyspawnpos)
|
||||
{
|
||||
sector_t *sec;
|
||||
FCheckPosition tmf;
|
||||
|
@ -196,7 +197,7 @@ void P_FindFloorCeiling (AActor *actor, bool onlymidtex)
|
|||
|
||||
if (tmf.touchmidtex) tmf.dropoffz = tmf.floorz;
|
||||
|
||||
if (!onlymidtex || (tmf.touchmidtex && (tmf.floorz <= actor->z)))
|
||||
if (!onlyspawnpos || (tmf.touchmidtex && (tmf.floorz <= actor->z)))
|
||||
{
|
||||
actor->floorz = tmf.floorz;
|
||||
actor->dropoffz = tmf.dropoffz;
|
||||
|
@ -206,6 +207,28 @@ void P_FindFloorCeiling (AActor *actor, bool onlymidtex)
|
|||
actor->ceilingpic = tmf.ceilingpic;
|
||||
actor->ceilingsector = tmf.ceilingsector;
|
||||
}
|
||||
|
||||
#ifdef _3DFLOORS
|
||||
// also check 3D floors at the spawn position if the result from the block lines iterator cannot be used.
|
||||
if (onlyspawnpos)
|
||||
{
|
||||
for(unsigned int i=0;i<actor->Sector->e->XFloor.ffloors.Size();i++)
|
||||
{
|
||||
F3DFloor* rover=actor->Sector->e->XFloor.ffloors[i];
|
||||
|
||||
if (!(rover->flags & FF_SOLID) || !(rover->flags & FF_EXISTS)) continue;
|
||||
|
||||
fixed_t ff_bottom=rover->bottom.plane->ZatPoint(actor->x, actor->y);
|
||||
fixed_t ff_top=rover->top.plane->ZatPoint(actor->x, actor->y);
|
||||
|
||||
fixed_t delta1 = actor->z - (ff_bottom + ((ff_top-ff_bottom)/2));
|
||||
fixed_t delta2 = actor->z + (actor->height? actor->height:1) - (ff_bottom + ((ff_top-ff_bottom)/2));
|
||||
|
||||
if (ff_top > actor->floorz && abs(delta1) < abs(delta2)) actor->floorz = ff_top;
|
||||
if (ff_bottom < actor->ceilingz && abs(delta1) >= abs(delta2)) actor->ceilingz = ff_bottom;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -406,6 +429,26 @@ int P_GetFriction (const AActor *mo, int *frictionfactor)
|
|||
for (m = mo->touching_sectorlist; m; m = m->m_tnext)
|
||||
{
|
||||
sec = m->m_sector;
|
||||
|
||||
#ifdef _3DFLOORS
|
||||
// 3D floors must be checked, too
|
||||
for(unsigned i=0;i<sec->e->XFloor.ffloors.Size();i++)
|
||||
{
|
||||
F3DFloor * rover=sec->e->XFloor.ffloors[i];
|
||||
if (!(rover->flags&FF_EXISTS)) continue;
|
||||
if(!(rover->flags & FF_SOLID)) continue;
|
||||
|
||||
// Player must be on top of the floor to be affected...
|
||||
if(mo->z != rover->top.plane->ZatPoint(mo->x,mo->y)) continue;
|
||||
fixed_t newfriction=secfriction(rover->model);
|
||||
if (newfriction<friction)
|
||||
{
|
||||
friction = newfriction;
|
||||
movefactor = secmovefac(rover->model);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!(sec->special & FRICTION_MASK) &&
|
||||
Terrains[TerrainTypes[sec->GetTexture(sector_t::floor)]].Friction == 0)
|
||||
{
|
||||
|
@ -559,10 +602,11 @@ bool PIT_CheckLine (line_t *ld, const FBoundingBox &box, FCheckPosition &tm)
|
|||
FLineOpening open;
|
||||
|
||||
// set openrange, opentop, openbottom
|
||||
if (((ld->frontsector->floorplane.a | ld->frontsector->floorplane.b) |
|
||||
if ((((ld->frontsector->floorplane.a | ld->frontsector->floorplane.b) |
|
||||
(ld->backsector->floorplane.a | ld->backsector->floorplane.b) |
|
||||
(ld->frontsector->ceilingplane.a | ld->frontsector->ceilingplane.b) |
|
||||
(ld->backsector->ceilingplane.a | ld->backsector->ceilingplane.b)) == 0)
|
||||
&& ld->backsector->e->XFloor.ffloors.Size()==0 && ld->frontsector->e->XFloor.ffloors.Size()==0)
|
||||
{
|
||||
P_LineOpening (open, tm.thing, ld, sx=tm.x, sy=tm.y, tm.x, tm.y);
|
||||
}
|
||||
|
@ -596,7 +640,16 @@ bool PIT_CheckLine (line_t *ld, const FBoundingBox &box, FCheckPosition &tm)
|
|||
P_LineOpening (open, tm.thing, ld, sx=ld->v1->x + MulScale24 (r, ld->dx),
|
||||
sy=ld->v1->y + MulScale24 (r, ld->dy), tm.x, tm.y);
|
||||
}
|
||||
/* Printf (" %d %d %d\n", sx, sy, openbottom);*/
|
||||
|
||||
// the floorplane on both sides is identical with the current one
|
||||
// so don't mess around with the z-position
|
||||
if (ld->frontsector->floorplane==ld->backsector->floorplane &&
|
||||
ld->frontsector->floorplane==tm.thing->Sector->floorplane &&
|
||||
!ld->frontsector->e->XFloor.ffloors.Size() && !ld->backsector->e->XFloor.ffloors.Size())
|
||||
{
|
||||
open.bottom=INT_MIN;
|
||||
}
|
||||
/* Printf (" %d %d %d\n", sx, sy, openbottom);*/
|
||||
}
|
||||
|
||||
if (rail &&
|
||||
|
@ -1049,7 +1102,40 @@ bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y, FCheckPosition &tm)
|
|||
//Added by MC: Fill the tmsector.
|
||||
tm.sector = newsec;
|
||||
|
||||
#ifdef _3DFLOORS
|
||||
//Check 3D floors
|
||||
if(newsec->e->XFloor.ffloors.Size())
|
||||
{
|
||||
F3DFloor* rover;
|
||||
fixed_t delta1;
|
||||
fixed_t delta2;
|
||||
int thingtop = thing->z + (thing->height==0? 1:thing->height);
|
||||
|
||||
for(unsigned i=0;i<newsec->e->XFloor.ffloors.Size();i++)
|
||||
{
|
||||
rover = newsec->e->XFloor.ffloors[i];
|
||||
if(!(rover->flags & FF_SOLID) || !(rover->flags & FF_EXISTS)) continue;
|
||||
|
||||
fixed_t ff_bottom=rover->bottom.plane->ZatPoint(x, y);
|
||||
fixed_t ff_top=rover->top.plane->ZatPoint(x, y);
|
||||
|
||||
delta1 = thing->z - (ff_bottom + ((ff_top-ff_bottom)/2));
|
||||
delta2 = thingtop - (ff_bottom + ((ff_top-ff_bottom)/2));
|
||||
|
||||
if(ff_top > tm.floorz && abs(delta1) < abs(delta2))
|
||||
{
|
||||
tm.floorz = tm.dropoffz = ff_top;
|
||||
tm.floorpic = *rover->top.texture;
|
||||
}
|
||||
if(ff_bottom < tm.ceilingz && abs(delta1) >= abs(delta2))
|
||||
{
|
||||
tm.ceilingz = ff_bottom;
|
||||
tm.ceilingpic = *rover->bottom.texture;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
validcount++;
|
||||
spechit.Clear ();
|
||||
|
||||
|
@ -1335,7 +1421,7 @@ static void CheckForPushSpecial (line_t *line, int side, AActor *mobj)
|
|||
//
|
||||
bool P_TryMove (AActor *thing, fixed_t x, fixed_t y,
|
||||
bool dropoff, // killough 3/15/98: allow dropoff as option
|
||||
bool onfloor, // [RH] Let P_TryMove keep the thing on the floor
|
||||
const secplane_t *onfloor, // [RH] Let P_TryMove keep the thing on the floor
|
||||
FCheckPosition &tm)
|
||||
{
|
||||
fixed_t oldx;
|
||||
|
@ -1351,7 +1437,7 @@ bool P_TryMove (AActor *thing, fixed_t x, fixed_t y,
|
|||
oldz = thing->z;
|
||||
if (onfloor)
|
||||
{
|
||||
thing->z = thing->floorsector->floorplane.ZatPoint (x, y);
|
||||
thing->z = onfloor->ZatPoint (x, y);
|
||||
}
|
||||
if (!P_CheckPosition (thing, x, y, tm))
|
||||
{
|
||||
|
@ -1679,7 +1765,7 @@ pushline:
|
|||
|
||||
bool P_TryMove (AActor *thing, fixed_t x, fixed_t y,
|
||||
bool dropoff, // killough 3/15/98: allow dropoff as option
|
||||
bool onfloor) // [RH] Let P_TryMove keep the thing on the floor
|
||||
const secplane_t *onfloor) // [RH] Let P_TryMove keep the thing on the floor
|
||||
{
|
||||
FCheckPosition tm;
|
||||
return P_TryMove(thing, x, y, dropoff, onfloor, tm);
|
||||
|
@ -1959,7 +2045,7 @@ void FSlide::SlideMove (AActor *mo, fixed_t tryx, fixed_t tryy, int numsteps)
|
|||
fixed_t trailx, traily;
|
||||
fixed_t newx, newy;
|
||||
fixed_t xmove, ymove;
|
||||
bool walkplane;
|
||||
const secplane_t * walkplane;
|
||||
int hitcount;
|
||||
|
||||
hitcount = 3;
|
||||
|
@ -2075,26 +2161,64 @@ void P_SlideMove (AActor *mo, fixed_t tryx, fixed_t tryy, int numsteps)
|
|||
//
|
||||
//============================================================================
|
||||
|
||||
bool P_CheckSlopeWalk (AActor *actor, fixed_t &xmove, fixed_t &ymove)
|
||||
const secplane_t * P_CheckSlopeWalk (AActor *actor, fixed_t &xmove, fixed_t &ymove)
|
||||
{
|
||||
static secplane_t copyplane;
|
||||
if (actor->flags & MF_NOGRAVITY)
|
||||
{
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const secplane_t *plane = &actor->floorsector->floorplane;
|
||||
fixed_t planezhere = plane->ZatPoint (actor->x, actor->y);
|
||||
|
||||
#ifdef _3DFLOORS
|
||||
for(unsigned int i=0;i<actor->floorsector->e->XFloor.ffloors.Size();i++)
|
||||
{
|
||||
F3DFloor * rover= actor->floorsector->e->XFloor.ffloors[i];
|
||||
if(!(rover->flags & FF_SOLID) || !(rover->flags & FF_EXISTS)) continue;
|
||||
|
||||
fixed_t thisplanez = rover->top.plane->ZatPoint(actor->x, actor->y);
|
||||
|
||||
if (thisplanez>planezhere && thisplanez<=actor->z + actor->MaxStepHeight)
|
||||
{
|
||||
copyplane = *rover->top.plane;
|
||||
if (copyplane.c<0) copyplane.FlipVert();
|
||||
plane = ©plane;
|
||||
planezhere=thisplanez;
|
||||
}
|
||||
}
|
||||
|
||||
if (actor->floorsector != actor->Sector)
|
||||
{
|
||||
for(unsigned int i=0;i<actor->Sector->e->XFloor.ffloors.Size();i++)
|
||||
{
|
||||
F3DFloor * rover= actor->Sector->e->XFloor.ffloors[i];
|
||||
if(!(rover->flags & FF_SOLID) || !(rover->flags & FF_EXISTS)) continue;
|
||||
|
||||
fixed_t thisplanez = rover->top.plane->ZatPoint(actor->x, actor->y);
|
||||
|
||||
if (thisplanez>planezhere && thisplanez<=actor->z + actor->MaxStepHeight)
|
||||
{
|
||||
copyplane = *rover->top.plane;
|
||||
if (copyplane.c<0) copyplane.FlipVert();
|
||||
plane = ©plane;
|
||||
planezhere=thisplanez;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (actor->floorsector != actor->Sector)
|
||||
{
|
||||
// this additional check prevents sliding on sloped dropoffs
|
||||
if (planezhere>actor->floorz+4*FRACUNIT)
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (actor->z - planezhere > FRACUNIT)
|
||||
{ // not on floor
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((plane->a | plane->b) != 0)
|
||||
|
@ -2112,7 +2236,7 @@ bool P_CheckSlopeWalk (AActor *actor, fixed_t &xmove, fixed_t &ymove)
|
|||
{ // Can't climb up slopes of ~45 degrees or more
|
||||
if (actor->flags & MF_NOCLIP)
|
||||
{
|
||||
return (actor->floorsector == actor->Sector);
|
||||
return (actor->floorsector == actor->Sector) ? plane : NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2139,7 +2263,7 @@ bool P_CheckSlopeWalk (AActor *actor, fixed_t &xmove, fixed_t &ymove)
|
|||
xmove = actor->momx = plane->a * 2;
|
||||
ymove = actor->momy = plane->b * 2;
|
||||
}
|
||||
return false;
|
||||
return (actor->floorsector == actor->Sector) ? plane : NULL;
|
||||
}
|
||||
}
|
||||
// Slide the desired location along the plane's normal
|
||||
|
@ -2148,7 +2272,7 @@ bool P_CheckSlopeWalk (AActor *actor, fixed_t &xmove, fixed_t &ymove)
|
|||
desty -= FixedMul (plane->b, t);
|
||||
xmove = destx - actor->x;
|
||||
ymove = desty - actor->y;
|
||||
return (actor->floorsector == actor->Sector);
|
||||
return (actor->floorsector == actor->Sector) ? plane : NULL;
|
||||
}
|
||||
else if (t > 0)
|
||||
{ // Desired location is in front of (above) the plane
|
||||
|
@ -2159,11 +2283,11 @@ bool P_CheckSlopeWalk (AActor *actor, fixed_t &xmove, fixed_t &ymove)
|
|||
desty += FixedMul (plane->b, t);
|
||||
xmove = destx - actor->x;
|
||||
ymove = desty - actor->y;
|
||||
return (actor->floorsector == actor->Sector);//(plane->c >= STEEPSLOPE);
|
||||
return (actor->floorsector == actor->Sector) ? plane : NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
@ -2360,11 +2484,126 @@ struct aim_t
|
|||
angle_t pitch_friend, pitch_other;
|
||||
bool notsmart;
|
||||
bool check3d;
|
||||
#ifdef _3DFLOORS
|
||||
sector_t * lastsector;
|
||||
secplane_t * lastfloorplane;
|
||||
secplane_t * lastceilingplane;
|
||||
|
||||
bool crossedffloors;
|
||||
|
||||
bool AimTraverse3DFloors(const divline_t &trace, intercept_t * in);
|
||||
#endif
|
||||
|
||||
void AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t endy);
|
||||
|
||||
};
|
||||
|
||||
#ifdef _3DFLOORS
|
||||
//============================================================================
|
||||
//
|
||||
// AimTraverse3DFloors
|
||||
//
|
||||
//============================================================================
|
||||
bool aim_t::AimTraverse3DFloors(const divline_t &trace, intercept_t * in)
|
||||
{
|
||||
sector_t * nextsector;
|
||||
secplane_t * nexttopplane, * nextbottomplane;
|
||||
line_t * li=in->d.line;
|
||||
|
||||
nextsector=NULL;
|
||||
nexttopplane=nextbottomplane=NULL;
|
||||
|
||||
if(li->frontsector->e->XFloor.ffloors.Size() || li->backsector->e->XFloor.ffloors.Size())
|
||||
{
|
||||
int frontflag;
|
||||
F3DFloor* rover;
|
||||
int highpitch, lowpitch;
|
||||
|
||||
fixed_t trX = trace.x + FixedMul (trace.dx, in->frac);
|
||||
fixed_t trY = trace.y + FixedMul (trace.dy, in->frac);
|
||||
fixed_t dist = FixedMul (attackrange, in->frac);
|
||||
|
||||
|
||||
int dir = aimpitch < 0 ? 1 : aimpitch > 0 ? -1 : 0;
|
||||
|
||||
frontflag = P_PointOnLineSide(shootthing->x, shootthing->y, li);
|
||||
|
||||
// 3D floor check. This is not 100% accurate but normally sufficient when
|
||||
// combined with a final sight check
|
||||
for(int i=1;i<=2;i++)
|
||||
{
|
||||
sector_t * s=i==1? li->frontsector:li->backsector;
|
||||
|
||||
for(unsigned k=0;k<s->e->XFloor.ffloors.Size();k++)
|
||||
{
|
||||
crossedffloors=true;
|
||||
rover=s->e->XFloor.ffloors[k];
|
||||
|
||||
if((rover->flags & FF_SHOOTTHROUGH) || !(rover->flags & FF_EXISTS)) continue;
|
||||
|
||||
fixed_t ff_bottom=rover->bottom.plane->ZatPoint(trX, trY);
|
||||
fixed_t ff_top=rover->top.plane->ZatPoint(trX, trY);
|
||||
|
||||
|
||||
highpitch = -(int)R_PointToAngle2 (0, shootz, dist, ff_top);
|
||||
lowpitch = -(int)R_PointToAngle2 (0, shootz, dist, ff_bottom);
|
||||
|
||||
if (highpitch<=toppitch)
|
||||
{
|
||||
// blocks completely
|
||||
if (lowpitch>=bottompitch) return false;
|
||||
// blocks upper edge of view
|
||||
if (lowpitch>toppitch)
|
||||
{
|
||||
toppitch=lowpitch;
|
||||
if (frontflag!=i-1)
|
||||
{
|
||||
nexttopplane=rover->bottom.plane;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (lowpitch>=bottompitch)
|
||||
{
|
||||
// blocks lower edge of view
|
||||
if (highpitch<bottompitch)
|
||||
{
|
||||
bottompitch=highpitch;
|
||||
if (frontflag!=i-1)
|
||||
{
|
||||
nextbottomplane=rover->top.plane;
|
||||
}
|
||||
}
|
||||
}
|
||||
// trace is leaving a sector with a 3d-floor
|
||||
|
||||
if (frontflag==i-1)
|
||||
{
|
||||
if (s==lastsector)
|
||||
{
|
||||
// upper slope intersects with this 3d-floor
|
||||
if (rover->bottom.plane==lastceilingplane && lowpitch > toppitch)
|
||||
{
|
||||
toppitch=lowpitch;
|
||||
}
|
||||
// lower slope intersects with this 3d-floor
|
||||
if (rover->top.plane==lastfloorplane && highpitch < bottompitch)
|
||||
{
|
||||
bottompitch=highpitch;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (toppitch >= bottompitch) return false; // stop
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lastsector=nextsector;
|
||||
lastceilingplane=nexttopplane;
|
||||
lastfloorplane=nextbottomplane;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// PTR_AimTraverse
|
||||
|
@ -2386,7 +2625,7 @@ void aim_t::AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t e
|
|||
fixed_t thingbottompitch;
|
||||
fixed_t dist;
|
||||
int thingpitch;
|
||||
|
||||
|
||||
if (in->isaline)
|
||||
{
|
||||
li = in->d.line;
|
||||
|
@ -2397,8 +2636,8 @@ void aim_t::AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t e
|
|||
// Crosses a two sided line.
|
||||
// A two sided line will restrict the possible target ranges.
|
||||
FLineOpening open;
|
||||
P_LineOpening (open, NULL, li, it.Trace().x + FixedMul (it.Trace().dx, in->frac),
|
||||
it.Trace().y + FixedMul (it.Trace().dy, in->frac));
|
||||
P_LineOpening (open, NULL, li, it.Trace().x + FixedMul (it.Trace().dx, in->frac),
|
||||
it.Trace().y + FixedMul (it.Trace().dy, in->frac));
|
||||
|
||||
if (open.bottom >= open.top)
|
||||
return; // stop
|
||||
|
@ -2415,7 +2654,10 @@ void aim_t::AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t e
|
|||
|
||||
if (toppitch >= bottompitch)
|
||||
return; // stop
|
||||
|
||||
|
||||
#ifdef _3DFLOORS
|
||||
if (!AimTraverse3DFloors(it.Trace(), in)) return;
|
||||
#endif
|
||||
continue; // shot continues
|
||||
}
|
||||
|
||||
|
@ -2437,6 +2679,34 @@ void aim_t::AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t e
|
|||
}
|
||||
|
||||
dist = FixedMul (attackrange, in->frac);
|
||||
|
||||
#ifdef _3DFLOORS
|
||||
// we must do one last check whether the trace has crossed a 3D floor
|
||||
if (lastsector==th->Sector && th->Sector->e->XFloor.ffloors.Size())
|
||||
{
|
||||
if (lastceilingplane)
|
||||
{
|
||||
fixed_t ff_top=lastceilingplane->ZatPoint(th->x, th->y);
|
||||
fixed_t pitch = -(int)R_PointToAngle2 (0, shootz, dist, ff_top);
|
||||
// upper slope intersects with this 3d-floor
|
||||
if (pitch > toppitch)
|
||||
{
|
||||
toppitch=pitch;
|
||||
}
|
||||
}
|
||||
if (lastfloorplane)
|
||||
{
|
||||
fixed_t ff_bottom=lastfloorplane->ZatPoint(th->x, th->y);
|
||||
fixed_t pitch = -(int)R_PointToAngle2 (0, shootz, dist, ff_bottom);
|
||||
// lower slope intersects with this 3d-floor
|
||||
if (pitch < bottompitch)
|
||||
{
|
||||
bottompitch=pitch;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// check angles to see if the thing can be aimed at
|
||||
|
||||
thingtoppitch = -(int)R_PointToAngle2 (0, shootz, dist, th->z + th->height);
|
||||
|
@ -2449,6 +2719,27 @@ void aim_t::AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t e
|
|||
if (thingbottompitch < toppitch)
|
||||
continue; // shot under the thing
|
||||
|
||||
#ifdef _3DFLOORS
|
||||
if (crossedffloors)
|
||||
{
|
||||
// if 3D floors were in the way do an extra visibility check for safety
|
||||
if (!P_CheckSight(shootthing, th, 1))
|
||||
{
|
||||
// the thing can't be seen so we can safely exclude its range from our aiming field
|
||||
if (thingtoppitch<toppitch)
|
||||
{
|
||||
if (thingbottompitch>toppitch) toppitch=thingbottompitch;
|
||||
}
|
||||
else if (thingbottompitch>bottompitch)
|
||||
{
|
||||
if (thingtoppitch<bottompitch) bottompitch=thingtoppitch;
|
||||
}
|
||||
if (toppitch < bottompitch) continue;
|
||||
else return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// this thing can be hit!
|
||||
if (thingtoppitch < toppitch)
|
||||
thingtoppitch = toppitch;
|
||||
|
@ -2568,6 +2859,25 @@ fixed_t P_AimLineAttack (AActor *t1, angle_t angle, fixed_t distance, AActor **p
|
|||
|
||||
// Information for tracking crossed 3D floors
|
||||
aim.aimpitch=t1->pitch;
|
||||
|
||||
#ifdef _3DFLOORS
|
||||
aim.crossedffloors=t1->Sector->e->XFloor.ffloors.Size()!=0;
|
||||
aim.lastsector=t1->Sector;
|
||||
aim.lastfloorplane=aim.lastceilingplane=NULL;
|
||||
|
||||
// set initial 3d-floor info
|
||||
for(unsigned i=0;i<t1->Sector->e->XFloor.ffloors.Size();i++)
|
||||
{
|
||||
F3DFloor * rover=t1->Sector->e->XFloor.ffloors[i];
|
||||
fixed_t bottomz=rover->bottom.plane->ZatPoint(t1->x, t1->y);
|
||||
|
||||
if (bottomz>=t1->z+t1->height) aim.lastceilingplane=rover->bottom.plane;
|
||||
|
||||
bottomz=rover->top.plane->ZatPoint(t1->x, t1->y);
|
||||
if (bottomz<=t1->z) aim.lastfloorplane=rover->top.plane;
|
||||
}
|
||||
#endif
|
||||
|
||||
aim.AimTraverse (t1->x, t1->y, x2, y2);
|
||||
|
||||
if (!aim.linetarget)
|
||||
|
@ -2916,6 +3226,7 @@ void P_TraceBleed (int damage, fixed_t x, fixed_t y, fixed_t z, AActor *actor, a
|
|||
DImpactDecal::StaticCreate (bloodType,
|
||||
bleedtrace.X, bleedtrace.Y, bleedtrace.Z,
|
||||
sides + bleedtrace.Line->sidenum[bleedtrace.Side],
|
||||
bleedtrace.ffloor,
|
||||
bloodcolor);
|
||||
}
|
||||
}
|
||||
|
@ -4124,7 +4435,56 @@ bool P_ChangeSector (sector_t *sector, int crunch, int amt, int floorOrCeil, boo
|
|||
cpos.movemidtex = false;
|
||||
cpos.sector = sector;
|
||||
|
||||
// [RH] Use different functions for the four different types of sector movement.
|
||||
#ifdef _3DFLOORS
|
||||
// Also process all sectors that have 3D floors transferred from the
|
||||
// changed sector.
|
||||
if(sector->e->XFloor.attached.Size())
|
||||
{
|
||||
unsigned i;
|
||||
sector_t* sec;
|
||||
|
||||
|
||||
// Use different functions for the four different types of sector movement.
|
||||
// for 3D-floors the meaning of floor and ceiling is inverted!!!
|
||||
if (floorOrCeil == 1)
|
||||
{
|
||||
iterator = (amt >= 0) ? PIT_FloorRaise : PIT_FloorDrop;
|
||||
}
|
||||
else
|
||||
{
|
||||
iterator = (amt >=0) ? PIT_CeilingRaise : PIT_CeilingLower;
|
||||
}
|
||||
|
||||
for(i = 0; i < sector->e->XFloor.attached.Size(); i ++)
|
||||
{
|
||||
sec = sector->e->XFloor.attached[i];
|
||||
P_Recalculate3DFloors(sec); // Must recalculate the 3d floor and light lists
|
||||
|
||||
// no thing checks for attached sectors because of heightsec
|
||||
if (sec->heightsec==sector) continue;
|
||||
|
||||
for (n=sec->touching_thinglist; n; n=n->m_snext) n->visited = false;
|
||||
do
|
||||
{
|
||||
for (n=sec->touching_thinglist; n; n=n->m_snext)
|
||||
{
|
||||
if (!n->visited)
|
||||
{
|
||||
n->visited = true;
|
||||
if (!(n->m_thing->flags&MF_NOBLOCKMAP)) iterator(n->m_thing, &cpos);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (n);
|
||||
}
|
||||
}
|
||||
P_Recalculate3DFloors(sector); // Must recalculate the 3d floor and light lists
|
||||
#endif
|
||||
|
||||
|
||||
// [RH] Use different functions for the four different types of sector
|
||||
// movement. Also update the soundorg's z-coordinate for 3D sound.
|
||||
switch (floorOrCeil)
|
||||
{
|
||||
case 0:
|
||||
|
@ -4497,13 +4857,15 @@ void SpawnShootDecal (AActor *t1, const FTraceResults &trace)
|
|||
if (decalbase != NULL)
|
||||
{
|
||||
DImpactDecal::StaticCreate (decalbase->GetDecal (),
|
||||
trace.X, trace.Y, trace.Z, sides + trace.Line->sidenum[trace.Side]);
|
||||
trace.X, trace.Y, trace.Z, sides + trace.Line->sidenum[trace.Side], trace.ffloor);
|
||||
}
|
||||
}
|
||||
|
||||
static void SpawnDeepSplash (AActor *t1, const FTraceResults &trace, AActor *puff,
|
||||
fixed_t vx, fixed_t vy, fixed_t vz, fixed_t shootz)
|
||||
{
|
||||
if (!trace.CrossedWater->heightsec) return;
|
||||
|
||||
fixed_t num, den, hitdist;
|
||||
const secplane_t *plane = &trace.CrossedWater->heightsec->floorplane;
|
||||
|
||||
|
|
|
@ -197,6 +197,12 @@ void P_LineOpening (FLineOpening &open, AActor *actor, const line_t *linedef,
|
|||
open.lowfloor = ff;
|
||||
}
|
||||
|
||||
// Check 3D floors
|
||||
if (actor != NULL)
|
||||
{
|
||||
P_LineOpening_XFloors(open, actor, linedef, x, y, refx, refy);
|
||||
}
|
||||
|
||||
if (actor != NULL && linedef->frontsector != NULL && linedef->backsector != NULL &&
|
||||
linedef->flags & ML_3DMIDTEX)
|
||||
{
|
||||
|
|
142
src/p_mobj.cpp
142
src/p_mobj.cpp
|
@ -1066,8 +1066,31 @@ void P_ExplodeMissile (AActor *mo, line_t *line, AActor *target)
|
|||
y = line->v1->y + MulScale30 (line->dy, frac);
|
||||
z = mo->z;
|
||||
|
||||
F3DFloor * ffloor=NULL;
|
||||
#ifdef _3DFLOORS
|
||||
if (line->sidenum[side^1]!=NO_SIDE)
|
||||
{
|
||||
sector_t * backsector=sides[line->sidenum[side^1]].sector;
|
||||
extsector_t::xfloor &xf = backsector->e->XFloor;
|
||||
// find a 3D-floor to stick to
|
||||
for(unsigned int i=0;i<xf.ffloors.Size();i++)
|
||||
{
|
||||
F3DFloor * rover=xf.ffloors[i];
|
||||
|
||||
if ((rover->flags&(FF_EXISTS|FF_SOLID|FF_RENDERSIDES))==(FF_EXISTS|FF_SOLID|FF_RENDERSIDES))
|
||||
{
|
||||
if (z<=rover->top.plane->ZatPoint(x, y) && z>=rover->bottom.plane->ZatPoint( x, y))
|
||||
{
|
||||
ffloor=rover;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
DImpactDecal::StaticCreate (base->GetDecal (),
|
||||
x, y, z, sides + line->sidenum[side]);
|
||||
x, y, z, sides + line->sidenum[side], ffloor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1318,7 +1341,7 @@ void P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
|
|||
fixed_t ptryx, ptryy;
|
||||
player_t *player;
|
||||
fixed_t xmove, ymove;
|
||||
bool walkplane;
|
||||
const secplane_t * walkplane;
|
||||
static const int windTab[3] = {2048*5, 2048*10, 2048*25};
|
||||
int steps, step, totalsteps;
|
||||
fixed_t startx, starty;
|
||||
|
@ -1723,7 +1746,19 @@ explode:
|
|||
{
|
||||
if (mo->dropoffz != mo->floorz) // 3DMidtex or other special cases that must be excluded
|
||||
{
|
||||
return;
|
||||
#ifdef _3DFLOORS
|
||||
unsigned i;
|
||||
for(i=0;i<mo->Sector->e->XFloor.ffloors.Size();i++)
|
||||
{
|
||||
// Sliding around on 3D floors looks extremely bad so
|
||||
// if the floor comes from one in the current sector stop sliding the corpse!
|
||||
F3DFloor * rover=mo->Sector->e->XFloor.ffloors[i];
|
||||
if (!(rover->flags&FF_EXISTS)) continue;
|
||||
if (rover->flags&FF_SOLID && rover->top.plane->ZatPoint(mo->x,mo->y)==mo->floorz) break;
|
||||
}
|
||||
if (i==mo->Sector->e->XFloor.ffloors.Size())
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1894,6 +1929,7 @@ void P_ZMovement (AActor *mo)
|
|||
{ // [RH] Let the sector do something to the actor
|
||||
mo->Sector->SecActTarget->TriggerAction (mo, SECSPAC_HitFloor);
|
||||
}
|
||||
P_CheckFor3DFloorHit(mo);
|
||||
// [RH] Need to recheck this because the sector action might have
|
||||
// teleported the actor so it is no longer below the floor.
|
||||
if (mo->z <= mo->floorz)
|
||||
|
@ -1992,6 +2028,7 @@ void P_ZMovement (AActor *mo)
|
|||
{ // [RH] Let the sector do something to the actor
|
||||
mo->Sector->SecActTarget->TriggerAction (mo, SECSPAC_HitCeiling);
|
||||
}
|
||||
P_CheckFor3DCeilingHit(mo);
|
||||
// [RH] Need to recheck this because the sector action might have
|
||||
// teleported the actor so it is no longer above the ceiling.
|
||||
if (mo->z + mo->height > mo->ceilingz)
|
||||
|
@ -2829,6 +2866,26 @@ void AActor::Tick ()
|
|||
floorz == z)
|
||||
{
|
||||
const secplane_t * floorplane = &floorsector->floorplane;
|
||||
static secplane_t copyplane;
|
||||
|
||||
#ifdef _3DFLOORS
|
||||
// Check 3D floors as well
|
||||
if (floorsector->e) // apparently this can be called when the data is already gone-
|
||||
for(unsigned int i=0;i<floorsector->e->XFloor.ffloors.Size();i++)
|
||||
{
|
||||
F3DFloor * rover= floorsector->e->XFloor.ffloors[i];
|
||||
if(!(rover->flags & FF_SOLID) || !(rover->flags & FF_EXISTS)) continue;
|
||||
|
||||
if (rover->top.plane->ZatPoint(x, y) == floorz)
|
||||
{
|
||||
copyplane = *rover->top.plane;
|
||||
if (copyplane.c<0) copyplane.FlipVert();
|
||||
floorplane = ©plane;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (floorplane->c < STEEPSLOPE &&
|
||||
floorplane->ZatPoint (x, y) <= floorz)
|
||||
{
|
||||
|
@ -3053,8 +3110,42 @@ bool AActor::UpdateWaterLevel (fixed_t oldz, bool dosplash)
|
|||
// But the water level must be reset when this function returns
|
||||
if (!(hsec->MoreFlags&SECF_UNDERWATERMASK)) reset=true;
|
||||
}
|
||||
}
|
||||
#ifdef _3DFLOORS
|
||||
else
|
||||
{
|
||||
// Check 3D floors as well!
|
||||
for(unsigned int i=0;i<Sector->e->XFloor.ffloors.Size();i++)
|
||||
{
|
||||
F3DFloor* rover=Sector->e->XFloor.ffloors[i];
|
||||
|
||||
if (!(rover->flags & FF_EXISTS)) continue;
|
||||
if(!(rover->flags & FF_SWIMMABLE) || rover->flags & FF_SOLID) continue;
|
||||
|
||||
fixed_t ff_bottom=rover->bottom.plane->ZatPoint(x, y);
|
||||
fixed_t ff_top=rover->top.plane->ZatPoint(x, y);
|
||||
|
||||
if(ff_top <= z || ff_bottom > (z + (height >> 1))) continue;
|
||||
|
||||
fh=ff_top;
|
||||
if (z < fh)
|
||||
{
|
||||
waterlevel = 1;
|
||||
if (z + height/2 < fh)
|
||||
{
|
||||
waterlevel = 2;
|
||||
if ((player && z + player->viewheight <= fh) ||
|
||||
(z + height <= fh))
|
||||
{
|
||||
waterlevel = 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// some additional checks to make deep sectors like Boom's splash without setting
|
||||
// the water flags.
|
||||
|
@ -3064,7 +3155,7 @@ bool AActor::UpdateWaterLevel (fixed_t oldz, bool dosplash)
|
|||
}
|
||||
boomwaterlevel=waterlevel;
|
||||
if (reset) waterlevel=lastwaterlevel;
|
||||
return false; // we did the splash ourselves! ;)
|
||||
return false; // we did the splash ourselves
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -3377,6 +3468,9 @@ void AActor::AdjustFloorClip ()
|
|||
fixed_t shallowestclip = FIXED_MAX;
|
||||
const msecnode_t *m;
|
||||
|
||||
// possibly standing on a 3D-floor!
|
||||
if (Sector->e->XFloor.ffloors.Size() && z>Sector->floorplane.ZatPoint(x,y)) floorclip=0;
|
||||
|
||||
// [RH] clip based on shallowest floor player is standing on
|
||||
// If the sector has a deep water effect, then let that effect
|
||||
// do the floorclipping instead of the terrain type.
|
||||
|
@ -4234,6 +4328,25 @@ bool P_HitWater (AActor * thing, sector_t * sec, fixed_t x, fixed_t y, fixed_t z
|
|||
if (z == FIXED_MIN) z = thing->z;
|
||||
// don't splash above the object
|
||||
if (checkabove && z > thing->z + (thing->height >> 1)) return false;
|
||||
|
||||
#ifdef _3DFLOORS
|
||||
for(unsigned int i=0;i<sec->e->XFloor.ffloors.Size();i++)
|
||||
{
|
||||
F3DFloor * rover = sec->e->XFloor.ffloors[i];
|
||||
if (!(rover->flags & FF_EXISTS)) continue;
|
||||
fixed_t planez = rover->top.plane->ZatPoint(x, y);
|
||||
if (z > planez - FRACUNIT/2 && z < planez + FRACUNIT/2) // allow minor imprecisions
|
||||
{
|
||||
if (rover->flags & (FF_SOLID|FF_SWIMMABLE) )
|
||||
{
|
||||
terrainnum = TerrainTypes[*rover->top.texture];
|
||||
goto foundone;
|
||||
}
|
||||
}
|
||||
planez = rover->bottom.plane->ZatPoint(x, y);
|
||||
if (planez < z) return false;
|
||||
}
|
||||
#endif
|
||||
if (sec->heightsec == NULL ||
|
||||
//!sec->heightsec->waterzone ||
|
||||
(sec->heightsec->MoreFlags & SECF_IGNOREHEIGHTSEC) ||
|
||||
|
@ -4245,6 +4358,9 @@ bool P_HitWater (AActor * thing, sector_t * sec, fixed_t x, fixed_t y, fixed_t z
|
|||
{
|
||||
terrainnum = TerrainTypes[sec->heightsec->GetTexture(sector_t::floor)];
|
||||
}
|
||||
#ifdef _3DFLOORS
|
||||
foundone:
|
||||
#endif
|
||||
|
||||
int splashnum = Terrains[terrainnum].Splash;
|
||||
bool smallsplash = false;
|
||||
|
@ -4339,6 +4455,22 @@ bool P_HitFloor (AActor *thing)
|
|||
{
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef _3DFLOORS
|
||||
// Check 3D floors
|
||||
for(unsigned int i=0;i<m->m_sector->e->XFloor.ffloors.Size();i++)
|
||||
{
|
||||
F3DFloor * rover = m->m_sector->e->XFloor.ffloors[i];
|
||||
if (!(rover->flags & FF_EXISTS)) continue;
|
||||
if (rover->flags & (FF_SOLID|FF_SWIMMABLE))
|
||||
{
|
||||
if (rover->top.plane->ZatPoint(thing->x, thing->y) == thing->z)
|
||||
{
|
||||
return P_HitWater (thing, m->m_sector);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (m == NULL ||
|
||||
(m->m_sector->heightsec != NULL &&
|
||||
|
|
|
@ -1242,6 +1242,7 @@ void P_LoadSectors (MapData * map)
|
|||
// killough 8/28/98: initialize all sectors to normal friction
|
||||
ss->friction = ORIG_FRICTION;
|
||||
ss->movefactor = ORIG_FRICTION_FACTOR;
|
||||
ss->sectornum = i;
|
||||
}
|
||||
delete[] msp;
|
||||
}
|
||||
|
@ -2131,6 +2132,28 @@ void P_ProcessSideTextures(bool checktranmap, side_t *sd, sector_t *sec, mapside
|
|||
}
|
||||
break;
|
||||
|
||||
#ifdef _3DFLOORS
|
||||
case Sector_Set3DFloor:
|
||||
if (msd->toptexture[0]=='#')
|
||||
{
|
||||
strncpy (name, msd->toptexture, 8);
|
||||
sd->SetTexture(side_t::top, FNullTextureID() +(-strtol(name+1, NULL, 10))); // store the alpha as a negative texture index
|
||||
// This will be sorted out by the 3D-floor code later.
|
||||
}
|
||||
else
|
||||
{
|
||||
strncpy (name, msd->toptexture, 8);
|
||||
sd->SetTexture(side_t::top, TexMan.GetTexture (name, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable));
|
||||
}
|
||||
|
||||
strncpy (name, msd->midtexture, 8);
|
||||
sd->SetTexture(side_t::mid, TexMan.GetTexture (name, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable));
|
||||
|
||||
strncpy (name, msd->bottomtexture, 8);
|
||||
sd->SetTexture(side_t::bottom, TexMan.GetTexture (name, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable));
|
||||
break;
|
||||
#endif
|
||||
|
||||
case TranslucentLine: // killough 4/11/98: apply translucency to 2s normal texture
|
||||
if (checktranmap)
|
||||
{
|
||||
|
@ -3483,6 +3506,9 @@ void P_SetupLevel (char *lumpname, int position)
|
|||
|
||||
deathmatchstarts.Clear ();
|
||||
|
||||
// Spawn 3d floors - must be done before spawning things so it can't be done in P_SpawnSpecials
|
||||
P_Spawn3DFloors();
|
||||
|
||||
if (!buildmap)
|
||||
{
|
||||
times[14].Clock();
|
||||
|
|
220
src/p_sight.cpp
220
src/p_sight.cpp
|
@ -37,19 +37,47 @@ This uses specialized forms of the maputils routines for optimized performance
|
|||
==============================================================================
|
||||
*/
|
||||
|
||||
static TArray<intercept_t> intercepts (128);
|
||||
static divline_t trace;
|
||||
|
||||
static fixed_t sightzstart; // eye z of looker
|
||||
static fixed_t topslope, bottomslope; // slopes to top and bottom of target
|
||||
static int SeePastBlockEverything, SeePastShootableLines;
|
||||
|
||||
// Performance meters
|
||||
static int sightcounts[6];
|
||||
static cycle_t SightCycles;
|
||||
static cycle_t MaxSightCycles;
|
||||
|
||||
static bool P_SightTraverseIntercepts ();
|
||||
static TArray<intercept_t> intercepts (128);
|
||||
|
||||
class SightCheck
|
||||
{
|
||||
fixed_t sightzstart; // eye z of looker
|
||||
const AActor * sightthing;
|
||||
const AActor * seeingthing;
|
||||
fixed_t lastztop; // z at last line
|
||||
fixed_t lastzbottom; // z at last line
|
||||
sector_t * lastsector; // last sector being entered by trace
|
||||
fixed_t topslope, bottomslope; // slopes to top and bottom of target
|
||||
int SeePastBlockEverything, SeePastShootableLines;
|
||||
divline_t trace;
|
||||
int myseethrough;
|
||||
|
||||
bool PTR_SightTraverse (intercept_t *in);
|
||||
bool P_SightCheckLine (line_t *ld);
|
||||
bool P_SightBlockLinesIterator (int x, int y);
|
||||
bool P_SightTraverseIntercepts ();
|
||||
|
||||
public:
|
||||
bool P_SightPathTraverse (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2);
|
||||
|
||||
SightCheck(const AActor * t1, const AActor * t2, int flags)
|
||||
{
|
||||
lastztop = lastzbottom = sightzstart = t1->z + t1->height - (t1->height>>2);
|
||||
lastsector = t1->Sector;
|
||||
sightthing=t1;
|
||||
seeingthing=t2;
|
||||
bottomslope = t2->z - sightzstart;
|
||||
topslope = bottomslope + t2->height;
|
||||
|
||||
SeePastBlockEverything = flags & 6;
|
||||
SeePastShootableLines = flags & 4;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
==============
|
||||
|
@ -59,7 +87,10 @@ static bool P_SightTraverseIntercepts ();
|
|||
==============
|
||||
*/
|
||||
|
||||
/*
|
||||
static bool PTR_SightTraverse (intercept_t *in)
|
||||
*/
|
||||
bool SightCheck::PTR_SightTraverse (intercept_t *in)
|
||||
{
|
||||
line_t *li;
|
||||
fixed_t slope;
|
||||
|
@ -70,8 +101,9 @@ static bool PTR_SightTraverse (intercept_t *in)
|
|||
//
|
||||
// crosses a two sided line
|
||||
//
|
||||
P_LineOpening (open, NULL, li, trace.x + FixedMul (trace.dx, in->frac),
|
||||
trace.y + FixedMul (trace.dy, in->frac));
|
||||
fixed_t trX=trace.x + FixedMul (trace.dx, in->frac);
|
||||
fixed_t trY=trace.y + FixedMul (trace.dy, in->frac);
|
||||
P_LineOpening (open, NULL, li, trX, trY);
|
||||
|
||||
if (open.range <= 0) // quick test for totally closed doors
|
||||
return false; // stop
|
||||
|
@ -89,6 +121,98 @@ static bool PTR_SightTraverse (intercept_t *in)
|
|||
if (topslope <= bottomslope)
|
||||
return false; // stop
|
||||
|
||||
#ifdef _3DFLOORS
|
||||
// now handle 3D-floors
|
||||
if(li->frontsector->e->XFloor.ffloors.Size() || li->backsector->e->XFloor.ffloors.Size())
|
||||
{
|
||||
int frontflag;
|
||||
|
||||
frontflag = P_PointOnLineSide(sightthing->x, sightthing->y, li);
|
||||
|
||||
//Check 3D FLOORS!
|
||||
for(int i=1;i<=2;i++)
|
||||
{
|
||||
sector_t * s=i==1? li->frontsector:li->backsector;
|
||||
fixed_t highslope, lowslope;
|
||||
|
||||
fixed_t topz= FixedMul (topslope, in->frac) + sightzstart;
|
||||
fixed_t bottomz= FixedMul (bottomslope, in->frac) + sightzstart;
|
||||
|
||||
for(unsigned int j=0;j<s->e->XFloor.ffloors.Size();j++)
|
||||
{
|
||||
F3DFloor* rover=s->e->XFloor.ffloors[j];
|
||||
|
||||
if((rover->flags & FF_SEETHROUGH) == myseethrough || !(rover->flags & FF_EXISTS)) continue;
|
||||
|
||||
fixed_t ff_bottom=rover->bottom.plane->ZatPoint(trX, trY);
|
||||
fixed_t ff_top=rover->top.plane->ZatPoint(trX, trY);
|
||||
|
||||
highslope = FixedDiv (ff_top - sightzstart, in->frac);
|
||||
lowslope = FixedDiv (ff_bottom - sightzstart, in->frac);
|
||||
|
||||
if (highslope>=topslope)
|
||||
{
|
||||
// blocks completely
|
||||
if (lowslope<=bottomslope) return false;
|
||||
// blocks upper edge of view
|
||||
if (lowslope<topslope) topslope=lowslope;
|
||||
}
|
||||
else if (lowslope<=bottomslope)
|
||||
{
|
||||
// blocks lower edge of view
|
||||
if (highslope>bottomslope) bottomslope=highslope;
|
||||
}
|
||||
else
|
||||
{
|
||||
// the 3D-floor is inside the viewing cone but neither clips the top nor the bottom so by
|
||||
// itself it can't be view blocking.
|
||||
// However, if there's a 3D-floor on the other side that obstructs the same vertical range
|
||||
// the 2 together will block sight.
|
||||
sector_t * sb=i==2? li->frontsector:li->backsector;
|
||||
|
||||
for(unsigned int k=0;k<sb->e->XFloor.ffloors.Size();k++)
|
||||
{
|
||||
F3DFloor* rover2=sb->e->XFloor.ffloors[k];
|
||||
|
||||
if((rover2->flags & FF_SEETHROUGH) == myseethrough || !(rover2->flags & FF_EXISTS)) continue;
|
||||
|
||||
fixed_t ffb_bottom=rover2->bottom.plane->ZatPoint(trX, trY);
|
||||
fixed_t ffb_top=rover2->top.plane->ZatPoint(trX, trY);
|
||||
|
||||
if (ffb_bottom >= ff_bottom && ffb_bottom<=ff_top ||
|
||||
ffb_top <= ff_top && ffb_top >= ff_bottom ||
|
||||
ffb_top >= ff_top && ffb_bottom <= ff_bottom ||
|
||||
ffb_top <= ff_top && ffb_bottom >= ff_bottom)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
// trace is leaving a sector with a 3d-floor
|
||||
if (s==lastsector && frontflag==i-1)
|
||||
{
|
||||
// upper slope intersects with this 3d-floor
|
||||
if (lastztop<=ff_bottom && topz>ff_top)
|
||||
{
|
||||
topslope=lowslope;
|
||||
}
|
||||
// lower slope intersects with this 3d-floor
|
||||
if (lastzbottom>=ff_top && bottomz<ff_top)
|
||||
{
|
||||
bottomslope=highslope;
|
||||
}
|
||||
}
|
||||
if (topslope <= bottomslope) return false; // stop
|
||||
}
|
||||
}
|
||||
lastsector = frontflag==0 ? li->backsector : li->frontsector;
|
||||
}
|
||||
else lastsector=NULL; // don't need it if there are no 3D-floors
|
||||
|
||||
lastztop= FixedMul (topslope, in->frac) + sightzstart;
|
||||
lastzbottom= FixedMul (bottomslope, in->frac) + sightzstart;
|
||||
#endif
|
||||
|
||||
return true; // keep going
|
||||
}
|
||||
|
||||
|
@ -102,7 +226,7 @@ static bool PTR_SightTraverse (intercept_t *in)
|
|||
===================
|
||||
*/
|
||||
|
||||
static bool P_SightCheckLine (line_t *ld)
|
||||
bool SightCheck::P_SightCheckLine (line_t *ld)
|
||||
{
|
||||
divline_t dl;
|
||||
|
||||
|
@ -123,7 +247,7 @@ static bool P_SightCheckLine (line_t *ld)
|
|||
return true; // line isn't crossed
|
||||
}
|
||||
|
||||
// try to early out the check
|
||||
// try to early out the check
|
||||
if (!ld->backsector || !(ld->flags & ML_TWOSIDED))
|
||||
return false; // stop checking
|
||||
|
||||
|
@ -156,7 +280,7 @@ static bool P_SightCheckLine (line_t *ld)
|
|||
}
|
||||
|
||||
sightcounts[3]++;
|
||||
// store the line for later intersection testing
|
||||
// store the line for later intersection testing
|
||||
intercept_t newintercept;
|
||||
newintercept.isaline = true;
|
||||
newintercept.d.line = ld;
|
||||
|
@ -173,7 +297,7 @@ static bool P_SightCheckLine (line_t *ld)
|
|||
===================
|
||||
*/
|
||||
|
||||
static bool P_SightBlockLinesIterator (int x, int y)
|
||||
bool SightCheck::P_SightBlockLinesIterator (int x, int y)
|
||||
{
|
||||
int offset;
|
||||
int *list;
|
||||
|
@ -222,12 +346,12 @@ static bool P_SightBlockLinesIterator (int x, int y)
|
|||
====================
|
||||
*/
|
||||
|
||||
static bool P_SightTraverseIntercepts ()
|
||||
bool SightCheck::P_SightTraverseIntercepts ()
|
||||
{
|
||||
size_t count;
|
||||
unsigned count;
|
||||
fixed_t dist;
|
||||
intercept_t *scan, *in;
|
||||
unsigned int scanpos;
|
||||
unsigned scanpos;
|
||||
divline_t dl;
|
||||
|
||||
count = intercepts.Size ();
|
||||
|
@ -269,6 +393,29 @@ static bool P_SightTraverseIntercepts ()
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef _3DFLOORS
|
||||
if (lastsector==seeingthing->Sector && lastsector->e->XFloor.ffloors.Size())
|
||||
{
|
||||
// we must do one last check whether the trace has crossed a 3D floor in the last sector
|
||||
|
||||
fixed_t topz= topslope + sightzstart;
|
||||
fixed_t bottomz= bottomslope + sightzstart;
|
||||
|
||||
for(unsigned int i=0;i<lastsector->e->XFloor.ffloors.Size();i++)
|
||||
{
|
||||
F3DFloor* rover = lastsector->e->XFloor.ffloors[i];
|
||||
|
||||
if((rover->flags & FF_SOLID) == myseethrough || !(rover->flags & FF_EXISTS)) continue;
|
||||
|
||||
fixed_t ff_bottom=rover->bottom.plane->ZatPoint(seeingthing->x, seeingthing->y);
|
||||
fixed_t ff_top=rover->top.plane->ZatPoint(seeingthing->x, seeingthing->y);
|
||||
|
||||
if (lastztop<=ff_bottom && topz>ff_bottom && lastzbottom<=ff_bottom && bottomz>ff_bottom) return false;
|
||||
if (lastzbottom>=ff_top && bottomz<ff_top && lastztop>=ff_top && topz<ff_top) return false;
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
return true; // everything was traversed
|
||||
}
|
||||
|
||||
|
@ -284,7 +431,7 @@ static bool P_SightTraverseIntercepts ()
|
|||
==================
|
||||
*/
|
||||
|
||||
static bool P_SightPathTraverse (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2)
|
||||
bool SightCheck::P_SightPathTraverse (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2)
|
||||
{
|
||||
fixed_t xt1,yt1,xt2,yt2;
|
||||
fixed_t xstep,ystep;
|
||||
|
@ -296,6 +443,27 @@ static bool P_SightPathTraverse (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2)
|
|||
validcount++;
|
||||
intercepts.Clear ();
|
||||
|
||||
#ifdef _3DFLOORS
|
||||
// for FF_SEETHROUGH the following rule applies:
|
||||
// If the viewer is in an area without FF_SEETHROUGH he can only see into areas without this flag
|
||||
// If the viewer is in an area with FF_SEETHROUGH he can only see into areas with this flag
|
||||
for(unsigned int i=0;i<lastsector->e->XFloor.ffloors.Size();i++)
|
||||
{
|
||||
F3DFloor* rover = lastsector->e->XFloor.ffloors[i];
|
||||
|
||||
if(!(rover->flags & FF_EXISTS)) continue;
|
||||
|
||||
fixed_t ff_bottom=rover->bottom.plane->ZatPoint(sightthing->x, sightthing->y);
|
||||
fixed_t ff_top=rover->top.plane->ZatPoint(sightthing->x, sightthing->y);
|
||||
|
||||
if (sightzstart < ff_top && sightzstart >= ff_bottom)
|
||||
{
|
||||
myseethrough = rover->flags & FF_SEETHROUGH;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( ((x1-bmaporgx)&(MAPBLOCKSIZE-1)) == 0)
|
||||
x1 += FRACUNIT; // don't side exactly on a line
|
||||
if ( ((y1-bmaporgy)&(MAPBLOCKSIZE-1)) == 0)
|
||||
|
@ -535,16 +703,10 @@ sightcounts[0]++;
|
|||
// Now look from eyes of t1 to any part of t2.
|
||||
|
||||
validcount++;
|
||||
|
||||
sightzstart = t1->z + t1->height - (t1->height>>2);
|
||||
bottomslope = t2->z - sightzstart;
|
||||
topslope = bottomslope + t2->height;
|
||||
|
||||
SeePastBlockEverything = flags & 6;
|
||||
SeePastShootableLines = flags & 4;
|
||||
res = P_SightPathTraverse (t1->x, t1->y, t2->x, t2->y);
|
||||
SeePastBlockEverything = 0;
|
||||
SeePastShootableLines = 0;
|
||||
{
|
||||
SightCheck s(t1, t2, flags);
|
||||
res = s.P_SightPathTraverse (t1->x, t1->y, t2->x, t2->y);
|
||||
}
|
||||
|
||||
done:
|
||||
SightCycles.Unclock();
|
||||
|
@ -573,3 +735,5 @@ void P_ResetSightCounters (bool full)
|
|||
SightCycles.Reset();
|
||||
memset (sightcounts, 0, sizeof(sightcounts));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -387,18 +387,22 @@ bool P_TestActivateLine (line_t *line, AActor *mo, int side, int activationType)
|
|||
// Called every tic frame
|
||||
// that the player origin is in a special sector
|
||||
//
|
||||
void P_PlayerInSpecialSector (player_t *player)
|
||||
void P_PlayerInSpecialSector (player_t *player, sector_t * sector)
|
||||
{
|
||||
sector_t *sector = player->mo->Sector;
|
||||
int special = sector->special & ~SECRET_MASK;
|
||||
|
||||
// Falling, not all the way down yet?
|
||||
if (player->mo->z != sector->floorplane.ZatPoint (player->mo->x, player->mo->y)
|
||||
&& !player->mo->waterlevel)
|
||||
if (sector == NULL)
|
||||
{
|
||||
return;
|
||||
// Falling, not all the way down yet?
|
||||
sector = player->mo->Sector;
|
||||
if (player->mo->z != sector->floorplane.ZatPoint (player->mo->x, player->mo->y)
|
||||
&& !player->mo->waterlevel)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int special = sector->special & ~SECRET_MASK;
|
||||
|
||||
// Has hit ground.
|
||||
AInventory *ironfeet;
|
||||
|
||||
|
|
|
@ -182,7 +182,7 @@ void P_UpdateSpecials (void);
|
|||
bool P_ActivateLine (line_t *ld, AActor *mo, int side, int activationType);
|
||||
bool P_TestActivateLine (line_t *ld, AActor *mo, int side, int activationType);
|
||||
|
||||
void P_PlayerInSpecialSector (player_t *player);
|
||||
void P_PlayerInSpecialSector (player_t *player, sector_t * sector=NULL);
|
||||
void P_PlayerOnSpecialFlat (player_t *player, int floorType);
|
||||
|
||||
void P_SetSectorFriction (int tag, int amount, bool alterFlag);
|
||||
|
|
228
src/p_trace.cpp
228
src/p_trace.cpp
|
@ -50,6 +50,13 @@ struct FTraceInfo
|
|||
fixed_t EnterDist;
|
||||
bool (*TraceCallback)(FTraceResults &res);
|
||||
DWORD TraceFlags;
|
||||
int inshootthrough;
|
||||
|
||||
// These are required for 3D-floor checking
|
||||
// to create a fake sector with a floor
|
||||
// or ceiling plane coming from a 3D-floor
|
||||
sector_t DummySector[2];
|
||||
int sectorsel;
|
||||
|
||||
bool TraceTraverse (int ptflags);
|
||||
bool CheckSectorPlane (const sector_t *sector, bool checkFloor);
|
||||
|
@ -85,27 +92,121 @@ bool Trace (fixed_t x, fixed_t y, fixed_t z, sector_t *sector,
|
|||
inf.TraceFlags = flags;
|
||||
res.CrossedWater = NULL;
|
||||
inf.Results = &res;
|
||||
inf.inshootthrough = true;
|
||||
|
||||
res.HitType = TRACE_HitNone;
|
||||
|
||||
// Do a 3D floor check in the starting sector
|
||||
memset(&res, 0, sizeof(res));
|
||||
inf.sectorsel=0;
|
||||
|
||||
#ifdef _3DFLOORS
|
||||
TDeletingArray<F3DFloor*> &ff = sector->e->XFloor.ffloors;
|
||||
|
||||
if (ff.Size())
|
||||
{
|
||||
memcpy(&inf.DummySector[0],sector,sizeof(sector_t));
|
||||
inf.CurSector=sector=&inf.DummySector[0];
|
||||
inf.sectorsel=1;
|
||||
fixed_t bf = sector->floorplane.ZatPoint (x, y);
|
||||
fixed_t bc = sector->ceilingplane.ZatPoint (x, y);
|
||||
|
||||
for(unsigned int i=0;i<ff.Size();i++)
|
||||
{
|
||||
F3DFloor * rover=ff[i];
|
||||
|
||||
if (!(rover->flags&FF_SHOOTTHROUGH) && rover->flags&FF_EXISTS)
|
||||
{
|
||||
fixed_t ff_bottom=rover->bottom.plane->ZatPoint(x, y);
|
||||
fixed_t ff_top=rover->top.plane->ZatPoint(x, y);
|
||||
// clip to the part of the sector we are in
|
||||
if (z>ff_top)
|
||||
{
|
||||
// above
|
||||
if (bf<ff_top)
|
||||
{
|
||||
sector->floorplane=*rover->top.plane;
|
||||
sector->SetTexture(sector_t::floor, *rover->top.texture, false);
|
||||
bf=ff_top;
|
||||
}
|
||||
}
|
||||
else if (z<ff_bottom)
|
||||
{
|
||||
//below
|
||||
if (bc>ff_bottom)
|
||||
{
|
||||
sector->ceilingplane=*rover->bottom.plane;
|
||||
sector->SetTexture(sector_t::ceiling, *rover->bottom.texture, false);
|
||||
bc=ff_bottom;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// inside
|
||||
if (bf<ff_bottom)
|
||||
{
|
||||
sector->floorplane=*rover->bottom.plane;
|
||||
sector->SetTexture(sector_t::floor, *rover->bottom.texture, false);
|
||||
bf=ff_bottom;
|
||||
}
|
||||
|
||||
if (bc>ff_top)
|
||||
{
|
||||
sector->ceilingplane=*rover->top.plane;
|
||||
sector->SetTexture(sector_t::ceiling, *rover->top.texture, false);
|
||||
bc=ff_top;
|
||||
}
|
||||
inf.inshootthrough = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// check for overflows and clip if necessary
|
||||
SQWORD xd= (SQWORD)x + ( ( SQWORD(vx) * SQWORD(maxDist) )>>16);
|
||||
|
||||
if (xd>SQWORD(32767)*FRACUNIT)
|
||||
{
|
||||
maxDist = inf.MaxDist=FixedDiv(FIXED_MAX-x,vx);
|
||||
}
|
||||
else if (xd<-SQWORD(32767)*FRACUNIT)
|
||||
{
|
||||
maxDist = inf.MaxDist=FixedDiv(FIXED_MIN-x,vx);
|
||||
}
|
||||
|
||||
|
||||
SQWORD yd= (SQWORD)y + ( ( SQWORD(vy) * SQWORD(maxDist) )>>16);
|
||||
|
||||
if (yd>SQWORD(32767)*FRACUNIT)
|
||||
{
|
||||
maxDist = inf.MaxDist=FixedDiv(FIXED_MAX-y,vy);
|
||||
}
|
||||
else if (yd<-SQWORD(32767)*FRACUNIT)
|
||||
{
|
||||
maxDist = inf.MaxDist=FixedDiv(FIXED_MIN-y,vy);
|
||||
}
|
||||
|
||||
// recalculate the trace's end points for robustness
|
||||
if (inf.TraceTraverse (ptflags))
|
||||
{ // check for intersection with floor/ceiling
|
||||
res.Sector = inf.CurSector;
|
||||
res.Sector = §ors[inf.CurSector->sectornum];
|
||||
|
||||
if (inf.CheckSectorPlane (inf.CurSector, true))
|
||||
{
|
||||
res.HitType = TRACE_HitFloor;
|
||||
res.HitTexture = inf.CurSector->GetTexture(sector_t::floor);
|
||||
if (res.CrossedWater == NULL &&
|
||||
inf.CurSector->heightsec != NULL &&
|
||||
inf.CurSector->heightsec->floorplane.ZatPoint (res.X, res.Y) >= res.Z)
|
||||
{
|
||||
res.CrossedWater = inf.CurSector;
|
||||
res.CrossedWater = §ors[inf.CurSector->sectornum];
|
||||
}
|
||||
}
|
||||
else if (inf.CheckSectorPlane (inf.CurSector, false))
|
||||
{
|
||||
res.HitType = TRACE_HitCeiling;
|
||||
res.HitTexture = inf.CurSector->GetTexture(sector_t::ceiling);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -154,11 +255,12 @@ bool FTraceInfo::TraceTraverse (int ptflags)
|
|||
|
||||
fixed_t ff, fc, bf = 0, bc = 0;
|
||||
|
||||
if (in->d.line->frontsector == CurSector)
|
||||
// CurSector may be a copy so we must compare the sector number, not the index!
|
||||
if (in->d.line->frontsector->sectornum == CurSector->sectornum)
|
||||
{
|
||||
lineside = 0;
|
||||
}
|
||||
else if (in->d.line->backsector == CurSector)
|
||||
else if (in->d.line->backsector && in->d.line->backsector->sectornum == CurSector->sectornum)
|
||||
{
|
||||
lineside = 1;
|
||||
}
|
||||
|
@ -202,22 +304,24 @@ bool FTraceInfo::TraceTraverse (int ptflags)
|
|||
}
|
||||
|
||||
if (Results->CrossedWater == NULL &&
|
||||
CurSector->heightsec &&
|
||||
CurSector->heightsec &&
|
||||
!(CurSector->MoreFlags & SECF_IGNOREHEIGHTSEC) &&
|
||||
//CurSector->heightsec->waterzone &&
|
||||
hitz <= CurSector->heightsec->floorplane.ZatPoint (hitx, hity))
|
||||
{
|
||||
// hit crossed a water plane
|
||||
Results->CrossedWater = CurSector;
|
||||
Results->CrossedWater = §ors[CurSector->sectornum];
|
||||
}
|
||||
|
||||
if (hitz <= ff)
|
||||
{ // hit floor in front of wall
|
||||
Results->HitType = TRACE_HitFloor;
|
||||
Results->HitTexture = CurSector->GetTexture(sector_t::floor);
|
||||
}
|
||||
else if (hitz >= fc)
|
||||
{ // hit ceiling in front of wall
|
||||
Results->HitType = TRACE_HitCeiling;
|
||||
Results->HitTexture = CurSector->GetTexture(sector_t::ceiling);
|
||||
}
|
||||
else if (entersector == NULL ||
|
||||
hitz <= bf || hitz >= bc ||
|
||||
|
@ -234,7 +338,65 @@ bool FTraceInfo::TraceTraverse (int ptflags)
|
|||
}
|
||||
}
|
||||
else
|
||||
{ // made it past the wall
|
||||
{ // made it past the wall
|
||||
#ifdef _3DFLOORS
|
||||
// check for 3D floors first
|
||||
if (entersector->e->XFloor.ffloors.Size())
|
||||
{
|
||||
memcpy(&DummySector[sectorsel],entersector,sizeof(sector_t));
|
||||
entersector=&DummySector[sectorsel];
|
||||
sectorsel^=1;
|
||||
|
||||
for(unsigned int i=0;i<entersector->e->XFloor.ffloors.Size();i++)
|
||||
{
|
||||
F3DFloor * rover=entersector->e->XFloor.ffloors[i];
|
||||
int entershootthrough = !!(rover->flags&FF_SHOOTTHROUGH);
|
||||
|
||||
if (entershootthrough != inshootthrough && rover->flags&FF_EXISTS)
|
||||
{
|
||||
fixed_t ff_bottom=rover->bottom.plane->ZatPoint(hitx, hity);
|
||||
fixed_t ff_top=rover->top.plane->ZatPoint(hitx, hity);
|
||||
|
||||
// clip to the part of the sector we are in
|
||||
if (hitz>ff_top)
|
||||
{
|
||||
// above
|
||||
if (bf<ff_top)
|
||||
{
|
||||
entersector->floorplane=*rover->top.plane;
|
||||
entersector->SetTexture(sector_t::floor, *rover->top.texture, false);
|
||||
bf=ff_top;
|
||||
}
|
||||
}
|
||||
else if (hitz<ff_bottom)
|
||||
{
|
||||
//below
|
||||
if (bc>ff_bottom)
|
||||
{
|
||||
entersector->ceilingplane=*rover->bottom.plane;
|
||||
entersector->SetTexture(sector_t::ceiling, *rover->bottom.texture, false);
|
||||
bc=ff_bottom;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//hit the edge - equivalent to hitting the wall
|
||||
Results->HitType = TRACE_HitWall;
|
||||
Results->Tier = TIER_FFloor;
|
||||
Results->ffloor = rover;
|
||||
if ((TraceFlags & TRACE_Impact) && in->d.line->special)
|
||||
{
|
||||
P_ActivateLine (in->d.line, IgnoreThis, lineside, SPAC_Impact);
|
||||
}
|
||||
goto cont;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
Results->HitType = TRACE_HitNone;
|
||||
if (TraceFlags & TRACE_PCross)
|
||||
{
|
||||
|
@ -246,11 +408,14 @@ bool FTraceInfo::TraceTraverse (int ptflags)
|
|||
P_ActivateLine (in->d.line, IgnoreThis, lineside, SPAC_Impact);
|
||||
}
|
||||
}
|
||||
#ifdef _3DFLOORS
|
||||
cont:
|
||||
#endif
|
||||
|
||||
if (Results->HitType != TRACE_HitNone)
|
||||
{
|
||||
// We hit something, so figure out where exactly
|
||||
Results->Sector = CurSector;
|
||||
Results->Sector = §ors[CurSector->sectornum];
|
||||
|
||||
if (Results->HitType != TRACE_HitWall &&
|
||||
!CheckSectorPlane (CurSector, Results->HitType == TRACE_HitFloor))
|
||||
|
@ -357,6 +522,41 @@ bool FTraceInfo::TraceTraverse (int ptflags)
|
|||
abs(hity - in->d.thing->y) > in->d.thing->radius) continue;
|
||||
}
|
||||
|
||||
// check for extrafloors first
|
||||
if (CurSector->e->XFloor.ffloors.Size())
|
||||
{
|
||||
fixed_t ff_floor=CurSector->floorplane.ZatPoint(hitx, hity);
|
||||
fixed_t ff_ceiling=CurSector->ceilingplane.ZatPoint(hitx, hity);
|
||||
|
||||
if (hitz>ff_ceiling) // actor is hit above the current ceiling
|
||||
{
|
||||
Results->HitType=TRACE_HitCeiling;
|
||||
Results->HitTexture = CurSector->GetTexture(sector_t::ceiling);
|
||||
}
|
||||
else if (hitz<ff_floor) // actor is hit below the current floor
|
||||
{
|
||||
Results->HitType=TRACE_HitFloor;
|
||||
Results->HitTexture = CurSector->GetTexture(sector_t::floor);
|
||||
}
|
||||
else goto cont1;
|
||||
|
||||
// the trace hit a 3D-floor before the thing.
|
||||
// Calculate an intersection and abort.
|
||||
Results->Sector = §ors[CurSector->sectornum];
|
||||
if (!CheckSectorPlane(CurSector, Results->HitType==TRACE_HitFloor))
|
||||
{
|
||||
Results->HitType=TRACE_HitNone;
|
||||
}
|
||||
if (TraceCallback != NULL)
|
||||
{
|
||||
return TraceCallback (*Results);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
cont1:
|
||||
|
||||
Results->HitType = TRACE_HitActor;
|
||||
Results->X = hitx;
|
||||
|
@ -418,17 +618,9 @@ static bool EditTraceResult (DWORD flags, FTraceResults &res)
|
|||
{
|
||||
if (flags & TRACE_NoSky)
|
||||
{ // Throw away sky hits
|
||||
if (res.HitType == TRACE_HitFloor)
|
||||
if (res.HitType == TRACE_HitFloor || res.HitType == TRACE_HitCeiling)
|
||||
{
|
||||
if (res.Sector->GetTexture(sector_t::floor) == skyflatnum)
|
||||
{
|
||||
res.HitType = TRACE_HitNone;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (res.HitType == TRACE_HitCeiling)
|
||||
{
|
||||
if (res.Sector->GetTexture(sector_t::ceiling) == skyflatnum)
|
||||
if (res.HitTexture == skyflatnum)
|
||||
{
|
||||
res.HitType = TRACE_HitNone;
|
||||
return false;
|
||||
|
|
|
@ -35,11 +35,12 @@
|
|||
#define __P_TRACE_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include "basictypes.h"
|
||||
#include "textures/textures.h"
|
||||
|
||||
struct sector_t;
|
||||
struct line_t;
|
||||
class AActor;
|
||||
struct F3DFloor;
|
||||
|
||||
enum ETraceResult
|
||||
{
|
||||
|
@ -54,12 +55,14 @@ enum
|
|||
{
|
||||
TIER_Middle,
|
||||
TIER_Upper,
|
||||
TIER_Lower
|
||||
TIER_Lower,
|
||||
TIER_FFloor,
|
||||
};
|
||||
|
||||
struct FTraceResults
|
||||
{
|
||||
sector_t *Sector;
|
||||
FTextureID HitTexture;
|
||||
fixed_t X, Y, Z;
|
||||
fixed_t Distance;
|
||||
fixed_t Fraction;
|
||||
|
@ -71,6 +74,7 @@ struct FTraceResults
|
|||
BYTE Tier;
|
||||
ETraceResult HitType;
|
||||
sector_t *CrossedWater;
|
||||
F3DFloor * ffloor;
|
||||
};
|
||||
|
||||
enum
|
||||
|
|
|
@ -2199,6 +2199,7 @@ void P_PlayerThink (player_t *player)
|
|||
|
||||
if (!(player->cheats & CF_PREDICTING))
|
||||
{
|
||||
P_PlayerOnSpecial3DFloor (player);
|
||||
if (player->mo->Sector->special || player->mo->Sector->damage)
|
||||
{
|
||||
P_PlayerInSpecialSector (player);
|
||||
|
|
11
src/r_defs.h
11
src/r_defs.h
|
@ -229,6 +229,7 @@ inline FArchive &operator<< (FArchive &arc, secplane_t &plane)
|
|||
return arc;
|
||||
}
|
||||
|
||||
#include "p_3dfloors.h"
|
||||
// Ceiling/floor flags
|
||||
enum
|
||||
{
|
||||
|
@ -319,6 +320,14 @@ struct extsector_t
|
|||
TArray<FLinkedSector> Sectors;
|
||||
} Floor, Ceiling;
|
||||
} Linked;
|
||||
|
||||
// 3D floors
|
||||
struct xfloor
|
||||
{
|
||||
TDeletingArray<F3DFloor *> ffloors; // 3D floors in this sector
|
||||
TArray<lightlist_t> lightlist; // 3D light list
|
||||
TArray<sector_t*> attached; // 3D floors attached to this sector
|
||||
} XFloor;
|
||||
|
||||
void Serialize(FArchive &arc);
|
||||
};
|
||||
|
@ -600,6 +609,7 @@ struct sector_t
|
|||
|
||||
vertex_t *Triangle[3]; // Three points that can define a plane
|
||||
short oldspecial; //jff 2/16/98 remembers if sector WAS secret (automap)
|
||||
int sectornum; // for comparing sector copies
|
||||
|
||||
extsector_t * e; // This stores data that requires construction/destruction. Such data must not be copied by R_FakeFlat.
|
||||
};
|
||||
|
@ -742,7 +752,6 @@ struct line_t
|
|||
slopetype_t slopetype; // To aid move clipping.
|
||||
sector_t *frontsector, *backsector;
|
||||
int validcount; // if == validcount, already checked
|
||||
|
||||
};
|
||||
|
||||
// phares 3/14/98
|
||||
|
|
|
@ -29,6 +29,7 @@ static const struct {
|
|||
int code;
|
||||
const char *name;
|
||||
} sigill_codes[] = {
|
||||
#ifndef __FreeBSD__
|
||||
{ ILL_ILLOPC, "Illegal opcode" },
|
||||
{ ILL_ILLOPN, "Illegal operand" },
|
||||
{ ILL_ILLADR, "Illegal addressing mode" },
|
||||
|
@ -37,6 +38,7 @@ static const struct {
|
|||
{ ILL_PRVREG, "Privileged register" },
|
||||
{ ILL_COPROC, "Coprocessor error" },
|
||||
{ ILL_BADSTK, "Internal stack error" },
|
||||
#endif
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
|
@ -59,8 +61,10 @@ static const struct {
|
|||
int code;
|
||||
const char *name;
|
||||
} sigsegv_codes[] = {
|
||||
#ifndef __FreeBSD__
|
||||
{ SEGV_MAPERR, "Address not mapped to object" },
|
||||
{ SEGV_ACCERR, "Invalid permissions for mapped object" },
|
||||
#endif
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
|
@ -68,9 +72,11 @@ static const struct {
|
|||
int code;
|
||||
const char *name;
|
||||
} sigbus_codes[] = {
|
||||
#ifndef __FreeBSD__
|
||||
{ BUS_ADRALN, "Invalid address alignment" },
|
||||
{ BUS_ADRERR, "Non-existent physical address" },
|
||||
{ BUS_OBJERR, "Object specific hardware error" },
|
||||
#endif
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
|
@ -176,7 +182,9 @@ static void crash_catcher(int signum, siginfo_t *siginfo, void *context)
|
|||
const char *sigdesc = NULL;
|
||||
pid_t pid, dbg_pid;
|
||||
struct stat sbuf;
|
||||
#ifndef __FreeBSD__
|
||||
struct rlimit rl;
|
||||
#endif
|
||||
int status, i;
|
||||
FILE *f;
|
||||
|
||||
|
@ -374,7 +382,12 @@ int cc_install_handlers(int num_signals, int *signals, const char *logfile, int
|
|||
memset(&sa, 0, sizeof(sa));
|
||||
|
||||
sa.sa_sigaction = crash_catcher;
|
||||
|
||||
#ifndef __FreeBSD__
|
||||
sa.sa_flags = SA_ONESHOT | SA_NODEFER | SA_SIGINFO;
|
||||
#else
|
||||
sa.sa_flags = SA_NODEFER | SA_SIGINFO;
|
||||
#endif
|
||||
|
||||
cc_logfile = logfile;
|
||||
cc_user_info = user_info;
|
||||
|
|
|
@ -736,6 +736,10 @@
|
|||
RelativePath=".\src\nodebuild_utility.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\p_3dfloors.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\p_3dmidtex.cpp"
|
||||
>
|
||||
|
@ -1377,6 +1381,10 @@
|
|||
RelativePath=".\src\nodebuild.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\p_3dfloors.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\p_3dmidtex.h"
|
||||
>
|
||||
|
|
Loading…
Reference in a new issue