From 32bbec7cadbea9d5ca318030a29eaacaa921795d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 7 Apr 2016 14:14:44 +0200 Subject: [PATCH 1/4] - fixed: the random offset that gets used when spawning blood applies to both sprites and particles, not just sprites. --- src/p_mobj.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) 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 From 47e20aead442a3e0b468e873630d426737bf036f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 7 Apr 2016 17:13:56 +0200 Subject: [PATCH 2/4] - disallow crossable portals on one-sided linedefs which do not belong to a polyobject. Sadly the mappers cannot be trusted to use a feature correctly. Despite repeatedly telling that portals on one-sided lines are problematic, everybody seems to do it this way - and then report bugs if it doesn't work. Under such circumstances the only safe option is to block such portals entirely. See http://forum.zdoom.org/viewtopic.php?f=2&t=51511&p=898522#p898522 for a typical example of the problems this might cause. --- src/p_map.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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; From 0cbdb9ab723d9b8875a2bf98caa42c7d8866d77a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 7 Apr 2016 19:35:01 +0200 Subject: [PATCH 3/4] - handle display of player sprite during portal transition properly. This checks if the current viewpoint lies on the interpolation path, translated by all active portals. --- src/r_main.cpp | 22 ++++++++++ src/r_utility.cpp | 108 +++++++++++++++++++++++++--------------------- src/r_utility.h | 1 + 3 files changed, 83 insertions(+), 48 deletions(-) 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 94c2b0c00..f2908c6fa 100644 --- a/src/r_utility.cpp +++ b/src/r_utility.cpp @@ -85,7 +85,7 @@ struct InterpolationViewer static TArray PastViewers; static FRandom pr_torchflicker ("TorchFlicker"); static FRandom pr_hom; -static bool NoInterpolateView; +bool NoInterpolateView; // GL needs access to this. static TArray InterpolationPath; // PUBLIC DATA DEFINITIONS ------------------------------------------------- @@ -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; From 58002f7f965cb3933df777d3f750c9c00cc55348 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 7 Apr 2016 20:31:12 +0200 Subject: [PATCH 4/4] - fixed: an 'if' that gets completely optimized away by a constant 'false' condition should not make the entire function disappear. --- src/thingdef/thingdef_exp.h | 19 +++++++++++++++++++ src/thingdef/thingdef_expression.cpp | 1 + 2 files changed, 20 insertions(+) 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; }