mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-10 14:51: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)
|
||||
{ // 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) ||
|
||||
((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)
|
||||
{
|
||||
fixed_t bestfrac = FIXED_MAX;
|
||||
spechit_t *besthit = NULL;
|
||||
spechit_t besthit;
|
||||
// find the portal nearest to the crossing actor
|
||||
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);
|
||||
if (frac < bestfrac)
|
||||
{
|
||||
besthit = &spec;
|
||||
besthit = spec;
|
||||
bestfrac = frac;
|
||||
}
|
||||
}
|
||||
|
@ -2168,7 +2180,7 @@ bool P_TryMove(AActor *thing, fixed_t x, fixed_t y,
|
|||
|
||||
if (bestfrac < FIXED_MAX)
|
||||
{
|
||||
line_t *ld = besthit->line;
|
||||
line_t *ld = besthit.line;
|
||||
FLinePortal *port = ld->getPortal();
|
||||
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.
|
||||
P_TranslatePortalXY(ld, out, pos.x, pos.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);
|
||||
thing->SetXYZ(thingpos.x, thingpos.y, pos.z);
|
||||
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->SetXYZ(pos);
|
||||
P_TranslatePortalVXVY(ld, out, thing->velx, thing->vely);
|
||||
P_TranslatePortalAngle(ld, out, thing->angle);
|
||||
thing->LinkToWorld();
|
||||
P_FindFloorCeiling(thing);
|
||||
thing->ClearInterpolation();
|
||||
portalcrossed = true;
|
||||
}
|
||||
// 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.
|
||||
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 };
|
||||
fixedvec3 hit = { dl1.x + FixedMul(dl1.dx, bestfrac), dl1.y + FixedMul(dl1.dy, bestfrac), 0 };
|
||||
divline_t dl1 = { besthit.oldrefpos.x,besthit. oldrefpos.y, besthit.refpos.x - besthit.oldrefpos.x, besthit.refpos.y - besthit.oldrefpos.y };
|
||||
fixedvec3a hit = { dl1.x + FixedMul(dl1.dx, bestfrac), dl1.y + FixedMul(dl1.dy, bestfrac), 0, 0 };
|
||||
line_t *out = port->mDestination;
|
||||
|
||||
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_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);
|
||||
}
|
||||
|
@ -5450,7 +5465,7 @@ void PIT_FloorDrop(AActor *thing, FChangePosition *cpos)
|
|||
}
|
||||
if (thing->player && thing->player->mo == thing)
|
||||
{
|
||||
thing->player->viewz += thing->Z() - oldz;
|
||||
//thing->player->viewz += thing->Z() - oldz;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4045,7 +4045,8 @@ void P_SetupLevel (const char *lumpname, int position)
|
|||
|
||||
times[16].Clock();
|
||||
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();
|
||||
|
||||
assert(sidetemp != NULL);
|
||||
|
|
|
@ -1531,8 +1531,6 @@ void P_SpawnSpecials (void)
|
|||
}
|
||||
// [RH] Start running any open scripts on this map
|
||||
FBehavior::StaticStartTypedScripts (SCRIPT_Open, NULL, false);
|
||||
P_FinalizePortals();
|
||||
P_CreateLinkedPortals();
|
||||
}
|
||||
|
||||
// killough 2/28/98:
|
||||
|
|
|
@ -323,6 +323,12 @@ void P_UpdatePortal(FLinePortal *port)
|
|||
// Portal has no destination: switch it off
|
||||
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)
|
||||
{
|
||||
//portal doesn't link back. This will be a simple teleporter portal.
|
||||
|
@ -387,6 +393,7 @@ void P_FinalizePortals()
|
|||
}
|
||||
P_CollectLinkedPortals();
|
||||
BuildBlockmap();
|
||||
P_CreateLinkedPortals();
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
|
|
@ -81,7 +81,7 @@ static TArray<InterpolationViewer> PastViewers;
|
|||
static FRandom pr_torchflicker ("TorchFlicker");
|
||||
static FRandom pr_hom;
|
||||
static bool NoInterpolateView;
|
||||
static TArray<fixedvec3> InterpolationPath;
|
||||
static TArray<fixedvec3a> InterpolationPath;
|
||||
|
||||
// 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 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)
|
||||
{
|
||||
viewx = iview->nviewx;
|
||||
|
@ -601,27 +603,31 @@ void R_InterpolateView (player_t *player, fixed_t frac, InterpolationViewer *ivi
|
|||
fixed_t pathlen = 0;
|
||||
fixed_t zdiff = 0;
|
||||
fixed_t totalzdiff = 0;
|
||||
angle_t adiff = 0;
|
||||
angle_t totaladiff = 0;
|
||||
fixed_t oviewz = iview->oviewz;
|
||||
fixed_t nviewz = iview->nviewz;
|
||||
fixedvec3 oldpos = { iview->oviewx, iview->oviewy, 0 };
|
||||
fixedvec3 newpos = { iview->nviewx, iview->nviewy, 0 };
|
||||
fixedvec3a oldpos = { iview->oviewx, iview->oviewy, 0, 0 };
|
||||
fixedvec3a newpos = { iview->nviewx, iview->nviewy, 0, 0 };
|
||||
InterpolationPath.Push(newpos); // add this to the array to simplify the loops below
|
||||
|
||||
for (unsigned i = 0; i < InterpolationPath.Size(); i += 2)
|
||||
{
|
||||
fixedvec3 &start = i == 0 ? oldpos : InterpolationPath[i - 1];
|
||||
fixedvec3 &end = InterpolationPath[i];
|
||||
fixedvec3a &start = i == 0 ? oldpos : InterpolationPath[i - 1];
|
||||
fixedvec3a &end = InterpolationPath[i];
|
||||
pathlen += xs_CRoundToInt(TVector2<double>(end.x - start.x, end.y - start.y).Length());
|
||||
totalzdiff += start.z;
|
||||
totaladiff += start.angle;
|
||||
}
|
||||
fixed_t interpolatedlen = FixedMul(frac, pathlen);
|
||||
|
||||
for (unsigned i = 0; i < InterpolationPath.Size(); i += 2)
|
||||
{
|
||||
fixedvec3 &start = i == 0 ? oldpos : InterpolationPath[i - 1];
|
||||
fixedvec3 &end = InterpolationPath[i];
|
||||
fixedvec3a &start = i == 0 ? oldpos : InterpolationPath[i - 1];
|
||||
fixedvec3a &end = InterpolationPath[i];
|
||||
fixed_t fraglen = xs_CRoundToInt(TVector2<double>(end.x - start.x, end.y - start.y).Length());
|
||||
zdiff += start.z;
|
||||
adiff += start.angle;
|
||||
if (fraglen <= interpolatedlen)
|
||||
{
|
||||
interpolatedlen -= fraglen;
|
||||
|
@ -631,9 +637,12 @@ void R_InterpolateView (player_t *player, fixed_t frac, InterpolationViewer *ivi
|
|||
fixed_t fragfrac = FixedDiv(interpolatedlen, fraglen);
|
||||
oviewz += zdiff;
|
||||
nviewz -= totalzdiff - zdiff;
|
||||
oviewangle += adiff;
|
||||
nviewangle -= totaladiff - adiff;
|
||||
viewx = start.x + FixedMul(fragfrac, end.x - start.x);
|
||||
viewy = start.y + FixedMul(fragfrac, end.y - start.y);
|
||||
viewz = oviewz + FixedMul(frac, nviewz - oviewz);
|
||||
break;
|
||||
}
|
||||
}
|
||||
InterpolationPath.Pop();
|
||||
|
@ -661,7 +670,7 @@ void R_InterpolateView (player_t *player, fixed_t frac, InterpolationViewer *ivi
|
|||
(!netgame || !cl_noprediction) &&
|
||||
!LocalKeyboardTurner)
|
||||
{
|
||||
viewangle = iview->nviewangle + (LocalViewAngle & 0xFFFF0000);
|
||||
viewangle = nviewangle + (LocalViewAngle & 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
|
||||
{
|
||||
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.
|
||||
|
@ -876,7 +885,7 @@ void R_ClearInterpolationPath()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void R_AddInterpolationPoint(const fixedvec3 &vec)
|
||||
void R_AddInterpolationPoint(const fixedvec3a &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));
|
||||
}
|
||||
|
||||
// Used for interpolation waypoints.
|
||||
struct fixedvec3a
|
||||
{
|
||||
fixed_t x, y, z;
|
||||
angle_t angle;
|
||||
};
|
||||
|
||||
|
||||
subsector_t *R_PointInSubsector (fixed_t x, fixed_t y);
|
||||
fixed_t R_PointToDist2 (fixed_t dx, fixed_t dy);
|
||||
void R_ResetViewInterpolation ();
|
||||
void R_RebuildViewInterpolation(player_t *player);
|
||||
bool R_GetViewInterpolationStatus();
|
||||
void R_ClearInterpolationPath();
|
||||
void R_AddInterpolationPoint(const fixedvec3 &vec);
|
||||
void R_AddInterpolationPoint(const fixedvec3a &vec);
|
||||
void R_SetViewSize (int blocks);
|
||||
void R_SetFOV (float fov);
|
||||
float R_GetFOV ();
|
||||
|
|
Loading…
Reference in a new issue