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

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

View File

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

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

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