diff --git a/src/c_cvars.cpp b/src/c_cvars.cpp index ba6a5e53e0..18b77c3eaf 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; } diff --git a/src/hwrenderer/scene/hw_portal.cpp b/src/hwrenderer/scene/hw_portal.cpp index 9cb35c696c..787ef0b83f 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 f9d9e243c6..879420c106 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); diff --git a/src/hwrenderer/textures/hw_material.cpp b/src/hwrenderer/textures/hw_material.cpp index 48d313d95a..303c3e83a0 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 4274426290..c35b23c08f 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. @@ -93,7 +76,7 @@ public: } bool isMasked() const { - return !!sourcetex->bMasked; + return sourcetex->bMasked; } bool isExpanded() const { @@ -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 0a4c5507de..7a2363be67 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/p_enemy.cpp b/src/p_enemy.cpp index b99d607982..12f43e9fc1 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 1cd3970f4b..568bfd2b82 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); diff --git a/src/textures/texture.cpp b/src/textures/texture.cpp index 047a9b2055..85b57798df 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; @@ -1543,3 +1548,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 d064441d1d..fc70ef1229 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 diff --git a/wadsrc/static/zscript/strife/weapongrenade.txt b/wadsrc/static/zscript/strife/weapongrenade.txt index 8d6a12b2d3..e160be3c88 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.