diff --git a/README.md b/README.md new file mode 100644 index 0000000000..f04f324f7f --- /dev/null +++ b/README.md @@ -0,0 +1,22 @@ +# Welcome to GZDoom! + +[![Build Status](https://ci.appveyor.com/api/projects/status/github/coelckers/gzdoom?branch=master&svg=true)](https://ci.appveyor.com/project/coelckers/gzdoom) [![Build Status](https://travis-ci.org/coelckers/gzdoom.svg?branch=master)](https://travis-ci.org/coelckers/gzdoom) + +## GZDoom is a modder-friendly OpenGL source port based on the DOOM engine + +Copyright (c) 1998-2018 ZDoom + GZDoom teams, and contributors + +Doom Source (c) 1997 id Software, Raven Software, and contributors + +Please see license files for individual contributor licenses + +Special thanks to Coraline of the 3DGE team for allowing us to use her README.md as a template for this one. + +### Licensed under the GPL v3 (or greater) +##### https://www.gnu.org/licenses/quick-guide-gplv3.en.html +--- + +## How to build GZDoom + +To build GZDoom, please see the [wiki](https://zdoom.org/wiki/) and see the "Programmer's Corner" on the bottom-right corner of the page to build for your platform. + diff --git a/specs/udmf_zdoom.txt b/specs/udmf_zdoom.txt index 1851604614..185d2a6def 100644 --- a/specs/udmf_zdoom.txt +++ b/specs/udmf_zdoom.txt @@ -283,6 +283,7 @@ Note: All fields default to false unless mentioned otherwise. For things with ACS specials (80-86 and 226), if arg0str is present and non-null, it will be used as the name of the script to execute, and arg0 will be ignored. + On dynamic lights, arg0str can be used to set a color by name, this will supersede all args which are normally used to define a color. } @@ -426,6 +427,9 @@ floor_reflect and ceiling_reflect. 1.28 28.01.2017 sector material colors. +1.29 04.02.2018 +arg0str in dynamic lights. + =============================================================================== EOF =============================================================================== diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8610691abc..5740e3f6e8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -511,7 +511,7 @@ set( PLAT_SDL_SOURCES posix/sdl/st_start.cpp ) set( PLAT_UNIX_SOURCES posix/unix/i_specialpaths.cpp - posix/unix/iwadpicker_gtk.cpp ) + posix/unix/gtk_dialogs.cpp ) set( PLAT_OSX_SOURCES posix/osx/iwadpicker_cocoa.mm posix/osx/i_specialpaths.mm diff --git a/src/c_cmds.cpp b/src/c_cmds.cpp index efc11a3d24..842516ba34 100644 --- a/src/c_cmds.cpp +++ b/src/c_cmds.cpp @@ -681,7 +681,7 @@ UNSAFE_CCMD (crashout) #endif -CCMD (dir) +UNSAFE_CCMD (dir) { FString dir, path; char curdir[256]; diff --git a/src/c_cvars.cpp b/src/c_cvars.cpp index d51dacdcb0..7edf126ab8 100644 --- a/src/c_cvars.cpp +++ b/src/c_cvars.cpp @@ -53,6 +53,7 @@ #include "colormatcher.h" #include "menu/menu.h" #include "vm.h" +#include "v_text.h" struct FLatchedValue { @@ -1706,6 +1707,16 @@ void C_ArchiveCVars (FConfigFile *f, uint32_t filter) EXTERN_CVAR(Bool, sv_cheats); +static bool IsUnsafe(const FBaseCVar *const var) +{ + const bool unsafe = UnsafeExecutionContext && !(var->GetFlags() & CVAR_MOD); + if (unsafe) + { + Printf(TEXTCOLOR_RED "Cannot set console variable" TEXTCOLOR_GOLD " %s " TEXTCOLOR_RED "from unsafe command\n", var->GetName()); + } + return unsafe; +} + void FBaseCVar::CmdSet (const char *newval) { if ((GetFlags() & CVAR_CHEAT) && !sv_cheats) @@ -1713,6 +1724,10 @@ void FBaseCVar::CmdSet (const char *newval) Printf("sv_cheats must be true to set this console variable.\n"); return; } + else if (IsUnsafe(this)) + { + return; + } UCVarValue val; @@ -1799,6 +1814,11 @@ CCMD (toggle) { if ( (var = FindCVar (argv[1], &prev)) ) { + if (IsUnsafe(var)) + { + return; + } + val = var->GetGenericRep (CVAR_Bool); val.Bool = !val.Bool; var->SetGenericRep (val, CVAR_Bool); diff --git a/src/c_dispatch.cpp b/src/c_dispatch.cpp index ec4571b53b..cb1fb47e1d 100644 --- a/src/c_dispatch.cpp +++ b/src/c_dispatch.cpp @@ -127,8 +127,24 @@ FButtonStatus Button_Mlook, Button_Klook, Button_Use, Button_AltAttack, Button_AM_PanLeft, Button_AM_PanRight, Button_AM_PanDown, Button_AM_PanUp, Button_AM_ZoomIn, Button_AM_ZoomOut; -bool ParsingKeyConf; -static bool UnsafeExecutionContext; +bool ParsingKeyConf, UnsafeExecutionContext; + +class UnsafeExecutionScope +{ + const bool wasEnabled; + +public: + explicit UnsafeExecutionScope(const bool enable = true) + : wasEnabled(UnsafeExecutionContext) + { + UnsafeExecutionContext = enable; + } + + ~UnsafeExecutionScope() + { + UnsafeExecutionContext = wasEnabled; + } +}; // To add new actions, go to the console and type "key ". // This will give you the key value to use in the first column. Then @@ -227,10 +243,8 @@ void DWaitingCommand::Tick () { if (--TicsLeft == 0) { - const bool wasUnsafe = UnsafeExecutionContext; - UnsafeExecutionContext = IsUnsafe; + UnsafeExecutionScope scope; AddCommandString (Command); - UnsafeExecutionContext = wasUnsafe; Destroy (); } } @@ -658,12 +672,6 @@ void C_DoCommand (const char *cmd, int keynum) if (args.argc() >= 2) { // Set the variable - if (UnsafeExecutionContext && !(var->GetFlags() & CVAR_MOD)) - { - Printf(TEXTCOLOR_RED "Cannot set console variable" TEXTCOLOR_GOLD " %s " TEXTCOLOR_RED "from unsafe command\n", var->GetName()); - return; - } - var->CmdSet (args[1]); } else @@ -684,9 +692,9 @@ DEFINE_ACTION_FUNCTION(DOptionMenuItemCommand, DoCommand) if (CurrentMenu == nullptr) return 0; PARAM_PROLOGUE; PARAM_STRING(cmd); - UnsafeExecutionContext = true; + PARAM_BOOL(unsafe); + UnsafeExecutionScope scope(unsafe); C_DoCommand(cmd); - UnsafeExecutionContext = false; return 0; } @@ -1515,9 +1523,8 @@ void FConsoleAlias::SafeDelete () void FUnsafeConsoleAlias::Run (FCommandLine &args, APlayerPawn *instigator, int key) { - UnsafeExecutionContext = true; + UnsafeExecutionScope scope; FConsoleAlias::Run(args, instigator, key); - UnsafeExecutionContext = false; } void FExecList::AddCommand(const char *cmd, const char *file) diff --git a/src/c_dispatch.h b/src/c_dispatch.h index dac14b818a..aa82e20ba9 100644 --- a/src/c_dispatch.h +++ b/src/c_dispatch.h @@ -200,7 +200,7 @@ extern FButtonStatus Button_Mlook, Button_Klook, Button_Use, Button_AltAttack, Button_User1, Button_User2, Button_User3, Button_User4, Button_AM_PanLeft, Button_AM_PanRight, Button_AM_PanDown, Button_AM_PanUp, Button_AM_ZoomIn, Button_AM_ZoomOut; -extern bool ParsingKeyConf; +extern bool ParsingKeyConf, UnsafeExecutionContext; void ResetButtonTriggers (); // Call ResetTriggers for all buttons void ResetButtonStates (); // Same as above, but also clear bDown diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 5f109e418c..275c3814eb 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -280,7 +280,7 @@ void PClass::StaticShutdown () // This must be done in two steps because the native classes are not ordered by inheritance, // so all meta data must be gone before deleting the actual class objects. - for (auto cls : AllClasses) cls->DestroyMeta(cls->Meta); + for (auto cls : AllClasses) if (cls->Meta != nullptr) cls->DestroyMeta(cls->Meta); for (auto cls : AllClasses) delete cls; // Unless something went wrong, anything left here should be class and type objects only, which do not own any scripts. bShutdown = true; diff --git a/src/g_game.cpp b/src/g_game.cpp index 0e44e83016..d0cf74be7c 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -2599,7 +2599,7 @@ void G_DeferedPlayDemo (const char *name) gameaction = (gameaction == ga_loadgame) ? ga_loadgameplaydemo : ga_playdemo; } -CCMD (playdemo) +UNSAFE_CCMD (playdemo) { if (netgame) { diff --git a/src/g_inventory/a_weapons.cpp b/src/g_inventory/a_weapons.cpp index 440c67f9b7..a0458ce3ea 100644 --- a/src/g_inventory/a_weapons.cpp +++ b/src/g_inventory/a_weapons.cpp @@ -220,7 +220,21 @@ void AWeapon::MarkPrecacheSounds() const // //=========================================================================== -bool AWeapon::CheckAmmo (int fireMode, bool autoSwitch, bool requireAmmo, int ammocount) +bool AWeapon::CheckAmmo(int fireMode, bool autoSwitch, bool requireAmmo, int ammocount) +{ + IFVIRTUAL(AWeapon, CheckAmmo) + { + VMValue params[] = { (DObject*)this, fireMode, autoSwitch, requireAmmo, ammocount }; + VMReturn ret; + int retval; + ret.IntAt(&retval); + VMCall(func, params, 5, &ret, 1); + return !!retval; + } + return CheckAmmo(fireMode, autoSwitch, requireAmmo, ammocount); +} + +bool AWeapon::DoCheckAmmo (int fireMode, bool autoSwitch, bool requireAmmo, int ammocount) { int altFire; int count1, count2; @@ -293,7 +307,7 @@ DEFINE_ACTION_FUNCTION(AWeapon, CheckAmmo) PARAM_BOOL(autoswitch); PARAM_BOOL_DEF(require); PARAM_INT_DEF(ammocnt); - ACTION_RETURN_BOOL(self->CheckAmmo(mode, autoswitch, require, ammocnt)); + ACTION_RETURN_BOOL(self->DoCheckAmmo(mode, autoswitch, require, ammocnt)); } //=========================================================================== @@ -306,7 +320,21 @@ DEFINE_ACTION_FUNCTION(AWeapon, CheckAmmo) // //=========================================================================== -bool AWeapon::DepleteAmmo (bool altFire, bool checkEnough, int ammouse) +bool AWeapon::DepleteAmmo(bool altFire, bool checkEnough, int ammouse) +{ + IFVIRTUAL(AWeapon, DepleteAmmo) + { + VMValue params[] = { (DObject*)this, altFire, checkEnough, ammouse }; + VMReturn ret; + int retval; + ret.IntAt(&retval); + VMCall(func, params, 4, &ret, 1); + return !!retval; + } + return DoDepleteAmmo(altFire, checkEnough, ammouse); +} + +bool AWeapon::DoDepleteAmmo (bool altFire, bool checkEnough, int ammouse) { if (!((dmflags & DF_INFINITE_AMMO) || (Owner->FindInventory (PClass::FindActor(NAME_PowerInfiniteAmmo), true) != nullptr))) { @@ -357,7 +385,7 @@ DEFINE_ACTION_FUNCTION(AWeapon, DepleteAmmo) PARAM_BOOL(altfire); PARAM_BOOL_DEF(checkenough); PARAM_INT_DEF(ammouse); - ACTION_RETURN_BOOL(self->DepleteAmmo(altfire, checkenough, ammouse)); + ACTION_RETURN_BOOL(self->DoDepleteAmmo(altfire, checkenough, ammouse)); } diff --git a/src/g_inventory/a_weapons.h b/src/g_inventory/a_weapons.h index 9b397e402c..4c6f6ab45f 100644 --- a/src/g_inventory/a_weapons.h +++ b/src/g_inventory/a_weapons.h @@ -142,7 +142,9 @@ public: EitherFire }; bool CheckAmmo (int fireMode, bool autoSwitch, bool requireAmmo=false, int ammocount = -1); + bool DoCheckAmmo(int fireMode, bool autoSwitch, bool requireAmmo, int ammocount); bool DepleteAmmo (bool altFire, bool checkEnough=true, int ammouse = -1); + bool DoDepleteAmmo(bool altFire, bool checkEnough, int ammouse); enum { diff --git a/src/g_level.cpp b/src/g_level.cpp index 0b211f3e60..d6c712b241 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -648,7 +648,8 @@ void G_ChangeLevel(const char *levelname, int position, int flags, int nextSkill // If this is co-op, respawn any dead players now so they can // keep their inventory on the next map. - if ((multiplayer || level.flags2 & LEVEL2_ALLOWRESPAWN || sv_singleplayerrespawn) && !deathmatch && player->playerstate == PST_DEAD) + if ((multiplayer || level.flags2 & LEVEL2_ALLOWRESPAWN || sv_singleplayerrespawn || !!G_SkillProperty(SKILLP_PlayerRespawn)) + && !deathmatch && player->playerstate == PST_DEAD) { // Copied from the end of P_DeathThink [[ player->cls = NULL; // Force a new class if the player is using a random class @@ -2028,6 +2029,10 @@ DEFINE_FIELD(FLevelLocals, F1Pic) DEFINE_FIELD(FLevelLocals, maptype) DEFINE_FIELD(FLevelLocals, Music) DEFINE_FIELD(FLevelLocals, musicorder) +DEFINE_FIELD(FLevelLocals, skytexture1) +DEFINE_FIELD(FLevelLocals, skytexture2) +DEFINE_FIELD(FLevelLocals, skyspeed1) +DEFINE_FIELD(FLevelLocals, skyspeed2) DEFINE_FIELD(FLevelLocals, total_secrets) DEFINE_FIELD(FLevelLocals, found_secrets) DEFINE_FIELD(FLevelLocals, total_items) @@ -2093,3 +2098,19 @@ CCMD(skyfog) } } + +//========================================================================== +// +// ZScript counterpart to ACS ChangeSky, uses TextureIDs +// +//========================================================================== +DEFINE_ACTION_FUNCTION(FLevelLocals, ChangeSky) +{ + PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals); + PARAM_INT(sky1); + PARAM_INT(sky2); + sky1texture = self->skytexture1 = FSetTextureID(sky1); + sky2texture = self->skytexture2 = FSetTextureID(sky2); + R_InitSkyMap(); + return 0; +} diff --git a/src/gl/scene/gl_decal.cpp b/src/gl/scene/gl_decal.cpp index cf23102094..0f3bc7ffb4 100644 --- a/src/gl/scene/gl_decal.cpp +++ b/src/gl/scene/gl_decal.cpp @@ -289,7 +289,7 @@ void GLWall::DrawDecal(DBaseDecal *decal) // Note: This should be replaced with proper shader based lighting. double x, y; decal->GetXY(seg->sidedef, x, y); - gl_SetDynSpriteLight(NULL, x, y, zpos, sub); + gl_SetDynSpriteLight(nullptr, x, y, zpos - decalheight * 0.5f, sub); } // alpha color only has an effect when using an alpha texture. diff --git a/src/gl/scene/gl_scene.cpp b/src/gl/scene/gl_scene.cpp index a0bcb48821..178b39ff7c 100644 --- a/src/gl/scene/gl_scene.cpp +++ b/src/gl/scene/gl_scene.cpp @@ -842,7 +842,7 @@ sector_t * GLSceneDrawer::RenderViewpoint (AActor * camera, GL_IRECT * bounds, f stereo3dMode.SetUp(); for (int eye_ix = 0; eye_ix < stereo3dMode.eye_count(); ++eye_ix) { - if (eye_ix > 0) + if (eye_ix > 0 && camera->player) SetFixedColormap(camera->player); // reiterate color map for each eye, so night vision goggles work in both eyes const s3d::EyePose * eye = stereo3dMode.getEyePose(eye_ix); eye->SetUp(); diff --git a/src/gl/scene/gl_sprite.cpp b/src/gl/scene/gl_sprite.cpp index ac7eccac3f..a1816acd21 100644 --- a/src/gl/scene/gl_sprite.cpp +++ b/src/gl/scene/gl_sprite.cpp @@ -987,9 +987,8 @@ void GLSprite::Process(AActor* thing, sector_t * sector, int thruportal) RenderStyle.CheckFuzz(); if (RenderStyle.BlendOp == STYLEOP_Fuzz) { - if (gl_fuzztype != 0 && !gl.legacyMode) + if (gl_fuzztype != 0 && !gl.legacyMode && !(RenderStyle.Flags & STYLEF_InvertSource)) { - // Todo: implement shader selection here RenderStyle = LegacyRenderStyles[STYLE_Translucent]; OverrideShader = SHADER_NoTexture + gl_fuzztype; trans = 0.99f; // trans may not be 1 here diff --git a/src/gl/scene/gl_spritelight.cpp b/src/gl/scene/gl_spritelight.cpp index ac7e6971e5..1415ce16c9 100644 --- a/src/gl/scene/gl_spritelight.cpp +++ b/src/gl/scene/gl_spritelight.cpp @@ -74,7 +74,7 @@ void gl_SetDynSpriteLight(AActor *self, float x, float y, float z, subsector_t * while (node) { light=node->lightsource; - if (light->visibletoplayer && !(light->flags2&MF2_DORMANT) && (!(light->lightflags&LF_DONTLIGHTSELF) || light->target != self) && !(light->lightflags&LF_DONTLIGHTACTORS)) + if (light->visibletoplayer && !(light->flags2&MF2_DORMANT) && (!(light->lightflags&LF_DONTLIGHTSELF) || light->target != self || !self) && !(light->lightflags&LF_DONTLIGHTACTORS)) { float dist; FVector3 L; diff --git a/src/gl/stereo3d/gl_stereo_cvars.cpp b/src/gl/stereo3d/gl_stereo_cvars.cpp index 201e33590e..e7ce699f55 100644 --- a/src/gl/stereo3d/gl_stereo_cvars.cpp +++ b/src/gl/stereo3d/gl_stereo_cvars.cpp @@ -32,6 +32,7 @@ #include "gl/stereo3d/gl_sidebyside3d.h" #include "gl/stereo3d/gl_interleaved3d.h" #include "gl/system/gl_cvars.h" +#include "version.h" // Set up 3D-specific console variables: CVAR(Int, vr_mode, 0, CVAR_GLOBALCONFIG) @@ -42,7 +43,10 @@ CVAR(Bool, vr_swap_eyes, false, CVAR_GLOBALCONFIG) // For broadest GL compatibility, require user to explicitly enable quad-buffered stereo mode. // Setting vr_enable_quadbuffered_stereo does not automatically invoke quad-buffered stereo, // but makes it possible for subsequent "vr_mode 7" to invoke quad-buffered stereo -CVAR(Bool, vr_enable_quadbuffered, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +CUSTOM_CVAR(Bool, vr_enable_quadbuffered, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL) +{ + Printf("You must restart " GAMENAME " to switch quad stereo mode\n"); +} // intraocular distance in meters CVAR(Float, vr_ipd, 0.062f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) // METERS diff --git a/src/m_misc.cpp b/src/m_misc.cpp index eb51ec7b9a..481f956b51 100644 --- a/src/m_misc.cpp +++ b/src/m_misc.cpp @@ -673,7 +673,7 @@ void M_ScreenShot (const char *filename) } } -CCMD (screenshot) +UNSAFE_CCMD (screenshot) { if (argv.argc() == 1) G_ScreenShot (NULL); diff --git a/src/menu/menu.cpp b/src/menu/menu.cpp index 86ec78abf2..f03c37eb73 100644 --- a/src/menu/menu.cpp +++ b/src/menu/menu.cpp @@ -58,6 +58,7 @@ #include "vm.h" #include "events.h" #include "gl/renderer/gl_renderer.h" // for menu blur +#include "scripting/types.h" // // Todo: Move these elsewhere @@ -1180,6 +1181,8 @@ DMenuItemBase * CreateOptionMenuItemCommand(const char *label, FName cmd, bool c VMValue params[] = { p, &namestr, cmd.GetIndex(), centered }; auto f = dyn_cast(c->FindSymbol("Init", false)); VMCall(f->Variants[0].Implementation, params, countof(params), nullptr, 0); + auto unsafe = dyn_cast(c->FindSymbol("mUnsafe", false)); + unsafe->Type->SetValue(reinterpret_cast(p) + unsafe->Offset, 0); return (DMenuItemBase*)p; } diff --git a/src/p_acs.cpp b/src/p_acs.cpp index e2fccad141..e36cecde78 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -835,12 +835,12 @@ inline int uallong(const int &foo) //============================================================================ // ACS variables with world scope -int32_t ACS_WorldVars[NUM_WORLDVARS]; -FWorldGlobalArray ACS_WorldArrays[NUM_WORLDVARS]; +static BoundsCheckingArray ACS_WorldVars; +static BoundsCheckingArray ACS_WorldArrays; // ACS variables with global scope -int32_t ACS_GlobalVars[NUM_GLOBALVARS]; -FWorldGlobalArray ACS_GlobalArrays[NUM_GLOBALVARS]; +BoundsCheckingArray ACS_GlobalVars; +BoundsCheckingArray ACS_GlobalArrays; //---------------------------------------------------------------------------- // @@ -851,21 +851,7 @@ FWorldGlobalArray ACS_GlobalArrays[NUM_GLOBALVARS]; // //---------------------------------------------------------------------------- -struct FACSStackMemory -{ - int32_t& operator[](const size_t index) - { - if (index >= STACK_SIZE) - { - I_Error("Corrupted stack pointer in ACS VM"); - } - - return buffer[index]; - } - -private: - int32_t buffer[STACK_SIZE]; -}; +using FACSStackMemory = BoundsCheckingArray; struct FACSStack { @@ -1470,10 +1456,10 @@ void ACSStringPool::UnlockForLevel(int lnum) void P_MarkWorldVarStrings() { - GlobalACSStrings.MarkStringArray(ACS_WorldVars, countof(ACS_WorldVars)); - for (size_t i = 0; i < countof(ACS_WorldArrays); ++i) + GlobalACSStrings.MarkStringArray(ACS_WorldVars.Pointer(), ACS_WorldVars.Size()); + for (size_t i = 0; i < ACS_WorldArrays.Size(); ++i) { - GlobalACSStrings.MarkStringMap(ACS_WorldArrays[i]); + GlobalACSStrings.MarkStringMap(ACS_WorldArrays.Pointer()[i]); } } @@ -1485,10 +1471,10 @@ void P_MarkWorldVarStrings() void P_MarkGlobalVarStrings() { - GlobalACSStrings.MarkStringArray(ACS_GlobalVars, countof(ACS_GlobalVars)); - for (size_t i = 0; i < countof(ACS_GlobalArrays); ++i) + GlobalACSStrings.MarkStringArray(ACS_GlobalVars.Pointer(), ACS_GlobalVars.Size()); + for (size_t i = 0; i < ACS_GlobalArrays.Size(); ++i) { - GlobalACSStrings.MarkStringMap(ACS_GlobalArrays[i]); + GlobalACSStrings.MarkStringMap(ACS_GlobalArrays.Pointer()[i]); } } @@ -1571,14 +1557,14 @@ void P_ClearACSVars(bool alsoglobal) { int i; - memset (ACS_WorldVars, 0, sizeof(ACS_WorldVars)); + ACS_WorldVars.Fill(0); for (i = 0; i < NUM_WORLDVARS; ++i) { ACS_WorldArrays[i].Clear (); } if (alsoglobal) { - memset (ACS_GlobalVars, 0, sizeof(ACS_GlobalVars)); + ACS_GlobalVars.Fill(0); for (i = 0; i < NUM_GLOBALVARS; ++i) { ACS_GlobalArrays[i].Clear (); @@ -1726,10 +1712,10 @@ static void ReadArrayVars (FSerializer &file, FWorldGlobalArray *vars, size_t co void P_ReadACSVars(FSerializer &arc) { - ReadVars (arc, ACS_WorldVars, NUM_WORLDVARS, "acsworldvars"); - ReadVars (arc, ACS_GlobalVars, NUM_GLOBALVARS, "acsglobalvars"); - ReadArrayVars (arc, ACS_WorldArrays, NUM_WORLDVARS, "acsworldarrays"); - ReadArrayVars (arc, ACS_GlobalArrays, NUM_GLOBALVARS, "acsglobalarrays"); + ReadVars (arc, ACS_WorldVars.Pointer(), NUM_WORLDVARS, "acsworldvars"); + ReadVars (arc, ACS_GlobalVars.Pointer(), NUM_GLOBALVARS, "acsglobalvars"); + ReadArrayVars (arc, ACS_WorldArrays.Pointer(), NUM_WORLDVARS, "acsworldarrays"); + ReadArrayVars (arc, ACS_GlobalArrays.Pointer(), NUM_GLOBALVARS, "acsglobalarrays"); GlobalACSStrings.ReadStrings(arc, "acsglobalstrings"); } @@ -1741,10 +1727,10 @@ void P_ReadACSVars(FSerializer &arc) void P_WriteACSVars(FSerializer &arc) { - WriteVars (arc, ACS_WorldVars, NUM_WORLDVARS, "acsworldvars"); - WriteVars (arc, ACS_GlobalVars, NUM_GLOBALVARS, "acsglobalvars"); - WriteArrayVars (arc, ACS_WorldArrays, NUM_WORLDVARS, "acsworldarrays"); - WriteArrayVars (arc, ACS_GlobalArrays, NUM_GLOBALVARS, "acsglobalarrays"); + WriteVars (arc, ACS_WorldVars.Pointer(), NUM_WORLDVARS, "acsworldvars"); + WriteVars (arc, ACS_GlobalVars.Pointer(), NUM_GLOBALVARS, "acsglobalvars"); + WriteArrayVars (arc, ACS_WorldArrays.Pointer(), NUM_WORLDVARS, "acsworldarrays"); + WriteArrayVars (arc, ACS_GlobalArrays.Pointer(), NUM_GLOBALVARS, "acsglobalarrays"); GlobalACSStrings.WriteStrings(arc, "acsglobalstrings"); } @@ -9852,7 +9838,7 @@ scriptwait: if (STACK(2) != 0) { AActor *marine; - NActorIterator iterator("ScriptedMarine", STACK(2)); + NActorIterator iterator(NAME_ScriptedMarine, STACK(2)); while ((marine = iterator.Next()) != NULL) { @@ -9861,7 +9847,7 @@ scriptwait: } else { - if (activator != nullptr && activator->IsKindOf (PClass::FindClass("ScriptedMarine"))) + if (activator != nullptr && activator->IsKindOf (NAME_ScriptedMarine)) { SetMarineWeapon(activator, STACK(1)); } @@ -9878,7 +9864,7 @@ scriptwait: if (STACK(2) != 0) { AActor *marine; - NActorIterator iterator("ScriptedMarine", STACK(2)); + NActorIterator iterator(NAME_ScriptedMarine, STACK(2)); while ((marine = iterator.Next()) != NULL) { @@ -9887,7 +9873,7 @@ scriptwait: } else { - if (activator != nullptr && activator->IsKindOf("ScriptedMarine")) + if (activator != nullptr && activator->IsKindOf(NAME_ScriptedMarine)) { SetMarineSprite(activator, type); } diff --git a/src/p_acs.h b/src/p_acs.h index 4f53ce1a37..7b0d18bd82 100644 --- a/src/p_acs.h +++ b/src/p_acs.h @@ -60,13 +60,32 @@ struct InitIntToZero }; typedef TMap, InitIntToZero> FWorldGlobalArray; -// ACS variables with world scope -extern int32_t ACS_WorldVars[NUM_WORLDVARS]; -extern FWorldGlobalArray ACS_WorldArrays[NUM_WORLDVARS]; +// Type of elements count is unsigned int instead of size_t to match ACSStringPool interface +template +struct BoundsCheckingArray +{ + T &operator[](const unsigned int index) + { + if (index >= N) + { + I_Error("Out of bounds memory access in ACS VM"); + } + + return buffer[index]; + } + + T *Pointer() { return buffer; } + unsigned int Size() const { return N; } + + void Fill(const T &value) { std::fill(std::begin(buffer), std::end(buffer), value); } + +private: + T buffer[N]; +}; // ACS variables with global scope -extern int32_t ACS_GlobalVars[NUM_GLOBALVARS]; -extern FWorldGlobalArray ACS_GlobalArrays[NUM_GLOBALVARS]; +extern BoundsCheckingArray ACS_GlobalVars; +extern BoundsCheckingArray ACS_GlobalArrays; #define LIBRARYID_MASK 0xFFF00000 #define LIBRARYID_SHIFT 20 @@ -359,7 +378,7 @@ public: ACSProfileInfo *GetFunctionProfileData(ScriptFunction *func) { return GetFunctionProfileData((int)(func - (ScriptFunction *)Functions)); } const char *LookupString (uint32_t index) const; - int32_t *MapVars[NUM_MAPVARS]; + BoundsCheckingArray MapVars; static FBehavior *StaticLoadModule (int lumpnum, FileReader * fr=NULL, int len=0); static void StaticLoadDefaultModules (); diff --git a/src/p_glnodes.cpp b/src/p_glnodes.cpp index bd574ad837..60c666e82a 100644 --- a/src/p_glnodes.cpp +++ b/src/p_glnodes.cpp @@ -1216,7 +1216,7 @@ errorout: return false; } -CCMD(clearnodecache) +UNSAFE_CCMD(clearnodecache) { TArray list; FString path = M_GetCachePath(false); diff --git a/src/p_maputl.cpp b/src/p_maputl.cpp index 24c30375e2..6b19942e0f 100644 --- a/src/p_maputl.cpp +++ b/src/p_maputl.cpp @@ -809,11 +809,13 @@ bool FMultiBlockLinesIterator::GoUp(double x, double y) { if (!cursector->PortalBlocksMovement(sector_t::ceiling)) { - startIteratorForGroup(cursector->GetOppositePortalGroup(sector_t::ceiling)); - portalflags = FFCF_NOFLOOR; - return true; + if (startIteratorForGroup(cursector->GetOppositePortalGroup(sector_t::ceiling))) + { + portalflags = FFCF_NOFLOOR; + return true; + } } - else continueup = false; + continueup = false; } return false; } @@ -830,11 +832,13 @@ bool FMultiBlockLinesIterator::GoDown(double x, double y) { if (!cursector->PortalBlocksMovement(sector_t::floor)) { - startIteratorForGroup(cursector->GetOppositePortalGroup(sector_t::floor)); - portalflags = FFCF_NOCEILING; - return true; + if (startIteratorForGroup(cursector->GetOppositePortalGroup(sector_t::floor))) + { + portalflags = FFCF_NOCEILING; + return true; + } } - else continuedown = false; + continuedown = false; } return false; } @@ -906,14 +910,19 @@ bool FMultiBlockLinesIterator::Next(FMultiBlockLinesIterator::CheckResult *item) // //=========================================================================== -void FMultiBlockLinesIterator::startIteratorForGroup(int group) +bool FMultiBlockLinesIterator::startIteratorForGroup(int group) { offset = Displacements.getOffset(basegroup, group); offset.X += checkpoint.X; offset.Y += checkpoint.Y; cursector = group == startsector->PortalGroup ? startsector : P_PointInSector(offset); + // If we ended up in a different group, + // presumably because the spot to be checked is too far outside the actual portal group, + // the search needs to abort. + if (cursector->PortalGroup != group) return false; bbox.setBox(offset.X, offset.Y, checkpoint.Z); blockIterator.init(bbox); + return true; } //=========================================================================== diff --git a/src/p_maputl.h b/src/p_maputl.h index 8ac3ea76af..4dfa99e0f0 100644 --- a/src/p_maputl.h +++ b/src/p_maputl.h @@ -240,7 +240,7 @@ class FMultiBlockLinesIterator bool GoUp(double x, double y); bool GoDown(double x, double y); - void startIteratorForGroup(int group); + bool startIteratorForGroup(int group); public: diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 79f549dd38..8e5e1d3a26 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -6101,6 +6101,9 @@ AActor *P_SpawnMapThing (FMapThing *mthing, int position) if (mthing->arg0str != NAME_None) { PalEntry color = V_GetColor(nullptr, mthing->arg0str); + light->args[0] = color.r; + light->args[1] = color.g; + light->args[2] = color.b; } else if (light->lightflags & LF_SPOT) { @@ -7766,7 +7769,13 @@ FState *AActor::GetRaiseState() void AActor::Revive() { AActor *info = GetDefault(); + FLinkContext ctx; + + bool flagchange = (flags & (MF_NOBLOCKMAP | MF_NOSECTOR)) != (info->flags & (MF_NOBLOCKMAP | MF_NOSECTOR)); + + if (flagchange) UnlinkFromWorld(&ctx); flags = info->flags; + if (flagchange) LinkToWorld(&ctx); flags2 = info->flags2; flags3 = info->flags3; flags4 = info->flags4; diff --git a/src/p_sectors.cpp b/src/p_sectors.cpp index 369c5de61b..fb4789e17e 100644 --- a/src/p_sectors.cpp +++ b/src/p_sectors.cpp @@ -1659,7 +1659,7 @@ DEFINE_ACTION_FUNCTION(_Sector, NextLowestFloorAt) PARAM_SELF_STRUCT_PROLOGUE(sector_t); PARAM_INT(pos); PARAM_FLOAT(o); - self->SetXScale(pos, o); + self->SetYScale(pos, o); return 0; } diff --git a/src/p_trace.cpp b/src/p_trace.cpp index d00a5c4cc0..fd79861ec2 100644 --- a/src/p_trace.cpp +++ b/src/p_trace.cpp @@ -955,8 +955,8 @@ static bool EditTraceResult (uint32_t flags, FTraceResults &res) // [ZZ] here go the methods for the ZScript interface // //========================================================================== -IMPLEMENT_CLASS(DTracer, false, false) -DEFINE_FIELD_X(Tracer, DTracer, Results) +IMPLEMENT_CLASS(DLineTracer, false, false) +DEFINE_FIELD(DLineTracer, Results) // define TraceResults fields DEFINE_FIELD_NAMED_X(TraceResults, FTraceResults, Sector, HitSector) @@ -978,9 +978,9 @@ DEFINE_FIELD_X(TraceResults, FTraceResults, CrossedWaterPos) DEFINE_FIELD_X(TraceResults, FTraceResults, Crossed3DWater) DEFINE_FIELD_X(TraceResults, FTraceResults, Crossed3DWaterPos) -DEFINE_ACTION_FUNCTION(DTracer, Trace) +DEFINE_ACTION_FUNCTION(DLineTracer, Trace) { - PARAM_SELF_PROLOGUE(DTracer); + PARAM_SELF_PROLOGUE(DLineTracer); /*bool Trace(const DVector3 &start, sector_t *sector, const DVector3 &direction, double maxDist, ActorFlags ActorMask, uint32_t WallMask, AActor *ignore, FTraceResults &res, uint32_t traceFlags = 0, ETraceStatus(*callback)(FTraceResults &res, void *) = NULL, void *callbackdata = NULL);*/ @@ -1001,13 +1001,13 @@ DEFINE_ACTION_FUNCTION(DTracer, Trace) // Trace(vector3 start, Sector sector, vector3 direction, double maxDist, ETraceFlags traceFlags) bool res = Trace(DVector3(start_x, start_y, start_z), sector, DVector3(direction_x, direction_y, direction_z), maxDist, - (ActorFlag)0xFFFFFFFF, 0xFFFFFFFF, nullptr, self->Results, traceFlags, &DTracer::TraceCallback, self); + (ActorFlag)0xFFFFFFFF, 0xFFFFFFFF, nullptr, self->Results, traceFlags, &DLineTracer::TraceCallback, self); ACTION_RETURN_BOOL(res); } -ETraceStatus DTracer::TraceCallback(FTraceResults& res, void* pthis) +ETraceStatus DLineTracer::TraceCallback(FTraceResults& res, void* pthis) { - DTracer* self = (DTracer*)pthis; + DLineTracer* self = (DLineTracer*)pthis; // "res" here should refer to self->Results anyway. // patch results a bit. modders don't expect it to work like this most likely. @@ -1036,13 +1036,13 @@ ETraceStatus DTracer::TraceCallback(FTraceResults& res, void* pthis) return self->CallZScriptCallback(); } -ETraceStatus DTracer::CallZScriptCallback() +ETraceStatus DLineTracer::CallZScriptCallback() { - IFVIRTUAL(DTracer, TraceCallback) + IFVIRTUAL(DLineTracer, TraceCallback) { int status; VMReturn results[1] = { &status }; - VMValue params[1] = { (DTracer*)this }; + VMValue params[1] = { (DLineTracer*)this }; VMCall(func, params, 1, results, 1); return (ETraceStatus)status; } diff --git a/src/p_trace.h b/src/p_trace.h index af4187f785..0a61cc7258 100644 --- a/src/p_trace.h +++ b/src/p_trace.h @@ -113,9 +113,9 @@ bool Trace(const DVector3 &start, sector_t *sector, const DVector3 &direction, d ETraceStatus(*callback)(FTraceResults &res, void *) = NULL, void *callbackdata = NULL); // [ZZ] this is the object that's used for ZScript -class DTracer : public DObject +class DLineTracer : public DObject { - DECLARE_CLASS(DTracer, DObject) + DECLARE_CLASS(DLineTracer, DObject) public: FTraceResults Results; static ETraceStatus TraceCallback(FTraceResults& res, void* pthis); diff --git a/src/posix/sdl/i_main.cpp b/src/posix/sdl/i_main.cpp index 21f58e71e9..95ed8322eb 100644 --- a/src/posix/sdl/i_main.cpp +++ b/src/posix/sdl/i_main.cpp @@ -73,6 +73,10 @@ extern "C" int cc_install_handlers(int, char**, int, int*, const char*, int(*)(c void Mac_I_FatalError(const char* errortext); #endif +#ifdef __linux__ +void Linux_I_FatalError(const char* errortext); +#endif + // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- @@ -268,6 +272,10 @@ int main (int argc, char **argv) Mac_I_FatalError(error.GetMessage()); #endif // __APPLE__ +#ifdef __linux__ + Linux_I_FatalError(error.GetMessage()); +#endif // __linux__ + exit (-1); } catch (...) diff --git a/src/posix/sdl/i_system.cpp b/src/posix/sdl/i_system.cpp index b71acb8f8d..f980e25983 100644 --- a/src/posix/sdl/i_system.cpp +++ b/src/posix/sdl/i_system.cpp @@ -79,6 +79,7 @@ extern "C" #ifndef NO_GTK bool I_GtkAvailable (); int I_PickIWad_Gtk (WadStuff *wads, int numwads, bool showwin, int defaultiwad); +void I_FatalError_Gtk(const char* errortext); #elif defined(__APPLE__) int I_PickIWad_Cocoa (WadStuff *wads, int numwads, bool showwin, int defaultiwad); #endif @@ -157,6 +158,37 @@ bool gameisdead; void Mac_I_FatalError(const char* errortext); #endif +#ifdef __linux__ +void Linux_I_FatalError(const char* errortext) +{ + // Close window or exit fullscreen and release mouse capture + SDL_Quit(); + + const char *str; + if((str=getenv("KDE_FULL_SESSION")) && strcmp(str, "true") == 0) + { + FString cmd; + cmd << "kdialog --title \"" GAMESIG " "; + cmd << GetVersionString() << ": No IWAD found\" "; + cmd << "--msgbox \"" << errortext << "\""; + popen(cmd, "r"); + } +#ifndef NO_GTK + else if (I_GtkAvailable()) + { + I_FatalError_Gtk(errortext); + } +#endif + else + { + FString message; + message << GAMESIG " "; + message << GetVersionString() << ": No IWAD found"; + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, message, errortext, NULL); + } +} +#endif + void I_FatalError (const char *error, ...) { static bool alreadyThrown = false; @@ -175,6 +207,10 @@ void I_FatalError (const char *error, ...) #ifdef __APPLE__ Mac_I_FatalError(errortext); #endif // __APPLE__ + +#ifdef __linux__ + Linux_I_FatalError(errortext); +#endif // Record error to log (if logging) if (Logfile) diff --git a/src/posix/unix/iwadpicker_gtk.cpp b/src/posix/unix/gtk_dialogs.cpp similarity index 83% rename from src/posix/unix/iwadpicker_gtk.cpp rename to src/posix/unix/gtk_dialogs.cpp index ebaab609f8..658f8cbc5d 100644 --- a/src/posix/unix/iwadpicker_gtk.cpp +++ b/src/posix/unix/gtk_dialogs.cpp @@ -1,5 +1,5 @@ /* -** iwadpicker_gtk.cpp +** gtk_dialogs.cpp ** **--------------------------------------------------------------------------- ** Copyright 2008-2016 Braden Obrzut @@ -126,12 +126,16 @@ DYN_GTK_SYM(gtk_window_new); DYN_GTK_SYM(gtk_window_set_gravity); DYN_GTK_SYM(gtk_window_set_position); DYN_GTK_SYM(gtk_window_set_title); +DYN_GTK_SYM(gtk_window_set_resizable); +DYN_GTK_SYM(gtk_dialog_run); +DYN_GTK_SYM(gtk_dialog_get_type); // Gtk3 Only DYN_GTK_OPT3_SYM(gtk_box_new, GtkWidget *(*)(GtkOrientation, gint)); DYN_GTK_OPT3_SYM(gtk_button_box_new, GtkWidget *(*)(GtkOrientation)); DYN_GTK_OPT3_SYM(gtk_widget_set_halign, void(*)(GtkWidget *, GtkAlign)); DYN_GTK_OPT3_SYM(gtk_widget_set_valign, void(*)(GtkWidget *, GtkAlign)); +DYN_GTK_OPT3_SYM(gtk_message_dialog_new, GtkWidget* (*)(GtkWindow*, GtkDialogFlags, GtkMessageType, GtkButtonsType, const gchar*, ...)); // Gtk2 Only DYN_GTK_OPT2_SYM(gtk_misc_get_type, GType(*)()); @@ -342,6 +346,70 @@ static int PickIWad (WadStuff *wads, int numwads, bool showwin, int defaultiwad) return i; } +static void ShowError(const char* errortext) +{ + GtkWidget *window; + GtkWidget *widget; + GtkWidget *vbox = nullptr; + GtkWidget *bbox = nullptr; + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_title (GTK_WINDOW(window), "Fatal error"); + gtk_window_set_position (GTK_WINDOW(window), GTK_WIN_POS_CENTER); + gtk_window_set_gravity (GTK_WINDOW(window), GDK_GRAVITY_CENTER); + gtk_window_set_resizable (GTK_WINDOW(window), false); + gtk_container_set_border_width (GTK_CONTAINER(window), 10); + g_signal_connect (window, "delete_event", G_CALLBACK(gtk_main_quit), NULL); + g_signal_connect (window, "key_press_event", G_CALLBACK(CheckEscape), NULL); + + // Create the vbox container. + if (gtk_box_new) // Gtk3 + vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10); + else if (gtk_vbox_new) // Gtk2 + vbox = gtk_vbox_new (FALSE, 10); + + gtk_container_add (GTK_CONTAINER(window), vbox); + + // Create the label. + widget = gtk_label_new ((const gchar *) errortext); + gtk_box_pack_start (GTK_BOX(vbox), widget, false, false, 0); + + if (gtk_widget_set_halign && gtk_widget_set_valign) // Gtk3 + { + gtk_widget_set_halign (widget, GTK_ALIGN_START); + gtk_widget_set_valign (widget, GTK_ALIGN_START); + } + else if (gtk_misc_set_alignment && gtk_misc_get_type) // Gtk2 + gtk_misc_set_alignment (GTK_MISC(widget), 0, 0); + + // Create the Exit button box. + if (gtk_button_box_new) // Gtk3 + bbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL); + else if (gtk_hbutton_box_new) // Gtk2 + bbox = gtk_hbutton_box_new (); + + gtk_button_box_set_layout (GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END); + gtk_box_set_spacing (GTK_BOX(bbox), 10); + gtk_box_pack_end (GTK_BOX(vbox), bbox, false, false, 0); + + // Create the cancel button. + widget = gtk_button_new_with_label ("Exit"); + gtk_box_pack_start (GTK_BOX(bbox), widget, false, false, 0); + g_signal_connect (widget, "clicked", G_CALLBACK(gtk_main_quit), &window); + + // Finally we can show everything. + gtk_widget_show_all (window); + + gtk_main (); + + if (GTK_IS_WINDOW(window)) + { + gtk_widget_destroy (window); + // If we don't do this, then the X window might not actually disappear. + while (g_main_context_iteration (NULL, FALSE)) {} + } +} + } // namespace Gtk int I_PickIWad_Gtk (WadStuff *wads, int numwads, bool showwin, int defaultiwad) @@ -349,6 +417,10 @@ int I_PickIWad_Gtk (WadStuff *wads, int numwads, bool showwin, int defaultiwad) return Gtk::PickIWad (wads, numwads, showwin, defaultiwad); } +void I_FatalError_Gtk(const char* errortext) { + Gtk::ShowError(errortext); +} + bool I_GtkAvailable() { using namespace Gtk; diff --git a/src/s_sound.cpp b/src/s_sound.cpp index fede842b10..d3f587b948 100644 --- a/src/s_sound.cpp +++ b/src/s_sound.cpp @@ -2999,7 +2999,7 @@ CCMD (cd_resume) // //========================================================================== -CCMD (playlist) +UNSAFE_CCMD (playlist) { int argc = argv.argc(); diff --git a/src/sound/mididevices/music_fluidsynth_mididevice.cpp b/src/sound/mididevices/music_fluidsynth_mididevice.cpp index 07102c43d6..42244b61a7 100644 --- a/src/sound/mididevices/music_fluidsynth_mididevice.cpp +++ b/src/sound/mididevices/music_fluidsynth_mididevice.cpp @@ -124,13 +124,13 @@ CUSTOM_CVAR(Float, fluid_gain, 0.5, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) currSong->FluidSettingNum("synth.gain", self); } -CUSTOM_CVAR(Bool, fluid_reverb, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) +CUSTOM_CVAR(Bool, fluid_reverb, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) { if (currSong != NULL) currSong->FluidSettingInt("synth.reverb.active", self); } -CUSTOM_CVAR(Bool, fluid_chorus, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) +CUSTOM_CVAR(Bool, fluid_chorus, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) { if (currSong != NULL) currSong->FluidSettingInt("synth.chorus.active", self); diff --git a/src/textures/texturemanager.cpp b/src/textures/texturemanager.cpp index 5039f48b60..613aa3be9f 100644 --- a/src/textures/texturemanager.cpp +++ b/src/textures/texturemanager.cpp @@ -1206,8 +1206,21 @@ DEFINE_ACTION_FUNCTION(_TexMan, GetName) { PARAM_PROLOGUE; PARAM_INT(texid); - const FTexture* const tex = TexMan.ByIndex(texid); - ACTION_RETURN_STRING(nullptr == tex ? FString() : tex->Name); + auto tex = TexMan.ByIndex(texid); + FString retval; + + if (tex != nullptr) + { + if (tex->Name.IsNotEmpty()) retval = tex->Name; + else + { + // Textures for full path names do not have their own name, they merely link to the source lump. + auto lump = tex->GetSourceLump(); + if (Wads.GetLinkedTexture(lump) == tex) + retval = Wads.GetLumpFullName(lump); + } + } + ACTION_RETURN_STRING(retval); } //========================================================================== diff --git a/wadsrc/static/compatibility.txt b/wadsrc/static/compatibility.txt index 245c450529..b78b4e6648 100644 --- a/wadsrc/static/compatibility.txt +++ b/wadsrc/static/compatibility.txt @@ -376,6 +376,14 @@ F481922F4881F74760F3C0437FD5EDD0 // map03 setlinespecial 1008 Door_Open 0 64 0 0 0 } +7ED9800213C00D6E7FB98652AB48B3DE // Ultimate Simplicity, map04 +{ + // Add missing map spots on easy and medium skills + // Demons will teleport into starting room making 100% kills possible + setthingskills 31 31 + setthingskills 32 31 +} + 1891E029994B023910CFE0B3209C3CDB // Ultimate Simplicity, map07 { // It is possible to get stuck on skill 0 or 1 when no shots have been fired @@ -386,6 +394,13 @@ F481922F4881F74760F3C0437FD5EDD0 // map03 setlinespecial 411 NoiseAlert 0 0 0 0 0 } +F0E6F30F57B0425F17E43600AA813E80 // Ultimate Simplicity, map11 +{ + // If door (sector #309) is closed it cannot be open again + // from one side potentially blocking level progression + clearlinespecial 2445 +} + 952CC8D03572E17BA550B01B366EFBB9 // Cheogsh map01 { // make the blue key spawn above the 3D floor @@ -685,6 +700,10 @@ EBDAC00E9D25D884B2C8F4B1F0390539 // doom2.wad map21 setsectoroffset 50 ceil -56 setsectoroffset 54 ceil -56 } +94893A0DC429A22ADC4B3A73DA537E16 // DOOM2.WAD map25 +{ + rebuildnodes +} 110F84DE041052B59307FAF0293E6BC0 // Doom II, map27 { setsectorspecial 93 0 @@ -844,3 +863,8 @@ CA3773ED313E8899311F3DD0CA195A68 // e3m6 setthingz 403 168 setthingz 404 168 } + +6D4156EE0D12B77AD143A37C4D3DCF98 // dmonfear.wad map22 +{ + shorttex +} diff --git a/wadsrc/static/credits/rsmk.txt b/wadsrc/static/credits/rsmk.txt new file mode 100644 index 0000000000..e37c200866 --- /dev/null +++ b/wadsrc/static/credits/rsmk.txt @@ -0,0 +1,3 @@ +These sprites were made by Talon1024 and have been put in the public domain: + +https://forum.zdoom.org/viewtopic.php?f=15&t=59245 diff --git a/wadsrc/static/language.enu b/wadsrc/static/language.enu index 7b5eed9a05..5014365528 100644 --- a/wadsrc/static/language.enu +++ b/wadsrc/static/language.enu @@ -2729,7 +2729,7 @@ GLPREFMNU_AMBLIGHT = "Ambient light level"; GLPREFMNU_RENDERQUALITY = "Rendering quality"; GLPREFMNU_MENUBLUR = "Menu Blur"; GLPREFMNU_VRMODE = "Stereo 3D VR"; -GLPREFMNU_VRQUADSTEREO = "Enable Quad Stereo (Requires Restart)"; +GLPREFMNU_VRQUADSTEREO = "Enable Quad Stereo"; GLPREFMNU_MULTISAMPLE = "Multisample"; GLPREFMNU_TONEMAP = "Tonemap Mode"; GLPREFMNU_BLOOM = "Bloom effect"; diff --git a/wadsrc/static/mapinfo/common.txt b/wadsrc/static/mapinfo/common.txt index 1c1559b061..b79ecd5f4f 100644 --- a/wadsrc/static/mapinfo/common.txt +++ b/wadsrc/static/mapinfo/common.txt @@ -118,7 +118,7 @@ DoomEdNums 9851 = SpotLightPulseAdditive 9852 = SpotLightFlickerAdditive 9853 = SectorSpotLightAdditive - 9854 = SpotLightFlickerRandomSubtractive + 9854 = SpotLightFlickerRandomAdditive 9860 = SpotLightSubtractive 9861 = SpotLightPulseSubtractive 9862 = SpotLightFlickerSubtractive diff --git a/wadsrc/static/shaders/glsl/fuzz_software.fp b/wadsrc/static/shaders/glsl/fuzz_software.fp index 4fe4ab669e..7840ce8be4 100644 --- a/wadsrc/static/shaders/glsl/fuzz_software.fp +++ b/wadsrc/static/shaders/glsl/fuzz_software.fp @@ -5,8 +5,8 @@ #define FRACBITS 16 #define fixed_t int -int fuzz_random_x_offset[FUZZ_RANDOM_X_SIZE] = -{ +int fuzz_random_x_offset[FUZZ_RANDOM_X_SIZE] = int[] +( 75, 76, 21, 91, 56, 33, 62, 99, 61, 79, 95, 54, 41, 18, 69, 43, 49, 59, 10, 84, 94, 17, 57, 46, 9, 39, 55, 34,100, 81, @@ -17,16 +17,16 @@ int fuzz_random_x_offset[FUZZ_RANDOM_X_SIZE] = 65, 15, 97, 20, 67, 74, 98, 85, 60, 68, 19, 26, 8, 87, 86, 64, 11, 37, 31, 47, 25, 5, 50, 51, 23, 2, 93, 70, 40, 45 -}; +); -int fuzzoffset[FUZZTABLE] = -{ +int fuzzoffset[FUZZTABLE] = int[] +( 6, 11, 6, 11, 6, 6, 11, 6, 6, 11, 6, 6, 6, 11, 6, 6, 6, 11, 15, 18, 21, 6, 11, 15, 6, 6, 6, 6, 11, 6, 11, 6, 6, 11, 15, 6, 6, 11, 15, 18, 21, 6, 6, 6, 6, 11, 6, 6, 11, 6 -}; +); vec4 ProcessTexel() { diff --git a/wadsrc/static/sprites/rsmka0.png b/wadsrc/static/sprites/rsmka0.png new file mode 100644 index 0000000000..8387c22445 Binary files /dev/null and b/wadsrc/static/sprites/rsmka0.png differ diff --git a/wadsrc/static/sprites/rsmkb0.png b/wadsrc/static/sprites/rsmkb0.png new file mode 100644 index 0000000000..7417f79823 Binary files /dev/null and b/wadsrc/static/sprites/rsmkb0.png differ diff --git a/wadsrc/static/sprites/rsmkc0.png b/wadsrc/static/sprites/rsmkc0.png new file mode 100644 index 0000000000..d1ec180687 Binary files /dev/null and b/wadsrc/static/sprites/rsmkc0.png differ diff --git a/wadsrc/static/sprites/rsmkd0.png b/wadsrc/static/sprites/rsmkd0.png new file mode 100644 index 0000000000..08d3c95e53 Binary files /dev/null and b/wadsrc/static/sprites/rsmkd0.png differ diff --git a/wadsrc/static/sprites/rsmke0.png b/wadsrc/static/sprites/rsmke0.png new file mode 100644 index 0000000000..ab4ddb55ad Binary files /dev/null and b/wadsrc/static/sprites/rsmke0.png differ diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index bef1751da8..5d30435b59 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -524,7 +524,7 @@ struct TraceResults native native vector3 Crossed3DWaterPos; } -class Tracer : Object native +class LineTracer : Object native { native @TraceResults Results; native bool Trace(vector3 start, Sector sec, vector3 direction, double maxDist, ETraceFlags traceFlags); @@ -591,6 +591,10 @@ struct LevelLocals native native readonly int maptype; native readonly String Music; native readonly int musicorder; + native readonly TextureID skytexture1; + native readonly TextureID skytexture2; + native float skyspeed1; + native float skyspeed2; native int total_secrets; native int found_secrets; native int total_items; @@ -640,7 +644,9 @@ struct LevelLocals native native static clearscope vector3 Vec3Diff(vector3 v1, vector3 v2); native String GetChecksum() const; - + + native void ChangeSky( TextureID sky1, TextureID sky2 ); + String TimeFormatted(bool totals = false) { int sec = Thinker.Tics2Seconds(totals? totaltime : time); diff --git a/wadsrc/static/zscript/inventory/weapons.txt b/wadsrc/static/zscript/inventory/weapons.txt index f837bf4e54..4786e44d7a 100644 --- a/wadsrc/static/zscript/inventory/weapons.txt +++ b/wadsrc/static/zscript/inventory/weapons.txt @@ -78,8 +78,8 @@ class Weapon : StateProvider native Stop; } - native bool CheckAmmo(int fireMode, bool autoSwitch, bool requireAmmo = false, int ammocount = -1); - native bool DepleteAmmo(bool altFire, bool checkEnough = true, int ammouse = -1); + native virtual bool CheckAmmo(int fireMode, bool autoSwitch, bool requireAmmo = false, int ammocount = -1); + native virtual bool DepleteAmmo(bool altFire, bool checkEnough = true, int ammouse = -1); virtual State GetReadyState () { diff --git a/wadsrc/static/zscript/menu/optionmenuitems.txt b/wadsrc/static/zscript/menu/optionmenuitems.txt index 4668ea0681..00fe4893cc 100644 --- a/wadsrc/static/zscript/menu/optionmenuitems.txt +++ b/wadsrc/static/zscript/menu/optionmenuitems.txt @@ -128,16 +128,18 @@ class OptionMenuItemCommand : OptionMenuItemSubmenu { private String ccmd; // do not allow access to this from the outside. bool mCloseOnSelect; + private bool mUnsafe; OptionMenuItemCommand Init(String label, Name command, bool centered = false, bool closeonselect = false) { Super.Init(label, command, 0, centered); ccmd = command; mCloseOnSelect = closeonselect; + mUnsafe = true; return self; } - private native static void DoCommand(String cmd); // This is very intentionally limited to this menu item to prevent abuse. + private native static void DoCommand(String cmd, bool unsafe); // This is very intentionally limited to this menu item to prevent abuse. override bool Activate() { @@ -151,7 +153,7 @@ class OptionMenuItemCommand : OptionMenuItemSubmenu if (m.GetItem(mAction) != self) return false; } Menu.MenuSound("menu/choose"); - DoCommand(ccmd); + DoCommand(ccmd, mUnsafe); if (mCloseOnSelect) { let curmenu = Menu.GetCurrentMenu(); diff --git a/wadsrc/static/zscript/shared/player.txt b/wadsrc/static/zscript/shared/player.txt index d43a59ce27..8ecce11cb2 100644 --- a/wadsrc/static/zscript/shared/player.txt +++ b/wadsrc/static/zscript/shared/player.txt @@ -528,7 +528,7 @@ class PlayerPawn : Actor native if (level.time >= player.respawn_time || ((player.cmd.buttons & BT_USE) && player.Bot == NULL)) { player.cls = NULL; // Force a new class if the player is using a random class - player.playerstate = (multiplayer || (level.AllowRespawn) || sv_singleplayerrespawn)? PST_REBORN : PST_ENTER; + player.playerstate = (multiplayer || level.AllowRespawn || sv_singleplayerrespawn || G_SkillPropertyInt(SKILLP_PlayerRespawn)) ? PST_REBORN : PST_ENTER; if (special1 > 2) { special1 = 0; diff --git a/wadsrc_extra/static/sprites/rsmka0.png b/wadsrc_extra/static/sprites/rsmka0.png deleted file mode 100644 index 761e091709..0000000000 Binary files a/wadsrc_extra/static/sprites/rsmka0.png and /dev/null differ diff --git a/wadsrc_extra/static/sprites/rsmkb0.png b/wadsrc_extra/static/sprites/rsmkb0.png deleted file mode 100644 index 0bcfef43da..0000000000 Binary files a/wadsrc_extra/static/sprites/rsmkb0.png and /dev/null differ diff --git a/wadsrc_extra/static/sprites/rsmkc0.png b/wadsrc_extra/static/sprites/rsmkc0.png deleted file mode 100644 index 3e952cdba9..0000000000 Binary files a/wadsrc_extra/static/sprites/rsmkc0.png and /dev/null differ diff --git a/wadsrc_extra/static/sprites/rsmkd0.png b/wadsrc_extra/static/sprites/rsmkd0.png deleted file mode 100644 index 60827b6dcb..0000000000 Binary files a/wadsrc_extra/static/sprites/rsmkd0.png and /dev/null differ diff --git a/wadsrc_extra/static/sprites/rsmke0.png b/wadsrc_extra/static/sprites/rsmke0.png deleted file mode 100644 index 9d5652bd25..0000000000 Binary files a/wadsrc_extra/static/sprites/rsmke0.png and /dev/null differ