diff --git a/src/dehacked.c b/src/dehacked.c index 0662074ba..df692391c 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -9585,7 +9585,9 @@ struct { {"RF_VERTICALFLIP",RF_VERTICALFLIP}, {"RF_ABSOLUTEOFFSETS",RF_ABSOLUTEOFFSETS}, {"RF_FLIPOFFSETS",RF_FLIPOFFSETS}, + {"RF_SPLATMASK",RF_SLOPESPLAT}, {"RF_SLOPESPLAT",RF_SLOPESPLAT}, + {"RF_OBJECTSLOPESPLAT",RF_OBJECTSLOPESPLAT}, {"RF_NOSPLATBILLBOARD",RF_NOSPLATBILLBOARD}, {"RF_NOSPLATROLLANGLE",RF_NOSPLATROLLANGLE}, {"RF_BLENDMASK",RF_BLENDMASK}, diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 315737108..948045df3 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -3942,6 +3942,7 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) { F2DCoord verts[4]; F2DCoord rotated[4]; + angle_t angle; float ca, sa; float w, h; @@ -3950,12 +3951,14 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) float leftoffset, topoffset; float scale = spr->scale; float zoffset = (P_MobjFlip(spr->mobj) * 0.05f); + pslope_t *splatslope = NULL; INT32 i; - if (spr->renderflags & RF_SHADOWEFFECTS) + renderflags_t renderflags = spr->renderflags; + if (renderflags & RF_SHADOWEFFECTS) scale *= spr->shadowscale; - if (spr->rotateflags & SRF_3D || spr->renderflags & RF_NOSPLATBILLBOARD) + if (spr->rotateflags & SRF_3D || renderflags & RF_NOSPLATBILLBOARD) angle = spr->mobj->angle; else angle = viewangle; @@ -4015,13 +4018,24 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) wallVerts[i].z = rotated[i].y + FIXED_TO_FLOAT(spr->mobj->y); } - if (spr->renderflags & RF_SLOPESPLAT && spr->mobj->standingslope) + if (renderflags & (RF_SLOPESPLAT | RF_OBJECTSLOPESPLAT)) { - pslope_t *slope = spr->mobj->standingslope; + pslope_t *standingslope = spr->mobj->standingslope; // The slope that the object is standing on. + // The slope that was defined for the sprite. + if (renderflags & RF_SLOPESPLAT) + splatslope = spr->mobj->floorspriteslope; + + if (standingslope && (renderflags & RF_OBJECTSLOPESPLAT)) + splatslope = standingslope; + } + + // Set vertical position + if (splatslope) + { for (i = 0; i < 4; i++) { - fixed_t slopez = P_GetSlopeZAt(slope, FLOAT_TO_FIXED(wallVerts[i].x), FLOAT_TO_FIXED(wallVerts[i].z)); + fixed_t slopez = P_GetSlopeZAt(splatslope, FLOAT_TO_FIXED(wallVerts[i].x), FLOAT_TO_FIXED(wallVerts[i].z)); wallVerts[i].y = FIXED_TO_FLOAT(slopez) + zoffset; } } diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index a544f151c..75b0c2f89 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -43,6 +43,7 @@ enum mobj_e { mobj_spriteyscale, mobj_spritexoffset, mobj_spriteyoffset, + mobj_floorspriteslope, mobj_touching_sectorlist, mobj_subsector, mobj_floorz, @@ -117,6 +118,7 @@ static const char *const mobj_opt[] = { "spriteyscale", "spritexoffset", "spriteyoffset", + "floorspriteslope", "touching_sectorlist", "subsector", "floorz", @@ -249,6 +251,9 @@ static int mobj_get(lua_State *L) case mobj_spriteyoffset: lua_pushfixed(L, mo->spriteyoffset); break; + case mobj_floorspriteslope: + LUA_PushUserdata(L, mo->floorspriteslope, META_SLOPE); + break; case mobj_touching_sectorlist: return UNIMPLEMENTED; case mobj_subsector: @@ -529,6 +534,8 @@ static int mobj_set(lua_State *L) case mobj_spriteyoffset: mo->spriteyoffset = luaL_checkfixed(L, 3); break; + case mobj_floorspriteslope: + return NOSET; case mobj_touching_sectorlist: return UNIMPLEMENTED; case mobj_subsector: diff --git a/src/p_mobj.c b/src/p_mobj.c index 2260ace51..6d36ee303 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10473,6 +10473,8 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) // Sprite rendering mobj->spritexscale = mobj->spriteyscale = mobj->scale; mobj->spritexoffset = mobj->spriteyoffset = 0; + mobj->floorspriteslope = Z_Calloc(sizeof(pslope_t), PU_LEVEL, NULL); + mobj->floorspriteslope->normal.z = FRACUNIT; // set subsector and/or block links P_SetThingPosition(mobj); @@ -10935,6 +10937,10 @@ void P_RemoveMobj(mobj_t *mobj) mobj->state = NULL; mobj->player = NULL; + if (mobj->floorspriteslope) + Z_Free(mobj->floorspriteslope); + mobj->floorspriteslope = NULL; + // stop any playing sound S_StopSound(mobj); diff --git a/src/p_mobj.h b/src/p_mobj.h index 0b688a9ad..d26a38897 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -289,6 +289,7 @@ typedef struct mobj_s UINT32 renderflags; // render flags fixed_t spritexscale, spriteyscale; fixed_t spritexoffset, spriteyoffset; + struct pslope_s *floorspriteslope; // The slope that the floorsprite is rotated by struct msecnode_s *touching_sectorlist; // a linked list of sectors where this object appears diff --git a/src/p_saveg.c b/src/p_saveg.c index 3a9663326..ae8181693 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1393,12 +1393,13 @@ typedef enum MD2_COLORIZED = 1<<12, MD2_MIRRORED = 1<<13, MD2_ROLLANGLE = 1<<14, - MD2_SPRITEXSCALE = 1<<15, - MD2_SPRITEYSCALE = 1<<16, - MD2_SPRITEXOFFSET = 1<<17, - MD2_SPRITEYOFFSET = 1<<18, - MD2_SHADOWSCALE = 1<<19, - MD2_RENDERFLAGS = 1<<20, + MD2_SHADOWSCALE = 1<<15, + MD2_RENDERFLAGS = 1<<16, + MD2_SPRITEXSCALE = 1<<17, + MD2_SPRITEYSCALE = 1<<18, + MD2_SPRITEXOFFSET = 1<<19, + MD2_SPRITEYOFFSET = 1<<20, + MD2_FLOORSPRITESLOPE = 1<<21, } mobj_diff2_t; typedef enum @@ -1609,18 +1610,27 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) diff2 |= MD2_MIRRORED; if (mobj->rollangle) diff2 |= MD2_ROLLANGLE; + if (mobj->shadowscale) + diff2 |= MD2_SHADOWSCALE; + if (mobj->renderflags) + diff2 |= MD2_RENDERFLAGS; if (mobj->spritexscale != FRACUNIT) diff2 |= MD2_SPRITEXSCALE; if (mobj->spriteyscale != FRACUNIT) diff2 |= MD2_SPRITEYSCALE; if (mobj->spritexoffset) diff2 |= MD2_SPRITEXOFFSET; - if (mobj->spriteyoffset) - diff2 |= MD2_SPRITEYOFFSET; - if (mobj->shadowscale) - diff2 |= MD2_SHADOWSCALE; - if (mobj->renderflags) - diff2 |= MD2_RENDERFLAGS; + + { + pslope_t *slope = mobj->floorspriteslope; + if (slope->zangle || slope->zdelta || slope->xydirection + || slope->o.x || slope->o.y || slope->o.z + || slope->d.x || slope->d.y + || slope->normal.x || slope->normal.y + || (slope->normal.z != FRACUNIT)) + diff2 |= MD2_FLOORSPRITESLOPE; + } + if (diff2 != 0) diff |= MD_MORE; @@ -1761,6 +1771,10 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) WRITEUINT8(save_p, mobj->mirrored); if (diff2 & MD2_ROLLANGLE) WRITEANGLE(save_p, mobj->rollangle); + if (diff2 & MD2_SHADOWSCALE) + WRITEFIXED(save_p, mobj->shadowscale); + if (diff2 & MD2_RENDERFLAGS) + WRITEUINT32(save_p, mobj->renderflags); if (diff2 & MD2_SPRITEXSCALE) WRITEFIXED(save_p, mobj->spritexscale); if (diff2 & MD2_SPRITEYSCALE) @@ -1769,10 +1783,25 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) WRITEFIXED(save_p, mobj->spritexoffset); if (diff2 & MD2_SPRITEYOFFSET) WRITEFIXED(save_p, mobj->spriteyoffset); - if (diff2 & MD2_SHADOWSCALE) - WRITEFIXED(save_p, mobj->shadowscale); - if (diff2 & MD2_RENDERFLAGS) - WRITEUINT32(save_p, mobj->renderflags); + if (diff2 & MD2_FLOORSPRITESLOPE) + { + pslope_t *slope = mobj->floorspriteslope; + + WRITEFIXED(save_p, slope->zdelta); + WRITEANGLE(save_p, slope->zangle); + WRITEANGLE(save_p, slope->xydirection); + + WRITEFIXED(save_p, slope->o.x); + WRITEFIXED(save_p, slope->o.y); + WRITEFIXED(save_p, slope->o.z); + + WRITEFIXED(save_p, slope->d.x); + WRITEFIXED(save_p, slope->d.y); + + WRITEFIXED(save_p, slope->normal.x); + WRITEFIXED(save_p, slope->normal.y); + WRITEFIXED(save_p, slope->normal.z); + } WRITEUINT32(save_p, mobj->mobjnum); } @@ -2780,6 +2809,10 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) mobj->mirrored = READUINT8(save_p); if (diff2 & MD2_ROLLANGLE) mobj->rollangle = READANGLE(save_p); + if (diff2 & MD2_SHADOWSCALE) + mobj->shadowscale = READFIXED(save_p); + if (diff2 & MD2_RENDERFLAGS) + mobj->renderflags = READUINT32(save_p); if (diff2 & MD2_SPRITEXSCALE) mobj->spritexscale = READFIXED(save_p); if (diff2 & MD2_SPRITEYSCALE) @@ -2788,10 +2821,25 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) mobj->spritexoffset = READFIXED(save_p); if (diff2 & MD2_SPRITEYOFFSET) mobj->spriteyoffset = READFIXED(save_p); - if (diff2 & MD2_SHADOWSCALE) - mobj->shadowscale = READFIXED(save_p); - if (diff2 & MD2_RENDERFLAGS) - mobj->renderflags = READUINT32(save_p); + if (diff2 & MD2_FLOORSPRITESLOPE) + { + pslope_t *slope = mobj->floorspriteslope; + + slope->zdelta = READFIXED(save_p); + slope->zangle = READANGLE(save_p); + slope->xydirection = READANGLE(save_p); + + slope->o.x = READFIXED(save_p); + slope->o.y = READFIXED(save_p); + slope->o.z = READFIXED(save_p); + + slope->d.x = READFIXED(save_p); + slope->d.y = READFIXED(save_p); + + slope->normal.x = READFIXED(save_p); + slope->normal.y = READFIXED(save_p); + slope->normal.z = READFIXED(save_p); + } if (diff & MD_REDFLAG) { diff --git a/src/r_defs.h b/src/r_defs.h index 7b7c5d7f0..4423a4266 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -720,9 +720,11 @@ typedef enum RF_ABSOLUTEOFFSETS = 0x0004, // Sprite uses the object's offsets absolutely, instead of relatively RF_FLIPOFFSETS = 0x0008, // Relative object offsets are flipped with the sprite - RF_SLOPESPLAT = 0x0010, // Rotate floor sprites by the object's standing slope - RF_NOSPLATBILLBOARD = 0x0020, // Don't billboard floor sprites (faces forward from the view angle) - RF_NOSPLATROLLANGLE = 0x0040, // Don't rotate floor sprites by the object's rollangle (uses rotated patches instead) + RF_SPLATMASK = 0x00F0, // --Floor sprite flags + RF_SLOPESPLAT = 0x0010, // Rotate floor sprites by a slope + RF_OBJECTSLOPESPLAT = 0x0020, // Rotate floor sprites by the object's standing slope + RF_NOSPLATBILLBOARD = 0x0040, // Don't billboard floor sprites (faces forward from the view angle) + RF_NOSPLATROLLANGLE = 0x0080, // Don't rotate floor sprites by the object's rollangle (uses rotated patches instead) RF_BLENDMASK = 0x0F00, // --Blending modes RF_FULLBRIGHT = 0x0100, // Sprite is drawn at full brightness diff --git a/src/r_things.c b/src/r_things.c index a0b6239a7..e8c00b86b 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2797,21 +2797,26 @@ static void R_DrawVisSplat(vissprite_t *spr) #ifdef FLOORSPLATS floorsplat_t splat; fixed_t tr_x, tr_y, rot_x, rot_y, rot_z; + vector3_t *v3d; vector2_t v2d[4]; + vector2_t rotated[4]; + fixed_t x, y; fixed_t w, h; - angle_t splatangle, angle; + angle_t angle, splatangle; fixed_t ca, sa; fixed_t xscale, yscale; fixed_t xoffset, yoffset; fixed_t leftoffset, topoffset; + pslope_t *slope = NULL; + INT32 i; + boolean hflip = (spr->xiscale < 0); boolean vflip = (spr->cut & SC_VFLIP); UINT8 flipflags = 0; - vector2_t rotated[4]; - pslope_t *slope = NULL; - INT32 i; + + renderflags_t renderflags = spr->renderflags; if (hflip) flipflags |= PICFLAGS_XFLIP; @@ -2831,7 +2836,7 @@ static void R_DrawVisSplat(vissprite_t *spr) if (spr->mobj->skin && ((skin_t *)spr->mobj->skin)->flags & SF_HIRES) splat.scale = FixedMul(splat.scale, ((skin_t *)spr->mobj->skin)->highresscale); - if (spr->rotateflags & SRF_3D || spr->renderflags & RF_NOSPLATBILLBOARD) + if (spr->rotateflags & SRF_3D || renderflags & RF_NOSPLATBILLBOARD) splatangle = spr->mobj->angle; else splatangle = viewangle; @@ -2895,9 +2900,18 @@ static void R_DrawVisSplat(vissprite_t *spr) rotated[i].y = FixedMul(splat.verts[i].x, sa) + FixedMul(splat.verts[i].y, ca); } - if (spr->renderflags & RF_SLOPESPLAT) + if (renderflags & (RF_SLOPESPLAT | RF_OBJECTSLOPESPLAT)) { - slope = spr->mobj->standingslope; + pslope_t *standingslope = spr->mobj->standingslope; // The slope that the object is standing on. + + // The slope that was defined for the sprite. + if (renderflags & RF_SLOPESPLAT) + slope = spr->mobj->floorspriteslope; + + if (standingslope && (renderflags & RF_OBJECTSLOPESPLAT)) + slope = standingslope; + + // Set splat as tilted splat.tilted = (slope != NULL); }