Merge branch 'gzdoom' into materials

This commit is contained in:
Magnus Norddahl 2018-02-10 00:08:17 +01:00
commit 94fbcacf22
53 changed files with 419 additions and 122 deletions

22
README.md Normal file
View file

@ -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.

View file

@ -283,6 +283,7 @@ Note: All <bool> fields default to false unless mentioned otherwise.
For things with ACS specials (80-86 and 226), if arg0str is present and non-null, it 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. 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 1.28 28.01.2017
sector material colors. sector material colors.
1.29 04.02.2018
arg0str in dynamic lights.
=============================================================================== ===============================================================================
EOF EOF
=============================================================================== ===============================================================================

View file

@ -511,7 +511,7 @@ set( PLAT_SDL_SOURCES
posix/sdl/st_start.cpp ) posix/sdl/st_start.cpp )
set( PLAT_UNIX_SOURCES set( PLAT_UNIX_SOURCES
posix/unix/i_specialpaths.cpp posix/unix/i_specialpaths.cpp
posix/unix/iwadpicker_gtk.cpp ) posix/unix/gtk_dialogs.cpp )
set( PLAT_OSX_SOURCES set( PLAT_OSX_SOURCES
posix/osx/iwadpicker_cocoa.mm posix/osx/iwadpicker_cocoa.mm
posix/osx/i_specialpaths.mm posix/osx/i_specialpaths.mm

View file

@ -681,7 +681,7 @@ UNSAFE_CCMD (crashout)
#endif #endif
CCMD (dir) UNSAFE_CCMD (dir)
{ {
FString dir, path; FString dir, path;
char curdir[256]; char curdir[256];

View file

@ -53,6 +53,7 @@
#include "colormatcher.h" #include "colormatcher.h"
#include "menu/menu.h" #include "menu/menu.h"
#include "vm.h" #include "vm.h"
#include "v_text.h"
struct FLatchedValue struct FLatchedValue
{ {
@ -1706,6 +1707,16 @@ void C_ArchiveCVars (FConfigFile *f, uint32_t filter)
EXTERN_CVAR(Bool, sv_cheats); 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) void FBaseCVar::CmdSet (const char *newval)
{ {
if ((GetFlags() & CVAR_CHEAT) && !sv_cheats) 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"); Printf("sv_cheats must be true to set this console variable.\n");
return; return;
} }
else if (IsUnsafe(this))
{
return;
}
UCVarValue val; UCVarValue val;
@ -1799,6 +1814,11 @@ CCMD (toggle)
{ {
if ( (var = FindCVar (argv[1], &prev)) ) if ( (var = FindCVar (argv[1], &prev)) )
{ {
if (IsUnsafe(var))
{
return;
}
val = var->GetGenericRep (CVAR_Bool); val = var->GetGenericRep (CVAR_Bool);
val.Bool = !val.Bool; val.Bool = !val.Bool;
var->SetGenericRep (val, CVAR_Bool); var->SetGenericRep (val, CVAR_Bool);

View file

@ -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_PanLeft, Button_AM_PanRight, Button_AM_PanDown, Button_AM_PanUp,
Button_AM_ZoomIn, Button_AM_ZoomOut; Button_AM_ZoomIn, Button_AM_ZoomOut;
bool ParsingKeyConf; bool ParsingKeyConf, UnsafeExecutionContext;
static bool 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 <action name>". // To add new actions, go to the console and type "key <action name>".
// This will give you the key value to use in the first column. Then // This will give you the key value to use in the first column. Then
@ -227,10 +243,8 @@ void DWaitingCommand::Tick ()
{ {
if (--TicsLeft == 0) if (--TicsLeft == 0)
{ {
const bool wasUnsafe = UnsafeExecutionContext; UnsafeExecutionScope scope;
UnsafeExecutionContext = IsUnsafe;
AddCommandString (Command); AddCommandString (Command);
UnsafeExecutionContext = wasUnsafe;
Destroy (); Destroy ();
} }
} }
@ -658,12 +672,6 @@ void C_DoCommand (const char *cmd, int keynum)
if (args.argc() >= 2) if (args.argc() >= 2)
{ // Set the variable { // 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]); var->CmdSet (args[1]);
} }
else else
@ -684,9 +692,9 @@ DEFINE_ACTION_FUNCTION(DOptionMenuItemCommand, DoCommand)
if (CurrentMenu == nullptr) return 0; if (CurrentMenu == nullptr) return 0;
PARAM_PROLOGUE; PARAM_PROLOGUE;
PARAM_STRING(cmd); PARAM_STRING(cmd);
UnsafeExecutionContext = true; PARAM_BOOL(unsafe);
UnsafeExecutionScope scope(unsafe);
C_DoCommand(cmd); C_DoCommand(cmd);
UnsafeExecutionContext = false;
return 0; return 0;
} }
@ -1515,9 +1523,8 @@ void FConsoleAlias::SafeDelete ()
void FUnsafeConsoleAlias::Run (FCommandLine &args, APlayerPawn *instigator, int key) void FUnsafeConsoleAlias::Run (FCommandLine &args, APlayerPawn *instigator, int key)
{ {
UnsafeExecutionContext = true; UnsafeExecutionScope scope;
FConsoleAlias::Run(args, instigator, key); FConsoleAlias::Run(args, instigator, key);
UnsafeExecutionContext = false;
} }
void FExecList::AddCommand(const char *cmd, const char *file) void FExecList::AddCommand(const char *cmd, const char *file)

View file

@ -200,7 +200,7 @@ extern FButtonStatus Button_Mlook, Button_Klook, Button_Use, Button_AltAttack,
Button_User1, Button_User2, Button_User3, Button_User4, Button_User1, Button_User2, Button_User3, Button_User4,
Button_AM_PanLeft, Button_AM_PanRight, Button_AM_PanDown, Button_AM_PanUp, Button_AM_PanLeft, Button_AM_PanRight, Button_AM_PanDown, Button_AM_PanUp,
Button_AM_ZoomIn, Button_AM_ZoomOut; Button_AM_ZoomIn, Button_AM_ZoomOut;
extern bool ParsingKeyConf; extern bool ParsingKeyConf, UnsafeExecutionContext;
void ResetButtonTriggers (); // Call ResetTriggers for all buttons void ResetButtonTriggers (); // Call ResetTriggers for all buttons
void ResetButtonStates (); // Same as above, but also clear bDown void ResetButtonStates (); // Same as above, but also clear bDown

View file

@ -280,7 +280,7 @@ void PClass::StaticShutdown ()
// This must be done in two steps because the native classes are not ordered by inheritance, // 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. // 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; 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. // Unless something went wrong, anything left here should be class and type objects only, which do not own any scripts.
bShutdown = true; bShutdown = true;

View file

@ -2599,7 +2599,7 @@ void G_DeferedPlayDemo (const char *name)
gameaction = (gameaction == ga_loadgame) ? ga_loadgameplaydemo : ga_playdemo; gameaction = (gameaction == ga_loadgame) ? ga_loadgameplaydemo : ga_playdemo;
} }
CCMD (playdemo) UNSAFE_CCMD (playdemo)
{ {
if (netgame) if (netgame)
{ {

View file

@ -221,6 +221,20 @@ 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 altFire;
int count1, count2; int count1, count2;
@ -293,7 +307,7 @@ DEFINE_ACTION_FUNCTION(AWeapon, CheckAmmo)
PARAM_BOOL(autoswitch); PARAM_BOOL(autoswitch);
PARAM_BOOL_DEF(require); PARAM_BOOL_DEF(require);
PARAM_INT_DEF(ammocnt); PARAM_INT_DEF(ammocnt);
ACTION_RETURN_BOOL(self->CheckAmmo(mode, autoswitch, require, ammocnt)); ACTION_RETURN_BOOL(self->DoCheckAmmo(mode, autoswitch, require, ammocnt));
} }
//=========================================================================== //===========================================================================
@ -307,6 +321,20 @@ 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))) 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(altfire);
PARAM_BOOL_DEF(checkenough); PARAM_BOOL_DEF(checkenough);
PARAM_INT_DEF(ammouse); PARAM_INT_DEF(ammouse);
ACTION_RETURN_BOOL(self->DepleteAmmo(altfire, checkenough, ammouse)); ACTION_RETURN_BOOL(self->DoDepleteAmmo(altfire, checkenough, ammouse));
} }

View file

@ -142,7 +142,9 @@ public:
EitherFire EitherFire
}; };
bool CheckAmmo (int fireMode, bool autoSwitch, bool requireAmmo=false, int ammocount = -1); 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 DepleteAmmo (bool altFire, bool checkEnough=true, int ammouse = -1);
bool DoDepleteAmmo(bool altFire, bool checkEnough, int ammouse);
enum enum
{ {

View file

@ -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 // If this is co-op, respawn any dead players now so they can
// keep their inventory on the next map. // 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 [[ // Copied from the end of P_DeathThink [[
player->cls = NULL; // Force a new class if the player is using a random class 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, maptype)
DEFINE_FIELD(FLevelLocals, Music) DEFINE_FIELD(FLevelLocals, Music)
DEFINE_FIELD(FLevelLocals, musicorder) 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, total_secrets)
DEFINE_FIELD(FLevelLocals, found_secrets) DEFINE_FIELD(FLevelLocals, found_secrets)
DEFINE_FIELD(FLevelLocals, total_items) 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;
}

View file

@ -289,7 +289,7 @@ void GLWall::DrawDecal(DBaseDecal *decal)
// Note: This should be replaced with proper shader based lighting. // Note: This should be replaced with proper shader based lighting.
double x, y; double x, y;
decal->GetXY(seg->sidedef, 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. // alpha color only has an effect when using an alpha texture.

View file

@ -842,7 +842,7 @@ sector_t * GLSceneDrawer::RenderViewpoint (AActor * camera, GL_IRECT * bounds, f
stereo3dMode.SetUp(); stereo3dMode.SetUp();
for (int eye_ix = 0; eye_ix < stereo3dMode.eye_count(); ++eye_ix) 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 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); const s3d::EyePose * eye = stereo3dMode.getEyePose(eye_ix);
eye->SetUp(); eye->SetUp();

View file

@ -987,9 +987,8 @@ void GLSprite::Process(AActor* thing, sector_t * sector, int thruportal)
RenderStyle.CheckFuzz(); RenderStyle.CheckFuzz();
if (RenderStyle.BlendOp == STYLEOP_Fuzz) 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]; RenderStyle = LegacyRenderStyles[STYLE_Translucent];
OverrideShader = SHADER_NoTexture + gl_fuzztype; OverrideShader = SHADER_NoTexture + gl_fuzztype;
trans = 0.99f; // trans may not be 1 here trans = 0.99f; // trans may not be 1 here

View file

@ -74,7 +74,7 @@ void gl_SetDynSpriteLight(AActor *self, float x, float y, float z, subsector_t *
while (node) while (node)
{ {
light=node->lightsource; 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; float dist;
FVector3 L; FVector3 L;

View file

@ -32,6 +32,7 @@
#include "gl/stereo3d/gl_sidebyside3d.h" #include "gl/stereo3d/gl_sidebyside3d.h"
#include "gl/stereo3d/gl_interleaved3d.h" #include "gl/stereo3d/gl_interleaved3d.h"
#include "gl/system/gl_cvars.h" #include "gl/system/gl_cvars.h"
#include "version.h"
// Set up 3D-specific console variables: // Set up 3D-specific console variables:
CVAR(Int, vr_mode, 0, CVAR_GLOBALCONFIG) 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. // 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, // 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 // 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 // intraocular distance in meters
CVAR(Float, vr_ipd, 0.062f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) // METERS CVAR(Float, vr_ipd, 0.062f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) // METERS

View file

@ -673,7 +673,7 @@ void M_ScreenShot (const char *filename)
} }
} }
CCMD (screenshot) UNSAFE_CCMD (screenshot)
{ {
if (argv.argc() == 1) if (argv.argc() == 1)
G_ScreenShot (NULL); G_ScreenShot (NULL);

View file

@ -58,6 +58,7 @@
#include "vm.h" #include "vm.h"
#include "events.h" #include "events.h"
#include "gl/renderer/gl_renderer.h" // for menu blur #include "gl/renderer/gl_renderer.h" // for menu blur
#include "scripting/types.h"
// //
// Todo: Move these elsewhere // Todo: Move these elsewhere
@ -1180,6 +1181,8 @@ DMenuItemBase * CreateOptionMenuItemCommand(const char *label, FName cmd, bool c
VMValue params[] = { p, &namestr, cmd.GetIndex(), centered }; VMValue params[] = { p, &namestr, cmd.GetIndex(), centered };
auto f = dyn_cast<PFunction>(c->FindSymbol("Init", false)); auto f = dyn_cast<PFunction>(c->FindSymbol("Init", false));
VMCall(f->Variants[0].Implementation, params, countof(params), nullptr, 0); VMCall(f->Variants[0].Implementation, params, countof(params), nullptr, 0);
auto unsafe = dyn_cast<PField>(c->FindSymbol("mUnsafe", false));
unsafe->Type->SetValue(reinterpret_cast<uint8_t*>(p) + unsafe->Offset, 0);
return (DMenuItemBase*)p; return (DMenuItemBase*)p;
} }

View file

@ -835,12 +835,12 @@ inline int uallong(const int &foo)
//============================================================================ //============================================================================
// ACS variables with world scope // ACS variables with world scope
int32_t ACS_WorldVars[NUM_WORLDVARS]; static BoundsCheckingArray<int32_t, NUM_WORLDVARS> ACS_WorldVars;
FWorldGlobalArray ACS_WorldArrays[NUM_WORLDVARS]; static BoundsCheckingArray<FWorldGlobalArray, NUM_WORLDVARS> ACS_WorldArrays;
// ACS variables with global scope // ACS variables with global scope
int32_t ACS_GlobalVars[NUM_GLOBALVARS]; BoundsCheckingArray<int32_t, NUM_GLOBALVARS> ACS_GlobalVars;
FWorldGlobalArray ACS_GlobalArrays[NUM_GLOBALVARS]; BoundsCheckingArray<FWorldGlobalArray, NUM_GLOBALVARS> ACS_GlobalArrays;
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// //
@ -851,21 +851,7 @@ FWorldGlobalArray ACS_GlobalArrays[NUM_GLOBALVARS];
// //
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
struct FACSStackMemory using FACSStackMemory = BoundsCheckingArray<int32_t, STACK_SIZE>;
{
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];
};
struct FACSStack struct FACSStack
{ {
@ -1470,10 +1456,10 @@ void ACSStringPool::UnlockForLevel(int lnum)
void P_MarkWorldVarStrings() void P_MarkWorldVarStrings()
{ {
GlobalACSStrings.MarkStringArray(ACS_WorldVars, countof(ACS_WorldVars)); GlobalACSStrings.MarkStringArray(ACS_WorldVars.Pointer(), ACS_WorldVars.Size());
for (size_t i = 0; i < countof(ACS_WorldArrays); ++i) 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() void P_MarkGlobalVarStrings()
{ {
GlobalACSStrings.MarkStringArray(ACS_GlobalVars, countof(ACS_GlobalVars)); GlobalACSStrings.MarkStringArray(ACS_GlobalVars.Pointer(), ACS_GlobalVars.Size());
for (size_t i = 0; i < countof(ACS_GlobalArrays); ++i) 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; int i;
memset (ACS_WorldVars, 0, sizeof(ACS_WorldVars)); ACS_WorldVars.Fill(0);
for (i = 0; i < NUM_WORLDVARS; ++i) for (i = 0; i < NUM_WORLDVARS; ++i)
{ {
ACS_WorldArrays[i].Clear (); ACS_WorldArrays[i].Clear ();
} }
if (alsoglobal) if (alsoglobal)
{ {
memset (ACS_GlobalVars, 0, sizeof(ACS_GlobalVars)); ACS_GlobalVars.Fill(0);
for (i = 0; i < NUM_GLOBALVARS; ++i) for (i = 0; i < NUM_GLOBALVARS; ++i)
{ {
ACS_GlobalArrays[i].Clear (); ACS_GlobalArrays[i].Clear ();
@ -1726,10 +1712,10 @@ static void ReadArrayVars (FSerializer &file, FWorldGlobalArray *vars, size_t co
void P_ReadACSVars(FSerializer &arc) void P_ReadACSVars(FSerializer &arc)
{ {
ReadVars (arc, ACS_WorldVars, NUM_WORLDVARS, "acsworldvars"); ReadVars (arc, ACS_WorldVars.Pointer(), NUM_WORLDVARS, "acsworldvars");
ReadVars (arc, ACS_GlobalVars, NUM_GLOBALVARS, "acsglobalvars"); ReadVars (arc, ACS_GlobalVars.Pointer(), NUM_GLOBALVARS, "acsglobalvars");
ReadArrayVars (arc, ACS_WorldArrays, NUM_WORLDVARS, "acsworldarrays"); ReadArrayVars (arc, ACS_WorldArrays.Pointer(), NUM_WORLDVARS, "acsworldarrays");
ReadArrayVars (arc, ACS_GlobalArrays, NUM_GLOBALVARS, "acsglobalarrays"); ReadArrayVars (arc, ACS_GlobalArrays.Pointer(), NUM_GLOBALVARS, "acsglobalarrays");
GlobalACSStrings.ReadStrings(arc, "acsglobalstrings"); GlobalACSStrings.ReadStrings(arc, "acsglobalstrings");
} }
@ -1741,10 +1727,10 @@ void P_ReadACSVars(FSerializer &arc)
void P_WriteACSVars(FSerializer &arc) void P_WriteACSVars(FSerializer &arc)
{ {
WriteVars (arc, ACS_WorldVars, NUM_WORLDVARS, "acsworldvars"); WriteVars (arc, ACS_WorldVars.Pointer(), NUM_WORLDVARS, "acsworldvars");
WriteVars (arc, ACS_GlobalVars, NUM_GLOBALVARS, "acsglobalvars"); WriteVars (arc, ACS_GlobalVars.Pointer(), NUM_GLOBALVARS, "acsglobalvars");
WriteArrayVars (arc, ACS_WorldArrays, NUM_WORLDVARS, "acsworldarrays"); WriteArrayVars (arc, ACS_WorldArrays.Pointer(), NUM_WORLDVARS, "acsworldarrays");
WriteArrayVars (arc, ACS_GlobalArrays, NUM_GLOBALVARS, "acsglobalarrays"); WriteArrayVars (arc, ACS_GlobalArrays.Pointer(), NUM_GLOBALVARS, "acsglobalarrays");
GlobalACSStrings.WriteStrings(arc, "acsglobalstrings"); GlobalACSStrings.WriteStrings(arc, "acsglobalstrings");
} }
@ -9852,7 +9838,7 @@ scriptwait:
if (STACK(2) != 0) if (STACK(2) != 0)
{ {
AActor *marine; AActor *marine;
NActorIterator iterator("ScriptedMarine", STACK(2)); NActorIterator iterator(NAME_ScriptedMarine, STACK(2));
while ((marine = iterator.Next()) != NULL) while ((marine = iterator.Next()) != NULL)
{ {
@ -9861,7 +9847,7 @@ scriptwait:
} }
else else
{ {
if (activator != nullptr && activator->IsKindOf (PClass::FindClass("ScriptedMarine"))) if (activator != nullptr && activator->IsKindOf (NAME_ScriptedMarine))
{ {
SetMarineWeapon(activator, STACK(1)); SetMarineWeapon(activator, STACK(1));
} }
@ -9878,7 +9864,7 @@ scriptwait:
if (STACK(2) != 0) if (STACK(2) != 0)
{ {
AActor *marine; AActor *marine;
NActorIterator iterator("ScriptedMarine", STACK(2)); NActorIterator iterator(NAME_ScriptedMarine, STACK(2));
while ((marine = iterator.Next()) != NULL) while ((marine = iterator.Next()) != NULL)
{ {
@ -9887,7 +9873,7 @@ scriptwait:
} }
else else
{ {
if (activator != nullptr && activator->IsKindOf("ScriptedMarine")) if (activator != nullptr && activator->IsKindOf(NAME_ScriptedMarine))
{ {
SetMarineSprite(activator, type); SetMarineSprite(activator, type);
} }

View file

@ -60,13 +60,32 @@ struct InitIntToZero
}; };
typedef TMap<int32_t, int32_t, THashTraits<int32_t>, InitIntToZero> FWorldGlobalArray; typedef TMap<int32_t, int32_t, THashTraits<int32_t>, InitIntToZero> FWorldGlobalArray;
// ACS variables with world scope // Type of elements count is unsigned int instead of size_t to match ACSStringPool interface
extern int32_t ACS_WorldVars[NUM_WORLDVARS]; template <typename T, unsigned int N>
extern FWorldGlobalArray ACS_WorldArrays[NUM_WORLDVARS]; 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 // ACS variables with global scope
extern int32_t ACS_GlobalVars[NUM_GLOBALVARS]; extern BoundsCheckingArray<int32_t, NUM_GLOBALVARS> ACS_GlobalVars;
extern FWorldGlobalArray ACS_GlobalArrays[NUM_GLOBALVARS]; extern BoundsCheckingArray<FWorldGlobalArray, NUM_GLOBALVARS> ACS_GlobalArrays;
#define LIBRARYID_MASK 0xFFF00000 #define LIBRARYID_MASK 0xFFF00000
#define LIBRARYID_SHIFT 20 #define LIBRARYID_SHIFT 20
@ -359,7 +378,7 @@ public:
ACSProfileInfo *GetFunctionProfileData(ScriptFunction *func) { return GetFunctionProfileData((int)(func - (ScriptFunction *)Functions)); } ACSProfileInfo *GetFunctionProfileData(ScriptFunction *func) { return GetFunctionProfileData((int)(func - (ScriptFunction *)Functions)); }
const char *LookupString (uint32_t index) const; const char *LookupString (uint32_t index) const;
int32_t *MapVars[NUM_MAPVARS]; BoundsCheckingArray<int32_t *, NUM_MAPVARS> MapVars;
static FBehavior *StaticLoadModule (int lumpnum, FileReader * fr=NULL, int len=0); static FBehavior *StaticLoadModule (int lumpnum, FileReader * fr=NULL, int len=0);
static void StaticLoadDefaultModules (); static void StaticLoadDefaultModules ();

View file

@ -1216,7 +1216,7 @@ errorout:
return false; return false;
} }
CCMD(clearnodecache) UNSAFE_CCMD(clearnodecache)
{ {
TArray<FFileList> list; TArray<FFileList> list;
FString path = M_GetCachePath(false); FString path = M_GetCachePath(false);

View file

@ -809,11 +809,13 @@ bool FMultiBlockLinesIterator::GoUp(double x, double y)
{ {
if (!cursector->PortalBlocksMovement(sector_t::ceiling)) if (!cursector->PortalBlocksMovement(sector_t::ceiling))
{ {
startIteratorForGroup(cursector->GetOppositePortalGroup(sector_t::ceiling)); if (startIteratorForGroup(cursector->GetOppositePortalGroup(sector_t::ceiling)))
{
portalflags = FFCF_NOFLOOR; portalflags = FFCF_NOFLOOR;
return true; return true;
} }
else continueup = false; }
continueup = false;
} }
return false; return false;
} }
@ -830,11 +832,13 @@ bool FMultiBlockLinesIterator::GoDown(double x, double y)
{ {
if (!cursector->PortalBlocksMovement(sector_t::floor)) if (!cursector->PortalBlocksMovement(sector_t::floor))
{ {
startIteratorForGroup(cursector->GetOppositePortalGroup(sector_t::floor)); if (startIteratorForGroup(cursector->GetOppositePortalGroup(sector_t::floor)))
{
portalflags = FFCF_NOCEILING; portalflags = FFCF_NOCEILING;
return true; return true;
} }
else continuedown = false; }
continuedown = false;
} }
return 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 = Displacements.getOffset(basegroup, group);
offset.X += checkpoint.X; offset.X += checkpoint.X;
offset.Y += checkpoint.Y; offset.Y += checkpoint.Y;
cursector = group == startsector->PortalGroup ? startsector : P_PointInSector(offset); 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); bbox.setBox(offset.X, offset.Y, checkpoint.Z);
blockIterator.init(bbox); blockIterator.init(bbox);
return true;
} }
//=========================================================================== //===========================================================================

View file

@ -240,7 +240,7 @@ class FMultiBlockLinesIterator
bool GoUp(double x, double y); bool GoUp(double x, double y);
bool GoDown(double x, double y); bool GoDown(double x, double y);
void startIteratorForGroup(int group); bool startIteratorForGroup(int group);
public: public:

View file

@ -6101,6 +6101,9 @@ AActor *P_SpawnMapThing (FMapThing *mthing, int position)
if (mthing->arg0str != NAME_None) if (mthing->arg0str != NAME_None)
{ {
PalEntry color = V_GetColor(nullptr, mthing->arg0str); 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) else if (light->lightflags & LF_SPOT)
{ {
@ -7766,7 +7769,13 @@ FState *AActor::GetRaiseState()
void AActor::Revive() void AActor::Revive()
{ {
AActor *info = GetDefault(); 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; flags = info->flags;
if (flagchange) LinkToWorld(&ctx);
flags2 = info->flags2; flags2 = info->flags2;
flags3 = info->flags3; flags3 = info->flags3;
flags4 = info->flags4; flags4 = info->flags4;

View file

@ -1659,7 +1659,7 @@ DEFINE_ACTION_FUNCTION(_Sector, NextLowestFloorAt)
PARAM_SELF_STRUCT_PROLOGUE(sector_t); PARAM_SELF_STRUCT_PROLOGUE(sector_t);
PARAM_INT(pos); PARAM_INT(pos);
PARAM_FLOAT(o); PARAM_FLOAT(o);
self->SetXScale(pos, o); self->SetYScale(pos, o);
return 0; return 0;
} }

View file

@ -955,8 +955,8 @@ static bool EditTraceResult (uint32_t flags, FTraceResults &res)
// [ZZ] here go the methods for the ZScript interface // [ZZ] here go the methods for the ZScript interface
// //
//========================================================================== //==========================================================================
IMPLEMENT_CLASS(DTracer, false, false) IMPLEMENT_CLASS(DLineTracer, false, false)
DEFINE_FIELD_X(Tracer, DTracer, Results) DEFINE_FIELD(DLineTracer, Results)
// define TraceResults fields // define TraceResults fields
DEFINE_FIELD_NAMED_X(TraceResults, FTraceResults, Sector, HitSector) 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, Crossed3DWater)
DEFINE_FIELD_X(TraceResults, FTraceResults, Crossed3DWaterPos) 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, /*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, ActorFlags ActorMask, uint32_t WallMask, AActor *ignore, FTraceResults &res, uint32_t traceFlags = 0,
ETraceStatus(*callback)(FTraceResults &res, void *) = NULL, void *callbackdata = NULL);*/ 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) // 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, 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); 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. // "res" here should refer to self->Results anyway.
// patch results a bit. modders don't expect it to work like this most likely. // 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(); return self->CallZScriptCallback();
} }
ETraceStatus DTracer::CallZScriptCallback() ETraceStatus DLineTracer::CallZScriptCallback()
{ {
IFVIRTUAL(DTracer, TraceCallback) IFVIRTUAL(DLineTracer, TraceCallback)
{ {
int status; int status;
VMReturn results[1] = { &status }; VMReturn results[1] = { &status };
VMValue params[1] = { (DTracer*)this }; VMValue params[1] = { (DLineTracer*)this };
VMCall(func, params, 1, results, 1); VMCall(func, params, 1, results, 1);
return (ETraceStatus)status; return (ETraceStatus)status;
} }

View file

@ -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); ETraceStatus(*callback)(FTraceResults &res, void *) = NULL, void *callbackdata = NULL);
// [ZZ] this is the object that's used for ZScript // [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: public:
FTraceResults Results; FTraceResults Results;
static ETraceStatus TraceCallback(FTraceResults& res, void* pthis); static ETraceStatus TraceCallback(FTraceResults& res, void* pthis);

View file

@ -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); void Mac_I_FatalError(const char* errortext);
#endif #endif
#ifdef __linux__
void Linux_I_FatalError(const char* errortext);
#endif
// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
@ -268,6 +272,10 @@ int main (int argc, char **argv)
Mac_I_FatalError(error.GetMessage()); Mac_I_FatalError(error.GetMessage());
#endif // __APPLE__ #endif // __APPLE__
#ifdef __linux__
Linux_I_FatalError(error.GetMessage());
#endif // __linux__
exit (-1); exit (-1);
} }
catch (...) catch (...)

View file

@ -79,6 +79,7 @@ extern "C"
#ifndef NO_GTK #ifndef NO_GTK
bool I_GtkAvailable (); bool I_GtkAvailable ();
int I_PickIWad_Gtk (WadStuff *wads, int numwads, bool showwin, int defaultiwad); int I_PickIWad_Gtk (WadStuff *wads, int numwads, bool showwin, int defaultiwad);
void I_FatalError_Gtk(const char* errortext);
#elif defined(__APPLE__) #elif defined(__APPLE__)
int I_PickIWad_Cocoa (WadStuff *wads, int numwads, bool showwin, int defaultiwad); int I_PickIWad_Cocoa (WadStuff *wads, int numwads, bool showwin, int defaultiwad);
#endif #endif
@ -157,6 +158,37 @@ bool gameisdead;
void Mac_I_FatalError(const char* errortext); void Mac_I_FatalError(const char* errortext);
#endif #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, ...) void I_FatalError (const char *error, ...)
{ {
static bool alreadyThrown = false; static bool alreadyThrown = false;
@ -176,6 +208,10 @@ void I_FatalError (const char *error, ...)
Mac_I_FatalError(errortext); Mac_I_FatalError(errortext);
#endif // __APPLE__ #endif // __APPLE__
#ifdef __linux__
Linux_I_FatalError(errortext);
#endif
// Record error to log (if logging) // Record error to log (if logging)
if (Logfile) if (Logfile)
{ {

View file

@ -1,5 +1,5 @@
/* /*
** iwadpicker_gtk.cpp ** gtk_dialogs.cpp
** **
**--------------------------------------------------------------------------- **---------------------------------------------------------------------------
** Copyright 2008-2016 Braden Obrzut ** 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_gravity);
DYN_GTK_SYM(gtk_window_set_position); DYN_GTK_SYM(gtk_window_set_position);
DYN_GTK_SYM(gtk_window_set_title); 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 // Gtk3 Only
DYN_GTK_OPT3_SYM(gtk_box_new, GtkWidget *(*)(GtkOrientation, gint)); 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_button_box_new, GtkWidget *(*)(GtkOrientation));
DYN_GTK_OPT3_SYM(gtk_widget_set_halign, void(*)(GtkWidget *, GtkAlign)); 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_widget_set_valign, void(*)(GtkWidget *, GtkAlign));
DYN_GTK_OPT3_SYM(gtk_message_dialog_new, GtkWidget* (*)(GtkWindow*, GtkDialogFlags, GtkMessageType, GtkButtonsType, const gchar*, ...));
// Gtk2 Only // Gtk2 Only
DYN_GTK_OPT2_SYM(gtk_misc_get_type, GType(*)()); 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; 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 } // namespace Gtk
int I_PickIWad_Gtk (WadStuff *wads, int numwads, bool showwin, int defaultiwad) 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); return Gtk::PickIWad (wads, numwads, showwin, defaultiwad);
} }
void I_FatalError_Gtk(const char* errortext) {
Gtk::ShowError(errortext);
}
bool I_GtkAvailable() bool I_GtkAvailable()
{ {
using namespace Gtk; using namespace Gtk;

View file

@ -2999,7 +2999,7 @@ CCMD (cd_resume)
// //
//========================================================================== //==========================================================================
CCMD (playlist) UNSAFE_CCMD (playlist)
{ {
int argc = argv.argc(); int argc = argv.argc();

View file

@ -124,13 +124,13 @@ CUSTOM_CVAR(Float, fluid_gain, 0.5, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
currSong->FluidSettingNum("synth.gain", self); 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) if (currSong != NULL)
currSong->FluidSettingInt("synth.reverb.active", self); 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) if (currSong != NULL)
currSong->FluidSettingInt("synth.chorus.active", self); currSong->FluidSettingInt("synth.chorus.active", self);

View file

@ -1206,8 +1206,21 @@ DEFINE_ACTION_FUNCTION(_TexMan, GetName)
{ {
PARAM_PROLOGUE; PARAM_PROLOGUE;
PARAM_INT(texid); PARAM_INT(texid);
const FTexture* const tex = TexMan.ByIndex(texid); auto tex = TexMan.ByIndex(texid);
ACTION_RETURN_STRING(nullptr == tex ? FString() : tex->Name); 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);
} }
//========================================================================== //==========================================================================

View file

@ -376,6 +376,14 @@ F481922F4881F74760F3C0437FD5EDD0 // map03
setlinespecial 1008 Door_Open 0 64 0 0 0 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 1891E029994B023910CFE0B3209C3CDB // Ultimate Simplicity, map07
{ {
// It is possible to get stuck on skill 0 or 1 when no shots have been fired // 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 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 952CC8D03572E17BA550B01B366EFBB9 // Cheogsh map01
{ {
// make the blue key spawn above the 3D floor // make the blue key spawn above the 3D floor
@ -685,6 +700,10 @@ EBDAC00E9D25D884B2C8F4B1F0390539 // doom2.wad map21
setsectoroffset 50 ceil -56 setsectoroffset 50 ceil -56
setsectoroffset 54 ceil -56 setsectoroffset 54 ceil -56
} }
94893A0DC429A22ADC4B3A73DA537E16 // DOOM2.WAD map25
{
rebuildnodes
}
110F84DE041052B59307FAF0293E6BC0 // Doom II, map27 110F84DE041052B59307FAF0293E6BC0 // Doom II, map27
{ {
setsectorspecial 93 0 setsectorspecial 93 0
@ -844,3 +863,8 @@ CA3773ED313E8899311F3DD0CA195A68 // e3m6
setthingz 403 168 setthingz 403 168
setthingz 404 168 setthingz 404 168
} }
6D4156EE0D12B77AD143A37C4D3DCF98 // dmonfear.wad map22
{
shorttex
}

View file

@ -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

View file

@ -2729,7 +2729,7 @@ GLPREFMNU_AMBLIGHT = "Ambient light level";
GLPREFMNU_RENDERQUALITY = "Rendering quality"; GLPREFMNU_RENDERQUALITY = "Rendering quality";
GLPREFMNU_MENUBLUR = "Menu Blur"; GLPREFMNU_MENUBLUR = "Menu Blur";
GLPREFMNU_VRMODE = "Stereo 3D VR"; GLPREFMNU_VRMODE = "Stereo 3D VR";
GLPREFMNU_VRQUADSTEREO = "Enable Quad Stereo (Requires Restart)"; GLPREFMNU_VRQUADSTEREO = "Enable Quad Stereo";
GLPREFMNU_MULTISAMPLE = "Multisample"; GLPREFMNU_MULTISAMPLE = "Multisample";
GLPREFMNU_TONEMAP = "Tonemap Mode"; GLPREFMNU_TONEMAP = "Tonemap Mode";
GLPREFMNU_BLOOM = "Bloom effect"; GLPREFMNU_BLOOM = "Bloom effect";

View file

@ -118,7 +118,7 @@ DoomEdNums
9851 = SpotLightPulseAdditive 9851 = SpotLightPulseAdditive
9852 = SpotLightFlickerAdditive 9852 = SpotLightFlickerAdditive
9853 = SectorSpotLightAdditive 9853 = SectorSpotLightAdditive
9854 = SpotLightFlickerRandomSubtractive 9854 = SpotLightFlickerRandomAdditive
9860 = SpotLightSubtractive 9860 = SpotLightSubtractive
9861 = SpotLightPulseSubtractive 9861 = SpotLightPulseSubtractive
9862 = SpotLightFlickerSubtractive 9862 = SpotLightFlickerSubtractive

View file

@ -5,8 +5,8 @@
#define FRACBITS 16 #define FRACBITS 16
#define fixed_t int #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, 75, 76, 21, 91, 56, 33, 62, 99, 61, 79,
95, 54, 41, 18, 69, 43, 49, 59, 10, 84, 95, 54, 41, 18, 69, 43, 49, 59, 10, 84,
94, 17, 57, 46, 9, 39, 55, 34,100, 81, 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, 65, 15, 97, 20, 67, 74, 98, 85, 60, 68,
19, 26, 8, 87, 86, 64, 11, 37, 31, 47, 19, 26, 8, 87, 86, 64, 11, 37, 31, 47,
25, 5, 50, 51, 23, 2, 93, 70, 40, 45 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, 11, 6, 11, 6, 6, 11, 6, 6, 11,
6, 6, 6, 11, 6, 6, 6, 11, 15, 18, 6, 6, 6, 11, 6, 6, 6, 11, 15, 18,
21, 6, 11, 15, 6, 6, 6, 6, 11, 6, 21, 6, 11, 15, 6, 6, 6, 6, 11, 6,
11, 6, 6, 11, 15, 6, 6, 11, 15, 18, 11, 6, 6, 11, 15, 6, 6, 11, 15, 18,
21, 6, 6, 6, 6, 11, 6, 6, 11, 6 21, 6, 6, 6, 6, 11, 6, 6, 11, 6
}; );
vec4 ProcessTexel() vec4 ProcessTexel()
{ {

Binary file not shown.

After

Width:  |  Height:  |  Size: 992 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -524,7 +524,7 @@ struct TraceResults native
native vector3 Crossed3DWaterPos; native vector3 Crossed3DWaterPos;
} }
class Tracer : Object native class LineTracer : Object native
{ {
native @TraceResults Results; native @TraceResults Results;
native bool Trace(vector3 start, Sector sec, vector3 direction, double maxDist, ETraceFlags traceFlags); 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 int maptype;
native readonly String Music; native readonly String Music;
native readonly int musicorder; native readonly int musicorder;
native readonly TextureID skytexture1;
native readonly TextureID skytexture2;
native float skyspeed1;
native float skyspeed2;
native int total_secrets; native int total_secrets;
native int found_secrets; native int found_secrets;
native int total_items; native int total_items;
@ -641,6 +645,8 @@ struct LevelLocals native
native String GetChecksum() const; native String GetChecksum() const;
native void ChangeSky( TextureID sky1, TextureID sky2 );
String TimeFormatted(bool totals = false) String TimeFormatted(bool totals = false)
{ {
int sec = Thinker.Tics2Seconds(totals? totaltime : time); int sec = Thinker.Tics2Seconds(totals? totaltime : time);

View file

@ -78,8 +78,8 @@ class Weapon : StateProvider native
Stop; Stop;
} }
native bool CheckAmmo(int fireMode, bool autoSwitch, bool requireAmmo = false, int ammocount = -1); native virtual 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 DepleteAmmo(bool altFire, bool checkEnough = true, int ammouse = -1);
virtual State GetReadyState () virtual State GetReadyState ()
{ {

View file

@ -128,16 +128,18 @@ class OptionMenuItemCommand : OptionMenuItemSubmenu
{ {
private String ccmd; // do not allow access to this from the outside. private String ccmd; // do not allow access to this from the outside.
bool mCloseOnSelect; bool mCloseOnSelect;
private bool mUnsafe;
OptionMenuItemCommand Init(String label, Name command, bool centered = false, bool closeonselect = false) OptionMenuItemCommand Init(String label, Name command, bool centered = false, bool closeonselect = false)
{ {
Super.Init(label, command, 0, centered); Super.Init(label, command, 0, centered);
ccmd = command; ccmd = command;
mCloseOnSelect = closeonselect; mCloseOnSelect = closeonselect;
mUnsafe = true;
return self; 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() override bool Activate()
{ {
@ -151,7 +153,7 @@ class OptionMenuItemCommand : OptionMenuItemSubmenu
if (m.GetItem(mAction) != self) return false; if (m.GetItem(mAction) != self) return false;
} }
Menu.MenuSound("menu/choose"); Menu.MenuSound("menu/choose");
DoCommand(ccmd); DoCommand(ccmd, mUnsafe);
if (mCloseOnSelect) if (mCloseOnSelect)
{ {
let curmenu = Menu.GetCurrentMenu(); let curmenu = Menu.GetCurrentMenu();

View file

@ -528,7 +528,7 @@ class PlayerPawn : Actor native
if (level.time >= player.respawn_time || ((player.cmd.buttons & BT_USE) && player.Bot == NULL)) 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.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) if (special1 > 2)
{ {
special1 = 0; special1 = 0;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 376 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 388 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 550 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 380 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 255 B