mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-11 15:22:16 +00:00
- fixed some line clipping issues with portals
* Blocking lines above or below the current sector should only block if they actually intersect with the currently checking actor. * Sectors above a ceiling portal should not change current floor information and vice versa.
This commit is contained in:
parent
1f09341d2b
commit
58839200e5
1 changed files with 102 additions and 30 deletions
132
src/p_map.cpp
132
src/p_map.cpp
|
@ -748,6 +748,30 @@ int P_GetMoveFactor(const AActor *mo, int *frictionp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// Checks if the line intersects with the actor
|
||||||
|
// returns
|
||||||
|
// - 1 when above/below
|
||||||
|
// - 0 when intersecting
|
||||||
|
// - -1 when outside the portal
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
static int LineIsAbove(line_t *line, AActor *actor)
|
||||||
|
{
|
||||||
|
AActor *point = line->frontsector->SkyBoxes[sector_t::floor];
|
||||||
|
if (point == NULL) return -1;
|
||||||
|
return point->threshold >= actor->Top();
|
||||||
|
}
|
||||||
|
|
||||||
|
static int LineIsBelow(line_t *line, AActor *actor)
|
||||||
|
{
|
||||||
|
AActor *point = line->frontsector->SkyBoxes[sector_t::ceiling];
|
||||||
|
if (point == NULL) return -1;
|
||||||
|
return point->threshold <= actor->Z();
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// MOVEMENT ITERATOR FUNCTIONS
|
// MOVEMENT ITERATOR FUNCTIONS
|
||||||
//
|
//
|
||||||
|
@ -788,6 +812,13 @@ bool PIT_CheckLine(FMultiBlockLinesIterator &mit, FMultiBlockLinesIterator::Chec
|
||||||
|
|
||||||
if (!ld->backsector)
|
if (!ld->backsector)
|
||||||
{ // One sided line
|
{ // One sided line
|
||||||
|
if (((cres.portalflags & FFCF_NOFLOOR) && LineIsAbove(cres.line, tm.thing) != 0) ||
|
||||||
|
((cres.portalflags & FFCF_NOCEILING) && LineIsBelow(cres.line, tm.thing) != 0))
|
||||||
|
{
|
||||||
|
// this blocking line is in a different vertical layer and does not intersect with the actor that is being checked.
|
||||||
|
// Since a one-sided line does not have an opening there's nothing left to do about it.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (tm.thing->flags2 & MF2_BLASTED)
|
if (tm.thing->flags2 & MF2_BLASTED)
|
||||||
{
|
{
|
||||||
P_DamageMobj(tm.thing, NULL, NULL, tm.thing->Mass >> 5, NAME_Melee);
|
P_DamageMobj(tm.thing, NULL, NULL, tm.thing->Mass >> 5, NAME_Melee);
|
||||||
|
@ -818,17 +849,52 @@ bool PIT_CheckLine(FMultiBlockLinesIterator &mit, FMultiBlockLinesIterator::Chec
|
||||||
((Projectile) && (ld->flags & ML_BLOCKPROJECTILE)) || // block projectiles
|
((Projectile) && (ld->flags & ML_BLOCKPROJECTILE)) || // block projectiles
|
||||||
((tm.thing->flags & MF_FLOAT) && (ld->flags & ML_BLOCK_FLOATERS))) // block floaters
|
((tm.thing->flags & MF_FLOAT) && (ld->flags & ML_BLOCK_FLOATERS))) // block floaters
|
||||||
{
|
{
|
||||||
if (tm.thing->flags2 & MF2_BLASTED)
|
if (cres.portalflags & FFCF_NOFLOOR)
|
||||||
{
|
{
|
||||||
P_DamageMobj(tm.thing, NULL, NULL, tm.thing->Mass >> 5, NAME_Melee);
|
int state = LineIsAbove(cres.line, tm.thing);
|
||||||
|
if (state == -1) return true;
|
||||||
|
if (state == 1)
|
||||||
|
{
|
||||||
|
// the line should not block but we should set the ceilingz to the portal boundary so that we can't float up into that line.
|
||||||
|
fixed_t portalz = cres.line->frontsector->SkyBoxes[sector_t::floor]->threshold;
|
||||||
|
if (portalz < tm.ceilingz)
|
||||||
|
{
|
||||||
|
tm.ceilingz = portalz;
|
||||||
|
tm.ceilingsector = cres.line->frontsector;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (cres.portalflags & FFCF_NOCEILING)
|
||||||
|
{
|
||||||
|
// same, but for downward portals
|
||||||
|
int state = LineIsBelow(cres.line, tm.thing);
|
||||||
|
if (state == -1) return true;
|
||||||
|
if (state == 1)
|
||||||
|
{
|
||||||
|
fixed_t portalz = cres.line->frontsector->SkyBoxes[sector_t::ceiling]->threshold;
|
||||||
|
if (portalz > tm.floorz)
|
||||||
|
{
|
||||||
|
tm.floorz = portalz;
|
||||||
|
tm.floorsector = cres.line->frontsector;
|
||||||
|
tm.floorterrain = 0;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (tm.thing->flags2 & MF2_BLASTED)
|
||||||
|
{
|
||||||
|
P_DamageMobj(tm.thing, NULL, NULL, tm.thing->Mass >> 5, NAME_Melee);
|
||||||
|
}
|
||||||
|
tm.thing->BlockingLine = ld;
|
||||||
|
// Calculate line side based on the actor's original position, not the new one.
|
||||||
|
CheckForPushSpecial(ld, P_PointOnLineSide(cres.position.x, cres.position.y, ld), tm.thing);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
tm.thing->BlockingLine = ld;
|
|
||||||
// Calculate line side based on the actor's original position, not the new one.
|
|
||||||
CheckForPushSpecial(ld, P_PointOnLineSide(cres.position.x, cres.position.y, ld), tm.thing);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fixedvec2 ref = FindRefPoint(ld, cres.position);
|
fixedvec2 ref = FindRefPoint(ld, cres.position);
|
||||||
FLineOpening open;
|
FLineOpening open;
|
||||||
|
|
||||||
|
@ -867,33 +933,39 @@ bool PIT_CheckLine(FMultiBlockLinesIterator &mit, FMultiBlockLinesIterator::Chec
|
||||||
}
|
}
|
||||||
|
|
||||||
// adjust floor / ceiling heights
|
// adjust floor / ceiling heights
|
||||||
if (open.top < tm.ceilingz)
|
if (!(cres.portalflags & FFCF_NOCEILING))
|
||||||
{
|
{
|
||||||
tm.ceilingz = open.top;
|
if (open.top < tm.ceilingz)
|
||||||
tm.ceilingsector = open.topsec;
|
{
|
||||||
tm.ceilingpic = open.ceilingpic;
|
tm.ceilingz = open.top;
|
||||||
tm.ceilingline = ld;
|
tm.ceilingsector = open.topsec;
|
||||||
tm.thing->BlockingLine = ld;
|
tm.ceilingpic = open.ceilingpic;
|
||||||
|
tm.ceilingline = ld;
|
||||||
|
tm.thing->BlockingLine = ld;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (open.bottom > tm.floorz)
|
if (!(cres.portalflags & FFCF_NOFLOOR))
|
||||||
{
|
{
|
||||||
tm.floorz = open.bottom;
|
if (open.bottom > tm.floorz)
|
||||||
tm.floorsector = open.bottomsec;
|
{
|
||||||
tm.floorpic = open.floorpic;
|
tm.floorz = open.bottom;
|
||||||
tm.floorterrain = open.floorterrain;
|
tm.floorsector = open.bottomsec;
|
||||||
tm.touchmidtex = open.touchmidtex;
|
tm.floorpic = open.floorpic;
|
||||||
tm.abovemidtex = open.abovemidtex;
|
tm.floorterrain = open.floorterrain;
|
||||||
tm.thing->BlockingLine = ld;
|
tm.touchmidtex = open.touchmidtex;
|
||||||
}
|
tm.abovemidtex = open.abovemidtex;
|
||||||
else if (open.bottom == tm.floorz)
|
tm.thing->BlockingLine = ld;
|
||||||
{
|
}
|
||||||
tm.touchmidtex |= open.touchmidtex;
|
else if (open.bottom == tm.floorz)
|
||||||
tm.abovemidtex |= open.abovemidtex;
|
{
|
||||||
}
|
tm.touchmidtex |= open.touchmidtex;
|
||||||
|
tm.abovemidtex |= open.abovemidtex;
|
||||||
|
}
|
||||||
|
|
||||||
if (open.lowfloor < tm.dropoffz)
|
if (open.lowfloor < tm.dropoffz)
|
||||||
tm.dropoffz = open.lowfloor;
|
tm.dropoffz = open.lowfloor;
|
||||||
|
}
|
||||||
|
|
||||||
// if contacted a special line, add it to the list
|
// if contacted a special line, add it to the list
|
||||||
spechit_t spec;
|
spechit_t spec;
|
||||||
|
@ -903,7 +975,7 @@ bool PIT_CheckLine(FMultiBlockLinesIterator &mit, FMultiBlockLinesIterator::Chec
|
||||||
spec.refpos = cres.position;
|
spec.refpos = cres.position;
|
||||||
spechit.Push(spec);
|
spechit.Push(spec);
|
||||||
}
|
}
|
||||||
if (ld->portalindex >= 0)
|
if (ld->portalindex >= 0 && ld->portalindex != UINT_MAX)
|
||||||
{
|
{
|
||||||
spec.line = ld;
|
spec.line = ld;
|
||||||
spec.refpos = cres.position;
|
spec.refpos = cres.position;
|
||||||
|
|
Loading…
Reference in a new issue