diff --git a/specs/udmf_zdoom.txt b/specs/udmf_zdoom.txt index 2f30e4df9..2559ebe78 100644 --- a/specs/udmf_zdoom.txt +++ b/specs/udmf_zdoom.txt @@ -210,6 +210,9 @@ Note: All fields default to false unless mentioned otherwise. coloradd_top = ; // Additive material color to apply to top section of sidedef. Default is black (0x000000) coloradd_mid = ; // Additive material color to apply to middle section of sidedef. Default is black (0x000000) coloradd_bottom = ; // Additive material color to apply to bottom section of sidedef. Default is black (0x000000) + colorization_top = ; // Sets a colorization record for the upper texture. Colorization records must be defined in TEXTURES. + colorization_mid = ; // Sets a colorization record for the middle texture. Colorization records must be defined in TEXTURES. + colorization_bottom = ; // Sets a colorization record for the lower texture. Colorization records must be defined in TEXTURES. } sector @@ -288,6 +291,9 @@ Note: All fields default to false unless mentioned otherwise. coloradd_sprites = ; // Additive material color applied to sprites within the sector. Default is black (0x000000) coloradd_walls = ; // Additive material color applied to walls within the sector. Default is black (0x000000) + colorization_floor = ; // Sets a colorization record for the floor texture. Colorization records must be defined in TEXTURES. + colorization_ceiling = ; // Sets a colorization record for the ceiling texture. Colorization records must be defined in TEXTURES. + portal_ceil_blocksound = ; // ceiling portal blocks sound. portal_ceil_disabled = ; // ceiling portal disabled. portal_ceil_nopass = ; // ceiling portal blocks movement if true. @@ -495,6 +501,9 @@ arg0str in dynamic lights. Added automapstyle and revealed linedef properties. Replaced tabs with spaces. +1.31 22.12.2019 +Coloriation options added + =============================================================================== EOF =============================================================================== diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1101d5cea..98157a04d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1171,6 +1171,7 @@ add_executable( zdoom WIN32 MACOSX_BUNDLE utility/x86.cpp utility/strnatcmp.c utility/zstring.cpp + utility/dictionary.cpp utility/math/asin.c utility/math/atan.c utility/math/const.c diff --git a/src/console/c_cvars.cpp b/src/console/c_cvars.cpp index 103c8cf95..0b4bdd2ed 100644 --- a/src/console/c_cvars.cpp +++ b/src/console/c_cvars.cpp @@ -48,6 +48,8 @@ #include "menu/menu.h" #include "vm.h" +#include "version.h" + struct FLatchedValue { FBaseCVar *Variable; @@ -1745,3 +1747,55 @@ CCMD (archivecvar) } } } + +void C_GrabCVarDefaults () +{ + int lump, lastlump = 0; + int lumpversion, gamelastrunversion; + gamelastrunversion = atoi(LASTRUNVERSION); + + while ((lump = Wads.FindLump("DEFCVARS", &lastlump)) != -1) + { + FScanner sc(lump); + + sc.MustGetString(); + if (!sc.Compare("version")) + sc.ScriptError("Must declare version for defcvars!"); + sc.MustGetNumber(); + lumpversion = sc.Number; + if (lumpversion > gamelastrunversion) + sc.ScriptError("Unsupported version %i (%i supported)", lumpversion, gamelastrunversion); + if (lumpversion < 218) + sc.ScriptError("Version must be at least 218 (current version %i)", gamelastrunversion); + + FBaseCVar *var; + + while (sc.GetString()) + { + if (sc.Compare("set")) + { + sc.MustGetString(); + } + var = FindCVar (sc.String, NULL); + if (var != NULL) + { + if (var->GetFlags() & CVAR_ARCHIVE) + { + UCVarValue val; + + sc.MustGetString(); + val.String = const_cast(sc.String); + var->SetGenericRepDefault(val, CVAR_String); + } + else + { + sc.ScriptError("Cannot set cvar default for non-config cvar '%s'", sc.String); + } + } + else + { + sc.ScriptError("Unknown cvar '%s'", sc.String); + } + } + } +} diff --git a/src/d_main.cpp b/src/d_main.cpp index bc4b66dde..12ea85c47 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -145,6 +145,7 @@ void DrawFullscreenSubtitle(const char *text); void D_Cleanup(); void FreeSBarInfoScript(); void I_UpdateWindowTitle(); +void C_GrabCVarDefaults (); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- @@ -2531,6 +2532,8 @@ static int D_DoomMain_Internal (void) allwads.ShrinkToFit(); SetMapxxFlag(); + C_GrabCVarDefaults(); //parse DEFCVARS + GameConfig->DoKeySetup(gameinfo.ConfigName); // Now that wads are loaded, define mod-specific cvars. diff --git a/src/gamedata/r_defs.h b/src/gamedata/r_defs.h index 6b345692e..4987ee6fc 100644 --- a/src/gamedata/r_defs.h +++ b/src/gamedata/r_defs.h @@ -34,6 +34,7 @@ #include "templates.h" #include "m_bbox.h" #include "dobjgc.h" +#include "r_data/r_translate.h" // Some more or less basic data types // we depend on. @@ -601,24 +602,6 @@ FSerializer &Serialize(FSerializer &arc, const char *key, secspecial_t &spec, se enum class EMoveResult { ok, crushed, pastdest }; -struct TextureManipulation -{ - enum - { - BlendNone = 0, - BlendAlpha = 1, - BlendScreen = 2, - BlendOverlay = 3, - BlendHardLight = 4, - BlendMask = 7, - InvertBit = 8 - }; - PalEntry AddColor; // Alpha contains the blend flags - PalEntry ModulateColor; // Alpha may contain a multiplier to get higher values than 1.0 without promoting this to 4 full floats. - PalEntry BlendColor; - float DesaturationFactor; -}; - struct sector_t { @@ -1047,66 +1030,40 @@ public: Flags &= ~SECF_SPECIALFLAGS; } + void CheckExColorFlag(); + + void InitAllExcolors() + { + if (SpecialColors[sector_t::wallbottom] != 0xffffffff || SpecialColors[sector_t::walltop] != 0xffffffff || AdditiveColors[sector_t::walltop] != 0xffffffff) CheckExColorFlag(); + } + void SetSpecialColor(int slot, int r, int g, int b) { SpecialColors[slot] = PalEntry(255, r, g, b); + if ((slot == sector_t::wallbottom || slot == sector_t::walltop) && SpecialColors[slot] != 0xffffffff) CheckExColorFlag(); } void SetSpecialColor(int slot, PalEntry rgb) { rgb.a = 255; SpecialColors[slot] = rgb; + if ((slot == sector_t::wallbottom || slot == sector_t::walltop) && rgb != 0xffffffff) CheckExColorFlag(); } void SetAdditiveColor(int slot, PalEntry rgb) { rgb.a = 255; AdditiveColors[slot] = rgb; + if ((slot == sector_t::walltop) && AdditiveColors[slot] != 0xffffffff) CheckExColorFlag(); // Wallbottom of this is not used. + } // TextureFX parameters - void SetTextureFx(int slot, const TextureManipulation &tm) + void SetTextureFx(int slot, const TextureManipulation *tm) { - planes[slot].TextureFx = tm; // this is for getting the data from a texture. - } - - void SetTextureModulateColor(int slot, PalEntry rgb) - { - rgb.a = planes[slot].TextureFx.ModulateColor.a; - planes[slot].TextureFx.ModulateColor = rgb; - } - - void SetTextureModulateScaleFactor(int slot, int fac) - { - planes[slot].TextureFx.ModulateColor.a = (uint8_t)fac; - } - - void SetTextureAdditiveColor(int slot, PalEntry rgb) - { - rgb.a = planes[slot].TextureFx.AddColor.a; - planes[slot].TextureFx.AddColor = rgb; - } - - void SetTextureBlendColor(int slot, PalEntry rgb) - { - planes[slot].TextureFx.BlendColor = rgb; - } - - void SetTextureDesaturationFactor(int slot, double fac) - { - planes[slot].TextureFx.DesaturationFactor = (float)fac; - } - - void SetTextureBlendMode(int slot, int mode) - { - planes[slot].TextureFx.AddColor.a = (planes[slot].TextureFx.AddColor.a & ~TextureManipulation::BlendMask) | (mode & TextureManipulation::BlendMask); - } - - void SetTextureInvert(int slot, bool on) - { - if (on) planes[slot].TextureFx.AddColor.a |= TextureManipulation::InvertBit; - else planes[slot].TextureFx.AddColor.a &= ~TextureManipulation::InvertBit; + if (tm) planes[slot].TextureFx = *tm; // this is for getting the data from a texture. + else planes[slot].TextureFx = {}; } @@ -1194,6 +1151,7 @@ enum WALLF_WRAP_MIDTEX = 32, // Like the line counterpart, but only for this side. WALLF_POLYOBJ = 64, // This wall belongs to a polyobject. WALLF_LIGHT_FOG = 128, // This wall's Light is used even in fog. + WALLF_EXTCOLOR = 256, // enables the extended color options (flagged to allow the renderer to easily skip the relevant code) }; struct side_t @@ -1250,7 +1208,7 @@ struct side_t uint32_t LeftSide, RightSide; // [RH] Group walls into loops uint16_t TexelLength; int16_t Light; - uint8_t Flags; + uint16_t Flags; int UDMFIndex; // needed to access custom UDMF fields which are stored in loading order. FLightNode * lighthead; // all dynamic lights that may affect this wall seg_t **segs; // all segs belonging to this sidedef in ascending order. Used for precise rendering @@ -1385,10 +1343,11 @@ struct side_t void EnableAdditiveColor(int which, bool enable) { - int flag = enable ? part::UseOwnAdditiveColor : 0; + const int flag = part::UseOwnAdditiveColor; if (enable) { textures[which].flags |= flag; + Flags |= WALLF_EXTCOLOR; } else { @@ -1402,42 +1361,17 @@ struct side_t textures[which].AdditiveColor = rgb; } - void SetTextureModulateColor(int slot, PalEntry rgb) + void SetTextureFx(int slot, const TextureManipulation* tm) { - rgb.a = textures[slot].TextureFx.ModulateColor.a; - textures[slot].TextureFx.ModulateColor = rgb; - } - - void SetTextureModulateScaleFactor(int slot, int fac) - { - textures[slot].TextureFx.ModulateColor.a = (uint8_t)fac; - } - - void SetTextureAdditiveColor(int slot, PalEntry rgb) - { - rgb.a = textures[slot].TextureFx.AddColor.a; - textures[slot].TextureFx.AddColor = rgb; - } - - void SetTextureBlendColor(int slot, PalEntry rgb) - { - textures[slot].TextureFx.BlendColor = rgb; - } - - void SetTextureDesaturationFactor(int slot, double fac) - { - textures[slot].TextureFx.DesaturationFactor = (float)fac; - } - - void SetTextureBlendMode(int slot, int mode) - { - textures[slot].TextureFx.AddColor.a = (textures[slot].TextureFx.AddColor.a & ~TextureManipulation::BlendMask) | (mode & TextureManipulation::BlendMask); - } - - void SetTextureInvert(int slot, bool on) - { - if (on) textures[slot].TextureFx.AddColor.a |= TextureManipulation::InvertBit; - else textures[slot].TextureFx.AddColor.a &= ~TextureManipulation::InvertBit; + if (tm) + { + textures[slot].TextureFx = *tm; // this is for getting the data from a texture. + if (tm->AddColor.a) Flags |= WALLF_EXTCOLOR; + } + else + { + textures[slot].TextureFx = {}; + } } PalEntry GetAdditiveColor(int which, sector_t *frontsector) const @@ -1785,5 +1719,15 @@ inline int sector_t::GetFloorLight() const { return ::GetFloorLight(this); } inline int sector_t::GetCeilingLight() const { return ::GetCeilingLight(this); } inline double sector_t::GetFriction(int plane, double *movefac) const { return ::GetFriction(this, plane, movefac); } +inline void sector_t::CheckExColorFlag() +{ + for (auto ld : Lines) + { + if (ld->frontsector == this) ld->sidedef[0]->Flags |= WALLF_EXTCOLOR; + if (ld->backsector == this) ld->sidedef[1]->Flags |= WALLF_EXTCOLOR; + } +} + + #endif diff --git a/src/gamedata/textures/texturemanager.cpp b/src/gamedata/textures/texturemanager.cpp index 1bdbf9624..589f787b3 100644 --- a/src/gamedata/textures/texturemanager.cpp +++ b/src/gamedata/textures/texturemanager.cpp @@ -141,6 +141,7 @@ void FTextureManager::DeleteAll() } mAnimatedDoors.Clear(); BuildTileData.Clear(); + tmanips.Clear(); } //========================================================================== @@ -688,6 +689,74 @@ void FTextureManager::AddHiresTextures (int wadnum) // //========================================================================== +void FTextureManager::ParseColorization(FScanner& sc) +{ + TextureManipulation tm = {}; + tm.ModulateColor = 0x01ffffff; + sc.MustGetString(); + FName cname = sc.String; + sc.MustGetToken('{'); + while (!sc.CheckToken('}')) + { + sc.MustGetString(); + if (sc.Compare("DesaturationFactor")) + { + sc.MustGetFloat(); + tm.DesaturationFactor = (float)sc.Float; + } + else if (sc.Compare("AddColor")) + { + sc.MustGetString(); + tm.AddColor = (tm.AddColor & 0xff000000) | (V_GetColor(NULL, sc) & 0xffffff); + } + else if (sc.Compare("ModulateColor")) + { + sc.MustGetString(); + tm.ModulateColor = V_GetColor(NULL, sc) & 0xffffff; + if (sc.CheckToken(',')) + { + sc.MustGetNumber(); + tm.ModulateColor.a = sc.Number; + } + else tm.ModulateColor.a = 1; + } + else if (sc.Compare("BlendColor")) + { + sc.MustGetString(); + tm.BlendColor = V_GetColor(NULL, sc) & 0xffffff; + sc.MustGetToken(','); + sc.MustGetString(); + static const char* opts[] = { "none", "alpha", "screen", "overlay", "hardlight", nullptr }; + tm.AddColor.a = (tm.AddColor.a & ~TextureManipulation::BlendMask) | sc.MustMatchString(opts); + if (sc.Compare("alpha")) + { + sc.MustGetToken(','); + sc.MustGetFloat(); + tm.BlendColor.a = (uint8_t)(clamp(sc.Float, 0., 1.) * 255); + } + } + else if (sc.Compare("invert")) + { + tm.AddColor.a |= TextureManipulation::InvertBit; + } + else sc.ScriptError("Unknown token '%s'", sc.String); + } + if (tm.CheckIfEnabled()) + { + tmanips.Insert(cname, tm); + } + else + { + tmanips.Remove(cname); + } + +} +//========================================================================== +// +// Loads the HIRESTEX lumps +// +//========================================================================== + void FTextureManager::LoadTextureDefs(int wadnum, const char *lumpname, FMultipatchTextureBuilder &build) { int remapLump, lastLump; @@ -824,19 +893,23 @@ void FTextureManager::ParseTextureDef(int lump, FMultipatchTextureBuilder &build } else if (sc.Compare("sprite")) { - build.ParseTexture(sc, ETextureType::Sprite); + build.ParseTexture(sc, ETextureType::Sprite); } else if (sc.Compare("walltexture")) { - build.ParseTexture(sc, ETextureType::Wall); + build.ParseTexture(sc, ETextureType::Wall); } else if (sc.Compare("flat")) { - build.ParseTexture(sc, ETextureType::Flat); + build.ParseTexture(sc, ETextureType::Flat); } else if (sc.Compare("graphic")) { - build.ParseTexture(sc, ETextureType::MiscPatch); + build.ParseTexture(sc, ETextureType::MiscPatch); + } + else if (sc.Compare("colorization")) + { + ParseColorization(sc); } else if (sc.Compare("#include")) { diff --git a/src/gamedata/textures/textures.h b/src/gamedata/textures/textures.h index 279119915..416d9e719 100644 --- a/src/gamedata/textures/textures.h +++ b/src/gamedata/textures/textures.h @@ -601,6 +601,7 @@ public: void AddPatches (int lumpnum); void AddHiresTextures (int wadnum); void LoadTextureDefs(int wadnum, const char *lumpname, FMultipatchTextureBuilder &build); + void ParseColorization(FScanner& sc); void ParseTextureDef(int remapLump, FMultipatchTextureBuilder &build); void SortTexturesByType(int start, int end); bool AreTexturesCompatible (FTextureID picnum1, FTextureID picnum2); @@ -626,6 +627,12 @@ public: FSwitchDef *FindSwitch (FTextureID texture); FDoorAnimation *FindAnimatedDoor (FTextureID picnum); + TextureManipulation* GetTextureManipulation(FName name) + { + return tmanips.CheckKey(name); + } + + private: // texture counting @@ -683,6 +690,7 @@ private: TArray mSwitchDefs; TArray mAnimatedDoors; + TMap tmanips; public: TArray mAnimations; diff --git a/src/maploader/udmf.cpp b/src/maploader/udmf.cpp index 8226f525d..c1aae1715 100644 --- a/src/maploader/udmf.cpp +++ b/src/maploader/udmf.cpp @@ -1295,6 +1295,18 @@ public: Flag(sd->Flags, WALLF_NOAUTODECALS, key); continue; + case NAME_colorization_top: + sd->SetTextureFx(side_t::top, TexMan.GetTextureManipulation(CheckString(key))); + break; + + case NAME_colorization_mid: + sd->SetTextureFx(side_t::mid, TexMan.GetTextureManipulation(CheckString(key))); + break; + + case NAME_colorization_bottom: + sd->SetTextureFx(side_t::bottom, TexMan.GetTextureManipulation(CheckString(key))); + break; + case NAME_nogradient_top: Flag(sd->textures[side_t::top].flags, side_t::part::NoGradient, key); break; @@ -1308,7 +1320,8 @@ public: break; case NAME_useowncolors_top: - Flag(sd->textures[side_t::top].flags, side_t::part::UseOwnSpecialColors, key); + if (Flag(sd->textures[side_t::top].flags, side_t::part::UseOwnSpecialColors, key)) + sd->Flags |= WALLF_EXTCOLOR; break; case NAME_uppercolor_top: @@ -1332,7 +1345,9 @@ public: break; case NAME_useowncolors_mid: - Flag(sd->textures[side_t::mid].flags, side_t::part::UseOwnSpecialColors, key); + if (Flag(sd->textures[side_t::mid].flags, side_t::part::UseOwnSpecialColors, key)) + sd->Flags |= WALLF_EXTCOLOR; + break; case NAME_uppercolor_mid: @@ -1356,7 +1371,8 @@ public: break; case NAME_useowncolors_bottom: - Flag(sd->textures[side_t::bottom].flags, side_t::part::UseOwnSpecialColors, key); + if (Flag(sd->textures[side_t::bottom].flags, side_t::part::UseOwnSpecialColors, key)) + sd->Flags |= WALLF_EXTCOLOR; break; case NAME_uppercolor_bottom: @@ -1380,13 +1396,17 @@ public: break; case NAME_useowncoloradd_top: - sd->textures[side_t::top].flags |= side_t::part::UseOwnAdditiveColor * CheckBool(key); + Flag(sd->textures[side_t::top].flags, side_t::part::UseOwnAdditiveColor, key); + sd->Flags |= WALLF_EXTCOLOR; case NAME_useowncoloradd_mid: - sd->textures[side_t::mid].flags |= side_t::part::UseOwnAdditiveColor * CheckBool(key); + if (Flag(sd->textures[side_t::mid].flags, side_t::part::UseOwnAdditiveColor, key)) + sd->Flags |= WALLF_EXTCOLOR; case NAME_useowncoloradd_bottom: - sd->textures[side_t::bottom].flags |= side_t::part::UseOwnAdditiveColor * CheckBool(key); + if (Flag(sd->textures[side_t::bottom].flags, side_t::part::UseOwnAdditiveColor, key)) + sd->Flags |= WALLF_EXTCOLOR; + break; default: break; @@ -1642,6 +1662,14 @@ public: sec->AdditiveColors[sector_t::sprites] = CheckInt(key) | 0xff000000; break; + case NAME_colorization_floor: + sec->SetTextureFx(sector_t::floor, TexMan.GetTextureManipulation(CheckString(key))); + break; + + case NAME_colorization_ceiling: + sec->SetTextureFx(sector_t::ceiling, TexMan.GetTextureManipulation(CheckString(key))); + break; + case NAME_Desaturation: desaturation = int(255*CheckFloat(key) + FLT_EPSILON); // FLT_EPSILON to avoid rounding errors with numbers slightly below a full integer. continue; @@ -2284,6 +2312,11 @@ public: // Create the real linedefs and decompress the sidedefs ProcessLineDefs(); + // enable the excolor flag on all sidedefs which need it for a gradient transfer from the sector. + for (auto& sec : Level->sectors) + { + sec.CheckExColorFlag(); + } } }; diff --git a/src/maploader/udmf.h b/src/maploader/udmf.h index 8e0901755..a6f402bf1 100644 --- a/src/maploader/udmf.h +++ b/src/maploader/udmf.h @@ -23,12 +23,18 @@ protected: const char *CheckString(const char *key); template - void Flag(T &value, int mask, const char *key) + bool Flag(T &value, int mask, const char *key) { if (CheckBool(key)) + { value |= mask; + return true; + } else + { value &= ~mask; + return false; + } } }; diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index 025ca18a4..add4ce024 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -89,6 +89,31 @@ FSerializer &Serialize(FSerializer &arc, const char *key, line_t &line, line_t * } +//========================================================================== +// +// +// +//========================================================================== + +FSerializer& Serialize(FSerializer& arc, const char* key, TextureManipulation& part, TextureManipulation *def) +{ + if (arc.canSkip() && def != nullptr && !memcmp(&part, def, sizeof(part))) + { + return arc; + } + + if (arc.BeginObject(key)) + { + arc("addcolor", part.AddColor, def->AddColor) + ("yoffset", part.ModulateColor, def->ModulateColor) + ("xscale", part.BlendColor, def->BlendColor) + ("yscale", part.DesaturationFactor, def->DesaturationFactor) + .EndObject(); + } + return arc; +} + + //========================================================================== // // @@ -114,6 +139,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, side_t::part &part, si ("color1", part.SpecialColors[0], def->SpecialColors[0]) ("color2", part.SpecialColors[1], def->SpecialColors[1]) ("addcolor", part.AdditiveColor, def->AdditiveColor) + ("texturefx", part.TextureFx, def->TextureFx) .EndObject(); } return arc; @@ -212,6 +238,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, sector_t::splane &p, s ("alpha", p.alpha, def->alpha) ("glowcolor", p.GlowColor, def->GlowColor) ("glowheight", p.GlowHeight, def->GlowHeight) + ("texturefx", p.TextureFx, def->TextureFx) .EndObject(); } return arc; diff --git a/src/playsim/actor.h b/src/playsim/actor.h index d2ca855c8..06e06b385 100644 --- a/src/playsim/actor.h +++ b/src/playsim/actor.h @@ -411,6 +411,7 @@ enum ActorFlag8 MF8_NOFRICTIONBOUNCE = 0x00000040, // don't bounce off walls when on icy floors MF8_RETARGETAFTERSLAM = 0x00000080, // Forces jumping to the idle state after slamming into something MF8_RECREATELIGHTS = 0x00000100, // Internal flag that signifies that the light attachments need to be recreated at the + MF8_STOPRAILS = 0x00000200, // [MC] Prevent rails from going further if an actor has this flag. }; // --- mobj.renderflags --- diff --git a/src/playsim/p_map.cpp b/src/playsim/p_map.cpp index 08525e6d6..00d47aa37 100644 --- a/src/playsim/p_map.cpp +++ b/src/playsim/p_map.cpp @@ -5089,12 +5089,6 @@ static ETraceStatus ProcessRailHit(FTraceResults &res, void *userdata) return TRACE_Stop; } - // Invulnerable things completely block the shot - if (data->StopAtInvul && res.Actor->flags2 & MF2_INVULNERABLE) - { - return TRACE_Stop; - } - // Skip actors if the puff has: // 1. THRUACTORS (This one did NOT include a check for spectral) // 2. MTHRUSPECIES on puff and the shooter has same species as the hit actor @@ -5109,6 +5103,12 @@ static ETraceStatus ProcessRailHit(FTraceResults &res, void *userdata) return TRACE_Skip; } + // Invulnerable things completely block the shot + if (data->StopAtInvul && res.Actor->flags2 & MF2_INVULNERABLE) + { + return TRACE_Stop; + } + // Save this thing for damaging later, and continue the trace SRailHit newhit; newhit.HitActor = res.Actor; @@ -5127,7 +5127,8 @@ static ETraceStatus ProcessRailHit(FTraceResults &res, void *userdata) { data->count++; } - return (data->StopAtOne || (data->limit && (data->count >= data->limit))) ? TRACE_Stop : TRACE_Continue; + return (data->StopAtOne || (data->limit && (data->count >= data->limit)) || (res.Actor->flags8 & MF8_STOPRAILS)) + ? TRACE_Stop : TRACE_Continue; } //========================================================================== diff --git a/src/r_data/r_translate.h b/src/r_data/r_translate.h index 8e704a5d3..0c52f256d 100644 --- a/src/r_data/r_translate.h +++ b/src/r_data/r_translate.h @@ -147,6 +147,77 @@ int CreateBloodTranslation(PalEntry color); int R_FindCustomTranslation(FName name); void R_ParseTrnslate(); +struct TextureManipulation +{ + enum + { + BlendNone = 0, + BlendAlpha = 1, + BlendScreen = 2, + BlendOverlay = 3, + BlendHardLight = 4, + BlendMask = 7, + InvertBit = 8, + ActiveBit = 16, // Must be set for the shader to do something + }; + PalEntry AddColor; // Alpha contains the blend flags + PalEntry ModulateColor; // Alpha may contain a multiplier to get higher values than 1.0 without promoting this to 4 full floats. + PalEntry BlendColor; + float DesaturationFactor; + + bool CheckIfEnabled() // check if this manipulation is doing something. NoOps do not need to be preserved, unless they override older setttings. + { + if (AddColor != 0 || // this includes a check for the blend mode without which BlendColor is not active + ModulateColor != 0x01ffffff || // 1 in alpha must be the default for a no-op. + DesaturationFactor != 0) + { + AddColor.a |= ActiveBit; // mark as active for the shader's benefit. + return true; + } + return false; + } + + void SetTextureModulateColor(int slot, PalEntry rgb) + { + rgb.a = ModulateColor.a; + ModulateColor = rgb; + } + + void SetTextureModulateScaleFactor(int slot, int fac) + { + ModulateColor.a = (uint8_t)fac; + } + + void SetTextureAdditiveColor(int slot, PalEntry rgb) + { + rgb.a = AddColor.a; + AddColor = rgb; + } + + void SetTextureBlendColor(int slot, PalEntry rgb) + { + BlendColor = rgb; + } + + void SetTextureDesaturationFactor(int slot, double fac) + { + DesaturationFactor = (float)fac; + } + + void SetTextureBlendMode(int slot, int mode) + { + AddColor.a = (AddColor.a & ~TextureManipulation::BlendMask) | (mode & TextureManipulation::BlendMask); + } + + void SetTextureInvert(bool on) + { + AddColor.a |= TextureManipulation::InvertBit; + AddColor.a &= ~TextureManipulation::InvertBit; + } + +}; + + #endif // __R_TRANSLATE_H diff --git a/src/rendering/hwrenderer/scene/hw_renderstate.h b/src/rendering/hwrenderer/scene/hw_renderstate.h index d725d820d..42092b2e1 100644 --- a/src/rendering/hwrenderer/scene/hw_renderstate.h +++ b/src/rendering/hwrenderer/scene/hw_renderstate.h @@ -157,7 +157,7 @@ struct FVector4PalEntry r = newvalue.r * normScale; g = newvalue.g * normScale; b = newvalue.b * normScale; - a = newvalue.a; + a = 1; return *this; } diff --git a/src/rendering/hwrenderer/scene/hw_walls.cpp b/src/rendering/hwrenderer/scene/hw_walls.cpp index 9b98bc28a..1873ce5d3 100644 --- a/src/rendering/hwrenderer/scene/hw_walls.cpp +++ b/src/rendering/hwrenderer/scene/hw_walls.cpp @@ -168,38 +168,42 @@ void HWWall::RenderTexturedWall(HWDrawInfo *di, FRenderState &state, int rflags) if (type != RENDERWALL_COLOR && seg->sidedef != nullptr) { auto side = seg->sidedef; - auto tierndx = renderwalltotier[type]; - auto &tier = side->textures[tierndx]; - PalEntry color1 = side->GetSpecialColor(tierndx, side_t::walltop, frontsector); - PalEntry color2 = side->GetSpecialColor(tierndx, side_t::wallbottom, frontsector); - state.SetObjectColor(color1); - state.SetObjectColor2((color1 != color2) ? color2 : PalEntry(0)); - state.SetAddColor(side->GetAdditiveColor(tierndx, frontsector)); - state.ApplyTextureManipulation(&side->textures[tierndx].TextureFx); - - if (color1 != color2) + if (seg->sidedef->Flags & WALLF_EXTCOLOR) // this block incurs a costly cache miss, so only process if needed. { - // Do gradient setup only if there actually is a gradient. - state.EnableGradient(true); - if ((tier.flags & side_t::part::ClampGradient) && backsector) + auto tierndx = renderwalltotier[type]; + auto& tier = side->textures[tierndx]; + PalEntry color1 = side->GetSpecialColor(tierndx, side_t::walltop, frontsector); + PalEntry color2 = side->GetSpecialColor(tierndx, side_t::wallbottom, frontsector); + state.SetObjectColor(color1); + state.SetObjectColor2((color1 != color2) ? color2 : PalEntry(0)); + state.SetAddColor(side->GetAdditiveColor(tierndx, frontsector)); + state.ApplyTextureManipulation(&tier.TextureFx); + + if (color1 != color2) { - if (tierndx == side_t::top) + // Do gradient setup only if there actually is a gradient. + + state.EnableGradient(true); + if ((tier.flags & side_t::part::ClampGradient) && backsector) { - state.SetGradientPlanes(frontsector->ceilingplane, backsector->ceilingplane); + if (tierndx == side_t::top) + { + state.SetGradientPlanes(frontsector->ceilingplane, backsector->ceilingplane); + } + else if (tierndx == side_t::mid) + { + state.SetGradientPlanes(backsector->ceilingplane, backsector->floorplane); + } + else // side_t::bottom: + { + state.SetGradientPlanes(backsector->floorplane, frontsector->floorplane); + } } - else if (tierndx == side_t::mid) + else { - state.SetGradientPlanes(backsector->ceilingplane, backsector->floorplane); + state.SetGradientPlanes(frontsector->ceilingplane, frontsector->floorplane); } - else // side_t::bottom: - { - state.SetGradientPlanes(backsector->floorplane, frontsector->floorplane); - } - } - else - { - state.SetGradientPlanes(frontsector->ceilingplane, frontsector->floorplane); } } } diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 43982bc25..c308b00e3 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -55,6 +55,7 @@ #include "wi_stuff.h" #include "a_dynlight.h" #include "types.h" +#include "utility/dictionary.h" static TArray properties; static TArray AFTable; @@ -322,6 +323,7 @@ static FFlagDef ActorFlagDefs[]= DEFINE_FLAG(MF8, NOFRICTION, AActor, flags8), DEFINE_FLAG(MF8, NOFRICTIONBOUNCE, AActor, flags8), DEFINE_FLAG(MF8, RETARGETAFTERSLAM, AActor, flags8), + DEFINE_FLAG(MF8, STOPRAILS, AActor, flags8), // Effect flags DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects), @@ -841,6 +843,21 @@ void InitThingdef() wbplayerstruct->Size = sizeof(wbplayerstruct_t); wbplayerstruct->Align = alignof(wbplayerstruct_t); + auto dictionarystruct = NewStruct("Dictionary", nullptr, true); + dictionarystruct->Size = sizeof(Dictionary); + dictionarystruct->Align = alignof(Dictionary); + NewPointer(dictionarystruct, false)->InstallHandlers( + [](FSerializer &ar, const char *key, const void *addr) + { + ar(key, *(Dictionary **)addr); + }, + [](FSerializer &ar, const char *key, void *addr) + { + Serialize(ar, key, *(Dictionary **)addr, nullptr); + return true; + } + ); + FAutoSegIterator probe(CRegHead, CRegTail); while (*++probe != NULL) diff --git a/src/scripting/vmthunks.cpp b/src/scripting/vmthunks.cpp index 4f0d2fb32..ea4d9530b 100644 --- a/src/scripting/vmthunks.cpp +++ b/src/scripting/vmthunks.cpp @@ -652,6 +652,24 @@ DEFINE_ACTION_FUNCTION_NATIVE(_Sector, SetAdditiveColor, SetAdditiveColor) return 0; } +static void SetColorization(sector_t* self, int pos, int cname) +{ + if (pos >= 0 && pos < 2) + { + self->SetTextureFx(pos, TexMan.GetTextureManipulation(ENamedName(cname))); + } +} + +DEFINE_ACTION_FUNCTION_NATIVE(_Sector, SetColorization, SetColorization) +{ + PARAM_SELF_STRUCT_PROLOGUE(sector_t); + PARAM_INT(pos); + PARAM_INT(color); + SetColorization(self, pos, color); + return 0; +} + + static void SetFogDensity(sector_t *self, int dens) { self->Colormap.FogDensity = dens; @@ -1749,6 +1767,25 @@ DEFINE_ACTION_FUNCTION_NATIVE(_Sector, SetXOffset, SetXOffset) return 0; } + static void SetWallColorization(side_t* self, int pos, int cname) + { + if (pos >= 0 && pos < 2) + { + self->SetTextureFx(pos, TexMan.GetTextureManipulation(ENamedName(cname))); + } + } + + DEFINE_ACTION_FUNCTION_NATIVE(_Side, SetColorization, SetWallColorization) + { + PARAM_SELF_STRUCT_PROLOGUE(side_t); + PARAM_INT(pos); + PARAM_INT(color); + SetWallColorization(self, pos, color); + return 0; + } + + + static int SideIndex(side_t *self) { return self->Index(); diff --git a/src/serializer.cpp b/src/serializer.cpp index 57ce752cb..490a3bef9 100644 --- a/src/serializer.cpp +++ b/src/serializer.cpp @@ -2156,6 +2156,81 @@ template<> FSerializer &Serialize(FSerializer &arc, const char *key, FFont *&fon } +//========================================================================== +// +// Dictionary +// +//========================================================================== + +FString DictionaryToString(const Dictionary &dict) +{ + Dictionary::ConstPair *pair; + Dictionary::ConstIterator i { dict }; + + rapidjson::StringBuffer buffer; + rapidjson::Writer writer(buffer); + writer.StartObject(); + + while (i.NextPair(pair)) + { + writer.Key(pair->Key); + writer.String(pair->Value); + } + + writer.EndObject(); + + FString contents { buffer.GetString(), buffer.GetSize() }; + return contents; +} + +Dictionary *DictionaryFromString(const FString &string) +{ + if (string.IsEmpty()) + { + return nullptr; + } + + Dictionary *const dict = new Dictionary; + + rapidjson::Document doc; + doc.Parse(string.GetChars(), string.Len()); + + if (doc.GetType() != rapidjson::Type::kObjectType) + { + I_Error("Dictionary is expected to be an object."); + return dict; + } + + for (auto i = doc.MemberBegin(); i != doc.MemberEnd(); ++i) + { + if (i->value.GetType() != rapidjson::Type::kStringType) + { + I_Error("Dictionary value is expected to be a string."); + return dict; + } + + dict->Insert(i->name.GetString(), i->value.GetString()); + } + + return dict; +} + +template<> FSerializer &Serialize(FSerializer &arc, const char *key, Dictionary *&dict, Dictionary **) +{ + if (arc.isWriting()) + { + FString contents { dict ? DictionaryToString(*dict) : "" }; + return arc(key, contents); + } + else + { + FString contents; + arc(key, contents); + dict = DictionaryFromString(contents); + return arc; + } +} + //========================================================================== // // Handler to retrieve a numeric value of any kind. diff --git a/src/serializer.h b/src/serializer.h index 46f6dfbb2..71f8f76e1 100644 --- a/src/serializer.h +++ b/src/serializer.h @@ -7,6 +7,7 @@ #include "r_defs.h" #include "resourcefiles/file_zip.h" #include "tflags.h" +#include "utility/dictionary.h" extern bool save_full; @@ -270,6 +271,7 @@ template<> FSerializer &Serialize(FSerializer &arc, const char *key, FDoorAnimat template<> FSerializer &Serialize(FSerializer &arc, const char *key, char *&pstr, char **def); template<> FSerializer &Serialize(FSerializer &arc, const char *key, FFont *&font, FFont **def); template<> FSerializer &Serialize(FSerializer &arc, const char *key, FLevelLocals *&font, FLevelLocals **def); +template<> FSerializer &Serialize(FSerializer &arc, const char *key, Dictionary *&dict, Dictionary **def); FSerializer &Serialize(FSerializer &arc, const char *key, FState *&state, FState **def, bool *retcode); template<> inline FSerializer &Serialize(FSerializer &arc, const char *key, FState *&state, FState **def) @@ -311,5 +313,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, TFlags &flags, return Serialize(arc, key, flags.Value, def? &def->Value : nullptr); } +FString DictionaryToString(const Dictionary &dict); +Dictionary *DictionaryFromString(const FString &string); #endif diff --git a/src/sound/backend/i_soundinternal.h b/src/sound/backend/i_soundinternal.h index 08dd311a2..823f672b7 100644 --- a/src/sound/backend/i_soundinternal.h +++ b/src/sound/backend/i_soundinternal.h @@ -20,8 +20,6 @@ enum EChanFlag CHANF_AREA = 128, // Sound plays from all around. Only valid with sector sounds. CHANF_LOOP = 256, - CHANF_PICKUP = CHANF_MAYBE_LOCAL, - CHANF_NONE = 0, CHANF_IS3D = 1, // internal: Sound is 3D. CHANF_EVICTED = 2, // internal: Sound was evicted. diff --git a/src/sound/s_doomsound.cpp b/src/sound/s_doomsound.cpp index d2f551597..12ec59cf1 100644 --- a/src/sound/s_doomsound.cpp +++ b/src/sound/s_doomsound.cpp @@ -470,14 +470,14 @@ void A_StartSound(AActor *self, int soundid, int channel, int flags, double volu { if (!looping) { - if (!(flags & CHANF_NOSTOP) || !S_IsActorPlayingSomething(self, channel & 7, soundid)) + if (!(flags & CHANF_NOSTOP) || !S_IsActorPlayingSomething(self, channel, soundid)) { S_PlaySoundPitch(self, channel, EChanFlags::FromInt(flags), soundid, (float)volume, (float)attenuation, local, (float)pitch); } } else { - if (!S_IsActorPlayingSomething(self, channel & 7, soundid)) + if (!S_IsActorPlayingSomething(self, channel, soundid)) { S_PlaySoundPitch(self, channel, EChanFlags::FromInt(flags) | CHANF_LOOP, soundid, (float)volume, (float)attenuation, local, (float)pitch); } diff --git a/src/sound/s_sound.cpp b/src/sound/s_sound.cpp index d07b744d2..5e6c16095 100644 --- a/src/sound/s_sound.cpp +++ b/src/sound/s_sound.cpp @@ -542,7 +542,6 @@ FSoundChan *SoundEngine::StartSound(int type, const void *source, if (foundit) { StopChannel(chan); - break; } } } @@ -1055,7 +1054,6 @@ void SoundEngine::ChangeSoundVolume(int sourcetype, const void *source, int chan { GSnd->ChannelVolume(chan, volume); chan->Volume = volume; - return; } } return; @@ -1086,7 +1084,6 @@ void SoundEngine::ChangeSoundPitch(int sourcetype, const void *source, int chann (sound_id == -1? (chan->EntChannel == channel) : (chan->OrgID == sound_id))) { SetPitch(chan, (float)pitch); - return; } } return; diff --git a/src/sound/s_soundinternal.h b/src/sound/s_soundinternal.h index 2865e766b..09cffbcf9 100644 --- a/src/sound/s_soundinternal.h +++ b/src/sound/s_soundinternal.h @@ -192,7 +192,6 @@ struct FSoundChan : public FISoundChannel // CHAN_VOICE is for oof, sight, or other voice sounds // CHAN_ITEM is for small things and item pickup // CHAN_BODY is for generic body sounds -// CHAN_PICKUP can optionally be set as a local sound only for "compatibility" enum EChannel { diff --git a/src/utility/dictionary.cpp b/src/utility/dictionary.cpp new file mode 100644 index 000000000..e951439ec --- /dev/null +++ b/src/utility/dictionary.cpp @@ -0,0 +1,83 @@ +#include "utility/dictionary.h" + +#include "scripting/vm/vm.h" +#include "serializer.h" + +//===================================================================================== +// +// Dictionary exports +// +//===================================================================================== + +DEFINE_ACTION_FUNCTION(_Dictionary, Create) +{ + PARAM_PROLOGUE; + ACTION_RETURN_POINTER(new Dictionary); +} + +static void DictInsert(Dictionary *dict, const FString &key, const FString &value) +{ + dict->Insert(key, value); +} + +DEFINE_ACTION_FUNCTION_NATIVE(_Dictionary, Insert, DictInsert) +{ + PARAM_SELF_STRUCT_PROLOGUE(Dictionary); + PARAM_STRING(key); + PARAM_STRING(value); + DictInsert(self, key, value); + return 0; +} + +static void DictAt(const Dictionary *dict, const FString &key, FString *result) +{ + const FString *value = dict->CheckKey(key); + *result = value ? *value : ""; +} + +DEFINE_ACTION_FUNCTION_NATIVE(_Dictionary, At, DictAt) +{ + PARAM_SELF_STRUCT_PROLOGUE(Dictionary); + PARAM_STRING(key); + FString result; + DictAt(self, key, &result); + ACTION_RETURN_STRING(result); +} + +static void DictToString(const Dictionary *dict, FString *result) +{ + *result = DictionaryToString(*dict); +} + +DEFINE_ACTION_FUNCTION_NATIVE(_Dictionary, ToString, DictToString) +{ + PARAM_SELF_STRUCT_PROLOGUE(Dictionary); + FString result; + DictToString(self, &result); + ACTION_RETURN_STRING(result); +} + +static Dictionary *DictFromString(const FString& string) +{ + return DictionaryFromString(string); +} + +DEFINE_ACTION_FUNCTION_NATIVE(_Dictionary, FromString, DictFromString) +{ + PARAM_PROLOGUE; + PARAM_STRING(string); + ACTION_RETURN_POINTER(DictFromString(string)); +} + +static void DictRemove(Dictionary *dict, const FString &key) +{ + dict->Remove(key); +} + +DEFINE_ACTION_FUNCTION_NATIVE(_Dictionary, Remove, DictRemove) +{ + PARAM_SELF_STRUCT_PROLOGUE(Dictionary); + PARAM_STRING(key); + DictRemove(self, key); + return 0; +} diff --git a/src/utility/dictionary.h b/src/utility/dictionary.h new file mode 100644 index 000000000..460716c91 --- /dev/null +++ b/src/utility/dictionary.h @@ -0,0 +1,6 @@ +#pragma once + +#include "tarray.h" +#include "zstring.h" + +using Dictionary = TMap; diff --git a/src/utility/namedef.h b/src/utility/namedef.h index e2063f8a7..c0d5f82d3 100644 --- a/src/utility/namedef.h +++ b/src/utility/namedef.h @@ -671,6 +671,11 @@ xx(useowncoloradd_mid) xx(coloradd_mid) xx(useowncoloradd_bottom) xx(coloradd_bottom) +xx(colorization_top) +xx(colorization_mid) +xx(colorization_bottom) +xx(colorization_floor) +xx(colorization_ceiling) xx(Renderstyle) diff --git a/src/utility/sc_man.cpp b/src/utility/sc_man.cpp index 986d41d7a..3901a1f44 100644 --- a/src/utility/sc_man.cpp +++ b/src/utility/sc_man.cpp @@ -31,29 +31,6 @@ ** */ -// This file contains some code by Raven Software, licensed under: - -//----------------------------------------------------------------------------- -// -// Copyright 1994-1996 Raven Software -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see http://www.gnu.org/licenses/ -// -//----------------------------------------------------------------------------- -// - - // HEADER FILES ------------------------------------------------------------ @@ -622,12 +599,14 @@ bool FScanner::GetToken () String[StringLen - 2] == 'u' || String[StringLen - 2] == 'U') { TokenType = TK_UIntConst; - Number = (int)strtoull(String, &stopper, 0); + BigNumber = (int64_t)strtoull(String, &stopper, 0); + Number = (int)clamp(BigNumber, 0, UINT_MAX); Float = (unsigned)Number; } else { - Number = (int)strtoll(String, &stopper, 0); + BigNumber = strtoll(String, &stopper, 0); + Number = (int)clamp(BigNumber, INT_MIN, INT_MAX); Float = Number; } } @@ -728,7 +707,8 @@ bool FScanner::GetNumber () } else { - Number = (int)strtoll (String, &stopper, 0); + BigNumber = strtoll(String, &stopper, 0); + Number = (int)clamp(BigNumber, INT_MIN, INT_MAX); if (*stopper != 0) { ScriptError ("SC_GetNumber: Bad numeric constant \"%s\".", String); @@ -779,11 +759,13 @@ bool FScanner::CheckNumber () } else if (strcmp (String, "MAXINT") == 0) { + BigNumber = INT64_MAX; Number = INT_MAX; } else { - Number = (int)strtoll (String, &stopper, 0); + BigNumber = strtoll (String, &stopper, 0); + Number = (int)clamp(BigNumber, INT_MIN, INT_MAX); if (*stopper != 0) { UnGet(); diff --git a/src/utility/sc_man.h b/src/utility/sc_man.h index b345ee15b..908089b8e 100644 --- a/src/utility/sc_man.h +++ b/src/utility/sc_man.h @@ -87,6 +87,7 @@ public: int StringLen; int TokenType; int Number; + int64_t BigNumber; double Float; int Line; bool End; diff --git a/src/win32/zdoom.rc b/src/win32/zdoom.rc index c4e3340ea..f22b2573c 100644 --- a/src/win32/zdoom.rc +++ b/src/win32/zdoom.rc @@ -228,149 +228,6 @@ BEGIN CONTROL "SoftPoly",IDC_WELCOME_VULKAN3,"Button",BS_AUTORADIOBUTTON,13,188,43,10 END -IDD_EAXPROPERTYLIST DIALOGEX 0, 0, 265, 404 -STYLE DS_SETFONT | DS_3DLOOK | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_VSCROLL -EXSTYLE WS_EX_CLIENTEDGE -FONT 8, "MS Shell Dlg", 400, 0, 0x1 -BEGIN - EDITTEXT IDCE_ENVIRONMENTSIZE,76,7,48,12,ES_AUTOHSCROLL,WS_EX_RIGHT - EDITTEXT IDCE_ENVIRONMENTDIFFUSION,76,20,48,12,ES_AUTOHSCROLL,WS_EX_RIGHT - EDITTEXT IDCE_ROOM,76,33,48,12,ES_AUTOHSCROLL,WS_EX_RIGHT - EDITTEXT IDCE_ROOMHF,76,46,48,12,ES_AUTOHSCROLL,WS_EX_RIGHT - EDITTEXT IDCE_ROOMLF,76,59,48,12,ES_AUTOHSCROLL,WS_EX_RIGHT - EDITTEXT IDCE_DECAYTIME,76,72,48,12,ES_AUTOHSCROLL,WS_EX_RIGHT - EDITTEXT IDCE_DECAYHFRATIO,76,85,48,12,ES_AUTOHSCROLL,WS_EX_RIGHT - EDITTEXT IDCE_DECAYLFRATIO,76,98,48,12,ES_AUTOHSCROLL,WS_EX_RIGHT - EDITTEXT IDCE_REFLECTIONS,76,111,48,12,ES_AUTOHSCROLL,WS_EX_RIGHT - EDITTEXT IDCE_REFLECTIONSDELAY,76,124,48,12,ES_AUTOHSCROLL,WS_EX_RIGHT - EDITTEXT IDCE_REVERB,76,137,48,12,ES_AUTOHSCROLL,WS_EX_RIGHT - EDITTEXT IDCE_REVERBDELAY,76,150,48,12,ES_AUTOHSCROLL,WS_EX_RIGHT - EDITTEXT IDCE_ECHOTIME,76,163,48,12,ES_AUTOHSCROLL,WS_EX_RIGHT - EDITTEXT IDCE_ECHODEPTH,76,176,48,12,ES_AUTOHSCROLL,WS_EX_RIGHT - EDITTEXT IDCE_MODULATIONTIME,76,189,48,12,ES_AUTOHSCROLL,WS_EX_RIGHT - EDITTEXT IDCE_MODULATIONDEPTH,76,202,48,12,ES_AUTOHSCROLL,WS_EX_RIGHT - EDITTEXT IDCE_AIRABSORPTIONHF,76,215,48,12,ES_AUTOHSCROLL,WS_EX_RIGHT - EDITTEXT IDCE_HFREFERENCE,76,228,48,12,ES_AUTOHSCROLL,WS_EX_RIGHT - EDITTEXT IDCE_LFREFERENCE,76,241,48,12,ES_AUTOHSCROLL,WS_EX_RIGHT - EDITTEXT IDCE_ROOMROLLOFFFACTOR,76,254,48,12,ES_AUTOHSCROLL,WS_EX_RIGHT - EDITTEXT IDCE_REFLECTIONSPANX,76,267,48,12,ES_AUTOHSCROLL,WS_EX_RIGHT - EDITTEXT IDCE_REFLECTIONSPANY,76,280,48,12,ES_AUTOHSCROLL,WS_EX_RIGHT - EDITTEXT IDCE_REFLECTIONSPANZ,76,293,48,12,ES_AUTOHSCROLL,WS_EX_RIGHT - EDITTEXT IDCE_REVERBPANX,76,306,48,12,ES_AUTOHSCROLL,WS_EX_RIGHT - EDITTEXT IDCE_REVERBPANY,76,319,48,12,ES_AUTOHSCROLL,WS_EX_RIGHT - EDITTEXT IDCE_REVERBPANZ,76,332,48,12,ES_AUTOHSCROLL,WS_EX_RIGHT - CONTROL "",IDCS_ENVIRONMENTSIZE,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,126,7,123,12 - CONTROL "",IDCS_ENVIRONMENTDIFFUSION,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,126,20,123,12 - CONTROL "",IDCS_ROOM,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,126,33,123,12 - CONTROL "",IDCS_ROOMHF,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,126,46,123,12 - CONTROL "",IDCS_ROOMLF,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,126,59,123,12 - CONTROL "",IDCS_DECAYTIME,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,126,72,123,12 - CONTROL "",IDCS_DECAYHFRATIO,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,126,85,123,12 - CONTROL "",IDCS_DECAYLFRATIO,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,126,98,123,12 - CONTROL "",IDCS_REFLECTIONS,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,126,111,123,12 - CONTROL "",IDCS_REFLECTIONSDELAY,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,126,124,123,12 - CONTROL "",IDCS_REVERB,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,126,137,123,12 - CONTROL "",IDCS_REVERBDELAY,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,126,150,123,12 - CONTROL "",IDCS_ECHOTIME,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,126,163,123,12 - CONTROL "",IDCS_ECHODEPTH,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,126,176,123,12 - CONTROL "",IDCS_MODULATIONTIME,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,126,189,123,12 - CONTROL "",IDCS_MODULATIONDEPTH,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,126,202,123,12 - CONTROL "",IDCS_AIRABSORPTIONHF,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,126,215,123,12 - CONTROL "",IDCS_HFREFERENCE,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,126,228,123,12 - CONTROL "",IDCS_LFREFERENCE,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,126,241,123,12 - CONTROL "",IDCS_ROOMROLLOFFFACTOR,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,126,254,123,12 - CONTROL "",IDCS_REFLECTIONSPANX,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,126,267,123,12 - CONTROL "",IDCS_REFLECTIONSPANY,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,126,280,123,12 - CONTROL "",IDCS_REFLECTIONSPANZ,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,126,293,123,12 - CONTROL "",IDCS_REVERBPANX,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,126,306,123,12 - CONTROL "",IDCS_REVERBPANY,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,126,319,123,12 - CONTROL "",IDCS_REVERBPANZ,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,126,332,123,12 - CONTROL "Reflections Scale",IDC_REFLECTIONSSCALE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,19,353,70,10 - CONTROL "Reflections Delay Scale",IDC_REFLECTIONSDELAYSCALE, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,19,366,90,10 - CONTROL "Decay Time Scale",IDC_DECAYTIMESCALE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,19,377,71,10 - CONTROL "Decay HF Limit",IDC_DECAYHFLIMIT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,19,390,63,10 - CONTROL "Reverb Scale",IDC_REVERBSCALE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,139,353,58,10 - CONTROL "Reverb Delay Scale",IDC_REVERBDELAYSCALE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,139,366,78,10 - CONTROL "Echo Time Scale",IDC_ECHOTIMESCALE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,139,377,67,10 - CONTROL "Modulation Time Scale",IDC_MODULATIONTIMESCALE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,139,390,86,10 - LTEXT "Environment Size",IDC_STATIC,17,9,56,8,0,WS_EX_RIGHT - LTEXT "Environment Diffusion",IDC_STATIC,2,22,71,8,0,WS_EX_RIGHT - LTEXT "Room",IDC_STATIC,53,35,19,8,0,WS_EX_RIGHT - LTEXT "Room HF",IDC_STATIC,43,48,30,8,0,WS_EX_RIGHT - LTEXT "Room LF",IDC_STATIC,45,60,28,8,0,WS_EX_RIGHT - LTEXT "Decay Time",IDC_STATIC,35,74,38,8,0,WS_EX_RIGHT - LTEXT "Decay HF Ratio",IDC_STATIC,23,87,50,8,0,WS_EX_RIGHT - LTEXT "Decay LF Ratio",IDC_STATIC,24,100,49,8,0,WS_EX_RIGHT - LTEXT "Reflections",IDC_STATIC,37,113,36,8,0,WS_EX_RIGHT - LTEXT "Reflections Delay",IDC_STATIC,17,126,56,8,0,WS_EX_RIGHT - LTEXT "Reflections Pan X",IDC_STATIC,17,267,56,8,0,WS_EX_RIGHT - LTEXT "Reflections Pan Y",IDC_STATIC,17,280,56,8,0,WS_EX_RIGHT - LTEXT "Reflections Pan Z",IDC_STATIC,17,293,56,8,0,WS_EX_RIGHT - LTEXT "Reverb",IDC_STATIC,49,137,24,8,0,WS_EX_RIGHT - LTEXT "Reverb Delay",IDC_STATIC,29,150,44,8,0,WS_EX_RIGHT - LTEXT "Reverb Pan X",IDC_STATIC,29,306,44,8,0,WS_EX_RIGHT - LTEXT "Reverb Pan Y",IDC_STATIC,29,319,44,8,0,WS_EX_RIGHT - LTEXT "Reverb Pan Z",IDC_STATIC,29,332,44,8,0,WS_EX_RIGHT - LTEXT "Echo Time",IDC_STATIC,40,163,33,8,0,WS_EX_RIGHT - LTEXT "Echo Depth",IDC_STATIC,35,176,38,8,0,WS_EX_RIGHT - LTEXT "Modulation Time",IDC_STATIC,21,189,52,8,0,WS_EX_RIGHT - LTEXT "Modulation Depth",IDC_STATIC,16,202,57,8,0,WS_EX_RIGHT - LTEXT "Air Absorption HF",IDC_STATIC,16,215,57,8,0,WS_EX_RIGHT - LTEXT "HF Reference",IDC_STATIC,28,228,45,8,0,WS_EX_RIGHT - LTEXT "LF Reference",IDC_STATIC,29,241,44,8,0,WS_EX_RIGHT - LTEXT "Room Rolloff Factor",IDC_STATIC,9,254,64,8,0,WS_EX_RIGHT -END - -IDD_EAXEDIT DIALOGEX 0, 0, 280, 326 -STYLE DS_SETFONT | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME -EXSTYLE WS_EX_TOOLWINDOW | WS_EX_WINDOWEDGE -CAPTION "Environment Editor" -FONT 8, "MS Shell Dlg", 400, 0, 0x1 -BEGIN - COMBOBOX IDC_CURRENTENVIRONMENT,7,19,265,14,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP - LTEXT "Static",IDC_DUMMY,7,36,265,263,0,WS_EX_CLIENTEDGE - PUSHBUTTON "&New...",IDC_NEW,8,305,45,14 - PUSHBUTTON "&Save...",IDC_SAVE,60,305,45,14 - PUSHBUTTON "&Revert",IDC_REVERT,112,305,45,14 - CONTROL "&Test in level",IDC_TESTEAX,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,165,307,54,10 - PUSHBUTTON "&Done",IDOK,228,305,45,14 - CONTROL "Show &IDs in List",IDC_SHOWIDS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,7,66,10 - LTEXT "ID 2:",IDC_STATIC,239,7,19,8 - LTEXT "ID 1:",IDC_STATIC,198,7,19,8 - LTEXT "255",IDC_ID2,258,7,15,8 - LTEXT "255",IDC_ID1,218,7,15,8 -END - -IDD_NEWEAX DIALOGEX 0, 0, 348, 257 -STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTERMOUSE | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU -CAPTION "Create New Environment..." -FONT 8, "MS Shell Dlg", 400, 0, 0x1 -BEGIN - EDITTEXT IDC_NEWENVNAME,32,216,187,12,ES_AUTOHSCROLL - EDITTEXT IDC_EDITID1,248,216,32,12,ES_AUTOHSCROLL | ES_NUMBER - CONTROL "",IDC_SPINID1,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,236,216,11,14 - EDITTEXT IDC_EDITID2,309,216,32,12,ES_AUTOHSCROLL | ES_NUMBER - CONTROL "",IDC_SPINID2,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,297,216,11,14 - CONTROL "",IDC_ENVIRONMENTLIST,"SysListView32",LVS_LIST | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_SORTASCENDING | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,7,18,334,192 - DEFPUSHBUTTON "Create",IDOK,246,236,45,14 - PUSHBUTTON "Cancel",IDCANCEL,296,236,45,14 - LTEXT "Name:",IDC_STATIC,7,218,22,8 - LTEXT "ID 1:",IDC_STATIC,226,218,17,8 - LTEXT "ID 2:",IDC_STATIC,287,218,17,8 - LTEXT "Based on:",IDC_STATIC,7,7,33,8 -END - -IDD_SAVEEAX DIALOGEX 0, 0, 394, 95 -STYLE DS_SETFONT | DS_3DLOOK | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_SYSMENU -EXSTYLE WS_EX_TRANSPARENT -FONT 8, "MS Shell Dlg", 400, 0, 0x1 -BEGIN - GROUPBOX "Include these environments:",IDC_SAVEGROUP,6,0,371,90,0,WS_EX_TRANSPARENT - CONTROL "",IDC_ENVLIST,"SysListView32",LVS_LIST | LVS_SHOWSELALWAYS | LVS_SORTASCENDING | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,12,12,303,72 - PUSHBUTTON "Select All",IDC_SELECTALL,320,12,50,14 - PUSHBUTTON "Select None",IDC_SELECTNONE,320,31,50,14 -END IDD_CRASHDIALOG DIALOGEX 0, 0, 415, 308 STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 7981d9032..921c9beb8 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -8,6 +8,7 @@ version "4.2" #include "zscript/destructible.zs" #include "zscript/level_postprocessor.zs" #include "zscript/level_compatibility.zs" +#include "zscript/dictionary.zs" #include "zscript/actors/actor.zs" #include "zscript/actors/checks.zs" diff --git a/wadsrc/static/zscript/actors/hexen/magelightning.zs b/wadsrc/static/zscript/actors/hexen/magelightning.zs index 5ece4fd80..f68defe9d 100644 --- a/wadsrc/static/zscript/actors/hexen/magelightning.zs +++ b/wadsrc/static/zscript/actors/hexen/magelightning.zs @@ -124,7 +124,7 @@ class Lightning : Actor if ((!thing.player && !thing.bBoss) || !(Level.maptime & 1)) { thing.DamageMobj(self, target, 3, 'Electric'); - A_PlaySound(AttackSound, CHAN_WEAPON|CHAN_NOSTOP, 1, false); + A_StartSound(AttackSound, CHAN_WEAPON, CHANF_NOSTOP, 1, false); if (thing.bIsMonster && random[LightningHit]() < 64) { thing.Howl (); diff --git a/wadsrc/static/zscript/actors/inventory/inventory.zs b/wadsrc/static/zscript/actors/inventory/inventory.zs index 98db7e9aa..ca6d48de2 100644 --- a/wadsrc/static/zscript/actors/inventory/inventory.zs +++ b/wadsrc/static/zscript/actors/inventory/inventory.zs @@ -1046,6 +1046,7 @@ class Inventory : Actor { double atten; int chan; + int flags = 0; if (bNoAttenPickupSound) { @@ -1065,13 +1066,15 @@ class Inventory : Actor if (toucher != NULL && toucher.CheckLocalView()) { - chan = CHAN_PICKUP|CHAN_NOPAUSE; + chan = CHAN_ITEM; + flags = CHANF_NOPAUSE | CHANF_MAYBE_LOCAL; } else { - chan = CHAN_PICKUP; + chan = CHAN_ITEM; + flags = CHANF_MAYBE_LOCAL; } - toucher.A_PlaySound(PickupSound, chan, 1, false, atten); + toucher.A_StartSound(PickupSound, chan, flags, 1, false, atten); } //=========================================================================== diff --git a/wadsrc/static/zscript/actors/inventory_util.zs b/wadsrc/static/zscript/actors/inventory_util.zs index d64625109..6b65b6420 100644 --- a/wadsrc/static/zscript/actors/inventory_util.zs +++ b/wadsrc/static/zscript/actors/inventory_util.zs @@ -504,6 +504,10 @@ extend class Actor { return false; } + if (receiver == NULL) + { + return false; + } if (!orresult) { receiver = receiver.GetPointer(setreceiver); diff --git a/wadsrc/static/zscript/constants.zs b/wadsrc/static/zscript/constants.zs index 7e7f0722f..8c91efb09 100644 --- a/wadsrc/static/zscript/constants.zs +++ b/wadsrc/static/zscript/constants.zs @@ -418,10 +418,19 @@ enum ESoundFlags CHAN_UI = 32, CHAN_NOPAUSE = 64, CHAN_LOOP = 256, - CHAN_PICKUP = (CHAN_ITEM|CHAN_MAYBE_LOCAL), + CHAN_PICKUP = (CHAN_ITEM|CHAN_MAYBE_LOCAL), // Do not use this with A_StartSound! It would not do what is expected. CHAN_NOSTOP = 4096, CHAN_OVERLAP = 8192, + // Same as above, with an F appended to allow better distinction of channel and channel flags. + CHANF_LISTENERZ = 8, + CHANF_MAYBE_LOCAL = 16, + CHANF_UI = 32, + CHANF_NOPAUSE = 64, + CHANF_LOOP = 256, + CHANF_NOSTOP = 4096, + CHANF_OVERLAP = 8192, + }; // sound attenuation values diff --git a/wadsrc/static/zscript/dictionary.zs b/wadsrc/static/zscript/dictionary.zs new file mode 100644 index 000000000..f802a2fae --- /dev/null +++ b/wadsrc/static/zscript/dictionary.zs @@ -0,0 +1,11 @@ +struct Dictionary native +{ + native static Dictionary Create(); + native static Dictionary FromString(String s); + + native void Insert(String key, String value); + native void Remove(String key); + native String At(String key) const; + + native String ToString() const; +} diff --git a/wadsrc/static/zscript/mapdata.zs b/wadsrc/static/zscript/mapdata.zs index a2298629f..f7e07d211 100644 --- a/wadsrc/static/zscript/mapdata.zs +++ b/wadsrc/static/zscript/mapdata.zs @@ -67,7 +67,7 @@ struct Side native play //DBaseDecal* AttachedDecals; // [RH] Decals bound to the wall native readonly Line linedef; native int16 Light; - native uint8 Flags; + native uint16 Flags; native TextureID GetTexture(int which); native void SetTexture(int which, TextureID tex); @@ -87,6 +87,7 @@ struct Side native play native Color GetAdditiveColor(int tier); native void SetAdditiveColor(int tier, Color color); native void EnableAdditiveColor(int tier, bool enable); + native void SetColorization(int tier, Name cname); //native DInterpolation *SetInterpolation(int position); //native void StopInterpolation(int position); @@ -158,7 +159,7 @@ struct Line native play native uint activation; // activation type native int special; native int args[5]; // <--- hexen-style arguments (expanded to ZDoom's full width) - native double alpha; // <--- translucency (0=invisible, FRACUNIT=opaque) + native double alpha; // <--- translucency (0=invisible, 1.0=opaque) native readonly Side sidedef[2]; native readonly double bbox[4]; // bounding box, for the extent of the LineDef. native readonly Sector frontsector, backsector; @@ -469,6 +470,7 @@ struct Sector native play native void SetGlowColor(int pos, color color); native void SetSpecialColor(int pos, color color); native void SetAdditiveColor(int pos, Color color); + native void SetColorization(int tier, Name cname); native TextureID GetTexture(int pos); native void SetTexture(int pos, TextureID tex, bool floorclip = true);