diff --git a/src/p_maputl.c b/src/p_maputl.c index a944adf04..5da7839f3 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -544,16 +544,18 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if (delta1 > delta2) { // Below if (opentop > texbottom) { opentop = texbottom; - if ((linedef->flags & ML_MIDPEG) != 0) { - opentopslope = openbottomslope; - } + if (linedef->flags & ML_NOSKEW) + opentopslope = NULL; + else + opentopslope = linedef->midtexslope; } } else { // Above if (openbottom < textop) { openbottom = textop; - if ((linedef->flags & ML_MIDPEG) == 0) { - openbottomslope = opentopslope; - } + if (linedef->flags & ML_NOSKEW) + openbottomslope = NULL; + else + openbottomslope = linedef->midtexslope; } } } diff --git a/src/p_setup.c b/src/p_setup.c index 41487d702..3dd3d942c 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1113,6 +1113,8 @@ static void P_InitializeLinedef(line_t *ld) ld->callcount = 0; ld->secportal = UINT32_MAX; + ld->midtexslope = NULL; + // cph 2006/09/30 - fix sidedef errors right away. // cph 2002/07/20 - these errors are fatal if not fixed, so apply them for (j = 0; j < 2; j++) diff --git a/src/p_slopes.c b/src/p_slopes.c index e75d36ede..11327506e 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -28,6 +28,8 @@ pslope_t *slopelist = NULL; UINT16 slopecount = 0; +static void P_UpdateMidtextureSlopesForSector(sector_t *sector); + // Calculate line normal void P_CalculateSlopeNormal(pslope_t *slope) { @@ -212,6 +214,9 @@ void T_DynamicSlopeLine (dynlineplanethink_t* th) slope->zangle = R_PointToAngle2(0, 0, th->extent, -zdelta); slope->moved = true; P_CalculateSlopeNormal(slope); + P_UpdateMidtextureSlopesForSector(srcline->frontsector); + if (srcline->backsector) + P_UpdateMidtextureSlopesForSector(srcline->backsector); } } @@ -232,6 +237,12 @@ void T_DynamicSlopeVert (dynvertexplanethink_t* th) } ReconfigureViaVertexes(th->slope, th->vex[0], th->vex[1], th->vex[2]); + + for (i = 0; i < 3; i++) + { + if (th->secs[i]) + P_UpdateMidtextureSlopesForSector(th->secs[i]); + } } static inline void P_AddDynLineSlopeThinker (pslope_t* slope, dynplanetype_t type, line_t* sourceline, fixed_t extent) @@ -758,6 +769,111 @@ pslope_t *P_MakeSlopeViaEquationConstants(const double a, const double b, const return ret; } +static pslope_t *P_GetReferenceSlopeForMidtexture(line_t *line) +{ + if (line->flags & ML_MIDPEG) + { + // Line has ML_MIDPEG, so use the floor slope + fixed_t frontheight = P_GetSectorFloorZAt(line->frontsector, line->v1->x, line->v1->y); + fixed_t backheight = P_GetSectorFloorZAt(line->backsector, line->v1->x, line->v1->y); + + if (frontheight > backheight) + { + return line->frontsector->f_slope; + } + else + { + return line->backsector->f_slope; + } + } + else + { + // Line does not have ML_MIDPEG, so use the ceiling slope + fixed_t frontheight = P_GetSectorCeilingZAt(line->frontsector, line->v1->x, line->v1->y); + fixed_t backheight = P_GetSectorCeilingZAt(line->backsector, line->v1->x, line->v1->y); + + if (frontheight < backheight) + { + return line->frontsector->c_slope; + } + else + { + return line->backsector->c_slope; + } + } + + return NULL; +} + +// Updates a slope for a solid midtexture based on the slope of the sector it's in. +static void P_UpdateSolidMidtextureSlope(line_t *line, pslope_t *ref) +{ + pslope_t *slope = line->midtexslope; + + if (ref == NULL) + return; + + // Set origin + vector3_t origin; + origin.x = line->v1->x; + origin.y = line->v1->y; + origin.z = P_GetSlopeZAt(ref, origin.x, origin.y); + FV3_Copy(&slope->o, &origin); + + // Get where the line ends + vector3_t point; + point.x = line->v2->x; + point.y = line->v2->y; + point.z = P_GetSlopeZAt(ref, point.x, point.y); + + // Get length of the line + fixed_t extent = R_PointToDist2(0, 0, line->dx, line->dy); + + // Precalculate variables + slope->zdelta = FixedDiv(origin.z - point.z, extent); + slope->zangle = R_PointToAngle2(0, origin.z, extent, point.z); + slope->xydirection = line->angle; + + // Precalculate the direction + vector2_t dir; + dir.x = FixedMul(FINECOSINE(slope->zangle >> ANGLETOFINESHIFT), FINECOSINE((slope->xydirection+ANGLE_180) >> ANGLETOFINESHIFT)); + dir.y = FixedMul(FINECOSINE(slope->zangle >> ANGLETOFINESHIFT), FINESINE((slope->xydirection+ANGLE_180) >> ANGLETOFINESHIFT)); + FV2_Copy(&slope->d, &dir); + + P_CalculateSlopeNormal(slope); + + // Calling P_CalculateSlopeVectors is not necessary. + slope->moved = true; +} + +// Goes through every line in the sector and updates the midtexture slope if it is present +static void P_UpdateMidtextureSlopesForSector(sector_t *sector) +{ + for (size_t i = 0; i < sector->linecount; i++) + { + if (sector->lines[i]->midtexslope != NULL) + P_UpdateSolidMidtextureSlope(sector->lines[i], P_GetReferenceSlopeForMidtexture(sector->lines[i])); + } +} + +// Creates a solid midtexture slope for the line if possible +static void P_CreateSolidMidtextureSlope(line_t *line) +{ + if (line->backsector == NULL) // Ignore single-sided lines (of course) + return; + + if ((line->flags & ML_MIDSOLID) == 0) // Ignore if the midtexture is not solid + return; + + pslope_t *ref = P_GetReferenceSlopeForMidtexture(line); + if (ref) + { + line->midtexslope = Slope_Add(ref->flags & SL_NOPHYSICS); + + P_UpdateSolidMidtextureSlope(line, ref); + } +} + /// Initializes and reads the slopes from the map data. void P_SpawnSlopes(const boolean fromsave) { size_t i; @@ -785,14 +901,21 @@ void P_SpawnSlopes(const boolean fromsave) { /// Copies slopes from tagged sectors via line specials. /// \note Doesn't actually copy, but instead they share the same pointers. + // Also, creates midtexture slopes. for (i = 0; i < numlines; i++) - switch (lines[i].special) + { + line_t *line = &lines[i]; + + switch (line->special) { case 720: - P_CopySectorSlope(&lines[i]); + P_CopySectorSlope(line); default: break; } + + P_CreateSolidMidtextureSlope(line); + } } /// Initializes slopes. diff --git a/src/r_defs.h b/src/r_defs.h index da4dd2d70..7a6f518ee 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -612,6 +612,8 @@ typedef struct line_s INT16 callcount; // no. of calls left before triggering, for the "X calls" linedef specials, defaults to 0 UINT32 secportal; // transferred sector portal + + struct pslope_s *midtexslope; } line_t; typedef struct