diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
index efaa8612c..a8e67a7f2 100644
--- a/.github/workflows/windows.yml
+++ b/.github/workflows/windows.yml
@@ -29,6 +29,7 @@ jobs:
with:
packages: |
b2sdk
+ PyNaCl
- name: Prepare build
run: .\ci\win-buildgen.ps1
- name: Turn on problem matcher
@@ -37,6 +38,32 @@ jobs:
run: cmake --build .\build\ --config RelWithDebInfo --parallel
- name: Prepare artifact
run: .\ci\win-artifact.ps1
+ - name: Stage artifacts for testing
+ run: .\ci\win-prepare-demotest.ps1
+ - name: Download OdaTests and Testing Resources
+ run: .\ci\win-get-demotester.ps1
+ env:
+ DEMOTESTER_URL: ${{ vars.DEMOTESTER_DOWNLOAD_URL }}
+ DEMORESOURCES_URL: ${{ vars.DEMORESOURCES_DOWNLOAD_URL }}
+ continue-on-error: true
+ - name: Decrypt IWADs
+ run: |
+ python .\secret.py decrypt plutonia
+ python .\secret.py decrypt tnt
+ python .\secret.py decrypt doom
+ python .\secret.py decrypt doom1
+ python .\secret.py decrypt doom2
+ python .\secret.py decrypt hacx
+ env:
+ SECRET_KEY: ${{ secrets.DEMOTESTER_IWAD_KEY }}
+ working-directory: .\build\demotester
+ continue-on-error: true
+ - name: Run OdaTests
+ run: python .\odatestcases.py
+ env:
+ ODAMEX_BIN: ..\demotest\odamex.exe
+ working-directory: .\build\demotester
+ continue-on-error: true
- name: Upload artifact to B2
run: python .\ci\upload-b2.py .\build\archive Win-x64
env:
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ac0c606d5..94ba20658 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -26,6 +26,11 @@ include(GNUInstallDirs OPTIONAL)
add_definitions(-DINSTALL_BINDIR="${CMAKE_INSTALL_BINDIR}")
add_definitions(-DINSTALL_DATADIR="${CMAKE_INSTALL_DATADIR}")
+# Set up FHS installation path
+if(NOT APPLE AND NOT WIN32)
+ add_definitions(-DINSTALL_PREFIX="${CMAKE_INSTALL_PREFIX}")
+endif()
+
if(WIN32)
set(USE_INTERNAL_LIBS 1)
else()
@@ -49,7 +54,7 @@ cmake_dependent_option( ENABLE_PORTMIDI "Enable portmidi support" 1 BUILD_CLIENT
cmake_dependent_option( USE_MINIUPNP "Build with UPnP support" 1 BUILD_SERVER 0 )
cmake_dependent_option( USE_INTERNAL_MINIUPNP "Use internal MiniUPnP" 1 USE_MINIUPNP 0 )
-set(PROJECT_COPYRIGHT "2006-2022")
+set(PROJECT_COPYRIGHT "2006-2023")
set(PROJECT_RC_VERSION "11,0,0,0")
set(PROJECT_COMPANY "The Odamex Team")
diff --git a/README.md b/README.md
index 5fcaecfad..915689568 100644
--- a/README.md
+++ b/README.md
@@ -77,6 +77,23 @@ Before submitting a pull request, please make sure it follows [our coding standa
[3]: https://odamex.net/wiki/Coding_standard
+**Note**: This project contains a demo testing utility that ensures vanilla compatibility by
+running a specific set of demos after each commit. When forking this project to prepare a pull request,
+this functionality will be unavailable by default to protect sensitive files.
+You can restore this functionality by:
+
+1. Forking [OdaTest-Resources](https://github.com/odamex/odatests-resources) to get the PWADs.
+2. Downloading [OdaTests](https://github.com/odamex/odatests) to get the encryption module.
+3. Replacing the encrypted IWADs with your own set of encrypted IWADs.
+Encrypt using `python .\secret.py encrypt doom2` with the environment variable
+`SECRET_KEY` defined to encrypt the IWADs with. The following IWADs (latest version) are needed to run all tests:
+`doom, doom1, doom2, tnt, plutonia, hacx`
+4. Create a release for your forked OdaTest-Resources repo.
+5. Enter the following Secrets / Repository Variables in GitHub:
+ - `secrets.DEMOTESTER_IWAD_KEY` - Encryption key for the IWADs
+ - `vars.DEMOTESTER_DOWNLOAD_URL` - Full URL to download the latest OdaTests release.
+ - `vars.DEMORESOURCES_DOWNLOAD_URL` - Full URL to download your personal demo resources
+
External Links
--------------
diff --git a/ag-odalaunch/res/Info.plist b/ag-odalaunch/res/Info.plist
index 1900c3f22..837a26fcc 100644
--- a/ag-odalaunch/res/Info.plist
+++ b/ag-odalaunch/res/Info.plist
@@ -23,11 +23,11 @@
CFBundleShortVersionString
11.0.0
CFBundleGetInfoString
- Copyright © 2006-2022 The Odamex Team
+ Copyright © 2006-2023 The Odamex Team
CFBundleLongVersionString
11.0.0
NSHumanReadableCopyright
- Copyright © 2006-2022 The Odamex Team
+ Copyright © 2006-2023 The Odamex Team
LSRequiresCarbon
diff --git a/ci/win-get-demotester.ps1 b/ci/win-get-demotester.ps1
new file mode 100644
index 000000000..ed21c6e9d
--- /dev/null
+++ b/ci/win-get-demotester.ps1
@@ -0,0 +1,25 @@
+Set-PSDebug -Trace 1
+
+if (!([String]::IsNullOrWhiteSpace($env:DEMOTESTER_URL)) -and !([String]::IsNullOrWhiteSpace($env:DEMORESOURCES_URL)))
+{
+ Write-Output "OdaTests Download URL: $env:DEMOTESTER_URL"
+ Write-Output "OdaTests WAD Resources Download URL: $env:DEMORESOURCES_URL"
+
+ $DemoTesterPath = $env:DEMOTESTER_URL
+ $DemoResourcePath = $env:DEMORESOURCES_URL
+
+ Set-Location "build"
+ New-Item -Name "demotester" -ItemType "directory" | Out-Null
+
+ Invoke-WebRequest -Uri $DemoTesterPath -OutFile .\odatests.zip
+ Invoke-WebRequest -Uri $DemoResourcePath -OutFile .\odatests-resources.zip
+
+ 7z.exe x odatests.zip -odemotester -y
+ 7z.exe x odatests-resources.zip -odemotester -y
+
+ Set-Location ..
+}
+else
+{
+ Write-Output "OdaTests URL or OdaTests Resources URL missing, skipping..."
+}
diff --git a/ci/win-prepare-demotest.ps1 b/ci/win-prepare-demotest.ps1
new file mode 100644
index 000000000..a1f6d6c78
--- /dev/null
+++ b/ci/win-prepare-demotest.ps1
@@ -0,0 +1,22 @@
+Set-PSDebug -Trace 1
+
+Set-Location "build"
+New-Item -Name "demotest" -ItemType "directory" | Out-Null
+
+# Copy all built files into artifact directory
+Copy-Item -Path `
+ ".\client\RelWithDebInfo\odamex.exe", `
+ ".\client\RelWithDebInfo\odamex.pdb", `
+ ".\client\RelWithDebInfo\*.dll", `
+ ".\server\RelWithDebInfo\odasrv.exe", `
+ ".\server\RelWithDebInfo\odasrv.pdb", `
+ ".\odalaunch\RelWithDebInfo\odalaunch.exe", `
+ ".\odalaunch\RelWithDebInfo\odalaunch.pdb", `
+ ".\odalaunch\RelWithDebInfo\*.dll", `
+ ".\wad\odamex.wad", `
+ "C:\Windows\System32\msvcp140.dll", `
+ "C:\Windows\System32\vcruntime140.dll", `
+ "C:\Windows\System32\vcruntime140_1.dll" `
+ -Destination "demotest"
+
+Set-Location ..
diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt
index 3644285f0..4e3c5903a 100644
--- a/client/CMakeLists.txt
+++ b/client/CMakeLists.txt
@@ -128,11 +128,6 @@ if(APPLE)
${AUDIOUNIT_LIBRARY})
endif()
-# Set up FHS installation path
-if(NOT APPLE AND NOT WIN32)
- add_definitions(-DINSTALL_PREFIX="${CMAKE_INSTALL_PREFIX}")
-endif()
-
# Client target
if(TARGET SDL2::SDL2 OR TARGET SDL::SDL)
@@ -168,14 +163,17 @@ if(TARGET SDL2::SDL2 OR TARGET SDL::SDL)
message(STATUS "Default SIMD flags not touched for AMD64")
elseif(ODAMEX_TARGET_ARCH STREQUAL "i386")
if(NOT MSVC)
- # Pentium M has SSE2.
- target_compile_definitions(odamex PRIVATE -march=pentium-m)
+ target_compile_options(odamex PRIVATE -msse2)
else()
- target_compile_definitions(odamex PRIVATE /arch:SSE2)
+ target_compile_options(odamex PRIVATE /arch:SSE2)
endif()
message(STATUS "Default SIMD flags set to SSE2")
elseif(ODAMEX_TARGET_ARCH MATCHES "ppc")
- target_compile_definitions(odamex PRIVATE -faltivec)
+ if(APPLE)
+ target_compile_options(odamex PRIVATE -faltivec)
+ else()
+ target_compile_options(odamex PRIVATE -maltivec)
+ endif()
message(STATUS "Default SIMD flags set to AltiVec")
endif()
else()
diff --git a/client/gui/gui_boot.cpp b/client/gui/gui_boot.cpp
index 35cd3d8c9..a50bc0857 100644
--- a/client/gui/gui_boot.cpp
+++ b/client/gui/gui_boot.cpp
@@ -98,7 +98,7 @@ static void EraseSelected(scannedPWADPtrs_t& mut, scannedPWAD_t* pwad)
const scannedIWAD_t* g_SelectedIWAD;
scannedWADs_t g_SelectedWADs;
-const int WINDOW_WIDTH = 320;
+const int WINDOW_WIDTH = 425;
const int WINDOW_HEIGHT = 240;
class BootWindow : public Fl_Window
@@ -112,13 +112,20 @@ class BootWindow : public Fl_Window
Fl_Hold_Browser* m_IWADBrowser;
Fl_Check_Browser* m_PWADSelectBrowser;
Fl_Hold_Browser* m_PWADOrderBrowser;
+ Fl_Check_Browser* m_gameOptionsBrowser;
StringTokens m_WADDirs;
Fl_Hold_Browser* m_WADDirList;
+ // display strings for options tab and their corresponding command line arguments
+ std::vector > OPTIONS_LIST;
public:
BootWindow(int X, int Y, int W, int H, const char* L)
: Fl_Window(X, Y, W, H, L), m_IWADs()
{
+ OPTIONS_LIST.push_back(std::make_pair("No Monsters", "-nomonsters"));
+ OPTIONS_LIST.push_back(std::make_pair("Fast Monsters", "-fast"));
+ OPTIONS_LIST.push_back(std::make_pair("Respawn Monsters", "-respawn"));
+ OPTIONS_LIST.push_back(std::make_pair("Pistol Start", "-pistolstart"));
{
Fl_Tabs* tabs = new Fl_Tabs(0, 0, 425, 200);
{
@@ -132,6 +139,8 @@ class BootWindow : public Fl_Window
} // Fl_Box* logo
{
m_IWADBrowser = new Fl_Hold_Browser(135, 35, 280, 155);
+ m_IWADBrowser->callback(BootWindow::doPlayCB, static_cast(this));
+ m_IWADBrowser->when(FL_WHEN_ENTER_KEY);
} // Fl_Browser* m_IWADBrowser
m_tabIWAD->end();
} // Fl_Group* tabIWAD
@@ -165,6 +174,26 @@ class BootWindow : public Fl_Window
} // Fl_Button* doWADRemove
m_tabPWADs->end();
} // Fl_Group* tabPWADs
+ {
+ Fl_Group* tabGameOptions =
+ new Fl_Group(0, 25, 425, 175, "Game Options");
+ {
+ Fl_Box* o = new Fl_Box(
+ 10, 35, 405, 20,
+ "Set gameplay options to modify your experience.");
+ o->align(Fl_Align(132 | FL_ALIGN_INSIDE));
+ } // Fl_Box* o
+ {
+ m_gameOptionsBrowser = new Fl_Check_Browser(10, 65, 405, 125);
+ for (std::vector >::const_iterator it = OPTIONS_LIST.begin();
+ it != OPTIONS_LIST.end(); ++it)
+ {
+ m_gameOptionsBrowser->add((*it).first.c_str());
+ }
+ }
+ tabGameOptions->end();
+
+ } // Fl_Group* tabGameOptions
{
Fl_Group* tabWADDirs =
new Fl_Group(0, 25, 425, 175, "Resource Locations");
@@ -272,6 +301,7 @@ class BootWindow : public Fl_Window
}
boot->selectedWADs();
+ boot->setOptions();
Fl::delete_widget(boot);
}
@@ -497,6 +527,14 @@ class BootWindow : public Fl_Window
}
}
+ void setOptions()
+ {
+ for (int i = 1; i <= m_gameOptionsBrowser->nitems(); i++) {
+ if (m_gameOptionsBrowser->checked(i))
+ g_SelectedWADs.options.push_back(OPTIONS_LIST[i - 1].second);
+ }
+ }
+
/**
* @brief Update the WAD dir browser widget from the vector.
*/
@@ -527,7 +565,7 @@ class BootWindow : public Fl_Window
*/
static BootWindow* MakeBootWindow()
{
- return new BootWindow(0, 0, 425, 240, "Odamex " DOTVERSIONSTR);
+ return new BootWindow(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, "Odamex " DOTVERSIONSTR);
}
/**
diff --git a/client/gui/gui_boot.h b/client/gui/gui_boot.h
index e70fede4e..0b39c2b3d 100644
--- a/client/gui/gui_boot.h
+++ b/client/gui/gui_boot.h
@@ -27,6 +27,7 @@ struct scannedWADs_t
{
std::string iwad;
StringTokens pwads;
+ StringTokens options;
};
scannedWADs_t GUI_BootWindow();
diff --git a/client/sdl/i_input_sdl20.cpp b/client/sdl/i_input_sdl20.cpp
index e7283b165..d26d123d1 100644
--- a/client/sdl/i_input_sdl20.cpp
+++ b/client/sdl/i_input_sdl20.cpp
@@ -726,23 +726,56 @@ void ISDL20JoystickInputDevice::gatherEvents()
}
else
{
- float deadzone = (joy_deadzone * 32767);
event_t motion_event(ev_joystick);
motion_event.type = ev_joystick;
motion_event.data2 = sdl_ev.caxis.axis;
- if ((sdl_ev.caxis.value >= deadzone) ||
- (sdl_ev.caxis.value <= -deadzone)){
- motion_event.data3 = sdl_ev.caxis.value;
- }
-
+ motion_event.data3 = calcAxisValue(sdl_ev.caxis.value);
mEvents.push(motion_event);
}
}
}
}
+
+ // Flush all remaining joystick and game controller events.
+ SDL_FlushEvents(SDL_JOYAXISMOTION, SDL_CONTROLLERDEVICEREMAPPED);
}
+int ISDL20JoystickInputDevice::calcAxisValue(int raw_value)
+{
+ float value;
+
+ // Normalize.
+ if (raw_value > 0)
+ {
+ value = (float)raw_value / (float)SDL_JOYSTICK_AXIS_MAX;
+ }
+ else if (raw_value < 0)
+ {
+ value = (float)raw_value / (float)abs(SDL_JOYSTICK_AXIS_MIN);
+ }
+ else
+ {
+ value = 0.0f;
+ }
+
+ // Apply deadzone.
+ if (value > joy_deadzone)
+ {
+ value = (value - joy_deadzone) / (1.0f - joy_deadzone);
+ }
+ else if (value < -joy_deadzone)
+ {
+ value = (value + joy_deadzone) / (1.0f - joy_deadzone);
+ }
+ else
+ {
+ value = 0.0f;
+ }
+
+ // Scale value to the range used for calculations in G_BuildTiccmd().
+ return lroundf(value * 32767.0f);
+}
//
// ISDL20JoystickInputDevice::getEvent
@@ -788,6 +821,14 @@ ISDL20InputSubsystem::ISDL20InputSubsystem() :
SDL_EventState(SDL_CONTROLLERBUTTONDOWN, SDL_IGNORE);
SDL_EventState(SDL_CONTROLLERBUTTONUP, SDL_IGNORE);
+ // Ignore unsupported game controller events.
+#if (SDL_MINOR_VERSION > 0 || SDL_PATCHLEVEL >= 14)
+ SDL_EventState(SDL_CONTROLLERTOUCHPADDOWN, SDL_IGNORE);
+ SDL_EventState(SDL_CONTROLLERTOUCHPADMOTION, SDL_IGNORE);
+ SDL_EventState(SDL_CONTROLLERTOUCHPADUP, SDL_IGNORE);
+ SDL_EventState(SDL_CONTROLLERSENSORUPDATE, SDL_IGNORE);
+#endif
+
grabInput();
}
diff --git a/client/sdl/i_input_sdl20.h b/client/sdl/i_input_sdl20.h
index b3cdcf855..0d3d9012a 100644
--- a/client/sdl/i_input_sdl20.h
+++ b/client/sdl/i_input_sdl20.h
@@ -139,6 +139,8 @@ class ISDL20JoystickInputDevice : public IInputDevice
virtual void flushEvents();
private:
+ int calcAxisValue(int raw_value);
+
static const int JOY_DEADZONE = 6000;
bool mActive;
diff --git a/client/sdl/i_musicsystem_au.cpp b/client/sdl/i_musicsystem_au.cpp
index 9192939c2..3d84bb2f9 100644
--- a/client/sdl/i_musicsystem_au.cpp
+++ b/client/sdl/i_musicsystem_au.cpp
@@ -180,9 +180,12 @@ void AuMusicSystem::startSong(byte* data, size_t length, bool loop)
return;
}
+ MusicTimeStamp maxtime = 0;
for (UInt32 i = 0; i < outNumberOfTracks; i++)
{
MusicTrack track;
+ MusicTimeStamp time;
+ UInt32 size = sizeof(time);
if (MusicSequenceGetIndTrack(m_sequence, i, &track) != noErr)
{
@@ -190,31 +193,39 @@ void AuMusicSystem::startSong(byte* data, size_t length, bool loop)
return;
}
- struct s_loopinfo
- {
- MusicTimeStamp time;
- long loops;
- } LoopInfo;
-
- UInt32 inLength = sizeof(LoopInfo);
-
- if (MusicTrackGetProperty(track, kSequenceTrackProperty_LoopInfo, &LoopInfo,
- &inLength) != noErr)
+ if (MusicTrackGetProperty(track, kSequenceTrackProperty_TrackLength, &time,
+ &size) != noErr)
{
Printf(PRINT_HIGH, "I_PlaySong: MusicTrackGetProperty failed\n");
return;
}
- inLength = sizeof(LoopInfo.time);
+ if (time > maxtime)
+ {
+ maxtime = time;
+ }
+ }
+
+ for (UInt32 i = 0; i < outNumberOfTracks; i++)
+ {
+ MusicTrack track;
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1050
+ typedef struct
+ {
+ MusicTimeStamp loopDuration;
+ SInt32 numberOfLoops;
+ } MusicTrackLoopInfo;
+#endif
+ MusicTrackLoopInfo LoopInfo;
- if (MusicTrackGetProperty(track, kSequenceTrackProperty_TrackLength,
- &LoopInfo.time, &inLength) != noErr)
+ if (MusicSequenceGetIndTrack(m_sequence, i, &track) != noErr)
{
- Printf(PRINT_HIGH, "I_PlaySong: MusicTrackGetProperty failed\n");
+ Printf(PRINT_HIGH, "I_PlaySong: MusicSequenceGetIndTrack failed\n");
return;
}
- LoopInfo.loops = loop ? 0 : 1;
+ LoopInfo.loopDuration = maxtime;
+ LoopInfo.numberOfLoops = (loop ? 0 : 1);
if (MusicTrackSetProperty(track, kSequenceTrackProperty_LoopInfo, &LoopInfo,
sizeof(LoopInfo)) != noErr)
diff --git a/client/src/cl_cvarlist.cpp b/client/src/cl_cvarlist.cpp
index d7013c302..8ba00d710 100644
--- a/client/src/cl_cvarlist.cpp
+++ b/client/src/cl_cvarlist.cpp
@@ -309,7 +309,7 @@ CVAR (joy_fastsensitivity, "15.0", "", CVARTYPE_FLOAT, CVAR_CLIENTARCHIVE | CVAR
CVAR (joy_freelook, "0", "", CVARTYPE_FLOAT, CVAR_CLIENTARCHIVE)
CVAR (joy_invert, "0", "", CVARTYPE_FLOAT, CVAR_CLIENTARCHIVE)
-CVAR_RANGE (joy_deadzone, "0.34", "", CVARTYPE_FLOAT, CVAR_CLIENTARCHIVE | CVAR_NOENABLEDISABLE, 0.0f, 1.0f)
+CVAR_RANGE (joy_deadzone, "0.20", "", CVARTYPE_FLOAT, CVAR_CLIENTARCHIVE | CVAR_NOENABLEDISABLE, 0.0f, 0.75f)
CVAR_RANGE(joy_lefttrigger_deadzone, "0.2", "Sets the required pressure to trigger a press on the left trigger (Analog controllers only)",
CVARTYPE_FLOAT, CVAR_CLIENTARCHIVE | CVAR_NOENABLEDISABLE, 0.01f, 1.0f)
diff --git a/client/src/cl_parse.cpp b/client/src/cl_parse.cpp
index cdadbbdf2..e15c45edc 100644
--- a/client/src/cl_parse.cpp
+++ b/client/src/cl_parse.cpp
@@ -2354,7 +2354,7 @@ static void CL_SectorProperties(const odaproto::svc::SectorProperties* msg)
break;
}
case SPC_Gravity:
- *(int*)§or->gravity = msg->sector().gravity();
+ *§or->gravity = msg->sector().gravity();
break;
case SPC_Panning:
sector->ceiling_xoffs = msg->sector().ceiling_offs().x();
diff --git a/client/src/d_main.cpp b/client/src/d_main.cpp
index d6d966b35..309553abf 100644
--- a/client/src/d_main.cpp
+++ b/client/src/d_main.cpp
@@ -801,6 +801,12 @@ void D_DoomMain()
scannedWADs_t wads = GUI_BootWindow();
iwad = wads.iwad;
pwads = wads.pwads;
+
+ for (StringTokens::iterator it = wads.options.begin();
+ it != wads.options.end(); ++it)
+ {
+ Args.AppendArg((*it).c_str());
+ }
}
}
@@ -858,7 +864,7 @@ void D_DoomMain()
// set the default value for vid_ticker based on the presence of -devparm
if (devparm)
vid_ticker.SetDefault("1");
-
+
// Nomonsters
sv_nomonsters = Args.CheckParm("-nomonsters");
diff --git a/client/src/m_menu.cpp b/client/src/m_menu.cpp
index 6268e1819..f82cbf40d 100644
--- a/client/src/m_menu.cpp
+++ b/client/src/m_menu.cpp
@@ -25,6 +25,8 @@
#include "odamex.h"
+#include
+
#include "gstrings.h"
#include "c_console.h"
#include "c_dispatch.h"
diff --git a/client/src/m_options.cpp b/client/src/m_options.cpp
index 9f55798dc..30c720ef2 100644
--- a/client/src/m_options.cpp
+++ b/client/src/m_options.cpp
@@ -1468,7 +1468,7 @@ void M_SwitchMenu(menu_t* menu)
for (i = 0; i < menu->numitems; i++)
{
item = menu->items + i;
- if (item->type != whitetext && item->type != redtext)
+ if (item->type != whitetext && item->type != redtext && item->type != orangetext)
{
thiswidth = V_StringWidth (item->label);
if (thiswidth > widest)
@@ -1932,6 +1932,7 @@ void M_OptResponder (event_t *ev)
} while (CurrentMenu->items[CurrentItem].type == redtext ||
CurrentMenu->items[CurrentItem].type == whitetext ||
CurrentMenu->items[CurrentItem].type == yellowtext ||
+ CurrentMenu->items[CurrentItem].type == orangetext ||
(CurrentMenu->items[CurrentItem].type == screenres &&
!CurrentMenu->items[CurrentItem].b.res1));
@@ -1972,6 +1973,7 @@ void M_OptResponder (event_t *ev)
} while (CurrentMenu->items[CurrentItem].type == redtext ||
CurrentMenu->items[CurrentItem].type == whitetext ||
CurrentMenu->items[CurrentItem].type == yellowtext ||
+ CurrentMenu->items[CurrentItem].type == orangetext ||
(CurrentMenu->items[CurrentItem].type == screenres &&
!CurrentMenu->items[CurrentItem].b.res1));
@@ -1993,6 +1995,7 @@ void M_OptResponder (event_t *ev)
while (CurrentMenu->items[CurrentItem].type == redtext ||
CurrentMenu->items[CurrentItem].type == whitetext ||
CurrentMenu->items[CurrentItem].type == yellowtext ||
+ CurrentMenu->items[CurrentItem].type == orangetext ||
(CurrentMenu->items[CurrentItem].type == screenres &&
!CurrentMenu->items[CurrentItem].b.res1))
{
@@ -2015,6 +2018,7 @@ void M_OptResponder (event_t *ev)
while (CurrentMenu->items[CurrentItem].type == redtext ||
CurrentMenu->items[CurrentItem].type == whitetext ||
CurrentMenu->items[CurrentItem].type == yellowtext ||
+ CurrentMenu->items[CurrentItem].type == orangetext ||
(CurrentMenu->items[CurrentItem].type == screenres &&
!CurrentMenu->items[CurrentItem].b.res1))
{
diff --git a/client/src/r_drawt_altivec.cpp b/client/src/r_drawt_altivec.cpp
index eea758733..5a0cdf95e 100644
--- a/client/src/r_drawt_altivec.cpp
+++ b/client/src/r_drawt_altivec.cpp
@@ -36,9 +36,7 @@
#include "r_main.h"
#include "i_video.h"
-#if !defined(__APPLE_ALTIVEC__)
#include
-#endif
#define ALTIVEC_ALIGNED(x) x __attribute__((aligned(16)))
diff --git a/client/src/st_new.cpp b/client/src/st_new.cpp
index 8e12ce198..a79bf1c28 100644
--- a/client/src/st_new.cpp
+++ b/client/src/st_new.cpp
@@ -1368,9 +1368,14 @@ void LevelStateHUD()
break;
}
case LevelState::ENDROUND_COUNTDOWN: {
- StrFormat(lines.title,
- "Round " TEXTCOLOR_YELLOW "%d " TEXTCOLOR_GREY "complete\n",
- ::levelstate.getRound());
+ if (G_IsCoopGame() || G_IsHordeMode())
+ StrFormat(lines.title,
+ "Attempt " TEXTCOLOR_YELLOW "%d " TEXTCOLOR_GREY "complete\n",
+ ::levelstate.getRound());
+ else
+ StrFormat(lines.title,
+ "Round " TEXTCOLOR_YELLOW "%d " TEXTCOLOR_GREY "complete\n",
+ ::levelstate.getRound());
WinInfo win = ::levelstate.getWinInfo();
if (win.type == WinInfo::WIN_DRAW)
@@ -1381,15 +1386,27 @@ void LevelStateHUD()
else if (win.type == WinInfo::WIN_TEAM)
StrFormat(lines.subtitle[0], "%s team wins the round",
WinToColorString(win).c_str());
+ else if (G_IsCoopGame() || G_IsHordeMode())
+ StrFormat(lines.subtitle[0], "Next attempt in " TEXTCOLOR_GREEN "%d",
+ ::levelstate.getCountdown());
else
StrFormat(lines.subtitle[0], "Next round in " TEXTCOLOR_GREEN "%d",
::levelstate.getCountdown());
break;
}
case LevelState::ENDGAME_COUNTDOWN: {
- StrFormat(lines.title, "Match complete");
-
WinInfo win = ::levelstate.getWinInfo();
+ //Upper Text
+ if
+ (win.type == WinInfo::WIN_EVERYBODY)
+ StrFormat(lines.title, TEXTCOLOR_YELLOW "Mission Success!");
+ else if
+ (win.type == WinInfo::WIN_NOBODY)
+ StrFormat(lines.title, TEXTCOLOR_RED "Mission Failed!");
+ else
+ StrFormat(lines.title, "Match complete");
+
+ // Lower Text
if (win.type == WinInfo::WIN_DRAW)
StrFormat(lines.subtitle[0], "The game ends in a tie");
else if (win.type == WinInfo::WIN_PLAYER)
diff --git a/client/src/v_screenshot.cpp b/client/src/v_screenshot.cpp
index 2f24cb184..375de5b9d 100644
--- a/client/src/v_screenshot.cpp
+++ b/client/src/v_screenshot.cpp
@@ -24,6 +24,8 @@
#include "odamex.h"
+#include
+
#include
#include
diff --git a/common/c_cvarlist.cpp b/common/c_cvarlist.cpp
index 1e4f22145..312c042dc 100644
--- a/common/c_cvarlist.cpp
+++ b/common/c_cvarlist.cpp
@@ -245,12 +245,13 @@ CVAR(g_preroundreset, "0", "After preround is over, reset the map one last time.
CVAR(g_postroundtime, "3", "Amount of time after a round before the next round/endgame",
CVARTYPE_INT, CVAR_SERVERARCHIVE | CVAR_NOENABLEDISABLE)
-CVAR_RANGE(g_coopthingfilter, "0", "Removes cooperative things of the map. Values are:\n" \
- "// 0 - All Coop things are retained (default).\n" \
+CVAR_RANGE(g_thingfilter, "0", "Removes some things from the map. Values are:\n" \
+ "// 0 - All things are retained (default).\n" \
"// 1 - Only Coop weapons are removed.\n" \
- "// 2 - All Coop things are removed.",
+ "// 2 - All Coop things are removed.\n" \
+ "// 3 - All pickupable things are removed.",
CVARTYPE_BYTE, CVAR_SERVERARCHIVE | CVAR_SERVERINFO | CVAR_NOENABLEDISABLE | CVAR_LATCH,
- 0.0f, 2.0f)
+ 0.0f, 3.0f)
CVAR(g_resetinvonexit, "0",
"Always reset players to their starting inventory on level exit", CVARTYPE_BOOL,
diff --git a/common/c_dispatch.cpp b/common/c_dispatch.cpp
index 0a409deaf..523c113ac 100644
--- a/common/c_dispatch.cpp
+++ b/common/c_dispatch.cpp
@@ -26,6 +26,7 @@
#include
#include
+#include
#include "cmdlib.h"
#include "c_console.h"
diff --git a/common/cmdlib.h b/common/cmdlib.h
index c7041837b..a20be7c4c 100644
--- a/common/cmdlib.h
+++ b/common/cmdlib.h
@@ -24,6 +24,7 @@
#pragma once
#include
+#include
#ifdef _MSC_VER
#pragma warning(disable : 4244) // MIPS
diff --git a/common/d_dehacked.cpp b/common/d_dehacked.cpp
index b63e1e10d..ec697cbbb 100644
--- a/common/d_dehacked.cpp
+++ b/common/d_dehacked.cpp
@@ -1244,19 +1244,14 @@ static int PatchThing(int thingy)
info->flags3 |= MF3_E4M8BOSS;
}
- if (tempval & MF3_FULLVOLSOUNDS)
- {
- info->flags3 |= MF3_FULLVOLSOUNDS;
- }
-
- if (tempval & MF2_NODMGTHRUST)
+ if (tempval & BIT(17)) // MBF21 RIP is 1 << 17
{
- info->flags2 |= MF2_NODMGTHRUST;
+ info->flags2 |= MF2_RIP;
}
- if (tempval & MF2_RIP)
+ if (tempval & MF3_FULLVOLSOUNDS)
{
- info->flags2 |= MF2_RIP;
+ info->flags3 |= MF3_FULLVOLSOUNDS;
}
value[3] |= atoi(strval);
diff --git a/common/d_player.h b/common/d_player.h
index c16f1f904..7240e95cb 100644
--- a/common/d_player.h
+++ b/common/d_player.h
@@ -134,7 +134,6 @@ class player_s
struct ticcmd_t cmd; // the ticcmd currently being processed
std::queue cmdqueue; // all received ticcmds
- int missingticcmdcount; // number of gametics without processing a ticcmd for this player
// [RH] who is this?
UserInfo userinfo;
diff --git a/common/doomdata.h b/common/doomdata.h
index 367616ef5..2bbe997eb 100644
--- a/common/doomdata.h
+++ b/common/doomdata.h
@@ -269,7 +269,7 @@ typedef struct MapThing
#define MTF_DEATHMATCH 0x0400 // Thing appears in deathmatch games
// Custom MapThing Flags
-#define MTF_FILTER_COOPWPN 0x0800 // Weapon thing is filtered with g_coopthingfilter 1.
+#define MTF_FILTER_COOPWPN 0x0800 // Weapon thing is filtered with g_thingfilter 1.
// (Hate this method but it works...)
diff --git a/common/g_mapinfo.cpp b/common/g_mapinfo.cpp
index b311b99dc..36184ba23 100644
--- a/common/g_mapinfo.cpp
+++ b/common/g_mapinfo.cpp
@@ -1479,70 +1479,74 @@ struct MapInfoDataSetter
MapInfoDataSetter(level_pwad_info_t& ref)
{
- mapInfoDataContainer = {
- { "levelnum", &MIType_Int, &ref.levelnum},
- { "next", &MIType_MapName, &ref.nextmap},
- { "secretnext", &MIType_MapName, &ref.secretmap},
- { "secret", &MIType_MapName, &ref.secretmap },
- { "cluster", &MIType_Cluster, &ref.cluster },
- { "sky1", &MIType_Sky, &ref.skypic },
- { "sky2", &MIType_Sky, &ref.skypic2 },
- { "fade", &MIType_Color, &ref.fadeto_color },
- { "outsidefog", &MIType_Color, &ref.outsidefog_color },
- { "titlepatch", &MIType_LumpName, &ref.pname },
- { "par", &MIType_Int, &ref.partime },
- { "music", &MIType_MusicLumpName, &ref.music },
- { "nointermission", &MIType_SetFlag, &ref.flags, LEVEL_NOINTERMISSION },
- { "doublesky", &MIType_SetFlag, &ref.flags, LEVEL_DOUBLESKY },
- { "nosoundclipping", &MIType_SetFlag, &ref.flags, LEVEL_NOSOUNDCLIPPING },
- { "allowmonstertelefrags", &MIType_SetFlag, &ref.flags,
- LEVEL_MONSTERSTELEFRAG },
- { "map07special", &MIType_Map07Special, &ref.bossactions },
- { "baronspecial", &MIType_BaronSpecial, &ref.bossactions },
- { "cyberdemonspecial", &MIType_CyberdemonSpecial, &ref.bossactions },
- { "spidermastermindspecial", &MIType_SpiderMastermindSpecial, &ref.bossactions },
- { "specialaction_exitlevel", &MIType_SpecialAction_ExitLevel, &ref.bossactions },
- { "specialaction_opendoor", &MIType_SpecialAction_OpenDoor, &ref.bossactions },
- { "specialaction_lowerfloor", &MIType_SpecialAction_LowerFloor, &ref.bossactions },
- { "lightning" },
- { "fadetable", &MIType_LumpName, &ref.fadetable },
- { "evenlighting", &MIType_SetFlag, &ref.flags, LEVEL_EVENLIGHTING },
- { "noautosequences", &MIType_SetFlag, &ref.flags, LEVEL_SNDSEQTOTALCTRL },
- { "forcenoskystretch", &MIType_SetFlag, &ref.flags, LEVEL_FORCENOSKYSTRETCH },
- { "allowfreelook", &MIType_SCFlags, &ref.flags, LEVEL_FREELOOK_YES,
- ~LEVEL_FREELOOK_NO },
- { "nofreelook", &MIType_SCFlags, &ref.flags, LEVEL_FREELOOK_NO,
- ~LEVEL_FREELOOK_YES },
- { "allowjump", &MIType_SCFlags, &ref.flags, LEVEL_JUMP_YES, ~LEVEL_JUMP_NO },
- { "nojump", &MIType_SCFlags, &ref.flags, LEVEL_JUMP_NO, ~LEVEL_JUMP_YES },
- { "cdtrack", &MIType_EatNext },
- { "cd_start_track", &MIType_EatNext },
- { "cd_end1_track", &MIType_EatNext },
- { "cd_end2_track", &MIType_EatNext },
- { "cd_end3_track", &MIType_EatNext },
- { "cd_intermission_track", &MIType_EatNext },
- { "cd_title_track", &MIType_EatNext },
- { "warptrans", &MIType_EatNext },
- { "gravity", &MIType_Float, &ref.gravity },
- { "aircontrol", &MIType_Float, &ref.aircontrol },
- { "islobby", &MIType_SetFlag, &ref.flags, LEVEL_LOBBYSPECIAL },
- { "lobby", &MIType_SetFlag, &ref.flags, LEVEL_LOBBYSPECIAL },
- { "nocrouch" },
- { "intermusic", &MIType_EatNext },
- { "par", &MIType_Int, &ref.partime },
- { "sucktime", &MIType_EatNext },
- { "enterpic", &MIType_InterLumpName, &ref.enterpic }, // todo: add intermission script support
- { "exitpic", &MIType_InterLumpName, &ref.exitpic }, // todo: add intermission script support
- { "interpic", &MIType_EatNext },
- { "translator", &MIType_EatNext },
- { "compat_shorttex", &MIType_CompatFlag, &ref.flags }, // todo: not implemented
- { "compat_limitpain", &MIType_CompatFlag, &ref.flags }, // todo: not implemented
- { "compat_dropoff", &MIType_CompatFlag, &ref.flags, LEVEL_COMPAT_DROPOFF },
- { "compat_trace", &MIType_CompatFlag, &ref.flags }, // todo: not implemented
- { "compat_boomscroll", &MIType_CompatFlag, &ref.flags }, // todo: not implemented
- { "compat_sectorsounds", &MIType_CompatFlag, &ref.flags }, // todo: not implemented
- { "compat_nopassover", &MIType_CompatFlag, &ref.flags, LEVEL_COMPAT_NOPASSOVER }
- };
+ mapInfoDataContainer.reserve(
+ 70); // [DE] some random number, i'm not counting all these
+
+ ENTRY3("levelnum", &MIType_Int, &ref.levelnum)
+ ENTRY3("next", &MIType_MapName, &ref.nextmap)
+ ENTRY3("secretnext", &MIType_MapName, &ref.secretmap)
+ ENTRY3("secret", &MIType_MapName, &ref.secretmap)
+ ENTRY3("cluster", &MIType_Cluster, &ref.cluster)
+ ENTRY3("sky1", &MIType_Sky, &ref.skypic)
+ ENTRY3("sky2", &MIType_Sky, &ref.skypic2)
+ ENTRY3("fade", &MIType_Color, &ref.fadeto_color)
+ ENTRY3("outsidefog", &MIType_Color, &ref.outsidefog_color)
+ ENTRY3("titlepatch", &MIType_LumpName, &ref.pname)
+ ENTRY3("par", &MIType_Int, &ref.partime)
+ ENTRY3("music", &MIType_MusicLumpName, &ref.music)
+ ENTRY4("nointermission", &MIType_SetFlag, &ref.flags, LEVEL_NOINTERMISSION)
+ ENTRY4("doublesky", &MIType_SetFlag, &ref.flags, LEVEL_DOUBLESKY)
+ ENTRY4("nosoundclipping", &MIType_SetFlag, &ref.flags, LEVEL_NOSOUNDCLIPPING)
+ ENTRY4("allowmonstertelefrags", &MIType_SetFlag, &ref.flags,
+ LEVEL_MONSTERSTELEFRAG)
+ ENTRY3("map07special", &MIType_Map07Special, &ref.bossactions)
+ ENTRY3("baronspecial", &MIType_BaronSpecial, &ref.bossactions)
+ ENTRY3("cyberdemonspecial", &MIType_CyberdemonSpecial, &ref.bossactions)
+ ENTRY3("spidermastermindspecial", &MIType_SpiderMastermindSpecial, &ref.bossactions)
+ ENTRY3("specialaction_exitlevel", &MIType_SpecialAction_ExitLevel, &ref.bossactions)
+ ENTRY3("specialaction_opendoor", &MIType_SpecialAction_OpenDoor, &ref.bossactions)
+ ENTRY3("specialaction_lowerfloor", &MIType_SpecialAction_LowerFloor, &ref.bossactions)
+ ENTRY1("lightning")
+ ENTRY3("fadetable", &MIType_LumpName, &ref.fadetable)
+ ENTRY4("evenlighting", &MIType_SetFlag, &ref.flags, LEVEL_EVENLIGHTING)
+ ENTRY4("noautosequences", &MIType_SetFlag, &ref.flags, LEVEL_SNDSEQTOTALCTRL)
+ ENTRY4("forcenoskystretch", &MIType_SetFlag, &ref.flags, LEVEL_FORCENOSKYSTRETCH)
+ ENTRY5("allowfreelook", &MIType_SCFlags, &ref.flags, LEVEL_FREELOOK_YES,
+ ~LEVEL_FREELOOK_NO)
+ ENTRY5("nofreelook", &MIType_SCFlags, &ref.flags, LEVEL_FREELOOK_NO,
+ ~LEVEL_FREELOOK_YES)
+ ENTRY5("allowjump", &MIType_SCFlags, &ref.flags, LEVEL_JUMP_YES, ~LEVEL_JUMP_NO)
+ ENTRY5("nojump", &MIType_SCFlags, &ref.flags, LEVEL_JUMP_NO, ~LEVEL_JUMP_YES)
+ ENTRY2("cdtrack", &MIType_EatNext)
+ ENTRY2("cd_start_track", &MIType_EatNext)
+ ENTRY2("cd_end1_track", &MIType_EatNext)
+ ENTRY2("cd_end2_track", &MIType_EatNext)
+ ENTRY2("cd_end3_track", &MIType_EatNext)
+ ENTRY2("cd_intermission_track", &MIType_EatNext)
+ ENTRY2("cd_title_track", &MIType_EatNext)
+ ENTRY2("warptrans", &MIType_EatNext)
+ ENTRY3("gravity", &MIType_Float, &ref.gravity)
+ ENTRY3("aircontrol", &MIType_Float, &ref.aircontrol)
+ ENTRY4("islobby", &MIType_SetFlag, &ref.flags, LEVEL_LOBBYSPECIAL)
+ ENTRY4("lobby", &MIType_SetFlag, &ref.flags, LEVEL_LOBBYSPECIAL)
+ ENTRY1("nocrouch")
+ ENTRY2("intermusic", &MIType_EatNext)
+ ENTRY3("par", &MIType_Int, &ref.partime)
+ ENTRY2("sucktime", &MIType_EatNext)
+ ENTRY3("enterpic", &MIType_InterLumpName,
+ &ref.enterpic) // todo: add intermission script support
+ ENTRY3("exitpic", &MIType_InterLumpName,
+ &ref.exitpic) // todo: add intermission script support
+ ENTRY2("interpic", &MIType_EatNext)
+ ENTRY2("translator", &MIType_EatNext)
+ ENTRY3("compat_shorttex", &MIType_CompatFlag, &ref.flags) // todo: not implemented
+ ENTRY3("compat_limitpain", &MIType_CompatFlag, &ref.flags) // todo: not implemented
+ ENTRY4("compat_dropoff", &MIType_CompatFlag, &ref.flags, LEVEL_COMPAT_DROPOFF)
+ ENTRY3("compat_trace", &MIType_CompatFlag, &ref.flags) // todo: not implemented
+ ENTRY3("compat_boomscroll", &MIType_CompatFlag, &ref.flags) // todo: not implemented
+ ENTRY3("compat_sectorsounds", &MIType_CompatFlag, &ref.flags) // todo: not implemented
+ ENTRY4("compat_nopassover", &MIType_CompatFlag, &ref.flags, LEVEL_COMPAT_NOPASSOVER)
+ ENTRY3("compat_invisibility", &MIType_CompatFlag, &ref.flags) // todo: not implemented
}
};
diff --git a/common/m_resfile.cpp b/common/m_resfile.cpp
index cf77547bc..a278c769a 100644
--- a/common/m_resfile.cpp
+++ b/common/m_resfile.cpp
@@ -71,7 +71,7 @@ bool OResFile::make(OResFile& out, const std::string& file)
out.m_fullpath = fullpath;
out.m_md5 = hash;
- out.m_basename = StdStringToUpper(basename);
+ out.m_basename = basename;
return true;
}
@@ -111,7 +111,7 @@ bool OResFile::makeWithHash(OResFile& out, const std::string& file, const OMD5Ha
out.m_fullpath = fullpath;
out.m_md5 = hash;
- out.m_basename = StdStringToUpper(basename);
+ out.m_basename = basename;
return true;
}
@@ -136,8 +136,8 @@ bool OWantFile::make(OWantFile& out, const std::string& file, const ofile_t type
out.m_wantedpath = file;
out.m_wantedtype = type;
- out.m_basename = StdStringToUpper(basename);
- out.m_extension = std::string(".") + StdStringToUpper(extension);
+ out.m_basename = basename;
+ out.m_extension = std::string(".") + extension;
return true;
}
@@ -165,8 +165,8 @@ bool OWantFile::makeWithHash(OWantFile& out, const std::string& file, const ofil
out.m_wantedpath = file;
out.m_wantedtype = type;
out.m_wantedMD5 = hash;
- out.m_basename = StdStringToUpper(basename);
- out.m_extension = StdStringToUpper(extension);
+ out.m_basename = basename;
+ out.m_extension = extension;
return true;
}
@@ -290,7 +290,7 @@ bool M_ResolveWantedFile(OResFile& out, const OWantFile& wanted)
M_ExtractFileBase(path, basename);
if (M_ExtractFileExtension(path, strext))
{
- exts.push_back("." + StdStringToUpper(strext));
+ exts.push_back("." + strext);
}
else
{
diff --git a/common/p_boomfspec.cpp b/common/p_boomfspec.cpp
index 2307217ee..bed8da9f5 100644
--- a/common/p_boomfspec.cpp
+++ b/common/p_boomfspec.cpp
@@ -1304,17 +1304,20 @@ void P_PlayerInCompatibleSector(player_t* player)
{
switch ((sector->special & DAMAGE_MASK) >> DAMAGE_SHIFT)
{
- case 0: // Kill player unless invuln or rad suit
- if (!player->powers[pw_invulnerability] && !player->powers[pw_ironfeet])
+ case 0: // Kill player unless invuln or rad suit or IDDQD
+ if (!player->powers[pw_invulnerability] && !player->powers[pw_ironfeet] && !(player->cheats & CF_GODMODE))
{
- P_DamageMobj(player->mo, NULL, NULL, 10000, MOD_UNKNOWN);
+ P_DamageMobj(player->mo, NULL, NULL, 999, MOD_UNKNOWN); // 999 so BUDDHA can survive
}
break;
- case 1: // Kill player with no scruples
- P_DamageMobj(player->mo, NULL, NULL, 10000, MOD_UNKNOWN);
+ case 1: // Kill player with no scruples unless IDDQD
+ if(!(player->cheats & CF_GODMODE))
+ {
+ P_DamageMobj(player->mo, NULL, NULL, 10000, MOD_UNKNOWN);
+ }
break;
case 2: // Kill all players and exit. There's no delay here so it may confuse
- // some players.
+ // some players. Do NOT kill players with IDDQD.
if (serverside)
{
if (sv_allowexit)
@@ -1322,14 +1325,14 @@ void P_PlayerInCompatibleSector(player_t* player)
for (Players::iterator it = ::players.begin();
it != ::players.end(); ++it)
{
- if (player->ingame() && player->health > 0)
+ if (player->ingame() && player->health > 0 && !(player->cheats & CF_GODMODE))
{
P_DamageMobj((*it).mo, NULL, NULL, 10000, MOD_EXIT);
}
}
G_ExitLevel(0, 1);
}
- else
+ else if (!(player->cheats & CF_GODMODE)) // Do NOT kill players with IDDQD.
{
P_DamageMobj(
player->mo, NULL, NULL, 10000,
@@ -1339,7 +1342,7 @@ void P_PlayerInCompatibleSector(player_t* player)
}
break;
case 3: // Kill all players and secret exit. There's no delay here so it may
- // confuse some players.
+ // confuse some players. Do NOT kill players with IDDQD.
if (serverside)
{
if (sv_allowexit)
@@ -1347,14 +1350,14 @@ void P_PlayerInCompatibleSector(player_t* player)
for (Players::iterator it = ::players.begin();
it != ::players.end(); ++it)
{
- if (player->ingame() && player->health > 0)
+ if (player->ingame() && player->health > 0 && !(player->cheats & CF_GODMODE))
{
P_DamageMobj((*it).mo, NULL, NULL, 10000, MOD_EXIT);
}
}
G_SecretExitLevel(0, 1);
}
- else
+ else if (!(player->cheats & CF_GODMODE)) // Do NOT kill players with IDDQD.
{
P_DamageMobj(
player->mo, NULL, NULL, 10000,
@@ -1365,7 +1368,7 @@ void P_PlayerInCompatibleSector(player_t* player)
break;
}
}
- else
+ else if (!(player->cheats & CF_GODMODE)) // Do NOT damage players with IDDQD.
{
P_ApplyGeneralizedSectorDamage(player, (sector->special & DAMAGE_MASK) >>
DAMAGE_SHIFT);
diff --git a/common/p_map.cpp b/common/p_map.cpp
index bde33b11f..a3b3ddf44 100644
--- a/common/p_map.cpp
+++ b/common/p_map.cpp
@@ -651,7 +651,7 @@ static BOOL PIT_CheckThing (AActor *thing)
if (tmthing->info->ripsound)
S_Sound(tmthing, CHAN_VOICE, tmthing->info->ripsound, 1, ATTN_NORM);
- P_DamageMobj(thing, tmthing, tmthing->target, damage);
+ P_DamageMobj(thing, tmthing, tmthing->target, damage, MOD_UNKNOWN);
if (thing->flags2 & MF2_PUSHABLE && !(tmthing->flags2 & MF2_CANNOTPUSH))
{ // Push thing
thing->momx += tmthing->momx >> 2;
@@ -680,8 +680,16 @@ static BOOL PIT_CheckThing (AActor *thing)
mod = MOD_BFG_BOOM;
break;
// [AM] Monster fireballs get a special MOD.
+ // Unless they're from players
default:
- mod = MOD_FIREBALL;
+ if ((tmthing->target && tmthing->target->player) || !tmthing->target)
+ {
+ mod = MOD_UNKNOWN;
+ }
+ else
+ {
+ mod = MOD_FIREBALL;
+ }
break;
}
P_DamageMobj (thing, tmthing, tmthing->target, damage, mod);
@@ -697,12 +705,35 @@ static BOOL PIT_CheckThing (AActor *thing)
// [SL] Work-around the additional height added to players
// in P_CheckPosition. Don't let players grab items above
// their real height!
- if (!P_AllowPassover() || !tmthing->player ||
- thing->z < tmthing->z + tmthing->height - 24*FRACUNIT)
+
+ fixed_t max_z = tmthing->z + tmthing->height;
+
+ if (tmthing->player)
+ max_z -= 24 * FRACUNIT;
+
+ if (!P_AllowPassover() || thing->z < max_z)
P_TouchSpecialThing (thing, tmthing); // can remove thing
+
+ return !solid;
}
- return !solid;
+ // killough 3/16/98: Allow non-solid moving objects to move through solid
+ // ones, by allowing the moving thing (tmthing) to move if it's non-solid,
+ // despite another solid thing being in the way.
+ // killough 4/11/98: Treat no-clipping things as not blocking
+ // ...but not in demo_compatibility mode
+
+ // e6y
+ // Correction of wrong return value with demo_compatibility.
+ // There is no more synch on http://www.doomworld.com/sda/dwdemo/w303-115.zip
+ // (with correction in setMobjInfoValue)
+ if (demoplayback || !co_boomphys
+ //&& !prboom_comp[PC_TREAT_NO_CLIPPING_THINGS_AS_NOT_BLOCKING].state
+ )
+ return !(thing->flags & MF_SOLID);
+ else
+ return !((thing->flags & MF_SOLID && !(thing->flags & MF_NOCLIP)) &&
+ (tmthing->flags & MF_SOLID || (demoplayback || !co_boomphys)));
}
// This routine checks for Lost Souls trying to be spawned // phares
diff --git a/common/p_maputl.cpp b/common/p_maputl.cpp
index 8278c557d..6805465c3 100644
--- a/common/p_maputl.cpp
+++ b/common/p_maputl.cpp
@@ -1231,6 +1231,13 @@ static AActor* RoughBlockCheck(AActor* mo, int index, angle_t fov)
continue;
}
+ // [Blair] Don't target spectators
+ if (link->player && link->player->spectator)
+ {
+ link = link->snext;
+ continue;
+ }
+
// [Blair] Don't target teammates
if (mo->target->player && link->player &&
P_AreTeammates((player_t&)mo->target->player, (player_t&)link->player))
diff --git a/common/p_mobj.cpp b/common/p_mobj.cpp
index e9ad3efd6..aee30e6ba 100644
--- a/common/p_mobj.cpp
+++ b/common/p_mobj.cpp
@@ -85,6 +85,7 @@ EXTERN_CVAR(co_fixweaponimpacts)
EXTERN_CVAR(co_fineautoaim)
EXTERN_CVAR(sv_allowshowspawns)
EXTERN_CVAR(sv_teamsinplay)
+EXTERN_CVAR(g_thingfilter)
mapthing2_t itemrespawnque[ITEMQUESIZE];
int itemrespawntime[ITEMQUESIZE];
@@ -127,8 +128,8 @@ AActor::AActor()
prevangle(0), sprite(SPR_UNKN), frame(0), pitch(0), prevpitch(0), effects(0),
subsector(NULL), floorz(0), ceilingz(0), dropoffz(0), floorsector(NULL), radius(0),
height(0), momx(0), momy(0), momz(0), validcount(0), type(MT_UNKNOWNTHING),
- info(NULL), tics(0), state(NULL), damage(0), flags(0), flags2(0), flags3(0), oflags(0),
- special1(0), special2(0), health(0), movedir(0), movecount(0), visdir(0),
+ info(NULL), tics(0), state(NULL), damage(0), flags(0), flags2(0),
+ flags3(0), oflags(0), special1(0), special2(0), health(0), movedir(0), movecount(0), visdir(0),
reactiontime(0), threshold(0), player(NULL), lastlook(0), special(0), inext(NULL),
iprev(NULL), translation(translationref_t()), translucency(0), waterlevel(0),
gear(0), onground(false), touching_sectorlist(NULL), deadtic(0), oldframe(0),
@@ -148,8 +149,9 @@ AActor::AActor(const AActor& other)
dropoffz(other.dropoffz), floorsector(other.floorsector), radius(other.radius),
height(other.height), momx(other.momx), momy(other.momy), momz(other.momz),
validcount(other.validcount), type(other.type), info(other.info), tics(other.tics),
- state(other.state), damage(other.damage), flags(other.flags), flags2(other.flags2),
- flags3(other.flags3), oflags(other.oflags), special1(other.special1), special2(other.special2),
+ state(other.state), damage(other.damage),
+ flags(other.flags), flags2(other.flags2), flags3(other.flags3), oflags(other.oflags),
+ special1(other.special1), special2(other.special2),
health(other.health), movedir(other.movedir), movecount(other.movecount),
visdir(other.visdir), reactiontime(other.reactiontime), threshold(other.threshold),
player(other.player), lastlook(other.lastlook), special(other.special),
@@ -675,18 +677,19 @@ void AActor::RunThink ()
prevx = x;
prevy = y;
prevz = z;
+
if (!player)
{
prevangle = angle;
prevpitch = pitch;
}
- // server removal of corpses only
- if (!clientside && serverside)
- {
- if (type == MT_PLAYER && health <= 0)
- deadtic++;
- }
+ // server removal of corpses only
+ if (!clientside && serverside)
+ {
+ if (type == MT_PLAYER && health <= 0)
+ deadtic++;
+ }
// GhostlyDeath -- Was a spectator but now it's nothing!
if ((this->oflags & MFO_SPECTATOR ) && !player)
@@ -2630,9 +2633,9 @@ void P_ExplodeMissile (AActor* mo)
case MT_BFG:
mod = MOD_BFG_BOOM;
break;
- // [AM] Monster fireballs get a special MOD.
+ // Blair: Unknown player projectiles get an unknown mod
default:
- mod = MOD_FIREBALL;
+ mod = MOD_UNKNOWN;
break;
}
@@ -2693,6 +2696,16 @@ size_t P_GetMapThingPlayerNumber(mapthing2_t *mthing)
(mthing->type - 4001 + 4) % MAXPLAYERSTARTS;
}
+int P_IsPickupableThing(short type)
+{
+ return (type == 82 // SSG
+ || (type >= 2000 && type <= 2050) // weapons, ammo, health, armor, special items
+ || type == 17 // cell pack
+ || type == 83 // megasphere
+ || type == 8 // backpack
+ );
+}
+
//
// P_SpawnMapThing
// The fields of the mapthing should
@@ -2834,6 +2847,9 @@ void P_SpawnMapThing (mapthing2_t *mthing, int position)
return;
}
+ if (g_thingfilter == 3 && P_IsPickupableThing(mthing->type))
+ return;
+
// check for appropriate skill level
if (!(mthing->flags & G_GetCurrentSkill().spawn_filter))
return;
diff --git a/common/p_setup.cpp b/common/p_setup.cpp
index 0c639b680..cb76b8e6a 100644
--- a/common/p_setup.cpp
+++ b/common/p_setup.cpp
@@ -70,7 +70,7 @@ int P_TranslateSectorSpecial(int special);
extern dyncolormap_t NormalLight;
extern AActor* shootthing;
-EXTERN_CVAR(g_coopthingfilter)
+EXTERN_CVAR(g_thingfilter)
bool g_ValidLevel = false;
@@ -629,9 +629,9 @@ void P_LoadThings (int lump)
#ifdef SERVER_APP
if (G_IsCoopGame())
{
- if (g_coopthingfilter == 1)
+ if (g_thingfilter == 1)
mt2.flags |= MTF_FILTER_COOPWPN;
- else if (g_coopthingfilter == 2)
+ else if (g_thingfilter == 2)
mt2.flags &= ~MTF_COOPERATIVE;
}
else
diff --git a/common/p_spec.cpp b/common/p_spec.cpp
index 4fdcf4407..eb04c2db1 100644
--- a/common/p_spec.cpp
+++ b/common/p_spec.cpp
@@ -465,7 +465,7 @@ void DPusher::Serialize (FArchive &arc)
else
{
arc >> m_Type;
- arc.ReadObject((DObject*&)m_Source, DPusher::StaticType());
+ arc.ReadObject((DObject*&)*m_Source, DPusher::StaticType());
arc >> m_Xmag >> m_Ymag >> m_Magnitude >> m_Radius >> m_X >> m_Y >> m_Affectee;
}
}
diff --git a/common/p_user.cpp b/common/p_user.cpp
index 0296f7993..461a3ef03 100644
--- a/common/p_user.cpp
+++ b/common/p_user.cpp
@@ -26,6 +26,8 @@
#include "odamex.h"
+#include
+
#include
#include "cmdlib.h"
@@ -1321,7 +1323,6 @@ player_s::player_s() :
ping(0),
last_received(0),
tic(0),
- missingticcmdcount(0),
snapshots(PlayerSnapshotManager()),
spying(0),
spectator(false),
@@ -1441,8 +1442,6 @@ player_s &player_s::operator =(const player_s &other)
last_received = other.last_received;
tic = other.tic;
- missingticcmdcount = other.missingticcmdcount;
-
spying = other.spying;
spectator = other.spectator;
// deadspectator = other.deadspectator;
diff --git a/common/version.h b/common/version.h
index 7873b4570..982b040d5 100644
--- a/common/version.h
+++ b/common/version.h
@@ -77,7 +77,7 @@
#define DOTVERSIONSTR "11.0.0"
#define GAMEVER (MAKEVER(11, 0, 0))
-#define COPYRIGHTSTR "Copyright (C) 2006-2022 The Odamex Team"
+#define COPYRIGHTSTR "Copyright (C) 2006-2023 The Odamex Team"
#define SERVERMAJ (VERMAJ(gameversion))
#define SERVERMIN (VERMIN(gameversion))
diff --git a/odalaunch/res/Info.plist b/odalaunch/res/Info.plist
index 76a11a5d5..6dc73d25d 100644
--- a/odalaunch/res/Info.plist
+++ b/odalaunch/res/Info.plist
@@ -23,11 +23,11 @@
CFBundleShortVersionString
11.0.0
CFBundleGetInfoString
- Copyright © 2006-2022 The Odamex Team
+ Copyright © 2006-2023 The Odamex Team
CFBundleLongVersionString
11.0.0
NSHumanReadableCopyright
- Copyright © 2006-2022 The Odamex Team
+ Copyright © 2006-2023 The Odamex Team
LSRequiresCarbon
diff --git a/odalaunch/res/gui_project.fbp b/odalaunch/res/gui_project.fbp
index 77c1130ea..2345bf017 100644
--- a/odalaunch/res/gui_project.fbp
+++ b/odalaunch/res/gui_project.fbp
@@ -10315,7 +10315,7 @@
0
0
wxID_ANY
- Copyright (C) 2006-2022 The Odamex Team
+ Copyright (C) 2006-2023 The Odamex Team
0
diff --git a/odalaunch/src/dlg_about.cpp b/odalaunch/src/dlg_about.cpp
index 3f7da287d..2e0991890 100644
--- a/odalaunch/src/dlg_about.cpp
+++ b/odalaunch/src/dlg_about.cpp
@@ -30,7 +30,7 @@
#include
#include
-#define _ODA_COPYRIGHT_ "Copyright (C) 2006-2022 The Odamex Team"
+#define _ODA_COPYRIGHT_ "Copyright (C) 2006-2023 The Odamex Team"
BEGIN_EVENT_TABLE(dlgAbout, wxDialog)
EVT_TEXT_URL(XRCID("Id_TxtCtrlDevelopers"), dlgAbout::OnTxtCtrlUrlClick)
diff --git a/odalpapi/net_io.cpp b/odalpapi/net_io.cpp
index d6dd666fe..16f136374 100644
--- a/odalpapi/net_io.cpp
+++ b/odalpapi/net_io.cpp
@@ -194,7 +194,7 @@ void BufferedSocket::SetRemoteAddress(const string& Address, const uint16_t& Por
m_RemoteAddress.sin_family = PF_INET;
m_RemoteAddress.sin_port = htons(Port);
- m_RemoteAddress.sin_addr.s_addr = *((unsigned long*)&(((sockaddr_in*)result->ai_addr)->sin_addr));
+ m_RemoteAddress.sin_addr = ((sockaddr_in*)result->ai_addr)->sin_addr;
memset(m_RemoteAddress.sin_zero, '\0', sizeof m_RemoteAddress.sin_zero);
freeaddrinfo(result);
diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt
index 567b890fb..8820723aa 100644
--- a/server/CMakeLists.txt
+++ b/server/CMakeLists.txt
@@ -37,11 +37,6 @@ if(WIN32 AND NOT MSVC)
add_definitions(-DWINVER=0x0500)
endif()
-# Set up FHS installation path
-if(NOT APPLE AND NOT WIN32)
- add_definitions(-DINSTALL_PREFIX="${CMAKE_INSTALL_PREFIX}")
-endif()
-
add_executable(odasrv
${COMMON_SOURCES} ${SERVER_SOURCES} ${SERVER_WIN32_SOURCES})
odamex_target_settings(odasrv)
diff --git a/server/src/c_console.cpp b/server/src/c_console.cpp
index 66116ee6b..159bb986a 100644
--- a/server/src/c_console.cpp
+++ b/server/src/c_console.cpp
@@ -24,6 +24,8 @@
#include "odamex.h"
+#include
+
#include
#include "m_fileio.h"
diff --git a/server/src/sv_banlist.cpp b/server/src/sv_banlist.cpp
index c271fe68c..36cdf9b63 100644
--- a/server/src/sv_banlist.cpp
+++ b/server/src/sv_banlist.cpp
@@ -24,6 +24,7 @@
#include "odamex.h"
+#include
#include
#include "win32inc.h"
diff --git a/server/src/sv_banlist.h b/server/src/sv_banlist.h
index 6096f73fc..f4d686071 100644
--- a/server/src/sv_banlist.h
+++ b/server/src/sv_banlist.h
@@ -23,6 +23,7 @@
#pragma once
+#include
#include
#include "json/json.h"
diff --git a/server/src/sv_main.cpp b/server/src/sv_main.cpp
index c718dc010..ffa61a676 100644
--- a/server/src/sv_main.cpp
+++ b/server/src/sv_main.cpp
@@ -127,6 +127,7 @@ void P_PlayerLeavesGame(player_s* player);
bool P_LineSpecialMovesSector(short special);
void SV_UpdateShareKeys(player_t& player);
+std::string SV_BuildKillsDeathsStatusString(player_t& player);
std::string V_GetTeamColor(UserInfo userinfo);
CVAR_FUNC_IMPL (sv_maxclients)
@@ -183,7 +184,10 @@ CVAR_FUNC_IMPL (sv_maxplayers)
SVC_PlayerMembers(*it, SVC_PM_SPECTATOR));
}
- SV_BroadcastPrintf ("%s became a spectator.\n", it->userinfo.netname.c_str());
+ std::string status = SV_BuildKillsDeathsStatusString(*it);
+ SV_BroadcastPrintf(PRINT_HIGH, "%s became a spectator.(%s)\n",
+ it->userinfo.netname.c_str(), status.c_str());
+
MSG_WriteSVC(
&it->client.reliablebuf,
SVC_Print(PRINT_CHAT,
@@ -1166,6 +1170,7 @@ bool SV_AwarenessUpdate(player_t &player, AActor *mo)
return true;
}
+
return false;
}
@@ -1930,6 +1935,50 @@ void SV_ConnectClient2(player_t& player)
SV_MidPrint((char*)sv_motd.cstring(), &player, 6);
}
+
+//
+// SV_BuildKillsDeathsStatusString
+//
+std::string SV_BuildKillsDeathsStatusString(player_t& player)
+{
+ std::string status;
+ char temp_str[100];
+
+ if (player.playerstate == PST_DOWNLOAD)
+ status = "downloading";
+ else if (player.playerstate == PST_DISCONNECT && player.spectator)
+ status = "SPECTATOR";
+ else
+ {
+ if (G_IsTeamGame())
+ {
+ sprintf(temp_str, "%s TEAM, ", GetTeamInfo(player.userinfo.team)->ColorStringUpper.c_str());
+ status += temp_str;
+ }
+
+ // Points (CTF).
+ if (sv_gametype == GM_CTF)
+ {
+ sprintf(temp_str, "%d POINTS, ", player.points);
+ status += temp_str;
+ }
+
+ // Frags (DM/TDM/CTF) or Kills (Coop).
+ if (G_IsCoopGame())
+ sprintf(temp_str, "%d KILLS, ", player.killcount);
+ else
+ sprintf(temp_str, "%d FRAGS, ", player.fragcount);
+
+ status += temp_str;
+
+ // Deaths.
+ sprintf(temp_str, "%d DEATHS", player.deathcount);
+ status += temp_str;
+ }
+ return status;
+}
+
+
//
// SV_DisconnectClient
//
@@ -1952,43 +2001,12 @@ void SV_DisconnectClient(player_t &who)
Maplist_Disconnect(who);
Vote_Disconnect(who);
+ who.playerstate = PST_DISCONNECT;
+
if (who.client.displaydisconnect)
{
// print some final stats for the disconnected player
- std::string status;
- if (who.playerstate == PST_DOWNLOAD)
- status = "downloading";
- else if (who.spectator)
- status = "SPECTATOR";
- else
- {
- if (G_IsTeamGame())
- {
- sprintf(str, "%s TEAM, ", GetTeamInfo(who.userinfo.team)->ColorStringUpper.c_str());
- status += str;
- }
-
- // Points (CTF).
- if (sv_gametype == GM_CTF)
- {
- sprintf(str, "%d POINTS, ", who.points);
- status += str;
- }
-
- // Frags (DM/TDM/CTF) or Kills (Coop).
- if (G_IsCoopGame())
- sprintf(str, "%d KILLS, ", who.killcount);
- else
- sprintf(str, "%d FRAGS, ", who.fragcount);
-
- status += str;
-
- // Deaths.
- sprintf(str, "%d DEATHS", who.deathcount);
- status += str;
- }
-
- // Name and reason for disconnect.
+ std::string status = SV_BuildKillsDeathsStatusString(who);
if (gametic - who.client.last_received == CLIENT_TIMEOUT*35)
SV_BroadcastPrintf("%s timed out. (%s)\n",
who.userinfo.netname.c_str(), status.c_str());
@@ -1997,7 +2015,6 @@ void SV_DisconnectClient(player_t &who)
who.userinfo.netname.c_str(), status.c_str());
}
- who.playerstate = PST_DISCONNECT;
SV_UpdatePlayerQueuePositions(G_CanJoinGame, &who);
}
@@ -3204,39 +3221,35 @@ int SV_CalculateNumTiccmds(player_t &player)
static const size_t maximum_queue_size = TICRATE / 4;
- if (!sv_ticbuffer || gamestate != GS_LEVEL || player.spectator || player.playerstate == PST_DEAD)
+ if (!sv_ticbuffer || player.spectator || player.playerstate == PST_DEAD)
{
// Process all queued ticcmds.
return maximum_queue_size;
}
- if (player.missingticcmdcount > 0)
+ if (player.mo->momx == 0 && player.mo->momy == 0 && player.mo->momz == 0)
{
- if (player.mo->momx == 0 && player.mo->momy == 0 && player.mo->momz == 0)
- {
- // Player is not moving
- return 2;
- }
- if (player.cmdqueue.size() > 2 && gametic % (2*TICRATE) == player.id % (2*TICRATE))
- {
- // Process an extra ticcmd once every 2 seconds to reduce the
- // queue size. Use player id to stagger the timing to prevent everyone
- // from running an extra ticcmd at the same time.
- return 2;
- }
- if (player.cmdqueue.size() > maximum_queue_size)
- {
- // The player experienced a large latency spike so try to catch up by
- // processing more than one ticcmd at the expense of appearing perfectly
- // smooth.
- return 2;
- }
+ // Player is not moving
+ return 2;
+ }
+ if (player.cmdqueue.size() > 2 && gametic % 2*TICRATE == player.id % 2*TICRATE)
+ {
+ // Process an extra ticcmd once every 2 seconds to reduce the
+ // queue size. Use player id to stagger the timing to prevent everyone
+ // from running an extra ticcmd at the same time.
+ return 2;
+ }
+ if (player.cmdqueue.size() > maximum_queue_size)
+ {
+ // The player experienced a large latency spike so try to catch up by
+ // processing more than one ticcmd at the expense of appearing perfectly
+ // smooth
+ return 2;
}
// always run at least 1 ticcmd if possible
return 1;
}
-
//
// SV_ProcessPlayerCmd
//
@@ -3266,9 +3279,6 @@ void SV_ProcessPlayerCmd(player_t &player)
player.userinfo.netname, player.cmdqueue.size());
#endif // _TICCMD_QUEUE_DEBUG_
- if (player.cmdqueue.empty())
- player.missingticcmdcount++;
-
int num_cmds = SV_CalculateNumTiccmds(player);
for (int i = 0; i < num_cmds && !player.cmdqueue.empty(); i++)
@@ -3310,7 +3320,6 @@ void SV_ProcessPlayerCmd(player_t &player)
}
player.cmdqueue.pop(); // remove this tic from the queue after being processed
- player.missingticcmdcount--;
}
}
@@ -3579,7 +3588,11 @@ void SV_SpecPlayer(player_t &player, bool silent)
P_SetSpectatorFlags(player);
if (!silent)
- SV_BroadcastPrintf(PRINT_HIGH, "%s became a spectator.\n", player.userinfo.netname.c_str());
+ {
+ std::string status = SV_BuildKillsDeathsStatusString(player);
+ SV_BroadcastPrintf(PRINT_HIGH, "%s became a spectator.(%s)\n",
+ player.userinfo.netname.c_str(), status.c_str());
+ }
P_PlayerLeavesGame(&player);
SV_UpdatePlayerQueuePositions(G_CanJoinGame, &player);
diff --git a/server/src/sv_maplist.cpp b/server/src/sv_maplist.cpp
index 06b63a5cc..e1baa2180 100644
--- a/server/src/sv_maplist.cpp
+++ b/server/src/sv_maplist.cpp
@@ -129,13 +129,9 @@ bool Maplist::insert(const size_t &position, maplist_entry_t &maplist_entry) {
}
}
- // capitalize the map name and WAD file names
+ // capitalize the map names
maplist_entry.map = StdStringToUpper(maplist_entry.map);
- for (std::vector::iterator it = maplist_entry.wads.begin();
- it != maplist_entry.wads.end(); ++it)
- *it = StdStringToUpper(*it);
-
// Puts the map into its proper place
this->maplist.insert(this->maplist.begin() + position, maplist_entry);
diff --git a/tools/upversion/upversion.ini b/tools/upversion/upversion.ini
index b02d8018a..3bfa85d94 100644
--- a/tools/upversion/upversion.ini
+++ b/tools/upversion/upversion.ini
@@ -5,15 +5,15 @@
; Existing and new versions of Odamex, in dotted-number format.
; Middle number only goes up to 25, last number only goes up to 9.
-old_version=10.3.0
+old_version=10.4.0
new_version=11.0.0
; Existing and new year ranges. Note that if these are the same, year
; replacement will be skipped entirely. Year ranges will not be updated
; in code comments.
-old_year=2006-2022
-new_year=2006-2022
+old_year=2006-2023
+new_year=2006-2023
[files]
diff --git a/wad/graphics/net.gif b/wad/graphics/net.gif
index a89b51ac0..834705dbf 100644
Binary files a/wad/graphics/net.gif and b/wad/graphics/net.gif differ
diff --git a/wad/lumps/_chexnfo.lmp b/wad/lumps/_chexnfo.lmp
index 3817fc76a..e5e58109c 100644
--- a/wad/lumps/_chexnfo.lmp
+++ b/wad/lumps/_chexnfo.lmp
@@ -21,7 +21,7 @@ map E1M1 lookup "CHUSTR_E1M1"
secretnext = "E1M9"
sky1 = "SKY1"
cluster = 1
- par = 30
+ par = 120
music = "$MUSIC_E1M1"
}
@@ -33,7 +33,7 @@ map E1M2 lookup "CHUSTR_E1M2"
secretnext = "E1M9"
sky1 = "SKY1"
cluster = 1
- par = 75
+ par = 360
music = "$MUSIC_E1M2"
}
@@ -45,7 +45,7 @@ map E1M3 lookup "CHUSTR_E1M3"
secretnext = "E1M9"
sky1 = "SKY1"
cluster = 1
- par = 120
+ par = 480
music = "$MUSIC_E1M3"
}
@@ -57,7 +57,7 @@ map E1M4 lookup "CHUSTR_E1M4"
secretnext = "E1M9"
sky1 = "SKY1"
cluster = 1
- par = 90
+ par = 200
music = "$MUSIC_E1M4"
}
@@ -69,7 +69,7 @@ map E1M5 lookup "CHUSTR_E1M5"
secretnext = "E1M9"
sky1 = "SKY1"
cluster = 1
- par = 165
+ par = 360
music = "$MUSIC_E1M5"
nointermission
}