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

View file

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

View file

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

View file

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

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_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 <action name>".
// 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)

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

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,
// 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;

View file

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

View file

@ -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));
}

View file

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

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
// 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;
}

View file

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

View file

@ -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();

View file

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

View file

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

View file

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

View file

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

View file

@ -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<PFunction>(c->FindSymbol("Init", false));
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;
}

View file

@ -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<int32_t, NUM_WORLDVARS> ACS_WorldVars;
static BoundsCheckingArray<FWorldGlobalArray, NUM_WORLDVARS> ACS_WorldArrays;
// ACS variables with global scope
int32_t ACS_GlobalVars[NUM_GLOBALVARS];
FWorldGlobalArray ACS_GlobalArrays[NUM_GLOBALVARS];
BoundsCheckingArray<int32_t, NUM_GLOBALVARS> ACS_GlobalVars;
BoundsCheckingArray<FWorldGlobalArray, NUM_GLOBALVARS> 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<int32_t, STACK_SIZE>;
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);
}

View file

@ -60,13 +60,32 @@ struct InitIntToZero
};
typedef TMap<int32_t, int32_t, THashTraits<int32_t>, 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 <typename T, unsigned int N>
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<int32_t, NUM_GLOBALVARS> ACS_GlobalVars;
extern BoundsCheckingArray<FWorldGlobalArray, NUM_GLOBALVARS> 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<int32_t *, NUM_MAPVARS> MapVars;
static FBehavior *StaticLoadModule (int lumpnum, FileReader * fr=NULL, int len=0);
static void StaticLoadDefaultModules ();

View file

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

View file

@ -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;
}
//===========================================================================

View file

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

View file

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

View file

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

View file

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

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);
// [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);

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);
#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 (...)

View file

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

View file

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

View file

@ -2999,7 +2999,7 @@ CCMD (cd_resume)
//
//==========================================================================
CCMD (playlist)
UNSAFE_CCMD (playlist)
{
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);
}
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);

View file

@ -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);
}
//==========================================================================