diff --git a/.travis.yml b/.travis.yml index 54c5901d0..9878e6ca9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,8 +30,8 @@ addons: before_script: - mkdir -p $HOME/srb2_cache - - wget --verbose --server-response -c http://rosenthalcastle.org/srb2/SRB2-v2114-assets.7z -O $HOME/srb2_cache/SRB2-v2114-assets.7z - - 7z x $HOME/srb2_cache/SRB2-v2114-assets.7z -oassets + - wget --verbose --server-response -c http://rosenthalcastle.org/srb2/SRB2-v2115-assets-2.7z -O $HOME/srb2_cache/SRB2-v2115-assets-2.7z + - 7z x $HOME/srb2_cache/SRB2-v2115-assets-2.7z -oassets - mkdir build - cd build - cmake .. diff --git a/src/config.h.in b/src/config.h.in index eef4fec13..5f06ec45d 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -29,14 +29,14 @@ #else /* Manually defined asset hashes for non-CMake builds - * Last updated 2000 / 00 / 00 + * Last updated 2015 / 05 / 03 */ #define ASSET_HASH_SRB2_SRB "c1b9577687f8a795104aef4600720ea7" #define ASSET_HASH_ZONES_DTA "303838c6c534d9540288360fa49cca60" #define ASSET_HASH_PLAYER_DTA "cfca0f1c73023cbbd8f844f45480f799" #define ASSET_HASH_RINGS_DTA "85901ad4bf94637e5753d2ac2c03ea26" #ifdef USE_PATCH_DTA -#define ASSET_HASH_PATCH_DTA "0c66790502e648bfce90fdc5bb15722e" +#define ASSET_HASH_PATCH_DTA "dbbf8bc6121618ee3be2d5b14650429b" #endif #endif diff --git a/src/d_netcmd.c b/src/d_netcmd.c index c5be2f29d..2d95904e0 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1113,6 +1113,13 @@ static void SendNameAndColor(void) players[consoleplayer].mo->color = (UINT8)players[consoleplayer].skincolor; } } + else + { + cv_skin.value = players[consoleplayer].skin; + CV_StealthSet(&cv_skin, skins[players[consoleplayer].skin].name); + // will always be same as current + SetPlayerSkin(consoleplayer, cv_skin.string); + } return; } @@ -1230,6 +1237,13 @@ static void SendNameAndColor2(void) players[secondplaya].mo->color = players[secondplaya].skincolor; } } + else + { + cv_skin2.value = players[secondplaya].skin; + CV_StealthSet(&cv_skin2, skins[players[secondplaya].skin].name); + // will always be same as current + SetPlayerSkin(secondplaya, cv_skin2.string); + } return; } diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 3ab3bb028..d3a04f3c7 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -39,7 +39,9 @@ #include "../st_stuff.h" #include "../i_system.h" #include "../m_cheat.h" - +#ifdef ESLOPE +#include "../p_slopes.h" +#endif #include "hw_md2.h" #define R_FAKEFLOORS @@ -535,16 +537,42 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, fixed_t fi angle_t angle = 0; FSurfaceInfo Surf; fixed_t tempxsow, tempytow; +#ifdef ESLOPE + pslope_t *slope = NULL; +#endif static FOutVector *planeVerts = NULL; static UINT16 numAllocedPlaneVerts = 0; - (void)sector; + (void)sector; ///@TODO remove shitty unused variable // no convex poly were generated for this subsector if (!xsub->planepoly) return; +#ifdef ESLOPE + // Get the slope pointer to simplify future code + if (FOFsector) + { + if (FOFsector->f_slope && FOFsector->floorheight == fixedheight) + slope = FOFsector->f_slope; + else if (FOFsector->c_slope && FOFsector->ceilingheight == fixedheight) + slope = FOFsector->c_slope; + } + else + { + // Use fixedheight to determine whether to check floor or ceiling because I hate my life + if (gr_frontsector->f_slope && gr_frontsector->floorheight == fixedheight) + slope = gr_frontsector->f_slope; + else if (gr_frontsector->c_slope && gr_frontsector->ceilingheight == fixedheight) + slope = gr_frontsector->c_slope; + } + + // Set fixedheight to the slope's height from our viewpoint, if we have a slope + if (slope) + fixedheight = P_GetZAt(slope, viewx, viewy); +#endif + height = FIXED_TO_FLOAT(fixedheight); pv = xsub->planepoly->pts; @@ -610,7 +638,12 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, fixed_t fi if (FOFsector != NULL) { +#ifdef ESLOPE + if ((slope && slope == FOFsector->f_slope) + || fixedheight == FOFsector->floorheight) // it's a floor +#else if (fixedheight == FOFsector->floorheight) // it's a floor +#endif { scrollx = FIXED_TO_FLOAT(FOFsector->floor_xoffs)/fflatsize; scrolly = FIXED_TO_FLOAT(FOFsector->floor_yoffs)/fflatsize; @@ -625,7 +658,12 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, fixed_t fi } else if (gr_frontsector) { +#ifdef ESLOPE + if ((slope && slope == gr_frontsector->f_slope) + || fixedheight == gr_frontsector->floorheight) // it's a floor +#else if (fixedheight < dup_viewz) // it's a floor +#endif { scrollx = FIXED_TO_FLOAT(gr_frontsector->floor_xoffs)/fflatsize; scrolly = FIXED_TO_FLOAT(gr_frontsector->floor_yoffs)/fflatsize; @@ -680,6 +718,14 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, fixed_t fi v3d->x = pv->x; v3d->y = height; v3d->z = pv->y; + +#ifdef ESLOPE + if (slope) + { + fixedheight = P_GetZAt(slope, FLOAT_TO_FIXED(pv->x), FLOAT_TO_FIXED(pv->y)); + v3d->y = FIXED_TO_FLOAT(fixedheight); + } +#endif } // only useful for flat coloured triangles @@ -697,6 +743,11 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, fixed_t fi { sector_t *psector = gr_frontsector; +#ifdef ESLOPE + if (slope) + fixedheight = P_GetZAt(slope, psector->soundorg.x, psector->soundorg.y); +#endif + if (psector->ffloors) { ffloor_t *caster = psector->lightlist[R_GetPlaneLight(psector, fixedheight, false)].caster; @@ -1033,23 +1084,50 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, lightlist. This may also include leaving out parts of the wall that can't be seen */ GLTexture_t * glTex; + float realtop, realbot, top, bot; float pegt, pegb, pegmul; float height = 0.0f, bheight = 0.0f; + +#ifdef ESLOPE + float endrealtop, endrealbot, endtop, endbot; + float endpegt, endpegb, endpegmul; + float endheight = 0.0f, endbheight = 0.0f; + + fixed_t v1x = FLOAT_TO_FIXED(wallVerts[0].x); + fixed_t v1y = FLOAT_TO_FIXED(wallVerts[0].y); + fixed_t v2x = FLOAT_TO_FIXED(wallVerts[1].x); + fixed_t v2y = FLOAT_TO_FIXED(wallVerts[1].y); + // compiler complains when P_GetZAt is used in FLOAT_TO_FIXED directly + // use this as a temp var to store P_GetZAt's return value each time + fixed_t temp; +#endif + INT32 solid, i; lightlist_t * list = sector->lightlist; const UINT8 alpha = Surf->FlatColor.s.alpha; FUINT lightnum; extracolormap_t *colormap; - realtop = top = wallVerts[2].y; + realtop = top = wallVerts[3].y; realbot = bot = wallVerts[0].y; - pegt = wallVerts[2].t; + pegt = wallVerts[3].t; pegb = wallVerts[0].t; pegmul = (pegb - pegt) / (top - bot); +#ifdef ESLOPE + endrealtop = endtop = wallVerts[2].y; + endrealbot = endbot = wallVerts[1].y; + endpegt = wallVerts[2].t; + endpegb = wallVerts[1].t; + endpegmul = (endpegb - endpegt) / (endtop - endbot); +#endif + for (i = 1; i < sector->numlights; i++) { +#ifdef ESLOPE + if (endtop < endrealbot) +#endif if (top < realbot) return; @@ -1082,14 +1160,45 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, if (cutflag == FF_CUTSOLIDS) // These are regular walls sent in from StoreWallRange, they shouldn't be cut from this solid = false; +#ifdef ESLOPE + if (list[i].slope) + { + temp = P_GetZAt(list[i].slope, v1x, v1y); + height = FIXED_TO_FLOAT(temp); + temp = P_GetZAt(list[i].slope, v2x, v2y); + endheight = FIXED_TO_FLOAT(temp); + } + else + height = endheight = FIXED_TO_FLOAT(list[i].height); + if (solid) + { + if (*list[i].caster->b_slope) + { + temp = P_GetZAt(*list[i].caster->b_slope, v1x, v1y); + bheight = FIXED_TO_FLOAT(temp); + temp = P_GetZAt(*list[i].caster->b_slope, v2x, v2y); + endbheight = FIXED_TO_FLOAT(temp); + } + else + bheight = endbheight = FIXED_TO_FLOAT(*list[i].caster->bottomheight); + } +#else height = FIXED_TO_FLOAT(list[i].height); if (solid) bheight = FIXED_TO_FLOAT(*list[i].caster->bottomheight); +#endif +#ifdef ESLOPE + if (endheight >= endtop) +#endif if (height >= top) { if (solid && top > bheight) top = bheight; +#ifdef ESLOPE + if (solid && endtop > endbheight) + endtop = endbheight; +#endif continue; } @@ -1099,6 +1208,13 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, if (bot < realbot) bot = realbot; +#ifdef ESLOPE + endbot = endheight; + + if (endbot < endrealbot) + endbot = endrealbot; +#endif + // colormap test if (list[i-1].caster) { @@ -1113,13 +1229,25 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, Surf->FlatColor.s.alpha = alpha; +#ifdef ESLOPE + wallVerts[3].t = pegt + ((realtop - top) * pegmul); + wallVerts[2].t = endpegt + ((endrealtop - endtop) * endpegmul); + wallVerts[0].t = pegt + ((realtop - bot) * pegmul); + wallVerts[1].t = endpegt + ((endrealtop - endbot) * endpegmul); + // set top/bottom coords + wallVerts[3].y = top; + wallVerts[2].y = endtop; + wallVerts[0].y = bot; + wallVerts[1].y = endbot; +#else wallVerts[3].t = wallVerts[2].t = pegt + ((realtop - top) * pegmul); wallVerts[0].t = wallVerts[1].t = pegt + ((realtop - bot) * pegmul); // set top/bottom coords wallVerts[2].y = wallVerts[3].y = top; wallVerts[0].y = wallVerts[1].y = bot; +#endif glTex = HWR_GetTexture(texnum); if (cutflag & FF_TRANSLUCENT) @@ -1133,9 +1261,19 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, top = bheight; else top = height; +#ifdef ESLOPE + if (solid) + endtop = endbheight; + else + endtop = endheight; +#endif } bot = realbot; +#ifdef ESLOPE + endbot = endrealbot; + if (endtop <= endrealbot) +#endif if (top <= realbot) return; @@ -1151,12 +1289,25 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum, } Surf->FlatColor.s.alpha = alpha; - wallVerts[3].t = wallVerts[2].t = pegt + ((realtop - top) * pegmul); - wallVerts[0].t = wallVerts[1].t = pegt + ((realtop - bot) * pegmul); +#ifdef ESLOPE + wallVerts[3].t = pegt + ((realtop - top) * pegmul); + wallVerts[2].t = endpegt + ((endrealtop - endtop) * endpegmul); + wallVerts[0].t = pegt + ((realtop - bot) * pegmul); + wallVerts[1].t = endpegt + ((endrealtop - endbot) * endpegmul); // set top/bottom coords - wallVerts[2].y = wallVerts[3].y = top; - wallVerts[0].y = wallVerts[1].y = bot; + wallVerts[3].y = top; + wallVerts[2].y = endtop; + wallVerts[0].y = bot; + wallVerts[1].y = endbot; +#else + wallVerts[3].t = wallVerts[2].t = pegt + ((realtop - top) * pegmul); + wallVerts[0].t = wallVerts[1].t = pegt + ((realtop - bot) * pegmul); + + // set top/bottom coords + wallVerts[2].y = wallVerts[3].y = top; + wallVerts[0].y = wallVerts[1].y = bot; +#endif glTex = HWR_GetTexture(texnum); if (cutflag & FF_TRANSLUCENT) @@ -1304,11 +1455,19 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) fixed_t worldtop, worldbottom; fixed_t worldhigh = 0, worldlow = 0; +#ifdef ESLOPE + fixed_t worldtopslope, worldbottomslope; + fixed_t worldhighslope = 0, worldlowslope = 0; + fixed_t v1x, v1y, v2x, v2y; +#endif GLTexture_t *grTex = NULL; float cliplow = 0.0f, cliphigh = 0.0f; INT32 gr_midtexture; fixed_t h, l; // 3D sides and 2s middle textures +#ifdef ESLOPE + fixed_t hS, lS; +#endif FUINT lightnum = 0; // shut up compiler extracolormap_t *colormap; @@ -1320,22 +1479,56 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) gr_sidedef = gr_curline->sidedef; gr_linedef = gr_curline->linedef; - if (gr_frontsector->heightsec != -1) - { - worldtop = sectors[gr_frontsector->heightsec].ceilingheight; - worldbottom = sectors[gr_frontsector->heightsec].floorheight; - } - else - { - worldtop = gr_frontsector->ceilingheight; - worldbottom = gr_frontsector->floorheight; - } - vs.x = ((polyvertex_t *)gr_curline->v1)->x; vs.y = ((polyvertex_t *)gr_curline->v1)->y; ve.x = ((polyvertex_t *)gr_curline->v2)->x; ve.y = ((polyvertex_t *)gr_curline->v2)->y; +#ifdef ESLOPE + v1x = FLOAT_TO_FIXED(vs.x); + v1y = FLOAT_TO_FIXED(vs.y); + v2x = FLOAT_TO_FIXED(ve.x); + v2y = FLOAT_TO_FIXED(ve.y); +#endif + + if (gr_frontsector->heightsec != -1) + { +#ifdef ESLOPE + worldtop = worldtopslope = sectors[gr_frontsector->heightsec].ceilingheight; + worldbottom = worldbottomslope = sectors[gr_frontsector->heightsec].floorheight; +#else + worldtop = sectors[gr_frontsector->heightsec].ceilingheight; + worldbottom = sectors[gr_frontsector->heightsec].floorheight; +#endif + } + else + { +#ifdef ESLOPE + if (gr_frontsector->c_slope) + { + worldtop = P_GetZAt(gr_frontsector->c_slope, v1x, v1y); + worldtopslope = P_GetZAt(gr_frontsector->c_slope, v2x, v2y); + } + else + { + worldtop = worldtopslope = gr_frontsector->ceilingheight; + } + + if (gr_frontsector->f_slope) + { + worldbottom = P_GetZAt(gr_frontsector->f_slope, v1x, v1y); + worldbottomslope = P_GetZAt(gr_frontsector->f_slope, v2x, v2y); + } + else + { + worldbottom = worldbottomslope = gr_frontsector->floorheight; + } +#else + worldtop = gr_frontsector->ceilingheight; + worldbottom = gr_frontsector->floorheight; +#endif + } + // remember vertices ordering // 3--2 // | /| @@ -1379,13 +1572,40 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) // two sided line if (gr_backsector->heightsec != -1) { +#ifdef ESLOPE + worldhigh = worldhighslope = sectors[gr_backsector->heightsec].ceilingheight; + worldlow = worldlowslope = sectors[gr_backsector->heightsec].floorheight; +#else worldhigh = sectors[gr_backsector->heightsec].ceilingheight; worldlow = sectors[gr_backsector->heightsec].floorheight; +#endif } else { +#ifdef ESLOPE + if (gr_backsector->c_slope) + { + worldhigh = P_GetZAt(gr_backsector->c_slope, v1x, v1y); + worldhighslope = P_GetZAt(gr_backsector->c_slope, v2x, v2y); + } + else + { + worldhigh = worldhighslope = gr_backsector->ceilingheight; + } + + if (gr_backsector->f_slope) + { + worldlow = P_GetZAt(gr_backsector->f_slope, v1x, v1y); + worldlowslope = P_GetZAt(gr_backsector->f_slope, v2x, v2y); + } + else + { + worldlow = worldlowslope = gr_backsector->floorheight; + } +#else worldhigh = gr_backsector->ceilingheight; worldlow = gr_backsector->floorheight; +#endif } // hack to allow height changes in outdoor areas @@ -1394,10 +1614,18 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) gr_backsector->ceilingpic == skyflatnum) { worldtop = worldhigh; +#ifdef ESLOPE + worldtopslope = worldhighslope; +#endif } // check TOP TEXTURE - if (worldhigh < worldtop && texturetranslation[gr_sidedef->toptexture]) + if (( +#ifdef ESLOPE + worldhighslope < worldtopslope || +#endif + worldhigh < worldtop + ) && texturetranslation[gr_sidedef->toptexture]) { if (drawtextured) { @@ -1408,8 +1636,15 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) // PEGGING if (gr_linedef->flags & ML_DONTPEGTOP) texturevpegtop = 0; - else +#ifdef ESLOPE + else if (gr_linedef->flags & ML_EFFECT1) texturevpegtop = worldhigh + textureheight[gr_sidedef->toptexture] - worldtop; + else + texturevpegtop = gr_backsector->ceilingheight + textureheight[gr_sidedef->toptexture] - gr_frontsector->ceilingheight; +#else + else + texturevpegtop = worldhigh + textureheight[gr_sidedef->toptexture] - worldtop; +#endif texturevpegtop += gr_sidedef->rowoffset; @@ -1417,14 +1652,46 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) texturevpegtop %= SHORT(textures[texturetranslation[gr_sidedef->toptexture]]->height)<scaleY; - wallVerts[0].t = wallVerts[1].t = (texturevpegtop + worldtop - worldhigh) * grTex->scaleY; + wallVerts[0].t = wallVerts[1].t = (texturevpegtop + gr_frontsector->ceilingheight - gr_backsector->ceilingheight) * grTex->scaleY; wallVerts[0].s = wallVerts[3].s = cliplow * grTex->scaleX; wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX; + +#ifdef ESLOPE + // Adjust t value for sloped walls + if (!(gr_linedef->flags & ML_EFFECT1)) + { + // Unskewed + wallVerts[3].t -= (worldtop - gr_frontsector->ceilingheight) * grTex->scaleY; + wallVerts[2].t -= (worldtopslope - gr_frontsector->ceilingheight) * grTex->scaleY; + wallVerts[0].t -= (worldhigh - gr_backsector->ceilingheight) * grTex->scaleY; + wallVerts[1].t -= (worldhighslope - gr_backsector->ceilingheight) * grTex->scaleY; + } + else if (gr_linedef->flags & ML_DONTPEGTOP) + { + // Skewed by top + wallVerts[0].t = (texturevpegtop + worldtop - worldhigh) * grTex->scaleY; + wallVerts[1].t = (texturevpegtop + worldtopslope - worldhighslope) * grTex->scaleY; + } + else + { + // Skewed by bottom + wallVerts[0].t = (texturevpegtop + worldhigh - worldtop) * grTex->scaleY; + wallVerts[2].t = wallVerts[3].t - (worldhighslope - worldhigh) * grTex->scaleY; + wallVerts[1].t = wallVerts[2].t - (worldhighslope - worldtopslope) * grTex->scaleY; + } +#endif } // set top/bottom coords +#ifdef ESLOPE + wallVerts[3].y = FIXED_TO_FLOAT(worldtop); + wallVerts[0].y = FIXED_TO_FLOAT(worldhigh); + wallVerts[2].y = FIXED_TO_FLOAT(worldtopslope); + wallVerts[1].y = FIXED_TO_FLOAT(worldhighslope); +#else wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(worldtop); wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(worldhigh); +#endif if (gr_frontsector->numlights) HWR_SplitWall(gr_frontsector, wallVerts, texturetranslation[gr_sidedef->toptexture], &Surf, FF_CUTSOLIDS); @@ -1435,7 +1702,11 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) } // check BOTTOM TEXTURE - if (worldlow > worldbottom && texturetranslation[gr_sidedef->bottomtexture]) //only if VISIBLE!!! + if (( +#ifdef ESLOPE + worldlowslope > worldbottomslope || +#endif + worldlow > worldbottom) && texturetranslation[gr_sidedef->bottomtexture]) //only if VISIBLE!!! { if (drawtextured) { @@ -1444,10 +1715,19 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) grTex = HWR_GetTexture(texturetranslation[gr_sidedef->bottomtexture]); // PEGGING - if (gr_linedef->flags & ML_DONTPEGBOTTOM) +#ifdef ESLOPE + if (!(gr_linedef->flags & ML_DONTPEGBOTTOM)) + texturevpegbottom = 0; + else if (gr_linedef->flags & ML_EFFECT1) texturevpegbottom = worldtop - worldlow; else - texturevpegbottom = 0; + texturevpegbottom = gr_frontsector->ceilingheight - gr_backsector->floorheight; +#else + if (gr_linedef->flags & ML_DONTPEGBOTTOM) + texturevpegbottom = worldtop - worldlow; + else + texturevpegbottom = 0; +#endif texturevpegbottom += gr_sidedef->rowoffset; @@ -1455,14 +1735,46 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) texturevpegbottom %= SHORT(textures[texturetranslation[gr_sidedef->bottomtexture]]->height)<scaleY; - wallVerts[0].t = wallVerts[1].t = (texturevpegbottom + worldlow - worldbottom) * grTex->scaleY; + wallVerts[0].t = wallVerts[1].t = (texturevpegbottom + gr_backsector->floorheight - gr_frontsector->floorheight) * grTex->scaleY; wallVerts[0].s = wallVerts[3].s = cliplow * grTex->scaleX; wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX; + +#ifdef ESLOPE + // Adjust t value for sloped walls + if (!(gr_linedef->flags & ML_EFFECT1)) + { + // Unskewed + wallVerts[0].t -= (worldbottom - gr_frontsector->floorheight) * grTex->scaleY; + wallVerts[1].t -= (worldbottomslope - gr_frontsector->floorheight) * grTex->scaleY; + wallVerts[3].t -= (worldlow - gr_backsector->floorheight) * grTex->scaleY; + wallVerts[2].t -= (worldlowslope - gr_backsector->floorheight) * grTex->scaleY; + } + else if (gr_linedef->flags & ML_DONTPEGBOTTOM) + { + // Skewed by bottom + wallVerts[0].t = (texturevpegbottom + worldlow - worldbottom) * grTex->scaleY; + wallVerts[2].t = wallVerts[3].t - (worldlowslope - worldlow) * grTex->scaleY; + wallVerts[1].t = wallVerts[2].t - (worldbottomslope - worldlowslope) * grTex->scaleY; + } + else + { + // Skewed by top + wallVerts[0].t = (texturevpegbottom + worldlow - worldbottom) * grTex->scaleY; + wallVerts[1].t = (texturevpegbottom + worldlowslope - worldbottomslope) * grTex->scaleY; + } +#endif } // set top/bottom coords +#ifdef ESLOPE + wallVerts[3].y = FIXED_TO_FLOAT(worldlow); + wallVerts[0].y = FIXED_TO_FLOAT(worldbottom); + wallVerts[2].y = FIXED_TO_FLOAT(worldlowslope); + wallVerts[1].y = FIXED_TO_FLOAT(worldbottomslope); +#else wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(worldlow); wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(worldbottom); +#endif if (gr_frontsector->numlights) HWR_SplitWall(gr_frontsector, wallVerts, texturetranslation[gr_sidedef->bottomtexture], &Surf, FF_CUTSOLIDS); @@ -1529,14 +1841,36 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) popentop = back->ceilingheight; popenbottom = back->floorheight; } -#endif else - { - popentop = front->ceilingheight < back->ceilingheight ? front->ceilingheight : back->ceilingheight; - popenbottom = front->floorheight > back->floorheight ? front->floorheight : back->floorheight; +#endif + { +#ifdef ESLOPE + popentop = min(worldtop, worldhigh); + popenbottom = max(worldbottom, worldlow); +#else + popentop = min(front->ceilingheight, back->ceilingheight); + popenbottom = max(front->floorheight, back->floorheight); +#endif } - if (gr_linedef->flags & ML_DONTPEGBOTTOM) +#ifdef ESLOPE + if (gr_linedef->flags & ML_EFFECT2) + { + if (!!(gr_linedef->flags & ML_DONTPEGBOTTOM) ^ !!(gr_linedef->flags & ML_EFFECT3)) + { + polybottom = max(front->floorheight, back->floorheight) + gr_sidedef->rowoffset; + polytop = polybottom + textureheight[gr_midtexture]*repeats; + } + else + { + polytop = min(front->ceilingheight, back->ceilingheight) + gr_sidedef->rowoffset; + polybottom = polytop - textureheight[gr_midtexture]*repeats; + } + } + else if (!!(gr_linedef->flags & ML_DONTPEGBOTTOM) ^ !!(gr_linedef->flags & ML_EFFECT3)) +#else + if (gr_linedef->flags & ML_DONTPEGBOTTOM) +#endif { polybottom = popenbottom + gr_sidedef->rowoffset; polytop = polybottom + textureheight[gr_midtexture]*repeats; @@ -1559,17 +1893,21 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) else { // The cut-off values of a linedef can always be constant, since every line has an absoulute front and or back sector - lowcut = front->floorheight > back->floorheight ? front->floorheight : back->floorheight; - highcut = front->ceilingheight < back->ceilingheight ? front->ceilingheight : back->ceilingheight; + lowcut = popenbottom; + highcut = popentop; } - h = polytop > highcut ? highcut : polytop; - l = polybottom < lowcut ? lowcut : polybottom; + h = min(highcut, polytop); + l = max(polybottom, lowcut); if (drawtextured) { // PEGGING +#ifdef ESLOPE + if (!!(gr_linedef->flags & ML_DONTPEGBOTTOM) ^ !!(gr_linedef->flags & ML_EFFECT3)) +#else if (gr_linedef->flags & ML_DONTPEGBOTTOM) +#endif texturevpeg = textureheight[gr_sidedef->midtexture]*repeats - h + polybottom; else texturevpeg = polytop - h; @@ -1588,6 +1926,52 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(h); wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(l); +#ifdef ESLOPE + // Correct to account for slopes + { + fixed_t midtextureslant; + + if (gr_linedef->flags & ML_EFFECT2) + midtextureslant = 0; + else if (!!(gr_linedef->flags & ML_DONTPEGBOTTOM) ^ !!(gr_linedef->flags & ML_EFFECT3)) + midtextureslant = worldlow < worldbottom + ? worldbottomslope-worldbottom + : worldlowslope-worldlow; + else + midtextureslant = worldtop < worldhigh + ? worldtopslope-worldtop + : worldhighslope-worldhigh; + + polytop += midtextureslant; + polybottom += midtextureslant; + + highcut += worldtop < worldhigh + ? worldtopslope-worldtop + : worldhighslope-worldhigh; + lowcut += worldlow < worldbottom + ? worldbottomslope-worldbottom + : worldlowslope-worldlow; + + // Texture stuff + h = min(highcut, polytop); + l = max(polybottom, lowcut); + + if (drawtextured) + { + // PEGGING + if (!!(gr_linedef->flags & ML_DONTPEGBOTTOM) ^ !!(gr_linedef->flags & ML_EFFECT3)) + texturevpeg = textureheight[gr_sidedef->midtexture]*repeats - h + polybottom; + else + texturevpeg = polytop - h; + wallVerts[2].t = texturevpeg * grTex->scaleY; + wallVerts[1].t = (h - l + texturevpeg) * grTex->scaleY; + } + + wallVerts[2].y = FIXED_TO_FLOAT(h); + wallVerts[1].y = FIXED_TO_FLOAT(l); + } +#endif + // set alpha for transparent walls (new boom and legacy linedef types) // ooops ! this do not work at all because render order we should render it in backtofront order switch (gr_linedef->special) @@ -1768,6 +2152,11 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) { fixed_t texturevpeg; // PEGGING +#ifdef ESLOPE + if ((gr_linedef->flags & (ML_DONTPEGBOTTOM|ML_EFFECT2)) == (ML_DONTPEGBOTTOM|ML_EFFECT2)) + texturevpeg = gr_frontsector->floorheight + textureheight[gr_sidedef->midtexture] - gr_frontsector->ceilingheight + gr_sidedef->rowoffset; + else +#endif if (gr_linedef->flags & ML_DONTPEGBOTTOM) texturevpeg = worldbottom + textureheight[gr_sidedef->midtexture] - worldtop + gr_sidedef->rowoffset; else @@ -1777,14 +2166,37 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) grTex = HWR_GetTexture(gr_midtexture); wallVerts[3].t = wallVerts[2].t = texturevpeg * grTex->scaleY; - wallVerts[0].t = wallVerts[1].t = (texturevpeg + worldtop - worldbottom) * grTex->scaleY; + wallVerts[0].t = wallVerts[1].t = (texturevpeg + gr_frontsector->ceilingheight - gr_frontsector->floorheight) * grTex->scaleY; wallVerts[0].s = wallVerts[3].s = cliplow * grTex->scaleX; wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX; + +#ifdef ESLOPE + // Texture correction for slopes + if (gr_linedef->flags & ML_EFFECT2) { + wallVerts[3].t += (gr_frontsector->ceilingheight - worldtop) * grTex->scaleY; + wallVerts[2].t += (gr_frontsector->ceilingheight - worldtopslope) * grTex->scaleY; + wallVerts[0].t += (gr_frontsector->floorheight - worldbottom) * grTex->scaleY; + wallVerts[1].t += (gr_frontsector->floorheight - worldbottomslope) * grTex->scaleY; + } else if (gr_linedef->flags & ML_DONTPEGBOTTOM) { + wallVerts[3].t = wallVerts[0].t + (worldbottom-worldtop) * grTex->scaleY; + wallVerts[2].t = wallVerts[1].t + (worldbottomslope-worldtopslope) * grTex->scaleY; + } else { + wallVerts[0].t = wallVerts[3].t - (worldbottom-worldtop) * grTex->scaleY; + wallVerts[1].t = wallVerts[2].t - (worldbottomslope-worldtopslope) * grTex->scaleY; + } +#endif } +#ifdef ESLOPE + //Set textures properly on single sided walls that are sloped + wallVerts[3].y = FIXED_TO_FLOAT(worldtop); + wallVerts[0].y = FIXED_TO_FLOAT(worldbottom); + wallVerts[2].y = FIXED_TO_FLOAT(worldtopslope); + wallVerts[1].y = FIXED_TO_FLOAT(worldbottomslope); +#else // set top/bottom coords wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(worldtop); wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(worldbottom); - +#endif // I don't think that solid walls can use translucent linedef types... if (gr_frontsector->numlights) HWR_SplitWall(gr_frontsector, wallVerts, gr_midtexture, &Surf, FF_CUTSOLIDS); @@ -1817,6 +2229,8 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) INT32 texnum; line_t * newline = NULL; // Multi-Property FOF + ///TODO add slope support (fixing cutoffs, proper wall clipping) - maybe just disable highcut/lowcut if either sector or FOF has a slope + /// to allow fun plane intersecting in OGL? But then people would abuse that and make software look bad. :C highcut = gr_frontsector->ceilingheight < gr_backsector->ceilingheight ? gr_frontsector->ceilingheight : gr_backsector->ceilingheight; lowcut = gr_frontsector->floorheight > gr_backsector->floorheight ? gr_frontsector->floorheight : gr_backsector->floorheight; @@ -1838,6 +2252,24 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) texnum = texturetranslation[sides[newline->sidenum[0]].midtexture]; } +#ifdef ESLOPE + h = *rover->t_slope ? P_GetZAt(*rover->t_slope, v1x, v1y) : *rover->topheight; + hS = *rover->t_slope ? P_GetZAt(*rover->t_slope, v2x, v2y) : *rover->topheight; + l = *rover->b_slope ? P_GetZAt(*rover->b_slope, v1x, v1y) : *rover->bottomheight; + lS = *rover->b_slope ? P_GetZAt(*rover->b_slope, v2x, v2y) : *rover->bottomheight; + if (!(*rover->t_slope) && !gr_frontsector->c_slope && !gr_backsector->c_slope && h > highcut) + h = hS = highcut; + if (!(*rover->b_slope) && !gr_frontsector->f_slope && !gr_backsector->f_slope && l < lowcut) + l = lS = lowcut; + //Hurdler: HW code starts here + //FIXME: check if peging is correct + // set top/bottom coords + + wallVerts[3].y = FIXED_TO_FLOAT(h); + wallVerts[2].y = FIXED_TO_FLOAT(hS); + wallVerts[0].y = FIXED_TO_FLOAT(l); + wallVerts[1].y = FIXED_TO_FLOAT(lS); +#else h = *rover->topheight; l = *rover->bottomheight; if (h > highcut) @@ -1849,6 +2281,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) // set top/bottom coords wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(h); wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(l); +#endif if (rover->flags & FF_FOG) { wallVerts[3].t = wallVerts[2].t = 0; @@ -1858,6 +2291,15 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) } else if (drawtextured) { +#ifdef ESLOPE // P.S. this is better-organized than the old version + fixed_t offs = sides[(newline ?: rover->master)->sidenum[0]].rowoffset; + grTex = HWR_GetTexture(texnum); + + wallVerts[3].t = (*rover->topheight - h + offs) * grTex->scaleY; + wallVerts[2].t = (*rover->topheight - hS + offs) * grTex->scaleY; + wallVerts[0].t = (*rover->topheight - l + offs) * grTex->scaleY; + wallVerts[1].t = (*rover->topheight - lS + offs) * grTex->scaleY; +#else grTex = HWR_GetTexture(texnum); if (newline) @@ -1870,6 +2312,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) wallVerts[3].t = wallVerts[2].t = (*rover->topheight - h + sides[rover->master->sidenum[0]].rowoffset) * grTex->scaleY; wallVerts[0].t = wallVerts[1].t = (h - l + (*rover->topheight - h + sides[rover->master->sidenum[0]].rowoffset)) * grTex->scaleY; } +#endif wallVerts[0].s = wallVerts[3].s = cliplow * grTex->scaleX; wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX; @@ -1942,7 +2385,24 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) newline = rover->master->frontsector->lines[0] + linenum; texnum = texturetranslation[sides[newline->sidenum[0]].midtexture]; } +#ifdef ESLOPE //backsides + h = *rover->t_slope ? P_GetZAt(*rover->t_slope, v1x, v1y) : *rover->topheight; + hS = *rover->t_slope ? P_GetZAt(*rover->t_slope, v2x, v2y) : *rover->topheight; + l = *rover->b_slope ? P_GetZAt(*rover->b_slope, v1x, v1y) : *rover->bottomheight; + lS = *rover->b_slope ? P_GetZAt(*rover->b_slope, v2x, v2y) : *rover->bottomheight; + if (!(*rover->t_slope) && !gr_frontsector->c_slope && !gr_backsector->c_slope && h > highcut) + h = hS = highcut; + if (!(*rover->b_slope) && !gr_frontsector->f_slope && !gr_backsector->f_slope && l < lowcut) + l = lS = lowcut; + //Hurdler: HW code starts here + //FIXME: check if peging is correct + // set top/bottom coords + wallVerts[3].y = FIXED_TO_FLOAT(h); + wallVerts[2].y = FIXED_TO_FLOAT(hS); + wallVerts[0].y = FIXED_TO_FLOAT(l); + wallVerts[1].y = FIXED_TO_FLOAT(lS); +#else h = *rover->topheight; l = *rover->bottomheight; if (h > highcut) @@ -1954,7 +2414,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) // set top/bottom coords wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(h); wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(l); - +#endif if (rover->flags & FF_FOG) { wallVerts[3].t = wallVerts[2].t = 0; @@ -2448,13 +2908,17 @@ static void HWR_AddLine(seg_t * line) // and no middle texture. if ( #ifdef POLYOBJECTS - !line->polyseg + !line->polyseg && +#endif + gr_backsector->ceilingpic == gr_frontsector->ceilingpic + && gr_backsector->floorpic == gr_frontsector->floorpic +#ifdef ESLOPE + && gr_backsector->f_slope == gr_frontsector->f_slope + && gr_backsector->c_slope == gr_frontsector->c_slope #endif - && gr_backsector->ceilingpic == gr_frontsector->ceilingpic - && gr_backsector->floorpic == gr_frontsector->floorpic && gr_backsector->lightlevel == gr_frontsector->lightlevel - && gr_curline->sidedef->midtexture == 0 - && !gr_backsector->ffloors && !gr_frontsector->ffloors) + && gr_curline->sidedef->midtexture == 0 + && !gr_backsector->ffloors && !gr_frontsector->ffloors) // SoM: For 3D sides... Boris, would you like to take a // crack at rendering 3D sides? You would need to add the // above check and add code to HWR_StoreWallRange... @@ -2848,6 +3312,7 @@ static void HWR_Subsector(size_t num) INT32 floorlightlevel; INT32 ceilinglightlevel; INT32 locFloorHeight, locCeilingHeight; + INT32 cullFloorHeight, cullCeilingHeight; INT32 light = 0; extracolormap_t *floorcolormap; extracolormap_t *ceilingcolormap; @@ -2904,26 +3369,41 @@ static void HWR_Subsector(size_t num) // ----- for special tricks with HW renderer ----- if (gr_frontsector->pseudoSector) { - locFloorHeight = gr_frontsector->virtualFloorheight; - locCeilingHeight = gr_frontsector->virtualCeilingheight; + cullFloorHeight = locFloorHeight = gr_frontsector->virtualFloorheight; + cullCeilingHeight = locCeilingHeight = gr_frontsector->virtualCeilingheight; } else if (gr_frontsector->virtualFloor) { - locFloorHeight = gr_frontsector->virtualFloorheight; + ///@TODO Is this whole virtualFloor mess even useful? I don't think it even triggers ever. + cullFloorHeight = locFloorHeight = gr_frontsector->virtualFloorheight; if (gr_frontsector->virtualCeiling) - locCeilingHeight = gr_frontsector->virtualCeilingheight; + cullCeilingHeight = locCeilingHeight = gr_frontsector->virtualCeilingheight; else - locCeilingHeight = gr_frontsector->ceilingheight; + cullCeilingHeight = locCeilingHeight = gr_frontsector->ceilingheight; } else if (gr_frontsector->virtualCeiling) { - locCeilingHeight = gr_frontsector->virtualCeilingheight; - locFloorHeight = gr_frontsector->floorheight; + cullCeilingHeight = locCeilingHeight = gr_frontsector->virtualCeilingheight; + cullFloorHeight = locFloorHeight = gr_frontsector->floorheight; } else { - locFloorHeight = gr_frontsector->floorheight; - locCeilingHeight = gr_frontsector->ceilingheight; + cullFloorHeight = locFloorHeight = gr_frontsector->floorheight; + cullCeilingHeight = locCeilingHeight = gr_frontsector->ceilingheight; + +#ifdef ESLOPE + if (gr_frontsector->f_slope) + { + cullFloorHeight = P_GetZAt(gr_frontsector->f_slope, viewx, viewy); + locFloorHeight = P_GetZAt(gr_frontsector->f_slope, gr_frontsector->soundorg.x, gr_frontsector->soundorg.y); + } + + if (gr_frontsector->c_slope) + { + cullCeilingHeight = P_GetZAt(gr_frontsector->c_slope, viewx, viewy); + locCeilingHeight = P_GetZAt(gr_frontsector->c_slope, gr_frontsector->soundorg.x, gr_frontsector->soundorg.y); + } +#endif } // ----- end special tricks ----- @@ -2954,14 +3434,18 @@ static void HWR_Subsector(size_t num) // render floor ? #ifdef DOPLANES // yeah, easy backface cull! :) - if (locFloorHeight < dup_viewz) + if (cullFloorHeight < dup_viewz) { if (gr_frontsector->floorpic != skyflatnum) { if (sub->validcount != validcount) { HWR_GetFlat(levelflats[gr_frontsector->floorpic].lumpnum); - HWR_RenderPlane(gr_frontsector, &extrasubsectors[num], locFloorHeight, PF_Occlude, floorlightlevel, levelflats[gr_frontsector->floorpic].lumpnum, NULL, 255, false, floorcolormap); + HWR_RenderPlane(gr_frontsector, &extrasubsectors[num], + // Hack to make things continue to work around slopes. + locFloorHeight == cullFloorHeight ? locFloorHeight : gr_frontsector->floorheight, + // We now return you to your regularly scheduled rendering. + PF_Occlude, floorlightlevel, levelflats[gr_frontsector->floorpic].lumpnum, NULL, 255, false, floorcolormap); } } else @@ -2972,14 +3456,18 @@ static void HWR_Subsector(size_t num) } } - if (locCeilingHeight > dup_viewz) + if (cullCeilingHeight > dup_viewz) { if (gr_frontsector->ceilingpic != skyflatnum) { if (sub->validcount != validcount) { HWR_GetFlat(levelflats[gr_frontsector->ceilingpic].lumpnum); - HWR_RenderPlane(NULL, &extrasubsectors[num], locCeilingHeight, PF_Occlude, ceilinglightlevel, levelflats[gr_frontsector->ceilingpic].lumpnum,NULL, 255, false, ceilingcolormap); + HWR_RenderPlane(NULL, &extrasubsectors[num], + // Hack to make things continue to work around slopes. + locCeilingHeight == cullCeilingHeight ? locCeilingHeight : gr_frontsector->ceilingheight, + // We now return you to your regularly scheduled rendering. + PF_Occlude, ceilinglightlevel, levelflats[gr_frontsector->ceilingpic].lumpnum,NULL, 255, false, ceilingcolormap); } } else @@ -3008,22 +3496,34 @@ static void HWR_Subsector(size_t num) for (rover = gr_frontsector->ffloors; rover; rover = rover->next) { + fixed_t cullHeight, centerHeight; + + // bottom plane +#ifdef ESLOPE + if (*rover->b_slope) + { + cullHeight = P_GetZAt(*rover->b_slope, viewx, viewy); + centerHeight = P_GetZAt(*rover->b_slope, gr_frontsector->soundorg.x, gr_frontsector->soundorg.y); + } + else +#endif + cullHeight = centerHeight = *rover->bottomheight; if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERPLANES)) continue; if (sub->validcount == validcount) continue; - if (*rover->bottomheight <= gr_frontsector->ceilingheight && - *rover->bottomheight >= gr_frontsector->floorheight && - ((dup_viewz < *rover->bottomheight && !(rover->flags & FF_INVERTPLANES)) || - (dup_viewz > *rover->bottomheight && (rover->flags & FF_BOTHPLANES || rover->flags & FF_INVERTPLANES)))) + if (centerHeight <= locCeilingHeight && + centerHeight >= locFloorHeight && + ((dup_viewz < cullHeight && !(rover->flags & FF_INVERTPLANES)) || + (dup_viewz > cullHeight && (rover->flags & FF_BOTHPLANES || rover->flags & FF_INVERTPLANES)))) { if (rover->flags & FF_FOG) { UINT8 alpha; - light = R_GetPlaneLight(gr_frontsector, *rover->bottomheight, dup_viewz < *rover->bottomheight ? true : false); + light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); if (rover->master->frontsector->extra_colormap) alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap->rgba, rover->master->frontsector->extra_colormap->fadergba); @@ -3039,7 +3539,7 @@ static void HWR_Subsector(size_t num) } else if (rover->flags & FF_TRANSLUCENT) // SoM: Flags are more efficient { - light = R_GetPlaneLight(gr_frontsector, *rover->bottomheight, dup_viewz < *rover->bottomheight ? true : false); + light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); #ifndef SORTING HWR_Add3DWater(levelflats[*rover->bottompic].lumpnum, &extrasubsectors[num], @@ -3058,21 +3558,33 @@ static void HWR_Subsector(size_t num) else { HWR_GetFlat(levelflats[*rover->bottompic].lumpnum); - light = R_GetPlaneLight(gr_frontsector, *rover->bottomheight, dup_viewz < *rover->bottomheight ? true : false); + light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); HWR_RenderPlane(NULL, &extrasubsectors[num], *rover->bottomheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->bottompic].lumpnum, rover->master->frontsector, 255, false, gr_frontsector->lightlist[light].extra_colormap); } } - if (*rover->topheight >= gr_frontsector->floorheight && - *rover->topheight <= gr_frontsector->ceilingheight && - ((dup_viewz > *rover->topheight && !(rover->flags & FF_INVERTPLANES)) || - (dup_viewz < *rover->topheight && (rover->flags & FF_BOTHPLANES || rover->flags & FF_INVERTPLANES)))) + + // top plane +#ifdef ESLOPE + if (*rover->t_slope) + { + cullHeight = P_GetZAt(*rover->t_slope, viewx, viewy); + centerHeight = P_GetZAt(*rover->t_slope, gr_frontsector->soundorg.x, gr_frontsector->soundorg.y); + } + else +#endif + cullHeight = centerHeight = *rover->topheight; + + if (centerHeight >= locFloorHeight && + centerHeight <= locCeilingHeight && + ((dup_viewz > cullHeight && !(rover->flags & FF_INVERTPLANES)) || + (dup_viewz < cullHeight && (rover->flags & FF_BOTHPLANES || rover->flags & FF_INVERTPLANES)))) { if (rover->flags & FF_FOG) { UINT8 alpha; - light = R_GetPlaneLight(gr_frontsector, *rover->topheight, dup_viewz < *rover->topheight ? true : false); + light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); if (rover->master->frontsector->extra_colormap) alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap->rgba, rover->master->frontsector->extra_colormap->fadergba); @@ -3088,7 +3600,7 @@ static void HWR_Subsector(size_t num) } else if (rover->flags & FF_TRANSLUCENT) { - light = R_GetPlaneLight(gr_frontsector, *rover->topheight, dup_viewz < *rover->topheight ? true : false); + light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); #ifndef SORTING HWR_Add3DWater(levelflats[*rover->toppic].lumpnum, &extrasubsectors[num], @@ -3108,7 +3620,7 @@ static void HWR_Subsector(size_t num) else { HWR_GetFlat(levelflats[*rover->toppic].lumpnum); - light = R_GetPlaneLight(gr_frontsector, *rover->topheight, dup_viewz < *rover->topheight ? true : false); + light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); HWR_RenderPlane(NULL, &extrasubsectors[num], *rover->topheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->toppic].lumpnum, rover->master->frontsector, 255, false, gr_frontsector->lightlist[light].extra_colormap); } @@ -3980,11 +4492,10 @@ static void HWR_SortVisSprites(void) gr_vsprsortedhead.next = gr_vsprsortedhead.prev = &gr_vsprsortedhead; for (i = 0; i < gr_visspritecount; i++) { - bestdist = ZCLIP_PLANE-1; - bestdispoffset = INT32_MAX; + best = NULL; for (ds = unsorted.next; ds != &unsorted; ds = ds->next) { - if (ds->tz > bestdist) + if (!best || ds->tz > bestdist) { bestdist = ds->tz; bestdispoffset = ds->dispoffset; @@ -4499,7 +5010,7 @@ static void HWR_ProjectSprite(mobj_t *thing) tz = (tr_x * gr_viewcos) + (tr_y * gr_viewsin); // thing is behind view plane? - if (tz < ZCLIP_PLANE) + if (tz < ZCLIP_PLANE && (!cv_grmd2.value || md2_models[thing->sprite].notfound == true)) //Yellow: Only MD2's dont disappear return; tx = (tr_x * gr_viewsin) - (tr_y * gr_viewcos); diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 4a13ec0e5..bf16908a3 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -287,8 +287,8 @@ static int lib_pSpawnMobj(lua_State *L) fixed_t z = luaL_checkfixed(L, 3); mobjtype_t type = luaL_checkinteger(L, 4); NOHUD - if (type > MT_LASTFREESLOT) - return luaL_error(L, "mobjtype_t out of bounds error!"); + if (type >= NUMMOBJTYPES) + return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1); LUA_PushUserdata(L, P_SpawnMobj(x, y, z, type), META_MOBJ); return 1; } @@ -313,8 +313,8 @@ static int lib_pSpawnMissile(lua_State *L) NOHUD if (!source || !dest) return LUA_ErrInvalid(L, "mobj_t"); - if (type > MT_LASTFREESLOT) - return luaL_error(L, "mobjtype_t out of bounds error!"); + if (type >= NUMMOBJTYPES) + return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1); LUA_PushUserdata(L, P_SpawnMissile(source, dest, type), META_MOBJ); return 1; } @@ -330,8 +330,8 @@ static int lib_pSpawnXYZMissile(lua_State *L) NOHUD if (!source || !dest) return LUA_ErrInvalid(L, "mobj_t"); - if (type > MT_LASTFREESLOT) - return luaL_error(L, "mobjtype_t out of bounds error!"); + if (type >= NUMMOBJTYPES) + return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1); LUA_PushUserdata(L, P_SpawnXYZMissile(source, dest, type, x, y, z), META_MOBJ); return 1; } @@ -349,8 +349,8 @@ static int lib_pSpawnPointMissile(lua_State *L) NOHUD if (!source) return LUA_ErrInvalid(L, "mobj_t"); - if (type > MT_LASTFREESLOT) - return luaL_error(L, "mobjtype_t out of bounds error!"); + if (type >= NUMMOBJTYPES) + return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1); LUA_PushUserdata(L, P_SpawnPointMissile(source, xa, ya, za, type, x, y, z), META_MOBJ); return 1; } @@ -366,8 +366,8 @@ static int lib_pSpawnAlteredDirectionMissile(lua_State *L) NOHUD if (!source) return LUA_ErrInvalid(L, "mobj_t"); - if (type > MT_LASTFREESLOT) - return luaL_error(L, "mobjtype_t out of bounds error!"); + if (type >= NUMMOBJTYPES) + return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1); LUA_PushUserdata(L, P_SpawnAlteredDirectionMissile(source, type, x, y, z, shiftingAngle), META_MOBJ); return 1; } @@ -395,8 +395,8 @@ static int lib_pSPMAngle(lua_State *L) NOHUD if (!source) return LUA_ErrInvalid(L, "mobj_t"); - if (type > MT_LASTFREESLOT) - return luaL_error(L, "mobjtype_t out of bounds error!"); + if (type >= NUMMOBJTYPES) + return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1); LUA_PushUserdata(L, P_SPMAngle(source, type, angle, allowaim, flags2), META_MOBJ); return 1; } @@ -409,8 +409,8 @@ static int lib_pSpawnPlayerMissile(lua_State *L) NOHUD if (!source) return LUA_ErrInvalid(L, "mobj_t"); - if (type > MT_LASTFREESLOT) - return luaL_error(L, "mobjtype_t out of bounds error!"); + if (type >= NUMMOBJTYPES) + return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1); LUA_PushUserdata(L, P_SpawnPlayerMissile(source, type, flags2), META_MOBJ); return 1; } @@ -429,8 +429,8 @@ static int lib_pWeaponOrPanel(lua_State *L) { mobjtype_t type = luaL_checkinteger(L, 1); //HUDSAFE - if (type > MT_LASTFREESLOT) - return luaL_error(L, "mobjtype_t out of bounds error!"); + if (type >= NUMMOBJTYPES) + return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1); lua_pushboolean(L, P_WeaponOrPanel(type)); return 1; } @@ -469,8 +469,10 @@ static int lib_pSpawnParaloop(lua_State *L) statenum_t nstate = luaL_optinteger(L, 8, S_NULL); boolean spawncenter = lua_optboolean(L, 9); NOHUD - if (type > MT_LASTFREESLOT) - return luaL_error(L, "mobjtype_t out of bounds error!"); + if (type >= NUMMOBJTYPES) + return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1); + if (nstate >= NUMSTATES) + return luaL_error(L, "state %d out of range (0 - %d)", nstate, NUMSTATES-1); P_SpawnParaloop(x, y, z, radius, number, type, nstate, rotangle, spawncenter); return 0; } @@ -900,8 +902,8 @@ static int lib_pSpawnSpinMobj(lua_State *L) NOHUD if (!player) return LUA_ErrInvalid(L, "player_t"); - if (type > MT_LASTFREESLOT) - return luaL_error(L, "mobjtype_t out of bounds error!"); + if (type >= NUMMOBJTYPES) + return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1); P_SpawnSpinMobj(player, type); return 0; } @@ -1270,6 +1272,8 @@ static int lib_pSetMobjStateNF(lua_State *L) NOHUD if (!mobj) return LUA_ErrInvalid(L, "mobj_t"); + if (state >= NUMSTATES) + return luaL_error(L, "state %d out of range (0 - %d)", state, NUMSTATES-1); if (mobj->player && state == S_NULL) return luaL_error(L, "Attempt to remove player mobj with S_NULL."); lua_pushboolean(L, P_SetMobjStateNF(mobj, state)); @@ -1381,8 +1385,8 @@ static int lib_pIsFlagAtBase(lua_State *L) { mobjtype_t flag = luaL_checkinteger(L, 1); NOHUD - if (flag > MT_LASTFREESLOT) - return luaL_error(L, "mobjtype_t out of bounds error!"); + if (flag >= NUMMOBJTYPES) + return luaL_error(L, "mobj type %d out of range (0 - %d)", flag, NUMMOBJTYPES-1); lua_pushboolean(L, P_IsFlagAtBase(flag)); return 1; } @@ -1615,7 +1619,7 @@ static int lib_rSetPlayerSkin(lua_State *L) { INT32 i = luaL_checkinteger(L, 2); if (i < 0 || i >= MAXSKINS) - return luaL_error(L, "argument #2 cannot exceed MAXSKINS"); + return luaL_error(L, "skin number (argument #2) %d out of range (0 - %d)", i, MAXSKINS-1); SetPlayerSkinByNum(player-players, i); } else // skin name @@ -1635,6 +1639,8 @@ static int lib_sStartSound(lua_State *L) sfxenum_t sound_id = luaL_checkinteger(L, 2); player_t *player = NULL; NOHUD + if (sound_id >= NUMSFX) + return luaL_error(L, "sfx %d out of range (0 - %d)", sound_id, NUMSFX-1); if (!lua_isnil(L, 1)) { origin = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); @@ -1659,12 +1665,15 @@ static int lib_sStartSoundAtVolume(lua_State *L) INT32 volume = (INT32)luaL_checkinteger(L, 3); player_t *player = NULL; NOHUD + if (!lua_isnil(L, 1)) { origin = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); if (!origin) return LUA_ErrInvalid(L, "mobj_t"); } + if (sound_id >= NUMSFX) + return luaL_error(L, "sfx %d out of range (0 - %d)", sound_id, NUMSFX-1); if (!lua_isnone(L, 4) && lua_isuserdata(L, 4)) { player = *((player_t **)luaL_checkudata(L, 4, META_PLAYER)); @@ -1796,6 +1805,8 @@ static int lib_sIdPlaying(lua_State *L) { sfxenum_t id = luaL_checkinteger(L, 1); NOHUD + if (id >= NUMSFX) + return luaL_error(L, "sfx %d out of range (0 - %d)", id, NUMSFX-1); lua_pushboolean(L, S_IdPlaying(id)); return 1; } @@ -1807,6 +1818,8 @@ static int lib_sSoundPlaying(lua_State *L) NOHUD if (!origin) return LUA_ErrInvalid(L, "mobj_t"); + if (id >= NUMSFX) + return luaL_error(L, "sfx %d out of range (0 - %d)", id, NUMSFX-1); lua_pushboolean(L, S_SoundPlaying(origin, id)); return 1; } @@ -1827,7 +1840,7 @@ static int lib_gDoReborn(lua_State *L) INT32 playernum = luaL_checkinteger(L, 1); NOHUD if (playernum >= MAXPLAYERS) - return luaL_error(L, "playernum out of bounds error!"); + return luaL_error(L, "playernum %d out of range (0 - %d)", playernum, MAXPLAYERS-1); G_DoReborn(playernum); return 0; } diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 52770a88a..33cc1b367 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -166,6 +166,8 @@ static int lib_getHudInfo(lua_State *L) lua_remove(L, 1); i = luaL_checkinteger(L, 1); + if (i >= NUMHUDITEMS) + return luaL_error(L, "hudinfo[] index %d out of range (0 - %d)", i, NUMHUDITEMS-1); LUA_PushUserdata(L, &hudinfo[i], META_HUDINFO); return 1; } @@ -526,6 +528,22 @@ static int libd_height(lua_State *L) return 1; } +static int libd_dupx(lua_State *L) +{ + HUDONLY + lua_pushinteger(L, vid.dupx); // push integral scale (patch scale) + lua_pushfixed(L, vid.fdupx); // push fixed point scale (position scale) + return 2; +} + +static int libd_dupy(lua_State *L) +{ + HUDONLY + lua_pushinteger(L, vid.dupy); // push integral scale (patch scale) + lua_pushfixed(L, vid.fdupy); // push fixed point scale (position scale) + return 2; +} + static int libd_renderer(lua_State *L) { HUDONLY @@ -550,6 +568,8 @@ static luaL_Reg lib_draw[] = { {"getColormap", libd_getColormap}, {"width", libd_width}, {"height", libd_height}, + {"dupx", libd_dupx}, + {"dupy", libd_dupy}, {"renderer", libd_renderer}, {NULL, NULL} }; diff --git a/src/lua_infolib.c b/src/lua_infolib.c index a983bb002..fb2e94051 100644 --- a/src/lua_infolib.c +++ b/src/lua_infolib.c @@ -184,6 +184,8 @@ static int lib_getState(lua_State *L) lua_remove(L, 1); i = luaL_checkinteger(L, 1); + if (i >= NUMSTATES) + return luaL_error(L, "states[] index %d out of range (0 - %d)", i, NUMSTATES-1); LUA_PushUserdata(L, &states[i], META_STATE); return 1; } @@ -193,7 +195,12 @@ static int lib_setState(lua_State *L) { state_t *state; lua_remove(L, 1); // don't care about states[] userdata. - state = &states[luaL_checkinteger(L, 1)]; // get the state to assign to. + { + UINT32 i = luaL_checkinteger(L, 1); + if (i >= NUMSTATES) + return luaL_error(L, "states[] index %d out of range (0 - %d)", i, NUMSTATES-1); + state = &states[i]; // get the state to assign to. + } luaL_checktype(L, 2, LUA_TTABLE); // check that we've been passed a table. lua_remove(L, 1); // pop state num, don't need it any more. lua_settop(L, 1); // cut the stack here. the only thing left now is the table of data we're assigning to the state. @@ -474,6 +481,8 @@ static int lib_getMobjInfo(lua_State *L) lua_remove(L, 1); i = luaL_checkinteger(L, 1); + if (i >= NUMMOBJTYPES) + return luaL_error(L, "mobjinfo[] index %d out of range (0 - %d)", i, NUMMOBJTYPES-1); LUA_PushUserdata(L, &mobjinfo[i], META_MOBJINFO); return 1; } @@ -483,7 +492,12 @@ static int lib_setMobjInfo(lua_State *L) { mobjinfo_t *info; lua_remove(L, 1); // don't care about mobjinfo[] userdata. - info = &mobjinfo[luaL_checkinteger(L, 1)]; // get the mobjinfo to assign to. + { + UINT32 i = luaL_checkinteger(L, 1); + if (i >= NUMMOBJTYPES) + return luaL_error(L, "mobjinfo[] index %d out of range (0 - %d)", i, NUMMOBJTYPES-1); + info = &mobjinfo[i]; // get the mobjinfo to assign to. + } luaL_checktype(L, 2, LUA_TTABLE); // check that we've been passed a table. lua_remove(L, 1); // pop mobjtype num, don't need it any more. lua_settop(L, 1); // cut the stack here. the only thing left now is the table of data we're assigning to the mobjinfo. @@ -755,6 +769,8 @@ static int lib_getSfxInfo(lua_State *L) lua_remove(L, 1); i = luaL_checkinteger(L, 1); + if (i >= NUMSFX) + return luaL_error(L, "sfxinfo[] index %d out of range (0 - %d)", i, NUMSFX-1); LUA_PushUserdata(L, &S_sfx[i], META_SFXINFO); return 1; } @@ -765,7 +781,12 @@ static int lib_setSfxInfo(lua_State *L) sfxinfo_t *info; lua_remove(L, 1); - info = &S_sfx[luaL_checkinteger(L, 1)]; // get the mobjinfo to assign to. + { + UINT32 i = luaL_checkinteger(L, 1); + if (i >= NUMSFX) + return luaL_error(L, "sfxinfo[] index %d out of range (0 - %d)", i, NUMSFX-1); + info = &S_sfx[i]; // get the mobjinfo to assign to. + } luaL_checktype(L, 2, LUA_TTABLE); // check that we've been passed a table. lua_remove(L, 1); // pop mobjtype num, don't need it any more. lua_settop(L, 1); // cut the stack here. the only thing left now is the table of data we're assigning to the mobjinfo. diff --git a/src/lua_mathlib.c b/src/lua_mathlib.c index a55e3a0e4..d78cb23a4 100644 --- a/src/lua_mathlib.c +++ b/src/lua_mathlib.c @@ -32,13 +32,17 @@ static int lib_abs(lua_State *L) static int lib_min(lua_State *L) { - lua_pushinteger(L, min(luaL_checkinteger(L, 1), luaL_checkinteger(L, 2))); + int a = luaL_checkinteger(L, 1); + int b = luaL_checkinteger(L, 2); + lua_pushinteger(L, min(a,b)); return 1; } static int lib_max(lua_State *L) { - lua_pushinteger(L, max(luaL_checkinteger(L, 1), luaL_checkinteger(L, 2))); + int a = luaL_checkinteger(L, 1); + int b = luaL_checkinteger(L, 2); + lua_pushinteger(L, max(a,b)); return 1; } diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 53af2e3ac..388fe3175 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -55,7 +55,7 @@ static int lib_getPlayer(lua_State *L) { lua_Integer i = luaL_checkinteger(L, 2); if (i < 0 || i >= MAXPLAYERS) - return luaL_error(L, "players[] index cannot exceed MAXPLAYERS"); + return luaL_error(L, "players[] index %d out of range (0 - %d)", i, MAXPLAYERS-1); if (!playeringame[i]) return 0; if (!players[i].mo) diff --git a/src/lua_skinlib.c b/src/lua_skinlib.c index f07b4564c..545cf55b0 100644 --- a/src/lua_skinlib.c +++ b/src/lua_skinlib.c @@ -244,7 +244,7 @@ static int lib_getSkin(lua_State *L) { i = luaL_checkinteger(L, 2); if (i < 0 || i >= MAXSKINS) - return luaL_error(L, "skins[] index cannot exceed MAXSKINS"); + return luaL_error(L, "skins[] index %d out of range (0 - %d)", i, MAXSKINS-1); if (i >= numskins) return 0; LUA_PushUserdata(L, &skins[i], META_SKIN); diff --git a/src/m_misc.c b/src/m_misc.c index 22effdddf..6899059b6 100644 --- a/src/m_misc.c +++ b/src/m_misc.c @@ -1787,17 +1787,6 @@ UINT8 M_CountBits(UINT32 num, UINT8 size) return sum; } - -/** Get the most significant bit in a number. - * (integer log2) - */ -UINT8 M_HighestBit(UINT32 num) -{ - UINT8 i = 0; - while (num >>= 1) ++i; - return i; -} - const char *GetRevisionString(void) { static char rev[9] = {0}; diff --git a/src/m_misc.h b/src/m_misc.h index f681bfcb3..5fc4fa63b 100644 --- a/src/m_misc.h +++ b/src/m_misc.h @@ -95,7 +95,6 @@ void M_SetupMemcpy(void); // counting bits, for weapon ammo code, usually FUNCMATH UINT8 M_CountBits(UINT32 num, UINT8 size); -FUNCMATH UINT8 M_HighestBit(UINT32 num); // Flags for AA trees. #define AATREE_ZUSER 1 // Treat values as z_zone-allocated blocks and set their user fields diff --git a/src/p_map.c b/src/p_map.c index 0600e9d60..3fc70cbd4 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -1979,22 +1979,28 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) thing->z = (thing->ceilingz = thingtop = tmceilingz) - thing->height; thing->eflags |= MFE_JUSTSTEPPEDDOWN; } - else if (tmceilingz < thingtop && thingtop - tmceilingz <= maxstep) +#ifdef ESLOPE + // HACK TO FIX DSZ2: apply only if slopes are involved + else if (tmceilingslope && tmceilingz < thingtop && thingtop - tmceilingz <= maxstep) { thing->z = (thing->ceilingz = thingtop = tmceilingz) - thing->height; thing->eflags |= MFE_JUSTSTEPPEDDOWN; } +#endif } else if (thing->z == thing->floorz && tmfloorz < thing->z && thing->z - tmfloorz <= maxstep) { thing->z = thing->floorz = tmfloorz; thing->eflags |= MFE_JUSTSTEPPEDDOWN; } - else if (tmfloorz > thing->z && tmfloorz - thing->z <= maxstep) +#ifdef ESLOPE + // HACK TO FIX DSZ2: apply only if slopes are involved + else if (tmfloorslope && tmfloorz > thing->z && tmfloorz - thing->z <= maxstep) { thing->z = thing->floorz = tmfloorz; thing->eflags |= MFE_JUSTSTEPPEDDOWN; } +#endif } if (thing->eflags & MFE_VERTICALFLIP) diff --git a/src/p_slopes.c b/src/p_slopes.c index 797fe46b4..d8f2936b8 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -1133,7 +1133,9 @@ void P_ButteredSlope(mobj_t *mo) // This makes it harder to zigzag up steep slopes, as well as allows greater top speed when rolling down // Multiply by gravity - thrust = FixedMul(thrust, FRACUNIT/2); // TODO actually get this + thrust = FixedMul(thrust, gravity); // TODO account for per-sector gravity etc + // Multiply by scale (gravity strength depends on mobj scale) + thrust = FixedMul(thrust, mo->scale); P_Thrust(mo, mo->standingslope->xydirection, thrust); } diff --git a/src/p_user.c b/src/p_user.c index cd9fc7966..9f61c9487 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -6873,7 +6873,7 @@ static void P_MovePlayer(player_t *player) } } // Super Sonic move - if (player->charflags & SF_SUPER && player->powers[pw_super] && player->speed > FixedMul(5<mo->scale) + if (player->skin == 0 && player->powers[pw_super] && player->speed > FixedMul(5<mo->scale) && P_MobjFlip(player->mo)*player->mo->momz <= 0) { if (player->panim == PA_ROLL || player->mo->state-states == S_PLAY_PAIN || player->panim == PA_WALK) diff --git a/src/r_plane.c b/src/r_plane.c index 417f0360a..ac7dcb90e 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -299,7 +299,7 @@ void R_MapPlane(INT32 y, INT32 x1, INT32 x2) } length = FixedMul (distance,distscale[x1]); - angle = (currentplane->viewangle + xtoviewangle[x1])>>ANGLETOFINESHIFT; + angle = (currentplane->viewangle + currentplane->plangle + xtoviewangle[x1])>>ANGLETOFINESHIFT; /// \note Wouldn't it be faster just to add viewx and viewy // to the plane's x/yoffs anyway?? @@ -475,7 +475,8 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel, && lightlevel == check->lightlevel && xoff == check->xoffs && yoff == check->yoffs && planecolormap == check->extra_colormap - && !pfloor && !check->ffloor && check->viewz == viewz + && !pfloor && !check->ffloor + && check->viewx == viewx && check->viewy == viewy && check->viewz == viewz && check->viewangle == viewangle #ifdef ESLOPE && check->slope == slope @@ -497,8 +498,10 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel, check->yoffs = yoff; check->extra_colormap = planecolormap; check->ffloor = pfloor; + check->viewx = viewx; + check->viewy = viewy; check->viewz = viewz; - check->viewangle = viewangle + plangle; + check->viewangle = viewangle; check->plangle = plangle; #ifdef POLYOBJECTS_PLANES check->polyobj = NULL; @@ -567,6 +570,8 @@ visplane_t *R_CheckPlane(visplane_t *pl, INT32 start, INT32 stop) new_pl->yoffs = pl->yoffs; new_pl->extra_colormap = pl->extra_colormap; new_pl->ffloor = pl->ffloor; + new_pl->viewx = pl->viewx; + new_pl->viewy = pl->viewy; new_pl->viewz = pl->viewz; new_pl->viewangle = pl->viewangle; new_pl->plangle = pl->plangle; @@ -665,7 +670,6 @@ void R_MakeSpans(INT32 x, INT32 t1, INT32 b1, INT32 t2, INT32 b2) void R_DrawPlanes(void) { visplane_t *pl; - angle_t skyviewangle = viewangle; // the flat angle itself can mess with viewangle, so do your own angle instead! INT32 x; INT32 angle; INT32 i; @@ -704,7 +708,7 @@ void R_DrawPlanes(void) if (dc_yl <= dc_yh) { - angle = (skyviewangle + xtoviewangle[x])>>ANGLETOSKYSHIFT; + angle = (pl->viewangle + xtoviewangle[x])>>ANGLETOSKYSHIFT; dc_x = x; dc_source = R_GetColumn(skytexture, @@ -857,13 +861,13 @@ void R_DrawSinglePlane(visplane_t *pl) #ifdef ESLOPE if (!pl->slope) // Don't mess with angle on slopes! We'll handle this ourselves later #endif - if (viewangle != pl->viewangle) + if (viewangle != pl->viewangle+pl->plangle) { memset(cachedheight, 0, sizeof (cachedheight)); - angle = (pl->viewangle-ANGLE_90)>>ANGLETOFINESHIFT; + angle = (pl->viewangle+pl->plangle-ANGLE_90)>>ANGLETOFINESHIFT; basexscale = FixedDiv(FINECOSINE(angle),centerxfrac); baseyscale = -FixedDiv(FINESINE(angle),centerxfrac); - viewangle = pl->viewangle; + viewangle = pl->viewangle+pl->plangle; } currentplane = pl; @@ -954,11 +958,11 @@ void R_DrawSinglePlane(visplane_t *pl) xoffs *= fudge; yoffs /= fudge; - vx = FIXED_TO_FLOAT(viewx+xoffs); - vy = FIXED_TO_FLOAT(viewy-yoffs); - vz = FIXED_TO_FLOAT(viewz); + vx = FIXED_TO_FLOAT(pl->viewx+xoffs); + vy = FIXED_TO_FLOAT(pl->viewy-yoffs); + vz = FIXED_TO_FLOAT(pl->viewz); - temp = P_GetZAt(pl->slope, viewx, viewy); + temp = P_GetZAt(pl->slope, pl->viewx, pl->viewy); zeroheight = FIXED_TO_FLOAT(temp); #define ANG2RAD(angle) ((float)((angle)*M_PI)/ANGLE_180) @@ -966,14 +970,14 @@ void R_DrawSinglePlane(visplane_t *pl) // p is the texture origin in view space // Don't add in the offsets at this stage, because doing so can result in // errors if the flat is rotated. - ang = ANG2RAD(ANGLE_270 - viewangle); + ang = ANG2RAD(ANGLE_270 - pl->viewangle); p.x = vx * cos(ang) - vy * sin(ang); p.z = vx * sin(ang) + vy * cos(ang); temp = P_GetZAt(pl->slope, -xoffs, yoffs); p.y = FIXED_TO_FLOAT(temp) - vz; // m is the v direction vector in view space - ang = ANG2RAD(ANGLE_180 - viewangle - pl->plangle); + ang = ANG2RAD(ANGLE_180 - (pl->viewangle + pl->plangle)); m.x = cos(ang); m.z = sin(ang); @@ -982,9 +986,9 @@ void R_DrawSinglePlane(visplane_t *pl) n.z = -cos(ang); ang = ANG2RAD(pl->plangle); - temp = P_GetZAt(pl->slope, viewx + FLOAT_TO_FIXED(sin(ang)), viewy + FLOAT_TO_FIXED(cos(ang))); + temp = P_GetZAt(pl->slope, pl->viewx + FLOAT_TO_FIXED(sin(ang)), pl->viewy + FLOAT_TO_FIXED(cos(ang))); m.y = FIXED_TO_FLOAT(temp) - zeroheight; - temp = P_GetZAt(pl->slope, viewx + FLOAT_TO_FIXED(cos(ang)), viewy - FLOAT_TO_FIXED(sin(ang))); + temp = P_GetZAt(pl->slope, pl->viewx + FLOAT_TO_FIXED(cos(ang)), pl->viewy - FLOAT_TO_FIXED(sin(ang))); n.y = FIXED_TO_FLOAT(temp) - zeroheight; m.x /= fudge; @@ -1040,6 +1044,14 @@ void R_DrawSinglePlane(visplane_t *pl) stop = pl->maxx + 1; + if (viewx != pl->viewx || viewy != pl->viewy) + { + viewx = pl->viewx; + viewy = pl->viewy; + } + if (viewz != pl->viewz) + viewz = pl->viewz; + for (x = pl->minx; x <= stop; x++) { R_MakeSpans(x, pl->top[x-1], pl->bottom[x-1], diff --git a/src/r_plane.h b/src/r_plane.h index 239723ed1..562c6a9ae 100644 --- a/src/r_plane.h +++ b/src/r_plane.h @@ -27,7 +27,8 @@ typedef struct visplane_s { struct visplane_s *next; - fixed_t height, viewz; + fixed_t height; + fixed_t viewx, viewy, viewz; angle_t viewangle; angle_t plangle; INT32 picnum; diff --git a/src/r_segs.c b/src/r_segs.c index 3f11bb364..a254d43aa 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -288,6 +288,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) line_t *ldef; sector_t *front, *back; INT32 times, repeats; + INT64 overflow_test; #ifdef ESLOPE INT32 range; #endif @@ -485,7 +486,6 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) spryscale = ds->scale1 + (x1 - ds->x1)*rw_scalestep; } - #ifndef ESLOPE if (curline->linedef->flags & ML_DONTPEGBOTTOM) { @@ -523,6 +523,24 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) // calculate lighting if (maskedtexturecol[dc_x] != INT16_MAX) { + // Check for overflows first + overflow_test = (INT64)centeryfrac - (((INT64)dc_texturemid*spryscale)>>FRACBITS); + if (overflow_test < 0) overflow_test = -overflow_test; + if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL) + { + // Eh, no, go away, don't waste our time + if (dc_numlights) + { + for (i = 0; i < dc_numlights; i++) + { + rlight = &dc_lightlist[i]; + rlight->height += rlight->heightstep; + } + } + spryscale += rw_scalestep; + continue; + } + if (dc_numlights) { lighttable_t **xwalllights; @@ -708,7 +726,8 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) line_t *newline = NULL; #ifdef ESLOPE // Render FOF sides kinda like normal sides, with the frac and step and everything - fixed_t top_frac, top_step, bottom_frac, bottom_step; + // NOTE: INT64 instead of fixed_t because overflow concerns + INT64 top_frac, top_step, bottom_frac, bottom_step; #endif void (*colfunc_2s) (column_t *); @@ -788,6 +807,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) #ifdef ESLOPE fixed_t leftheight, rightheight; fixed_t pfloorleft, pfloorright; + INT64 overflow_test; #endif light = &frontsector->lightlist[i]; rlight = &dc_lightlist[p]; @@ -823,6 +843,14 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) leftheight -= viewz; rightheight -= viewz; + + overflow_test = (INT64)centeryfrac - (((INT64)leftheight*ds->scale1)>>FRACBITS); + if (overflow_test < 0) overflow_test = -overflow_test; + if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL) continue; + overflow_test = (INT64)centeryfrac - (((INT64)rightheight*ds->scale2)>>FRACBITS); + if (overflow_test < 0) overflow_test = -overflow_test; + if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL) continue; + rlight->height = (centeryfrac) - FixedMul(leftheight, ds->scale1); rlight->heightstep = (centeryfrac) - FixedMul(rightheight, ds->scale2); rlight->heightstep = (rlight->heightstep-rlight->height)/(range); @@ -832,7 +860,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) continue; if (light->height > *pfloor->topheight && i+1 < dc_numlights && frontsector->lightlist[i+1].height > *pfloor->topheight) - continue; + continue; lheight = light->height;// > *pfloor->topheight ? *pfloor->topheight + FRACUNIT : light->height; rlight->heightstep = -FixedMul (rw_scalestep, (lheight - viewz)); @@ -851,6 +879,13 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) leftheight -= viewz; rightheight -= viewz; + overflow_test = (INT64)centeryfrac - (((INT64)leftheight*ds->scale1)>>FRACBITS); + if (overflow_test < 0) overflow_test = -overflow_test; + if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL) continue; + overflow_test = (INT64)centeryfrac - (((INT64)rightheight*ds->scale2)>>FRACBITS); + if (overflow_test < 0) overflow_test = -overflow_test; + if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL) continue; + rlight->botheight = (centeryfrac) - FixedMul(leftheight, ds->scale1); rlight->botheightstep = (centeryfrac) - FixedMul(rightheight, ds->scale2); rlight->botheightstep = (rlight->botheightstep-rlight->botheight)/(range); @@ -948,20 +983,27 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) { fixed_t left_top, right_top, left_bottom, right_bottom; - left_top = *pfloor->t_slope ? P_GetZAt(*pfloor->t_slope, ds->leftpos.x, ds->leftpos.y) : *pfloor->topheight; - right_top = *pfloor->t_slope ? P_GetZAt(*pfloor->t_slope, ds->rightpos.x, ds->rightpos.y) : *pfloor->topheight; - left_bottom = *pfloor->b_slope ? P_GetZAt(*pfloor->b_slope, ds->leftpos.x, ds->leftpos.y) : *pfloor->bottomheight; - right_bottom = *pfloor->b_slope ? P_GetZAt(*pfloor->b_slope, ds->rightpos.x, ds->rightpos.y) : *pfloor->bottomheight; + if (*pfloor->t_slope) + { + left_top = P_GetZAt(*pfloor->t_slope, ds->leftpos.x, ds->leftpos.y) - viewz; + right_top = P_GetZAt(*pfloor->t_slope, ds->rightpos.x, ds->rightpos.y) - viewz; + } + else + left_top = right_top = *pfloor->topheight - viewz; - left_top -= viewz; - right_top -= viewz; - left_bottom -= viewz; - right_bottom -= viewz; + if (*pfloor->b_slope) + { + left_bottom = P_GetZAt(*pfloor->b_slope, ds->leftpos.x, ds->leftpos.y) - viewz; + right_bottom = P_GetZAt(*pfloor->b_slope, ds->rightpos.x, ds->rightpos.y) - viewz; + } + else + left_bottom = right_bottom = *pfloor->bottomheight - viewz; - top_frac = centeryfrac - FixedMul(left_top, ds->scale1); - bottom_frac = centeryfrac - FixedMul(left_bottom, ds->scale1); - top_step = centeryfrac - FixedMul(right_top, ds->scale2); - bottom_step = centeryfrac - FixedMul(right_bottom, ds->scale2); + // using INT64 to avoid 32bit overflow + top_frac = (INT64)centeryfrac - (((INT64)left_top * ds->scale1) >> FRACBITS); + bottom_frac = (INT64)centeryfrac - (((INT64)left_bottom * ds->scale1) >> FRACBITS); + top_step = (INT64)centeryfrac - (((INT64)right_top * ds->scale2) >> FRACBITS); + bottom_step = (INT64)centeryfrac - (((INT64)right_bottom * ds->scale2) >> FRACBITS); top_step = (top_step-top_frac)/(range); bottom_step = (bottom_step-bottom_frac)/(range); @@ -971,6 +1013,9 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) } #endif +#define CLAMPMAX INT32_MAX +#define CLAMPMIN (-INT32_MAX) // This is not INT32_MIN on purpose! INT32_MIN makes the drawers freak out. + // draw the columns for (dc_x = x1; dc_x <= x2; dc_x++) { @@ -987,8 +1032,12 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) INT32 lighteffect = 0; #ifdef ESLOPE - sprtopscreen = windowtop = top_frac; - sprbotscreen = windowbottom = bottom_frac; + if (top_frac > (INT64)CLAMPMAX) sprtopscreen = windowtop = CLAMPMAX; + else if (top_frac > (INT64)CLAMPMIN) sprtopscreen = windowtop = (fixed_t)top_frac; + else sprtopscreen = windowtop = CLAMPMIN; + if (bottom_frac > (INT64)CLAMPMAX) sprbotscreen = windowbottom = CLAMPMAX; + else if (bottom_frac > (INT64)CLAMPMIN) sprbotscreen = windowbottom = (fixed_t)bottom_frac; + else sprbotscreen = windowbottom = CLAMPMIN; top_frac += top_step; bottom_frac += bottom_step; @@ -1133,22 +1182,13 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) if (pfloor->flags & FF_FOG && pfloor->master->frontsector->extra_colormap) dc_colormap = pfloor->master->frontsector->extra_colormap->colormap + (dc_colormap - colormaps); - //Handle over/underflows before they happen. This fixes the textures part of the FOF rendering bug. - //...for the most part, anyway. - if (((signed)dc_texturemid > 0 && (spryscale>>FRACBITS > INT32_MAX / (signed)dc_texturemid)) - || ((signed)dc_texturemid < 0 && (spryscale) && (signed)(dc_texturemid)>>FRACBITS < (INT32_MIN / spryscale))) - { - spryscale += rw_scalestep; #ifdef ESLOPE - top_frac += top_step; - bottom_frac += bottom_step; -#endif - continue; - } - -#ifdef ESLOPE - sprtopscreen = windowtop = top_frac; - sprbotscreen = windowbottom = bottom_frac; + if (top_frac > (INT64)CLAMPMAX) sprtopscreen = windowtop = CLAMPMAX; + else if (top_frac > (INT64)CLAMPMIN) sprtopscreen = windowtop = (fixed_t)top_frac; + else sprtopscreen = windowtop = CLAMPMIN; + if (bottom_frac > (INT64)CLAMPMAX) sprbotscreen = windowbottom = CLAMPMAX; + else if (bottom_frac > (INT64)CLAMPMIN) sprbotscreen = windowbottom = (fixed_t)bottom_frac; + else sprbotscreen = windowbottom = CLAMPMIN; top_frac += top_step; bottom_frac += bottom_step; @@ -1167,6 +1207,9 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) } } colfunc = wallcolfunc; + +#undef CLAMPMAX +#undef CLAMPMIN } // @@ -2046,13 +2089,8 @@ void R_StoreWallRange(INT32 start, INT32 stop) markceiling = false; } -#ifdef ESLOPE - if ((worldhigh <= worldbottom && worldhighslope <= worldbottomslope) - || (worldlow >= worldtop && worldlowslope >= worldtopslope)) -#else if (backsector->ceilingheight <= frontsector->floorheight || backsector->floorheight >= frontsector->ceilingheight) -#endif { // closed door markceiling = markfloor = true; diff --git a/src/r_things.c b/src/r_things.c index 116ab7b9d..ebf1deb86 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -748,10 +748,16 @@ static void R_DrawVisSprite(vissprite_t *vis) patch_t *patch = W_CacheLumpNum(vis->patch, PU_CACHE); fixed_t this_scale = vis->mobj->scale; INT32 x1, x2; + INT64 overflow_test; if (!patch) return; + // Check for overflow + overflow_test = (INT64)centeryfrac - (((INT64)vis->texturemid*vis->scale)>>FRACBITS); + if (overflow_test < 0) overflow_test = -overflow_test; + if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL) return; // fixed point mult would overflow + colfunc = basecolfunc; // hack: this isn't resetting properly somewhere. dc_colormap = vis->colormap; if ((vis->mobj->flags & MF_BOSS) && (vis->mobj->flags2 & MF2_FRET) && (leveltime & 1)) // Bosses "flash" @@ -1248,15 +1254,6 @@ static void R_ProjectSprite(mobj_t *thing) return; } - // quick check for possible overflows - // if either of these triggers then there's a possibility that drawing is unsafe - if (M_HighestBit(abs(gzt - viewz)) + M_HighestBit(abs(yscale)) > 47 // 31 bits + 16 from the division by FRACUNIT - || M_HighestBit(abs(gz - viewz)) + M_HighestBit(abs(yscale)) > 47) - { - CONS_Debug(DBG_RENDER, "Suspected overflow in ProjectSprite (sprite %s), ignoring\n", sprnames[thing->sprite]); - return; - } - // store information in a vissprite vis = R_NewVisSprite(); vis->heightsec = heightsec; //SoM: 3/17/2000 @@ -1467,14 +1464,6 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing) return; } - // quick check for possible overflows - // if either of these triggers then there's a possibility that drawing is unsafe - if (M_HighestBit(abs(gzt - viewz)) + M_HighestBit(abs(yscale)) > 47) // 31 bits + 16 from the division by FRACUNIT - { - CONS_Debug(DBG_RENDER, "Suspected overflow in ProjectPrecipitationSprite (sprite %s), ignoring\n", sprnames[thing->sprite]); - return; - } - // store information in a vissprite vis = R_NewVisSprite(); vis->scale = yscale; //<