From cfa11046abfdfe282c50b55213939ee832fd70a6 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 16 Nov 2018 21:36:21 +0100 Subject: [PATCH 1/6] - changed PhosphorousFire.DoSpecialDamage to match SVE's handling: * Everything with a damage factor for fire only uses that. * Everything that bleeds takes half damage * Robots take quarter damage. --- wadsrc/static/zscript/strife/weapongrenade.txt | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/wadsrc/static/zscript/strife/weapongrenade.txt b/wadsrc/static/zscript/strife/weapongrenade.txt index 8d6a12b2d..e160be3c8 100644 --- a/wadsrc/static/zscript/strife/weapongrenade.txt +++ b/wadsrc/static/zscript/strife/weapongrenade.txt @@ -244,11 +244,18 @@ class PhosphorousFire : Actor override int DoSpecialDamage (Actor target, int damage, Name damagetype) { + // This may look a bit weird but is the same as in SVE: + // For the bosses, only their regular 0.5 damage factor for fire applies. + let firedamage = target.ApplyDamageFactor('Fire', damage); + if (firedamage != damage) return damage; // if the target has a factor, do nothing here. The factor will be applied elsewhere. + + // For everything else damage is halved, for robots quartered. + damage >>= 1; if (target.bNoBlood) { - return damage / 2; + damage >>= 1; } - return Super.DoSpecialDamage (target, damage, damagetype); + return damage; } // This function is mostly redundant and only kept in case some mod references it. From bb4007f16aa3e6a56694aa634961b17c8c036fde Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 17 Nov 2018 15:23:57 +0100 Subject: [PATCH 2/6] - fixed: CVar.ResetToDefault was missing a check for use outside of menus. --- src/c_cvars.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/c_cvars.cpp b/src/c_cvars.cpp index 5be8a28a7..43572fe77 100644 --- a/src/c_cvars.cpp +++ b/src/c_cvars.cpp @@ -225,7 +225,7 @@ DEFINE_ACTION_FUNCTION(_CVar, SetInt) // Only menus are allowed to change non-mod CVARs. if (DMenu::InMenu == 0) { - I_FatalError("Attempt to change CVAR '%s' outside of menu code", self->GetName()); + ThrowAbortException(X_OTHER, "Attempt to change CVAR '%s' outside of menu code", self->GetName()); } } PARAM_INT(val); @@ -243,7 +243,7 @@ DEFINE_ACTION_FUNCTION(_CVar, SetFloat) // Only menus are allowed to change non-mod CVARs. if (DMenu::InMenu == 0) { - I_FatalError("Attempt to change CVAR '%s' outside of menu code", self->GetName()); + ThrowAbortException(X_OTHER, "Attempt to change CVAR '%s' outside of menu code", self->GetName()); } } PARAM_FLOAT(val); @@ -262,7 +262,7 @@ DEFINE_ACTION_FUNCTION(_CVar, SetString) // Only menus are allowed to change non-mod CVARs. if (DMenu::InMenu == 0) { - I_FatalError("Attempt to change CVAR '%s' outside of menu code", self->GetName()); + ThrowAbortException(X_OTHER, "Attempt to change CVAR '%s' outside of menu code", self->GetName()); } } PARAM_STRING(val); @@ -1161,6 +1161,15 @@ void FBaseCVar::ResetToDefault () DEFINE_ACTION_FUNCTION(_CVar, ResetToDefault) { PARAM_SELF_STRUCT_PROLOGUE(FBaseCVar); + if (!(self->GetFlags() & CVAR_MOD)) + { + // Only menus are allowed to change non-mod CVARs. + if (DMenu::InMenu == 0) + { + ThrowAbortException(X_OTHER, "Attempt to change CVAR '%s' outside of menu code", self->GetName()); + } + } + self->ResetToDefault(); return 0; } From 160f17a90772cfb340c55b91365b21a8c226384f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 17 Nov 2018 15:34:23 +0100 Subject: [PATCH 3/6] - fixed stencil cap generation for old hardware and changed it so that it only gets done once for each stencil setup, not for each stencil pass. --- src/hwrenderer/scene/hw_portal.cpp | 48 ++++++++++++++++++++---------- src/hwrenderer/scene/hw_portal.h | 1 + 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/src/hwrenderer/scene/hw_portal.cpp b/src/hwrenderer/scene/hw_portal.cpp index 9cb35c696..787ef0b83 100644 --- a/src/hwrenderer/scene/hw_portal.cpp +++ b/src/hwrenderer/scene/hw_portal.cpp @@ -185,6 +185,33 @@ void HWPortal::DrawPortalStencil(FRenderState &state, int pass) mPrimIndices[i * 2] = lines[i].vertindex; mPrimIndices[i * 2 + 1] = lines[i].vertcount; } + + if (NeedCap() && lines.Size() > 1 && planesused != 0) + { + screen->mVertexData->Map(); + if (planesused & (1 << sector_t::floor)) + { + auto verts = screen->mVertexData->AllocVertices(4); + auto ptr = verts.first; + ptr[0].Set((float)boundingBox.left, -32767.f, (float)boundingBox.top, 0, 0); + ptr[1].Set((float)boundingBox.right, -32767.f, (float)boundingBox.top, 0, 0); + ptr[2].Set((float)boundingBox.left, -32767.f, (float)boundingBox.bottom, 0, 0); + ptr[3].Set((float)boundingBox.right, -32767.f, (float)boundingBox.bottom, 0, 0); + mBottomCap = verts.second; + } + if (planesused & (1 << sector_t::ceiling)) + { + auto verts = screen->mVertexData->AllocVertices(4); + auto ptr = verts.first; + ptr[0].Set((float)boundingBox.left, 32767.f, (float)boundingBox.top, 0, 0); + ptr[1].Set((float)boundingBox.right, 32767.f, (float)boundingBox.top, 0, 0); + ptr[2].Set((float)boundingBox.left, 32767.f, (float)boundingBox.bottom, 0, 0); + ptr[3].Set((float)boundingBox.right, 32767.f, (float)boundingBox.bottom, 0, 0); + mTopCap = verts.second; + } + screen->mVertexData->Unmap(); + } + } for (unsigned int i = 0; i < mPrimIndices.Size(); i += 2) @@ -196,26 +223,15 @@ void HWPortal::DrawPortalStencil(FRenderState &state, int pass) // The cap's depth handling needs special treatment so that it won't block further portal caps. if (pass == STP_DepthRestore) state.SetDepthRange(1, 1); - if (planesused & (1 << sector_t::floor)) + if (mBottomCap != ~0u) { - auto verts = screen->mVertexData->AllocVertices(4); - auto ptr = verts.first; - ptr[0].Set((float)boundingBox.left, -32767.f, (float)boundingBox.top, 0, 0); - ptr[1].Set((float)boundingBox.right, -32767.f, (float)boundingBox.top, 0, 0); - ptr[2].Set((float)boundingBox.left, -32767.f, (float)boundingBox.bottom, 0, 0); - ptr[3].Set((float)boundingBox.right, -32767.f, (float)boundingBox.bottom, 0, 0); - state.Draw(DT_TriangleStrip, verts.second, 4, false); + state.Draw(DT_TriangleStrip, mBottomCap, 4, false); } - if (planesused & (1 << sector_t::ceiling)) + if (mTopCap != ~0u) { - auto verts = screen->mVertexData->AllocVertices(4); - auto ptr = verts.first; - ptr[0].Set((float)boundingBox.left, 32767.f, (float)boundingBox.top, 0, 0); - ptr[1].Set((float)boundingBox.right, 32767.f, (float)boundingBox.top, 0, 0); - ptr[2].Set((float)boundingBox.left, 32767.f, (float)boundingBox.bottom, 0, 0); - ptr[3].Set((float)boundingBox.right, 32767.f, (float)boundingBox.bottom, 0, 0); - state.Draw(DT_TriangleStrip, verts.second, 4, false); + state.Draw(DT_TriangleStrip, mTopCap, 4, false); } + if (pass == STP_DepthRestore) state.SetDepthRange(0, 1); } } diff --git a/src/hwrenderer/scene/hw_portal.h b/src/hwrenderer/scene/hw_portal.h index f9d9e243c..879420c10 100644 --- a/src/hwrenderer/scene/hw_portal.h +++ b/src/hwrenderer/scene/hw_portal.h @@ -55,6 +55,7 @@ class HWPortal ActorRenderFlags savedvisibility; TArray mPrimIndices; + unsigned int mTopCap = ~0u, mBottomCap = ~0u; void DrawPortalStencil(FRenderState &state, int pass); From 701b793f2438bf12e20b848bbaf82c13cbe14852 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 17 Nov 2018 16:21:08 +0100 Subject: [PATCH 4/6] - fixed parameter mixup with P_CanResurrect. --- src/p_enemy.cpp | 10 +++++----- src/p_things.cpp | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index f49da9983..71dfcf46b 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -2767,9 +2767,9 @@ void A_DoChase (AActor *actor, bool fastchase, FState *meleestate, FState *missi //========================================================================== // [MC] Code is almost a duplicate of CanCollideWith but with changes to // accommodate checking of just one actor. -bool P_CanResurrect(AActor *tmthing, AActor *thing) +bool P_CanResurrect(AActor *raiser, AActor *thing) { - if (tmthing == nullptr) + if (raiser == nullptr) return false; static unsigned VIndex = ~0u; @@ -2779,12 +2779,12 @@ bool P_CanResurrect(AActor *tmthing, AActor *thing) assert(VIndex != ~0u); } - VMValue params[3] = { tmthing, thing, false }; + VMValue params[3] = { raiser, thing, false }; VMReturn ret; int retval; ret.IntAt(&retval); - auto clss = tmthing->GetClass(); + auto clss = raiser->GetClass(); VMFunction *func = clss->Virtuals.Size() > VIndex ? clss->Virtuals[VIndex] : nullptr; if (func != nullptr) { @@ -2793,7 +2793,7 @@ bool P_CanResurrect(AActor *tmthing, AActor *thing) } // Pointless to be running it again if it's just self. - if (thing == nullptr || thing == tmthing) + if (thing == nullptr || thing == raiser) return true; std::swap(params[0].a, params[1].a); diff --git a/src/p_things.cpp b/src/p_things.cpp index e7de17aab..0cd046c33 100644 --- a/src/p_things.cpp +++ b/src/p_things.cpp @@ -463,7 +463,7 @@ bool P_Thing_Raise(AActor *thing, AActor *raiser, int nocheck) return false; } - if (!P_CanResurrect(thing, raiser)) + if (!P_CanResurrect(raiser, thing)) return false; S_Sound (thing, CHAN_BODY, "vile/raise", 1, ATTN_IDLE); From 08fe9c375b63fbb90977b646d91fb9681b5086f4 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 17 Nov 2018 18:24:14 +0100 Subject: [PATCH 5/6] - use the same formula for calculating 3DMidTex offsets as the renderer when per-sidedef scaling is used. This reuses the FTexCoordInfo class the hardware renderer had been using to calculate wall texture offsetting. The software renderers still need this sorted out to bring them in line with the rest of the code, though, but they do not have this code sufficiently well organized to make this a straightforward task. --- src/hwrenderer/textures/hw_material.cpp | 108 ---------------------- src/hwrenderer/textures/hw_material.h | 22 +---- src/p_3dmidtex.cpp | 13 ++- src/textures/texture.cpp | 116 ++++++++++++++++++++++++ src/textures/textures.h | 19 ++++ 5 files changed, 145 insertions(+), 133 deletions(-) diff --git a/src/hwrenderer/textures/hw_material.cpp b/src/hwrenderer/textures/hw_material.cpp index 48d313d95..303c3e83a 100644 --- a/src/hwrenderer/textures/hw_material.cpp +++ b/src/hwrenderer/textures/hw_material.cpp @@ -128,70 +128,6 @@ void IHardwareTexture::Resize(int swidth, int sheight, int width, int height, un } } -//=========================================================================== -// -// -// -//=========================================================================== - -float FTexCoordInfo::RowOffset(float rowoffset) const -{ - float tscale = fabs(mTempScale.Y); - float scale = fabs(mScale.Y); - - if (tscale == 1.f) - { - if (scale == 1.f || mWorldPanning) return rowoffset; - else return rowoffset / scale; - } - else - { - if (mWorldPanning) return rowoffset / tscale; - else return rowoffset / scale; - } -} - -//=========================================================================== -// -// -// -//=========================================================================== - -float FTexCoordInfo::TextureOffset(float textureoffset) const -{ - float tscale = fabs(mTempScale.X); - float scale = fabs(mScale.X); - if (tscale == 1.f) - { - if (scale == 1.f || mWorldPanning) return textureoffset; - else return textureoffset / scale; - } - else - { - if (mWorldPanning) return textureoffset / tscale; - else return textureoffset / scale; - } -} - -//=========================================================================== -// -// Returns the size for which texture offset coordinates are used. -// -//=========================================================================== - -float FTexCoordInfo::TextureAdjustWidth() const -{ - if (mWorldPanning) - { - float tscale = fabs(mTempScale.X); - if (tscale == 1.f) return (float)mRenderWidth; - else return mWidth / fabs(tscale); - } - else return (float)mWidth; -} - - - //=========================================================================== // // @@ -522,50 +458,6 @@ void FMaterial::PrecacheList(SpriteHits &translations) while(it.NextPair(pair)) screen->PrecacheMaterial(this, pair->Key); } -//=========================================================================== -// -// Retrieve texture coordinate info for per-wall scaling -// -//=========================================================================== - -void FMaterial::GetTexCoordInfo(FTexCoordInfo *tci, float x, float y) const -{ - if (x == 1.f) - { - tci->mRenderWidth = mRenderWidth; - tci->mScale.X = (float)tex->Scale.X; - tci->mTempScale.X = 1.f; - } - else - { - float scale_x = x * (float)tex->Scale.X; - tci->mRenderWidth = xs_CeilToInt(mWidth / scale_x); - tci->mScale.X = scale_x; - tci->mTempScale.X = x; - } - - if (y == 1.f) - { - tci->mRenderHeight = mRenderHeight; - tci->mScale.Y = (float)tex->Scale.Y; - tci->mTempScale.Y = 1.f; - } - else - { - float scale_y = y * (float)tex->Scale.Y; - tci->mRenderHeight = xs_CeilToInt(mHeight / scale_y); - tci->mScale.Y = scale_y; - tci->mTempScale.Y = y; - } - if (tex->bHasCanvas) - { - tci->mScale.Y = -tci->mScale.Y; - tci->mRenderHeight = -tci->mRenderHeight; - } - tci->mWorldPanning = tex->bWorldPanning; - tci->mWidth = mWidth; -} - //=========================================================================== // // diff --git a/src/hwrenderer/textures/hw_material.h b/src/hwrenderer/textures/hw_material.h index 427442629..581368b55 100644 --- a/src/hwrenderer/textures/hw_material.h +++ b/src/hwrenderer/textures/hw_material.h @@ -25,23 +25,6 @@ enum }; - -struct FTexCoordInfo -{ - int mRenderWidth; - int mRenderHeight; - int mWidth; - FVector2 mScale; - FVector2 mTempScale; - bool mWorldPanning; - - float FloatToTexU(float v) const { return v / mRenderWidth; } - float FloatToTexV(float v) const { return v / mRenderHeight; } - float RowOffset(float ofs) const; - float TextureOffset(float ofs) const; - float TextureAdjustWidth() const; -}; - //=========================================================================== // // this is the material class for OpenGL. @@ -130,7 +113,10 @@ public: *r = mSpriteRect; } - void GetTexCoordInfo(FTexCoordInfo *tci, float x, float y) const; + void GetTexCoordInfo(FTexCoordInfo *tci, float x, float y) const + { + tci->GetFromTexture(tex, x, y); + } void GetTexCoordInfo(FTexCoordInfo *tci, side_t *side, int texpos) const { diff --git a/src/p_3dmidtex.cpp b/src/p_3dmidtex.cpp index 0a4c5507d..7a2363be6 100644 --- a/src/p_3dmidtex.cpp +++ b/src/p_3dmidtex.cpp @@ -232,13 +232,12 @@ bool P_GetMidTexturePosition(const line_t *line, int sideno, double *ptextop, do FTexture * tex= TexMan(texnum); if (!tex) return false; - double totalscale = fabs(side->GetTextureYScale(side_t::mid)) * tex->GetScaleY(); - double y_offset = side->GetTextureYOffset(side_t::mid); - double textureheight = tex->GetHeight() / totalscale; - if (totalscale != 1. && !tex->bWorldPanning) - { - y_offset /= totalscale; - } + FTexCoordInfo tci; + + // We only need the vertical positioning info here. + tci.GetFromTexture(tex, 1., (float)side->GetTextureYScale(side_t::mid)); + double y_offset = tci.RowOffset((float)side->GetTextureYOffset(side_t::mid)); + double textureheight = tci.mRenderHeight; if(line->flags & ML_DONTPEGBOTTOM) { diff --git a/src/textures/texture.cpp b/src/textures/texture.cpp index 047a9b205..75b7e5e7d 100644 --- a/src/textures/texture.cpp +++ b/src/textures/texture.cpp @@ -1543,3 +1543,119 @@ CCMD (printspans) #endif +//=========================================================================== +// +// Coordinate helper. +// The only reason this is even needed is that many years ago someone +// was convinced that having per-texel panning on walls was a good idea. +// If it wasn't for this relatively useless feature the entire positioning +// code for wall textures could be a lot simpler. +// +//=========================================================================== + +//=========================================================================== +// +// +// +//=========================================================================== + +float FTexCoordInfo::RowOffset(float rowoffset) const +{ + float tscale = fabs(mTempScale.Y); + float scale = fabs(mScale.Y); + + if (tscale == 1.f) + { + if (scale == 1.f || mWorldPanning) return rowoffset; + else return rowoffset / scale; + } + else + { + if (mWorldPanning) return rowoffset / tscale; + else return rowoffset / scale; + } +} + +//=========================================================================== +// +// +// +//=========================================================================== + +float FTexCoordInfo::TextureOffset(float textureoffset) const +{ + float tscale = fabs(mTempScale.X); + float scale = fabs(mScale.X); + if (tscale == 1.f) + { + if (scale == 1.f || mWorldPanning) return textureoffset; + else return textureoffset / scale; + } + else + { + if (mWorldPanning) return textureoffset / tscale; + else return textureoffset / scale; + } +} + +//=========================================================================== +// +// Returns the size for which texture offset coordinates are used. +// +//=========================================================================== + +float FTexCoordInfo::TextureAdjustWidth() const +{ + if (mWorldPanning) + { + float tscale = fabs(mTempScale.X); + if (tscale == 1.f) return (float)mRenderWidth; + else return mWidth / fabs(tscale); + } + else return (float)mWidth; +} + + +//=========================================================================== +// +// Retrieve texture coordinate info for per-wall scaling +// +//=========================================================================== + +void FTexCoordInfo::GetFromTexture(FTexture *tex, float x, float y) +{ + if (x == 1.f) + { + mRenderWidth = tex->GetScaledWidth(); + mScale.X = (float)tex->Scale.X; + mTempScale.X = 1.f; + } + else + { + float scale_x = x * (float)tex->Scale.X; + mRenderWidth = xs_CeilToInt(tex->GetWidth() / scale_x); + mScale.X = scale_x; + mTempScale.X = x; + } + + if (y == 1.f) + { + mRenderHeight = tex->GetScaledHeight(); + mScale.Y = (float)tex->Scale.Y; + mTempScale.Y = 1.f; + } + else + { + float scale_y = y * (float)tex->Scale.Y; + mRenderHeight = xs_CeilToInt(tex->GetHeight() / scale_y); + mScale.Y = scale_y; + mTempScale.Y = y; + } + if (tex->bHasCanvas) + { + mScale.Y = -mScale.Y; + mRenderHeight = -mRenderHeight; + } + mWorldPanning = tex->bWorldPanning; + mWidth = tex->GetWidth(); +} diff --git a/src/textures/textures.h b/src/textures/textures.h index d064441d1..fc70ef122 100644 --- a/src/textures/textures.h +++ b/src/textures/textures.h @@ -211,6 +211,7 @@ enum FTextureFormat : uint32_t TEX_Count }; + // Base texture class class FTexture { @@ -802,6 +803,24 @@ public: extern FTextureManager TexMan; +struct FTexCoordInfo +{ + int mRenderWidth; + int mRenderHeight; + int mWidth; + FVector2 mScale; + FVector2 mTempScale; + bool mWorldPanning; + + float FloatToTexU(float v) const { return v / mRenderWidth; } + float FloatToTexV(float v) const { return v / mRenderHeight; } + float RowOffset(float ofs) const; + float TextureOffset(float ofs) const; + float TextureAdjustWidth() const; + void GetFromTexture(FTexture *tex, float x, float y); +}; + + #endif From 45ef7bca4fab838ff562ab3d99c2f70423e03e6a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 17 Nov 2018 18:55:44 +0100 Subject: [PATCH 6/6] - fixed: FTexture::SmoothEdges must forward its result to the base texture in case a redirection is in effect. Both need the bMasked flag, or some code will think that the texture is not fully opaque if no holes were found. --- src/hwrenderer/textures/hw_material.h | 2 +- src/textures/texture.cpp | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/hwrenderer/textures/hw_material.h b/src/hwrenderer/textures/hw_material.h index 581368b55..c35b23c08 100644 --- a/src/hwrenderer/textures/hw_material.h +++ b/src/hwrenderer/textures/hw_material.h @@ -76,7 +76,7 @@ public: } bool isMasked() const { - return !!sourcetex->bMasked; + return sourcetex->bMasked; } bool isExpanded() const { diff --git a/src/textures/texture.cpp b/src/textures/texture.cpp index 75b7e5e7d..85b57798d 100644 --- a/src/textures/texture.cpp +++ b/src/textures/texture.cpp @@ -1351,6 +1351,11 @@ bool FTexture::ProcessData(unsigned char * buffer, int w, int h, bool ispatch) if (bMasked) { bMasked = SmoothEdges(buffer, w, h); + if (!bMasked) + { + auto stex = GetRedirect(); + stex->bMasked = false; // also clear in the base texture if there is a redirection. + } if (bMasked && !ispatch) FindHoles(buffer, w, h); } return true;