Implement object-defined floor sprite slopes.

This commit is contained in:
Jaime Passos 2020-10-14 00:57:13 -03:00
parent a8a66f698a
commit ab526e47cc
8 changed files with 129 additions and 35 deletions

View file

@ -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},

View file

@ -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;
}
}

View file

@ -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:

View file

@ -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);

View file

@ -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

View file

@ -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)
{

View file

@ -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

View file

@ -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);
}