diff --git a/src/k_terrain.c b/src/k_terrain.c index 0cb99dded..cd5841567 100644 --- a/src/k_terrain.c +++ b/src/k_terrain.c @@ -1107,6 +1107,10 @@ static void K_ParseTerrainParameter(size_t i, char *param, char *val) { terrain->trickPanel = (UINT8)get_number(val); // trick panel strength enum? } + else if (stricmp(param, "floorClip") == 0) + { + terrain->floorClip = FLOAT_TO_FIXED(atof(val)); + } else if (stricmp(param, "liquid") == 0) { K_FlagBoolean(&terrain->flags, TRF_LIQUID, val); diff --git a/src/k_terrain.h b/src/k_terrain.h index c83f199d2..016fde820 100644 --- a/src/k_terrain.h +++ b/src/k_terrain.h @@ -90,6 +90,7 @@ typedef struct terrain_s UINT8 offroad; // The default offroad level of this texture. INT16 damageType; // The default damage type of this texture. (Negative means no damage). UINT8 trickPanel; // Trick panel strength + fixed_t floorClip; // Offset for sprites on this ground UINT32 flags; // Flag values (see: terrain_flags_t) } terrain_t; diff --git a/src/r_segs.c b/src/r_segs.c index d8d9adfd5..7f190ea3f 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -84,7 +84,7 @@ static fixed_t *maskedtextureheight = NULL; // multi-patch textures. They are not normally needed as multi-patch // textures don't have holes in it. At least not for now. -static void R_Render2sidedMultiPatchColumn(column_t *column, column_t *brightmap) +static void R_Render2sidedMultiPatchColumn(column_t *column, column_t *brightmap, INT32 baseclip) { INT32 topscreen, bottomscreen; @@ -107,6 +107,9 @@ static void R_Render2sidedMultiPatchColumn(column_t *column, column_t *brightmap if (dc_yl <= mceilingclip[dc_x]) dc_yl = mceilingclip[dc_x] + 1; + if (dc_yh >= baseclip && baseclip != -1) + dc_yh = baseclip; + if (dc_yl >= vid.height || dc_yh < 0) return; @@ -144,7 +147,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) fixed_t height, realbot; lightlist_t *light; r_lightlist_t *rlight; - void (*colfunc_2s)(column_t *, column_t *); + void (*colfunc_2s)(column_t *, column_t *, INT32); line_t *ldef; sector_t *front, *back; INT32 times, repeats; @@ -457,7 +460,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) if (windowbottom >= realbot) { windowbottom = realbot; - colfunc_2s(col, bmCol); + colfunc_2s(col, bmCol, -1); for (i++; i < dc_numlights; i++) { rlight = &dc_lightlist[i]; @@ -466,7 +469,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) continue; } - colfunc_2s(col, bmCol); + colfunc_2s(col, bmCol, -1); windowtop = windowbottom + 1; dc_colormap = rlight->rcolormap; dc_fullbright = colormaps; @@ -478,7 +481,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) } windowbottom = realbot; if (windowtop < windowbottom) - colfunc_2s(col, bmCol); + colfunc_2s(col, bmCol, -1); spryscale += rw_scalestep; continue; @@ -561,7 +564,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) } else #endif - colfunc_2s(col, bmCol); + colfunc_2s(col, bmCol, -1); } spryscale += rw_scalestep; } @@ -571,10 +574,11 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) } // Loop through R_DrawMaskedColumn calls -static void R_DrawRepeatMaskedColumn(column_t *col, column_t *bm) +static void R_DrawRepeatMaskedColumn(column_t *col, column_t *bm, INT32 baseclip) { - while (sprtopscreen < sprbotscreen) { - R_DrawMaskedColumn(col, bm); + while (sprtopscreen < sprbotscreen) + { + R_DrawMaskedColumn(col, bm, baseclip); if ((INT64)sprtopscreen + dc_texheight*spryscale > (INT64)INT32_MAX) // prevent overflow sprtopscreen = INT32_MAX; else @@ -582,10 +586,10 @@ static void R_DrawRepeatMaskedColumn(column_t *col, column_t *bm) } } -static void R_DrawRepeatFlippedMaskedColumn(column_t *col, column_t *bm) +static void R_DrawRepeatFlippedMaskedColumn(column_t *col, column_t *bm, INT32 baseclip) { do { - R_DrawFlippedMaskedColumn(col, bm); + R_DrawFlippedMaskedColumn(col, bm, baseclip); sprtopscreen += dc_texheight*spryscale; } while (sprtopscreen < sprbotscreen); } @@ -632,7 +636,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) fixed_t left_top, left_bottom; // needed here for slope skewing pslope_t *skewslope = NULL; - void (*colfunc_2s) (column_t *, column_t *); + void (*colfunc_2s) (column_t *, column_t *, INT32); // Calculate light table. // Use different light tables @@ -1051,7 +1055,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) { windowbottom = sprbotscreen; // draw the texture - colfunc_2s (col, bmCol); + colfunc_2s (col, bmCol, -1); for (i++; i < dc_numlights; i++) { rlight = &dc_lightlist[i]; @@ -1062,7 +1066,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) continue; } // draw the texture - colfunc_2s (col, bmCol); + colfunc_2s (col, bmCol, -1); if (solid) windowtop = bheight; else @@ -1081,7 +1085,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) windowbottom = sprbotscreen; // draw the texture, if there is any space left if (windowtop < windowbottom) - colfunc_2s (col, bmCol); + colfunc_2s (col, bmCol, -1); spryscale += rw_scalestep; continue; @@ -1108,7 +1112,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps); // draw the texture - colfunc_2s (col, bmCol); + colfunc_2s (col, bmCol, -1); spryscale += rw_scalestep; } } diff --git a/src/r_things.c b/src/r_things.c index c0e727fd9..1a0e033a7 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -635,7 +635,7 @@ INT16 *mceilingclip; fixed_t spryscale = 0, sprtopscreen = 0, sprbotscreen = 0; fixed_t windowtop = 0, windowbottom = 0; -void R_DrawMaskedColumn(column_t *column, column_t *brightmap) +void R_DrawMaskedColumn(column_t *column, column_t *brightmap, INT32 baseclip) { INT32 topscreen; INT32 bottomscreen; @@ -673,11 +673,15 @@ void R_DrawMaskedColumn(column_t *column, column_t *brightmap) dc_yh = mfloorclip[dc_x]-1; if (dc_yl <= mceilingclip[dc_x]) dc_yl = mceilingclip[dc_x]+1; + if (dc_yl < 0) dc_yl = 0; if (dc_yh >= vid.height) // dc_yl must be < vid.height, so reduces number of checks in tight loop dc_yh = vid.height - 1; + if (dc_yh >= baseclip && baseclip != -1) + dc_yh = baseclip; + if (dc_yl <= dc_yh && dc_yh > 0) { dc_source = (UINT8 *)column + 3; @@ -711,7 +715,7 @@ void R_DrawMaskedColumn(column_t *column, column_t *brightmap) INT32 lengthcol; // column->length : for flipped column function pointers and multi-patch on 2sided wall = texture->height -void R_DrawFlippedMaskedColumn(column_t *column, column_t *brightmap) +void R_DrawFlippedMaskedColumn(column_t *column, column_t *brightmap, INT32 baseclip) { INT32 topscreen; INT32 bottomscreen; @@ -750,6 +754,10 @@ void R_DrawFlippedMaskedColumn(column_t *column, column_t *brightmap) dc_yh = mfloorclip[dc_x]-1; if (dc_yl <= mceilingclip[dc_x]) dc_yl = mceilingclip[dc_x]+1; + + if (dc_yh >= baseclip && baseclip != -1) + dc_yh = baseclip; + if (dc_yl < 0) dc_yl = 0; if (dc_yh >= vid.height) // dc_yl must be < vid.height, so reduces number of checks in tight loop @@ -855,7 +863,7 @@ UINT8 *R_GetSpriteTranslation(vissprite_t *vis) static void R_DrawVisSprite(vissprite_t *vis) { column_t *column; - void (*localcolfunc)(column_t *, column_t *); + void (*localcolfunc)(column_t *, column_t *, INT32); INT32 texturecolumn; INT32 pwidth; fixed_t frac; @@ -863,6 +871,7 @@ static void R_DrawVisSprite(vissprite_t *vis) fixed_t this_scale = vis->thingscale; INT32 x1, x2; INT64 overflow_test; + INT32 baseclip = -1; if (!patch) return; @@ -938,8 +947,10 @@ static void R_DrawVisSprite(vissprite_t *vis) if (!(vis->cut & SC_PRECIP) && vis->mobj->skin && ((skin_t *)vis->mobj->skin)->flags & SF_HIRES) this_scale = FixedMul(this_scale, ((skin_t *)vis->mobj->skin)->highresscale); + if (this_scale <= 0) this_scale = 1; + if (this_scale != FRACUNIT) { if (!(vis->cut & SC_ISSCALED)) @@ -961,6 +972,16 @@ static void R_DrawVisSprite(vissprite_t *vis) dc_iscale = FixedDiv(FRACUNIT, vis->scale); } + if (vis->floorclip) + { + sprbotscreen = sprtopscreen + FixedMul(patch->height << FRACBITS, spryscale); + baseclip = (sprbotscreen - FixedMul(vis->floorclip, spryscale)) >> FRACBITS; + } + else + { + baseclip = -1; + } + x1 = vis->x1; x2 = vis->x2; @@ -1001,7 +1022,7 @@ static void R_DrawVisSprite(vissprite_t *vis) column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[texturecolumn])); - localcolfunc (column, NULL); + localcolfunc (column, NULL, baseclip); } } else if (vis->cut & SC_SHEAR) @@ -1023,7 +1044,7 @@ static void R_DrawVisSprite(vissprite_t *vis) #endif sprtopscreen = (centeryfrac - FixedMul(dc_texturemid, spryscale)); - localcolfunc (column, NULL); + localcolfunc (column, NULL, baseclip); } } else @@ -1043,7 +1064,7 @@ static void R_DrawVisSprite(vissprite_t *vis) #else column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[frac>>FRACBITS])); #endif - localcolfunc (column, NULL); + localcolfunc (column, NULL, baseclip); } } @@ -1117,7 +1138,7 @@ static void R_DrawPrecipitationVisSprite(vissprite_t *vis) #else column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[frac>>FRACBITS])); #endif - R_DrawMaskedColumn(column, NULL); + R_DrawMaskedColumn(column, NULL, -1); } R_SetColumnFunc(BASEDRAWFUNC, false); @@ -1610,6 +1631,8 @@ static void R_ProjectSprite(mobj_t *thing) fixed_t this_scale; fixed_t spritexscale, spriteyscale; + fixed_t floorClip = 0; + // rotsprite fixed_t spr_width, spr_height; fixed_t spr_offset, spr_topoffset; @@ -2163,6 +2186,11 @@ static void R_ProjectSprite(mobj_t *thing) return; } + if (thing->terrain != NULL) + { + floorClip = thing->terrain->floorClip; + } + // store information in a vissprite vis = R_NewVisSprite(); vis->renderflags = thing->renderflags; @@ -2179,7 +2207,8 @@ static void R_ProjectSprite(mobj_t *thing) vis->thingheight = thing->height; vis->pz = interp.z; vis->pzt = vis->pz + vis->thingheight; - vis->texturemid = FixedDiv(gzt - viewz, spriteyscale); + vis->floorclip = floorClip; + vis->texturemid = FixedDiv(gzt - viewz - FixedMul(vis->floorclip, mapobjectscale), spriteyscale); vis->scalestep = scalestep; vis->paperoffset = paperoffset; vis->paperdistance = paperdistance; @@ -2441,6 +2470,7 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing) vis->thingheight = 4*FRACUNIT; vis->pz = interp.z; vis->pzt = vis->pz + vis->thingheight; + vis->floorclip = 0; vis->texturemid = vis->gzt - viewz; vis->scalestep = 0; vis->paperdistance = 0; diff --git a/src/r_things.h b/src/r_things.h index b89645fff..881de773e 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -47,8 +47,8 @@ extern fixed_t windowtop; extern fixed_t windowbottom; extern INT32 lengthcol; -void R_DrawMaskedColumn(column_t *column, column_t *brightmap); -void R_DrawFlippedMaskedColumn(column_t *column, column_t *brightmap); +void R_DrawMaskedColumn(column_t *column, column_t *brightmap, INT32 baseclip); +void R_DrawFlippedMaskedColumn(column_t *column, column_t *brightmap, INT32 baseclip); // ---------------- // SPRITE RENDERING @@ -217,6 +217,8 @@ typedef struct vissprite_s INT16 clipbot[MAXVIDWIDTH], cliptop[MAXVIDWIDTH]; INT32 dispoffset; // copy of info->dispoffset, affects ordering but not drawing + + fixed_t floorclip; // Cut off your tires in tall grass } vissprite_t; extern UINT32 visspritecount;