Merge branch 'master' of https://github.com/ZDoom/gzdoom into GZDoomUpdate-12-07-2023
This commit is contained in:
commit
07f722b6f3
74 changed files with 773 additions and 294 deletions
|
|
@ -2361,6 +2361,11 @@ alias -creep "joy_speedmultiplier 1.0"</pre>
|
|||
of a music lump or file on disk (which need not have been specified with the
|
||||
-file parameter).
|
||||
</div>
|
||||
<div class="c" id="changeskill">changeskill <i>skill</i></div>
|
||||
<div class="b">Changes the current skill of the game. The skill change will take
|
||||
effect at the next map change. The skill must be a number. The default skill
|
||||
levels range from 0 to 4 inclusive.
|
||||
</div>
|
||||
<div class="c" id="chase">chase</div>
|
||||
<div class="b">Turns the chasecom on and off. This command also works while
|
||||
watching demos, so you can bind it to a key and watch demos in the third
|
||||
|
|
@ -3177,6 +3182,7 @@ alias -creep "joy_speedmultiplier 1.0"</pre>
|
|||
<a href="#centerview">centerview</a><br />
|
||||
<a href="#changemap">changemap</a><br />
|
||||
<a href="#changemus">changemus</a><br />
|
||||
<a href="#changeskill">changeskill</a><br />
|
||||
<a href="#chase">chase</a><br />
|
||||
<a href="#chase_dist">chase_dist</a><br />
|
||||
<a href="#chase_height">chase_height</a><br />
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ if( WIN32 )
|
|||
add_definitions( -D_WIN32 )
|
||||
|
||||
set( PROJECT_LIBRARIES
|
||||
psapi
|
||||
wsock32
|
||||
winmm
|
||||
dinput8
|
||||
|
|
|
|||
|
|
@ -217,7 +217,7 @@ public:
|
|||
double originx, double originy, double scalex, double scaley,
|
||||
DAngle rotation, const FColormap &colormap, PalEntry flatcolor, double lightlevel, uint32_t *indices, size_t indexcount);
|
||||
void AddPoly(FGameTexture* img, FVector4 *vt, size_t vtcount, const unsigned int *ind, size_t idxcount, int translation, PalEntry color, FRenderStyle style, const IntRect* clip);
|
||||
void FillPolygon(int* rx1, int* ry1, int* xb1, int32_t npoints, int picnum, int palette, int shade, int props, const FVector2& xtex, const FVector2& ytex, const FVector2& otex,
|
||||
void FillPolygon(int* rx1, int* ry1, int* xb1, int32_t npoints, int pic, int palette, int shade, int props, const FVector2& xtex, const FVector2& ytex, const FVector2& otex,
|
||||
int clipx1, int clipy1, int clipx2, int clipy2);
|
||||
void AddFlatFill(int left, int top, int right, int bottom, FGameTexture *src, int local_origin = false, double flatscale = 1.0, PalEntry color = 0xffffffff, ERenderStyle rs = STYLE_Normal);
|
||||
|
||||
|
|
|
|||
|
|
@ -1786,12 +1786,12 @@ DEFINE_ACTION_FUNCTION(FCanvas, Dim)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void DrawBorder (F2DDrawer *drawer, FTextureID picnum, int x1, int y1, int x2, int y2)
|
||||
void DrawBorder (F2DDrawer *drawer, FTextureID texid, int x1, int y1, int x2, int y2)
|
||||
{
|
||||
int filltype = (ui_screenborder_classic_scaling) ? -1 : 0;
|
||||
if (picnum.isValid())
|
||||
if (texid.isValid())
|
||||
{
|
||||
drawer->AddFlatFill (x1, y1, x2, y2, TexMan.GetGameTexture(picnum, false), filltype);
|
||||
drawer->AddFlatFill (x1, y1, x2, y2, TexMan.GetGameTexture(texid, false), filltype);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -40,7 +40,6 @@
|
|||
#include <zlib.h>
|
||||
|
||||
#include <zmusic.h>
|
||||
#include "m_argv.h"
|
||||
#include "filesystem.h"
|
||||
#include "c_dispatch.h"
|
||||
|
||||
|
|
@ -218,13 +217,13 @@ static void SetupDMXGUS()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void I_InitMusic(void)
|
||||
void I_InitMusic(int musicstate)
|
||||
{
|
||||
I_InitSoundFonts();
|
||||
|
||||
snd_musicvolume->Callback ();
|
||||
|
||||
nomusic = !!Args->CheckParm("-nomusic") || !!Args->CheckParm("-nosound");
|
||||
nomusic = musicstate;
|
||||
|
||||
snd_mididevice->Callback();
|
||||
|
||||
|
|
|
|||
|
|
@ -34,27 +34,16 @@
|
|||
#ifndef __I_MUSIC_H__
|
||||
#define __I_MUSIC_H__
|
||||
|
||||
#include "c_cvars.h"
|
||||
|
||||
class FileReader;
|
||||
struct FOptionValues;
|
||||
|
||||
//
|
||||
// MUSIC I/O
|
||||
//
|
||||
void I_InitMusic ();
|
||||
void I_BuildMIDIMenuList (FOptionValues *);
|
||||
void I_InitMusic (int);
|
||||
|
||||
// Volume.
|
||||
void I_SetRelativeVolume(float);
|
||||
void I_SetMusicVolume (double volume);
|
||||
|
||||
|
||||
extern int nomusic;
|
||||
|
||||
EXTERN_CVAR(Bool, mus_enabled)
|
||||
EXTERN_CVAR(Float, snd_musicvolume)
|
||||
|
||||
|
||||
inline float AmplitudeTodB(float amplitude)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -53,9 +53,11 @@
|
|||
#include "gain_analysis.h"
|
||||
#include "i_specialpaths.h"
|
||||
#include "configfile.h"
|
||||
#include "c_cvars.h"
|
||||
|
||||
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
||||
|
||||
extern int nomusic;
|
||||
extern float S_GetMusicVolume (const char *music);
|
||||
|
||||
static void S_ActivatePlayList(bool goBack);
|
||||
|
|
@ -81,6 +83,8 @@ static MusicCallbacks mus_cb = { nullptr, DefaultOpenMusic };
|
|||
|
||||
|
||||
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
||||
EXTERN_CVAR(Bool, mus_enabled)
|
||||
EXTERN_CVAR(Float, snd_musicvolume)
|
||||
EXTERN_CVAR(Int, snd_mididevice)
|
||||
EXTERN_CVAR(Float, mod_dumb_mastervolume)
|
||||
EXTERN_CVAR(Float, fluid_gain)
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@
|
|||
#include <stdint.h>
|
||||
|
||||
#include "vectors.h"
|
||||
#include "tarray.h"
|
||||
#include "tflags.h"
|
||||
|
||||
enum EChanFlag
|
||||
|
|
@ -32,13 +31,12 @@ enum EChanFlag
|
|||
CHANF_LOCAL = 16384, // only plays locally for the calling actor
|
||||
CHANF_TRANSIENT = 32768, // Do not record in savegames - used for sounds that get restarted outside the sound system (e.g. ambients in SW and Blood)
|
||||
CHANF_FORCE = 65536, // Start, even if sound is paused.
|
||||
CHANF_SINGULAR = 0x20000, // Only start if no sound of this name is already playing.
|
||||
};
|
||||
|
||||
typedef TFlags<EChanFlag> EChanFlags;
|
||||
DEFINE_TFLAGS_OPERATORS(EChanFlags)
|
||||
|
||||
class FileReader;
|
||||
|
||||
// For convenience, this structure matches FMOD_REVERB_PROPERTIES.
|
||||
// Since I can't very well #include system-specific stuff in the
|
||||
// main game files, I duplicate it here.
|
||||
|
|
@ -77,14 +75,17 @@ struct REVERB_PROPERTIES
|
|||
unsigned int Flags;
|
||||
};
|
||||
|
||||
#define REVERB_FLAGS_DECAYTIMESCALE 0x00000001
|
||||
#define REVERB_FLAGS_REFLECTIONSSCALE 0x00000002
|
||||
#define REVERB_FLAGS_REFLECTIONSDELAYSCALE 0x00000004
|
||||
#define REVERB_FLAGS_REVERBSCALE 0x00000008
|
||||
#define REVERB_FLAGS_REVERBDELAYSCALE 0x00000010
|
||||
#define REVERB_FLAGS_DECAYHFLIMIT 0x00000020
|
||||
#define REVERB_FLAGS_ECHOTIMESCALE 0x00000040
|
||||
#define REVERB_FLAGS_MODULATIONTIMESCALE 0x00000080
|
||||
enum EReverbFlags
|
||||
{
|
||||
REVERB_FLAGS_DECAYTIMESCALE = 0x00000001,
|
||||
REVERB_FLAGS_REFLECTIONSSCALE = 0x00000002,
|
||||
REVERB_FLAGS_REFLECTIONSDELAYSCALE = 0x00000004,
|
||||
REVERB_FLAGS_REVERBSCALE = 0x00000008,
|
||||
REVERB_FLAGS_REVERBDELAYSCALE = 0x00000010,
|
||||
REVERB_FLAGS_DECAYHFLIMIT = 0x00000020,
|
||||
REVERB_FLAGS_ECHOTIMESCALE = 0x00000040,
|
||||
REVERB_FLAGS_MODULATIONTIMESCALE = 0x00000080,
|
||||
};
|
||||
|
||||
struct ReverbContainer
|
||||
{
|
||||
|
|
@ -143,8 +144,6 @@ struct FISoundChannel
|
|||
EChanFlags ChanFlags;
|
||||
};
|
||||
|
||||
class SoundStream;
|
||||
|
||||
void S_SetSoundPaused(int state);
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -488,7 +488,7 @@ FSoundChan *SoundEngine::StartSound(int type, const void *source,
|
|||
}
|
||||
|
||||
// If this is a singular sound, don't play it if it's already playing.
|
||||
if (sfx->bSingular && CheckSingular(sound_id))
|
||||
if ((sfx->bSingular || (flags & CHANF_SINGULAR)) && CheckSingular(sound_id))
|
||||
{
|
||||
chanflags |= CHANF_EVICTED;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ constexpr FSoundID INVALID_SOUND = FSoundID::fromInt(-1);
|
|||
float DefPitchMax = 0.f; // Randomized range with stronger control over pitch itself.
|
||||
|
||||
int16_t NearLimit = 4; // 0 means unlimited.
|
||||
int16_t UserVal = 0; // repurpose this gap for something useful
|
||||
uint8_t PitchMask = 0;
|
||||
bool bRandomHeader = false;
|
||||
bool bLoadRAW = false;
|
||||
|
|
@ -99,17 +100,16 @@ constexpr FSoundID INVALID_SOUND = FSoundID::fromInt(-1);
|
|||
bool bTentative = true;
|
||||
bool bExternal = false;
|
||||
|
||||
TArray<int> UserData;
|
||||
|
||||
int RawRate = 0; // Sample rate to use when bLoadRAW is true
|
||||
int LoopStart = -1; // -1 means no specific loop defined
|
||||
int LoopEnd = -1; // -1 means no specific loop defined
|
||||
float Attenuation = 1.f; // Multiplies the attenuation passed to S_Sound.
|
||||
|
||||
FSoundID link = NO_LINK;
|
||||
constexpr static FSoundID NO_LINK = FSoundID::fromInt(-1);
|
||||
|
||||
TArray<int> UserData;
|
||||
FRolloffInfo Rolloff{};
|
||||
float Attenuation = 1.f; // Multiplies the attenuation passed to S_Sound.
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
#pragma once
|
||||
#include <string>
|
||||
#include "zstring.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
|
|
|
|||
|
|
@ -546,7 +546,7 @@ bool InterplayDecoder::Open(FileReader &fr_)
|
|||
int chunkType = LE_16(&chunkPreamble[2]);
|
||||
if (chunkType == CHUNK_VIDEO)
|
||||
bAudioEnabled = false;
|
||||
else
|
||||
else if (bAudioEnabled)
|
||||
{
|
||||
if (ProcessNextChunk() != CHUNK_INIT_AUDIO)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -268,3 +268,4 @@ xx(BuiltinNameToClass)
|
|||
xx(BuiltinClassCast)
|
||||
|
||||
xx(ScreenJobRunner)
|
||||
xx(Action)
|
||||
|
|
|
|||
|
|
@ -367,7 +367,7 @@ static bool IndexOutOfRange(const int start1, const int end1, const int start2,
|
|||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
bool FRemapTable::operator==(const FRemapTable& o)
|
||||
bool FRemapTable::operator==(const FRemapTable& o) const
|
||||
{
|
||||
// Two translations are identical when they have the same amount of colors
|
||||
// and the palette values for both are identical.
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ struct FRemapTable
|
|||
FRemapTable(const FRemapTable& o) = default;
|
||||
FRemapTable& operator=(const FRemapTable& o) = default;
|
||||
|
||||
bool operator==(const FRemapTable& o);
|
||||
bool operator==(const FRemapTable& o) const;
|
||||
void MakeIdentity();
|
||||
bool IsIdentity() const;
|
||||
bool AddIndexRange(int start, int end, int pal1, int pal2);
|
||||
|
|
|
|||
|
|
@ -220,6 +220,7 @@ std2:
|
|||
'bright' { RET(StateOptions ? TK_Bright : TK_Identifier); }
|
||||
'fast' { RET(StateOptions ? TK_Fast : TK_Identifier); }
|
||||
'slow' { RET(StateOptions ? TK_Slow : TK_Identifier); }
|
||||
'ticadjust' { RET(StateOptions ? TK_NoDelay : TK_Identifier); }
|
||||
'nodelay' { RET(StateOptions ? TK_NoDelay : TK_Identifier); }
|
||||
'canraise' { RET(StateOptions ? TK_CanRaise : TK_Identifier); }
|
||||
'offset' { RET(StateOptions ? TK_Offset : TK_Identifier); }
|
||||
|
|
|
|||
|
|
@ -234,6 +234,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, FName &value, FName *d
|
|||
FSerializer &Serialize(FSerializer &arc, const char *key, FSoundID &sid, FSoundID *def);
|
||||
FSerializer &Serialize(FSerializer &arc, const char *key, FString &sid, FString *def);
|
||||
FSerializer &Serialize(FSerializer &arc, const char *key, NumericValue &sid, NumericValue *def);
|
||||
FSerializer &Serialize(FSerializer &arc, const char *key, struct ModelOverride &sid, struct ModelOverride *def);
|
||||
|
||||
template <typename T/*, typename = std::enable_if_t<std::is_base_of_v<DObject, T>>*/>
|
||||
FSerializer &Serialize(FSerializer &arc, const char *key, T *&value, T **)
|
||||
|
|
@ -244,7 +245,6 @@ FSerializer &Serialize(FSerializer &arc, const char *key, T *&value, T **)
|
|||
return arc;
|
||||
}
|
||||
|
||||
|
||||
template<class T, class TT>
|
||||
FSerializer &Serialize(FSerializer &arc, const char *key, TArray<T, TT> &value, TArray<T, TT> *def)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
#pragma once
|
||||
const char* UnicodeToString(const char* cc);
|
||||
const char* StringToUnicode(const char* cc, int size = -1);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
#pragma once
|
||||
#include "files.h"
|
||||
#include "engineerrors.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -65,21 +65,21 @@ protected:
|
|||
FSinglePicFont::FSinglePicFont(const char *picname) :
|
||||
FFont(-1) // Since lump is only needed for priority information we don't need to worry about this here.
|
||||
{
|
||||
FTextureID picnum = TexMan.CheckForTexture (picname, ETextureType::Any);
|
||||
FTextureID texid = TexMan.CheckForTexture (picname, ETextureType::Any);
|
||||
|
||||
if (!picnum.isValid())
|
||||
if (!texid.isValid())
|
||||
{
|
||||
I_FatalError ("%s is not a font or texture", picname);
|
||||
}
|
||||
|
||||
auto pic = TexMan.GetGameTexture(picnum);
|
||||
auto pic = TexMan.GetGameTexture(texid);
|
||||
|
||||
FontName = picname;
|
||||
FontHeight = (int)pic->GetDisplayHeight();
|
||||
SpaceWidth = (int)pic->GetDisplayWidth();
|
||||
GlobalKerning = 0;
|
||||
FirstChar = LastChar = 'A';
|
||||
PicNum = picnum;
|
||||
PicNum = texid;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
|||
|
|
@ -138,10 +138,10 @@ FFont *V_GetFont(const char *name, const char *fontlumpname)
|
|||
return font;
|
||||
}
|
||||
}
|
||||
FTextureID picnum = TexMan.CheckForTexture (name, ETextureType::Any);
|
||||
if (picnum.isValid())
|
||||
FTextureID texid = TexMan.CheckForTexture (name, ETextureType::Any);
|
||||
if (texid.isValid())
|
||||
{
|
||||
auto tex = TexMan.GetGameTexture(picnum);
|
||||
auto tex = TexMan.GetGameTexture(texid);
|
||||
if (tex && tex->GetSourceLump() >= folderfile)
|
||||
{
|
||||
FFont *CreateSinglePicFont(const char *name);
|
||||
|
|
|
|||
|
|
@ -1662,6 +1662,7 @@ static void InitMusicMenus()
|
|||
// Special menus will be created once all engine data is loaded
|
||||
//
|
||||
//=============================================================================
|
||||
void I_BuildMIDIMenuList(FOptionValues*);
|
||||
|
||||
void M_CreateMenus()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -231,6 +231,8 @@ void PClass::StaticInit ()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void ClearServices();
|
||||
|
||||
void PClass::StaticShutdown ()
|
||||
{
|
||||
if (WP_NOCHANGE != nullptr)
|
||||
|
|
@ -238,6 +240,7 @@ void PClass::StaticShutdown ()
|
|||
delete WP_NOCHANGE;
|
||||
}
|
||||
|
||||
ClearServices();
|
||||
// delete all variables containing pointers to script functions.
|
||||
for (auto p : FunctionPtrList)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -151,21 +151,24 @@ void I_DetectOS()
|
|||
case 10:
|
||||
switch (version.minorVersion)
|
||||
{
|
||||
case 12: name = "macOS Sierra"; break;
|
||||
case 13: name = "macOS High Sierra"; break;
|
||||
case 14: name = "macOS Mojave"; break;
|
||||
case 15: name = "macOS Catalina"; break;
|
||||
case 16: name = "macOS Big Sur"; break;
|
||||
case 12: name = "Sierra"; break;
|
||||
case 13: name = "High Sierra"; break;
|
||||
case 14: name = "Mojave"; break;
|
||||
case 15: name = "Catalina"; break;
|
||||
case 16: name = "Big Sur"; break;
|
||||
}
|
||||
break;
|
||||
case 11:
|
||||
name = "macOS Big Sur";
|
||||
name = "Big Sur";
|
||||
break;
|
||||
case 12:
|
||||
name = "macOS Monterey";
|
||||
name = "Monterey";
|
||||
break;
|
||||
case 13:
|
||||
name = "macOS Ventura";
|
||||
name = "Ventura";
|
||||
break;
|
||||
case 14:
|
||||
name = "Sonoma";
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -186,7 +189,7 @@ void I_DetectOS()
|
|||
"Unknown";
|
||||
#endif
|
||||
|
||||
Printf("%s running %s %d.%d.%d (%s) %s\n", model, name,
|
||||
Printf("%s running macOS %s %d.%d.%d (%s) %s\n", model, name,
|
||||
int(version.majorVersion), int(version.minorVersion), int(version.patchVersion),
|
||||
release, architecture);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,6 @@
|
|||
#include <asm/unistd.h>
|
||||
#include <linux/perf_event.h>
|
||||
#include <sys/mman.h>
|
||||
#include "printf.h"
|
||||
#endif
|
||||
|
||||
#include <SDL.h>
|
||||
|
|
@ -65,6 +64,7 @@
|
|||
#include "c_cvars.h"
|
||||
#include "palutil.h"
|
||||
#include "st_start.h"
|
||||
#include "printf.h"
|
||||
|
||||
|
||||
#ifndef NO_GTK
|
||||
|
|
@ -408,7 +408,7 @@ FString I_GetFromClipboard (bool use_primary_selection)
|
|||
|
||||
FString I_GetCWD()
|
||||
{
|
||||
char* curdir = get_current_dir_name();
|
||||
char* curdir = getcwd(NULL,0);
|
||||
if (!curdir)
|
||||
{
|
||||
return "";
|
||||
|
|
@ -447,7 +447,7 @@ unsigned int I_MakeRNGSeed()
|
|||
|
||||
void I_OpenShellFolder(const char* infolder)
|
||||
{
|
||||
char* curdir = get_current_dir_name();
|
||||
char* curdir = getcwd(NULL,0);
|
||||
|
||||
if (!chdir(infolder))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -189,6 +189,8 @@ CUSTOM_CVAR (Int, in_mouse, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOINITCALL)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
static bool mouse_shown = true;
|
||||
|
||||
static void SetCursorState(bool visible)
|
||||
{
|
||||
CursorState = visible || !m_hidepointer;
|
||||
|
|
@ -196,13 +198,19 @@ static void SetCursorState(bool visible)
|
|||
{
|
||||
if (CursorState)
|
||||
{
|
||||
ShowCursor(1);
|
||||
SetCursor((HCURSOR)(intptr_t)GetClassLongPtr(mainwindow.GetHandle(), GCLP_HCURSOR));
|
||||
if(!mouse_shown)
|
||||
{
|
||||
ShowCursor(true);
|
||||
mouse_shown = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowCursor(0);
|
||||
SetCursor(NULL);
|
||||
if(mouse_shown)
|
||||
{
|
||||
ShowCursor(false);
|
||||
mouse_shown = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
// winres.h - Windows resource definitions
|
||||
// extracted from WINUSER.H and COMMCTRL.H
|
||||
#pragma once
|
||||
|
||||
#ifdef _AFX_MINREBUILD
|
||||
#pragma component(minrebuild, off)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
|
||||
#include "hw_mesh.h"
|
||||
#include "v_video.h"
|
||||
#include "cmdlib.h"
|
||||
|
||||
#define USE_MESH_VERTEX_BUFFER
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include "vulkan/buffers/vk_buffer.h"
|
||||
#include <zvulkan/vulkanbuilders.h>
|
||||
#include "flatvertices.h"
|
||||
#include "cmdlib.h"
|
||||
|
||||
VkRSBuffers::VkRSBuffers(VulkanRenderDevice* fb)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#include "hw_viewpointuniforms.h"
|
||||
#include "v_2ddrawer.h"
|
||||
#include "i_specialpaths.h"
|
||||
#include "cmdlib.h"
|
||||
|
||||
VkRenderPassManager::VkRenderPassManager(VulkanRenderDevice* fb) : fb(fb)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -64,7 +64,6 @@
|
|||
|
||||
FString JitCaptureStackTrace(int framesToSkip, bool includeNativeFrames, int maxFrames = -1);
|
||||
|
||||
EXTERN_CVAR(Bool, r_drawvoxels)
|
||||
EXTERN_CVAR(Int, gl_tonemap)
|
||||
EXTERN_CVAR(Int, screenblocks)
|
||||
EXTERN_CVAR(Bool, cl_capfps)
|
||||
|
|
|
|||
|
|
@ -272,6 +272,13 @@ dottable_id(X) ::= IDENTIFIER(A).
|
|||
id->Id = A.Name();
|
||||
X = id;
|
||||
}
|
||||
// this is needed for defining properties named 'action'.
|
||||
dottable_id(X) ::= ACTION(A).
|
||||
{
|
||||
NEW_AST_NODE(Identifier,id,A);
|
||||
id->Id = NAME_Action;
|
||||
X = id;
|
||||
}
|
||||
dottable_id(X) ::= dottable_id(A) DOT IDENTIFIER(B).
|
||||
{
|
||||
NEW_AST_NODE(Identifier,id2,A);
|
||||
|
|
|
|||
|
|
@ -57,8 +57,8 @@
|
|||
|
||||
static ZSMap<FName, DObject*> AllServices;
|
||||
|
||||
static void MarkServices() {
|
||||
|
||||
static void MarkServices()
|
||||
{
|
||||
ZSMap<FName, DObject*>::Iterator it(AllServices);
|
||||
ZSMap<FName, DObject*>::Pair* pair;
|
||||
while (it.NextPair(pair))
|
||||
|
|
@ -82,6 +82,11 @@ void InitServices()
|
|||
GC::AddMarkerFunc(&MarkServices);
|
||||
}
|
||||
|
||||
void ClearServices()
|
||||
{
|
||||
AllServices.Clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
|
||||
#pragma once
|
||||
#include "jit.h"
|
||||
|
||||
#include "types.h"
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@
|
|||
#include "memarena.h"
|
||||
#include "name.h"
|
||||
#include "scopebarrier.h"
|
||||
#include <type_traits>
|
||||
|
||||
class DObject;
|
||||
union VMOP;
|
||||
|
|
@ -194,6 +195,12 @@ struct VMReturn
|
|||
*(void **)Location = val;
|
||||
}
|
||||
|
||||
void SetConstPointer(const void *val)
|
||||
{
|
||||
assert(RegType == REGT_POINTER);
|
||||
*(const void **)Location = val;
|
||||
}
|
||||
|
||||
void SetObject(DObject *val)
|
||||
{
|
||||
assert(RegType == REGT_POINTER);
|
||||
|
|
@ -611,6 +618,8 @@ namespace
|
|||
template<typename T> struct native_is_valid<T&> { static const bool value = true; static const bool retval = true; };
|
||||
template<> struct native_is_valid<void> { static const bool value = true; static const bool retval = true; };
|
||||
template<> struct native_is_valid<int> { static const bool value = true; static const bool retval = true; };
|
||||
// [RL0] this is disabled for now due to graf's concerns
|
||||
// template<> struct native_is_valid<FName> { static const bool value = true; static const bool retval = true; static_assert(sizeof(FName) == sizeof(int)); static_assert(std::is_pod_v<FName>);};
|
||||
template<> struct native_is_valid<unsigned int> { static const bool value = true; static const bool retval = true; };
|
||||
template<> struct native_is_valid<double> { static const bool value = true; static const bool retval = true; };
|
||||
template<> struct native_is_valid<bool> { static const bool value = true; static const bool retval = false;}; // Bool as return does not work!
|
||||
|
|
@ -621,26 +630,7 @@ struct DirectNativeDesc
|
|||
{
|
||||
DirectNativeDesc() = default;
|
||||
|
||||
#define TP(n) typename P##n
|
||||
#define VP(n) ValidateType<P##n>()
|
||||
template<typename Ret> DirectNativeDesc(Ret(*func)()) : Ptr(reinterpret_cast<void*>(func)) { ValidateRet<Ret>(); }
|
||||
template<typename Ret, TP(1)> DirectNativeDesc(Ret(*func)(P1)) : Ptr(reinterpret_cast<void*>(func)) { ValidateRet<Ret>(); VP(1); }
|
||||
template<typename Ret, TP(1), TP(2)> DirectNativeDesc(Ret(*func)(P1,P2)) : Ptr(reinterpret_cast<void*>(func)) { ValidateRet<Ret>(); VP(1); VP(2); }
|
||||
template<typename Ret, TP(1), TP(2), TP(3)> DirectNativeDesc(Ret(*func)(P1,P2,P3)) : Ptr(reinterpret_cast<void*>(func)) { ValidateRet<Ret>(); VP(1); VP(2); VP(3); }
|
||||
template<typename Ret, TP(1), TP(2), TP(3), TP(4)> DirectNativeDesc(Ret(*func)(P1, P2, P3, P4)) : Ptr(reinterpret_cast<void*>(func)) { ValidateRet<Ret>(); VP(1); VP(2); VP(3); VP(4); }
|
||||
template<typename Ret, TP(1), TP(2), TP(3), TP(4), TP(5)> DirectNativeDesc(Ret(*func)(P1, P2, P3, P4, P5)) : Ptr(reinterpret_cast<void*>(func)) { ValidateRet<Ret>(); VP(1); VP(2); VP(3); VP(4); VP(5); }
|
||||
template<typename Ret, TP(1), TP(2), TP(3), TP(4), TP(5), TP(6)> DirectNativeDesc(Ret(*func)(P1, P2, P3, P4, P5, P6)) : Ptr(reinterpret_cast<void*>(func)) { ValidateRet<Ret>(); VP(1); VP(2); VP(3); VP(4); VP(5); VP(6); }
|
||||
template<typename Ret, TP(1), TP(2), TP(3), TP(4), TP(5), TP(6), TP(7)> DirectNativeDesc(Ret(*func)(P1, P2, P3, P4, P5, P6, P7)) : Ptr(reinterpret_cast<void*>(func)) { ValidateRet<Ret>(); VP(1); VP(2); VP(3); VP(4); VP(5); VP(6); VP(7); }
|
||||
template<typename Ret, TP(1), TP(2), TP(3), TP(4), TP(5), TP(6), TP(7), TP(8)> DirectNativeDesc(Ret(*func)(P1, P2, P3, P4, P5, P6, P7, P8)) : Ptr(reinterpret_cast<void*>(func)) { ValidateRet<Ret>(); VP(1); VP(2); VP(3); VP(4); VP(5); VP(6); VP(7); VP(8); }
|
||||
template<typename Ret, TP(1), TP(2), TP(3), TP(4), TP(5), TP(6), TP(7), TP(8), TP(9)> DirectNativeDesc(Ret(*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9)) : Ptr(reinterpret_cast<void*>(func)) { ValidateRet<Ret>(); VP(1); VP(2); VP(3); VP(4); VP(5); VP(6); VP(7); VP(8); VP(9); }
|
||||
template<typename Ret, TP(1), TP(2), TP(3), TP(4), TP(5), TP(6), TP(7), TP(8), TP(9), TP(10)> DirectNativeDesc(Ret(*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10)) : Ptr(reinterpret_cast<void*>(func)) { ValidateRet<Ret>(); VP(1); VP(2); VP(3); VP(4); VP(5); VP(6); VP(7); VP(8); VP(9); VP(10); }
|
||||
template<typename Ret, TP(1), TP(2), TP(3), TP(4), TP(5), TP(6), TP(7), TP(8), TP(9), TP(10), TP(11)> DirectNativeDesc(Ret(*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11)) : Ptr(reinterpret_cast<void*>(func)) { ValidateRet<Ret>(); VP(1); VP(2); VP(3); VP(4); VP(5); VP(6); VP(7); VP(8); VP(9); VP(10); VP(11); }
|
||||
template<typename Ret, TP(1), TP(2), TP(3), TP(4), TP(5), TP(6), TP(7), TP(8), TP(9), TP(10), TP(11), TP(12)> DirectNativeDesc(Ret(*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12)) : Ptr(reinterpret_cast<void*>(func)) { ValidateRet<Ret>(); VP(1); VP(2); VP(3); VP(4); VP(5); VP(6); VP(7); VP(8); VP(9); VP(10); VP(11); VP(12); }
|
||||
template<typename Ret, TP(1), TP(2), TP(3), TP(4), TP(5), TP(6), TP(7), TP(8), TP(9), TP(10), TP(11), TP(12), TP(13)> DirectNativeDesc(Ret(*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13)) : Ptr(reinterpret_cast<void*>(func)) { ValidateRet<Ret>(); VP(1); VP(2); VP(3); VP(4); VP(5); VP(6); VP(7); VP(8); VP(9); VP(10); VP(11); VP(12); VP(13); }
|
||||
template<typename Ret, TP(1), TP(2), TP(3), TP(4), TP(5), TP(6), TP(7), TP(8), TP(9), TP(10), TP(11), TP(12), TP(13), TP(14)> DirectNativeDesc(Ret(*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14)) : Ptr(reinterpret_cast<void*>(func)) { ValidateRet<Ret>(); VP(1); VP(2); VP(3); VP(4); VP(5); VP(6); VP(7); VP(8); VP(9); VP(10); VP(11); VP(12); VP(13), VP(14); }
|
||||
template<typename Ret, TP(1), TP(2), TP(3), TP(4), TP(5), TP(6), TP(7), TP(8), TP(9), TP(10), TP(11), TP(12), TP(13), TP(14), TP(15)> DirectNativeDesc(Ret(*func)(P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14)) : Ptr(reinterpret_cast<void*>(func)) { ValidateRet<Ret>(); VP(1); VP(2); VP(3); VP(4); VP(5); VP(6); VP(7); VP(8); VP(9); VP(10); VP(11); VP(12); VP(13), VP(14), VP(15); }
|
||||
#undef TP
|
||||
#undef VP
|
||||
template<typename Ret, typename... Params> DirectNativeDesc(Ret(*func)(Params...)) : Ptr(reinterpret_cast<void*>(func)) { ValidateRet<Ret>(); (ValidateType<Params>(), ...); }
|
||||
|
||||
template<typename T> void ValidateType() { static_assert(native_is_valid<T>::value, "Argument type is not valid as a direct native parameter or return type"); }
|
||||
template<typename T> void ValidateRet() { static_assert(native_is_valid<T>::retval, "Return type is not valid as a direct native parameter or return type"); }
|
||||
|
|
@ -759,6 +749,7 @@ struct AFuncDesc
|
|||
class AActor;
|
||||
|
||||
#define ACTION_RETURN_STATE(v) do { FState *state = v; if (numret > 0) { assert(ret != NULL); ret->SetPointer(state); return 1; } return 0; } while(0)
|
||||
#define ACTION_RETURN_CONST_POINTER(v) do { const void *state = v; if (numret > 0) { assert(ret != NULL); ret->SetConstPointer(state); return 1; } return 0; } while(0)
|
||||
#define ACTION_RETURN_POINTER(v) do { void *state = v; if (numret > 0) { assert(ret != NULL); ret->SetPointer(state); return 1; } return 0; } while(0)
|
||||
#define ACTION_RETURN_OBJECT(v) do { auto state = v; if (numret > 0) { assert(ret != NULL); ret->SetObject(state); return 1; } return 0; } while(0)
|
||||
#define ACTION_RETURN_FLOAT(v) do { double u = v; if (numret > 0) { assert(ret != nullptr); ret->SetFloat(u); return 1; } return 0; } while(0)
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ Prepared for public release: 03/21/2003 - Charlie Wiederhold, 3D Realms
|
|||
Modifications for JonoF's port by Jonathon Fowler (jf@jonof.id.au)
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
//#ifdef WIN32
|
||||
//#define DLL __declspec(dllexport)
|
||||
//#else
|
||||
#pragma once
|
||||
#define DLL
|
||||
//#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ public:
|
|||
bool operator > (FTextureID other) const { return texnum > other.texnum; }
|
||||
|
||||
protected:
|
||||
FTextureID(int num) { texnum = num; }
|
||||
constexpr FTextureID(int num) : texnum(num) { }
|
||||
private:
|
||||
int texnum;
|
||||
};
|
||||
|
|
@ -53,13 +53,13 @@ private:
|
|||
class FNullTextureID : public FTextureID
|
||||
{
|
||||
public:
|
||||
FNullTextureID() : FTextureID(0) {}
|
||||
constexpr FNullTextureID() : FTextureID(0) {}
|
||||
};
|
||||
|
||||
// This is for the script interface which needs to do casts from int to texture.
|
||||
class FSetTextureID : public FTextureID
|
||||
{
|
||||
public:
|
||||
FSetTextureID(int v) : FTextureID(v) {}
|
||||
constexpr FSetTextureID(int v) : FTextureID(v) {}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -498,9 +498,9 @@ FTextureID FTextureManager::CreateTexture (int lumpnum, ETextureType usetype)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void FTextureManager::ReplaceTexture (FTextureID picnum, FGameTexture *newtexture, bool free)
|
||||
void FTextureManager::ReplaceTexture (FTextureID texid, FGameTexture *newtexture, bool free)
|
||||
{
|
||||
int index = picnum.GetIndex();
|
||||
int index = texid.GetIndex();
|
||||
if (unsigned(index) >= Textures.Size())
|
||||
return;
|
||||
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ public:
|
|||
void AddTextures(void (*progressFunc_)(), void (*checkForHacks)(BuildInfo&), void (*customtexturehandler)() = nullptr);
|
||||
void DeleteAll();
|
||||
|
||||
void ReplaceTexture (FTextureID picnum, FGameTexture *newtexture, bool free);
|
||||
void ReplaceTexture (FTextureID texid, FGameTexture *newtexture, bool free);
|
||||
|
||||
int NumTextures () const { return (int)Textures.Size(); }
|
||||
|
||||
|
|
|
|||
|
|
@ -62,8 +62,8 @@ void FImageCollection::Add (const char **patchNames, int numPatches, ETextureTyp
|
|||
|
||||
for (int i = 0; i < numPatches; ++i)
|
||||
{
|
||||
FTextureID picnum = TexMan.CheckForTexture(patchNames[i], namespc);
|
||||
ImageMap[OldCount + i] = picnum;
|
||||
FTextureID texid = TexMan.CheckForTexture(patchNames[i], namespc);
|
||||
ImageMap[OldCount + i] = texid;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -184,7 +184,7 @@ public:
|
|||
return mReader->Seek((long)offset, origin);
|
||||
}
|
||||
|
||||
Size Read(void *buffer, Size len)
|
||||
Size Read(void *buffer, Size len) const
|
||||
{
|
||||
return mReader->Read(buffer, (long)len);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@
|
|||
#include <new>
|
||||
#include <utility>
|
||||
#include <iterator>
|
||||
#include <algorithm>
|
||||
|
||||
#if !defined(_WIN32)
|
||||
#include <inttypes.h> // for intptr_t
|
||||
|
|
@ -327,9 +328,10 @@ public:
|
|||
}
|
||||
|
||||
// returns address of first element
|
||||
T *Data() const
|
||||
T *Data(size_t index = 0) const
|
||||
{
|
||||
return &Array[0];
|
||||
assert(index <= Count);
|
||||
return &Array[index];
|
||||
}
|
||||
|
||||
unsigned IndexOf(const T& elem) const
|
||||
|
|
@ -419,6 +421,26 @@ public:
|
|||
return start;
|
||||
}
|
||||
|
||||
unsigned AppendFill(const T& val, unsigned append_count)
|
||||
{
|
||||
unsigned start = Count;
|
||||
|
||||
Grow(append_count);
|
||||
Count += append_count;
|
||||
if constexpr (std::is_trivially_copyable<T>::value)
|
||||
{
|
||||
std::fill(Array + start, Array + Count, val);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned i = 0; i < append_count; i++)
|
||||
{
|
||||
new(&Array[start + i]) T(val);
|
||||
}
|
||||
}
|
||||
return start;
|
||||
}
|
||||
|
||||
bool Pop ()
|
||||
{
|
||||
if (Count > 0)
|
||||
|
|
|
|||
|
|
@ -44,23 +44,32 @@
|
|||
#include <math.h>
|
||||
#include <float.h>
|
||||
#include <string.h>
|
||||
|
||||
// this is needed to properly normalize angles. We cannot do that with compiler provided conversions because they differ too much
|
||||
#include "xs_Float.h"
|
||||
#include "math/cmath.h"
|
||||
#include "basics.h"
|
||||
#include "cmdlib.h"
|
||||
|
||||
|
||||
#define EQUAL_EPSILON (1/65536.)
|
||||
|
||||
// make this a local inline function to avoid any dependencies on other headers and not pollute the global namespace
|
||||
namespace pi
|
||||
{
|
||||
inline constexpr double pi() { return 3.14159265358979323846; }
|
||||
inline constexpr double pif() { return 3.14159265358979323846f; }
|
||||
inline constexpr float pif() { return 3.14159265358979323846f; }
|
||||
}
|
||||
|
||||
// optionally use reliable math routines if reproducability across hardware is important., but let this still compile without them.
|
||||
#if __has_include("math/cmath.h")
|
||||
#include "math/cmath.h"
|
||||
#else
|
||||
double g_cosdeg(double v) { return cos(v * (pi::pi() / 180.)); }
|
||||
double g_sindeg(double v) { return sin(v * (pi::pi() / 180.)); }
|
||||
double g_cos(double v) { return cos(v); }
|
||||
double g_sin(double v) { return sin(v); }
|
||||
double g_sqrt(double v) { return sqrt(v); }
|
||||
double g_atan2(double v, double w) { return atan2(v, w); }
|
||||
#endif
|
||||
|
||||
|
||||
#define EQUAL_EPSILON (1/65536.)
|
||||
|
||||
template<class vec_t> struct TVector3;
|
||||
template<class vec_t> struct TRotator;
|
||||
template<class vec_t> struct TAngle;
|
||||
|
|
@ -1450,8 +1459,13 @@ public:
|
|||
|
||||
double Tan() const
|
||||
{
|
||||
// use an optimized approach if we have a sine table. If not just call the CRT's tan function.
|
||||
#if __has_include("math/cmath.h")
|
||||
const auto bam = BAMs();
|
||||
return g_sinbam(bam) / g_cosbam(bam);
|
||||
#else
|
||||
return vec_t(tan(Radians()));
|
||||
#endif
|
||||
}
|
||||
|
||||
// This is for calculating vertical velocity. For high pitches the tangent will become too large to be useful.
|
||||
|
|
@ -1460,9 +1474,11 @@ public:
|
|||
return clamp(Tan(), -max, max);
|
||||
}
|
||||
|
||||
// returns sign of the NORMALIZED angle.
|
||||
int Sgn() const
|
||||
{
|
||||
return ::Sgn(int(BAMs()));
|
||||
auto val = int(BAMs());
|
||||
return (val > 0) - (val < 0);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
|
|
|||
|
|
@ -408,6 +408,39 @@ CCMD (changemap)
|
|||
}
|
||||
}
|
||||
|
||||
CCMD (changeskill)
|
||||
{
|
||||
if (!players[consoleplayer].mo || !usergame)
|
||||
{
|
||||
Printf ("Use the skill command when not in a game.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!players[consoleplayer].settings_controller && netgame)
|
||||
{
|
||||
Printf ("Only setting controllers can change the skill.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (argv.argc() == 2)
|
||||
{
|
||||
int skill = atoi(argv[1]);
|
||||
if ((unsigned)skill >= AllSkills.Size())
|
||||
{
|
||||
Printf ("Skill %d is out of range.\n", skill);
|
||||
}
|
||||
else
|
||||
{
|
||||
NextSkill = skill;
|
||||
Printf ("Skill %d will take effect on the next map.\n", skill);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Printf ("Usage: changeskill <skill>\n");
|
||||
}
|
||||
}
|
||||
|
||||
CCMD (give)
|
||||
{
|
||||
if (CheckCheatmode () || argv.argc() < 2)
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
// defcvars loader split from d_main.cpp
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
#pragma once
|
||||
|
||||
#define SHOULD_BLACKLIST(name) \
|
||||
if (#name[0]==CurrentFindCVar[0]) \
|
||||
|
|
|
|||
|
|
@ -148,6 +148,7 @@ void FIWadManager::ParseIWadInfo(const char *fn, const char *data, int datasize,
|
|||
else if(sc.Compare("Extended")) iwad->flags |= GI_MENUHACK_EXTENDED;
|
||||
else if(sc.Compare("Shorttex")) iwad->flags |= GI_COMPATSHORTTEX;
|
||||
else if(sc.Compare("Stairs")) iwad->flags |= GI_COMPATSTAIRS;
|
||||
else if (sc.Compare("nosectionmerge")) iwad->flags |= GI_NOSECTIONMERGE;
|
||||
else sc.ScriptError(NULL);
|
||||
}
|
||||
while (sc.CheckString(","));
|
||||
|
|
|
|||
|
|
@ -625,7 +625,7 @@ CUSTOM_CVAR(Int, compatmode, 0, CVAR_ARCHIVE|CVAR_NOINITCALL)
|
|||
COMPATF_TRACE | COMPATF_MISSILECLIP | COMPATF_SOUNDTARGET | COMPATF_NO_PASSMOBJ | COMPATF_LIMITPAIN |
|
||||
COMPATF_DEHHEALTH | COMPATF_INVISIBILITY | COMPATF_CROSSDROPOFF | COMPATF_VILEGHOSTS | COMPATF_HITSCAN |
|
||||
COMPATF_WALLRUN | COMPATF_NOTOSSDROPS | COMPATF_LIGHT | COMPATF_MASKEDMIDTEX;
|
||||
w = COMPATF2_BADANGLES | COMPATF2_FLOORMOVE | COMPATF2_POINTONLINE | COMPATF2_EXPLODE2 | COMPATF2_NOMBF21;
|
||||
w = COMPATF2_BADANGLES | COMPATF2_FLOORMOVE | COMPATF2_POINTONLINE | COMPATF2_EXPLODE2 | COMPATF2_NOMBF21 | COMPATF2_VOODOO_ZOMBIES;
|
||||
break;
|
||||
|
||||
case 3: // Boom compat mode
|
||||
|
|
|
|||
|
|
@ -233,6 +233,7 @@ enum : unsigned int
|
|||
COMPATF2_AVOID_HAZARDS = 1 << 12, // another MBF thing.
|
||||
COMPATF2_STAYONLIFT = 1 << 13, // yet another MBF thing.
|
||||
COMPATF2_NOMBF21 = 1 << 14, // disable MBF21 features that may clash with certain maps
|
||||
COMPATF2_VOODOO_ZOMBIES = 1 << 15, // [RL0] allow playerinfo, playerpawn, and voodoo health to all be different, and skip killing the player's mobj if a voodoo doll dies to allow voodoo zombies
|
||||
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
#pragma once
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
// This is separate because the files being compiled with it use different compiler settings which may affect how the header is compiled
|
||||
#pragma once
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
//
|
||||
// Globally visible constants.
|
||||
//
|
||||
#pragma once
|
||||
#define HU_FONTSTART uint8_t('!') // the first font characters
|
||||
#define HU_FONTEND uint8_t('\377') // the last font characters
|
||||
|
||||
|
|
|
|||
|
|
@ -1847,6 +1847,7 @@ MapFlagHandlers[] =
|
|||
{ "compat_avoidhazards", MITYPE_COMPATFLAG, 0, COMPATF2_AVOID_HAZARDS },
|
||||
{ "compat_stayonlift", MITYPE_COMPATFLAG, 0, COMPATF2_STAYONLIFT },
|
||||
{ "compat_nombf21", MITYPE_COMPATFLAG, 0, COMPATF2_NOMBF21 },
|
||||
{ "compat_voodoozombies", MITYPE_COMPATFLAG, 0, COMPATF2_VOODOO_ZOMBIES },
|
||||
{ "cd_start_track", MITYPE_EATNEXT, 0, 0 },
|
||||
{ "cd_end1_track", MITYPE_EATNEXT, 0, 0 },
|
||||
{ "cd_end2_track", MITYPE_EATNEXT, 0, 0 },
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ enum
|
|||
GI_COMPATPOLY1 = 0x00000040, // Hexen's MAP36 needs old polyobject drawing
|
||||
GI_COMPATPOLY2 = 0x00000080, // so does HEXDD's MAP47
|
||||
GI_IGNORETITLEPATCHES = 0x00000200, // Ignore the map name graphics when not runnning in English language
|
||||
GI_NOSECTIONMERGE = 0x00000400, // For the original id IWADs: avoid merging sections due to how idbsp created its sectors.
|
||||
};
|
||||
|
||||
#include "gametype.h"
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ struct UMapEntry
|
|||
FString InterText;
|
||||
FString InterTextSecret;
|
||||
TArray<FSpecialAction> BossActions;
|
||||
bool BossCleared = false;
|
||||
|
||||
char levelpic[9] = "";
|
||||
char nextmap[9] = "";
|
||||
|
|
@ -268,6 +269,7 @@ static int ParseStandardProperty(FScanner &scanner, UMapEntry *mape)
|
|||
// mark level free of boss actions
|
||||
classnum = special = tag = -1;
|
||||
mape->BossActions.Clear();
|
||||
mape->BossCleared = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -446,11 +448,12 @@ void CommitUMapinfo(level_info_t *defaultinfo)
|
|||
levelinfo->InterMusic = map.intermusic;
|
||||
levelinfo->intermusicorder = 0;
|
||||
}
|
||||
if (map.BossActions.Size() > 0)
|
||||
if (map.BossActions.Size() > 0 || map.BossCleared)
|
||||
{
|
||||
// Setting a boss action will deactivate the flag based monster actions.
|
||||
levelinfo->specialactions = std::move(map.BossActions);
|
||||
levelinfo->flags &= ~(LEVEL_BRUISERSPECIAL | LEVEL_CYBORGSPECIAL | LEVEL_SPIDERSPECIAL | LEVEL_MAP07SPECIAL | LEVEL_MINOTAURSPECIAL | LEVEL_HEADSPECIAL | LEVEL_SORCERER2SPECIAL | LEVEL_SPECACTIONSMASK | LEVEL_SPECKILLMONSTERS);
|
||||
levelinfo->flags3 &= ~(LEVEL3_E1M8SPECIAL | LEVEL3_E2M8SPECIAL | LEVEL3_E3M8SPECIAL | LEVEL3_E4M8SPECIAL | LEVEL3_E4M6SPECIAL);
|
||||
}
|
||||
|
||||
const int exflags = FExitText::DEF_TEXT | FExitText::DEF_BACKDROP | FExitText::DEF_MUSIC;
|
||||
|
|
|
|||
|
|
@ -171,6 +171,7 @@ static FCompatOption Options[] =
|
|||
{ "railing", COMPATF2_RAILING, SLOT_COMPAT2 },
|
||||
{ "scriptwait", COMPATF2_SCRIPTWAIT, SLOT_COMPAT2 },
|
||||
{ "nombf21", COMPATF2_NOMBF21, SLOT_COMPAT2 },
|
||||
{ "voodoozombies", COMPATF2_VOODOO_ZOMBIES, SLOT_COMPAT2 },
|
||||
{ NULL, 0, 0 }
|
||||
};
|
||||
|
||||
|
|
@ -291,13 +292,19 @@ FName MapLoader::CheckCompatibility(MapData *map)
|
|||
Level->ib_compatflags = 0;
|
||||
|
||||
// When playing Doom IWAD levels force BCOMPATF_NOSECTIONMERGE, COMPAT_SHORTTEX and COMPATF_LIGHT.
|
||||
// I'm not sure if the IWAD maps actually need COMPATF_LIGHT but it certainly does not hurt. BCOMPATF_NOSECTIONMERGE is mainly for MAP18's sector 0
|
||||
// I'm not sure if the IWAD maps actually need COMPATF_LIGHT but it certainly does not hurt.
|
||||
// TNT's MAP31 also needs COMPATF_STAIRINDEX but that only gets activated for TNT.WAD.
|
||||
if (fileSystem.GetFileContainer(map->lumpnum) == fileSystem.GetIwadNum() && (gameinfo.flags & GI_COMPATSHORTTEX) && Level->maptype == MAPTYPE_DOOM)
|
||||
if (fileSystem.GetFileContainer(map->lumpnum) == fileSystem.GetIwadNum())
|
||||
{
|
||||
Level->ii_compatflags = COMPATF_SHORTTEX|COMPATF_LIGHT;
|
||||
Level->ib_compatflags = BCOMPATF_NOSECTIONMERGE;
|
||||
if (gameinfo.flags & GI_COMPATSTAIRS) Level->ii_compatflags |= COMPATF_STAIRINDEX;
|
||||
if ((gameinfo.flags & GI_COMPATSHORTTEX) && Level->maptype == MAPTYPE_DOOM)
|
||||
{
|
||||
Level->ii_compatflags = COMPATF_SHORTTEX | COMPATF_LIGHT;
|
||||
if (gameinfo.flags & GI_COMPATSTAIRS) Level->ii_compatflags |= COMPATF_STAIRINDEX;
|
||||
}
|
||||
if (gameinfo.flags & GI_NOSECTIONMERGE)
|
||||
{
|
||||
Level->ib_compatflags |= BCOMPATF_NOSECTIONMERGE;
|
||||
}
|
||||
}
|
||||
|
||||
map->GetChecksum(md5.Bytes);
|
||||
|
|
|
|||
|
|
@ -677,20 +677,26 @@ enum EViewPosFlags // [MC] Flags for SetViewPos.
|
|||
VPSF_ABSOLUTEPOS = 1 << 2, // Use absolute position.
|
||||
};
|
||||
|
||||
struct ModelOverride
|
||||
{
|
||||
int modelID;
|
||||
TArray<FTextureID> surfaceSkinIDs;
|
||||
};
|
||||
|
||||
class DActorModelData : public DObject
|
||||
{
|
||||
DECLARE_CLASS(DActorModelData, DObject);
|
||||
public:
|
||||
FName modelDef;
|
||||
bool hasModel;
|
||||
TArray<int> modelIDs;
|
||||
TArray<FTextureID> skinIDs;
|
||||
TArray<FTextureID> surfaceSkinIDs;
|
||||
TArray<int> animationIDs;
|
||||
TArray<int> modelFrameGenerators;
|
||||
FName modelDef;
|
||||
bool hasModel;
|
||||
TArray<ModelOverride> models;
|
||||
TArray<FTextureID> skinIDs;
|
||||
TArray<int> animationIDs;
|
||||
TArray<int> modelFrameGenerators;
|
||||
|
||||
DActorModelData() = default;
|
||||
virtual void Serialize(FSerializer& arc) override;
|
||||
virtual void OnDestroy() override;
|
||||
};
|
||||
|
||||
class DViewPosition : public DObject
|
||||
|
|
|
|||
|
|
@ -5107,7 +5107,212 @@ enum ChangeModelFlags
|
|||
CMDL_USESURFACESKIN = 1 << 2,
|
||||
};
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_ChangeModel)
|
||||
void ChangeModelNative(
|
||||
AActor * self,
|
||||
AActor * invoker,
|
||||
FStateParamInfo * stateinfo,
|
||||
int i_modeldef,
|
||||
int i_modelindex,
|
||||
const FString &p_modelpath,
|
||||
int i_model,
|
||||
int i_skinindex,
|
||||
const FString &p_skinpath,
|
||||
int i_skin,
|
||||
int flags,
|
||||
int generatorindex,
|
||||
int i_animationindex,
|
||||
const FString &p_animationpath,
|
||||
int i_animation
|
||||
) {
|
||||
if(!self) ThrowAbortException(X_READ_NIL, "In function parameter self");
|
||||
|
||||
FName modeldef { ENamedName(i_modeldef) };
|
||||
FName model { ENamedName(i_model) };
|
||||
FName skin { ENamedName(i_skin) };
|
||||
FName animation { ENamedName(i_animation) };
|
||||
|
||||
if (modeldef != NAME_None && PClass::FindClass(modeldef.GetChars()) == nullptr)
|
||||
{
|
||||
Printf("Attempt to pass invalid modeldef name %s in %s.", modeldef.GetChars(), self->GetCharacterName());
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned modelindex = i_modelindex < 0 ? 0 : i_modelindex;
|
||||
unsigned skinindex = i_skinindex < 0 ? 0 : i_skinindex;
|
||||
unsigned animationindex = i_animationindex < 0 ? 0 : i_animationindex;
|
||||
|
||||
AActor* mobj = (ACTION_CALL_FROM_PSPRITE() && (flags & CMDL_WEAPONTOPLAYER)) || ACTION_CALL_FROM_INVENTORY() ? self : invoker;
|
||||
|
||||
FString modelpath = p_modelpath;
|
||||
FString skinpath = p_skinpath;
|
||||
FString animationpath = p_animationpath;
|
||||
|
||||
if (modelpath.Len() != 0 && modelpath[(int)modelpath.Len() - 1] != '/') modelpath += '/';
|
||||
if (skinpath.Len() != 0 && skinpath[(int)skinpath.Len() - 1] != '/') skinpath += '/';
|
||||
if (animationpath.Len() != 0 && animationpath[(int)animationpath.Len() - 1] != '/') animationpath += '/';
|
||||
|
||||
if (mobj->modelData == nullptr)
|
||||
{
|
||||
auto ptr = Create<DActorModelData>();
|
||||
|
||||
ptr->hasModel = mobj->hasmodel;
|
||||
ptr->modelDef = NAME_None;
|
||||
|
||||
mobj->modelData = ptr;
|
||||
mobj->hasmodel = true;
|
||||
GC::WriteBarrier(mobj, ptr);
|
||||
};
|
||||
|
||||
int queryModel = !(flags & CMDL_HIDEMODEL) ? model != NAME_None ? FindModel(modelpath.GetChars(), model.GetChars()) : -1 : -2;
|
||||
int queryAnimation = animation != NAME_None ? FindModel(animationpath.GetChars(), animation.GetChars()) : -1;
|
||||
|
||||
mobj->modelData->modelDef = modeldef;
|
||||
|
||||
assert(mobj->modelData->models.Size() == mobj->modelData->modelFrameGenerators.Size());
|
||||
|
||||
if(mobj->modelData->models.Size() < modelindex)
|
||||
{
|
||||
mobj->modelData->models.AppendFill({-1, {}}, modelindex - mobj->modelData->models.Size());
|
||||
mobj->modelData->modelFrameGenerators.AppendFill(-1, modelindex - mobj->modelData->modelFrameGenerators.Size());
|
||||
}
|
||||
|
||||
if(mobj->modelData->animationIDs.Size() < animationindex)
|
||||
{
|
||||
mobj->modelData->animationIDs.AppendFill(-1, animationindex - mobj->modelData->animationIDs.Size());
|
||||
}
|
||||
|
||||
auto skindata = skin != NAME_None ? LoadSkin(skinpath.GetChars(), skin.GetChars()) : FNullTextureID();
|
||||
|
||||
if(mobj->modelData->models.Size() == modelindex)
|
||||
{
|
||||
|
||||
if(flags & CMDL_USESURFACESKIN && skinindex >= 0)
|
||||
{
|
||||
TArray<FTextureID> surfaceSkins;
|
||||
if(skinindex > 0)
|
||||
{
|
||||
surfaceSkins.AppendFill(FNullTextureID(), skinindex);
|
||||
}
|
||||
surfaceSkins.Push(skindata);
|
||||
mobj->modelData->models.Push({queryModel, std::move(surfaceSkins)});
|
||||
mobj->modelData->modelFrameGenerators.Push(generatorindex);
|
||||
}
|
||||
else
|
||||
{
|
||||
mobj->modelData->models.Push({queryModel, {}});
|
||||
mobj->modelData->modelFrameGenerators.Push(generatorindex);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(flags & CMDL_USESURFACESKIN && skinindex >= 0)
|
||||
{
|
||||
if(skinindex > mobj->modelData->models[modelindex].surfaceSkinIDs.Size())
|
||||
{
|
||||
mobj->modelData->models[modelindex].surfaceSkinIDs.AppendFill(FNullTextureID(), skinindex - mobj->modelData->models[modelindex].surfaceSkinIDs.Size());
|
||||
}
|
||||
|
||||
if(skinindex == mobj->modelData->models[modelindex].surfaceSkinIDs.Size())
|
||||
{
|
||||
mobj->modelData->models[modelindex].surfaceSkinIDs.Push(skindata);
|
||||
}
|
||||
else
|
||||
{
|
||||
mobj->modelData->models[modelindex].surfaceSkinIDs[skinindex] = skindata;
|
||||
}
|
||||
}
|
||||
if(queryModel != -1) mobj->modelData->models[modelindex].modelID = queryModel;
|
||||
if(generatorindex != -1) mobj->modelData->modelFrameGenerators[modelindex] = generatorindex;
|
||||
}
|
||||
|
||||
if(mobj->modelData->animationIDs.Size() == animationindex)
|
||||
{
|
||||
mobj->modelData->animationIDs.Push(queryAnimation);
|
||||
}
|
||||
else
|
||||
{
|
||||
mobj->modelData->animationIDs[animationindex] = queryAnimation;
|
||||
}
|
||||
|
||||
if (!(flags & CMDL_USESURFACESKIN))
|
||||
{
|
||||
if(mobj->modelData->skinIDs.Size() < skinindex)
|
||||
{
|
||||
mobj->modelData->skinIDs.AppendFill(FNullTextureID(), skinindex - mobj->modelData->skinIDs.Size());
|
||||
}
|
||||
|
||||
if(mobj->modelData->skinIDs.Size() == skinindex)
|
||||
{
|
||||
mobj->modelData->skinIDs.Push(skindata);
|
||||
}
|
||||
else
|
||||
{
|
||||
mobj->modelData->skinIDs[skinindex] = skindata;
|
||||
}
|
||||
}
|
||||
|
||||
//[SM] - We need to serialize file paths and model names so that they are pushed on loading save files. Likewise, let's not include models that were already parsed when initialized.
|
||||
if (queryModel >= 0)
|
||||
{
|
||||
FString fullName;
|
||||
fullName.Format("%s%s", modelpath.GetChars(), model.GetChars());
|
||||
bool found = false;
|
||||
|
||||
for (auto &m : savedModelFiles)
|
||||
{
|
||||
if(m.CompareNoCase(fullName) == 0)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found) for (auto &m : Models)
|
||||
{
|
||||
if (m->mFileName.CompareNoCase(fullName) == 0)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found) savedModelFiles.Push(fullName);
|
||||
}
|
||||
//Same for animations
|
||||
if (queryAnimation >= 0)
|
||||
{
|
||||
FString fullName;
|
||||
fullName.Format("%s%s", animationpath.GetChars(), animation.GetChars());
|
||||
bool found = false;
|
||||
|
||||
for (auto &m : savedModelFiles)
|
||||
{
|
||||
if(m.CompareNoCase(fullName) == 0)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found) for (auto &m : Models)
|
||||
{
|
||||
if (m->mFileName.CompareNoCase(fullName) == 0)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found) savedModelFiles.Push(fullName);
|
||||
}
|
||||
|
||||
if (mobj->modelData->models.Size() == 0 && mobj->modelData->modelFrameGenerators.Size() == 0 && mobj->modelData->skinIDs.Size() == 0 && mobj->modelData->animationIDs.Size() == 0 && modeldef == NAME_None)
|
||||
{
|
||||
mobj->hasmodel = mobj->modelData->hasModel;
|
||||
mobj->modelData->Destroy();
|
||||
mobj->modelData = nullptr;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(AActor, A_ChangeModel, ChangeModelNative)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE(AActor);
|
||||
PARAM_NAME(modeldef);
|
||||
|
|
@ -5122,141 +5327,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_ChangeModel)
|
|||
PARAM_INT(animationindex);
|
||||
PARAM_STRING_VAL(animationpath);
|
||||
PARAM_NAME(animation);
|
||||
|
||||
if (self == nullptr)
|
||||
ACTION_RETURN_BOOL(false);
|
||||
else if (modeldef != NAME_None && PClass::FindClass(modeldef.GetChars()) == nullptr)
|
||||
{
|
||||
Printf("Attempt to pass invalid modeldef name %s in %s.", modeldef.GetChars(), self->GetCharacterName());
|
||||
ACTION_RETURN_BOOL(false);
|
||||
}
|
||||
else if (modelindex < 0)
|
||||
{
|
||||
Printf("Attempt to pass invalid model index %d in %s, index must be non-negative.", modelindex, self->GetCharacterName());
|
||||
ACTION_RETURN_BOOL(false);
|
||||
}
|
||||
else if (skinindex < 0)
|
||||
{
|
||||
Printf("Attempt to pass invalid skin index %d in %s, index must be non-negative.", skinindex, self->GetCharacterName());
|
||||
ACTION_RETURN_BOOL(false);
|
||||
}
|
||||
else if (animationindex < 0)
|
||||
{
|
||||
Printf("Attempt to pass invalid animation index %d in %s, index must be non-negative.", animationindex, self->GetCharacterName());
|
||||
ACTION_RETURN_BOOL(false);
|
||||
}
|
||||
|
||||
AActor* mobj = (ACTION_CALL_FROM_PSPRITE() && (flags & CMDL_WEAPONTOPLAYER)) || ACTION_CALL_FROM_INVENTORY() ? self : stateowner;
|
||||
|
||||
if (modelpath[(int)modelpath.Len() - 1] != '/') modelpath += '/';
|
||||
if (skinpath[(int)skinpath.Len() - 1] != '/') skinpath += '/';
|
||||
if (animationpath[(int)animationpath.Len() - 1] != '/') animationpath += '/';
|
||||
|
||||
if (mobj->modelData == nullptr)
|
||||
{
|
||||
auto ptr = Create<DActorModelData>();
|
||||
ptr->hasModel = mobj->hasmodel ? 1 : 0;
|
||||
ptr->modelIDs = *new TArray<int>();
|
||||
ptr->skinIDs = *new TArray<FTextureID>();
|
||||
ptr->surfaceSkinIDs = *new TArray<FTextureID>();
|
||||
ptr->animationIDs = *new TArray<int>();
|
||||
ptr->modelFrameGenerators = *new TArray<int>();
|
||||
ptr->modelDef = NAME_None;
|
||||
mobj->modelData = ptr;
|
||||
mobj->hasmodel = 1;
|
||||
GC::WriteBarrier(mobj, ptr);
|
||||
}
|
||||
|
||||
int maxModels = mobj->modelData->modelIDs.Size();
|
||||
int maxSkins = mobj->modelData->skinIDs.Size();
|
||||
int maxSurfaceSkins = mobj->modelData->surfaceSkinIDs.Size();
|
||||
int maxAnimations = mobj->modelData->animationIDs.Size();
|
||||
int maxGenerators = mobj->modelData->modelFrameGenerators.Size();
|
||||
|
||||
int skinPosition = skinindex + modelindex * MD3_MAX_SURFACES;
|
||||
|
||||
int queryModel = !(flags & CMDL_HIDEMODEL) ? model != NAME_None ? FindModel(modelpath.GetChars(), model.GetChars()) : -1 : -2;
|
||||
int queryAnimation = animation != NAME_None ? FindModel(animationpath.GetChars(), animation.GetChars()) : -1;
|
||||
|
||||
//[SM] - Let's clear out any potential entries at the specified indices
|
||||
mobj->modelData->modelDef = modeldef;
|
||||
if(maxModels > modelindex) mobj->modelData->modelIDs.Pop(mobj->modelData->modelIDs[modelindex]);
|
||||
if(maxAnimations > animationindex) mobj->modelData->animationIDs.Pop(mobj->modelData->animationIDs[animationindex]);
|
||||
if(maxGenerators > modelindex) mobj->modelData->modelFrameGenerators.Pop(mobj->modelData->modelFrameGenerators[modelindex]);
|
||||
|
||||
if (flags & CMDL_USESURFACESKIN)
|
||||
{
|
||||
if (maxSurfaceSkins > skinPosition)
|
||||
mobj->modelData->surfaceSkinIDs.Delete(skinPosition); //[SM] - It seems the only way to make sure this does what it's told is from Delete, not Pop
|
||||
}
|
||||
else
|
||||
{
|
||||
if (maxSkins > skinindex)
|
||||
mobj->modelData->skinIDs.Pop(mobj->modelData->skinIDs[skinindex]);
|
||||
}
|
||||
|
||||
//[SM] - We need to fill up any holes this new index will make so that it doesn't leave behind any undefined behavior
|
||||
while ((int)mobj->modelData->modelIDs.Size() < modelindex) mobj->modelData->modelIDs.Push(-1);
|
||||
while ((int)mobj->modelData->modelFrameGenerators.Size() < modelindex) mobj->modelData->modelFrameGenerators.Push(-1);
|
||||
while ((int)mobj->modelData->animationIDs.Size() < modelindex) mobj->modelData->animationIDs.Push(-1);
|
||||
if (flags & CMDL_USESURFACESKIN)
|
||||
while ((int)mobj->modelData->surfaceSkinIDs.Size() < skinPosition) mobj->modelData->surfaceSkinIDs.Push(FNullTextureID());
|
||||
else
|
||||
while ((int)mobj->modelData->skinIDs.Size() < skinindex) mobj->modelData->skinIDs.Push(FNullTextureID());
|
||||
|
||||
mobj->modelData->modelIDs.Insert(modelindex, queryModel);
|
||||
mobj->modelData->modelFrameGenerators.Insert(modelindex, generatorindex);
|
||||
mobj->modelData->animationIDs.Insert(animationindex, queryAnimation);
|
||||
if (flags & CMDL_USESURFACESKIN)
|
||||
mobj->modelData->surfaceSkinIDs.Insert(skinPosition, skin != NAME_None ? LoadSkin(skinpath.GetChars(), skin.GetChars()) : FNullTextureID());
|
||||
else
|
||||
mobj->modelData->skinIDs.Insert(skinindex, skin != NAME_None ? LoadSkin(skinpath.GetChars(), skin.GetChars()) : FNullTextureID());
|
||||
|
||||
//[SM] - We need to serialize file paths and model names so that they are pushed on loading save files. Likewise, let's not include models that were already parsed when initialized.
|
||||
if (queryModel >= 0)
|
||||
{
|
||||
FString fullName;
|
||||
fullName.Format("%s%s", modelpath.GetChars(), model.GetChars());
|
||||
bool allowPush = true;
|
||||
for (unsigned i = 0; i < savedModelFiles.Size(); i++) if (!savedModelFiles[i].CompareNoCase(fullName)) allowPush = false;
|
||||
for (unsigned i = 0; i < Models.Size()-1; i++) if (!Models[i]->mFileName.CompareNoCase(fullName)) allowPush = false;
|
||||
|
||||
if(allowPush) savedModelFiles.Push(fullName);
|
||||
}
|
||||
//Same for animations
|
||||
if (queryAnimation >= 0)
|
||||
{
|
||||
FString fullName;
|
||||
fullName.Format("%s%s", animationpath.GetChars(), animation.GetChars());
|
||||
bool allowPush = true;
|
||||
for (unsigned i = 0; i < savedModelFiles.Size(); i++) if (!savedModelFiles[i].CompareNoCase(fullName)) allowPush = false;
|
||||
for (unsigned i = 0; i < Models.Size() - 1; i++) if (!Models[i]->mFileName.CompareNoCase(fullName)) allowPush = false;
|
||||
|
||||
if (allowPush) savedModelFiles.Push(fullName);
|
||||
}
|
||||
|
||||
//[SM] - if an indice of modelIDs or skinIDs comes up blank and it's the last one, just delete it. For using very large amounts of indices, common sense says to just not run this repeatedly.
|
||||
while (mobj->modelData->modelIDs.Size() > 0 && mobj->modelData->modelIDs.Last() == -1)
|
||||
mobj->modelData->modelIDs.Pop(mobj->modelData->modelIDs.Last());
|
||||
while (mobj->modelData->modelFrameGenerators.Size() > 0 && mobj->modelData->modelFrameGenerators.Last() == -1)
|
||||
mobj->modelData->modelFrameGenerators.Pop(mobj->modelData->modelFrameGenerators.Last());
|
||||
while (mobj->modelData->skinIDs.Size() > 0 && mobj->modelData->skinIDs.Last() == FNullTextureID())
|
||||
mobj->modelData->skinIDs.Pop(mobj->modelData->skinIDs.Last());
|
||||
while (mobj->modelData->surfaceSkinIDs.Size() > 0 && mobj->modelData->surfaceSkinIDs.Last() == FNullTextureID())
|
||||
mobj->modelData->surfaceSkinIDs.Pop(mobj->modelData->surfaceSkinIDs.Last());
|
||||
while (mobj->modelData->animationIDs.Size() > 0 && mobj->modelData->animationIDs.Last() == -1)
|
||||
mobj->modelData->animationIDs.Pop(mobj->modelData->animationIDs.Last());
|
||||
|
||||
if (mobj->modelData->modelIDs.Size() == 0 && mobj->modelData->modelFrameGenerators.Size() == 0 && mobj->modelData->skinIDs.Size() == 0 && mobj->modelData->surfaceSkinIDs.Size() == 0 && mobj->modelData->animationIDs.Size() == 0 && modeldef == NAME_None)
|
||||
{
|
||||
mobj->hasmodel = mobj->modelData->hasModel;
|
||||
mobj->modelData->modelIDs.Reset();
|
||||
mobj->modelData->modelFrameGenerators.Reset();
|
||||
mobj->modelData->skinIDs.Reset();
|
||||
mobj->modelData->surfaceSkinIDs.Reset();
|
||||
mobj->modelData->animationIDs.Reset();
|
||||
mobj->modelData->Destroy();
|
||||
}
|
||||
ChangeModelNative(self,stateowner,stateinfo,modeldef.GetIndex(),modelindex,modelpath,model.GetIndex(),skinindex,skinpath,skin.GetIndex(),flags,generatorindex,animationindex,animationpath,animation.GetIndex());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1335,13 +1335,24 @@ static int DamageMobj (AActor *target, AActor *inflictor, AActor *source, int da
|
|||
}
|
||||
}
|
||||
|
||||
bool compat_voodoo_zombie = target->Level->i_compatflags2 & COMPATF2_VOODOO_ZOMBIES;
|
||||
|
||||
player->health -= damage; // mirror mobj health here for Dave
|
||||
// [RH] Make voodoo dolls and real players record the same health
|
||||
target->health = player->mo->health -= damage;
|
||||
if(compat_voodoo_zombie)
|
||||
{ // [RL0] To allow voodoo zombies, don't set the voodoo doll to the player mobj's health and don't change the player mobj's health on damage
|
||||
target->health -= damage;
|
||||
}
|
||||
else
|
||||
{ // [RH] Make voodoo dolls and real players record the same health
|
||||
target->health = player->mo->health -= damage;
|
||||
}
|
||||
if (player->health < 50 && !deathmatch && !(flags & DMG_FORCED))
|
||||
{
|
||||
P_AutoUseStrifeHealth (player);
|
||||
player->mo->health = player->health;
|
||||
if(!compat_voodoo_zombie)
|
||||
{ // [RL0] To match vanilla behavior, don't set the player mo's health to 0 if voodoo zombies compat is enabled
|
||||
player->mo->health = player->health;
|
||||
}
|
||||
}
|
||||
if (player->health <= 0)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1324,18 +1324,36 @@ bool AActor::Massacre ()
|
|||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
FSerializer &Serialize(FSerializer &arc, const char *key, ModelOverride &sid, ModelOverride *def)
|
||||
{
|
||||
arc.BeginObject(key);
|
||||
arc("modelID", sid.modelID);
|
||||
arc("surfaceSkinIDs", sid.surfaceSkinIDs);
|
||||
arc.EndObject();
|
||||
return arc;
|
||||
}
|
||||
|
||||
void DActorModelData::Serialize(FSerializer& arc)
|
||||
{
|
||||
Super::Serialize(arc);
|
||||
arc("modelDef", modelDef)
|
||||
("modelIDs", modelIDs)
|
||||
("models", models)
|
||||
("skinIDs", skinIDs)
|
||||
("surfaceSkinIDs", surfaceSkinIDs)
|
||||
//("surfaceSkinIDs", surfaceSkinIDs)
|
||||
("animationIDs", animationIDs)
|
||||
("modelFrameGenerators", modelFrameGenerators)
|
||||
("hasModel", hasModel);
|
||||
}
|
||||
|
||||
void DActorModelData::OnDestroy()
|
||||
{
|
||||
models.Reset();
|
||||
modelFrameGenerators.Reset();
|
||||
skinIDs.Reset();
|
||||
//surfaceSkinIDs.Reset();
|
||||
animationIDs.Reset();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// PROC P_ExplodeMissile
|
||||
|
|
|
|||
|
|
@ -187,7 +187,7 @@ TArray<FString> I_GetSteamPath()
|
|||
return result;
|
||||
}
|
||||
|
||||
SteamInstallFolders.Push(appSupportPath + "/Steam/SteamApps/common");
|
||||
SteamInstallFolders.Push(appSupportPath + "/Steam/steamapps/common");
|
||||
#else
|
||||
char* home = getenv("HOME");
|
||||
if(home != NULL && *home != '\0')
|
||||
|
|
@ -198,7 +198,7 @@ TArray<FString> I_GetSteamPath()
|
|||
// .steam at some point. Not sure if it's just my setup so I guess we
|
||||
// can fall back on it?
|
||||
if(!FileExists(regPath))
|
||||
regPath.Format("%s/.local/share/Steam/config/config.vdf", home);
|
||||
regPath.Format("%s/.steam/steam/config/config.vdf", home);
|
||||
|
||||
try
|
||||
{
|
||||
|
|
@ -210,7 +210,7 @@ TArray<FString> I_GetSteamPath()
|
|||
return result;
|
||||
}
|
||||
|
||||
regPath.Format("%s/.local/share/Steam/SteamApps/common", home);
|
||||
regPath.Format("%s/.steam/steam/steamapps/common", home);
|
||||
SteamInstallFolders.Push(regPath);
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -316,12 +316,12 @@ void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpr
|
|||
}
|
||||
}
|
||||
|
||||
int modelsamount = smf->modelsAmount;
|
||||
unsigned modelsamount = smf->modelsAmount;
|
||||
//[SM] - if we added any models for the frame to also render, then we also need to update modelsAmount for this smf
|
||||
if (actor->modelData != nullptr)
|
||||
{
|
||||
if (actor->modelData->modelIDs.Size() > (unsigned)modelsamount)
|
||||
modelsamount = actor->modelData->modelIDs.Size();
|
||||
if (actor->modelData->models.Size() > modelsamount)
|
||||
modelsamount = actor->modelData->models.Size();
|
||||
}
|
||||
|
||||
TArray<FTextureID> surfaceskinids;
|
||||
|
|
@ -330,57 +330,112 @@ void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpr
|
|||
int boneStartingPosition = 0;
|
||||
bool evaluatedSingle = false;
|
||||
|
||||
for (int i = 0; i < modelsamount; i++)
|
||||
for (unsigned i = 0; i < modelsamount; i++)
|
||||
{
|
||||
int modelid = -1;
|
||||
int animationid = -1;
|
||||
int modelframe = -1;
|
||||
int modelframenext = -1;
|
||||
FTextureID skinid; skinid.SetInvalid();
|
||||
FTextureID skinid; skinid.SetNull();
|
||||
|
||||
surfaceskinids.Clear();
|
||||
|
||||
if (actor->modelData != nullptr)
|
||||
{
|
||||
if (i < (int)actor->modelData->modelIDs.Size())
|
||||
modelid = actor->modelData->modelIDs[i];
|
||||
|
||||
if (i < (int)actor->modelData->animationIDs.Size())
|
||||
animationid = actor->modelData->animationIDs[i];
|
||||
|
||||
if (i < (int)actor->modelData->modelFrameGenerators.Size())
|
||||
//modelID
|
||||
if (actor->modelData->models.Size() > i && actor->modelData->models[i].modelID >= 0)
|
||||
{
|
||||
//[SM] - We will use this little snippet to allow a modder to specify a model index to clone. It's also pointless to clone something that clones something else in this case. And causes me headaches.
|
||||
if (actor->modelData->modelFrameGenerators[i] >= 0 && actor->modelData->modelFrameGenerators[i] <= modelsamount && smf->modelframes[actor->modelData->modelFrameGenerators[i]] != -1)
|
||||
modelid = actor->modelData->models[i].modelID;
|
||||
}
|
||||
else if(actor->modelData->models.Size() > i && actor->modelData->models[i].modelID == -2)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if(smf->modelsAmount > i)
|
||||
{
|
||||
modelid = smf->modelIDs[i];
|
||||
}
|
||||
|
||||
//animationID
|
||||
if (actor->modelData->animationIDs.Size() > i && actor->modelData->animationIDs[i] >= 0)
|
||||
{
|
||||
animationid = actor->modelData->animationIDs[i];
|
||||
}
|
||||
else if(smf->modelsAmount > i)
|
||||
{
|
||||
animationid = smf->animationIDs[i];
|
||||
}
|
||||
|
||||
//modelFrame
|
||||
if (actor->modelData->modelFrameGenerators.Size() > i
|
||||
&& actor->modelData->modelFrameGenerators[i] >= 0
|
||||
&& actor->modelData->modelFrameGenerators[i] < modelsamount
|
||||
&& smf->modelframes[actor->modelData->modelFrameGenerators[i]] >= 0
|
||||
) {
|
||||
modelframe = smf->modelframes[actor->modelData->modelFrameGenerators[i]];
|
||||
|
||||
if (smfNext)
|
||||
{
|
||||
modelframe = smf->modelframes[actor->modelData->modelFrameGenerators[i]];
|
||||
if (smfNext) modelframenext = smfNext->modelframes[actor->modelData->modelFrameGenerators[i]];
|
||||
if(smfNext->modelframes[actor->modelData->modelFrameGenerators[i]] >= 0)
|
||||
{
|
||||
modelframenext = smfNext->modelframes[actor->modelData->modelFrameGenerators[i]];
|
||||
}
|
||||
else
|
||||
{
|
||||
modelframenext = smfNext->modelframes[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (i < (int)actor->modelData->skinIDs.Size())
|
||||
else if(smf->modelsAmount > i)
|
||||
{
|
||||
if (actor->modelData->skinIDs[i].isValid())
|
||||
skinid = actor->modelData->skinIDs[i];
|
||||
modelframe = smf->modelframes[i];
|
||||
if (smfNext) modelframenext = smfNext->modelframes[i];
|
||||
}
|
||||
for (int surface = i * MD3_MAX_SURFACES; surface < (i + 1) * MD3_MAX_SURFACES; surface++)
|
||||
|
||||
//skinID
|
||||
if (actor->modelData->skinIDs.Size() > i && actor->modelData->skinIDs[i].isValid())
|
||||
{
|
||||
if (surface < (int)actor->modelData->surfaceSkinIDs.Size())
|
||||
skinid = actor->modelData->skinIDs[i];
|
||||
}
|
||||
else if(smf->modelsAmount > i)
|
||||
{
|
||||
skinid = smf->skinIDs[i];
|
||||
}
|
||||
|
||||
//surfaceSkinIDs
|
||||
if(actor->modelData->models.Size() > i && actor->modelData->models[i].surfaceSkinIDs.Size() > 0)
|
||||
{
|
||||
unsigned sz1 = smf->surfaceskinIDs.Size();
|
||||
unsigned sz2 = actor->modelData->models[i].surfaceSkinIDs.Size();
|
||||
unsigned start = i * MD3_MAX_SURFACES;
|
||||
|
||||
surfaceskinids = actor->modelData->models[i].surfaceSkinIDs;
|
||||
surfaceskinids.Resize(MD3_MAX_SURFACES);
|
||||
|
||||
for (unsigned surface = 0; surface < MD3_MAX_SURFACES; surface++)
|
||||
{
|
||||
if (actor->modelData->surfaceSkinIDs[surface].isValid())
|
||||
if (sz2 > surface && (actor->modelData->models[i].surfaceSkinIDs[surface].isValid()))
|
||||
{
|
||||
// only make a copy of the surfaceskinIDs array if really needed
|
||||
if (surfaceskinids.Size() == 0) surfaceskinids = smf->surfaceskinIDs;
|
||||
surfaceskinids[surface] = actor->modelData->surfaceSkinIDs[surface];
|
||||
continue;
|
||||
}
|
||||
if((surface + start) < sz1)
|
||||
{
|
||||
surfaceskinids[surface] = smf->surfaceskinIDs[surface + start];
|
||||
}
|
||||
else
|
||||
{
|
||||
surfaceskinids[surface].SetNull();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (i < smf->modelsAmount)
|
||||
else
|
||||
{
|
||||
if (modelid == -1) modelid = smf->modelIDs[i];
|
||||
if (animationid == -1) animationid = smf->animationIDs[i];
|
||||
if (modelframe == -1) modelframe = smf->modelframes[i];
|
||||
if (modelframenext == -1 && smfNext) modelframenext = smfNext->modelframes[i];
|
||||
if (!skinid.isValid()) skinid = smf->skinIDs[i];
|
||||
modelid = smf->modelIDs[i];
|
||||
animationid = smf->animationIDs[i];
|
||||
modelframe = smf->modelframes[i];
|
||||
if (smfNext) modelframenext = smfNext->modelframes[i];
|
||||
skinid = smf->skinIDs[i];
|
||||
}
|
||||
|
||||
if (modelid >= 0)
|
||||
|
|
@ -389,8 +444,9 @@ void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpr
|
|||
auto tex = skinid.isValid() ? TexMan.GetGameTexture(skinid, true) : nullptr;
|
||||
mdl->BuildVertexBuffer(renderer);
|
||||
|
||||
auto& ssids = surfaceskinids.Size() > 0 ? surfaceskinids : smf->surfaceskinIDs;
|
||||
auto ssidp = (unsigned)(i * MD3_MAX_SURFACES) < ssids.Size() ? &ssids[i * MD3_MAX_SURFACES] : nullptr;
|
||||
auto ssidp = surfaceskinids.Size() > 0
|
||||
? surfaceskinids.Data()
|
||||
: (((i * MD3_MAX_SURFACES) < smf->surfaceskinIDs.Size()) ? &smf->surfaceskinIDs[i * MD3_MAX_SURFACES] : nullptr);
|
||||
|
||||
|
||||
bool nextFrame = smfNext && modelframe != modelframenext;
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
||||
void UpdateVanillaTransparency();
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
|
||||
#pragma once
|
||||
#include "tarray.h"
|
||||
#include "r_defs.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "textures.h"
|
||||
#include "texturemanager.h"
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@
|
|||
#include "g_game.h"
|
||||
#include "s_music.h"
|
||||
#include "v_draw.h"
|
||||
#include "m_argv.h"
|
||||
|
||||
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
||||
|
||||
|
|
@ -229,7 +230,7 @@ void S_Init()
|
|||
}
|
||||
|
||||
I_InitSound();
|
||||
I_InitMusic();
|
||||
I_InitMusic(Args->CheckParm("-nomusic") || Args->CheckParm("-nosound"));
|
||||
|
||||
// Heretic and Hexen have sound curve lookup tables. Doom does not.
|
||||
int curvelump = fileSystem.CheckNumForName("SNDCURVE");
|
||||
|
|
|
|||
|
|
@ -80,6 +80,112 @@
|
|||
#include "cmdlib.h"
|
||||
#include "i_interface.h"
|
||||
|
||||
|
||||
//TODO maybe move this code to a separate cpp file, so that there isn't code duplication between the win32 and posix backends
|
||||
static void PSR_FindEndBlock(FScanner &sc)
|
||||
{
|
||||
int depth = 1;
|
||||
do
|
||||
{
|
||||
if(sc.CheckToken('}'))
|
||||
--depth;
|
||||
else if(sc.CheckToken('{'))
|
||||
++depth;
|
||||
else
|
||||
sc.MustGetAnyToken();
|
||||
}
|
||||
while(depth);
|
||||
}
|
||||
static void PSR_SkipBlock(FScanner &sc)
|
||||
{
|
||||
sc.MustGetToken('{');
|
||||
PSR_FindEndBlock(sc);
|
||||
}
|
||||
static bool PSR_FindAndEnterBlock(FScanner &sc, const char* keyword)
|
||||
{
|
||||
// Finds a block with a given keyword and then enter it (opening brace)
|
||||
// Should be closed with PSR_FindEndBlock
|
||||
while(sc.GetToken())
|
||||
{
|
||||
if(sc.TokenType == '}')
|
||||
{
|
||||
sc.UnGet();
|
||||
return false;
|
||||
}
|
||||
|
||||
sc.TokenMustBe(TK_StringConst);
|
||||
if(!sc.Compare(keyword))
|
||||
{
|
||||
if(!sc.CheckToken(TK_StringConst))
|
||||
PSR_SkipBlock(sc);
|
||||
}
|
||||
else
|
||||
{
|
||||
sc.MustGetToken('{');
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
static TArray<FString> PSR_ReadBaseInstalls(FScanner &sc)
|
||||
{
|
||||
TArray<FString> result;
|
||||
|
||||
// Get a list of possible install directories.
|
||||
while(sc.GetToken())
|
||||
{
|
||||
if(sc.TokenType == '}')
|
||||
break;
|
||||
|
||||
sc.TokenMustBe(TK_StringConst);
|
||||
FString key(sc.String);
|
||||
if(key.Left(18).CompareNoCase("BaseInstallFolder_") == 0)
|
||||
{
|
||||
sc.MustGetToken(TK_StringConst);
|
||||
result.Push(FString(sc.String) + "/steamapps/common");
|
||||
}
|
||||
else
|
||||
{
|
||||
if(sc.CheckToken('{'))
|
||||
PSR_FindEndBlock(sc);
|
||||
else
|
||||
sc.MustGetToken(TK_StringConst);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
static TArray<FString> ParseSteamRegistry(const char* path)
|
||||
{
|
||||
TArray<FString> dirs;
|
||||
|
||||
// Read registry data
|
||||
FScanner sc;
|
||||
if (sc.OpenFile(path))
|
||||
{
|
||||
sc.SetCMode(true);
|
||||
|
||||
// Find the SteamApps listing
|
||||
if (PSR_FindAndEnterBlock(sc, "InstallConfigStore"))
|
||||
{
|
||||
if (PSR_FindAndEnterBlock(sc, "Software"))
|
||||
{
|
||||
if (PSR_FindAndEnterBlock(sc, "Valve"))
|
||||
{
|
||||
if (PSR_FindAndEnterBlock(sc, "Steam"))
|
||||
{
|
||||
dirs = PSR_ReadBaseInstalls(sc);
|
||||
}
|
||||
PSR_FindEndBlock(sc);
|
||||
}
|
||||
PSR_FindEndBlock(sc);
|
||||
}
|
||||
PSR_FindEndBlock(sc);
|
||||
}
|
||||
}
|
||||
return dirs;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// QueryPathKey
|
||||
|
|
@ -240,18 +346,30 @@ TArray<FString> I_GetSteamPath()
|
|||
"Doom 2/finaldoombase"
|
||||
};
|
||||
|
||||
FString path;
|
||||
FString steamPath;
|
||||
|
||||
if (!QueryPathKey(HKEY_CURRENT_USER, L"Software\\Valve\\Steam", L"SteamPath", path))
|
||||
if (!QueryPathKey(HKEY_CURRENT_USER, L"Software\\Valve\\Steam", L"SteamPath", steamPath))
|
||||
{
|
||||
if (!QueryPathKey(HKEY_LOCAL_MACHINE, L"Software\\Valve\\Steam", L"InstallPath", path))
|
||||
if (!QueryPathKey(HKEY_LOCAL_MACHINE, L"Software\\Valve\\Steam", L"InstallPath", steamPath))
|
||||
return result;
|
||||
}
|
||||
path += "/SteamApps/common/";
|
||||
|
||||
TArray<FString> paths = ParseSteamRegistry(steamPath + "/config/config.vdf");
|
||||
|
||||
for(FString &path : paths)
|
||||
{
|
||||
path.ReplaceChars('\\','/');
|
||||
path+="/";
|
||||
}
|
||||
|
||||
paths.Push(steamPath + "/steamapps/common/");
|
||||
|
||||
for(unsigned int i = 0; i < countof(steam_dirs); ++i)
|
||||
{
|
||||
result.Push(path + steam_dirs[i]);
|
||||
for(const FString &path : paths)
|
||||
{
|
||||
result.Push(path + steam_dirs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
|
|||
|
|
@ -326,7 +326,9 @@ HE3TEXT = "";
|
|||
HE4TEXT = "";
|
||||
HE5TEXT = "";
|
||||
|
||||
//
|
||||
// mappings for duplicate texts
|
||||
//
|
||||
|
||||
CNTRLMNU_TITLE = "$$OPTMNU_CONTROLS";
|
||||
MOUSEMNU_TITLE = "$$OPTMNU_MOUSE";
|
||||
|
|
@ -337,9 +339,49 @@ OPENALMNU_TITLE = "$$SNDMNU_OPENAL";
|
|||
SNDMNU_TITLE = "$$OPTMNU_SOUND";
|
||||
MODMNU_TITLE = "$$SNDMNU_MODREPLAYER";
|
||||
MISCMNU_TITLE = "$$OPTMNU_MISCELLANEOUS";
|
||||
|
||||
GLMNU_TEXOPT = "$$GLTEXMNU_TITLE";
|
||||
|
||||
SCORE_ITEMS = "$$TXT_IMITEMS";
|
||||
SCORE_KILLS = "$$TXT_IMKILLS";
|
||||
|
||||
FN_ZOMBIE = "$$CC_ZOMBIE";
|
||||
FN_IMP = "$$CC_IMP";
|
||||
FN_DEMON = "$$CC_DEMON";
|
||||
FN_LOST = "$$CC_LOST";
|
||||
FN_CACO = "$$CC_CACO";
|
||||
FN_HELL = "$$CC_HELL";
|
||||
FN_BARON = "$$CC_BARON";
|
||||
FN_ARACH = "$$CC_ARACH";
|
||||
FN_PAIN = "$$CC_PAIN";
|
||||
FN_REVEN = "$$CC_REVEN";
|
||||
FN_MANCU = "$$CC_MANCU";
|
||||
FN_ARCH = "$$CC_ARCH";
|
||||
|
||||
TAG_GAUNTLETS = "$$TXT_WPNGAUNTLETS";
|
||||
TAG_GAUNTLETSP = "$$TXT_WPNGAUNTLETS";
|
||||
TAG_CROSSBOW = "$$TXT_WPNCROSSBOW";
|
||||
TAG_CROSSBOWP = "$$TXT_WPNCROSSBOW";
|
||||
TAG_STAFFP = "$$TAG_STAFF";
|
||||
TAG_GOLDWANDP = "$$TAG_GOLDWAND";
|
||||
TAG_BLASTER = "$$TXT_WPNBLASTER";
|
||||
TAG_BLASTERP = "$$TXT_WPNBLASTER";
|
||||
TAG_SKULLROD = "$$TXT_WPNSKULLROD";
|
||||
TAG_SKULLRODP = "$$TXT_WPNSKULLROD";
|
||||
TAG_PHOENIXROD = "$$TXT_WPNPHOENIXROD";
|
||||
TAG_PHOENIXRODP = "$$TXT_WPNPHOENIXROD";
|
||||
TAG_MACE = "$$TXT_WPNMACE";
|
||||
TAG_MACEP = "$$TXT_WPNMACE";
|
||||
|
||||
TAG_ARTIEGG = "$$TXT_ARTIEGG";
|
||||
TAG_ARTIFIREBOMB = "$$TXT_ARTIFIREBOMB";
|
||||
TAG_ARTIFLY = "$$TXT_ARTIFLY";
|
||||
TAG_ARTIHEALTH = "$$TXT_ARTIHEALTH";
|
||||
TAG_ARTIINVISIBILITY = "$$TXT_ARTIINVISIBILITY";
|
||||
TAG_ARTIINVULNERABILITY = "$$TXT_ARTIINVULNERABILITY";
|
||||
TAG_ARTITELEPORT = "$$TXT_ARTITELEPORT";
|
||||
TAG_ARTITOMEOFPOWER = "$$TXT_ARTITOMEOFPOWER";
|
||||
TAG_ARTITORCH = "$$TXT_ARTITORCH";
|
||||
|
||||
// newly added text not in the string table
|
||||
|
||||
OPTMNU_SWRENDERER = "Software Renderer";
|
||||
|
|
|
|||
|
|
@ -932,6 +932,7 @@ class Weapon : StateProvider
|
|||
int count1, count2;
|
||||
int enough, enoughmask;
|
||||
int lAmmoUse1;
|
||||
int lAmmoUse2 = AmmoUse2;
|
||||
|
||||
if (sv_infiniteammo || (Owner.FindInventory ('PowerInfiniteAmmo', true) != null))
|
||||
{
|
||||
|
|
@ -957,20 +958,21 @@ class Weapon : StateProvider
|
|||
count1 = (Ammo1 != null) ? Ammo1.Amount : 0;
|
||||
count2 = (Ammo2 != null) ? Ammo2.Amount : 0;
|
||||
|
||||
if (bDehAmmo && Ammo1 == null)
|
||||
{
|
||||
lAmmoUse1 = 0;
|
||||
}
|
||||
else if (ammocount >= 0 && bDehAmmo)
|
||||
if (ammocount >= 0)
|
||||
{
|
||||
lAmmoUse1 = ammocount;
|
||||
lAmmoUse2 = ammocount;
|
||||
}
|
||||
else if (bDehAmmo && Ammo1 == null)
|
||||
{
|
||||
lAmmoUse1 = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
lAmmoUse1 = AmmoUse1;
|
||||
}
|
||||
|
||||
enough = (count1 >= lAmmoUse1) | ((count2 >= AmmoUse2) << 1);
|
||||
enough = (count1 >= lAmmoUse1) | ((count2 >= lAmmoUse2) << 1);
|
||||
if (useboth)
|
||||
{
|
||||
enoughmask = 3;
|
||||
|
|
|
|||
|
|
@ -85,6 +85,11 @@ class PlayerPawn : Actor
|
|||
flagdef CanSuperMorph: PlayerFlags, 1;
|
||||
flagdef CrouchableMorph: PlayerFlags, 2;
|
||||
flagdef WeaponLevel2Ended: PlayerFlags, 3;
|
||||
|
||||
enum EPrivatePlayerFlags
|
||||
{
|
||||
PF_VOODOO_ZOMBIE = 1<<4,
|
||||
}
|
||||
|
||||
Default
|
||||
{
|
||||
|
|
@ -777,14 +782,16 @@ class PlayerPawn : Actor
|
|||
Super.Die (source, inflictor, dmgflags, MeansOfDeath);
|
||||
|
||||
if (player != NULL && player.mo == self) player.bonuscount = 0;
|
||||
|
||||
if (player != NULL && player.mo != self)
|
||||
|
||||
// [RL0] To allow voodoo zombies, don't kill the player together with voodoo dolls if the compat flag is enabled
|
||||
if (player != NULL && player.mo != self && !(Level.compatflags2 & COMPATF2_VOODOO_ZOMBIES))
|
||||
{ // Make the real player die, too
|
||||
player.mo.Die (source, inflictor, dmgflags, MeansOfDeath);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (player != NULL && sv_weapondrop)
|
||||
// [RL0] player.mo == self will always be true if COMPATF2_VOODOO_ZOMBIES is false, so there's no need to check the compatflag here too, just self
|
||||
if (player != NULL && sv_weapondrop && player.mo == self)
|
||||
{ // Voodoo dolls don't drop weapons
|
||||
let weap = player.ReadyWeapon;
|
||||
if (weap != NULL)
|
||||
|
|
@ -1609,6 +1616,12 @@ class PlayerPawn : Actor
|
|||
{
|
||||
let player = self.player;
|
||||
UserCmd cmd = player.cmd;
|
||||
|
||||
// [RL0] Mark players that became zombies (this stays even if they 'revive' by healing, until a level change)
|
||||
if((Level.compatflags2 & COMPATF2_VOODOO_ZOMBIES) && player.health <= 0 && player.mo.health > 0)
|
||||
{
|
||||
PlayerFlags |= PF_VOODOO_ZOMBIE;
|
||||
}
|
||||
|
||||
CheckFOV();
|
||||
|
||||
|
|
@ -1692,6 +1705,9 @@ class PlayerPawn : Actor
|
|||
|
||||
void BringUpWeapon ()
|
||||
{
|
||||
// [RL0] Don't bring up weapon when in a voodoo zombie state
|
||||
if(PlayerFlags & PF_VOODOO_ZOMBIE) return;
|
||||
|
||||
let player = self.player;
|
||||
if (player.PendingWeapon == WP_NOCHANGE)
|
||||
{
|
||||
|
|
@ -2007,6 +2023,19 @@ class PlayerPawn : Actor
|
|||
|
||||
void PlayerFinishLevel (int mode, int flags)
|
||||
{
|
||||
// [RL0] Handle player exit behavior for voodoo zombies
|
||||
if(PlayerFlags & PF_VOODOO_ZOMBIE)
|
||||
{
|
||||
if(player.health > 0)
|
||||
{
|
||||
PlayerFlags &= ~PF_VOODOO_ZOMBIE;
|
||||
}
|
||||
else
|
||||
{
|
||||
bShootable = false;
|
||||
bKilled = true;
|
||||
}
|
||||
}
|
||||
Inventory item, next;
|
||||
let p = player;
|
||||
|
||||
|
|
|
|||
|
|
@ -1429,6 +1429,11 @@ enum ECompatFlags
|
|||
COMPATF2_EXPLODE1 = 1 << 8, // No vertical explosion thrust
|
||||
COMPATF2_EXPLODE2 = 1 << 9, // Use original explosion code throughout.
|
||||
COMPATF2_RAILING = 1 << 10, // Bugged Strife railings.
|
||||
COMPATF2_SCRIPTWAIT = 1 << 11, // Use old scriptwait implementation where it doesn't wait on a non-running script.
|
||||
COMPATF2_AVOID_HAZARDS = 1 << 12, // another MBF thing.
|
||||
COMPATF2_STAYONLIFT = 1 << 13, // yet another MBF thing.
|
||||
COMPATF2_NOMBF21 = 1 << 14, // disable MBF21 features that may clash with certain maps
|
||||
COMPATF2_VOODOO_ZOMBIES = 1 << 15, // allow playerinfo, playerpawn, and voodoo health to all be different, and allow monster targetting of 'dead' players that have positive health
|
||||
};
|
||||
|
||||
const M_E = 2.7182818284590452354; // e
|
||||
|
|
|
|||
|
|
@ -326,7 +326,7 @@ IWad
|
|||
Config = "Doom"
|
||||
IWADName = "doom.wad", 2
|
||||
Mapinfo = "mapinfo/ultdoom.txt"
|
||||
Compatibility = "Shorttex"
|
||||
Compatibility = "Shorttex", "nosectionmerge"
|
||||
MustContain = "E1M1","E2M1","E2M2","E2M3","E2M4","E2M5","E2M6","E2M7","E2M8","E2M9",
|
||||
"E3M1","E3M2","E3M3","E3M4","E3M5","E3M6","E3M7","E3M8","E3M9",
|
||||
"DPHOOF","BFGGA0","HEADA1","CYBRA1","SPIDA1D1", "E4M2",
|
||||
|
|
@ -343,7 +343,7 @@ IWad
|
|||
Config = "Doom"
|
||||
IWADName = "doomunity.wad", 2
|
||||
Mapinfo = "mapinfo/ultdoom.txt"
|
||||
Compatibility = "Shorttex"
|
||||
Compatibility = "Shorttex", "nosectionmerge"
|
||||
MustContain = "E1M1","E2M1","E2M2","E2M3","E2M4","E2M5","E2M6","E2M7","E2M8","E2M9",
|
||||
"E3M1","E3M2","E3M3","E3M4","E3M5","E3M6","E3M7","E3M8","E3M9",
|
||||
"DPHOOF","BFGGA0","HEADA1","CYBRA1","SPIDA1D1", "E4M2",
|
||||
|
|
@ -375,7 +375,7 @@ IWad
|
|||
Config = "Doom"
|
||||
IWADName = "doom.wad"
|
||||
Mapinfo = "mapinfo/doomxbox.txt"
|
||||
Compatibility = "Shorttex"
|
||||
Compatibility = "Shorttex", "nosectionmerge"
|
||||
MustContain = "E1M1","E2M1","E2M2","E2M3","E2M4","E2M5","E2M6","E2M7","E2M8","E2M9",
|
||||
"E3M1","E3M2","E3M3","E3M4","E3M5","E3M6","E3M7","E3M8","E3M9",
|
||||
"DPHOOF","BFGGA0","HEADA1","CYBRA1","SPIDA1D1", "E4M2", "E1M10", "SEWERS"
|
||||
|
|
@ -391,7 +391,7 @@ IWad
|
|||
Config = "Doom"
|
||||
IWADName = "doom.wad"
|
||||
Mapinfo = "mapinfo/ultdoom.txt"
|
||||
Compatibility = "Shorttex"
|
||||
Compatibility = "Shorttex", "nosectionmerge"
|
||||
MustContain = "E1M1","E2M1","E2M2","E2M3","E2M4","E2M5","E2M6","E2M7","E2M8","E2M9",
|
||||
"E3M1","E3M2","E3M3","E3M4","E3M5","E3M6","E3M7","E3M8","E3M9",
|
||||
"DPHOOF","BFGGA0","HEADA1","CYBRA1","SPIDA1D1", "E4M2"
|
||||
|
|
@ -407,7 +407,7 @@ IWad
|
|||
Config = "Doom"
|
||||
IWADName = "doom.wad", 1
|
||||
Mapinfo = "mapinfo/doom1.txt"
|
||||
Compatibility = "Shorttex"
|
||||
Compatibility = "Shorttex", "nosectionmerge"
|
||||
MustContain = "E1M1","E2M1","E2M2","E2M3","E2M4","E2M5","E2M6","E2M7","E2M8","E2M9",
|
||||
"E3M1","E3M2","E3M3","E3M4","E3M5","E3M6","E3M7","E3M8","E3M9",
|
||||
"DPHOOF","BFGGA0","HEADA1","CYBRA1","SPIDA1D1"
|
||||
|
|
@ -422,7 +422,7 @@ IWad
|
|||
Game = "Doom"
|
||||
Config = "Doom"
|
||||
Mapinfo = "mapinfo/doom1.txt"
|
||||
Compatibility = "Shareware", "Shorttex"
|
||||
Compatibility = "Shareware", "Shorttex", "nosectionmerge"
|
||||
MustContain = "E1M1"
|
||||
BannerColors = "54 54 54", "a8 a8 a8"
|
||||
IgnoreTitlePatches = 1
|
||||
|
|
@ -492,7 +492,7 @@ IWad
|
|||
Config = "Doom"
|
||||
IWADName = "doom2.wad"
|
||||
Mapinfo = "mapinfo/doom2bfg.txt"
|
||||
Compatibility = "Shorttex"
|
||||
Compatibility = "Shorttex", "nosectionmerge"
|
||||
MustContain = "MAP01", "DMENUPIC", "M_ACPT", "M_CAN", "M_EXITO", "M_CHG"
|
||||
BannerColors = "a8 00 00", "a8 a8 a8"
|
||||
Load = "nerve.wad"
|
||||
|
|
@ -507,7 +507,7 @@ IWad
|
|||
Config = "Doom"
|
||||
IWADName = "doom2unity.wad"
|
||||
Mapinfo = "mapinfo/doom2unity.txt"
|
||||
Compatibility = "Shorttex"
|
||||
Compatibility = "Shorttex", "nosectionmerge"
|
||||
MustContain = "MAP01", "DMENUPIC"
|
||||
BannerColors = "00 7c 00", "a8 a8 a8"
|
||||
IgnoreTitlePatches = 1
|
||||
|
|
@ -522,7 +522,7 @@ IWad
|
|||
Config = "Doom"
|
||||
IWADName = "doom2.wad", 1
|
||||
Mapinfo = "mapinfo/doom2xbox.txt"
|
||||
Compatibility = "Shorttex"
|
||||
Compatibility = "Shorttex", "nosectionmerge"
|
||||
MustContain = "MAP01", "MAP33", "CWILV32"
|
||||
BannerColors = "18 18 18", "a8 a8 a8"
|
||||
IgnoreTitlePatches = 1
|
||||
|
|
@ -538,7 +538,7 @@ IWad
|
|||
Config = "Doom"
|
||||
IWADName = "doom2f.wad", 1
|
||||
Mapinfo = "mapinfo/doom2.txt"
|
||||
Compatibility = "Shorttex"
|
||||
Compatibility = "Shorttex", "nosectionmerge"
|
||||
MustContain = "MAP01", "WIOBJ"
|
||||
BannerColors = "ff ff ff", "a8 00 00"
|
||||
}
|
||||
|
|
@ -552,7 +552,7 @@ IWad
|
|||
Config = "Doom"
|
||||
IWADName = "doom2.wad", 1
|
||||
Mapinfo = "mapinfo/doom2.txt"
|
||||
Compatibility = "Shorttex"
|
||||
Compatibility = "Shorttex", "nosectionmerge"
|
||||
MustContain = "MAP01"
|
||||
BannerColors = "a8 00 00", "a8 a8 a8"
|
||||
IgnoreTitlePatches = 1
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue