mirror of
https://git.do.srb2.org/KartKrew/Kart-Public.git
synced 2024-12-27 04:41:23 +00:00
port P_CheckSight from vanilla
mostly a copy/paste job, this fixes issues with certain sloped surfaces improperly obstructing sight (ported files from srb2 commit 4c9b83b6bdd8cd3e2626505940de75668e3db0c2)
This commit is contained in:
parent
fd88c139a6
commit
a88c115b84
3 changed files with 137 additions and 22 deletions
127
src/p_sight.c
127
src/p_sight.c
|
@ -2,7 +2,7 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||||
// Copyright (C) 1999-2018 by Sonic Team Junior.
|
// Copyright (C) 1999-2021 by Sonic Team Junior.
|
||||||
//
|
//
|
||||||
// This program is free software distributed under the
|
// This program is free software distributed under the
|
||||||
// terms of the GNU General Public License, version 2.
|
// terms of the GNU General Public License, version 2.
|
||||||
|
@ -14,6 +14,7 @@
|
||||||
#include "doomdef.h"
|
#include "doomdef.h"
|
||||||
#include "doomstat.h"
|
#include "doomstat.h"
|
||||||
#include "p_local.h"
|
#include "p_local.h"
|
||||||
|
#include "p_slopes.h"
|
||||||
#include "r_main.h"
|
#include "r_main.h"
|
||||||
#include "r_state.h"
|
#include "r_state.h"
|
||||||
|
|
||||||
|
@ -102,12 +103,20 @@ static fixed_t P_InterceptVector2(divline_t *v2, divline_t *v1)
|
||||||
static boolean P_CrossSubsecPolyObj(polyobj_t *po, register los_t *los)
|
static boolean P_CrossSubsecPolyObj(polyobj_t *po, register los_t *los)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
|
sector_t *polysec;
|
||||||
|
|
||||||
|
if (!(po->flags & POF_RENDERALL))
|
||||||
|
return true; // the polyobject isn't visible, so we can ignore it
|
||||||
|
|
||||||
|
polysec = po->lines[0]->backsector;
|
||||||
|
|
||||||
for (i = 0; i < po->numLines; ++i)
|
for (i = 0; i < po->numLines; ++i)
|
||||||
{
|
{
|
||||||
line_t *line = po->lines[i];
|
line_t *line = po->lines[i];
|
||||||
divline_t divl;
|
divline_t divl;
|
||||||
const vertex_t *v1,*v2;
|
const vertex_t *v1,*v2;
|
||||||
|
fixed_t frac;
|
||||||
|
fixed_t topslope, bottomslope;
|
||||||
|
|
||||||
// already checked other side?
|
// already checked other side?
|
||||||
if (line->validcount == validcount)
|
if (line->validcount == validcount)
|
||||||
|
@ -139,7 +148,22 @@ static boolean P_CrossSubsecPolyObj(polyobj_t *po, register los_t *los)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// stop because it is not two sided
|
// stop because it is not two sided
|
||||||
return false;
|
//if (!(po->flags & POF_TESTHEIGHT))
|
||||||
|
//return false;
|
||||||
|
|
||||||
|
frac = P_InterceptVector2(&los->strace, &divl);
|
||||||
|
|
||||||
|
// get slopes of top and bottom of this polyobject line
|
||||||
|
topslope = FixedDiv(polysec->ceilingheight - los->sightzstart , frac);
|
||||||
|
bottomslope = FixedDiv(polysec->floorheight - los->sightzstart , frac);
|
||||||
|
|
||||||
|
if (topslope >= los->topslope && bottomslope <= los->bottomslope)
|
||||||
|
return false; // view completely blocked
|
||||||
|
|
||||||
|
// TODO: figure out if it's worth considering partially blocked cases or not?
|
||||||
|
// maybe to adjust los's top/bottom slopes if needed
|
||||||
|
//if (los->topslope <= los->bottomslope)
|
||||||
|
//return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -187,6 +211,8 @@ static boolean P_CrossSubsector(size_t num, register los_t *los)
|
||||||
const sector_t *front, *back;
|
const sector_t *front, *back;
|
||||||
const vertex_t *v1,*v2;
|
const vertex_t *v1,*v2;
|
||||||
fixed_t frac;
|
fixed_t frac;
|
||||||
|
fixed_t frontf, backf, frontc, backc;
|
||||||
|
fixed_t fracx, fracy;
|
||||||
|
|
||||||
// already checked other side?
|
// already checked other side?
|
||||||
if (line->validcount == validcount)
|
if (line->validcount == validcount)
|
||||||
|
@ -221,36 +247,44 @@ static boolean P_CrossSubsector(size_t num, register los_t *los)
|
||||||
if (!(line->flags & ML_TWOSIDED))
|
if (!(line->flags & ML_TWOSIDED))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// calculate fractional intercept (how far along we are divided by how far we are from t2)
|
||||||
|
frac = P_InterceptVector2(&los->strace, &divl);
|
||||||
|
|
||||||
|
front = seg->frontsector;
|
||||||
|
back = seg->backsector;
|
||||||
|
// calculate position at intercept
|
||||||
|
fracx = los->strace.x + FixedMul(los->strace.dx, frac);
|
||||||
|
fracy = los->strace.y + FixedMul(los->strace.dy, frac);
|
||||||
|
// calculate sector heights
|
||||||
|
frontf = P_GetSectorFloorZAt (front, fracx, fracy);
|
||||||
|
frontc = P_GetSectorCeilingZAt(front, fracx, fracy);
|
||||||
|
backf = P_GetSectorFloorZAt (back , fracx, fracy);
|
||||||
|
backc = P_GetSectorCeilingZAt(back , fracx, fracy);
|
||||||
// crosses a two sided line
|
// crosses a two sided line
|
||||||
// no wall to block sight with?
|
// no wall to block sight with?
|
||||||
if ((front = seg->frontsector)->floorheight ==
|
if (frontf == backf && frontc == backc
|
||||||
(back = seg->backsector)->floorheight &&
|
&& !front->ffloors & !back->ffloors) // (and no FOFs)
|
||||||
front->ceilingheight == back->ceilingheight)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// possible occluder
|
// possible occluder
|
||||||
// because of ceiling height differences
|
// because of ceiling height differences
|
||||||
popentop = front->ceilingheight < back->ceilingheight ?
|
popentop = min(frontc, backc);
|
||||||
front->ceilingheight : back->ceilingheight ;
|
|
||||||
|
|
||||||
// because of floor height differences
|
// because of floor height differences
|
||||||
popenbottom = front->floorheight > back->floorheight ?
|
popenbottom = max(frontf, backf);
|
||||||
front->floorheight : back->floorheight ;
|
|
||||||
|
|
||||||
// quick test for totally closed doors
|
// quick test for totally closed doors
|
||||||
if (popenbottom >= popentop)
|
if (popenbottom >= popentop)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
frac = P_InterceptVector2(&los->strace, &divl);
|
if (frontf != backf)
|
||||||
|
|
||||||
if (front->floorheight != back->floorheight)
|
|
||||||
{
|
{
|
||||||
fixed_t slope = FixedDiv(popenbottom - los->sightzstart , frac);
|
fixed_t slope = FixedDiv(popenbottom - los->sightzstart , frac);
|
||||||
if (slope > los->bottomslope)
|
if (slope > los->bottomslope)
|
||||||
los->bottomslope = slope;
|
los->bottomslope = slope;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (front->ceilingheight != back->ceilingheight)
|
if (frontc != backc)
|
||||||
{
|
{
|
||||||
fixed_t slope = FixedDiv(popentop - los->sightzstart , frac);
|
fixed_t slope = FixedDiv(popentop - los->sightzstart , frac);
|
||||||
if (slope < los->topslope)
|
if (slope < los->topslope)
|
||||||
|
@ -259,6 +293,48 @@ static boolean P_CrossSubsector(size_t num, register los_t *los)
|
||||||
|
|
||||||
if (los->topslope <= los->bottomslope)
|
if (los->topslope <= los->bottomslope)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// Monster Iestyn: check FOFs!
|
||||||
|
if (front->ffloors || back->ffloors)
|
||||||
|
{
|
||||||
|
ffloor_t *rover;
|
||||||
|
fixed_t topslope, bottomslope;
|
||||||
|
fixed_t topz, bottomz;
|
||||||
|
// check front sector's FOFs first
|
||||||
|
for (rover = front->ffloors; rover; rover = rover->next)
|
||||||
|
{
|
||||||
|
if (!(rover->flags & FF_EXISTS)
|
||||||
|
|| !(rover->flags & FF_RENDERSIDES) || (rover->flags & (FF_TRANSLUCENT|FF_FOG)))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
topz = P_GetFFloorTopZAt (rover, fracx, fracy);
|
||||||
|
bottomz = P_GetFFloorBottomZAt(rover, fracx, fracy);
|
||||||
|
topslope = FixedDiv( topz - los->sightzstart, frac);
|
||||||
|
bottomslope = FixedDiv(bottomz - los->sightzstart, frac);
|
||||||
|
if (topslope >= los->topslope && bottomslope <= los->bottomslope)
|
||||||
|
return false; // view completely blocked
|
||||||
|
}
|
||||||
|
// check back sector's FOFs as well
|
||||||
|
for (rover = back->ffloors; rover; rover = rover->next)
|
||||||
|
{
|
||||||
|
if (!(rover->flags & FF_EXISTS)
|
||||||
|
|| !(rover->flags & FF_RENDERSIDES) || (rover->flags & (FF_TRANSLUCENT|FF_FOG)))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
topz = P_GetFFloorTopZAt (rover, fracx, fracy);
|
||||||
|
bottomz = P_GetFFloorBottomZAt(rover, fracx, fracy);
|
||||||
|
topslope = FixedDiv( topz - los->sightzstart, frac);
|
||||||
|
bottomslope = FixedDiv(bottomz - los->sightzstart, frac);
|
||||||
|
if (topslope >= los->topslope && bottomslope <= los->bottomslope)
|
||||||
|
return false; // view completely blocked
|
||||||
|
}
|
||||||
|
// TODO: figure out if it's worth considering partially blocked cases or not?
|
||||||
|
// maybe to adjust los's top/bottom slopes if needed
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// passed the subsector ok
|
// passed the subsector ok
|
||||||
|
@ -364,6 +440,8 @@ boolean P_CheckSight(mobj_t *t1, mobj_t *t2)
|
||||||
if (s1 == s2) // Both sectors are the same.
|
if (s1 == s2) // Both sectors are the same.
|
||||||
{
|
{
|
||||||
ffloor_t *rover;
|
ffloor_t *rover;
|
||||||
|
fixed_t topz1, bottomz1; // top, bottom heights at t1's position
|
||||||
|
fixed_t topz2, bottomz2; // likewise but for t2
|
||||||
|
|
||||||
for (rover = s1->ffloors; rover; rover = rover->next)
|
for (rover = s1->ffloors; rover; rover = rover->next)
|
||||||
{
|
{
|
||||||
|
@ -371,14 +449,19 @@ boolean P_CheckSight(mobj_t *t1, mobj_t *t2)
|
||||||
/// \todo Improve by checking fog density/translucency
|
/// \todo Improve by checking fog density/translucency
|
||||||
/// and setting a sight limit.
|
/// and setting a sight limit.
|
||||||
if (!(rover->flags & FF_EXISTS)
|
if (!(rover->flags & FF_EXISTS)
|
||||||
|| !(rover->flags & FF_RENDERPLANES) || rover->flags & FF_TRANSLUCENT)
|
|| !(rover->flags & FF_RENDERPLANES) || (rover->flags & (FF_TRANSLUCENT|FF_FOG)))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
topz1 = P_GetFFloorTopZAt (rover, t1->x, t1->y);
|
||||||
|
topz2 = P_GetFFloorTopZAt (rover, t2->x, t2->y);
|
||||||
|
bottomz1 = P_GetFFloorBottomZAt(rover, t1->x, t1->y);
|
||||||
|
bottomz2 = P_GetFFloorBottomZAt(rover, t2->x, t2->y);
|
||||||
|
|
||||||
// Check for blocking floors here.
|
// Check for blocking floors here.
|
||||||
if ((los.sightzstart < *rover->bottomheight && t2->z >= *rover->topheight)
|
if ((los.sightzstart < bottomz1 && t2->z >= topz2)
|
||||||
|| (los.sightzstart >= *rover->topheight && t2->z + t2->height < *rover->bottomheight))
|
|| (los.sightzstart >= topz1 && t2->z + t2->height < bottomz2))
|
||||||
{
|
{
|
||||||
// no way to see through that
|
// no way to see through that
|
||||||
return false;
|
return false;
|
||||||
|
@ -387,21 +470,21 @@ boolean P_CheckSight(mobj_t *t1, mobj_t *t2)
|
||||||
if (rover->flags & FF_SOLID)
|
if (rover->flags & FF_SOLID)
|
||||||
continue; // shortcut since neither mobj can be inside the 3dfloor
|
continue; // shortcut since neither mobj can be inside the 3dfloor
|
||||||
|
|
||||||
if (!(rover->flags & FF_INVERTPLANES))
|
if (rover->flags & FF_BOTHPLANES || !(rover->flags & FF_INVERTPLANES))
|
||||||
{
|
{
|
||||||
if (los.sightzstart >= *rover->topheight && t2->z + t2->height < *rover->topheight)
|
if (los.sightzstart >= topz1 && t2->z + t2->height < topz2)
|
||||||
return false; // blocked by upper outside plane
|
return false; // blocked by upper outside plane
|
||||||
|
|
||||||
if (los.sightzstart < *rover->bottomheight && t2->z >= *rover->bottomheight)
|
if (los.sightzstart < bottomz1 && t2->z >= bottomz2)
|
||||||
return false; // blocked by lower outside plane
|
return false; // blocked by lower outside plane
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rover->flags & FF_INVERTPLANES || rover->flags & FF_BOTHPLANES)
|
if (rover->flags & FF_BOTHPLANES || rover->flags & FF_INVERTPLANES)
|
||||||
{
|
{
|
||||||
if (los.sightzstart < *rover->topheight && t2->z >= *rover->topheight)
|
if (los.sightzstart < topz1 && t2->z >= topz2)
|
||||||
return false; // blocked by upper inside plane
|
return false; // blocked by upper inside plane
|
||||||
|
|
||||||
if (los.sightzstart >= *rover->bottomheight && t2->z + t2->height < *rover->bottomheight)
|
if (los.sightzstart >= bottomz1 && t2->z + t2->height < bottomz2)
|
||||||
return false; // blocked by lower inside plane
|
return false; // blocked by lower inside plane
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -746,6 +746,30 @@ fixed_t P_GetZAt(pslope_t *slope, fixed_t x, fixed_t y)
|
||||||
return slope->o.z + FixedMul(dist, slope->zdelta);
|
return slope->o.z + FixedMul(dist, slope->zdelta);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the height of the sector floor at (x, y)
|
||||||
|
fixed_t P_GetSectorFloorZAt(const sector_t *sector, fixed_t x, fixed_t y)
|
||||||
|
{
|
||||||
|
return sector->f_slope ? P_GetZAt(sector->f_slope, x, y) : sector->floorheight;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the height of the sector ceiling at (x, y)
|
||||||
|
fixed_t P_GetSectorCeilingZAt(const sector_t *sector, fixed_t x, fixed_t y)
|
||||||
|
{
|
||||||
|
return sector->c_slope ? P_GetZAt(sector->c_slope, x, y) : sector->ceilingheight;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the height of the FOF top at (x, y)
|
||||||
|
fixed_t P_GetFFloorTopZAt(const ffloor_t *ffloor, fixed_t x, fixed_t y)
|
||||||
|
{
|
||||||
|
return *ffloor->t_slope ? P_GetZAt(*ffloor->t_slope, x, y) : *ffloor->topheight;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the height of the FOF bottom at (x, y)
|
||||||
|
fixed_t P_GetFFloorBottomZAt(const ffloor_t *ffloor, fixed_t x, fixed_t y)
|
||||||
|
{
|
||||||
|
return *ffloor->b_slope ? P_GetZAt(*ffloor->b_slope, x, y) : *ffloor->bottomheight;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// P_QuantizeMomentumToSlope
|
// P_QuantizeMomentumToSlope
|
||||||
|
|
|
@ -33,6 +33,14 @@ pslope_t *P_SlopeById(UINT16 id);
|
||||||
// Returns the height of the sloped plane at (x, y) as a fixed_t
|
// Returns the height of the sloped plane at (x, y) as a fixed_t
|
||||||
fixed_t P_GetZAt(pslope_t *slope, fixed_t x, fixed_t y);
|
fixed_t P_GetZAt(pslope_t *slope, fixed_t x, fixed_t y);
|
||||||
|
|
||||||
|
// Returns the height of the sector at (x, y)
|
||||||
|
fixed_t P_GetSectorFloorZAt (const sector_t *sector, fixed_t x, fixed_t y);
|
||||||
|
fixed_t P_GetSectorCeilingZAt(const sector_t *sector, fixed_t x, fixed_t y);
|
||||||
|
|
||||||
|
// Returns the height of the FOF at (x, y)
|
||||||
|
fixed_t P_GetFFloorTopZAt (const ffloor_t *ffloor, fixed_t x, fixed_t y);
|
||||||
|
fixed_t P_GetFFloorBottomZAt(const ffloor_t *ffloor, fixed_t x, fixed_t y);
|
||||||
|
|
||||||
// Lots of physics-based bullshit
|
// Lots of physics-based bullshit
|
||||||
void P_QuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope);
|
void P_QuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope);
|
||||||
void P_ReverseQuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope);
|
void P_ReverseQuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope);
|
||||||
|
|
Loading…
Reference in a new issue