diff --git a/docs/rh-log.txt b/docs/rh-log.txt index f5a202572..99967035f 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -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. diff --git a/src/d_net.cpp b/src/d_net.cpp index 3da985425..89c4043c0 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -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); } } } diff --git a/src/g_level.cpp b/src/g_level.cpp index 5d1d337c0..bda4858cc 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -2879,6 +2879,10 @@ void G_SerializeLevel (FArchive &arc, bool hubLoad) P_SerializePlayers (arc, hubLoad); P_SerializeSounds (arc); + if (arc.IsLoading()) for(i=0;iGetPlaneTexZ(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 diff --git a/src/g_shared/a_sharedglobal.h b/src/g_shared/a_sharedglobal.h index 509da8cf9..6afebfef5 100644 --- a/src/g_shared/a_sharedglobal.h +++ b/src/g_shared/a_sharedglobal.h @@ -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: diff --git a/src/p_3dfloors.cpp b/src/p_3dfloors.cpp new file mode 100644 index 000000000..73ace9820 --- /dev/null +++ b/src/p_3dfloors.cpp @@ -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;ilinecount;i++) + { + line_t * l=sec->lines[i]; + + alpha=255; + if (l->special==Sector_SetContents && l->frontsector==sec) + { + alpha=clamp(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;ie->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;ie->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;ie->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 & ffloors=sector->e->XFloor.ffloors; + TArray & 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 oldlist; + + oldlist = ffloors; + ffloors.Clear(); + + // first delete the old dynamic stuff + for(i=0;iflags&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;jtop.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_bottomflags|=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_bottomtoplightlevel; + 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 &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;iffloors.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;ispecial) + { + 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 \ No newline at end of file diff --git a/src/p_3dfloors.h b/src/p_3dfloors.h new file mode 100644 index 000000000..df83808ed --- /dev/null +++ b/src/p_3dfloors.h @@ -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 \ No newline at end of file diff --git a/src/p_local.h b/src/p_local.h index b114866d7..31d5ee79e 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -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); //---------------------------------------------------------------------------------- // diff --git a/src/p_map.cpp b/src/p_map.cpp index d7d0b34a0..9e3b79dae 100644 --- a/src/p_map.cpp +++ b/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;iSector->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;ie->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 (newfrictionmodel); + } + } +#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;ie->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;ifloorsector->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;iSector->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;ke->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 (highpitchtop.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 (thingtoppitchtoppitch) toppitch=thingbottompitch; + } + else if (thingbottompitch>bottompitch) + { + if (thingtoppitchpitch; + +#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;iSector->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; diff --git a/src/p_maputl.cpp b/src/p_maputl.cpp index b1e0ebcd8..6ad565f1b 100644 --- a/src/p_maputl.cpp +++ b/src/p_maputl.cpp @@ -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) { diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 5e87f1d9e..853d21d3e 100644 --- a/src/p_mobj.cpp +++ b/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;iflags&(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;iSector->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;ie->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;ie->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;ie->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;im_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 && diff --git a/src/p_setup.cpp b/src/p_setup.cpp index f7bd83635..6ae1739d1 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -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(); diff --git a/src/p_sight.cpp b/src/p_sight.cpp index 3076040a3..19a5e68ef 100644 --- a/src/p_sight.cpp +++ b/src/p_sight.cpp @@ -37,19 +37,47 @@ This uses specialized forms of the maputils routines for optimized performance ============================================================================== */ -static TArray 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 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;je->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 (lowslopebottomslope) 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;ke->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 && bottomzbacksector : 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;ie->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 && topze->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)); } + + diff --git a/src/p_spec.cpp b/src/p_spec.cpp index 175c4e214..f128e812f 100644 --- a/src/p_spec.cpp +++ b/src/p_spec.cpp @@ -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; diff --git a/src/p_spec.h b/src/p_spec.h index e79bd0306..26fcb4f27 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -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); diff --git a/src/p_trace.cpp b/src/p_trace.cpp index d1989c058..11ecf2c90 100644 --- a/src/p_trace.cpp +++ b/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 &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;iflags&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 (bffloorplane=*rover->top.plane; + sector->SetTexture(sector_t::floor, *rover->top.texture, false); + bf=ff_top; + } + } + else if (zff_bottom) + { + sector->ceilingplane=*rover->bottom.plane; + sector->SetTexture(sector_t::ceiling, *rover->bottom.texture, false); + bc=ff_bottom; + } + } + else + { + // inside + if (bffloorplane=*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;ie->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 (bffloorplane=*rover->top.plane; + entersector->SetTexture(sector_t::floor, *rover->top.texture, false); + bf=ff_top; + } + } + else if (hitzff_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 (hitzHitType=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; diff --git a/src/p_trace.h b/src/p_trace.h index be3dda84e..e13a7f905 100644 --- a/src/p_trace.h +++ b/src/p_trace.h @@ -35,11 +35,12 @@ #define __P_TRACE_H__ #include -#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 diff --git a/src/p_user.cpp b/src/p_user.cpp index 413f67e64..449fc76d2 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -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); diff --git a/src/r_defs.h b/src/r_defs.h index 2b9528e4a..14bd40eca 100644 --- a/src/r_defs.h +++ b/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 Sectors; } Floor, Ceiling; } Linked; + + // 3D floors + struct xfloor + { + TDeletingArray ffloors; // 3D floors in this sector + TArray lightlist; // 3D light list + TArray 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 diff --git a/src/sdl/crashcatcher.c b/src/sdl/crashcatcher.c index b6c1d7a84..f1d5f26cd 100644 --- a/src/sdl/crashcatcher.c +++ b/src/sdl/crashcatcher.c @@ -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; diff --git a/zdoom.vcproj b/zdoom.vcproj index f18aab9a0..d6aced38e 100644 --- a/zdoom.vcproj +++ b/zdoom.vcproj @@ -736,6 +736,10 @@ RelativePath=".\src\nodebuild_utility.cpp" > + + @@ -1377,6 +1381,10 @@ RelativePath=".\src\nodebuild.h" > + +