diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index e5b076acd..9852dce77 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); @@ -1101,18 +1103,76 @@ DEFINE_ACTION_FUNCTION(AActor, OverlayY) // Because non-action functions cannot acquire the ID of the overlay... //--------------------------------------------------------------------------- -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; +} //--------------------------------------------------------------------------- // @@ -1529,7 +1589,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 ea03e109f..6a782f8e0 100644 --- a/src/p_pspr.h +++ b/src/p_pspr.h @@ -53,11 +53,15 @@ enum PSPLayers enum PSPFlags { - PSPF_ADDWEAPON = 1 << 0, - PSPF_ADDBOB = 1 << 1, - PSPF_POWDOUBLE = 1 << 2, - PSPF_CVARFAST = 1 << 3, - PSPF_FLIP = 1 << 6, + 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, + PSPF_FORCEALPHA = 1 << 7, + PSPF_FORCESTYLE = 1 << 8, }; class DPSprite : public DObject @@ -78,11 +82,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_data/renderstyle.h b/src/r_data/renderstyle.h index 501c14c5f..63e0856cd 100644 --- a/src/r_data/renderstyle.h +++ b/src/r_data/renderstyle.h @@ -125,6 +125,9 @@ enum ERenderFlags // Actors only: Ignore sector fade and fade to black. To fade to white, // combine this with STYLEF_InvertOverlay. STYLEF_FadeToBlack = 64, + + // Force alpha. + STYLEF_ForceAlpha = 128, }; union FRenderStyle diff --git a/src/r_draw.cpp b/src/r_draw.cpp index 80b91ed2d..d0d1013ae 100644 --- a/src/r_draw.cpp +++ b/src/r_draw.cpp @@ -2373,7 +2373,11 @@ ESPSResult R_SetPatchStyle (FRenderStyle style, fixed_t alpha, int translation, color = 0; } - if (style.Flags & STYLEF_TransSoulsAlpha) + if (style.Flags & STYLEF_ForceAlpha) + { + alpha = clamp(alpha, 0, OPAQUE); + } + else if (style.Flags & STYLEF_TransSoulsAlpha) { alpha = fixed_t(transsouls * OPAQUE); } diff --git a/src/r_things.cpp b/src/r_things.cpp index ab75c15b0..2e6403918 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -1303,6 +1303,7 @@ void R_DrawPSprite(DPSprite *pspr, AActor *owner, float bobx, float boby, double FTexture* tex; vissprite_t* vis; bool noaccel; + double alpha = owner->Alpha; static TArray avis; if (avis.Size() < vispspindex + 1) @@ -1326,7 +1327,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 +1364,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,6 +1405,8 @@ void R_DrawPSprite(DPSprite *pspr, AActor *owner, float bobx, float boby, double vis->pic = tex; vis->ColormapNum = 0; + // 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); @@ -1422,8 +1425,114 @@ 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; + // [MC] Set the render style + + if (pspr->Flags & PSPF_RENDERSTYLE) + { + const int rs = clamp(pspr->RenderStyle, 0, STYLE_Count); + + if (pspr->Flags & PSPF_FORCESTYLE) + { + vis->Style.RenderStyle = LegacyRenderStyles[rs]; + } + else if (owner->RenderStyle == LegacyRenderStyles[STYLE_Fuzzy]) + { + vis->Style.RenderStyle = LegacyRenderStyles[STYLE_Fuzzy]; + } + else if (owner->RenderStyle == LegacyRenderStyles[STYLE_OptFuzzy]) + { + vis->Style.RenderStyle = LegacyRenderStyles[STYLE_OptFuzzy]; + vis->Style.RenderStyle.CheckFuzz(); + } + else if (owner->RenderStyle == LegacyRenderStyles[STYLE_Subtract]) + { + vis->Style.RenderStyle = LegacyRenderStyles[STYLE_Subtract]; + } + else + { + vis->Style.RenderStyle = LegacyRenderStyles[rs]; + } + } + else + { + vis->Style.RenderStyle = owner->RenderStyle; + } + + // Set the alpha based on if using the overlay's own or not. Also adjust + // and override the alpha if not forced. + if (pspr->Flags & PSPF_ALPHA) + { + if (vis->Style.RenderStyle == LegacyRenderStyles[STYLE_Fuzzy]) + { + alpha = owner->Alpha; + } + else if (vis->Style.RenderStyle == LegacyRenderStyles[STYLE_OptFuzzy]) + { + FRenderStyle style = vis->Style.RenderStyle; + style.CheckFuzz(); + switch (style.BlendOp) + { + default: + alpha = pspr->alpha * owner->Alpha; + break; + case STYLEOP_Fuzz: + case STYLEOP_Sub: + alpha = owner->Alpha; + break; + } + + } + else if (vis->Style.RenderStyle == LegacyRenderStyles[STYLE_Subtract]) + { + alpha = owner->Alpha; + } + else if (vis->Style.RenderStyle == LegacyRenderStyles[STYLE_Add] || + vis->Style.RenderStyle == LegacyRenderStyles[STYLE_Translucent] || + vis->Style.RenderStyle == LegacyRenderStyles[STYLE_TranslucentStencil] || + vis->Style.RenderStyle == LegacyRenderStyles[STYLE_AddStencil] || + vis->Style.RenderStyle == LegacyRenderStyles[STYLE_AddShaded]) + { + alpha = owner->Alpha * pspr->alpha; + } + else + { + alpha = owner->Alpha; + } + } + + // Should normal renderstyle come out on top at the end and we desire alpha, + // switch it to translucent. Normal never applies any sort of alpha. + if ((pspr->Flags & PSPF_ALPHA) && + vis->Style.RenderStyle == LegacyRenderStyles[STYLE_Normal] && + vis->Style.Alpha < 1.0) + { + vis->Style.RenderStyle = LegacyRenderStyles[STYLE_Translucent]; + alpha = owner->Alpha * pspr->alpha; + } + + // ALWAYS take priority if asked for, except fuzz. Fuzz does absolutely nothing + // no matter what way it's changed. + if (pspr->Flags & PSPF_FORCEALPHA) + { + //Due to lack of != operators... + if (vis->Style.RenderStyle == LegacyRenderStyles[STYLE_Fuzzy] || + vis->Style.RenderStyle == LegacyRenderStyles[STYLE_SoulTrans] || + vis->Style.RenderStyle == LegacyRenderStyles[STYLE_Stencil]) + { } + else + { + alpha = pspr->alpha; + vis->Style.RenderStyle.Flags |= STYLEF_ForceAlpha; + } + } + vis->Style.Alpha = clamp(float(alpha), 0.f, 1.f); + + // Due to how some of the effects are handled, going to 0 or less causes some + // weirdness to display. There's no point rendering it anyway if it's 0. + if (vis->Style.Alpha <= 0.) + return; + + //----------------------------------------------------------------------------- // 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 @@ -1522,7 +1631,6 @@ void R_DrawPSprite(DPSprite *pspr, AActor *owner, float bobx, float boby, double { colormap_to_use = basecolormap; vis->Style.colormap = basecolormap->Maps; - vis->Style.RenderStyle = STYLE_Normal; } // Check for hardware-assisted 2D. If it's available, and this sprite is not @@ -1543,6 +1651,7 @@ void R_DrawPSprite(DPSprite *pspr, AActor *owner, float bobx, float boby, double return; } } + R_DrawVisSprite(vis); } @@ -1657,6 +1766,7 @@ 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); diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index eecc843d3..c7368cac7 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -61,6 +61,9 @@ ACTOR Actor native //: Thinker action native float OverlayX(int layer = 0); action native float OverlayY(int layer = 0); + // Overlay Functions + native float OverlayAlpha(int layer); + // Action functions // Meh, MBF redundant functions. Only for DeHackEd support. action native A_Turn(float angle = 0); @@ -343,7 +346,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); @@ -355,9 +357,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); diff --git a/wadsrc/static/actors/constants.txt b/wadsrc/static/actors/constants.txt index df3bb860b..35f39a39d 100644 --- a/wadsrc/static/actors/constants.txt +++ b/wadsrc/static/actors/constants.txt @@ -594,11 +594,15 @@ enum // Flags for psprite layers enum { - PSPF_ADDWEAPON = 1 << 0, - PSPF_ADDBOB = 1 << 1, - PSPF_POWDOUBLE = 1 << 2, - PSPF_CVARFAST = 1 << 3, - PSPF_FLIP = 1 << 6, + 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, + PSPF_FORCEALPHA = 1 << 7, + PSPF_FORCESTYLE = 1 << 8, }; // Default psprite layers