- removed the one-sided line portals on polyobjects only limitation. Using Eternity's polyportal testmap shows that it expects one-sided crossable portals on non-polyobject walls.

- converted the P_TranslatePortal* functions to use floating point trigonometry. The combination of R_PointToAngle and finesine even created discrepancies with perfectly parallel portals which is just not acceptable.
- added a function to FPathTraverse to relocate the trace and restart from the new position.
- made P_UseLines portal aware. Traversal through line portals is complete (all types, even teleporters), whether sector portals need better treatment remains to be seen - at the moment it only checks the range at the player's vertical center.
This commit is contained in:
Christoph Oelckers 2016-03-01 01:36:36 +01:00
parent 6bcaa51968
commit 2584108200
9 changed files with 133 additions and 64 deletions

View file

@ -743,6 +743,7 @@ public:
inline bool IsNoClip2() const; inline bool IsNoClip2() const;
void CheckPortalTransition(bool islinked); void CheckPortalTransition(bool islinked);
fixedvec3 GetPortalTransition(fixed_t byoffset);
// What species am I? // What species am I?
virtual FName GetSpecies(); virtual FName GetSpecies();

View file

@ -820,8 +820,8 @@ bool PIT_CheckLine(FMultiBlockLinesIterator &mit, FMultiBlockLinesIterator::Chec
if (!ld->backsector) if (!ld->backsector)
{ // One sided line { // One sided line
// Needed for polyobject portals. Having two-sided lines just for portals on otherwise solid polyobjects is a messy subject. // Needed for polyobject portals.
if ((cres.line->sidedef[0]->Flags & WALLF_POLYOBJ) && cres.line->isLinePortal()) if (cres.line->isLinePortal())
{ {
spechit_t spec; spechit_t spec;
spec.line = ld; spec.line = ld;
@ -4731,10 +4731,11 @@ bool P_TalkFacing(AActor *player)
// //
//========================================================================== //==========================================================================
bool P_UseTraverse(AActor *usething, fixed_t endx, fixed_t endy, bool &foundline) bool P_UseTraverse(AActor *usething, fixed_t startx, fixed_t starty, fixed_t endx, fixed_t endy, bool &foundline)
{ {
FPathTraverse it(usething->X(), usething->Y(), endx, endy, PT_ADDLINES | PT_ADDTHINGS); FPathTraverse it(startx, starty, endx, endy, PT_ADDLINES | PT_ADDTHINGS);
intercept_t *in; intercept_t *in;
fixedvec3 xpos = { startx, starty, usething->Z() };
while ((in = it.Next())) while ((in = it.Next()))
{ {
@ -4754,6 +4755,21 @@ bool P_UseTraverse(AActor *usething, fixed_t endx, fixed_t endy, bool &foundline
} }
continue; continue;
} }
if (in->d.line->isLinePortal())
{
if (P_PointOnLineSide(xpos.x, xpos.y, in->d.line) == 0)
{
FLinePortal *port = in->d.line->getPortal();
if (port->mType != PORTT_LINKED) // other types will cause problems with
{
return true;
}
// Also translate the player origin, so that we can use that for checks further below and in P_CheckSwitchRange
it.PortalRealign(in, PT_ADDLINES | PT_ADDTHINGS, &xpos);
}
continue;
}
FLineOpening open; FLineOpening open;
if (in->d.line->special == 0 || !(in->d.line->activation & (SPAC_Use | SPAC_UseThrough | SPAC_UseBack))) if (in->d.line->special == 0 || !(in->d.line->activation & (SPAC_Use | SPAC_UseThrough | SPAC_UseBack)))
@ -4782,7 +4798,7 @@ bool P_UseTraverse(AActor *usething, fixed_t endx, fixed_t endy, bool &foundline
return true; return true;
} }
sec = P_PointOnLineSide(usething->X(), usething->Y(), in->d.line) == 0 ? sec = P_PointOnLineSide(xpos.x, xpos.y, in->d.line) == 0 ?
in->d.line->frontsector : in->d.line->backsector; in->d.line->frontsector : in->d.line->backsector;
if (sec != NULL && sec->SecActTarget && if (sec != NULL && sec->SecActTarget &&
@ -4801,7 +4817,7 @@ bool P_UseTraverse(AActor *usething, fixed_t endx, fixed_t endy, bool &foundline
continue; // not a special line, but keep checking continue; // not a special line, but keep checking
} }
if (P_PointOnLineSide(usething->X(), usething->Y(), in->d.line) == 1) if (P_PointOnLineSide(xpos.x, xpos.y, in->d.line) == 1)
{ {
if (!(in->d.line->activation & SPAC_UseBack)) if (!(in->d.line->activation & SPAC_UseBack))
{ {
@ -4811,7 +4827,7 @@ bool P_UseTraverse(AActor *usething, fixed_t endx, fixed_t endy, bool &foundline
} }
else else
{ {
P_ActivateLine(in->d.line, usething, 1, SPAC_UseBack); P_ActivateLine(in->d.line, usething, 1, SPAC_UseBack, &xpos);
return true; return true;
} }
} }
@ -4822,7 +4838,7 @@ bool P_UseTraverse(AActor *usething, fixed_t endx, fixed_t endy, bool &foundline
goto blocked; // Line cannot be used from front side so treat it as a non-trigger line goto blocked; // Line cannot be used from front side so treat it as a non-trigger line
} }
P_ActivateLine(in->d.line, usething, 0, SPAC_Use); P_ActivateLine(in->d.line, usething, 0, SPAC_Use, &xpos);
//WAS can't use more than one special line in a row //WAS can't use more than one special line in a row
//jff 3/21/98 NOW multiple use allowed with enabling line flag //jff 3/21/98 NOW multiple use allowed with enabling line flag
@ -4859,9 +4875,9 @@ bool P_UseTraverse(AActor *usething, fixed_t endx, fixed_t endy, bool &foundline
// //
//========================================================================== //==========================================================================
bool P_NoWayTraverse(AActor *usething, fixed_t endx, fixed_t endy) bool P_NoWayTraverse(AActor *usething, fixed_t startx, fixed_t starty, fixed_t endx, fixed_t endy)
{ {
FPathTraverse it(usething->X(), usething->Y(), endx, endy, PT_ADDLINES); FPathTraverse it(startx, starty, endx, endy, PT_ADDLINES);
intercept_t *in; intercept_t *in;
while ((in = it.Next())) while ((in = it.Next()))
@ -4872,6 +4888,7 @@ bool P_NoWayTraverse(AActor *usething, fixed_t endx, fixed_t endy)
// [GrafZahl] de-obfuscated. Was I the only one who was unable to make sense out of // [GrafZahl] de-obfuscated. Was I the only one who was unable to make sense out of
// this convoluted mess? // this convoluted mess?
if (ld->special) continue; if (ld->special) continue;
if (ld->isLinePortal()) return false;
if (ld->flags&(ML_BLOCKING | ML_BLOCKEVERYTHING | ML_BLOCK_PLAYERS)) return true; if (ld->flags&(ML_BLOCKING | ML_BLOCKEVERYTHING | ML_BLOCK_PLAYERS)) return true;
P_LineOpening(open, NULL, ld, it.Trace().x + FixedMul(it.Trace().dx, in->frac), P_LineOpening(open, NULL, ld, it.Trace().x + FixedMul(it.Trace().dx, in->frac),
it.Trace().y + FixedMul(it.Trace().dy, in->frac)); it.Trace().y + FixedMul(it.Trace().dy, in->frac));
@ -4890,12 +4907,16 @@ bool P_NoWayTraverse(AActor *usething, fixed_t endx, fixed_t endy)
// //
//========================================================================== //==========================================================================
CVAR(Int, userange, 0, 0);
void P_UseLines(player_t *player) void P_UseLines(player_t *player)
{ {
bool foundline = false; bool foundline = false;
// If the player is transitioning a portal, use the group that is at its vertical center.
fixedvec2 start = player->mo->GetPortalTransition(player->mo->height / 2);
// [NS] Now queries the Player's UseRange. // [NS] Now queries the Player's UseRange.
fixedvec2 end = player->mo->Vec2Angle(player->mo->UseRange, player->mo->angle, true); fixedvec2 end = start + Vec2Angle(userange > 0? fixed_t(userange<<FRACBITS) : player->mo->UseRange, player->mo->angle);
// old code: // old code:
// //
@ -4903,13 +4924,13 @@ void P_UseLines(player_t *player)
// //
// This added test makes the "oof" sound work on 2s lines -- killough: // This added test makes the "oof" sound work on 2s lines -- killough:
if (!P_UseTraverse(player->mo, end.x, end.y, foundline)) if (!P_UseTraverse(player->mo, start.x, start.y, end.x, end.y, foundline))
{ // [RH] Give sector a chance to eat the use { // [RH] Give sector a chance to eat the use
sector_t *sec = player->mo->Sector; sector_t *sec = player->mo->Sector;
int spac = SECSPAC_Use; int spac = SECSPAC_Use;
if (foundline) spac |= SECSPAC_UseWall; if (foundline) spac |= SECSPAC_UseWall;
if ((!sec->SecActTarget || !sec->SecActTarget->TriggerAction(player->mo, spac)) && if ((!sec->SecActTarget || !sec->SecActTarget->TriggerAction(player->mo, spac)) &&
P_NoWayTraverse(player->mo, end.x, end.y)) P_NoWayTraverse(player->mo, start.x, start.y, end.x, end.y))
{ {
S_Sound(player->mo, CHAN_VOICE, "*usefail", 1, ATTN_IDLE); S_Sound(player->mo, CHAN_VOICE, "*usefail", 1, ATTN_IDLE);
} }

View file

@ -1203,7 +1203,7 @@ void FPathTraverse::AddLineIntercepts(int bx, int by)
P_MakeDivline (ld, &dl); P_MakeDivline (ld, &dl);
frac = P_InterceptVector (&trace, &dl); frac = P_InterceptVector (&trace, &dl);
if (frac < 0 || frac > FRACUNIT) continue; // behind source or beyond end point if (frac < startfrac || frac > FRACUNIT) continue; // behind source or beyond end point
intercept_t newintercept; intercept_t newintercept;
@ -1284,7 +1284,7 @@ void FPathTraverse::AddThingIntercepts (int bx, int by, FBlockThingsIterator &it
{ {
// It's a hit // It's a hit
fixed_t frac = P_InterceptVector (&trace, &line); fixed_t frac = P_InterceptVector (&trace, &line);
if (frac < 0) if (frac < startfrac)
{ // behind source { // behind source
continue; continue;
} }
@ -1352,7 +1352,7 @@ void FPathTraverse::AddThingIntercepts (int bx, int by, FBlockThingsIterator &it
frac = P_InterceptVector (&trace, &dl); frac = P_InterceptVector (&trace, &dl);
if (frac >= 0) if (frac >= startfrac)
{ {
intercept_t newintercept; intercept_t newintercept;
newintercept.frac = frac; newintercept.frac = frac;
@ -1400,7 +1400,7 @@ intercept_t *FPathTraverse::Next()
// //
//=========================================================================== //===========================================================================
void FPathTraverse::init (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, int flags) void FPathTraverse::init (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, int flags, fixed_t startfrac)
{ {
fixed_t xt1, xt2; fixed_t xt1, xt2;
fixed_t yt1, yt2; fixed_t yt1, yt2;
@ -1424,6 +1424,7 @@ void FPathTraverse::init (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, int fl
validcount++; validcount++;
intercept_index = intercepts.Size(); intercept_index = intercepts.Size();
this->startfrac = startfrac;
if ( ((x1-bmaporgx)&(MAPBLOCKSIZE-1)) == 0) if ( ((x1-bmaporgx)&(MAPBLOCKSIZE-1)) == 0)
x1 += FRACUNIT; // don't side exactly on a line x1 += FRACUNIT; // don't side exactly on a line
@ -1444,8 +1445,8 @@ void FPathTraverse::init (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, int fl
trace.dy = y2 - y1; trace.dy = y2 - y1;
} }
_x1 = (long long)x1 - bmaporgx; _x1 = (long long)x1 + FixedMul(trace.dx, startfrac) - bmaporgx;
_y1 = (long long)y1 - bmaporgy; _y1 = (long long)y1 + FixedMul(trace.dy, startfrac) - bmaporgy;
x1 -= bmaporgx; x1 -= bmaporgx;
y1 -= bmaporgy; y1 -= bmaporgy;
xt1 = int(_x1 >> MAPBLOCKSHIFT); xt1 = int(_x1 >> MAPBLOCKSHIFT);
@ -1608,6 +1609,39 @@ void FPathTraverse::init (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, int fl
} }
} }
//===========================================================================
//
//
//
//===========================================================================
bool FPathTraverse::PortalRealign(intercept_t *in, int flags, fixedvec3 *optpos)
{
if (!in->isaline || !in->d.line->isLinePortal()) return false;
fixed_t hitx = trace.x;
fixed_t hity = trace.y;
fixed_t endx = trace.x + trace.dx;
fixed_t endy = trace.y + trace.dy;
line_t *out = in->d.line->getPortalDestination();
P_TranslatePortalXY(in->d.line, out, hitx, hity);
P_TranslatePortalXY(in->d.line, out, endx, endy);
if (optpos != NULL)
{
P_TranslatePortalXY(in->d.line, out, optpos->x, optpos->y);
P_TranslatePortalZ(in->d.line, out, optpos->z);
}
intercepts.Resize(intercept_index);
init(hitx, hity, endx, endy, flags, in->frac);
return true;
}
//===========================================================================
//
//
//
//===========================================================================
FPathTraverse::~FPathTraverse() FPathTraverse::~FPathTraverse()
{ {
intercepts.Resize(intercept_index); intercepts.Resize(intercept_index);

View file

@ -339,6 +339,7 @@ protected:
static TArray<intercept_t> intercepts; static TArray<intercept_t> intercepts;
divline_t trace; divline_t trace;
fixed_t startfrac;
unsigned int intercept_index; unsigned int intercept_index;
unsigned int intercept_count; unsigned int intercept_count;
unsigned int count; unsigned int count;
@ -354,7 +355,8 @@ public:
{ {
init(x1, y1, x2, y2, flags); init(x1, y1, x2, y2, flags);
} }
void init(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, int flags); void init(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, int flags, fixed_t startfrac = 0);
bool PortalRealign(intercept_t *in, int flags, fixedvec3 *optpos = NULL);
virtual ~FPathTraverse(); virtual ~FPathTraverse();
const divline_t &Trace() const { return trace; } const divline_t &Trace() const { return trace; }
}; };
@ -394,5 +396,4 @@ fixed_t P_InterceptVector (const divline_t *v2, const divline_t *v1);
#define PT_COMPATIBLE 4 #define PT_COMPATIBLE 4
#define PT_DELTA 8 // x2,y2 is passed as a delta, not as an endpoint #define PT_DELTA 8 // x2,y2 is passed as a delta, not as an endpoint
#endif #endif

View file

@ -3286,6 +3286,42 @@ void AActor::SetRoll(angle_t r, bool interpolate)
} }
fixedvec3 AActor::GetPortalTransition(fixed_t byoffset)
{
bool moved = false;
sector_t *sec = Sector;
fixed_t testz = Z() + byoffset;
fixedvec3 pos = Pos();
while (!sec->PortalBlocksMovement(sector_t::ceiling))
{
AActor *port = sec->SkyBoxes[sector_t::ceiling];
if (testz > port->threshold)
{
pos = PosRelative(port->Sector);
sec = P_PointInSector(pos.x, pos.y);
moved = true;
}
else break;
}
if (!moved)
{
while (!sec->PortalBlocksMovement(sector_t::floor))
{
AActor *port = sec->SkyBoxes[sector_t::floor];
if (testz <= port->threshold)
{
pos = PosRelative(port->Sector);
sec = P_PointInSector(pos.x, pos.y);
}
else break;
}
}
return pos;
}
void AActor::CheckPortalTransition(bool islinked) void AActor::CheckPortalTransition(bool islinked)
{ {
bool moved = false; bool moved = false;

View file

@ -201,14 +201,14 @@ bool CheckIfExitIsGood (AActor *self, level_info_t *info)
// //
//============================================================================ //============================================================================
bool P_ActivateLine (line_t *line, AActor *mo, int side, int activationType) bool P_ActivateLine (line_t *line, AActor *mo, int side, int activationType, fixedvec3 *optpos)
{ {
int lineActivation; int lineActivation;
INTBOOL repeat; INTBOOL repeat;
INTBOOL buttonSuccess; INTBOOL buttonSuccess;
BYTE special; BYTE special;
if (!P_TestActivateLine (line, mo, side, activationType)) if (!P_TestActivateLine (line, mo, side, activationType, optpos))
{ {
return false; return false;
} }
@ -262,7 +262,7 @@ bool P_ActivateLine (line_t *line, AActor *mo, int side, int activationType)
// //
//============================================================================ //============================================================================
bool P_TestActivateLine (line_t *line, AActor *mo, int side, int activationType) bool P_TestActivateLine (line_t *line, AActor *mo, int side, int activationType, fixedvec3 *optpos)
{ {
int lineActivation = line->activation; int lineActivation = line->activation;
@ -291,7 +291,7 @@ bool P_TestActivateLine (line_t *line, AActor *mo, int side, int activationType)
} }
if (activationType == SPAC_Use || activationType == SPAC_UseBack) if (activationType == SPAC_Use || activationType == SPAC_UseBack)
{ {
if (!P_CheckSwitchRange(mo, line, side)) if (!P_CheckSwitchRange(mo, line, side, optpos))
{ {
return false; return false;
} }

View file

@ -165,8 +165,8 @@ void P_SpawnSpecials (void);
void P_UpdateSpecials (void); void P_UpdateSpecials (void);
// when needed // when needed
bool P_ActivateLine (line_t *ld, AActor *mo, int side, int activationType); bool P_ActivateLine (line_t *ld, AActor *mo, int side, int activationType, fixedvec3 *optpos = NULL);
bool P_TestActivateLine (line_t *ld, AActor *mo, int side, int activationType); bool P_TestActivateLine (line_t *ld, AActor *mo, int side, int activationType, fixedvec3 *optpos = NULL);
bool P_PredictLine (line_t *ld, AActor *mo, int side, int activationType); bool P_PredictLine (line_t *ld, AActor *mo, int side, int activationType);
void P_PlayerInSpecialSector (player_t *player, sector_t * sector=NULL); void P_PlayerInSpecialSector (player_t *player, sector_t * sector=NULL);
@ -404,7 +404,7 @@ void EV_StartLightFading (int tag, int value, int tics);
#define BUTTONTIME TICRATE // 1 second, in ticks. #define BUTTONTIME TICRATE // 1 second, in ticks.
bool P_ChangeSwitchTexture (side_t *side, int useAgain, BYTE special, bool *quest=NULL); bool P_ChangeSwitchTexture (side_t *side, int useAgain, BYTE special, bool *quest=NULL);
bool P_CheckSwitchRange(AActor *user, line_t *line, int sideno); bool P_CheckSwitchRange(AActor *user, line_t *line, int sideno, fixedvec3 *optpos = NULL);
// //
// P_PLATS // P_PLATS

View file

@ -112,7 +112,7 @@ static bool P_StartButton (side_t *side, int Where, FSwitchDef *Switch, fixed_t
// //
//========================================================================== //==========================================================================
bool P_CheckSwitchRange(AActor *user, line_t *line, int sideno) bool P_CheckSwitchRange(AActor *user, line_t *line, int sideno, fixedvec3 *optpos)
{ {
// Activated from an empty side -> always succeed // Activated from an empty side -> always succeed
side_t *side = line->sidedef[sideno]; side_t *side = line->sidedef[sideno];
@ -140,7 +140,7 @@ bool P_CheckSwitchRange(AActor *user, line_t *line, int sideno)
P_MakeDivline (line, &dll); P_MakeDivline (line, &dll);
fixedvec3 pos = user->PosRelative(line); fixedvec3 pos = optpos? *optpos : user->PosRelative(line);
dlu.x = pos.x; dlu.x = pos.x;
dlu.y = pos.y; dlu.y = pos.y;
dlu.dx = finecosine[user->angle >> ANGLETOFINESHIFT]; dlu.dx = finecosine[user->angle >> ANGLETOFINESHIFT];

View file

@ -277,7 +277,7 @@ void P_SpawnLinePortal(line_t* line)
for (int i = 0; i < numlines; i++) for (int i = 0; i < numlines; i++)
{ {
if (tagManager.GetFirstLineID(&lines[i]) == mytag && lines[i].args[0] == 1) if (tagManager.GetFirstLineID(&lines[i]) == mytag && lines[i].args[0] == 1 && lines[i].special == Line_SetPortal)
{ {
line->portalindex = linePortals.Reserve(1); line->portalindex = linePortals.Reserve(1);
FLinePortal *port = &linePortals.Last(); FLinePortal *port = &linePortals.Last();
@ -323,12 +323,6 @@ void P_UpdatePortal(FLinePortal *port)
// Portal has no destination: switch it off // Portal has no destination: switch it off
port->mFlags = 0; port->mFlags = 0;
} }
else if ((port->mOrigin->backsector == NULL && !(port->mOrigin->sidedef[0]->Flags & WALLF_POLYOBJ)) ||
(port->mDestination->backsector == NULL && !(port->mOrigin->sidedef[0]->Flags & WALLF_POLYOBJ)))
{
// disable teleporting capability if a portal is or links to a one-sided wall (unless part of a polyobject.)
port->mFlags = PORTF_VISIBLE;
}
else if (port->mDestination->getPortalDestination() != port->mOrigin) else if (port->mDestination->getPortalDestination() != port->mOrigin)
{ {
//portal doesn't link back. This will be a simple teleporter portal. //portal doesn't link back. This will be a simple teleporter portal.
@ -562,24 +556,17 @@ void P_TranslatePortalXY(line_t* src, line_t* dst, fixed_t& x, fixed_t& y)
// Get the angle between the two linedefs, for rotating // Get the angle between the two linedefs, for rotating
// orientation and velocity. Rotate 180 degrees, and flip // orientation and velocity. Rotate 180 degrees, and flip
// the position across the exit linedef, if reversed. // the position across the exit linedef, if reversed.
angle_t angle =
R_PointToAngle2(0, 0, dst->dx, dst->dy) -
R_PointToAngle2(0, 0, src->dx, src->dy);
angle += ANGLE_180; double angle = atan2(dst->dy, dst->dx) - atan2(src->dy, src->dx) + M_PI;
fixed_t s = FLOAT2FIXED(sin(angle));
// Sine, cosine of angle adjustment fixed_t c = FLOAT2FIXED(cos(angle));
fixed_t s = finesine[angle>>ANGLETOFINESHIFT];
fixed_t c = finecosine[angle>>ANGLETOFINESHIFT];
fixed_t tx, ty;
nposx = x - src->v1->x; nposx = x - src->v1->x;
nposy = y - src->v1->y; nposy = y - src->v1->y;
// Rotate position along normal to match exit linedef // Rotate position along normal to match exit linedef
tx = FixedMul(nposx, c) - FixedMul(nposy, s); fixed_t tx = FixedMul(nposx, c) - FixedMul(nposy, s);
ty = FixedMul(nposy, c) + FixedMul(nposx, s); fixed_t ty = FixedMul(nposy, c) + FixedMul(nposx, s);
tx += dst->v2->x; tx += dst->v2->x;
ty += dst->v2->y; ty += dst->v2->y;
@ -596,15 +583,9 @@ void P_TranslatePortalXY(line_t* src, line_t* dst, fixed_t& x, fixed_t& y)
void P_TranslatePortalVXVY(line_t* src, line_t* dst, fixed_t& vx, fixed_t& vy) void P_TranslatePortalVXVY(line_t* src, line_t* dst, fixed_t& vx, fixed_t& vy)
{ {
angle_t angle = double angle = atan2(dst->dy, dst->dx) - atan2(src->dy, src->dx) + M_PI;
R_PointToAngle2(0, 0, dst->dx, dst->dy) - fixed_t s = FLOAT2FIXED(sin(angle));
R_PointToAngle2(0, 0, src->dx, src->dy); fixed_t c = FLOAT2FIXED(cos(angle));
angle += ANGLE_180;
// Sine, cosine of angle adjustment
fixed_t s = finesine[angle>>ANGLETOFINESHIFT];
fixed_t c = finecosine[angle>>ANGLETOFINESHIFT];
fixed_t orig_velx = vx; fixed_t orig_velx = vx;
fixed_t orig_vely = vy; fixed_t orig_vely = vy;
@ -626,12 +607,7 @@ void P_TranslatePortalAngle(line_t* src, line_t* dst, angle_t& angle)
// Get the angle between the two linedefs, for rotating // Get the angle between the two linedefs, for rotating
// orientation and velocity. Rotate 180 degrees, and flip // orientation and velocity. Rotate 180 degrees, and flip
// the position across the exit linedef, if reversed. // the position across the exit linedef, if reversed.
angle_t xangle = angle += RAD2ANGLE(atan2(dst->dy, dst->dx) - atan2(src->dy, src->dx)) + ANGLE_180;
R_PointToAngle2(0, 0, dst->dx, dst->dy) -
R_PointToAngle2(0, 0, src->dx, src->dy);
xangle += ANGLE_180;
angle += xangle;
} }
//============================================================================ //============================================================================