mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-11 15:21:51 +00:00
- made arbitrary portals passable.
This includes: * allow one sided portal linedefs to be crossable when part of a polyobject. Due to the limitations, two-sided linedefs won't work here. For general use this is still not allowed because making them passable would require some crippling fudging. * delay portal finalization until after polyobjects have been spawned. * the camera interpolation also needs to handle angle differences. The code is still not 100% complete - the most important thing that is still missing is proper handling of P_CheckPosition through arbitrary portals.
This commit is contained in:
parent
fcb38a9419
commit
047070d180
6 changed files with 60 additions and 22 deletions
|
@ -808,6 +808,18 @@ 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.
|
||||||
|
if ((cres.line->sidedef[0]->Flags & WALLF_POLYOBJ) && cres.line->isLinePortal())
|
||||||
|
{
|
||||||
|
spechit_t spec;
|
||||||
|
spec.line = ld;
|
||||||
|
spec.refpos = cres.position;
|
||||||
|
spec.oldrefpos = tm.thing->PosRelative(ld);
|
||||||
|
portalhit.Push(spec);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (((cres.portalflags & FFCF_NOFLOOR) && LineIsAbove(cres.line, tm.thing) != 0) ||
|
if (((cres.portalflags & FFCF_NOFLOOR) && LineIsAbove(cres.line, tm.thing) != 0) ||
|
||||||
((cres.portalflags & FFCF_NOCEILING) && LineIsBelow(cres.line, tm.thing) != 0))
|
((cres.portalflags & FFCF_NOCEILING) && LineIsBelow(cres.line, tm.thing) != 0))
|
||||||
{
|
{
|
||||||
|
@ -2143,7 +2155,7 @@ bool P_TryMove(AActor *thing, fixed_t x, fixed_t y,
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
fixed_t bestfrac = FIXED_MAX;
|
fixed_t bestfrac = FIXED_MAX;
|
||||||
spechit_t *besthit = NULL;
|
spechit_t besthit;
|
||||||
// find the portal nearest to the crossing actor
|
// find the portal nearest to the crossing actor
|
||||||
for (auto &spec : portalhit)
|
for (auto &spec : portalhit)
|
||||||
{
|
{
|
||||||
|
@ -2160,7 +2172,7 @@ bool P_TryMove(AActor *thing, fixed_t x, fixed_t y,
|
||||||
fixed_t frac = P_InterceptVector(&dl1, &dl2);
|
fixed_t frac = P_InterceptVector(&dl1, &dl2);
|
||||||
if (frac < bestfrac)
|
if (frac < bestfrac)
|
||||||
{
|
{
|
||||||
besthit = &spec;
|
besthit = spec;
|
||||||
bestfrac = frac;
|
bestfrac = frac;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2168,7 +2180,7 @@ bool P_TryMove(AActor *thing, fixed_t x, fixed_t y,
|
||||||
|
|
||||||
if (bestfrac < FIXED_MAX)
|
if (bestfrac < FIXED_MAX)
|
||||||
{
|
{
|
||||||
line_t *ld = besthit->line;
|
line_t *ld = besthit.line;
|
||||||
FLinePortal *port = ld->getPortal();
|
FLinePortal *port = ld->getPortal();
|
||||||
if (port->mType == PORTT_LINKED)
|
if (port->mType == PORTT_LINKED)
|
||||||
{
|
{
|
||||||
|
@ -2192,8 +2204,6 @@ bool P_TryMove(AActor *thing, fixed_t x, fixed_t y,
|
||||||
// so that the spechit array gets proper positions assigned that can be evaluated later.
|
// so that the spechit array gets proper positions assigned that can be evaluated later.
|
||||||
P_TranslatePortalXY(ld, out, pos.x, pos.y);
|
P_TranslatePortalXY(ld, out, pos.x, pos.y);
|
||||||
P_TranslatePortalXY(ld, out, thingpos.x, thingpos.y);
|
P_TranslatePortalXY(ld, out, thingpos.x, thingpos.y);
|
||||||
P_TranslatePortalVXVY(ld, out, thing->velx, thing->vely);
|
|
||||||
P_TranslatePortalAngle(ld, out, thing->angle);
|
|
||||||
P_TranslatePortalZ(ld, out, pos.z);
|
P_TranslatePortalZ(ld, out, pos.z);
|
||||||
thing->SetXYZ(thingpos.x, thingpos.y, pos.z);
|
thing->SetXYZ(thingpos.x, thingpos.y, pos.z);
|
||||||
if (!P_CheckPosition(thing, pos.x, pos.y))
|
if (!P_CheckPosition(thing, pos.x, pos.y))
|
||||||
|
@ -2204,16 +2214,19 @@ bool P_TryMove(AActor *thing, fixed_t x, fixed_t y,
|
||||||
}
|
}
|
||||||
thing->UnlinkFromWorld();
|
thing->UnlinkFromWorld();
|
||||||
thing->SetXYZ(pos);
|
thing->SetXYZ(pos);
|
||||||
|
P_TranslatePortalVXVY(ld, out, thing->velx, thing->vely);
|
||||||
|
P_TranslatePortalAngle(ld, out, thing->angle);
|
||||||
thing->LinkToWorld();
|
thing->LinkToWorld();
|
||||||
P_FindFloorCeiling(thing);
|
P_FindFloorCeiling(thing);
|
||||||
thing->ClearInterpolation();
|
thing->ClearInterpolation();
|
||||||
|
portalcrossed = true;
|
||||||
}
|
}
|
||||||
// if this is the current camera we need to store the point where the portal was crossed and the exit
|
// if this is the current camera we need to store the point where the portal was crossed and the exit
|
||||||
// so that the renderer can properly calculate an interpolated position along the movement path.
|
// so that the renderer can properly calculate an interpolated position along the movement path.
|
||||||
if (thing == players[consoleplayer].camera)
|
if (thing == players[consoleplayer].camera)
|
||||||
{
|
{
|
||||||
divline_t dl1 = { besthit->oldrefpos.x,besthit-> oldrefpos.y, besthit->refpos.x - besthit->oldrefpos.x, besthit->refpos.y - besthit->oldrefpos.y };
|
divline_t dl1 = { besthit.oldrefpos.x,besthit. oldrefpos.y, besthit.refpos.x - besthit.oldrefpos.x, besthit.refpos.y - besthit.oldrefpos.y };
|
||||||
fixedvec3 hit = { dl1.x + FixedMul(dl1.dx, bestfrac), dl1.y + FixedMul(dl1.dy, bestfrac), 0 };
|
fixedvec3a hit = { dl1.x + FixedMul(dl1.dx, bestfrac), dl1.y + FixedMul(dl1.dy, bestfrac), 0, 0 };
|
||||||
line_t *out = port->mDestination;
|
line_t *out = port->mDestination;
|
||||||
|
|
||||||
R_AddInterpolationPoint(hit);
|
R_AddInterpolationPoint(hit);
|
||||||
|
@ -2226,6 +2239,8 @@ bool P_TryMove(AActor *thing, fixed_t x, fixed_t y,
|
||||||
{
|
{
|
||||||
P_TranslatePortalXY(ld, out, hit.x, hit.y);
|
P_TranslatePortalXY(ld, out, hit.x, hit.y);
|
||||||
P_TranslatePortalZ(ld, out, hit.z);
|
P_TranslatePortalZ(ld, out, hit.z);
|
||||||
|
players[consoleplayer].viewz += hit.z; // needs to be done here because otherwise the renderer will not catch the change.
|
||||||
|
P_TranslatePortalAngle(ld, out, hit.angle);
|
||||||
}
|
}
|
||||||
R_AddInterpolationPoint(hit);
|
R_AddInterpolationPoint(hit);
|
||||||
}
|
}
|
||||||
|
@ -5450,7 +5465,7 @@ void PIT_FloorDrop(AActor *thing, FChangePosition *cpos)
|
||||||
}
|
}
|
||||||
if (thing->player && thing->player->mo == thing)
|
if (thing->player && thing->player->mo == thing)
|
||||||
{
|
{
|
||||||
thing->player->viewz += thing->Z() - oldz;
|
//thing->player->viewz += thing->Z() - oldz;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4046,6 +4046,7 @@ void P_SetupLevel (const char *lumpname, int position)
|
||||||
times[16].Clock();
|
times[16].Clock();
|
||||||
if (reloop) P_LoopSidedefs (false);
|
if (reloop) P_LoopSidedefs (false);
|
||||||
PO_Init (); // Initialize the polyobjs
|
PO_Init (); // Initialize the polyobjs
|
||||||
|
P_FinalizePortals(); // finalize line portals after polyobjects have been initialized. This info is needed for properly flagging them.
|
||||||
times[16].Unclock();
|
times[16].Unclock();
|
||||||
|
|
||||||
assert(sidetemp != NULL);
|
assert(sidetemp != NULL);
|
||||||
|
|
|
@ -1531,8 +1531,6 @@ void P_SpawnSpecials (void)
|
||||||
}
|
}
|
||||||
// [RH] Start running any open scripts on this map
|
// [RH] Start running any open scripts on this map
|
||||||
FBehavior::StaticStartTypedScripts (SCRIPT_Open, NULL, false);
|
FBehavior::StaticStartTypedScripts (SCRIPT_Open, NULL, false);
|
||||||
P_FinalizePortals();
|
|
||||||
P_CreateLinkedPortals();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// killough 2/28/98:
|
// killough 2/28/98:
|
||||||
|
|
|
@ -323,6 +323,12 @@ 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.
|
||||||
|
@ -387,6 +393,7 @@ void P_FinalizePortals()
|
||||||
}
|
}
|
||||||
P_CollectLinkedPortals();
|
P_CollectLinkedPortals();
|
||||||
BuildBlockmap();
|
BuildBlockmap();
|
||||||
|
P_CreateLinkedPortals();
|
||||||
}
|
}
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
|
@ -81,7 +81,7 @@ static TArray<InterpolationViewer> PastViewers;
|
||||||
static FRandom pr_torchflicker ("TorchFlicker");
|
static FRandom pr_torchflicker ("TorchFlicker");
|
||||||
static FRandom pr_hom;
|
static FRandom pr_hom;
|
||||||
static bool NoInterpolateView;
|
static bool NoInterpolateView;
|
||||||
static TArray<fixedvec3> InterpolationPath;
|
static TArray<fixedvec3a> InterpolationPath;
|
||||||
|
|
||||||
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
||||||
|
|
||||||
|
@ -586,6 +586,8 @@ void R_InterpolateView (player_t *player, fixed_t frac, InterpolationViewer *ivi
|
||||||
int oldgroup = R_PointInSubsector(iview->oviewx, iview->oviewy)->sector->PortalGroup;
|
int oldgroup = R_PointInSubsector(iview->oviewx, iview->oviewy)->sector->PortalGroup;
|
||||||
int newgroup = R_PointInSubsector(iview->nviewx, iview->nviewy)->sector->PortalGroup;
|
int newgroup = R_PointInSubsector(iview->nviewx, iview->nviewy)->sector->PortalGroup;
|
||||||
|
|
||||||
|
fixed_t oviewangle = iview->oviewangle;
|
||||||
|
fixed_t nviewangle = iview->nviewangle;
|
||||||
if ((iview->oviewx != iview->nviewx || iview->oviewy != iview->nviewy) && InterpolationPath.Size() > 0)
|
if ((iview->oviewx != iview->nviewx || iview->oviewy != iview->nviewy) && InterpolationPath.Size() > 0)
|
||||||
{
|
{
|
||||||
viewx = iview->nviewx;
|
viewx = iview->nviewx;
|
||||||
|
@ -601,27 +603,31 @@ void R_InterpolateView (player_t *player, fixed_t frac, InterpolationViewer *ivi
|
||||||
fixed_t pathlen = 0;
|
fixed_t pathlen = 0;
|
||||||
fixed_t zdiff = 0;
|
fixed_t zdiff = 0;
|
||||||
fixed_t totalzdiff = 0;
|
fixed_t totalzdiff = 0;
|
||||||
|
angle_t adiff = 0;
|
||||||
|
angle_t totaladiff = 0;
|
||||||
fixed_t oviewz = iview->oviewz;
|
fixed_t oviewz = iview->oviewz;
|
||||||
fixed_t nviewz = iview->nviewz;
|
fixed_t nviewz = iview->nviewz;
|
||||||
fixedvec3 oldpos = { iview->oviewx, iview->oviewy, 0 };
|
fixedvec3a oldpos = { iview->oviewx, iview->oviewy, 0, 0 };
|
||||||
fixedvec3 newpos = { iview->nviewx, iview->nviewy, 0 };
|
fixedvec3a newpos = { iview->nviewx, iview->nviewy, 0, 0 };
|
||||||
InterpolationPath.Push(newpos); // add this to the array to simplify the loops below
|
InterpolationPath.Push(newpos); // add this to the array to simplify the loops below
|
||||||
|
|
||||||
for (unsigned i = 0; i < InterpolationPath.Size(); i += 2)
|
for (unsigned i = 0; i < InterpolationPath.Size(); i += 2)
|
||||||
{
|
{
|
||||||
fixedvec3 &start = i == 0 ? oldpos : InterpolationPath[i - 1];
|
fixedvec3a &start = i == 0 ? oldpos : InterpolationPath[i - 1];
|
||||||
fixedvec3 &end = InterpolationPath[i];
|
fixedvec3a &end = InterpolationPath[i];
|
||||||
pathlen += xs_CRoundToInt(TVector2<double>(end.x - start.x, end.y - start.y).Length());
|
pathlen += xs_CRoundToInt(TVector2<double>(end.x - start.x, end.y - start.y).Length());
|
||||||
totalzdiff += start.z;
|
totalzdiff += start.z;
|
||||||
|
totaladiff += start.angle;
|
||||||
}
|
}
|
||||||
fixed_t interpolatedlen = FixedMul(frac, pathlen);
|
fixed_t interpolatedlen = FixedMul(frac, pathlen);
|
||||||
|
|
||||||
for (unsigned i = 0; i < InterpolationPath.Size(); i += 2)
|
for (unsigned i = 0; i < InterpolationPath.Size(); i += 2)
|
||||||
{
|
{
|
||||||
fixedvec3 &start = i == 0 ? oldpos : InterpolationPath[i - 1];
|
fixedvec3a &start = i == 0 ? oldpos : InterpolationPath[i - 1];
|
||||||
fixedvec3 &end = InterpolationPath[i];
|
fixedvec3a &end = InterpolationPath[i];
|
||||||
fixed_t fraglen = xs_CRoundToInt(TVector2<double>(end.x - start.x, end.y - start.y).Length());
|
fixed_t fraglen = xs_CRoundToInt(TVector2<double>(end.x - start.x, end.y - start.y).Length());
|
||||||
zdiff += start.z;
|
zdiff += start.z;
|
||||||
|
adiff += start.angle;
|
||||||
if (fraglen <= interpolatedlen)
|
if (fraglen <= interpolatedlen)
|
||||||
{
|
{
|
||||||
interpolatedlen -= fraglen;
|
interpolatedlen -= fraglen;
|
||||||
|
@ -631,9 +637,12 @@ void R_InterpolateView (player_t *player, fixed_t frac, InterpolationViewer *ivi
|
||||||
fixed_t fragfrac = FixedDiv(interpolatedlen, fraglen);
|
fixed_t fragfrac = FixedDiv(interpolatedlen, fraglen);
|
||||||
oviewz += zdiff;
|
oviewz += zdiff;
|
||||||
nviewz -= totalzdiff - zdiff;
|
nviewz -= totalzdiff - zdiff;
|
||||||
|
oviewangle += adiff;
|
||||||
|
nviewangle -= totaladiff - adiff;
|
||||||
viewx = start.x + FixedMul(fragfrac, end.x - start.x);
|
viewx = start.x + FixedMul(fragfrac, end.x - start.x);
|
||||||
viewy = start.y + FixedMul(fragfrac, end.y - start.y);
|
viewy = start.y + FixedMul(fragfrac, end.y - start.y);
|
||||||
viewz = oviewz + FixedMul(frac, nviewz - oviewz);
|
viewz = oviewz + FixedMul(frac, nviewz - oviewz);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
InterpolationPath.Pop();
|
InterpolationPath.Pop();
|
||||||
|
@ -661,7 +670,7 @@ void R_InterpolateView (player_t *player, fixed_t frac, InterpolationViewer *ivi
|
||||||
(!netgame || !cl_noprediction) &&
|
(!netgame || !cl_noprediction) &&
|
||||||
!LocalKeyboardTurner)
|
!LocalKeyboardTurner)
|
||||||
{
|
{
|
||||||
viewangle = iview->nviewangle + (LocalViewAngle & 0xFFFF0000);
|
viewangle = nviewangle + (LocalViewAngle & 0xFFFF0000);
|
||||||
|
|
||||||
fixed_t delta = player->centering ? 0 : -(signed)(LocalViewPitch & 0xFFFF0000);
|
fixed_t delta = player->centering ? 0 : -(signed)(LocalViewPitch & 0xFFFF0000);
|
||||||
|
|
||||||
|
@ -694,7 +703,7 @@ void R_InterpolateView (player_t *player, fixed_t frac, InterpolationViewer *ivi
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
viewpitch = iview->oviewpitch + FixedMul (frac, iview->nviewpitch - iview->oviewpitch);
|
viewpitch = iview->oviewpitch + FixedMul (frac, iview->nviewpitch - iview->oviewpitch);
|
||||||
viewangle = iview->oviewangle + FixedMul (frac, iview->nviewangle - iview->oviewangle);
|
viewangle = oviewangle + FixedMul (frac, nviewangle - oviewangle);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Due to interpolation this is not necessarily the same as the sector the camera is in.
|
// Due to interpolation this is not necessarily the same as the sector the camera is in.
|
||||||
|
@ -876,7 +885,7 @@ void R_ClearInterpolationPath()
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void R_AddInterpolationPoint(const fixedvec3 &vec)
|
void R_AddInterpolationPoint(const fixedvec3a &vec)
|
||||||
{
|
{
|
||||||
InterpolationPath.Push(vec);
|
InterpolationPath.Push(vec);
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,13 +63,21 @@ inline angle_t R_PointToAnglePrecise (fixed_t viewx, fixed_t viewy, fixed_t x, f
|
||||||
return xs_RoundToUInt(atan2(double(y-viewy), double(x-viewx)) * (ANGLE_180/M_PI));
|
return xs_RoundToUInt(atan2(double(y-viewy), double(x-viewx)) * (ANGLE_180/M_PI));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Used for interpolation waypoints.
|
||||||
|
struct fixedvec3a
|
||||||
|
{
|
||||||
|
fixed_t x, y, z;
|
||||||
|
angle_t angle;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
subsector_t *R_PointInSubsector (fixed_t x, fixed_t y);
|
subsector_t *R_PointInSubsector (fixed_t x, fixed_t y);
|
||||||
fixed_t R_PointToDist2 (fixed_t dx, fixed_t dy);
|
fixed_t R_PointToDist2 (fixed_t dx, fixed_t dy);
|
||||||
void R_ResetViewInterpolation ();
|
void R_ResetViewInterpolation ();
|
||||||
void R_RebuildViewInterpolation(player_t *player);
|
void R_RebuildViewInterpolation(player_t *player);
|
||||||
bool R_GetViewInterpolationStatus();
|
bool R_GetViewInterpolationStatus();
|
||||||
void R_ClearInterpolationPath();
|
void R_ClearInterpolationPath();
|
||||||
void R_AddInterpolationPoint(const fixedvec3 &vec);
|
void R_AddInterpolationPoint(const fixedvec3a &vec);
|
||||||
void R_SetViewSize (int blocks);
|
void R_SetViewSize (int blocks);
|
||||||
void R_SetFOV (float fov);
|
void R_SetFOV (float fov);
|
||||||
float R_GetFOV ();
|
float R_GetFOV ();
|
||||||
|
|
Loading…
Reference in a new issue