- more cleanup on portal implementation:
- store portal data in a separate structure. - store portal data in savegames because some of this will be changeable later. - run a cleanup pass after all portals have been created to weed out broken ones. - add a definition type that's compatible with Eternity Engine's line portal types. - swapped arg[2] and arg[3] of Line_SetPortal, because the type is more significant than the alignment.
This commit is contained in:
parent
9eaefc3685
commit
94b7ef72ca
13 changed files with 243 additions and 59 deletions
168
src/portal.cpp
168
src/portal.cpp
|
|
@ -6,10 +6,128 @@
|
|||
#include "c_cvars.h"
|
||||
#include "m_bbox.h"
|
||||
#include "p_tags.h"
|
||||
#include "farchive.h"
|
||||
|
||||
// simulation recurions maximum
|
||||
CVAR(Int, sv_portal_recursions, 4, CVAR_ARCHIVE|CVAR_SERVERINFO)
|
||||
|
||||
TArray<FLinePortal> linePortals;
|
||||
|
||||
|
||||
FArchive &operator<< (FArchive &arc, FLinePortal &port)
|
||||
{
|
||||
arc << port.mOrigin
|
||||
<< port.mDestination
|
||||
<< port.mXDisplacement
|
||||
<< port.mYDisplacement
|
||||
<< port.mType
|
||||
<< port.mFlags
|
||||
<< port.mDefFlags
|
||||
<< port.mAlign;
|
||||
return arc;
|
||||
}
|
||||
|
||||
|
||||
void P_SpawnLinePortal(line_t* line)
|
||||
{
|
||||
// portal destination is special argument #0
|
||||
line_t* dst = NULL;
|
||||
|
||||
if (line->args[2] >= PORTT_VISUAL && line->args[2] <= PORTT_LINKED)
|
||||
{
|
||||
if (line->args[0] > 0)
|
||||
{
|
||||
int linenum = -1;
|
||||
|
||||
for (int i = 0; i < numlines; i++)
|
||||
{
|
||||
if (&lines[i] == line)
|
||||
continue;
|
||||
if (tagManager.LineHasID(&lines[i], line->args[0]))
|
||||
{
|
||||
dst = &lines[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
line->portalindex = linePortals.Reserve(1);
|
||||
FLinePortal *port = &linePortals.Last();
|
||||
|
||||
memset(port, 0, sizeof(FLinePortal));
|
||||
port->mOrigin = line;
|
||||
port->mDestination = dst;
|
||||
port->mType = BYTE(line->args[2]); // range check is done above.
|
||||
port->mAlign = BYTE(line->args[3] >= PORG_ABSOLUTE && line->args[3] <= PORG_CEILING ? line->args[3] : PORG_ABSOLUTE);
|
||||
if (port->mDestination != NULL)
|
||||
{
|
||||
port->mDefFlags = port->mType == PORTT_VISUAL ? PORTF_VISIBLE : port->mType == PORTT_TELEPORT ? PORTF_TYPETELEPORT : PORTF_TYPEINTERACTIVE;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
else if (line->args[2] == PORTT_LINKEDEE && line->args[0] == 0)
|
||||
{
|
||||
// EE-style portals require that the first line ID is identical and the first arg of the two linked linedefs are 0 and 1 respectively.
|
||||
|
||||
int mytag = tagManager.GetFirstLineID(line);
|
||||
|
||||
for (int i = 0; i < numlines; i++)
|
||||
{
|
||||
if (tagManager.GetFirstLineID(&lines[i]) == mytag && lines[i].args[0] == 1)
|
||||
{
|
||||
line->portalindex = linePortals.Reserve(1);
|
||||
FLinePortal *port = &linePortals.Last();
|
||||
|
||||
memset(port, 0, sizeof(FLinePortal));
|
||||
port->mOrigin = line;
|
||||
port->mDestination = &lines[i];
|
||||
port->mType = PORTT_LINKED;
|
||||
port->mAlign = PORG_ABSOLUTE;
|
||||
port->mDefFlags = PORTF_TYPEINTERACTIVE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// undefined type
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void P_UpdatePortal(FLinePortal *port)
|
||||
{
|
||||
if (port->mDestination == NULL)
|
||||
{
|
||||
// Portal has no destination: switch it off
|
||||
port->mFlags = 0;
|
||||
}
|
||||
else if (port->mDestination->getPortalDestination() != port->mOrigin)
|
||||
{
|
||||
//portal doesn't link back. This will be a simple teleporter portal.
|
||||
port->mFlags = port->mDefFlags & ~PORTF_INTERACTIVE;
|
||||
if (port->mType == PORTT_LINKED)
|
||||
{
|
||||
// this is illegal. Demote the type to TELEPORT
|
||||
port->mType = PORTT_TELEPORT;
|
||||
port->mDefFlags &= ~PORTF_INTERACTIVE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
port->mFlags = port->mDefFlags;
|
||||
}
|
||||
}
|
||||
|
||||
void P_FinalizePortals()
|
||||
{
|
||||
for (unsigned i = 0; i < linePortals.Size(); i++)
|
||||
{
|
||||
FLinePortal * port = &linePortals[i];
|
||||
P_UpdatePortal(port);
|
||||
}
|
||||
}
|
||||
|
||||
// [ZZ] lots of floats here to avoid overflowing a lot
|
||||
bool P_IntersectLines(fixed_t o1x, fixed_t o1y, fixed_t p1x, fixed_t p1y,
|
||||
fixed_t o2x, fixed_t o2y, fixed_t p2x, fixed_t p2y,
|
||||
|
|
@ -78,41 +196,6 @@ bool P_ClipLineToPortal(line_t* line, line_t* portal, fixed_t viewx, fixed_t vie
|
|||
return false;
|
||||
}
|
||||
|
||||
void P_SpawnLinePortal(line_t* line)
|
||||
{
|
||||
// portal destination is special argument #0
|
||||
line_t* dst = NULL;
|
||||
|
||||
if (line->args[0] > 0)
|
||||
{
|
||||
int linenum = -1;
|
||||
|
||||
for (int i = 0; i < numlines; i++)
|
||||
{
|
||||
if (&lines[i] == line)
|
||||
continue;
|
||||
if (tagManager.LineHasID(&lines[i], line->args[0]))
|
||||
{
|
||||
dst = &lines[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dst)
|
||||
{
|
||||
line->_portal = true;
|
||||
//line->portal_passive = true;// !!(line->args[2] & PORTAL_VISUAL; (line->special == Line_SetVisualPortal);
|
||||
line->_portal_dst = dst;
|
||||
}
|
||||
else
|
||||
{
|
||||
line->_portal = false;
|
||||
//line->portal_passive = false;
|
||||
line->_portal_dst = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void P_TranslatePortalXY(line_t* src, line_t* dst, fixed_t& x, fixed_t& y)
|
||||
{
|
||||
if (!src || !dst)
|
||||
|
|
@ -185,17 +268,22 @@ void P_TranslatePortalAngle(line_t* src, line_t* dst, angle_t& angle)
|
|||
|
||||
void P_TranslatePortalZ(line_t* src, line_t* dst, fixed_t& z)
|
||||
{
|
||||
// args[2] = 0 - no teleport
|
||||
// args[2] = 0 - no adjustment
|
||||
// args[2] = 1 - adjust by floor difference
|
||||
// args[2] = 2 - adjust by ceiling difference
|
||||
|
||||
if (src->args[2] == 1)
|
||||
switch (src->getPortalAlignment())
|
||||
{
|
||||
case PORG_FLOOR:
|
||||
z = z - src->frontsector->floorplane.ZatPoint(src->v1->x, src->v1->y) + dst->frontsector->floorplane.ZatPoint(dst->v2->x, dst->v2->y);
|
||||
}
|
||||
else if (src->args[2] == 2)
|
||||
{
|
||||
return;
|
||||
|
||||
case PORG_CEILING:
|
||||
z = z - src->frontsector->ceilingplane.ZatPoint(src->v1->x, src->v1->y) + dst->frontsector->ceilingplane.ZatPoint(dst->v2->x, dst->v2->y);
|
||||
return;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue