diff --git a/src/gl/dynlights/gl_dynlight.cpp b/src/gl/dynlights/gl_dynlight.cpp index ae19ecf608..40008e3ad5 100644 --- a/src/gl/dynlights/gl_dynlight.cpp +++ b/src/gl/dynlights/gl_dynlight.cpp @@ -1082,6 +1082,7 @@ void gl_AttachLight(AActor *actor, unsigned int count, const FLightDefaults *lig light->target = actor; light->owned = true; light->ObjectFlags |= OF_Transient; + light->flags4 |= MF4_ATTENUATE; actor->dynamiclights.Push(light); } light->flags2&=~MF2_DORMANT; diff --git a/src/gl/dynlights/gl_dynlight.h b/src/gl/dynlights/gl_dynlight.h index 84965e3185..c51e0c79d8 100644 --- a/src/gl/dynlights/gl_dynlight.h +++ b/src/gl/dynlights/gl_dynlight.h @@ -50,6 +50,7 @@ enum #define MF4_SUBTRACTIVE MF4_MISSILEEVENMORE #define MF4_ADDITIVE MF4_MISSILEMORE #define MF4_DONTLIGHTSELF MF4_SEESDAGGERS +#define MF4_ATTENUATE MF4_INCOMBAT enum ELightType { diff --git a/src/gl/dynlights/gl_dynlight1.cpp b/src/gl/dynlights/gl_dynlight1.cpp index d20f5c01b1..2f8ef44edc 100644 --- a/src/gl/dynlights/gl_dynlight1.cpp +++ b/src/gl/dynlights/gl_dynlight1.cpp @@ -116,7 +116,7 @@ bool gl_GetLight(int group, Plane & p, ADynamicLight * light, bool checkside, FD data[4] = r; data[5] = g; data[6] = b; - data[7] = 0; + data[7] = !!(light->flags4 & MF4_ATTENUATE); return true; } diff --git a/src/p_acs.cpp b/src/p_acs.cpp index fcbff904a8..f36aaaf69a 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -2907,7 +2907,8 @@ FSerializer &Serialize(FSerializer &arc, const char *key, SavingRunningscript &r void DACSThinker::Serialize(FSerializer &arc) { Super::Serialize(arc); - arc("scripts", Scripts); + arc("scripts", Scripts) + ("lastscript", LastScript); if (arc.isWriting()) { diff --git a/src/portal.cpp b/src/portal.cpp index cef79820fe..f1454cdc6c 100644 --- a/src/portal.cpp +++ b/src/portal.cpp @@ -1024,7 +1024,8 @@ void P_CreateLinkedPortals() { if (sectors[i].GetPortalType(j) == PORTS_LINKEDPORTAL && sectors[i].PortalGroup == 0) { - CollectSectors(sectors[i].GetOppositePortalGroup(j), §ors[i]); + auto p = sectors[i].GetPortal(j); + CollectSectors(p->mOrigin->PortalGroup, §ors[i]); } } } diff --git a/src/textures/multipatchtexture.cpp b/src/textures/multipatchtexture.cpp index 5d9aeb433b..b7e664355b 100644 --- a/src/textures/multipatchtexture.cpp +++ b/src/textures/multipatchtexture.cpp @@ -48,6 +48,7 @@ #include "v_palette.h" #include "v_video.h" #include "v_text.h" +#include "cmdlib.h" #include "m_fixed.h" #include "textures/textures.h" #include "r_data/colormaps.h" @@ -138,7 +139,6 @@ struct strifemaptexture_t struct FPatchLookup { FString Name; - FTexture *Texture; }; @@ -166,6 +166,7 @@ public: int GetSourceLump() { return DefinitionLump; } FTexture *GetRedirect(bool wantwarped); FTexture *GetRawTexture(); + void ResolvePatches(); protected: BYTE *Pixels; @@ -185,8 +186,18 @@ protected: TexPart(); }; + struct TexInit + { + FString TexName; + int UseType = TEX_Null; + bool Silent = false; + bool HasLine = false; + FScriptPosition sc; + }; + int NumParts; TexPart *Parts; + TexInit *Inits; bool bRedirect:1; bool bTranslucentPatches:1; @@ -194,7 +205,7 @@ protected: private: void CheckForHacks (); - void ParsePatch(FScanner &sc, TexPart & part, bool silent, int usetype); + void ParsePatch(FScanner &sc, TexPart & part, TexInit &init); }; //========================================================================== @@ -204,7 +215,7 @@ private: //========================================================================== FMultiPatchTexture::FMultiPatchTexture (const void *texdef, FPatchLookup *patchlookup, int maxpatchnum, bool strife, int deflumpnum) -: Pixels (0), Spans(0), Parts(0), bRedirect(false), bTranslucentPatches(false) +: Pixels (0), Spans(0), Parts(nullptr), Inits(nullptr), bRedirect(false), bTranslucentPatches(false) { union { @@ -240,7 +251,8 @@ FMultiPatchTexture::FMultiPatchTexture (const void *texdef, FPatchLookup *patchl } UseType = FTexture::TEX_Wall; - Parts = NumParts > 0 ? new TexPart[NumParts] : NULL; + Parts = NumParts > 0 ? new TexPart[NumParts] : nullptr; + Inits = NumParts > 0 ? new TexInit[NumParts] : nullptr; Width = SAFESHORT(mtexture.d->width); Height = SAFESHORT(mtexture.d->height); Name = (char *)mtexture.d->name; @@ -272,17 +284,9 @@ FMultiPatchTexture::FMultiPatchTexture (const void *texdef, FPatchLookup *patchl } Parts[i].OriginX = LittleShort(mpatch.d->originx); Parts[i].OriginY = LittleShort(mpatch.d->originy); - Parts[i].Texture = patchlookup[LittleShort(mpatch.d->patch)].Texture; - if (Parts[i].Texture == NULL) - { - Printf(TEXTCOLOR_RED "Unknown patch %s in texture %s\n", patchlookup[LittleShort(mpatch.d->patch)].Name.GetChars(), Name.GetChars()); - NumParts--; - i--; - } - else - { - Parts[i].Texture->bKeepAround = true; - } + Parts[i].Texture = nullptr; + Inits[i].TexName = patchlookup[LittleShort(mpatch.d->patch)].Name; + Inits[i].UseType = TEX_WallPatch; if (strife) mpatch.s++; else @@ -295,17 +299,6 @@ FMultiPatchTexture::FMultiPatchTexture (const void *texdef, FPatchLookup *patchl CheckForHacks (); - // If this texture is just a wrapper around a single patch, we can simply - // forward GetPixels() and GetColumn() calls to that patch. - if (NumParts == 1) - { - if (Parts->OriginX == 0 && Parts->OriginY == 0 && - Parts->Texture->GetWidth() == Width && - Parts->Texture->GetHeight() == Height) - { - bRedirect = true; - } - } DefinitionLump = deflumpnum; } @@ -327,6 +320,11 @@ FMultiPatchTexture::~FMultiPatchTexture () delete[] Parts; Parts = NULL; } + if (Inits != nullptr) + { + delete[] Inits; + Inits = nullptr; + } if (Spans != NULL) { FreeSpans (Spans); @@ -865,19 +863,6 @@ void FTextureManager::AddTexturesLump (const void *lumpdata, int lumpsize, int d pnames.Read(pname, 8); pname[8] = '\0'; patchlookup[i].Name = pname; - FTextureID j = CheckForTexture (patchlookup[i].Name, FTexture::TEX_WallPatch); - if (j.isValid()) - { - patchlookup[i].Texture = Textures[j.GetIndex()].Texture; - } - else - { - // Shareware Doom has the same PNAMES lump as the registered - // Doom, so printing warnings for patches that don't really - // exist isn't such a good idea. - //Printf ("Patch %s not found.\n", patchlookup[i].Name); - patchlookup[i].Texture = NULL; - } } } @@ -998,35 +983,13 @@ void FTextureManager::AddTexturesLumps (int lump1, int lump2, int patcheslump) // //========================================================================== -void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part, bool silent, int usetype) +void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part, TexInit &init) { FString patchname; + int Mirror = 0; sc.MustGetString(); - FTextureID texno = TexMan.CheckForTexture(sc.String, usetype); - int Mirror = 0; - - if (!texno.isValid()) - { - if (strlen(sc.String) <= 8 && !strpbrk(sc.String, "./")) - { - int lumpnum = Wads.CheckNumForName(sc.String, usetype == TEX_MiscPatch? ns_graphics : ns_patches); - if (lumpnum >= 0) - { - part.Texture = FTexture::CreateTexture(lumpnum, usetype); - TexMan.AddTexture(part.Texture); - } - } - } - else - { - part.Texture = TexMan[texno]; - bComplex |= part.Texture->bComplex; - } - if (part.Texture == NULL) - { - if (!silent) sc.ScriptMessage(TEXTCOLOR_RED "Unknown patch '%s' in texture '%s'\n", sc.String, Name.GetChars()); - } + init.TexName = sc.String; sc.MustGetStringName(","); sc.MustGetNumber(); part.OriginX = sc.Number; @@ -1209,6 +1172,7 @@ FMultiPatchTexture::FMultiPatchTexture (FScanner &sc, int usetype) : Pixels (0), Spans(0), Parts(0), bRedirect(false), bTranslucentPatches(false) { TArray parts; + TArray inits; bool bSilent = false; bMultiPatch = true; @@ -1269,16 +1233,51 @@ FMultiPatchTexture::FMultiPatchTexture (FScanner &sc, int usetype) else if (sc.Compare("Patch")) { TexPart part; - ParsePatch(sc, part, bSilent, TEX_WallPatch); - if (part.Texture != NULL) parts.Push(part); + TexInit init; + ParsePatch(sc, part, init); + if (init.TexName.IsNotEmpty()) + { + parts.Push(part); + init.UseType = TEX_WallPatch; + init.Silent = bSilent; + init.HasLine = true; + init.sc = sc; + inits.Push(init); + } + part.Texture = NULL; + part.Translation = NULL; + } + else if (sc.Compare("Sprite")) + { + TexPart part; + TexInit init; + ParsePatch(sc, part, init); + if (init.TexName.IsNotEmpty()) + { + parts.Push(part); + init.UseType = TEX_Sprite; + init.Silent = bSilent; + init.HasLine = true; + init.sc = sc; + inits.Push(init); + } part.Texture = NULL; part.Translation = NULL; } else if (sc.Compare("Graphic")) { TexPart part; - ParsePatch(sc, part, bSilent, TEX_MiscPatch); - if (part.Texture != NULL) parts.Push(part); + TexInit init; + ParsePatch(sc, part, init); + if (init.TexName.IsNotEmpty()) + { + parts.Push(part); + init.UseType = TEX_MiscPatch; + init.Silent = bSilent; + init.HasLine = true; + init.sc = sc; + inits.Push(init); + } part.Texture = NULL; part.Translation = NULL; } @@ -1299,21 +1298,10 @@ FMultiPatchTexture::FMultiPatchTexture (FScanner &sc, int usetype) NumParts = parts.Size(); Parts = new TexPart[NumParts]; memcpy(Parts, &parts[0], NumParts * sizeof(*Parts)); - - //CalcBitSize (); - - // If this texture is just a wrapper around a single patch, we can simply - // forward GetPixels() and GetColumn() calls to that patch. - if (NumParts == 1) + Inits = new TexInit[NumParts]; + for (int i = 0; i < NumParts; i++) { - if (Parts->OriginX == 0 && Parts->OriginY == 0 && - Parts->Texture->GetWidth() == Width && - Parts->Texture->GetHeight() == Height && - Parts->Rotate == 0 && - !bComplex) - { - bRedirect = true; - } + Inits[i] = inits[i]; } } @@ -1330,6 +1318,58 @@ FMultiPatchTexture::FMultiPatchTexture (FScanner &sc, int usetype) } +void FMultiPatchTexture::ResolvePatches() +{ + if (Inits != nullptr) + { + for (int i = 0; i < NumParts; i++) + { + FTextureID texno = TexMan.CheckForTexture(Inits[i].TexName, Inits[i].UseType); + + if (!texno.isValid()) + { + if (!Inits[i].Silent) + { + if (Inits[i].HasLine) Inits[i].sc.Message(MSG_WARNING, "Unknown patch '%s' in texture '%s'\n", Inits[i].TexName.GetChars(), Name.GetChars()); + else Printf(TEXTCOLOR_YELLOW "Unknown patch '%s' in texture '%s'\n", Inits[i].TexName.GetChars(), Name.GetChars()); + } + } + else + { + Parts[i].Texture = TexMan[texno]; + bComplex |= Parts[i].Texture->bComplex; + Parts[i].Texture->bKeepAround = true; + } + } + for (int i = 0; i < NumParts; i++) + { + if (Parts[i].Texture == nullptr) + { + memcpy(&Parts[i], &Parts[i + 1], NumParts - i - 1); + i--; + NumParts--; + } + } + } + delete[] Inits; + Inits = nullptr; + + // If this texture is just a wrapper around a single patch, we can simply + // forward GetPixels() and GetColumn() calls to that patch. + + if (NumParts == 1) + { + if (Parts->OriginX == 0 && Parts->OriginY == 0 && + Parts->Texture->GetWidth() == Width && + Parts->Texture->GetHeight() == Height && + Parts->Rotate == 0 && + !bComplex) + { + bRedirect = true; + } + } +} + void FTextureManager::ParseXTexture(FScanner &sc, int usetype) { diff --git a/src/textures/texturemanager.cpp b/src/textures/texturemanager.cpp index 3fb01dc6cf..07ed71a3bb 100644 --- a/src/textures/texturemanager.cpp +++ b/src/textures/texturemanager.cpp @@ -981,6 +981,10 @@ void FTextureManager::Init() { AddTexturesForWad(i); } + for (unsigned i = 0; i < Textures.Size(); i++) + { + Textures[i].Texture->ResolvePatches(); + } // Add one marker so that the last WAD is easier to handle and treat // Build tiles as a completely separate block. diff --git a/src/textures/textures.h b/src/textures/textures.h index 1489aa7ef9..37db437063 100644 --- a/src/textures/textures.h +++ b/src/textures/textures.h @@ -242,6 +242,7 @@ public: int GetScaledTopOffset () { int foo = int((TopOffset * 2) / Scale.Y); return (foo >> 1) + (foo & 1); } double GetScaledLeftOffsetDouble() { return LeftOffset / Scale.X; } double GetScaledTopOffsetDouble() { return TopOffset / Scale.Y; } + virtual void ResolvePatches() {} virtual void SetFrontSkyLayer(); diff --git a/wadsrc/static/shaders/glsl/main.fp b/wadsrc/static/shaders/glsl/main.fp index 5ab9f11188..5834dcf5d8 100644 --- a/wadsrc/static/shaders/glsl/main.fp +++ b/wadsrc/static/shaders/glsl/main.fp @@ -146,16 +146,19 @@ float diffuseContribution(vec3 lightDirection, vec3 normal) // //=========================================================================== -float pointLightAttenuation(vec4 lightpos) +float pointLightAttenuation(vec4 lightpos, float attenuate) { float attenuation = max(lightpos.w - distance(pixelpos.xyz, lightpos.xyz),0.0) / lightpos.w; - #if 0 + if (attenuate == 0.0) + { return attenuation; - #else + } + else + { vec3 lightDirection = normalize(lightpos.xyz - pixelpos.xyz); float diffuseAmount = diffuseContribution(lightDirection, normalize(vWorldNormal.xyz)); return attenuation * diffuseAmount; - #endif + } } //=========================================================================== @@ -233,7 +236,7 @@ vec4 getLightColor(float fogdist, float fogfactor) vec4 lightpos = lights[i]; vec4 lightcolor = lights[i+1]; - lightcolor.rgb *= pointLightAttenuation(lightpos); + lightcolor.rgb *= pointLightAttenuation(lightpos, lightcolor.a); dynlight.rgb += lightcolor.rgb; } // @@ -244,7 +247,7 @@ vec4 getLightColor(float fogdist, float fogfactor) vec4 lightpos = lights[i]; vec4 lightcolor = lights[i+1]; - lightcolor.rgb *= pointLightAttenuation(lightpos); + lightcolor.rgb *= pointLightAttenuation(lightpos, lightcolor.a); dynlight.rgb -= lightcolor.rgb; } } @@ -352,7 +355,7 @@ void main() vec4 lightpos = lights[i]; vec4 lightcolor = lights[i+1]; - lightcolor.rgb *= pointLightAttenuation(lightpos); + lightcolor.rgb *= pointLightAttenuation(lightpos, lightcolor.a); addlight.rgb += lightcolor.rgb; } frag.rgb = clamp(frag.rgb + desaturate(addlight).rgb, 0.0, 1.0);