diff --git a/src/p_map.cpp b/src/p_map.cpp index 8fbbb3e99..5d5777d6f 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -708,7 +708,7 @@ bool PIT_CheckLine(FMultiBlockLinesIterator &mit, FMultiBlockLinesIterator::Chec { // One sided line // Needed for polyobject portals. - if (cres.line->isLinePortal()) + if (cres.line->isLinePortal() && (cres.line->sidedef[0]->Flags & WALLF_POLYOBJ)) { spechit_t spec; spec.line = ld; diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 2c7c4ea42..13670bcb1 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -5129,12 +5129,14 @@ AActor *P_SpawnPuff (AActor *source, PClassActor *pufftype, const DVector3 &pos, // //--------------------------------------------------------------------------- -void P_SpawnBlood (const DVector3 &pos, DAngle dir, int damage, AActor *originator) +void P_SpawnBlood (const DVector3 &pos1, DAngle dir, int damage, AActor *originator) { AActor *th; PalEntry bloodcolor = originator->GetBloodColor(); PClassActor *bloodcls = originator->GetBloodType(); - + DVector3 pos = pos1; + pos.Z += pr_spawnblood.Random2() / 64.; + int bloodtype = cl_bloodtype; if (bloodcls != NULL && !(GetDefaultByType(bloodcls)->flags4 & MF4_ALLOWPARTICLES)) @@ -5142,8 +5144,7 @@ void P_SpawnBlood (const DVector3 &pos, DAngle dir, int damage, AActor *originat if (bloodcls != NULL) { - double z = pr_spawnblood.Random2 () / 64.; - th = Spawn(bloodcls, pos + DVector3(0, 0, z), NO_REPLACE); // GetBloodType already performed the replacement + th = Spawn(bloodcls, pos, NO_REPLACE); // GetBloodType already performed the replacement th->Vel.Z = 2; th->Angles.Yaw = dir; // [NG] Applying PUFFGETSOWNER to the blood will make it target the owner diff --git a/src/r_main.cpp b/src/r_main.cpp index 3577b3c3b..0a8a63512 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -692,6 +692,8 @@ void R_EnterPortal (PortalDrawseg* pds, int depth) fixed_t startx = viewx; fixed_t starty = viewy; fixed_t startz = viewz; + DVector3 savedpath[2] = { ViewPath[0], ViewPath[1] }; + int savedvisibility = camera->renderflags & RF_INVISIBLE; CurrentPortalUniq++; @@ -738,10 +740,27 @@ void R_EnterPortal (PortalDrawseg* pds, int depth) P_TranslatePortalXY(pds->src, view.X, view.Y); P_TranslatePortalZ(pds->src, view.Z); P_TranslatePortalAngle(pds->src, va); + P_TranslatePortalXY(pds->src, ViewPath[0].X, ViewPath[0].Y); + P_TranslatePortalXY(pds->src, ViewPath[1].X, ViewPath[1].Y); viewx = FLOAT2FIXED(view.X); viewy = FLOAT2FIXED(view.Y); viewz = FLOAT2FIXED(view.Z); viewangle = va.BAMs(); + + if (!r_showviewer) + { + double distp = (ViewPath[0] - ViewPath[1]).Length(); + if (distp > EQUAL_EPSILON) + { + double dist1 = (view - ViewPath[0]).Length(); + double dist2 = (view - ViewPath[1]).Length(); + + if (dist1 + dist2 < distp + 1) + { + camera->renderflags |= RF_INVISIBLE; + } + } + } } ViewAngle = AngleToFloat(viewangle); @@ -783,6 +802,7 @@ void R_EnterPortal (PortalDrawseg* pds, int depth) InSubsector = NULL; R_RenderBSPNode (nodes + numnodes - 1); R_3D_ResetClip(); // reset clips (floor/ceiling) + if (!savedvisibility) camera->renderflags &= ~RF_INVISIBLE; PlaneCycles.Clock(); R_DrawPlanes (); @@ -822,6 +842,8 @@ void R_EnterPortal (PortalDrawseg* pds, int depth) viewx = startx; viewy = starty; viewz = startz; + ViewPath[0] = savedpath[0]; + ViewPath[1] = savedpath[1]; ViewAngle = AngleToFloat(viewangle); } diff --git a/src/r_utility.cpp b/src/r_utility.cpp index f84224aad..f2908c6fa 100644 --- a/src/r_utility.cpp +++ b/src/r_utility.cpp @@ -108,6 +108,7 @@ int viewwindowy; DVector3 ViewPos; DAngle ViewAngle; DAngle ViewPitch; +DVector3 ViewPath[2]; extern "C" { @@ -590,67 +591,78 @@ void R_InterpolateView (player_t *player, double Frac, InterpolationViewer *ivie DAngle oviewangle = iview->Old.Angles.Yaw; DAngle nviewangle = iview->New.Angles.Yaw; - if ((iview->Old.Pos.X != iview->New.Pos.X || iview->Old.Pos.Y != iview->New.Pos.Y) && InterpolationPath.Size() > 0) + if (!cl_capfps) { - DVector3 view = iview->New.Pos; - - // Interpolating through line portals is a messy affair. - // What needs be done is to store the portal transitions of the camera actor as waypoints - // and then find out on which part of the path the current view lies. - // Needless to say, this doesn't work for chasecam mode. - if (!r_showviewer) + if ((iview->Old.Pos.X != iview->New.Pos.X || iview->Old.Pos.Y != iview->New.Pos.Y) && InterpolationPath.Size() > 0) { - double pathlen = 0; - double zdiff = 0; - double totalzdiff = 0; - DAngle adiff = 0.; - DAngle totaladiff = 0.; - double oviewz = iview->Old.Pos.Z; - double nviewz = iview->New.Pos.Z; - DVector3a oldpos = { { iview->Old.Pos.X, iview->Old.Pos.Y, 0 }, 0. }; - DVector3a newpos = { { iview->New.Pos.X, iview->New.Pos.Y, 0 }, 0. }; - InterpolationPath.Push(newpos); // add this to the array to simplify the loops below + DVector3 view = iview->New.Pos; - for (unsigned i = 0; i < InterpolationPath.Size(); i += 2) + // Interpolating through line portals is a messy affair. + // What needs be done is to store the portal transitions of the camera actor as waypoints + // and then find out on which part of the path the current view lies. + // Needless to say, this doesn't work for chasecam mode. + if (!r_showviewer) { - DVector3a &start = i == 0 ? oldpos : InterpolationPath[i - 1]; - DVector3a &end = InterpolationPath[i]; - pathlen += (end.pos-start.pos).Length(); - totalzdiff += start.pos.Z; - totaladiff += start.angle; - } - double interpolatedlen = Frac * pathlen; + double pathlen = 0; + double zdiff = 0; + double totalzdiff = 0; + DAngle adiff = 0.; + DAngle totaladiff = 0.; + double oviewz = iview->Old.Pos.Z; + double nviewz = iview->New.Pos.Z; + DVector3a oldpos = { { iview->Old.Pos.X, iview->Old.Pos.Y, 0 }, 0. }; + DVector3a newpos = { { iview->New.Pos.X, iview->New.Pos.Y, 0 }, 0. }; + InterpolationPath.Push(newpos); // add this to the array to simplify the loops below - for (unsigned i = 0; i < InterpolationPath.Size(); i += 2) - { - DVector3a &start = i == 0 ? oldpos : InterpolationPath[i - 1]; - DVector3a &end = InterpolationPath[i]; - double fraglen = (end.pos - start.pos).Length(); - zdiff += start.pos.Z; - adiff += start.angle; - if (fraglen <= interpolatedlen) + for (unsigned i = 0; i < InterpolationPath.Size(); i += 2) { - interpolatedlen -= fraglen; + DVector3a &start = i == 0 ? oldpos : InterpolationPath[i - 1]; + DVector3a &end = InterpolationPath[i]; + pathlen += (end.pos - start.pos).Length(); + totalzdiff += start.pos.Z; + totaladiff += start.angle; } - else + double interpolatedlen = Frac * pathlen; + + for (unsigned i = 0; i < InterpolationPath.Size(); i += 2) { - double fragfrac = interpolatedlen / fraglen; - oviewz += zdiff; - nviewz -= totalzdiff - zdiff; - oviewangle += adiff; - nviewangle -= totaladiff - adiff; - DVector2 viewpos = start.pos + (fragfrac * (end.pos - start.pos)); - ViewPos = { viewpos, oviewz + Frac * (nviewz - oviewz) }; - break; + DVector3a &start = i == 0 ? oldpos : InterpolationPath[i - 1]; + DVector3a &end = InterpolationPath[i]; + double fraglen = (end.pos - start.pos).Length(); + zdiff += start.pos.Z; + adiff += start.angle; + if (fraglen <= interpolatedlen) + { + interpolatedlen -= fraglen; + } + else + { + double fragfrac = interpolatedlen / fraglen; + oviewz += zdiff; + nviewz -= totalzdiff - zdiff; + oviewangle += adiff; + nviewangle -= totaladiff - adiff; + DVector2 viewpos = start.pos + (fragfrac * (end.pos - start.pos)); + ViewPos = { viewpos, oviewz + Frac * (nviewz - oviewz) }; + break; + } } + InterpolationPath.Pop(); + ViewPath[0] = iview->Old.Pos; } - InterpolationPath.Pop(); + } + else + { + DVector2 disp = Displacements.getOffset(oldgroup, newgroup); + ViewPos = iview->Old.Pos + (iview->New.Pos - iview->Old.Pos - disp) * Frac; + ViewPath[1] = iview->New.Pos; + ViewPath[0] = iview->Old.Pos; } } else { - DVector2 disp = Displacements.getOffset(oldgroup, newgroup); - ViewPos = iview->Old.Pos + (iview->New.Pos - iview->Old.Pos - disp) * Frac; + ViewPos = iview->New.Pos; + ViewPath[0] = ViewPath[1] = iview->New.Pos; } if (player != NULL && !(player->cheats & CF_INTERPVIEW) && diff --git a/src/r_utility.h b/src/r_utility.h index 9e2ccf3cf..06ed29654 100644 --- a/src/r_utility.h +++ b/src/r_utility.h @@ -15,6 +15,7 @@ extern DCanvas *RenderTarget; extern DVector3 ViewPos; extern DAngle ViewAngle; extern DAngle ViewPitch; +extern DVector3 ViewPath[2]; extern fixed_t viewx, viewy, viewz; extern angle_t viewangle; diff --git a/src/thingdef/thingdef_exp.h b/src/thingdef/thingdef_exp.h index b692be4ad..e56215b0f 100644 --- a/src/thingdef/thingdef_exp.h +++ b/src/thingdef/thingdef_exp.h @@ -997,6 +997,25 @@ public: void SetFunction(VMScriptFunction *func) { MyFunction = func; } }; +//========================================================================== +// +// +// +//========================================================================== + +class FxNop : public FxExpression +{ +public: + FxNop(const FScriptPosition &p) + : FxExpression(p) + { + isresolved = true; + } + ExpEmit Emit(VMFunctionBuilder *build) + { + return ExpEmit(); + } +}; FxExpression *ParseExpression (FScanner &sc, PClassActor *cls, bool mustresolve = false); diff --git a/src/thingdef/thingdef_expression.cpp b/src/thingdef/thingdef_expression.cpp index 1b570c62e..d2ee090e6 100644 --- a/src/thingdef/thingdef_expression.cpp +++ b/src/thingdef/thingdef_expression.cpp @@ -3648,6 +3648,7 @@ FxExpression *FxIfStatement::Resolve(FCompileContext &ctx) FxExpression *e = result ? WhenTrue : WhenFalse; delete (result ? WhenFalse : WhenTrue); WhenTrue = WhenFalse = NULL; + if (e == NULL) e = new FxNop(ScriptPosition); // create a dummy if this statement gets completely removed by optimizing out the constant parts. delete this; return e; }