diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index fab7e38d8..4c9872993 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -111,14 +111,16 @@ END_POINTERS //------------------------------------------------------------------------ DPSprite::DPSprite(player_t *owner, AActor *caller, int id) -: x(.0), y(.0), - oldx(.0), oldy(.0), - firstTic(true), - Flags(0), - Caller(caller), - Owner(owner), - ID(id), - processPending(true) +: x(.0), y(.0), + oldx(.0), oldy(.0), + alpha(1.), + firstTic(true), + Flags(0), + Caller(caller), + Owner(owner), + ID(id), + processPending(true), + RenderStyle(STYLE_Normal) { DPSprite *prev = nullptr; DPSprite *next = Owner->psprites; @@ -967,7 +969,7 @@ void A_OverlayOffset(AActor *self, int layer, double wx, double wy, int flags) player_t *player = self->player; DPSprite *psp; - if (player && (player->playerstate != PST_DEAD)) + if (player) { psp = player->FindPSprite(layer); @@ -1051,22 +1053,80 @@ DEFINE_ACTION_FUNCTION(AActor, A_OverlayFlags) //--------------------------------------------------------------------------- // -// PROC OverlayID -// Because non-action functions cannot acquire the ID of the overlay... +// PROC A_OverlayAlpha +// //--------------------------------------------------------------------------- -DEFINE_ACTION_FUNCTION(AActor, OverlayID) +DEFINE_ACTION_FUNCTION(AActor, A_OverlayAlpha) { PARAM_ACTION_PROLOGUE; + PARAM_INT(layer); + PARAM_FLOAT(alphaset); - if (ACTION_CALL_FROM_PSPRITE()) - { - ACTION_RETURN_INT(stateinfo->mPSPIndex); - } - ACTION_RETURN_INT(0); + if (self->player == nullptr) + return 0; + + DPSprite *pspr = self->player->FindPSprite(layer); + + if (pspr == nullptr) + return 0; + + pspr->alpha = clamp(alphaset, 0.0, 1.0); + + return 0; } +// NON-ACTION function to get the overlay alpha of a layer. +DEFINE_ACTION_FUNCTION(AActor, OverlayAlpha) +{ + if (numret > 0) + { + assert(ret != nullptr); + PARAM_SELF_PROLOGUE(AActor); + PARAM_INT(layer); + if (self->player == nullptr) + return 0; + + DPSprite *pspr = self->player->FindPSprite(layer); + + if (pspr == nullptr) + { + ret->SetFloat(0.0); + } + else + { + ret->SetFloat(pspr->alpha); + } + return 1; + } + return 0; +} + +//--------------------------------------------------------------------------- +// +// PROC A_OverlayRenderStyle +// +//--------------------------------------------------------------------------- + +DEFINE_ACTION_FUNCTION(AActor, A_OverlayRenderStyle) +{ + PARAM_ACTION_PROLOGUE; + PARAM_INT(layer); + PARAM_INT(style); + + if (self->player == nullptr) + return 0; + + DPSprite *pspr = self->player->FindPSprite(layer); + + if (pspr == nullptr || style >= STYLE_Count) + return 0; + + pspr->RenderStyle = style; + + return 0; +} //--------------------------------------------------------------------------- // @@ -1483,7 +1543,8 @@ void DPSprite::Serialize(FSerializer &arc) ("x", x) ("y", y) ("oldx", oldx) - ("oldy", oldy); + ("oldy", oldy) + ("alpha", alpha); } //------------------------------------------------------------------------ diff --git a/src/p_pspr.h b/src/p_pspr.h index 7e5109657..86f484a3a 100644 --- a/src/p_pspr.h +++ b/src/p_pspr.h @@ -53,10 +53,13 @@ enum PSPLayers enum PSPFlags { - PSPF_ADDWEAPON = 1 << 0, - PSPF_ADDBOB = 1 << 1, - PSPF_POWDOUBLE = 1 << 2, - PSPF_CVARFAST = 1 << 3, + PSPF_ADDWEAPON = 1 << 0, + PSPF_ADDBOB = 1 << 1, + PSPF_POWDOUBLE = 1 << 2, + PSPF_CVARFAST = 1 << 3, + PSPF_ALPHA = 1 << 4, + PSPF_RENDERSTYLE = 1 << 5, + PSPF_FLIP = 1 << 6, }; class DPSprite : public DObject @@ -77,11 +80,12 @@ public: AActor* GetCaller() { return Caller; } void SetCaller(AActor *newcaller) { Caller = newcaller; } - double x, y; + double x, y, alpha; double oldx, oldy; bool firstTic; int Tics; int Flags; + int RenderStyle; private: DPSprite () {} diff --git a/src/r_things.cpp b/src/r_things.cpp index a45a6826a..0c49a2dc2 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -1290,7 +1290,7 @@ void R_AddSprites (sector_t *sec, int lightlevel, int fakeside) // // R_DrawPSprite // -void R_DrawPSprite(DPSprite *pspr, AActor *owner, float bobx, float boby, double wx, double wy, double ticfrac) +void R_DrawPSprite(DPSprite *pspr, AActor *owner, float bobx, float boby, double wx, double wy, double ticfrac, double alpha) { double tx; int x1; @@ -1326,7 +1326,7 @@ void R_DrawPSprite(DPSprite *pspr, AActor *owner, float bobx, float boby, double flip = sprframe->Flip & 1; tex = TexMan(picnum); - if (tex->UseType == FTexture::TEX_Null) + if (tex->UseType == FTexture::TEX_Null || pspr->RenderStyle == STYLE_None) return; if (pspr->firstTic) @@ -1363,10 +1363,10 @@ void R_DrawPSprite(DPSprite *pspr, AActor *owner, float bobx, float boby, double tx += tex->GetScaledWidth(); x2 = xs_RoundToInt(CenterX + tx * pspritexscale); - + // off the left side if (x2 <= 0) - return; + return; // store information in a vissprite vis = &avis[vispspindex]; @@ -1404,7 +1404,9 @@ void R_DrawPSprite(DPSprite *pspr, AActor *owner, float bobx, float boby, double vis->pic = tex; vis->ColormapNum = 0; - if (flip) + // If flip is used, provided that it's not already flipped (that would just invert itself) + // (It's an XOR...) + if (!(flip) != !(pspr->Flags & PSPF_FLIP)) { vis->xiscale = -FLOAT2FIXED(pspritexiscale * tex->Scale.X); vis->startfrac = (tex->GetWidth() << FRACBITS) - 1; @@ -1422,8 +1424,26 @@ void R_DrawPSprite(DPSprite *pspr, AActor *owner, float bobx, float boby, double FDynamicColormap *colormap_to_use = nullptr; if (pspr->GetID() < PSP_TARGETCENTER) { - vis->Style.Alpha = float(owner->Alpha); - vis->Style.RenderStyle = owner->RenderStyle; + // Set the alpha based on if using the overlay's own or not. + vis->Style.Alpha = (pspr->Flags & PSPF_ALPHA) ? float(alpha) : float(owner->Alpha); + + // Set the render style + if (pspr->Flags & PSPF_RENDERSTYLE) + { + const int rs = clamp(pspr->RenderStyle, 0, STYLE_Count); + + if (rs == STYLE_Normal && vis->Style.Alpha < 1.0) + vis->Style.RenderStyle = LegacyRenderStyles[STYLE_Translucent]; + else + vis->Style.RenderStyle = LegacyRenderStyles[rs]; + } + else + { + if (owner->RenderStyle == LegacyRenderStyles[STYLE_Normal] && vis->Style.Alpha < 1.0) + vis->Style.RenderStyle = LegacyRenderStyles[STYLE_Translucent]; + else + vis->Style.RenderStyle = owner->RenderStyle; + } // The software renderer cannot invert the source without inverting the overlay // too. That means if the source is inverted, we need to do the reverse of what @@ -1657,9 +1677,10 @@ void R_DrawPlayerSprites () // It's possible this psprite's caller is now null but the layer itself hasn't been destroyed // because it didn't tick yet (if we typed 'take all' while in the console for example). // In this case let's simply not draw it to avoid crashing. + if ((psp->GetID() != PSP_TARGETCENTER || CrosshairImage == nullptr) && psp->GetCaller() != nullptr) { - R_DrawPSprite(psp, camera, bobx, boby, wx, wy, r_TicFracF); + R_DrawPSprite(psp, camera, bobx, boby, wx, wy, r_TicFracF, psp->alpha); } psp = psp->GetNext(); diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index 44b801f51..77c60bbca 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -59,6 +59,9 @@ ACTOR Actor native //: Thinker native int GetMissileDamage(int mask, int add, int ptr = AAPTR_DEFAULT); action native int OverlayID(); + // Overlay Functions + native float OverlayAlpha(int layer); + // Action functions // Meh, MBF redundant functions. Only for DeHackEd support. action native A_Turn(float angle = 0); @@ -340,7 +343,6 @@ ACTOR Actor native //: Thinker native state A_CheckSightOrRange(float distance, state label, bool two_dimension = false); native state A_CheckRange(float distance, state label, bool two_dimension = false); action native bool A_FaceMovementDirection(float offset = 0, float anglelimit = 0, float pitchlimit = 0, int flags = 0, int ptr = AAPTR_DEFAULT); - action native int A_ClearOverlays(int sstart = 0, int sstop = 0, bool safety = true); action native bool A_CopySpriteFrame(int from, int to, int flags = 0); action native bool A_SetSpriteAngle(float angle = 0, int ptr = AAPTR_DEFAULT); action native bool A_SetSpriteRotation(float angle = 0, int ptr = AAPTR_DEFAULT); @@ -352,9 +354,12 @@ ACTOR Actor native //: Thinker action native A_CopyFriendliness(int ptr_source = AAPTR_MASTER); action native bool A_Overlay(int layer, state start = "", bool nooverride = false); + action native int A_ClearOverlays(int sstart = 0, int sstop = 0, bool safety = true); action native A_WeaponOffset(float wx = 0, float wy = 32, int flags = 0); action native A_OverlayOffset(int layer = PSP_WEAPON, float wx = 0, float wy = 32, int flags = 0); action native A_OverlayFlags(int layer, int flags, bool set); + action native A_OverlayAlpha(int layer, float alphaset); + action native A_OverlayRenderStyle(int layer, int style); native int ACS_NamedExecute(name script, int mapnum=0, int arg1=0, int arg2=0, int arg3=0); native int ACS_NamedSuspend(name script, int mapnum=0);