From 4273896311a3bead49867683e234ab7793d79a21 Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 13 Oct 2020 12:57:36 -0300 Subject: [PATCH] Implement relative and absolute sprite offsets for objects (mobjs) Added RF_ABSOLUTEOFFSETS and RF_FLIPOFFSETS --- src/d_clisrv.c | 16 ++++++++++---- src/d_clisrv.h | 8 +++++-- src/dehacked.c | 4 +++- src/hardware/hw_glob.h | 4 +++- src/hardware/hw_main.c | 22 +++++++++++++++++-- src/lua_mobjlib.c | 48 ++++++++++++++++++++++++++++-------------- src/p_mobj.c | 5 ++++- src/p_mobj.h | 10 +++++++-- src/p_saveg.c | 18 ++++++++++++++-- src/r_defs.h | 10 +++++---- src/r_things.c | 25 +++++++++++++++++++--- src/r_things.h | 2 ++ 12 files changed, 134 insertions(+), 38 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 3db5a6207..636e2bfa8 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -643,6 +643,12 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i) rsp->frame = LONG(players[i].mo->frame); rsp->sprite2 = players[i].mo->sprite2; rsp->anim_duration = SHORT(players[i].mo->anim_duration); + + rsp->spritexscale = LONG(players[i].mo->spritexscale); + rsp->spriteyscale = LONG(players[i].mo->spriteyscale); + rsp->spritexoffset = LONG(players[i].mo->spritexoffset); + rsp->spriteyoffset = LONG(players[i].mo->spriteyoffset); + rsp->tics = LONG(players[i].mo->tics); rsp->statenum = (statenum_t)LONG(players[i].mo->state-states); // :( rsp->eflags = (UINT16)SHORT(players[i].mo->eflags); @@ -655,8 +661,6 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i) rsp->scale = LONG(players[i].mo->scale); rsp->destscale = LONG(players[i].mo->destscale); rsp->scalespeed = LONG(players[i].mo->scalespeed); - rsp->spritexscale = LONG(players[i].mo->spritexscale); - rsp->spriteyscale = LONG(players[i].mo->spriteyscale); } static void resynch_read_player(resynch_pak *rsp) @@ -805,6 +809,12 @@ static void resynch_read_player(resynch_pak *rsp) players[i].mo->frame = LONG(rsp->frame); players[i].mo->sprite2 = rsp->sprite2; players[i].mo->anim_duration = SHORT(rsp->anim_duration); + + players[i].mo->spritexscale = LONG(rsp->spritexscale); + players[i].mo->spriteyscale = LONG(rsp->spriteyscale); + players[i].mo->spritexoffset = LONG(rsp->spritexoffset); + players[i].mo->spriteyoffset = LONG(rsp->spriteyoffset); + players[i].mo->tics = LONG(rsp->tics); players[i].mo->state = &states[LONG(rsp->statenum)]; @@ -817,8 +827,6 @@ static void resynch_read_player(resynch_pak *rsp) players[i].mo->scale = LONG(rsp->scale); players[i].mo->destscale = LONG(rsp->destscale); players[i].mo->scalespeed = LONG(rsp->scalespeed); - players[i].mo->spritexscale = LONG(rsp->spritexscale); - players[i].mo->spriteyscale = LONG(rsp->spriteyscale); // And finally, SET THE MOBJ SKIN damn it. if ((players[i].powers[pw_carry] == CR_NIGHTSMODE) && (skins[players[i].skin].sprites[SPR2_NFLY].numframes == 0)) diff --git a/src/d_clisrv.h b/src/d_clisrv.h index 0ed0b10f5..94cec3ff7 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -288,6 +288,12 @@ typedef struct UINT32 frame; UINT8 sprite2; UINT16 anim_duration; + + fixed_t spritexscale; + fixed_t spriteyscale; + fixed_t spritexoffset; + fixed_t spriteyoffset; + INT32 tics; statenum_t statenum; UINT32 flags; @@ -300,8 +306,6 @@ typedef struct fixed_t scale; fixed_t destscale; fixed_t scalespeed; - fixed_t spritexscale; - fixed_t spriteyscale; } ATTRPACK resynch_pak; typedef struct diff --git a/src/dehacked.c b/src/dehacked.c index aa4a04be4..0662074ba 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -9583,10 +9583,12 @@ struct { // Render flags {"RF_HORIZONTALFLIP",RF_HORIZONTALFLIP}, {"RF_VERTICALFLIP",RF_VERTICALFLIP}, - {"RF_ONESIDED",RF_ONESIDED}, + {"RF_ABSOLUTEOFFSETS",RF_ABSOLUTEOFFSETS}, + {"RF_FLIPOFFSETS",RF_FLIPOFFSETS}, {"RF_SLOPESPLAT",RF_SLOPESPLAT}, {"RF_NOSPLATBILLBOARD",RF_NOSPLATBILLBOARD}, {"RF_NOSPLATROLLANGLE",RF_NOSPLATROLLANGLE}, + {"RF_BLENDMASK",RF_BLENDMASK}, {"RF_FULLBRIGHT",RF_FULLBRIGHT}, {"RF_FULLDARK",RF_FULLDARK}, {"RF_SPRITETYPEMASK",RF_SPRITETYPEMASK}, diff --git a/src/hardware/hw_glob.h b/src/hardware/hw_glob.h index cb517b611..6a9bb257c 100644 --- a/src/hardware/hw_glob.h +++ b/src/hardware/hw_glob.h @@ -69,9 +69,11 @@ typedef struct gl_vissprite_s float tracertz; // for MF2_LINKDRAW sprites, this contains tracer's tz for use in sorting float scale; - float spritexscale, spriteyscale; float shadowheight, shadowscale; + float spritexscale, spriteyscale; + float spritexoffset, spriteyoffset; + UINT32 renderflags; UINT8 rotateflags; diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 5c450e9d2..315737108 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -3966,8 +3966,8 @@ static void HWR_DrawSprite(gl_vissprite_t *spr) angle = -angle; angle += ANGLE_90; - topoffset = (float)gpatch->topoffset; - leftoffset = (float)gpatch->leftoffset; + topoffset = spr->spriteyoffset; + leftoffset = spr->spritexoffset; if (spr->flip) leftoffset = ((float)gpatch->width - leftoffset); @@ -4979,6 +4979,22 @@ static void HWR_ProjectSprite(mobj_t *thing) } #endif + if (thing->renderflags & RF_ABSOLUTEOFFSETS) + { + spr_offset = thing->spritexoffset; + spr_topoffset = thing->spriteyoffset; + } + else + { + SINT8 flipoffset = 1; + + if ((thing->renderflags & RF_FLIPOFFSETS) && flip) + flipoffset = -1; + + spr_offset += thing->spritexoffset * flipoffset; + spr_topoffset += thing->spriteyoffset * flipoffset; + } + if (papersprite) { rightsin = FIXED_TO_FLOAT(FINESINE((mobjangle)>>ANGLETOFINESHIFT)); @@ -5123,6 +5139,8 @@ static void HWR_ProjectSprite(mobj_t *thing) vis->scale = this_scale; vis->spritexscale = spritexscale; vis->spriteyscale = spriteyscale; + vis->spritexoffset = FIXED_TO_FLOAT(spr_offset); + vis->spriteyoffset = FIXED_TO_FLOAT(spr_topoffset); vis->rotated = false; diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index c390eb064..a544f151c 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -39,6 +39,10 @@ enum mobj_e { mobj_frame, mobj_sprite2, mobj_anim_duration, + mobj_spritexscale, + mobj_spriteyscale, + mobj_spritexoffset, + mobj_spriteyoffset, mobj_touching_sectorlist, mobj_subsector, mobj_floorz, @@ -84,8 +88,6 @@ enum mobj_e { mobj_scale, mobj_destscale, mobj_scalespeed, - mobj_spritexscale, - mobj_spriteyscale, mobj_extravalue1, mobj_extravalue2, mobj_cusval, @@ -111,6 +113,10 @@ static const char *const mobj_opt[] = { "frame", "sprite2", "anim_duration", + "spritexscale", + "spriteyscale", + "spritexoffset", + "spriteyoffset", "touching_sectorlist", "subsector", "floorz", @@ -156,8 +162,6 @@ static const char *const mobj_opt[] = { "scale", "destscale", "scalespeed", - "spritexscale", - "spriteyscale", "extravalue1", "extravalue2", "cusval", @@ -233,6 +237,18 @@ static int mobj_get(lua_State *L) case mobj_anim_duration: lua_pushinteger(L, mo->anim_duration); break; + case mobj_spritexscale: + lua_pushfixed(L, mo->spritexscale); + break; + case mobj_spriteyscale: + lua_pushfixed(L, mo->spriteyscale); + break; + case mobj_spritexoffset: + lua_pushfixed(L, mo->spritexoffset); + break; + case mobj_spriteyoffset: + lua_pushfixed(L, mo->spriteyoffset); + break; case mobj_touching_sectorlist: return UNIMPLEMENTED; case mobj_subsector: @@ -390,12 +406,6 @@ static int mobj_get(lua_State *L) case mobj_scalespeed: lua_pushfixed(L, mo->scalespeed); break; - case mobj_spritexscale: - lua_pushfixed(L, mo->spritexscale); - break; - case mobj_spriteyscale: - lua_pushfixed(L, mo->spriteyscale); - break; case mobj_extravalue1: lua_pushinteger(L, mo->extravalue1); break; @@ -507,6 +517,18 @@ static int mobj_set(lua_State *L) case mobj_anim_duration: mo->anim_duration = (UINT16)luaL_checkinteger(L, 3); break; + case mobj_spritexscale: + mo->spritexscale = luaL_checkfixed(L, 3); + break; + case mobj_spriteyscale: + mo->spriteyscale = luaL_checkfixed(L, 3); + break; + case mobj_spritexoffset: + mo->spritexoffset = luaL_checkfixed(L, 3); + break; + case mobj_spriteyoffset: + mo->spriteyoffset = luaL_checkfixed(L, 3); + break; case mobj_touching_sectorlist: return UNIMPLEMENTED; case mobj_subsector: @@ -739,12 +761,6 @@ static int mobj_set(lua_State *L) case mobj_scalespeed: mo->scalespeed = luaL_checkfixed(L, 3); break; - case mobj_spritexscale: - mo->spritexscale = luaL_checkfixed(L, 3); - break; - case mobj_spriteyscale: - mo->spriteyscale = luaL_checkfixed(L, 3); - break; case mobj_extravalue1: mo->extravalue1 = luaL_checkinteger(L, 3); break; diff --git a/src/p_mobj.c b/src/p_mobj.c index 827650ce6..2260ace51 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10465,12 +10465,15 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) mobj->scale = FRACUNIT; mobj->destscale = mobj->scale; mobj->scalespeed = FRACUNIT/12; - mobj->spritexscale = mobj->spriteyscale = mobj->scale; // TODO: Make this a special map header if ((maptol & TOL_ERZ3) && !(mobj->type == MT_BLACKEGGMAN)) mobj->destscale = FRACUNIT/2; + // Sprite rendering + mobj->spritexscale = mobj->spriteyscale = mobj->scale; + mobj->spritexoffset = mobj->spriteyoffset = 0; + // set subsector and/or block links P_SetThingPosition(mobj); I_Assert(mobj->subsector != NULL); diff --git a/src/p_mobj.h b/src/p_mobj.h index eb8a9ccc2..0b688a9ad 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -286,6 +286,10 @@ typedef struct mobj_s UINT8 sprite2; // player sprites UINT16 anim_duration; // for FF_ANIMATE states + UINT32 renderflags; // render flags + fixed_t spritexscale, spriteyscale; + fixed_t spritexoffset, spriteyoffset; + struct msecnode_s *touching_sectorlist; // a linked list of sectors where this object appears struct subsector_s *subsector; // Subsector the mobj resides in. @@ -309,7 +313,6 @@ typedef struct mobj_s UINT32 flags; // flags from mobjinfo tables UINT32 flags2; // MF2_ flags UINT16 eflags; // extra flags - UINT32 renderflags; // render flags void *skin; // overrides 'sprite' when non-NULL (for player bodies to 'remember' the skin) // Player and mobj sprites in multiplayer modes are modified @@ -362,7 +365,6 @@ typedef struct mobj_s fixed_t scale; fixed_t destscale; fixed_t scalespeed; - fixed_t spritexscale, spriteyscale; // Extra values are for internal use for whatever you want INT32 extravalue1; @@ -409,6 +411,10 @@ typedef struct precipmobj_s UINT8 sprite2; // player sprites UINT16 anim_duration; // for FF_ANIMATE states + UINT32 renderflags; // render flags + fixed_t spritexscale, spriteyscale; + fixed_t spritexoffset, spriteyoffset; + struct mprecipsecnode_s *touching_sectorlist; // a linked list of sectors where this object appears struct subsector_s *subsector; // Subsector the mobj resides in. diff --git a/src/p_saveg.c b/src/p_saveg.c index d613efd70..3a9663326 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1395,8 +1395,10 @@ typedef enum MD2_ROLLANGLE = 1<<14, MD2_SPRITEXSCALE = 1<<15, MD2_SPRITEYSCALE = 1<<16, - MD2_SHADOWSCALE = 1<<17, - MD2_RENDERFLAGS = 1<<18, + MD2_SPRITEXOFFSET = 1<<17, + MD2_SPRITEYOFFSET = 1<<18, + MD2_SHADOWSCALE = 1<<19, + MD2_RENDERFLAGS = 1<<20, } mobj_diff2_t; typedef enum @@ -1611,6 +1613,10 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) 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) @@ -1759,6 +1765,10 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) WRITEFIXED(save_p, mobj->spritexscale); if (diff2 & MD2_SPRITEYSCALE) WRITEFIXED(save_p, mobj->spriteyscale); + if (diff2 & MD2_SPRITEXOFFSET) + 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) @@ -2774,6 +2784,10 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) mobj->spritexscale = READFIXED(save_p); if (diff2 & MD2_SPRITEYSCALE) mobj->spriteyscale = READFIXED(save_p); + if (diff2 & MD2_SPRITEXOFFSET) + 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) diff --git a/src/r_defs.h b/src/r_defs.h index 749638db3..7b7c5d7f0 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -717,10 +717,12 @@ typedef enum { RF_HORIZONTALFLIP = 0x0001, // Flip sprite horizontally RF_VERTICALFLIP = 0x0002, // Flip sprite vertically - RF_ONESIDED = 0x0004, // Wall/floor sprite is visible from front only - RF_SLOPESPLAT = 0x0008, // Rotate floor sprites by the object's standing slope - RF_NOSPLATBILLBOARD = 0x0010, // Don't billboard floor sprites (faces forward from the view angle) - RF_NOSPLATROLLANGLE = 0x0020, // Don't rotate floor sprites by the object's rollangle (uses rotated patches instead) + 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_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 e23c08eb1..d60228e36 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1632,6 +1632,22 @@ static void R_ProjectSprite(mobj_t *thing) if (spritexscale < 1 || spriteyscale < 1) return; + if (thing->renderflags & RF_ABSOLUTEOFFSETS) + { + spr_offset = thing->spritexoffset; + spr_topoffset = thing->spriteyoffset; + } + else + { + SINT8 flipoffset = 1; + + if ((thing->renderflags & RF_FLIPOFFSETS) && flip) + flipoffset = -1; + + spr_offset += thing->spritexoffset * flipoffset; + spr_topoffset += thing->spriteyoffset * flipoffset; + } + if (flip) offset = spr_offset - spr_width; else @@ -1981,7 +1997,8 @@ static void R_ProjectSprite(mobj_t *thing) vis->spritexscale = spritexscale; vis->spriteyscale = spriteyscale; - vis->shadowscale = shadowscale; + vis->spritexoffset = spr_offset; + vis->spriteyoffset = spr_topoffset; if (shadowdraw || shadoweffects) { @@ -1992,6 +2009,8 @@ static void R_ProjectSprite(mobj_t *thing) else iscale = FixedDiv(FRACUNIT, vis->xscale); + vis->shadowscale = shadowscale; + if (flip) { vis->startfrac = spr_width-1; @@ -2818,8 +2837,8 @@ static void R_DrawVisSplat(vissprite_t *spr) splat.angle = -splatangle; splat.angle += ANGLE_90; - topoffset = (spr->patch->topoffset * FRACUNIT); - leftoffset = (spr->patch->leftoffset * FRACUNIT); + topoffset = spr->spriteyoffset; + leftoffset = spr->spritexoffset; if (hflip) leftoffset = ((splat.width * FRACUNIT) - leftoffset); diff --git a/src/r_things.h b/src/r_things.h index 643b2ca9e..f960089a1 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -195,6 +195,8 @@ typedef struct vissprite_s UINT8 rotateflags; fixed_t spritexscale, spriteyscale; + fixed_t spritexoffset, spriteyoffset; + fixed_t shadowscale; INT16 clipbot[MAXVIDWIDTH], cliptop[MAXVIDWIDTH];